look
The look of *Ashbloom*, as arithmetic. `look.at(t)` takes film-seconds and answers with one flat table holding every number the rig will push that frame — the key light, the fill, the ambient, the atmosphere, the fog, the exposure, the lens, the bright pass, the grade, the vignet…
ashbloom.light.look
The look of Ashbloom, as arithmetic. look.at(t) takes film-seconds and
answers with one flat table holding every number the rig will push that frame —
the key light, the fill, the ambient, the atmosphere, the fog, the exposure, the
lens, the bright pass, the grade, the vignette and the shadow config.
Nothing here touches the engine. Any moment of the film can be read back without a frame going by:
local look = require("ashbloom.light.look")
local L = look.at(115)
print(L.movement, L.key.intensity, L.ambient.intensity) --> bloom 0.081 0.011
The two inversions
The film's light source inverts twice, and both inversions live in this file.
Moon → sun. There is exactly ONE shadow-casting directional light in the
world, key. It is the moon through movements I–III and the sun from t = 146,
which is where the key's own intensity has fallen to about a hundredth of peak —
the shadow direction swings while nothing is casting one. The SKY is driven
separately (see below), which is what lets a night sky sit over a crater that a
moon is throwing cascaded shadows into.
Borrowed light → the garden's own. nightGate(t) = 1 - 0.97 * film.glow(t)
multiplies the moon, the fill and the cold ambient. The plants do not add light
in movement III, they REPLACE it: at t = 115 the key sits at 0.081 against a
peak of 4.0 and the only thing lighting the geometry is the geometry.
The sky's own illuminant
atmosphere.sunDirection / sunIntensity / sunColor are stated outright
rather than read off the scene's sun. Before film.DAWN the illuminant is the
MOON — the deep blue of a moonlit night is the same Rayleigh scattering as a
daytime sky, five magnitudes down, and the moon's true angular radius (0.0047
rad) puts a disc in frame. After it, the illuminant is the sun. The swap lands on
the cut into shot 21 with both ends near zero.
Where the lights stand
| azimuth | elevation | ||
|---|---|---|---|
| moon | 305° | 27° | clears the 19.5° rim by seven degrees, so it rakes |
| sun | 55° | film.sunElevation(t), −9° → +14° | over the north-east rim |
| fill | 150° | 22° | cold, opposite, casts nothing |
Both key sources stand north. The film's bookend wides look south from 92 m up on the north rim; a key from the south would give them a frame of shadowed inner wall.
The depth-of-field rack
RACK holds one row per shot — where the lens is focused, in metres, the
aperture, and how far the defocus may go. The FOCAL LENGTH is never authored: it
is derived from the shot's own vertical fov against a full-frame sensor
(focalFor), so a lens change by the camera slice moves the defocus with it
instead of leaving the two disagreeing. focusTo racks focus across a shot.
dofAt(t, override) layers the camera slice's rack over this one, row by row.
The four looks
LUT_NAMES / LUT_GRADES are the per-movement colour tables, built through
@builtin::modules.lut and installed under /source/ashbloom/light/looks/. The
continuous grade in at() does the moment-to-moment work; these carry the
character each movement's film stock would have had.
Scoped to this part · feeds back into the world's score.