Shader 在哪写?
如图,新建一个 sprite,在它的 Material 属性里点击新建 shaderMaerial,在 shaderMateril 里点击新建 shader,就会弹出着色器面板,可以在里面写 shader 了。
Shader 格式
第一行我们先写上:
shader_type canvas_item; void fragment(){ }
- shader_type shader 的类型,有 spatial,canvas_item 和 particles 三种。必须在第一行指定 shader_type。
- spatial: 用来渲染3D
- canvas_item: 用来渲染2D
- particles:用来渲染粒子
- fragment 函数里面就是我们要写处理逻辑的地方。
- fragment()是 shader 的回调函数,
每一个像素点都会运行一次 fragment 函数。
每一个像素点都会运行一次 fragment 函数。
每一个像素点都会运行一次 fragment 函数。
重要的事说三遍。
当然你会发现语法和 gdscript 有些不同,语句结尾要加分号,函数要用大括号括起来。
详细的请参考官方文档。
Shader 基本逻辑
全白效果
先从简单的开始
shader_type canvas_item; void fragment(){ COLOR=vec4(1.0,1.0,1.0,1.0); }
- COLOR是 shader 内置属性,它表示一个像素点的颜色。
- vec4 是 shader 的数据类型,4维向量,可以用来表示颜色。
- vec4有四个属性,x,y,z,w。每个属性都是 float 类型(所以用1.0而不是1)。
- vec4的四个属性也可以用 r,g,b,a 来表示,就是说 vec4.x 和 vec4.r 是完全一样的。
- shader 常用类型有 float,vec2,vec3,vec4等。
现在我们来看 COLOR=vec4(1.0,1.0,1.0,1.0); 这句话,vec4(1.0,1.0,1.0,1.0)表示 rgba 都是1.0的颜色,就是白色。每个像素点都会运行一次这个语句,所以每个像素点的颜色都变成了白色。
剪影效果
我们先写上
shader_type canvas_item; void fragment(){ COLOR=texture(TEXTURE,UV); }
你可能会想:咦?这不是和原来一样吗。
是的,确实和原来一样。这句话是什么意思呢?
UV 是 shader 内置属性,用来表示当前像素点的坐标。它是一个 vec2。
每个像素点都有一个 UV 值,每个像素点的 UV 值不一样。
左上角的像素点 UV 值是(0.0,0.0),
右下角的像素点 UV 值是(1.0,1.0),
正中心的像素点 UV 值是(0.5,0.5)。
- TEXTURE是 shader 的内置属性(反正这些全大写的都是内置属性)。它表示原始的纹理。
- texture 函数是 shader 的内置函数,传入纹理和 uv 值,可以返回纹理上 uv 坐标的颜色(vec4)。
我们来看:COLOR=texture(TEXTURE,UV);
就是每个像素获取自己原来的颜色,赋值给 COLOR。当然不会有任何变化。
接下来我们写
shader_type canvas_item; void fragment(){ COLOR=texture(TEXTURE,UV); COLOR.rgb=vec3(1.0,1.0,1.0); }
效果如图,成功实现了剪影效果。
COLOR.rgb=xxx 这是 shader 中的语法,可以同时给 r,g,b 三个值赋值,非常方便。
你可能会说,为什么要写 COLOR=texture(TEXTURE,UV);?
我不能直接写 COLOR.rgb=vec3(1.0,1.0,1.0);吗?
这是不行的,COLOR 默认值其实是(1.0,1.0,1.0,1.0)。
只要调用了 COLOR,COLOR 就会变成(1.0,1.0,1.0,1.0)。
你可以试试这样
shader_type canvas_item; void fragment(){ COLOR; }
如图,也能让图片变全白。
制作像素化文字 shader
我这里用的字体是思源黑体 Medium。新建一个 label,字体大小设成12,我们看看默认的效果。
放大后:
为什么看上去这么不像素,主要是字体的抗锯齿,使它有半透明的部分。
所以要做的就是去掉半透明的部分。
学习了上面的知识,你应该知道怎么做了。
在 label 的 Meterial 属性里点击,新建 ShaderMeterial,然后新建 Shader
Shader 代码如下
shader_type canvas_item; void fragment(){ COLOR=texture(TEXTURE,UV); if(COLOR.a<0.5){ COLOR.a=0.0; }else{ COLOR.a=1.0; } }
如果像素的 alpha<0.5,就把 alpha 变成0。如果像素的 alpha>=0.5,就把 alpha 变成1。
看看效果
放大后:
很好很像素。
当然临界值可以不是0.5,如果我们希望可以微调临界值该怎么办?
这时要声明变量,代码如下
shader_type canvas_item; uniform float limit=0.5;//声明变量 limit,默认值是0.5 void fragment(){ COLOR=texture(TEXTURE,UV); if(COLOR.a<limit){ //把0.5替换成 limit COLOR.a=0.0; }else{ COLOR.a=1.0; } }
用 uniform 指定的变量可以在外部修改,可以微调像素化的效果。
最后点击保存按钮把 shader 保存成文件,就可以重复使用了
更多关于 shader 的信息请参考官方文档。
godot不错,但是没有我想要的样例模板。
很棒。但是,如果做成繁体字,会很糊吧。。能不能放歌繁体字实例
不错不错,学到了
大感谢,这对shader新手很有用