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 <noreply@anthropic.com>
This commit is contained in:
pkuzic
2026-09-25 16:56:30 +01:00
co-authored by Claude Opus 5.5
parent 76cee36b2c
commit 9c7e5fa4da
4 changed files with 12 additions and 4 deletions
@@ -279,7 +279,9 @@ fn rain_ripple_normal(world_xz: vec2<f32>, 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;
}
@@ -86,7 +86,8 @@ fn wet_sheen(boost: f32, n: vec3<f32>, to_view: vec3<f32>, to_light: vec3<f32>,
if (boost <= 0.0) {
return vec3<f32>(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<f32>(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);
@@ -1995,7 +1995,9 @@ fn fragment(in: GxVsOut) -> @location(0) vec4<f32> {
}
// 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),
+4 -1
View File
@@ -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)