Builtin Library
README.md
collage
A grid of frames in one image.
One picture that answers a question no single frame can: what does this look like from every side, what does this frame look like under each diagnostic pass, what moved over the last three seconds, which of these twenty shots is the shot.
The axis is always stated
A collage varies one thing across its cells, and the argument you pass is what that thing is:
| Argument | One cell per |
|---|---|
setups | whole camera set-up — a shot list, each entry aimed the way a single capture is |
viewpoints | named view of one subject — a list, "front top left", or "sides" for all six |
passes | render pass — final, albedo, normal, depth, motion_vectors, or any content-registered capture view |
duration | sample, spread across that many seconds of gameplay |
setups and viewpoints are one axis — both say where the camera stands — so a
request names one of them.
Naming a station axis and passes lays out a 2D grid: a row per station, a
column per pass. Reading across a row is one set-up under every pass; reading
down a column is one pass from every set-up.
A collage with no axis is refused, naming all of them. It does not fall back to time — a silent time default is exactly what taught callers that a collage could only ever be time, so nobody looked for a grid of views.
duration cannot combine with setups, viewpoints or passes. A cell that
differs both in what it looks at and in when it was taken answers neither
question; take one collage per axis.
The shot list
Each entry of setups is written the way a single capture is aimed — source,
camera, entity/entities, position, lookAt, rotation, distance,
angle, margin, viewpoint, basis, projection, orthoHeight, fov,
near, far — plus label to name the shot on the result. A field an entry
leaves out comes from the collage's own options, so a shot list writes down only
what makes each shot differ:
zero capture collage --setups '[
{ "position": [-14.6, 1.35, 4.5], "lookAt": [-16.3, 1.1, 1.6], "fov": 28, "label": "doorway" },
{ "position": [8, 3, 12], "lookAt": [0, 1, 0], "fov": 50, "label": "wide" },
{ "entity": "hero", "viewpoint": "front", "basis": "local", "label": "closeup" }
]'
Three stations, three lenses, three subjects, one instant, one picture — which is
the comparison a framing pass is made of. A key outside that vocabulary is
refused where it was written, so a misspelled fov names itself instead of
quietly framing a shot nobody asked for.
Reading the result
The grid shape is worked out from the number of cells — pass grid ("3x2") to
state it, and it is an error rather than a silent crop if it cannot hold them.
Every cell comes back labelled in cells, with its label, the viewpoint
and/or pass that made it differ, the eye it was rendered from and the lens it
was rendered through. A grid is meant to be readable from the response, not
guessable from the pictures. Only a time collage reports the window it covered —
a station or pass grid samples one instant, and reporting a span for it would
invite reading the difference between cells as motion.
Aiming it
Exactly as a single capture is aimed: entity (with viewpoint and basis, or
angle and distance), position with lookAt, camera, or nothing at all
for the main scene camera. projection, orthoHeight, isolate,
renderLayers, fov, width and height all mean what they mean for one
frame, and apply to every cell a set-up of its own does not override.
The shot most of this exists for is one call:
zero capture collage --entity crate --viewpoints sides --basis local \
--projection orthographic --isolate
Six sides of one object, each an orthographic elevation, nothing else in frame.