Weather occlusion: untilted heightfield + per-drop direction march (rain shadow follows the actual rain) #1198

Open
opened 2026-10-28 16:10:46 +00:00 by sky_line · 0 comments
Owner

Weather occlusion today is a tilted top-down depth map: drawn along the slow mean wind and re-drawn only when that mean turns more than 2.5 degrees. The drops fly with the current wind (gusts, per-drop speed), so the rain shadow does not follow the rain: with gusts, or the wind reversing, the shadow points the wrong way. Nearly every #1145 leak also came from the tilt:

  • a steep roof the rain runs nearly parallel to is edge-on in the map (big height jumps between texels, wrong faces at ridge / eave creases);
  • the lee roof vanishes from the map, so the ridge reads as an edge and run-off streams and drips pour through the roof into the attic;
  • the camera's own column moves far off the map's centre under a strong tilt (attics fell onto the coarse map).

Decided direction (deferred for now; what shipped on dev is good enough for the moment).

Design: one untilted heightfield + a march along each consumer's own direction

  1. Draw the occlusion maps straight down (untilted), always. Each texel holds the highest static surface over that column. They re-render only on camera cell moves and scene changes (#1037 change spheres), never on wind changes. Snow already renders untilted (M3), so this extends that path to rain.
  2. Cover test = march. From a point P, step back up its own precipitation direction (about 8 steps, height-adaptive) through the heightfield. P is covered when:
    • the heightfield over P's own column is above P (anything overhead: indoors, under a roof), or
    • any marched point lies below the heightfield at its column (a wall, a roof or a tree upwind: the rain shadow).
  3. Consumers:
    • Rain / snow particles (clean_weather_sim.comp): march along the drop's own velocity (gusts included), so the shadow follows the actual rain per drop and per frame.
    • Wet / snowy surfaces (clean_weather_surface.glsl): march along the current precipitation direction, with the PCF softening at the end (budget about the current 4-tap disc x gather).
    • Run-off (clean_weather_runoff.comp): outlets on the untilted heightfield are real eaves (no false ridge edges). Streams and drips check their own falling path with the same march.
    • Snow accumulation: already marches the vertical heightfield (ssr.weather[7].zw); unify with the shared helper.
  4. Remove: the tilt (mTilt, kMaxTiltDeg, kTiltStepDeg, the per-tilt re-render), the sheared projection and parallelepiped cull planes, the camera / ground column centring for the near cascade (an untilted map centres on the camera), the slope-step and 3x3-max workarounds, the outlet cover probe, and the drip roof test.

Trade-offs

  • Lost case: rain blown in at a slant under a deep overhang (a porch, deep eaves) stays dry, because anything overhead counts as cover. That is right indoors and acceptable outdoors.
  • Possible later add-on: on RT-capable cards only, a sparse ray-query refinement for near-camera surfaces the heightfield calls covered. Not the base path: it must run on every tier (GTX 1080), and RT cores are already the frame's bottleneck.
  • Cost: fewer map renders than today (no wind-driven re-render). About 8 extra fetches per drop (negligible) and about the current per-pixel budget for surfaces.

Validation

  • The owner's attic under steep (about 60 degree) wind-driven rain: no streaks, rivulets, streams or drips inside; rafters stay dry.
  • Gusts and wind reversal: the shadow (debug view RenderVKWeatherOcclDebug) swings with the rain immediately.
  • Outdoors: wet roofs without dry specks, dormer rain shadows downwind, eave drips and streams landing outside.
  • Snow behaviour unchanged.

Related: #1145, #1037, #783.

Weather occlusion today is a **tilted** top-down depth map: drawn along the slow mean wind and re-drawn only when that mean turns more than 2.5 degrees. The drops fly with the current wind (gusts, per-drop speed), so the rain shadow does not follow the rain: with gusts, or the wind reversing, the shadow points the wrong way. Nearly every #1145 leak also came from the tilt: - a steep roof the rain runs nearly parallel to is edge-on in the map (big height jumps between texels, wrong faces at ridge / eave creases); - the lee roof vanishes from the map, so the ridge reads as an edge and run-off streams and drips pour through the roof into the attic; - the camera's own column moves far off the map's centre under a strong tilt (attics fell onto the coarse map). Decided direction (deferred for now; what shipped on dev is good enough for the moment). ## Design: one untilted heightfield + a march along each consumer's own direction 1. **Draw the occlusion maps straight down (untilted), always.** Each texel holds the highest static surface over that column. They re-render only on camera cell moves and scene changes (#1037 change spheres), never on wind changes. Snow already renders untilted (M3), so this extends that path to rain. 2. **Cover test = march.** From a point P, step back up its own precipitation direction (about 8 steps, height-adaptive) through the heightfield. P is covered when: - the heightfield over P's own column is above P (anything overhead: indoors, under a roof), or - any marched point lies below the heightfield at its column (a wall, a roof or a tree upwind: the rain shadow). 3. **Consumers:** - **Rain / snow particles** (`clean_weather_sim.comp`): march along the drop's own velocity (gusts included), so the shadow follows the actual rain per drop and per frame. - **Wet / snowy surfaces** (`clean_weather_surface.glsl`): march along the current precipitation direction, with the PCF softening at the end (budget about the current 4-tap disc x gather). - **Run-off** (`clean_weather_runoff.comp`): outlets on the untilted heightfield are real eaves (no false ridge edges). Streams and drips check their own falling path with the same march. - **Snow accumulation**: already marches the vertical heightfield (`ssr.weather[7].zw`); unify with the shared helper. 4. Remove: the tilt (`mTilt`, `kMaxTiltDeg`, `kTiltStepDeg`, the per-tilt re-render), the sheared projection and parallelepiped cull planes, the camera / ground column centring for the near cascade (an untilted map centres on the camera), the slope-step and 3x3-max workarounds, the outlet cover probe, and the drip roof test. ## Trade-offs - **Lost case:** rain blown in at a slant under a deep overhang (a porch, deep eaves) stays dry, because anything overhead counts as cover. That is right indoors and acceptable outdoors. - **Possible later add-on:** on RT-capable cards only, a sparse ray-query refinement for near-camera surfaces the heightfield calls covered. Not the base path: it must run on every tier (GTX 1080), and RT cores are already the frame's bottleneck. - **Cost:** fewer map renders than today (no wind-driven re-render). About 8 extra fetches per drop (negligible) and about the current per-pixel budget for surfaces. ## Validation - The owner's attic under steep (about 60 degree) wind-driven rain: no streaks, rivulets, streams or drips inside; rafters stay dry. - Gusts and wind reversal: the shadow (debug view `RenderVKWeatherOcclDebug`) swings with the rain immediately. - Outdoors: wet roofs without dry specks, dormer rain shadows downwind, eave drips and streams landing outside. - Snow behaviour unchanged. Related: #1145, #1037, #783.
sky_line added this to the Slipstream project 2026-10-28 16:10:47 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
sky_line/Slipstream#1198
No description provided.