200字
GODOT入门:移动云朵shader
2026-01-29
2026-01-29

近期对游戏开发感兴趣,于是学习了GODOT游戏引擎并试着做了一些小DEMO来熟悉技术

其中一个DEMO是雷霆战机的粗糙手机翻版,于是有了实现天空背景的需求,大概有以下两点:

  • 背景要向下运动,以体现飞机在向上飞行

  • 云朵要不间断变化,同时不能太单调

正好最近进一步了解了shader的部分原理,于是便试着使用几行简单的shader实现了,在这里分享出来

先看效果:

相信大佬应该已经看出来了,实现的方式非常简单hhh

不过作为初学者的总结,还是想把我自己的实现思路描述一下

首先,需要模拟云朵且可以做到无缝流转循环,我最先想到的就是使用循环噪声图,它易于实现(GODOT中可以直接可视化创建调整),计算成本小,同时也方便在后期调整为自己绘制的专用纹理,它长这样:

在确定好纹理后,我们需要让它动起来,具体实现方式是在每次像素采样时让采样位置与原位置产生一定的偏移

我们需要让其根据时间不断向后移动及变化,这一点可以通过内置的 TIME 变量及自己设置的云层移动速度变量 cloud_moving_speed 来对采样偏移量进行控制,其中 TIME 变量指代引擎启动后到现在的时间,单位为秒

uniform vec2 cloud_moving_speed = vec2(0.01, -0.2);  // 设置云层移动速度

void fragment() {
    vec2 offset = TIME * cloud_moving_speed;  // 设置采样偏移量
    vec2 uv = UV + offset;  // 获得偏移后的坐标
    uv = fract(uv);  // 确保采样坐标超过1时回到0-1的范围,以实现循环采样
    COLOR = texture(cloud_texture, uv)
}

这样,移动的云层就做好啦!

为了进一步增强云层的变化效果,我选择在最终实现时使用两张噪声图按比例进行混合

uniform sampler2D cloud_texture_1;
uniform sampler2D cloud_texture_2;
uniform float mix_ratio : hint_range(0.0, 1.0) = 0.2;

// ··· ··· 其它代码
color = texture(cloud_texture_1, uv2) * mix_ratio + texture(cloud_texture_2, uv1) * (1.0 - mix_ratio);
// ··· ···

再添加一下背景色,大功告成!

uniform vec4 sky_color : source_color = vec4(0.53, 0.81, 0.98, 1.0);

// ··· ···其他代码
color.a = color.r;
color = mix(sky_color, color, color.a);
// ··· ···

以下是完整代码,供大家参考

shader_type canvas_item;


group_uniforms cloud_layer_1;
uniform sampler2D cloud_texture_1;
uniform vec2 cloud_moving_speed_1 = vec2(0.01, -0.2);

group_uniforms cloud_layer_2;
uniform sampler2D cloud_texture_2;
uniform vec2 cloud_moving_speed_2 = vec2(-0.02, -0.15);

uniform vec4 sky_color : source_color = vec4(0.53, 0.81, 0.98, 1.0);
uniform float mix_ratio : hint_range(0.0, 1.0) = 0.2;

void fragment() {
    vec2 offset1 = TIME * cloud_moving_speed_1;
    vec2 offset2 = TIME * cloud_moving_speed_2;
    vec2 uv1 = UV + offset1;
    vec2 uv2 = UV + offset2;

    uv1 = fract(uv1);
    uv2 = fract(uv2);

    vec4 color = texture(TEXTURE, uv1);
    color = texture(cloud_texture_1, uv1) * mix_ratio + texture(cloud_texture_2, uv2) * (1.0 - mix_ratio);

    // mix with sky color
    color.a = color.r;
    color = mix(sky_color, color, color.a);

    COLOR = color;
}

感谢阅读!本文偏技术解析,也欢迎大家直接看我发在godot shader网站上仅包含使用方法的 源代码分享帖

评论