From 9c7e5fa4dae859ca4dbd6f6dc59765a7a91d1320 Mon Sep 17 00:00:00 2001 From: pkuzic Date: Fri, 25 Sep 2026 16:56:30 +0100 Subject: [PATCH] MONKEY (fix-wet): seamless ripple wrap, no dry-weather churn, no sheen NaN, windows stay lit Review B3: floor(cycle) % 50 keeps the ring roll continuous across the 1000 s wrap. B8: publish the ripple clock only while it rains. B7: nudge the wet sheen half-vector off zero. B6: WORD_WINDOW batches are excluded from wet darkening. Co-Authored-By: Claude Opus 5.5 --- crates/benilla-assets/src/shaders/enhanced_water.wgsl | 4 +++- crates/benilla-assets/src/shaders/wet_hook.wgsl | 3 ++- crates/benilla-world/src/shaders/static_gx.wgsl | 4 +++- crates/benilla-world/src/weather/wetness.rs | 5 ++++- 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/crates/benilla-assets/src/shaders/enhanced_water.wgsl b/crates/benilla-assets/src/shaders/enhanced_water.wgsl index 990bb420..411ffc0f 100644 --- a/crates/benilla-assets/src/shaders/enhanced_water.wgsl +++ b/crates/benilla-assets/src/shaders/enhanced_water.wgsl @@ -279,7 +279,9 @@ fn rain_ripple_normal(world_xz: vec2, footprint: f32, distance: f32, room: let h_alt = ripple_hash(seed + 19.19); // Each period re-rolls whether this cell rains, so the pattern does not repeat. let cycle = wet_row.z * rate + h.x; - let roll = ripple_hash(seed + floor(cycle) * 7.31).x; + // MONKEY (fix-wet): `% 50` keeps the roll sequence continuous across the 1000 s + // clock wrap (cycle drops by 800 / 650, both multiples of 50). + let roll = ripple_hash(seed + (floor(cycle) % 50.0) * 7.31).x; if roll > rain * 0.85 { continue; } diff --git a/crates/benilla-assets/src/shaders/wet_hook.wgsl b/crates/benilla-assets/src/shaders/wet_hook.wgsl index cb108adf..4bf3b73b 100644 --- a/crates/benilla-assets/src/shaders/wet_hook.wgsl +++ b/crates/benilla-assets/src/shaders/wet_hook.wgsl @@ -86,7 +86,8 @@ fn wet_sheen(boost: f32, n: vec3, to_view: vec3, to_light: vec3, if (boost <= 0.0) { return vec3(0.0); } - let h = normalize(to_light + to_view); + // MONKEY (fix-wet): nudged so opposite light/view vectors never normalize a zero vector (NaN). + let h = normalize(to_light + to_view + vec3(0.0, 1.0e-4, 0.0)); let nl = max(dot(n, to_light), 0.0); let spec = pow(max(dot(n, h), 0.0), 80.0) * smoothstep(0.0, 0.15, nl); let fres = 0.03 + 0.97 * pow(1.0 - clamp(dot(n, to_view), 0.0, 1.0), 5.0); diff --git a/crates/benilla-world/src/shaders/static_gx.wgsl b/crates/benilla-world/src/shaders/static_gx.wgsl index ad217a91..9009163e 100644 --- a/crates/benilla-world/src/shaders/static_gx.wgsl +++ b/crates/benilla-world/src/shaders/static_gx.wgsl @@ -1995,7 +1995,9 @@ fn fragment(in: GxVsOut) -> @location(0) vec4 { } // MONKEY (wet): rain on sky-exposed surfaces (wet_hook.wgsl); interior, unlit and dry = untouched. let wet = wet_hook::wet_surface(rgb, n_lit, in.world_position.xyz, - select(1.0, 0.0, (in.word & (WORD_INTERIOR | WORD_UNLIT)) != 0u), wow_light.monkey); + // MONKEY (fix-wet): lit WMO windows (WORD_WINDOW) are not darkened by rain either. + select(1.0, 0.0, (in.word & (WORD_INTERIOR | WORD_UNLIT | WORD_WINDOW)) != 0u), + wow_light.monkey); rgb = wet.albedo; if (wet.boost > 0.0) { rgb = min(rgb + wet_hook::wet_sheen(wet.boost, n_lit, normalize(view.world_position - in.world_position.xyz), diff --git a/crates/benilla-world/src/weather/wetness.rs b/crates/benilla-world/src/weather/wetness.rs index caa9c4e2..ebcf73df 100644 --- a/crates/benilla-world/src/weather/wetness.rs +++ b/crates/benilla-world/src/weather/wetness.rs @@ -104,7 +104,10 @@ fn wetness_tick( ( rain, env.wetness.unwrap_or(wet.wetness), - env.ripple_t.unwrap_or(wet.ripple_time_s), + // MONKEY (fix-wet): the rings read the clock only while it rains; publishing it when + // dry rewrote the shared light buffer every frame in clear weather. + env.ripple_t + .unwrap_or(if rain > 0.0 { wet.ripple_time_s } else { 0.0 }), ) } else { (0.0, 0.0, 0.0)