Testing_the_waters
Placeholder info
Shader code
shader_type canvas_item;
uniform sampler2D screen_texture : hint_screen_texture, repeat_disable, filter_nearest;
uniform sampler2D disp_large : repeat_enable, filter_nearest;
uniform sampler2D disp_small : repeat_enable, filter_nearest;
uniform float waterline : hint_range(0.0, 1.0) = 0.55;
uniform float fade_depth : hint_range(0.01, 1.0) = 0.30;
uniform float shoreline_softness : hint_range(0.0, 0.1) = 0.01;
uniform vec4 water_tint : source_color = vec4(0.12, 0.20, 0.26, 1.0);
uniform float reflection_strength : hint_range(0.0, 2.0) = 1.0;
uniform vec2 pixel_resolution = vec2(480.0, 270.0);
// Large displacement map
uniform vec2 large_scale = vec2(1.2, 0.35);
uniform vec2 large_scroll = vec2(0.01, 0.0);
uniform vec2 large_strength = vec2(0.008, 0.0015);
// Small displacement map
uniform vec2 small_scale = vec2(4.0, 1.2);
uniform vec2 small_scroll = vec2(-0.025, 0.0);
uniform vec2 small_strength = vec2(0.0025, 0.0008);
// Perspective correction inspired by the Kingdom post.
// Set to 0.0 to disable.
uniform float perspective_amount : hint_range(-3.0, 3.0) = 0.0;
// Higher values make distortion fade out faster with depth.
uniform float distortion_depth_power : hint_range(-3.0, 3.0) = -1.0;
vec2 snap_uv(vec2 uv, vec2 res) {
return (floor(uv * res) + vec2(0.5)) / res;
}
void fragment() {
vec2 uv = SCREEN_UV;
if (uv.y <= waterline) {
COLOR = vec4(0.0);
} else {
// Snap the destination pixel row first for stable pixel-art distortion.
vec2 snapped_uv = snap_uv(uv, pixel_resolution);
float dist_below = snapped_uv.y - waterline;
float fade = 1.0 - smoothstep(0.0, fade_depth, dist_below);
float shoreline = smoothstep(waterline, waterline + shoreline_softness, snapped_uv.y);
// Mirror vertically around the waterline.
vec2 refl_uv = snapped_uv;
refl_uv.y = 2.0 * waterline - snapped_uv.y;
// Stylized perspective correction on displacement lookup.
vec2 perspective_correction = vec2(
2.0 * (0.5 - snapped_uv.x) * snapped_uv.y * perspective_amount,
0.0
);
vec2 large_uv = refl_uv * large_scale + perspective_correction + TIME * large_scroll;
vec2 small_uv = refl_uv * small_scale + perspective_correction + TIME * small_scroll;
// Read displacement from RG channels, centered around 0.
vec2 disp1 = texture(disp_large, large_uv).rg - vec2(0.5);
vec2 disp2 = texture(disp_small, small_uv).rg - vec2(0.5);
float depth_factor = pow(max(fade, 0.0), distortion_depth_power);
vec2 total_disp =
disp1 * large_strength +
disp2 * small_strength;
total_disp *= depth_factor;
refl_uv += total_disp;
// Snap again after distortion to keep the reflected image crisp.
refl_uv = snap_uv(refl_uv, pixel_resolution);
refl_uv = clamp(refl_uv, vec2(0.0), vec2(1.0));
vec4 reflected = textureLod(screen_texture, refl_uv, 0.0);
vec4 stylized = mix(water_tint, reflected * reflection_strength, fade);
COLOR = vec4(stylized.rgb, fade * shoreline);
}
}
