Expand description
Flat opaque elements painted on their own paper (ADR-0123).
Every other scene in this engine draws light: premultiplied additive
colour into a linear-light composite, where nothing is in front of anything
(ADR-0018, ADR-0046, ADR-0056). This one draws a graphic. A pixel starts
at the paper colour and walks an array of elements in array order,
compositing each with over, so a black bar genuinely sits in front of a red
one and the array index is the depth. There is no depth buffer, no sort,
and no ordering state — the painter’s loop is the whole mechanism.
§Three engine properties this look rests on, and breaks without
Measured in ADR-0123’s Context; named here because each is a thing an unrelated edit could take away.
- A fullscreen scene emitting alpha 1 holds the backdrop out entirely — not darkened, absent. So a scene covering every pixel owns its own ground.
- The tonemap is exactly the identity below
KNEE = 0.6(ADR-0046), so an element at or under it leaves the post chain unshaded. Below the knee the pipeline is a no-op — flatness is not argued for against it. - Bloom’s threshold sits above that knee, so a canvas living under it gets no halo and hard edges stay hard, at no cost and no parameter.
The authored hex does reach the display, and the knee is why. A palette
stop is sRGB and is decoded to light once at the load boundary (ADR-0151), so
the load decode and the display encode are inverses and everything between
them is the identity below the knee: an element written #494949 presents as
#494949. The cap therefore has an authored form — 0.6 of light is sRGB
byte 0xcb, the brightest channel any element here may carry. Same curve for
every element, no shading and no halo: that is the property the look rests
on. Nor does the curve give paper at pure white — f(1.0) = 0.800, and 1.0 is
asymptotically unreachable, so both reference grounds are off-white by
construction.
§Colour is a palette coordinate
An element stores a coordinate, never an RGB triple, so every palette, custom
stop and A/B crossfade in docs/preset-palettes.md applies here on arrival
with no special case (ADR-0086, ADR-0102). The paper takes a coordinate too,
and deliberately a raw one: color_span and palette_shift move the
elements’ colours and must not drag the ground along with them.
§The aspect comes from the render target (ADR-0037)
This scene computes screen-destined geometry from a normalized space, which
is exactly the shape of the bug that has shipped three times in this repo.
The canvas is built in square units by stretching NDC x by the render
target’s aspect, so a circle element is round at every window shape. tests
renders at 1280x800 and measures a circle’s own width against its height:
1920x1080 and this box’s 2048x1152 are both exactly 16:9, where no test can
tell a target-derived aspect from a grid-derived one, and 16:10 is the case
that discriminates.
§The cost, and where its bound lives
The draw is O(elements) per pixel and the bounding-box reject removes the
distance evaluation but not the loop step, so a wavefront walks every
element regardless. The bound is
TierConfig::collage_elements
— measured by core/tests/collage_cost.rs, not assumed.
Two things here exist to keep that loop cheap and are worth not tidying away:
the rotation arrives as a precomputed cosine and sine pair rather than an
angle (no per-pixel-per-element trig, and no dependence on sin’s
implementation-defined precision, which ADR-0096 disqualifies elsewhere for
the same reason), and the axis-aligned bounding box is computed CPU-side and
tight for every kind — a loose box is a silent cost regression that no
picture would show.
Structs§
- Shape
Collage Scene - The flat-graphic canvas: opaque elements over their own paper, composited in one fullscreen distance-field pass.
Constants§
- PARAMS
- The parameter names this scene consumes — the vocabulary a preset binding is
checked against at load (ADR-0020). Keep in sync with
set_parambelow;declared_params_match_set_paramincore/tests/preset.rsfails if the two drift.