Files
Ransom-s-wake/game/world/sites/sunlit_shallows_surface_ceiling.gdshader
T
OlivierandClaude Fable 5.1 f0072a3e11
Quality Gate / Quality Gate (pull_request) Successful in 6m55s
Add sunlit shallows site with localized sun shafts
New visual test site under game/world/sites: flat sandy floor at
-40 m, calm surface at 0 m, fixed daytime sun ahead of and above
the submarine. Light shafts come from a shadow-only surface
occluder whose alpha-scissor ripples open only inside a pool a few
tens of metres ahead; a subtractive FogVolume cancels the global
volumetric fog above the water, and an unshaded ceiling mesh shows
the lit underside of the surface inside that pool. A composed
world (sunlit_shallows_world.tscn) mounts the submarine, cockpit
and camera rig in it, with the projectors kept out of the fog.

Cockpit: the porthole glass moves to its own render layer with a
rougher material and the porthole fill light excludes that layer,
so interior lamps no longer mirror as hard specular points.

Quality gate: new integration suite for the site (42 checks), three
glass assertions in the foundation suite, and the Input-access
architecture rule now matches both path separators so the gate runs
on Windows. project.godot raises the volumetric fog froxel grid to
128 so the shafts stay readable.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-06 23:18:56 +02:00

33 lines
1.3 KiB
Plaintext

// Underside of the calm surface as seen from below: dark everywhere, lit with
// drifting crests only inside the pool where the occluder lets the sun through.
// Purely visual; shadows and shafts come from the occluder mesh.
shader_type spatial;
render_mode unshaded, cull_disabled;
uniform sampler2D ripple_noise : repeat_enable, filter_linear_mipmap;
uniform vec2 pool_center_xz = vec2(-14.0, -31.0);
uniform float pool_radius = 22.0;
uniform float ripple_scale = 0.03;
uniform float drift_speed = 0.012;
uniform float lit_scale : hint_range(0.0, 1.0) = 0.3;
uniform vec3 dark_color : source_color = vec3(0.01, 0.05, 0.09);
uniform vec3 lit_color : source_color = vec3(0.5, 0.85, 1.0);
varying vec2 world_xz;
void vertex() {
world_xz = (MODEL_MATRIX * vec4(VERTEX, 1.0)).xz;
}
void fragment() {
vec2 slow_drift = vec2(TIME * drift_speed);
vec2 cross_drift = vec2(-TIME * drift_speed * 0.7);
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 crest = smoothstep(0.45, 0.7, broad * 0.65 + fine * 0.35);
float pool = 1.0 - smoothstep(
pool_radius * 0.6, pool_radius * 1.6, distance(world_xz, pool_center_xz)
);
ALBEDO = mix(dark_color, lit_color * (0.35 + crest) * lit_scale, pool);
}