Tilemap Wind shader
Inspired by: https://twitter.com/RustedMoss/status/1515359363103293442
A simple shader to apply a vertex distortion on a tilemap based on a noise texture.
Shader code
shader_type canvas_item;
// helpful to visually debug the noise scrolling texture.
uniform bool render_noise = false;
// Change if you want to move the bottom vertex of each tile.
uniform bool move_top = true;
// how strong is the vertex going to be pulled.
uniform vec2 distortion_force = vec2(10.0, 0.0);
// how fast is the noise texture is going to scroll.
uniform float time_scale :hint_range(0.0, 1.0, 0.01) = 0.1;
// the distortion texture, can be hand made or generated with the Godot builtin
// noise texture.
uniform sampler2D noise_texture: hint_white;
// the scale of the texture
uniform float noise_scale :hint_range(0.0, 2.0, 0.0001)= 0.002;
// you need to pass the world position from a script as seen
// https://docs.godotengine.org/en/3.5/tutorials/shaders/shader_reference/canvas_item_shader.html#vertex-built-ins
uniform mat4 global_transform;
varying vec2 world_position;
// the size of the tilemap tiles.
const float tile_size = 8.0;
vec2 get_uv(vec2 uv, float scale, float time) {
vec2 new_uv = uv;
new_uv *= scale;
new_uv += time;
return new_uv;
}
void vertex(){
world_position = (global_transform * vec4(VERTEX, 0.0, 1.0)).xy;
vec2 world_uv = get_uv(world_position, noise_scale, TIME * time_scale);
vec2 noise = texture(noise_texture, world_uv).rg;
noise *= 2.0;
noise -= 1.0;
noise *= distortion_force;
float a = fract(VERTEX.y / tile_size);
if (a == 0.0 && move_top) {
VERTEX.x += noise.x;
VERTEX.y += noise.y;
}
if (a > 0.0 && !move_top) {
VERTEX.x += noise.x;
VERTEX.y += noise.y;
}
}
void fragment() {
vec4 sample = texture(TEXTURE, UV);
COLOR = sample;
if (render_noise) {
vec3 color = sample.rgb;
vec2 world_uv = get_uv(world_position, noise_scale, TIME * time_scale);
color = texture(noise_texture, world_uv).rgb;
COLOR = vec4(color, 1.0);
}
}
it crashed my editor xdddddd
with godot 4.0.2:
shoud setting:
render_mode skip_vertex_transform;
then in vertex() modify line:
world_position = (MODEL_MATRIX * vec4(VERTEX, 0.0, 1.0)).xy;
at last add line:
VERTEX = (MODEL_MATRIX * vec4(VERTEX, 0.0, 1.0)).xy;
after that, it worked.
Under version 4.1.1. I can not get it to run with these modifications. It seems that the noise texture is not read correctly. Maybe some tips?
Additionally to the changes mentioned above try out
this seemed to do the trick for me on Godot stable 4.1.1