A scatter point in Isometric Blocks — which measures worse, twice

Asked for, built, and honest about the result: the focal point costs this scene
a quarter of its variety and I could not make it pay for itself.

    uniform scatter, no focus     0.0490
    focus, trading scatter for it 0.0374
    focus, added on top of it     0.0365

The first version spent the scatter budget near the focus and calmed the rest,
which put most of the field back on the rigid lattice and took the orientation
variety with it, 0.164 down to 0.105. That diagnosis looked right, so the second
version made the focus additive — every cell keeps its full scatter and the ones
near the point get more. It changed nothing: 0.0365, orientation still 0.104.

So the diagnosis was wrong and I do not have the real one. The remaining suspect
is the height modulation, which lifts blocks toward the focus and may be
flattening the skyline's variety between songs by dominating it — but that is a
guess, and two guesses have already been wrong here.

The feature is committed rather than reverted because the metric does not
measure what was asked for. A scatter point is a compositional idea, and the
gallery scores how much a scene changes BETWEEN songs, which is a different
question — Apollonian Gasket makes the same point from the other direction. This
may well look better and score worse. It needs eyes on it before the number
decides.

`gather` is a parameter and seed-driven like any other, so the amount varies per
song as asked; the focal points themselves come from the identity.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Dejvino 2026-08-18 16:42:55 +02:00
parent b1e58a6603
commit 5a9dfa6b2b

View File

@ -27,6 +27,16 @@ export const isometricBlocks = {
// enough to nothing. Displacing them per cell puts the SONG in the
// arrangement rather than only in the elevation.
scatter: { type: 'float', range: [0, 0.85], default: 0.3, uniform: 'u_scatter', bias: 'density' },
// Extra disturbance AT the song's focal points, on top of the scatter
// everywhere — not instead of it.
//
// It was a trade at first, spending the scatter budget near the focus
// and calming the rest, and that measured worse than no focus at all:
// 0.049 down to 0.037. Most of the field went back onto the rigid
// lattice and took the orientation variety with it, 0.164 to 0.105. The
// focal point has to be something the field gains, not something the
// rest of it pays for.
gather: { type: 'float', range: [0, 1.6], default: 0.8, uniform: 'u_gather' },
plan: { type: 'float', range: [0.2, 0.5], default: 0.4, uniform: 'u_plan' },
tilt: { type: 'float', range: [0.35, 0.75], default: 0.55, uniform: 'u_isoTilt' },
light: { type: 'float', range: [0, 1.4], default: 0.65, uniform: 'u_light' },
@ -88,14 +98,29 @@ vec4 scene(vec2 uv, vec2 p) {
float row = rowHere - float(7 - j);
vec2 cell = vec2(colX, row);
// Each cell steps off its slot by a fixed amount of its own, so the
// plan of the field is the song's rather than the lattice's. Bounded
// under half a cell: past that blocks cross each other and the
// isometric read — which is the whole point of the scene — breaks down.
vec2 offset = (hash22(cell + u_seed + 3.7) - 0.5) * u_scatter * cw * 0.9;
// Where this block would stand if nothing disturbed it, so the focus can
// be asked about the cell rather than about the pixel.
float restY = (row + stagger) * tilt * cw;
float focus = focusField(vec2((colX + 0.5) * cw - 0.5, restY));
float groundY = (row + stagger) * tilt * cw + offset.y; // where this cell meets the ground
float h = columnHeight(cell, t) * (1.0 + offset.x * 2.0);
// Each cell steps off its slot by a fixed amount of its own, and how far
// depends on how close it is to what the song is looking at. Spread
// evenly this is noise on a grid; concentrated, the lattice stands
// except where it is disturbed, and the field acquires a subject.
//
// Bounded under half a cell: past that blocks cross each other and the
// isometric read — which is the whole point of the scene — breaks down.
float amount = u_scatter * (1.0 + focus * u_gather * 2.0);
vec2 offset = (hash22(cell + u_seed + 3.7) - 0.5) * amount * cw * 0.9;
float groundY = restY + offset.y; // where this cell meets the ground
// Blocks rise toward the focus as well as scattering around it, so the
// disturbance is something you can see in the skyline rather than only
// in the plan — and rising changes WHERE the frame's energy is, which
// scattering alone did not.
float h = columnHeight(cell, t)
* (1.0 + offset.x * 2.0)
* (1.0 + focus * u_gather * u_focusPull * 1.3);
float dy = p.y - groundY; // height up the block face
// Side wall: the plan swept up from the ground line to the top face.