shader_type canvas_item; // Parameters uniform sampler2D water_texture; // Your 3x3 water texture uniform vec4 water_color : source_color = vec4(0.0, 0.0, 1.0, 1.0); uniform float speed : hint_range(0.0, 10.0) = 1.0; uniform float strength : hint_range(0.0, 0.2) = 0.05; uniform float tile_repeat : hint_range(1.0, 10.0) = 3.0; uniform vec2 pan_speed = vec2(0.2, 0.1); // how fast the water texture moves void fragment() { vec2 uv = UV; // Sample the base tile texture vec4 base_tex = texture(TEXTURE, uv); // Compute mask for water pixels only float is_water = step(0.8, 1.0 - distance(base_tex.rgb, water_color.rgb)); // Tile the water texture vec2 water_uv = uv * tile_repeat; water_uv = fract(water_uv); // Apply panning / movement water_uv += pan_speed * TIME; // Add wave distortion on top of the moving texture water_uv.y += sin(water_uv.x * 2.0 + TIME * speed) * strength * is_water; water_uv.x += cos(water_uv.y * 2.0 + TIME * speed * 0.5) * strength * is_water; // Sample the animated water texture vec4 water_sample = texture(water_texture, water_uv); // Combine: water animates, other pixels stay the same COLOR = mix(base_tex, water_sample, is_water); }