Commit Graph

4 Commits

Author SHA1 Message Date
Dejvino
8defef3ed0 Tell a dead shader apart from a boring scene in the gallery
A failed shader compile renders black, and black frames are identical to each
other, so every block scores 0.000 and the row reads as the least varied scene
in the library rather than as a broken one. That happened yesterday — the
subject helpers were declared above the ink they call, GLSL has no forward
declarations, the whole preamble failed to compile, and the gallery reported a
variety of exactly 0.000 with no indication anything was wrong. It is a
particularly bad failure mode for a tool whose entire job is ranking scenes by
that number.

A scene whose first frame has no luminance and no variance is now reported as
broken, with both figures and a pointer to the console, and the row is coloured
apart from the merely flat ones so it cannot be mistaken for a bad score. The
summary counts them separately.

Verified against both answers rather than only the happy one: a healthy Moiré
Grid comes back 0.0365 with no error, and a deliberately broken copy of the same
scene comes back with the diagnosis instead of a zero.

Recorded in HOWTO-variety.md alongside the other instrument traps, since the
general lesson outlives this instance — a broken render produces the most boring
possible numbers rather than an error.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-18 16:55:16 +02:00
Dejvino
71ddd37711 A minimum variety bar in the gallery, drawn as a red line
A visualizer that looks the same wherever it appears does not just fail to vary
— it leaks between songs, because it is cast into many of them and the viewer
who watches two videos ends up recognising the shot rather than the song. That
makes the floor a property of the scene, so the gallery now states it and the
scene has to clear it.

0.04 to start with, and honestly a starting bar rather than a derived one: set
where the flat cluster measurably sits, to be raised as scenes are lifted to it.

Drawn twice, because the two readings are different questions. Every meter
carries a red marker at the bar, so a single row can be judged on its own. And
in the default sort the list is cut by one red line where the scores cross it,
which answers the browsing question — everything above that line repeats itself
between songs.

Also restored progressive drawing, which the caching rewrite had quietly lost:
every draw had moved to the end of the build, leaving three minutes of spinner
and nothing to look at. The first rows are the interesting ones, since the sort
puts the repetitive scenes on top.

Verified by seeding the cache with rows spanning the bar and reloading: four
below, four above, the line between them, the marker at 20% of each meter, and
the grade colours switching at the right place.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-18 16:29:09 +02:00
Dejvino
e90951c277 Cache the gallery against a fingerprint of the source that built it
Three minutes of GPU work is fine once and intolerable on every page load, so
the gallery now builds once and comes back from IndexedDB after that.

The key is the part worth getting right. A cache you clear by hand is worse than
no cache: it will eventually show last week's pixels while you are judging this
morning's change, and it will look like a render, so you will believe it. Here
the key is a fingerprint of every file under src/, collected through
import.meta.glob so it covers the shaders, the identity, the look generator, the
engine and the descriptors without naming any of them — the file that
invalidates a render is exactly the one nobody remembers to list. Edit anything
and the entry stops matching and the page rebuilds without being asked.

Thumbnails are WebP blobs rather than raw pixels: sixty-five scenes at six
frames of 256x144 is 57MB raw, and measured, the compressed form is 4.1MB for
the whole library. Saving a build evicts every other one, so the store cannot
grow without bound.

The spinner is a CSS animation on purpose. Building blocks the main thread in
bursts and a JS-driven spinner would freeze mid-turn, which reads as a hang
exactly when the page most needs to look alive.

Verified rather than assumed, six behaviours: the fingerprint is stable across
calls; a build round-trips through storage and decodes to a real image (51%
non-black); a different fingerprint misses; saving a new key evicts the old; and
appending one comment to one scene file moved the fingerprint from 125-f842b05e
to 125-c056d7b9, which is the invalidation working end to end.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-18 07:19:22 +02:00
Dejvino
c6d96c9d40 A gallery, and a debug index to reach it from
Sixty-five visualizers, six renders each, one per song — each carrying that
song's whole identity: its cast, ink, lattice, palette and a fresh parameter
draw. Side by side, a scene that cannot be changed by the song is obvious in a
way no aggregate could show, which is the complaint this answers.

It scores as well as shows. Each row carries the mean structural distance
between its own six frames, on the same descriptor the variety harness uses and
with colour excluded, so six palettes cannot disguise one image. Sorted
least-varied first, because browsing sixty-five scenes hunting for the
repetitive ones is precisely what a sort order should do for you.

The result names names. Thirteen scenes barely change across six songs, and they
fall into two groups that were already known separately. The ink-only
migrations — Analog Wow, Halftone Misprint, Pitch Shatter, Block Mosh, Scan
Tear — are the shallow tier flagged in MIGRATION.md, where the whole migration
was one posterisation. And Moiré Grid, Isometric Blocks, Quasicrystal, Truchet
Fold, Voronoi Shatter and Apollonian Gasket are the structural twin cliques the
library sweep found weeks of measurement ago, arriving here by a completely
different route: the sweep compared scenes to each other, the gallery compares a
scene to itself, and they agree on the same offenders.

debug.html collects the tools, since there are now enough of them that knowing
which to open is its own problem. It also carries the two things a newcomer
would otherwise learn the hard way: which measurements are safe to steer by
(direct render comparisons) and which are not (aggregate ratios), and what to do
when a page renders perfectly and does nothing.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-18 07:13:54 +02:00