// Calm-water surface seen only through its shadow: the mesh is invisible // (SHADOW_ONLY) and the alpha-scissor cut-outs let the fixed daytime sun carve // light shafts into the volumetric fog below. shader_type spatial; render_mode cull_disabled, unshaded, depth_prepass_alpha; uniform sampler2D ripple_noise : repeat_enable, filter_linear_mipmap; uniform float ripple_scale = 0.025; uniform float drift_speed = 0.012; uniform float coverage : hint_range(0.0, 1.0) = 0.30; // World-space pool where the surface lets sunlight through. Outside it the // surface is fully opaque, so shafts only form in that patch of water. uniform vec2 pool_center_xz = vec2(-14.0, -31.0); uniform float pool_radius = 22.0; uniform float pool_edge = 12.0; varying vec2 world_xz; void vertex() { world_xz = (MODEL_MATRIX * vec4(VERTEX, 1.0)).xz; } void fragment() { vec2 slow_drift = TIME * drift_speed * vec2(1.0, 0.35); vec2 cross_drift = TIME * drift_speed * vec2(-0.4, 0.9); float broad = texture(ripple_noise, world_xz * ripple_scale + slow_drift).r; float fine = texture(ripple_noise, world_xz * ripple_scale * 1.9 + cross_drift).r; float raw_ripple = broad * 0.65 + fine * 0.35; // Inside the pool the crests are sharpened so the gaps cut crisp shafts. float pool_ripple = smoothstep(0.35, 0.65, raw_ripple); // Outside the pool only the deepest troughs open: a dim dapple, not darkness. float dim_ripple = smoothstep(0.16, 0.30, raw_ripple); float pool = 1.0 - smoothstep( pool_radius - pool_edge, pool_radius, distance(world_xz, pool_center_xz) ); ALBEDO = vec3(0.0); ALPHA = mix(dim_ripple, pool_ripple, pool); ALPHA_SCISSOR_THRESHOLD = coverage; }