Godot游戏引擎学习 第九课
再次学习Shader
这里先吐槽一句,以前玩全没接触过,在没有概念的情况下看待未知的事物的感觉真不好。跟着UP主把代码写出来效果实现后却对这些参数函数的意义完全不懂。
所以我索性上Godot的官方文档里重新认真大概了解一下Shader是什么东西,以下写的东西都是在Godot里的情况
着色器是在图形处理器上运行的独特程序。它们用于指定如何获取网格数据(顶点位置、颜色、法线等等)然后把它们绘制到屏幕上。着色器并不像普通程序那样处理信息,因为它们经过了优化,可以在图形处理器上运行。其结果是,着色器在运行后不会保留数据;它们把最后一种颜色输出到屏幕上,然后继续。因此,无法访问着色器上次运行时的颜色输出。
首先是Shader的类型,一个shader着色器开头必须定义它的类型,官方给了三种,分别是:
- Spatial:用于3d渲染
- canvas_item:用于2D渲染
- particles:用于粒子系统
定义完Shader类型后要写一个主入口函数,也分为三种
- vertex():运行在所有网格的定点上,并设置他们的位置及部分其他每个顶点的变量。
- fragment():官方没说,应该是为每个像素运行的。
- light():为每个像素和美术光照。
吐槽一下,Godot的官方文档翻译好烂啊....,哎,不过有总比没有好,毕竟都是网友翻译的。(这里不是否定大家的工作,相反还要感谢。)
这样就大概完成函数主体了,接下来我们就可以在主题中对像素进行操作了。
我目前理解的一些东西就是。
- 可以通过vec4变量来储存图片的rpga通道,当然也有三位变量储存rgb颜色值。
- 可以通过texture函数获取外部贴图
- UV代表一个像素再网格中的坐标,最小是0,最大是1,分为r,x,g,y,这里r和g我不知道是什么意思,但是x应该是水平坐标,y为垂直坐标。
- COLOR代表当前像素的原本颜色,你可以给与一个vec4变量来改变颜色。
目前的理解大概就是这样,当然只是最基础的部分。Shader肯定没这么简单,但是我现在也不需要了解的非常深刻,但是要有一些基础原理的理解有利于以后的学习。
Godot里利用shader完成花里胡哨转场
首先为Globals的ColorRect
添加一个ShaderMaterial
,并添加如下代码如下:
shader_type canvas_item;
// 定义默认值
// 渐变边界
uniform float cutoff: hint_range(0.0, 1.0) = 0.5;
// 模糊级别
uniform float feather:hint_range(0.0, 1.0) = 0.1;
// 2D纹理
uniform sampler2D mask;
// 片段函数,可以对图片中的每个像素进行操作
void fragment()
{
// 顶一个思维变量,代表像素的四个通道的颜色,分别是Red Green Blue Alpha
vec4 col = vec4(0.0, 0.0, 0.0, 1.0);
// 读取外部纹理
vec4 v = texture(mask, UV);
// //如果uv的横向还没到我们的效果区域则全部设置为透明
// if(UV.x < cutoff - feather){
// col.a = 0.0
// //如果横向坐标到达效果区的最右边
// }else if(UV.x < cutoff){
// // 则讲透明度设置成边界减羽化值
// col.a = (UV.x - (cutoff - feather))
// }
// 这个函数不太懂,看了下官方手册是一个插值函数,原理是一个名为:埃尔米特插值法(Hermite interpolation)的东西,我完全看不懂。
// up的解释是如果最后一个参数小于第一个参数则返回0,大于第二个参数则返回1,介于第一个参数和第二个参数之间的话返回一个过渡值
// 第三个为啥用纹理像素中的r通道,我自己测试了一下,其他通道也是可以,我觉得只是为了界定像素在哪个位置而已。
col.a = smoothstep(cutoff - feather, cutoff, v.g * (1.0 -feather));
// 应用颜色
COLOR = col;
}
然后修改fadein动画,动态改变代码中设置的cutoff
和feather
值。
效果如下:
怪物进入镜头视野后才会行动
另外这里处理了一个问题,就是原先怪物的逻辑是一加载到场景中就会开始执行设置好的动作,在Godot里这个功能甚至不用写代码...。这里我们给Enemy加了一个VisibilityEnabler2D节点,文档对这个节点的解释为:Enables certain nodes only when approximately visible.
,作用就是怪物进入镜头视野后才会开始执行预先设定的指令,且不会影响其加载。
改变关卡
到最后一集了,UP这一集基本上就是利用之前所学重新搭建了场景,增加了一个改变关卡的功能。
因为Godot的特性,所以这里我们搭建新关卡的时候很简单,只需要把我们之前创建好的怪物,道具什么的实例化到新场景,摆到想要摆放的位置即可,搭建这个新场景前后不过五分钟把...,面向对象万岁。
做了一个Exit
场景,并连接_on_Exit_body_entered
信号,这里指定类型用了和hint_range
一样的写法,指定类型为File,并且指定了可选择的后缀(想起了以前C#的文件组件。),这样我们就能在编辑器里设置下一个场景的路径,并调用我们写好的Globals.go_to_world(path)
函数跳转场景
# Exit.gd
extends Area2D
# 外部参数,指定使用文件系统,并设定可选区的文件类型
export(String, FILE, "*.tscn") var path
func _on_Exit_body_entered(_player):
# 调用转场函数,传入设置好的场景路径
Globals.go_to_world(path)
# ...
# Globals.gd
# ...
func go_to_world(path):
# 死亡的时候让动画倒叙播放
animation_player.play_backwards("fadein")
# 等待动画播放完毕
yield(animation_player, "animation_finished")
# 跳转场景
get_tree().change_scene(path)
# 动画正序播放
animation_player.play("fadein")
# ...
效果如下
好了,UP主上传的视频已经全部看完了,准备开始自己设计一些关卡,并制作机关功能。
加入评论