grade
FURROW's photograph, as pure functions of one number: `t`, the seconds of film elapsed. Nothing in here touches an entity or keeps a clock, so it is safe to require from anywhere and it answers the same twice.
grade
FURROW's photograph, as pure functions of one number: t, the seconds of film
elapsed. Nothing in here touches an entity or keeps a clock, so it is safe to
require from anywhere and it answers the same twice.
local grade = require("furrow.grade")
grade.dust(t) -- 0 at shot 1, 1 at shot 24. The film's whole arc.
grade.air(t) -- every PhysicalAtmosphere field, plus groundAlbedo/sunColor
grade.sun(t) -- the sun's colour and intensity (its DIRECTION never moves)
grade.ambient(t) -- the sky dome's colour and intensity
grade.fog(t) -- HeightFog settings; density 0 through Act I
grade.lensFx(t) -- flare, halo, streak, grain
grade.shutter() -- a 180-degree shutter, constant
grade.exposure(t) -- AutoExposure, on a half-stop leash
grade.grade(t) -- the seven knobs of the fullscreen grade pass
grade.dof(t) -- the lens for the set-up the film is on, racks included
grade.shotAt(t) -- which set-up, and how far through it
furrow.Look is the only thing that pushes these at the renderer. Other slices
are welcome to read grade.dust(t) — the SAND slice in particular, so airborne
density and air density agree instead of drifting.
The arc
The sun never moves. The air does. film.clarity(t) runs 0.04 to 1.00 and
grade.dust rebases it so every curve here reads 0 at shot 1 and 1 at shot 24.
The largest single-frame change in any of these channels, measured across the
whole 181 seconds at the film's own 1/24 s step, is about 1% of that channel's
range — the arc is continuous, not stepped.
| shot 1 | shot 24 | |
|---|---|---|
aerial | 0.15 | 1.00 |
mie | 0.20 | 18.0 |
rayleigh | 0.95 | 0.06 |
skyIntensity | 0.55 | 0.85 |
| sun | white, 4.0 | 1.0/0.60/0.30, 2.05 |
| ambient | cool blue-violet, 0.55 | warm brown, 1.15 |
| fog density | 0 (passes released) | 0.017 |
| grain | 0.014 | 0.040 |
| contrast / saturation | 1.10 / 1.16 | 0.94 / 0.92 |
Three numbers that were measured, not reasoned about
mieramps to 18, not to 2.5. At 2.5 the zenith of this scene is still frankly blue. The brown-out does not read until the Mie term buries the Rayleigh one.skyIntensitystarts at 0.55. At 1.0 the noon horizon clips to a flat band of pure white across the frame.skyIntensityscales the sky alone and leaves aerial perspective on the geometry untouched, which is why it is the right knob andexposureis not.- The flare threshold starts at 2.6, not the default 0.75. At noon on gypsum most of the frame is above 0.75, and the lens-optics pass at that threshold flares the GROUND. At 2.6 only the solar disc reaches it.
The grade pass
GRADE_WGSL is a fullscreen post-process registered from inline WGSL rather
than from a .shader asset, so it lives exactly as long as the component that
registered it and leaves nothing in the world tree. The frame arriving at it is
already display-referred, so it does not tonemap — it rolls the top end off
above 0.80, then does contrast, saturation, a split tone, a shadow lift and a
vignette. A second tonemap here was tried and takes a correct noon down to dusk.
Scoped to this part · feeds back into the world's score.