Log inGet started
World

Builtin Library

Branchmain
Branchesmainpublish
Commitdd348ac6c3

README.md

mediaShadow

The shadow a fog bank casts on what is behind it.

Two compute passes run after lighting:

OrderPassWork
36media_tau_mapOne ray per texel of a light-space map; accumulate optical depth
37media_shadow_applyAttenuate each surface by the density in front of it
38compositeBlit 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.