lightbox
The light and the air of **Standing Ovation** — the Odeon Marisol's four light sources, the medium they travel through, everything falling through it, and the chain the frame is photographed with.
lightbox
The light and the air of Standing Ovation — the Odeon Marisol's four light sources, the medium they travel through, everything falling through it, and the chain the frame is photographed with.
The film's arc is the light source, and it goes all the way round: one sodium worklight, then fourteen tungsten footlights from below, then one hard followspot through haze, then the chandelier and the house lights, and then back to the worklight alone. Every value in this module is a function of film time; nothing polls and nothing reads wall time.
local LB = require("lightbox.lightbox")
LB.install() -- build the rig and register it on the film clock
LB.report(50) -- what every source is doing at that film second
LB.teardown() -- take it all away again
Do not call install from a one-shot script. The volumetric march, the
depth of field, the shutter, the exposure meter and every particle emitter are
acquired in whatever resource scope creates them, and an execute scope ends a
moment later and takes them with it — the rig then reads back as live and draws
nothing. lightbox.lightbox (the component) exists to be that scope. Add it to
the scene's Lightbox anchor:
entity.find("Lightbox").component.add(
asset.resolve("lightbox.lightbox", "component"), {})
What it puts in the world
Everything is parented under lb_root beneath the Lightbox anchor.
lb_worklight + lb_worklight_bulb + lb_worklight_glow | the sodium practical: a shaded head making a pool on the deck, the bare bulb glowing into the haze, and the visible filament |
lb_foot_1..14 + lb_foot_glow_1..14 | fourteen tungsten footlights along the apron, aimed up and upstage so a performer's shadow climbs the back wall |
lb_followspot + lb_followspot_spill | the lantern on the balcony rail: a hard iris, and the light that escapes its gate |
lb_chandelier + lb_chandelier_glow + lb_house_1..8 | the chandelier and eight coves washing the walls above them |
lb_air | the participating medium — haze in all four acts |
lb_fog | a breath of height fog so the far end of the house falls away |
lb_lens / lb_shutter / lb_meter | depth of field, a 180-degree shutter, bounded auto-exposure |
| five GPU emitters | dust in the worklight's beam, the dome's leak, the rain behind it, water down both proscenium jambs, and the plaster that comes off the dome under shot 11 |
post effects lb_bloom / lb_tonemap / lb_lut / lb_grain / lb_vignette | the chain, in that order |
It also retunes the scene's ambient down to a floor and turns the world's
default daylight sky off — this is an interior at three in the morning.
The parts worth knowing before you change a number
TRIM converts the look's units into the renderer's, per fixture.
Film.LIGHTS[*].intensity states each source relative to the others — the
worklight at 60 against the followspot at 900. The renderer's rows are
photometric and fall off with the square of the distance, and these four
fixtures work at wildly different distances, so one conversion constant cannot
serve them. Each entry was read off a lit surface at the distance that fixture
is aimed at.
A light's range is composition, not performance. A worklight that reaches
the back of the house lights the whole room evenly and the shot reads as a lit
model. Clipped to sixteen metres it makes a pool on the deck and leaves an
enormous dark house around it, which is what shot 1 is about.
The house lights are coves, not bulbs. Each sits against a wall and washes up it. Point lights in the same positions light everything they can see equally, which is the fastest way to make an interior read as an architectural render rather than a photograph.
The followspot lantern sits beside and below the balcony-rail camera station, never on it. Co-axial, the first metres of its own haze fill the bottom of shot 8 with a white wash and the beam has no direction.
The volumetric march integrates only as far as the nearest surface, so a beam is visible where there is open air in front of the lens and invisible where a seat back is two metres away. Shots 8 and 12 look down the length of the house and are where the cone reads.
Shot 13 is graded through the same table as shot 1 — SHOT_GRADE names
"worklight" for both, and both resolve to the one installed lb_lut_worklight
asset, with the same exposure compensation. The two ends of the film cannot
drift apart because there is only one of them.
The grain runs on the film's frame number, not on a clock of its own, so two playthroughs carry the same negative and a held frame is bit-identical to itself.
Reading it back
LB.report(t) answers what every source is doing at a film second — level per
fixture, where the followspot is pointing, and the haze density. It is the call
to make before reading a screenshot when a frame is darker than expected.
Scoped to this part · feeds back into the world's score.