Godot的Shader入门+制作像素文字Shader
Shader在哪写?
如图,新建一个sprite,在它的Meterial属性里点击新建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); }
效果如图,整个sprite都变白了。
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的信息请参考官方文档:
http://docs.godotengine.org/zh_CN/latest/tutorials/shading/shading_language.html
nice
这个方案好,省钱了,人民群众的智慧果然是无穷的。
硬核像素hhh