Godot中实现驻波与行波着色器:让子弹呈现电磁波效果
实现Godot激光子弹的驻波/行波着色器效果
嘿,刚好我之前在Godot里折腾过类似的激光子弹波动效果,给你分享个完全适配你需求的方案——既能实现静态时的驻波,移动时又能变成沿激光长度方向传播的行波,完美避开你说的垂直振荡问题!
核心思路
你要的是沿激光自身长度方向的波动:静态时是驻波(固定位置的振荡,振幅随时间变化),移动时切换为行波(波整体跟着子弹同步移动)。之前的方案问题出在振荡方向垂直,那我们就把波动逻辑改成平行于激光长度,用片段着色器修改UV采样位置来实现,不用动顶点,简单高效。
着色器代码
直接把下面的代码粘贴到Sprite节点的ShaderMaterial里就行:
shader_type canvas_item; # 可调参数,根据你的激光外观自由调整 uniform float wave_frequency : hint_range(1.0, 20.0) = 8.0; # 波的疏密程度 uniform float wave_amplitude : hint_range(0.0, 0.5) = 0.1; # 波动幅度 uniform float wave_speed : hint_range(0.0, 10.0) = 5.0; # 波的移动/振荡速度 uniform vec2 wave_direction = vec2(1.0, 0.0); # 波的传播方向(沿激光长度) void fragment() { vec2 uv = UV; float wave_phase; // 根据子弹是否移动自动切换驻波/行波模式 if (length(VELOCITY) < 0.1) { // 静态驻波:位置正弦 × 时间余弦,形成固定节点的振荡效果 wave_phase = sin(uv.x * wave_frequency) * cos(TIME * wave_speed); } else { // 移动行波:结合世界位置和时间,让波跟着子弹同步移动 float move_offset = dot(WORLD_POSITION, wave_direction); wave_phase = sin(move_offset * wave_frequency + TIME * wave_speed); } // 把波动应用到激光长度对应的UV轴(比如激光沿x轴就改x,沿y轴就改y) uv.x += wave_phase * wave_amplitude; // 采样偏移后的UV,输出最终颜色 vec4 final_color = texture(TEXTURE, uv); // 可选:让颜色随波动微微变化,增强视觉冲击力 final_color.rgb += wave_phase * 0.15; COLOR = final_color; }
使用步骤
- 打开你的Bullet场景,选中Sprite节点;
- 在Inspector面板的
Material选项中,选择New ShaderMaterial; - 双击新建的ShaderMaterial,打开着色器编辑器,把上面的代码粘贴进去;
- 回到Inspector,你可以直接拖动uniform参数滑块,实时预览效果:
wave_frequency:数值越大,波越密集;wave_amplitude:数值越大,波动越明显;wave_direction:如果你的激光是垂直方向,改成vec2(0.0, 1.0)就行。
小技巧
- 要是想让驻波的“呼吸感”更强,可以把静态模式里的
cos(TIME * wave_speed)改成sin(TIME * wave_speed),或者调大wave_speed数值; - 如果行波方向反了,把
wave_direction的数值改成负数(比如vec2(-1.0, 0.0)); - 配合
GlowLayer给激光加个发光效果,波动起来会更炫酷!
内容的提问来源于stack exchange,提问作者Andrey Kachow
相关产品推荐
相关产品推荐

