Search

Godot开发之Shader

2025年09月20日 3 分钟阅读

Shader编程一直都是个很神秘东西,和一般的编程语言运行在CPU中不同,他是运行在GPU上的代码。以前学习Unity的时候尝试过学习Shader编程,实在过于晦涩难懂,最近有个开源引擎Godot很热门,决定从Godot入手再探Shader编程。

一个最简单的 2D Shader

最简单的将一张图片渲染为经典品红色的Shader

shader_type canvas_item;

void fragment() {
    COLOR = vec4(1, 0, 1, 1);
}

下面可以正确的渲染一张贴图

shader_type canvas_item;

void fragment() {
    COLOR = texture(TEXTURE, UV);
}

TEXTURE为传入的贴图,UV就是像素点的位置信息,简单来说就是取TEXTURE中对于UV位置的颜色。需要注意的是UV是一个标准化坐标,它的原点为左下角,值的范围为[0, 1]。

将贴图对应像素点的颜色取出来了,就可以对图片的颜色进行操作了,比如下面的代码可以把一张图片变为灰度图。

shader_type canvas_item;

void fragment() {
    vec4 color = texture(TEXTURE, UV);
    float gray = 0.299 * color.r  + 0.587 * color.g + 0.114 * color.b;
    COLOR = vec4(vec3(gray), color.a);
}

这个就是根据亮度加权公式 (Y = 0.299 * R + 0.587 * G + 0.114 * B) 来计算每个像素的亮度信息,所以展示出来的就是一张只有灰度信息的图片。

以上就是对于贴图最基本的操作了。

让贴图动起来

UI中有一种非常常见的效果,比如卡片溶解消失的效果就可以使用Shader来实现。

shader_type canvas_item;

uniform float dissolve_value : hint_range(0.0, 1.0);
uniform sampler2D noise_texture;

void fragment() {
    float noise = texture(noise_texture, UV).r;
    if (noise < dissolve_value) {
        COLOR.a = 0.0;
    } else {
        COLOR = texture(TEXTURE, UV);
    }
}

dissolve_value就是定义一个变量,这个变量可以在外部去控制。noise_texture就是一张噪声图,这个代码也很简单易懂就是通过判断噪声值的范围控制贴图Alpha。

当然这种消失比较单调,有时候希望的有那种被火烧掉的感觉。

shader_type canvas_item;

uniform float dissolve_value : hint_range(0.0, 1.0);
uniform sampler2D noise_texture;
uniform vec4 burn_color = vec4(1.0, 0.2, 0.0, 1.0);
uniform float edge_width : hint_range(0.0, 0.2) = 0.05;

void fragment() {
    float noise = texture(noise_texture, UV).r;
    vec4 base_col = texture(TEXTURE, UV);

    float edge = 1.0 - smoothstep(dissolve_value, dissolve_value + edge_width, noise);
    if (noise < dissolve_value) {
        COLOR = vec4(0.0);
    } else {
        COLOR = base_col;
    }

    COLOR.rgb = mix(COLOR.rgb, burn_color.rgb, edge);
}

最主要就是对边缘进行一个平滑插值计算,这样就可以获得一个边缘范围,然后根据插值结果做一个颜色混合,就会有被点燃的感觉。

如果dissolve_value外部使用代码去控制变化,就能实现一个溶解消失的效果,非常的简单有效。