Builtin Library
README.md
mediaShadow
The shadow a fog bank casts on what is behind it.
Two compute passes run after lighting:
| Order | Pass | Work |
|---|---|---|
| 36 | media_tau_map | One ray per texel of a light-space map; accumulate optical depth |
| 37 | media_shadow_apply | Attenuate each surface by the density in front of it |
| 38 | composite | Blit the result |
Why not a shadow map
A depth-based shadow map answers one question per texel: is this point nearer
the light than the first thing the light hit? Density has no first thing. What
a medium does to light is continuous — a ray crossing d units of extinction
k keeps exp(-k*d) of its energy — so what a receiver needs is the optical
depth between it and the light, not a depth to compare against.
The first pass therefore stores optical depth rather than distance, at four points down each ray. Two consequences fall out of that choice:
- Overlapping media stack. Optical depth is additive, so two volumes that intersect contribute to the same running total with nothing to resolve.
- Geometry inside a volume is lit correctly. A receiver looks up its own position along the ray and reads the depth accumulated up to that point, so a post standing in the middle of a fog bank is dimmed by the half in front of it rather than by the whole column.
Inputs
@scene.color, @scene.depth, @frame.camera, and the media_params /
media_volumes buffers packed by
@builtin::systems.volumetrics.mediaTransmittance.
Sky pixels are passed through untouched.