v1.1.0
Fixed
fresco.Rainrenders its four parallax depths as four, not three. The layer
cascade was pinned in raw field units, upstream of thesmoothstepcontrast curve
every value passes through before Pass 2. Smoothstep flattens approaching1, so
the near and mid layers —1.00and0.72, comfortably apart in the field — both
landed near the ramp's top and rendered 3.9 L* apart, against the 10-point
separation the design calls for and the16.2its own comment claimed. The
documented cascade81.9 / 65.7 / 47.4 / 35.2was never what reached the screen;
that was81.9 / 78.0 / 47.4 / 29.1.
TestRainLayersSeparateInBrightnessandTestRainHeadOutshinesItsTailnow measure
through the curve (rainScreenStopFor), which makes the guard fail on the shipped
value, and the mid layer'sbrightmoves0.72 → 0.64to satisfy it: the rendered
cascade is now81.9 / 65.7 / 47.4 / 29.1, separations16.2 / 18.3 / 18.3.0.64
is the centre of the stop-10 plateau rather than an edge of it, so a later palette
change cannot quietly tip it to a neighbouring stop. Measured on rendered output:
the mid layer's heads move out of theL* 70–79band (239 cells → 53) and into
60–69(50 → 193), opening the gap under the near layer that the parallax reads
from. Rendered bytes change by design; determinism, bounds and rain's other
invariants are untouched.
Changed
-
The README demo GIF re-recorded to tour all five variants — it previously
showed only the pre-campaign four (rain, tunnel, ripple, galaxy) and now includes
aurora, with every field at the re-art campaign's current look (including galaxy's
#60 bulge)..github/vhs/demo.tapeextends its tour by one variant accordingly.
Docs/asset only; no code change. -
fresco.Galaxy's bulge grades into the disk instead of saturating into a flat
bright mass (#60).galBulgeAmpdrops1.0 → 0.60. At 1.0 the pedestal sat near 1.0
across the inner disk, so the disk it rides on — floor + arm + knot, the knot term
doubled togalKnotAmp 2.0in #56 — stacked past 1 andclamp01flattened the sum:
2.84% of the pane clipped (val == 1.0, a field-level fact upstream of Pass 2) and
the core rendered as a solid block of two glyphs. The clamp was discarding real
structure, not a smooth saturated field — across the clipped cells the pre-clamp
bulge + diskspans1.02..2.75— so dropping the pedestal is what lets it show,
rather than making room for structure never computed. At 0.60 clipping falls to 1.36%
(the residue is sparse knot peaks, not a block) and the nucleus's local glyph
contrast —|centre − mean(8-ring)|in ramp steps, the flat-mass metric — rises
0.13 → 0.43, while the core stays the field's brightest region (core colour-stop
density 11.5 against the mid-disk's 6.1). A soft-knee was measured and rejected:
removing the clamp without dropping the pedestal compresses the1.02..2.75spread
into a band near 1.0 the glyph ramp cannot resolve, and the nucleus goes flatter
(contrast 0.008).galBulgeAmpwas settled by rendering{0.50, 0.55, 0.60, 0.65}
in colour and mono and looking: 0.65 fills the nucleus back toward the old solid look,
0.50 shrinks it to a dim dot that no longer reads as the bright core.
TestSplashGalaxyRendersABrightCoreAndDimmingArmsgains a core-structure floor
(nucleus glyph contrast> 0.25, placed between the measured flat0.13and graded
0.43): itscoreLit > 0.9andcoreDens > midDenswere both satisfied by the flat
block they were meant to guard and so could not have caught this. Rendered bytes
change by design; determinism, bounds and purity hold. -
The galaxy band tests measure against the renderer's own length scale (#61). The
radial ruler was computed two ways —renderFieldtook the vertical term as
max(cyFocal, h-1-cyFocal),galaxy_test.gotookcyFocal— which differ by one on
an even-height pane (29 vs 30 at 240×60; on odd heights the two are equal), so the
test'srhoran ~0.7% large — the raw vertical term differs ~3%, diluted through the
hypotenuse by the dominant half-width — and slid every band boundary inward. Both
now call onesplashMaxD(w, h, focalRow)helper (rain's and ripple's band tests
too), so they cannot diverge again. The knot entry
below quotes its arm-annulus bead figures on the pre-#61 ruler and the pre-#60 bulge
(118.5per 1000, ridge/gas213.8 / 19.7,10.9×); on the corrected ruler and the
shipped field they are135.5per 1000, and — taking ridges asarm ≥ 0.75and gas
asarm ≤ 0.30(the raised-cosine spiral phase, before the turbulence lift) across
the0.35 ≤ rho < 0.60annulus, over frames 0/30/60 at 240×60 —243.8 / 26.8, a
9.1×ratio (the lower bulge lifts the inner-annulus gas cells, so gas beads rise a
little more than ridge). No rendered-byte change. -
fresco.Tunnelretuned for a warmer, textured corridor. ItslumRangemoves
from1to0.75, so the ring texture takes the glyph-density ramp
(o → O → 0 → @) and reads as a tactile, receding surface rather than a flat
field of a single@; and the depth hue now relaxes to a warm base
(tunHueBase) where the sampling-rate mip leaves the sweep unresolved — the near
field and, on a real pane, most of the view — so the corridor reads as a warm
interior receding into the cool cyan rings that survive out where the sweep
resolves, instead of a uniform purple-blue wash. The field's brightness (the fog
depth cue) and its mip/angular-seam guarantees are unchanged; only the Pass-2
luminance split and the hue's unresolved fallback moved. Rendered bytes change by
design; determinism, bounds, and the tunnel's invariants still hold. -
fresco.Galaxycaught mid-turn. Its rigid pattern rotationgalRotSpddoubles
(1.0 → 2.0) so the spiral's turn — the roster's weakest motion — is plainly alive
within a second or two of viewing while staying stately rather than spinning (phase
is the field's only time term, so the per-frame step is far below any strobe). The
arm turbulence is also raised (galTurbAmp 0.62 → 0.72,galKnotThr 0.68 → 0.63,
galKnotAmp 0.70 → 0.85), which adds grain and lifts the brightest turbulence peaks
into local highlights. The texture stays additive-on-peaks, so it opens no holes; the
bright core still outshines the disk, the arm mip/anisotropy and core-finite
guarantees are unchanged, and hue still moves without touching brightness. Rendered
bytes change by design; determinism, bounds, and the galaxy's invariants still hold.An earlier draft of this entry claimed the knots "read as distinct bright beads
strung along filamentary arms". Measured againstgalKnotAmp = 0, that overstates
what the change does. The knot term is not inert — it produces 12× the local maxima
(73 against 6 across three frames, at ≥8 L* over their neighbours) — but those
maxima land in the bright core and the faint outskirts, not on the arms: per 1000
lit cells the arm annulus carries0.0and3.1beads against14.9at the core
and12.3further out, the lowest density in the field. In the glyph-density channel
they do nothing measurable at any radius (mean glyph weight9.24against9.22in
the arms). That draft went on to blame saturation — "the arms already sit at 8.4–9.2
of 11 on the ramp, so an additive term there clips instead of studding" — and that
mechanism is false too: re-measured at 240×60 over three frames, the arm annulus
clips (val == 1.0) on 11 of 14,712 cells, 0.07%, and sits at a meanvalof
0.40 of 1.0, so there was headroom where the claim said there was none. Clipping
in the field is real but lives at the bulge, not the arms (508 cells, 1.2% of the
pane). Both the mean-glyph figure and the local-maxima distribution above are also
single-channel readings taken before the instrument was sound. The
actual cause is measured in the entry below. The rotation half of this entry is
unaffected. -
fresco.Galaxy's arms are actually studded now, and the reason the previous
attempt could not have worked is a spatial-frequency one rather than a gain or a
headroom one. The knots were gated onsplashGalaxyTurbulence, an fBm carrying 47%
of its energy at a period of 7.7 columns and 74% at 3.8 columns or wider, so the term
brightened a region four to eight cells across — and a brightened region reads as a
brighter arm, not as a knot. Measured against the term switched off, only 40% of
the brightest decile of such brightenings survived subtracting its own eight
neighbours (27.6% across every cell the term brightened at all): the blob's own skirt
lifted the background it had to stand above.A bigger
galKnotAmpcould only buy that back by blowing the arms out. Swept on the
old term, arm beads per 1000 lit go13.1 → 32.2 → 50.8 → 70.4 → 84.7at
galKnotAmp 0.85 / 2 / 4 / 8 / 16, so gain alone does eventually clear this PR's own
guard (TestSplashGalaxyArmsCarryKnotsfloors at 40) — the flat "no amount of gain
could have fixed it" an earlier draft of this entry claimed is false. What it costs
is the field: arm clipping rises0.07% → 1.90% → 6.36%across that sweep, against
118.5 beads at 1.50% clipping from the lattice below. Four times the gain for
half the beads at worse clipping is the case for changing the term rather than
tuning it.So the knots now ride their own high-frequency lattice (
galKnotFreq 0.9,
galKnotPeak 0.5,galKnotAmp 0.85 → 2.0), sampled in screen cells rather than
in-plane ones — the in-plane axes are anisotropic bycellAspect/cos(galInc)= 2.17,
so a frequency compact enough to read horizontally packs past Nyquist vertically. The
turbulence now only gates them, softly (galKnotGas 0.35), because multiplying two
sparse gates together starves the count faster than amplitude pays it back. Its gate
also normalises againstgalTurbCeil 0.93— the fBm's measured maximum over 4.7M
samples — instead of the 1.0 it never reaches; the old divisor1-galKnotThrassumed
a peak of 1.0, so over that same sweep the gate topped out at 0.82 rather than 1
and averaged 0.157 over the 15.9% of samples where it fired at all (0.025 across
the whole sweep).lumRangedrops0.75 → 0.60alongside, becausedens = lit^(1-lumRange)was
spending the glyph ramp where it could not be seen: at 0.75 no measurable cell
anywhere rendered below glyph 4 of 11, so the disk used only the ramp's top two
thirds. At 0.60 the floor drops to glyph 2 and the faint disk grades· : ; +
into dark space rather than ending abruptly. Holding the knots fixed, that is worth
45.8 → 76.9 beads per 1000 lit cells across the measurable pane, and 73.5 →
118.5 inside the arm annulus. It stops at 0.60 rather than lower because 0.45
collapses the outskirts into the scatter of.and·the luminance channel exists
to prevent. Settled by
rendering{0.35, 0.45, 0.60, 0.75}in colour and mono and looking;galKnotFreq
the same way over{0.5, 0.7, 0.9, 1.3}(0.5 merged the beads into clumps, 1.3
degenerated into single-cell grain).Measured at 240×60 over three frames, beads per 1000 lit cells — cells standing a
full glyph step above their eight neighbours — go from5.6to118.5in the
arm annulus, and the arms carry the field's highest density (core17.6,
outskirts67.2) rather than its lowest. They land on the arms rather than between
them: taking the ridges asarm ≥ 0.75and the inter-arm gas asarm ≤ 0.30within
that annulus,213.8per 1000 against19.7, a 10.9× ratio.
TestSplashGalaxyArmsCarryKnotsis the new guard for this and fails on the
pre-change field; every previous galaxy assertion is a band mean and could not have.
Rendered bytes change by design; determinism, bounds, purity, the arm
mip/anisotropy and core-finite guarantees all still hold. -
fresco.Rippleretuned to make its interference pattern — the field's jewel —
read, in three moves. Its crest amplituderippleAmpdrops (0.85 → 0.65) to open
headroom under the clamp: at0.85the render curve already sent a lone crest to
within a hair of a doubled one, so the bright nodes where rings add did not stand
out; the lower value opens that gap and lights the constructive lattice against the
lone rings (the pool dims a little, the trade that keeps the fixed stars from
outshining the water). Its carrierrippleCycrises (1.5 → 1.8), deepening the
packet's trough (41% → 54%of the crest) so the cancellation nodes where two rings
meet out of phase darken and|sum|reads as a pattern rather than a stack of
circles, and giving each drop a second, fainter concentric wavefront — the train a
real drop throws. And the ring's hue is rebased onto its visible life
(rippleHueOpen): a drop is a filled disc for its first ~38% and only an expanding
ring after, so the raw age-hue spent its whole warm end on the disc and left the ring
the cool60%of the gradient — rebasing hands the expanding ring the whole
warm→cool journey, so a ring's age reads across its life. Separately the starfield —
ripple's alone among the variants — is thinned (starThreshold 0.986 → 0.992) from a
competing sparkle layer into a faint still sky the rings sit in front of. The|sum|
interference, the exact 3×3×2 spawn window, the compact-support packet, and purity
are unchanged. Rendered bytes change by design; determinism, bounds, and ripple's
invariants still hold. -
fresco.Rainretuned so its two signatures — the bright head and the depth —
land, in two coordinated moves. Its head lobe tightens (rainHeadR 4.5 → 2.9),
which is a fix as much as a retune:rainTailAmpbuys a ~28-point L* gap under
the head, but a 4.5-unit lobe reached 1.68 rows and sat in that gap itself, so the
cell one row behind a head landed at L* 71.8 against the head's 81.9 — a 10-point
step, and a head that rendered as a two-cell blob rather than an edge. At2.9
that step is 34.5 and the darkness the tail had already paid for finally reaches
the head; because the lobe is symmetric, it also cuts the glow ahead of a falling
head from ~1.7 rows to under a cell. And a fourth parallax depth is added
(rainLayers[3] → [4], withrainDensity 0.62 → 0.54so four compounding
layers do not fill the pane), because three left a hole in the middle of the
brightness histogram and the eye sorted them into "near" and "far" instead of
reading a recession; the four now land at L*81.9 / 65.7 / 47.4 / 35.2, and the
room for the extra layer came from the darker field the first move opens. The
anti-blink guarantee is untouched — the ramp's top stop is reachable only from the
rainHeadFlatplateau, and the rendered count of top-stop cells is unchanged
across the wholerainHeadRsweep.lumRangestays at1: rain's render branch
consumes only the luminance channel and discards the density one, so lowering it
would not hand the tail a glyph ramp at all — it would merely lift the whole field
and close the head/tail gap, which the rendered sweep confirmed. The stream-train
purity, the fall speed, the tail-length window, and the bespoke luminance ramp are
unchanged. Rendered bytes change by design; determinism, bounds, and rain's
invariants still hold.