shader_type spatial; render_mode blend_mix, cull_disabled, diffuse_burley, specular_schlick_ggx; // Lake water: two scrolling normal maps for ripples, colour and opacity from // the depth of water under each pixel (clear shallows, dark deep water), and // foam where the surface meets the shore. #include "res://shaders/common.gdshaderinc" uniform sampler2D DEPTH_TEXTURE : hint_depth_texture, filter_linear_mipmap; uniform sampler2D normal_tex : hint_normal, filter_linear_mipmap, repeat_enable; uniform vec3 shallow_col : source_color = vec3(0.22, 0.44, 0.42); uniform vec3 deep_col : source_color = vec3(0.03, 0.12, 0.17); uniform float clarity = 2.5; varying vec3 w_pos; void vertex() { w_pos = (MODEL_MATRIX * vec4(VERTEX, 1.0)).xyz; } void fragment() { vec2 uv = w_pos.xz; vec3 n1 = texture(normal_tex, uv * 0.045 + TIME * vec2(0.012, 0.008)).rgb; vec3 n2 = texture(normal_tex, uv * 0.11 + TIME * vec2(-0.010, 0.017)).rgb; NORMAL_MAP = mix(n1, n2, 0.5); NORMAL_MAP_DEPTH = 0.7; // Thickness of water between the surface and whatever is behind it. // (Godot 4.3+ uses reversed-Z: raw depth is the NDC z.) float depth = texture(DEPTH_TEXTURE, SCREEN_UV).r; vec4 behind = INV_PROJECTION_MATRIX * vec4(SCREEN_UV * 2.0 - 1.0, depth, 1.0); behind.xyz /= behind.w; float thick = max(VERTEX.z - behind.z, 0.0); float t = 1.0 - exp(-thick / clarity); vec3 col = mix(shallow_col, deep_col, t); float foam_n = nz(uv * 0.6 + TIME * 0.02); float foam = (1.0 - smoothstep(0.0, 0.25 + foam_n * 0.35, thick)) * 0.8; col = mix(col, vec3(0.88, 0.93, 0.93), foam); ALBEDO = col; ALPHA = clamp(mix(0.3, 0.93, t) + foam, 0.0, 1.0); ROUGHNESS = 0.04; SPECULAR = 0.6; METALLIC = 0.0; }