Godot Shader 入门:做一套像素文字 Shader

作者:logoss
2018-10-18
37 33 4

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);
}


效果如图,整个 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 的信息请参考官方文档

本文为用户投稿,不代表 indienova 观点。

近期点赞的会员

 分享这篇文章

logoss 

正在研究godot,会一点绘画 

您可能还会对这些文章感兴趣

参与此文章的讨论

  1. meishijie 2018-12-24

    godot不错,但是没有我想要的样例模板。

  2. 很棒。但是,如果做成繁体字,会很糊吧。。能不能放歌繁体字实例

  3. 深邃如海 2021-08-25

    不错不错,学到了

  4. ReEd1327 2022-11-07

    大感谢,这对shader新手很有用

您需要登录或者注册后才能发表评论

登录/注册