Stylized 2D Plane Water Shader
Stylized 2D Water Reflection Shader for Godot 4.x (CanvasItem shader)
This is a 2D stylized water shader designed for flat quad/ColorRect plane. It uses screen‑texture reflection and noise distortion to create animated wavy water surface.
Features:
– Real‑time screen‑space reflection: reflects everything rendered above the water plane
– Procedural noise‑driven wave distortion, creates flowing water ripples
– Adjustable water opacity, albedo tint and reflection strength
– Semi‑transparent water surface, supports blending with background
How to use:
1. Create a ColorRect node as your water plane.
2. Assign this shader to the ColorRect’s material.
3. Place this water rect at the bottom of your scene. All objects above the water will be reflected.
4. Tweak shader parameters: water opacity, noise scale, reflection intensity to adjust water look.
Note: Works for 2D scenes, CanvasItem type shader.
Shader code
shader_type canvas_item;
uniform sampler2D SCREEN_TEXTURE : hint_screen_texture;
uniform float level : hint_range(0.0, 1.0) = 0.5;
uniform vec4 water_albedo : source_color = vec4(0.26, 0.25, 0.73, 1.0);
uniform float water_opacity : hint_range(0.0, 1.0) = 0.35;
uniform float water_speed = 0.05;
uniform float wave_distortion = 0.2;
uniform int wave_multiplyer = 7;
uniform bool water_texture_on = true;
uniform float reflection_X_offset = 0.0;
uniform float reflection_Y_offset = 0.0;
uniform sampler2D noise_texture : filter_linear,repeat_enable;
uniform sampler2D noise_texture2 : filter_linear,repeat_enable;
void fragment() {
vec2 uv = UV;
COLOR = vec4(0.0);
if (uv.y >= level) {
COLOR.a = 1.0;
// distorted reflections
vec2 water_uv = vec2(uv.x, uv.y * float(wave_multiplyer));
float noise = texture(noise_texture, vec2(water_uv.x + TIME * water_speed, water_uv.y)).x * wave_distortion;
noise -= (0.5 * wave_distortion);
// water texture
if (water_texture_on) {
float water_texture_limit = 0.35;
vec4 water_texture = texture(noise_texture2, uv * vec2(0.5, 4.0) + vec2(noise, 0.0));
float water_texture_value = (water_texture.x < water_texture_limit) ? 1.0 : 0.0;
COLOR.xyz = vec3(water_texture_value);
}
// putting everything toghether
vec4 current_texture = texture(SCREEN_TEXTURE, vec2(SCREEN_UV.x + noise + reflection_X_offset, 1.0 - SCREEN_UV.y - (level - 0.5) * 2.0 + reflection_Y_offset));
COLOR = mix(COLOR, current_texture, 0.5);
COLOR = mix(COLOR, water_albedo, water_opacity);
}
}


