A silhouette is the same picture from every angle, so a scene that turns one is
showing you the same shape rotated. That is the ceiling the cast has been under:
it can be notched and hollowed and it still cannot be walked around.
So the identity generates an ASSEMBLY — two to six parts, each a primitive with
an offset, a scale, a rotation and a boolean op, all under a symmetry. The
symmetry is the load-bearing half: parts unioned at random positions read as
debris, the same parts folded read as designed, and only a designed object is
worth calling a protagonist. Prism parts are the existing 2D profile extruded,
so the solid and the silhouette stay one character rather than two generators
running side by side.
It travels as data like every other artifact: three vec4 rows per part in
u_formPart, plus the scalars. Scenes declare `consumes: ['form']` and get
castSDF3, castMarch, castSolid, castChorusSolid and castLit; with no identity
they fall back to the flat profile extruded, so the helpers are safe to call
unconditionally. The chorus is the same rows with fewer parts and its own
proportions — a relative, not a second generator, and no extra uniforms.
Three scenes carry it. Effigy is new and holds the object still while it turns.
Floating Geometry and Swarm were already loops of stamps and are now loops of
bodies; Swarm is what the chorus solid exists for. That is 34.8% of videos
containing a 3D cast, against 11.9% when only Effigy had it.
Measured, the outline does change rather than merely spin: over one turn the lit
area of Effigy's subject varies 14-113% against Soloist's 3-51% for the same
rotation. Whether that reaches the variety blocks is not yet measured, and
HOWTO-variety says so rather than claiming the win.
Four costs, each found by measuring rather than by reading:
* every pixel evaluated every instance's field — Swarm at 59ms/frame against a
60ms ceiling. Bounding-sphere reject first, now 12.3ms.
* instances overlap several deep at the top of the size range, and marching
all of them made Floating Geometry's own gate run for minutes. First-wins
instead of last-wins, which was arbitrary either way.
* a normal inside the march loop multiplies four copies of the SDF by the step
count, because GLSL unrolls a fixed bound. Hoisted out.
* the helpers in the shared preamble made all 68 scenes compile what 3 of them
call. FORM_PREAMBLE is appended per scene instead.
The lint's backtick check was green through two of my own breakages: quoting a
name in a doc comment adds backticks in PAIRS, so parity survives and the
pair-scanner just re-partitions the file. It now finds where a shader literal
opens and requires the next backtick to be a real terminator — which
immediately found a second stray pair.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Three runs of the post-migration song variety measurement give separation 0.314,
0.555 and 0.065 — mean 0.311, half-range 0.245. The 0.38 quoted from a single
run was meaningless.
The cause is structural rather than a sample-size accident. Separation is
(observed - floor) / (ceiling - floor), and here the numerator is 0.0089 while
floor and observed each carry an error bar of 0.015 to 0.019. Dividing one small
difference by another amplifies the noise in both. The metric cannot resolve the
thing it was built to report.
What survives: the ceiling now sits above the floor on every run, with zero
variance, where before the epic it landed underneath and the ratio was not
computable at all. That is a change in kind and it is solid. The magnitude is
not.
The decomposition is the measurement to steer by — noise floor of exactly zero,
effects an order of magnitude above any drift — because it compares renders
directly instead of dividing differences of aggregates. Documented as such.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Song separation went from not computable — the reference sat below the floor —
to 0.38, with the floor falling from 0.1449 to 0.1185 and the gap widening.
Every structural block moved: scale 40 to 59%, orient 65 to 89%, layout 60 to
111%, texture 89 to 81%, motion 53 to 65% of the reference.
Container variety rose throughout, 0.0557 to 0.0815 to 0.0901, which is the stop
condition holding: the library did not homogenise as it converged on shared
content.
Coupling did not move and is recorded as such. Whether a song looks different in
proportion to how it sounds different is still unsolved, and the migration was
never aimed at it.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The library is sixty-one scenes, which is too many to convert from memory or
from taste, so the migration is a queue with a gate rather than a judgement call
per file.
Three pieces. A classifier reads each shader and assigns a tier from evidence in
the source — drawn, figure, field, treatment — so two passes over the library
reach the same answer and the work has an order. MIGRATION.md is the recipe per
tier, written to be followed mechanically. And a gate makes the result
verifiable: `consumes` is now a schema field, the lint enforces it in both
directions, and the per-scene battery renders each scene under two deliberately
distant identities and requires the picture to change.
That gate is the part that matters. Without it `consumes` is a comment, and the
whole inversion becomes unverifiable at exactly the point where it stops being
checkable by eye. With it, a scene that declares the cast and ignores it fails.
Eighteen scenes migrated. Four by hand at the drawn tier — Firefly Drift,
Metaballs, Floating Geometry, Prism Bloom — and ten at the field tier by script,
which is one declaration and one wrapped return. All eighteen pass.
The field tier is honestly marginal and the gate says so: every one of the ten
moves by 37 to 39 of 255, against 173 to 255 for the drawn tier, and the
uniformity across ten unrelated scenes is the tell. That is one global
posterisation applying, not ten scenes expressing anything. Cheap, real, shallow.
The decomposition moved from identity being worth 54% of the container to 158%,
but the stage set changed underneath the measurement and part of that is
Metaballs expressing a cast better than Constellation did. What survives the
caveat is the useful finding: a migrated library scene carries the identity
better than a stage written from scratch to carry it. The four bespoke stages
were the wrong shape of effort.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>