Ray-traced sun and moon shadows (RenderVKSunShadows 2) #185

Closed
opened 2026-09-29 22:12:39 +00:00 by sky_line · 6 comments
Owner

Ray-traced sun and moon shadows, as a third technique beside the cascaded shadow maps, the same way projector shadows got one (RenderVKProjectorShadows 2).

Why

  • Pixel-exact contact shadows, no cascade seams, no shadow acne / peter-panning tuning, no resolution loss at distance.
  • Soft penumbrae that widen with distance from the caster (sun angular radius), which cascades can't do cheaply.
  • Skipping the cascade passes frees their GPU time (4 depth renders of the scene per frame) when RT is on.

Design (reuses the projector RT path)

  • Lit FS: one ray query toward the sun/moon per pixel against the scene TLAS (traceShadowRay, RT_MASK_SHADOW, the shared candidate alpha test for mask/blend casters). Directional: target direction jittered inside a cone of the sun's angular radius (default ~0.27 deg, setting).
  • Soft shadows: stratified multi-ray on the cone (as RenderVKRTShadowSamples) + IGN noise that varies per TAA phase (as projNoisePx); proper temporal/spatial filtering later via the RT denoiser (#85).
  • Normal / distance-scaled ray offset, as the projector path (RenderVKRTShadowBias).
  • Setting: RenderVKSunShadows 0 off / 1 cascades / 2 ray traced, switchable live; falls back to cascades without ray queries, over the RT budget (#164), or with no valid TLAS this frame. Still gated by RenderShadowDetail >= 1.
  • Sun vs moon: same path, LL's shadow light direction (whichever is casting).

Key open question: TLAS coverage

The TLAS is built from this frame's MAIN cull (candidates inside the view frustum). Sun shadows need casters OUTSIDE the frustum toward the sun (a tree behind the camera shading the ground in view). Options: extend the RT instance selection with a sun-direction swept volume (frustum extruded toward the light, like cascade caster culling), or a distance ring around the camera. Must stay inside the RT memory budget (#164) and the BLAS build budget (#157 perf).

Other passes

  • Mirror / probe captures: keep cascades (or unshadowed) there -- per-pixel rays in 6 cube faces are too costly (same rule as projectors).
  • Water, particles, alpha: receive via the same function in their FS variants where they receive cascades today.
  • Terrain and sim-surround: must be in the TLAS or keep a cascade fallback for them.
  • Debug view: raw ray visibility (RenderVKDebugView).

Done when

Sun/moon shadows with RT match cascade coverage (no missing off-screen casters), are free of acne and seams, soft edges are clean under TAA, and the frame is faster than or equal to cascades on RT hardware.

Related: #85 (denoiser), #104 (projector grain), #157 / #93 (RT build cost), #164 (RT VRAM budget).

Ray-traced sun and moon shadows, as a third technique beside the cascaded shadow maps, the same way projector shadows got one (RenderVKProjectorShadows 2). ### Why - Pixel-exact contact shadows, no cascade seams, no shadow acne / peter-panning tuning, no resolution loss at distance. - Soft penumbrae that widen with distance from the caster (sun angular radius), which cascades can't do cheaply. - Skipping the cascade passes frees their GPU time (4 depth renders of the scene per frame) when RT is on. ### Design (reuses the projector RT path) - Lit FS: one ray query toward the sun/moon per pixel against the scene TLAS (`traceShadowRay`, `RT_MASK_SHADOW`, the shared candidate alpha test for mask/blend casters). Directional: target direction jittered inside a cone of the sun's angular radius (default ~0.27 deg, setting). - Soft shadows: stratified multi-ray on the cone (as `RenderVKRTShadowSamples`) + IGN noise that varies per TAA phase (as `projNoisePx`); proper temporal/spatial filtering later via the RT denoiser (#85). - Normal / distance-scaled ray offset, as the projector path (`RenderVKRTShadowBias`). - Setting: `RenderVKSunShadows` 0 off / 1 cascades / 2 ray traced, switchable live; falls back to cascades without ray queries, over the RT budget (#164), or with no valid TLAS this frame. Still gated by RenderShadowDetail >= 1. - Sun vs moon: same path, LL's shadow light direction (whichever is casting). ### Key open question: TLAS coverage The TLAS is built from this frame's MAIN cull (candidates inside the view frustum). Sun shadows need casters OUTSIDE the frustum toward the sun (a tree behind the camera shading the ground in view). Options: extend the RT instance selection with a sun-direction swept volume (frustum extruded toward the light, like cascade caster culling), or a distance ring around the camera. Must stay inside the RT memory budget (#164) and the BLAS build budget (#157 perf). ### Other passes - Mirror / probe captures: keep cascades (or unshadowed) there -- per-pixel rays in 6 cube faces are too costly (same rule as projectors). - Water, particles, alpha: receive via the same function in their FS variants where they receive cascades today. - Terrain and sim-surround: must be in the TLAS or keep a cascade fallback for them. - Debug view: raw ray visibility (RenderVKDebugView). ### Done when Sun/moon shadows with RT match cascade coverage (no missing off-screen casters), are free of acne and seams, soft edges are clean under TAA, and the frame is faster than or equal to cascades on RT hardware. Related: #85 (denoiser), #104 (projector grain), #157 / #93 (RT build cost), #164 (RT VRAM budget).
Author
Owner

First version pushed (96be80b097..75ca3a315c): RenderVKSunShadows 2 = ray-traced sun/moon, soft (RenderVKRTSunSoftness), 1 ray/pixel + TAA, leaf-accurate alpha test, cascades skipped. Cost vs cascades on a 5090: +2.4 ms (14.8 -> 17.2 ms). Opt-in for now. Follow-ups: #195 (optimization), #194 (opacity micromaps). Still to do here: Preferences UI option, water / probe / mirror ray-query variants (they currently take the sun unshadowed in mode 2).

First version pushed (96be80b097..75ca3a315c): RenderVKSunShadows 2 = ray-traced sun/moon, soft (RenderVKRTSunSoftness), 1 ray/pixel + TAA, leaf-accurate alpha test, cascades skipped. Cost vs cascades on a 5090: +2.4 ms (14.8 -> 17.2 ms). Opt-in for now. Follow-ups: #195 (optimization), #194 (opacity micromaps). Still to do here: Preferences UI option, water / probe / mirror ray-query variants (they currently take the sun unshadowed in mode 2).
Author
Owner

Shipped: RenderVKSunShadows 2 (ray-traced sun/moon shadows) is in 96be80b097..75ca3a315c. Further optimization is tracked in #195, opacity micromaps in #194.

Shipped: RenderVKSunShadows 2 (ray-traced sun/moon shadows) is in 96be80b097..75ca3a315c. Further optimization is tracked in #195, opacity micromaps in #194.
Author
Owner

Reopening: closed by mistake. The technique shipped (96be80b097..75ca3a315c, in 0.12.0 Beta 10), but two items are still open and not tracked elsewhere: (1) a Preferences control, since it is only reachable via the RenderVKSunShadows debug setting today; (2) ray-traced variants for water / probe / mirror captures, which currently fall back to unshadowed or cascades. Optimization is in #195, opacity micromaps in #194.

Reopening: closed by mistake. The technique shipped (96be80b097..75ca3a315c, in 0.12.0 Beta 10), but two items are still open and not tracked elsewhere: (1) a Preferences control, since it is only reachable via the RenderVKSunShadows debug setting today; (2) ray-traced variants for water / probe / mirror captures, which currently fall back to unshadowed or cascades. Optimization is in #195, opacity micromaps in #194.
sky_line reopened this issue 2026-09-30 06:20:26 +00:00
Author
Owner

Status check (verification sweep):

  • Done: the Preferences control (8b43904fdd, Graphics prefs: Sun/moon shadows shadow maps / ray traced) landed at 06:32Z on 09-30, after the reopen. Shipped in v0.12.0-beta.10.
  • Still open: ray-traced variants for the other passes. The water glint is unshadowed in mode 2 (clean_water.frag ~206: shadow_params.w > 1.5 ? 1.0 : sunShadow(...)). Probe and mirror captures use cascades or are unshadowed (cfef35fcc8, b1cae70f1e; rtMaskUsable() excludes probeCapture/mirrorPass).
Status check (verification sweep): - Done: the Preferences control (8b43904fdd, Graphics prefs: Sun/moon shadows shadow maps / ray traced) landed at 06:32Z on 09-30, after the reopen. Shipped in v0.12.0-beta.10. - Still open: ray-traced variants for the other passes. The water glint is unshadowed in mode 2 (clean_water.frag ~206: `shadow_params.w > 1.5 ? 1.0 : sunShadow(...)`). Probe and mirror captures use cascades or are unshadowed (cfef35fcc8, b1cae70f1e; rtMaskUsable() excludes probeCapture/mirrorPass).
Author
Owner

Status 2026-10-05: shipped, with a Preferences control. Left open for the remaining scope: ray-traced shadows in water glints and probe / mirror captures (currently cascades or unshadowed).

Status 2026-10-05: shipped, with a Preferences control. Left open for the remaining scope: ray-traced shadows in water glints and probe / mirror captures (currently cascades or unshadowed).
sky_line added this to the Slipstream project 2026-10-06 15:04:15 +00:00
Author
Owner

Done: ray-traced sun and moon shadows ship as RenderVKSunShadows = 2 (Preferences > Graphics > Advanced). Follow-ups live in #572 and #567.

Done: ray-traced sun and moon shadows ship as RenderVKSunShadows = 2 (Preferences > Graphics > Advanced). Follow-ups live in #572 and #567.
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#185
No description provided.