stratum · round one · measured

The third axis

Thirteen spheres in close pack through the Bayer-8 gate, one fragment per dither cell. A 1-bit solid that does not shimmer: 0.47% of cells change per frame against 4.94% for the control.

evidence produced by scripts in artifact/strata/onebit-3d/ · plates in the review · live in the canon
The third axis plate

Evidence

Every number below came out of Playwright/Chromium launched with --use-gl=swiftshader --enable-unsafe-swiftshader. Headless has no GPU, so every timing is a lower bound on performance: software GL is roughly 10× slower than any real device.

Harness: the stratum's own HTML/CSS/JS mounted over the built <style> block lifted from canon.BEFORE.html, so the real Geist and Departure faces and the real token layer are in play. Run at 1440×900 and 390×844, plus a reducedMotion: 'reduce' context.

Compiles clean

Fragment and vertex shader compile, program links, and all three info logs are empty strings — not merely "no error flag". All six uniforms bind: u_res u_time u_mouse u_hover u_pitch u_rings.

Console

Zero page errors and zero console errors at 1440×900, at 390×844, and under reduced motion. (The only console output at all was four Chromium GPU stall due to ReadPixels performance warnings, emitted by the test harness's own readPixels calls, not by the stratum.)

Frame cost — measured, and it is the whole design argument

drawArrays followed by a 1-pixel readPixels to force the pipeline to finish, 24 frames, p50/p90:

bufferfragmentsp50p90
desktop stage, one fragment per cell (195×117)22,8155.9 ms6.6 ms
mobile stage, one fragment per cell (68×75)5,1001.6 ms1.7 ms
the same shader at 1:1 pixels (780×470)366,60082.2 ms93.0 ms

The budget is ≤7 ms/frame. Rendering one fragment per pixel misses it by 12× on this machine; rendering one fragment per dither cell meets it with margin. That is not an optimisation bolted on afterwards — it is the same decision that makes each cell take exactly one threshold decision.

Live loop, 80 rAF intervals: p50 16.7 ms, p90 16.7 ms at both viewports — vsync-capped, i.e. the loop never missed a frame. The adaptive ladder never fired: CELL stayed at 4 px on both.

It animates

Two canvas captures 1.4 s apart differ (byte-compare). [LIVE] in the meta row. Buffer 195×115 desktop, 68×75 mobile.

It does not shimmer — measured against a broken control

The real question is how many cells flip state between consecutive 60 Hz frames. Measured by rendering the exact shader at t = 3.000 … 3.500 in 1/60 s steps with preserveDrawingBuffer, reading the cells back, and counting disagreements. "Support" is the set of cells the object ever lights.

buildsupportcells flipped per frame% of support
shipped2,63512.30.47 %
control: patches sampled on gl_FragCoord, 3 s revolution3,948195.14.94 %

The control is the two mistakes the brief names, and nothing else changed. The shipped build is 10.5× quieter. 0.47 % of ~2,600 cells is about twelve cells a frame — a terminator creeping, not a boil.

Reduced motion is static AND non-blank

reducedMotion: 'reduce' → one frame at t = 3.0, no rAF. Two captures 2.0 s apart are byte-identical. State reads [STATIC], and the Turn control is disabled rather than silently inert.

Non-blank, counted off the 780×462 capture: 40,416 lit pixels — 11.22 % of the plate — of which 420 are the essence dot, 1,408 warm and 1,152 cold. The still frame carries the solid, the terminator seam, and the living dot at 0.99 of systole.

The pointer perturbs; it does not drive

Rendered at fixed t with the mouse at a fixed cell, comparing lit-cell sets:

testcells differing
u_hover = 0, mouse far vs mouse on the plate0 — exact identity
u_hover = 0 vs u_hover = 1 at the same instant129 (4.9 % of support)
pointer held perfectly still, t advanced 1.5 s765 (26.2 % of support)

Time moves the piece 5.3× more than full pointer presence does, and with no pointer the shader is bit-for-bit the no-pointer shader. Confirmed live too: two captures 1.6 s apart with the mouse motionless differ.

Type, colour, targets

Constants that were measured rather than inherited

Not established