Builtin Library
README.md
aerialPerspective
The render feature behind PhysicalAtmosphere and
@builtin::systems.atmosphere.atmosphere. Four compute passes run after
lighting, in order:
| order | pass | output |
|---|---|---|
| 10 | atmo_transmittance | 256x64 transmittance from a point out to the top of the atmosphere, in the Bruneton (r, mu) parameterisation |
| 12 | atmo_multiscatter | 32x32 multiple-scattering transfer function, integrated over the sphere of directions |
| 14 | atmo_skyview | 192x108 sky radiance per view direction from the camera's altitude, horizon-concentrated |
| 16 | atmo_composite | scene depth in, aerial perspective and sky out |
The composite reconstructs each pixel's world position from @scene.depth and
the drawn camera's inverse view-projection (@frame.camera), marches the medium
between the camera and the surface, and applies surface * transmittance + in-scattering. Sky pixels sample the sky-view LUT and add the solar disc,
attenuated by the same transmittance — which is what reddens a low sun.
Because the camera comes from @frame.camera, the atmosphere is correct in
offscreen captures and render-to-texture cameras, not only the live viewport.
The sky-view LUT derives its own altitude and sun elevation from that same
camera, so a capture from a different viewpoint gets its own sky rather than
the live viewport's.
Sky and geometry come out of one integral, so they agree at the horizon by construction: as a surface recedes its transmittance goes to zero and its in-scattered term goes to exactly the sky radiance for that direction.
Scattering coefficients are Earth's, in kilometres and inverse kilometres.
worldUnitsPerKm maps the scene onto them, so the same physics serves a
metre-scale scene and a kilometre-scale one.
Costs
The three LUTs are rebuilt every frame. Together they are around 1.2M shader steps — under a single full-screen pass at 1080p — and rebuilding unconditionally is what lets the sun move continuously with nothing to invalidate.
The composite marches per pixel rather than sampling a low-resolution froxel
volume. That trades the volume's fixed cost for accuracy that does not depend
on where a surface falls between froxel slices; aerialSteps is the knob.
Colour
The scene target holds display-encoded values, so the composite decodes them to
linear, attenuates and adds in-scattering in radiance, and encodes the result.
exposure is what maps radiance into the displayable range — raise it for a
brighter sky, and the aerial perspective brightens with it, since both come
from the same integral.
Parameters arrive through the atmo_params buffer, packed by
@builtin::systems.atmosphere.atmosphere.