band-field
band-field
ONE TAG, BOTH FAMILIES — the unified displaced surface.
Read the rig's notes
<heightfield> and <shadergradient> were the same idea twice. This reel is
that idea once: an ordinary primitive wearing a <bands> table, with the
three things they disagreed about turned into values.
1. UNITS ARE ONE CONVENTION. freq = cycles across the shape's own extent
(size-invariant); amp = PEAK MILLIMETRES that band displaces, an
absolute length; fold = 0..1 toward 1-|n| creases. The old pair
disagreed on both — heightfield's amp was mm while ShaderGradient's was
tenths of a 10-unit sheet scaled by `unit`, and their frequencies were
a factor of 4.3 apart. Neither `unit` nor `waterPlane` survives: size
is mm, and a waterPlane is a plane with both axes subdivided.
2. DIRECTION IS A VALUE. `along=y|z|normal`. A height field pushes along
one fixed axis; a blob pushes along its own normal — which is the only
reason <shadergradient> could take a sphere and <heightfield> could
not. WHERE the field is sampled is a separate question (`sample=`),
because a flat sheet sampled on its normal would be constant.
3. SHADING IS A SLOT. `mix` is the only colour model: stops along `u`,
optional accent along `v`, optional sun-dot, optional ambient of its
own (`brightness`, which is why these scenes need no <lights>).
Terrain is mix(u=height sun=… shade=…). ShaderGradient topology is
two U endpoints plus accent — mix(u=x v=height) on a sheet, mix(u=y
v=radius) on a blob. Every axis normalises by the field the scene
actually has, measured at build, not by a bound it never reaches. No
shading block, and the author's material stands untouched, which is
what an animated sea needs for transmission and real HDR
reflections.
And no new tag was needed. `<bands>` and a shading block are children that
any primitive can carry, so a sheet is <primitive><geometry type="plane">
and a blob is <polyhedron kind="icosahedron">.
THE OLD TAGS ARE STILL IN THE ENGINE. promos/primitives/terrain/terrain.promo
still runs on its own generator. <shadergradient> does too, but nothing
exercises it any more: all ten of its published presets now stand here as
<bands> + mix (S4, S5 and S44–S51), and the two reels that carried them —
backgrounds/shader-gradients.promo and its rows-form twin — are gone.
FIFTY-ONE SCENES, NINE FAMILIES. S01–S25 are the two old tags' own
territory, re-shot on the unified surface; S26–S43 are `mix` on its own
terms — every lever the colour model has, one per scene; S44–S51 are the
ten published ShaderGradient presets, which now live only here.
S01–S10 SHEETS, BAKED — still, so the field bakes into the geometry:
exact normals, real shadows, nothing per frame. Strata (mix(u=height)
with six stops), mesa (`floor`), crackle (an INVERTED spectrum —
the high band louder than the low, which fBm cannot express
because gain would have to exceed 1), canyon (`fold` on only the
top two bands), basin (every amp negative).
S11–S15 SHEETS IN MOTION — no shading block, so the author's material
owns the look: drifting dunes (`flow="1 0 0"` walks the field
sideways instead of boiling it), silk under two soft-boxes,
molten glass with transmission intact, a checker-roughness metal
shiver, and a wall standing up (`along=z`) raked by an area light.
S16–S20 MIX SHEETS — two U stops + accent, on fields ShaderGradient has
never had. Every one has MORE THAN ONE BAND, which the ten
presets cannot: two-band interference, a fine weave, one enormous
slow tide, a folded churn, an ember crust.
S21–S25 BLOBS — the same tables on a closed surface sampled on the
NORMAL: a lava lamp seen from inside, five-band folded coral, a
folded asteroid whose silhouette actually breaks, a cavern, and
a pearl whose whole field is a hundredth of its radius.
S26–S33 THE TABLE ITSELF — two colours, the three-colour wash, four, N,
a LIVE height ramp (a baked one cannot move), six-stop geology
in motion, and the same table on a blob and a reef.
S34–S37 THE AXES. `u` is a VALUE, not "across the sheet": RADIUS as the
main axis instead of the accent's (concentric rings, not a
wash), two SCREEN axes crossed (u=x, v=y) for a corner-to-corner
bilinear, PAIRED `at` values so the table steps instead of
blending — four flat fields out of eight stops — and ONE
repeated `at` inside a smooth table, which is a hard terminator
cutting the frame wherever the field crosses it.
S38–S41 THE FIELD. `along=z` pushing straight at the lens so the relief
rakes against a side light; every amp NEGATIVE, so the accent
floods the troughs the crests would have worn; the same mix on a
TORUS, where `radius` genuinely means inner-vs-outer; and a
still surface that bakes both the relief AND the mix.
S42–S43 THE LIGHT. A near-total sun-dot (`shade=0.92`) that darkens
every face turned from the sun no matter where on the table it
sits, and the opposite: a scene with no <lights> block at all,
lit only by the mix's own `brightness`.
S44–S51 THE TEN PUBLISHED PRESETS — ShaderGradient's own ten, converted
by two numbers per shape (the family header prints them). Five
sheets, then three blobs; halo and pensive are already S4 and
S5. This reel is now their only home.
S26–S43 ARE BACKGROUNDS in the way S01–S25 are mostly landscapes: from S34
on there is no horizon anywhere — the surface fills the frame and the stop
table IS the picture. They also carry two matched glow-sprite haze lobes
(haze-a / haze-b) over dark gradients, so the lobes travel the cuts too.
ONE GRADIENT BECOMES THE NEXT. `transition=match-move` used to carry a
matched surface's POSE across a cut and leave its look behind — the field
lives in a uniform table and the colours in custom uniforms, so neither the
transform lerp nor `material.color` reached them, and two gradients held
their old palette while the compositor dissolved underneath. Now the table
itself travels: bands slide in frequency, grow and shrink in amplitude, and
crease as `fold` rises, while the three colours and the noise seed move with
them. A band one side does not have is paired with a ZERO-AMPLITUDE band at
its own frequency, so it grows out of silence at the right scale instead of
sweeping in from nothing. Only pairs with the same along/sample/shading can
do it (anything else is a different compiled program), and only fields that
move — a baked one keeps its shape in the vertex buffer, not in a uniform.
S16→S20 are five in a row that all qualify; watch the gaps with
`npx tsx scripts/gap-shot.mts <this file> s16-beat s17-weave <out>`, because
a filmstrip samples scene mid-points and never looks inside a transition.
ONE LIMIT, STATED: `floor` is bake-only. A moving field rides in the
material, and there is nothing to bake a height clamp into — so a scene
that moves shapes itself without one, which is what S11–S15 do. `mix`
itself is not limited that way: a STILL field bakes it as vertex colours
(exact normals, real shadows) and a moving one runs it per pixel, off the
same measured axis frame either way.
Preview: /packages/runtime/index.html?project=promos/primitives/backgrounds/band-field.promo- Topic
- backgrounds
- Scenes
- 51
- Kind
- reference rig
//
ONE TAG, BOTH FAMILIES — the unified displaced surface.
<heightfield> and <shadergradient> were the same idea twice. This reel is
that idea once: an ordinary primitive wearing a <bands> table, with the
three things they disagreed about turned into values.
1. UNITS ARE ONE CONVENTION. freq = cycles across the shape's own extent
(size-invariant); amp = PEAK MILLIMETRES that band displaces, an
absolute length; fold = 0..1 toward 1-|n| creases. The old pair
disagreed on both — heightfield's amp was mm while ShaderGradient's was
tenths of a 10-unit sheet scaled by `unit`, and their frequencies were
a factor of 4.3 apart. Neither `unit` nor `waterPlane` survives: size
is mm, and a waterPlane is a plane with both axes subdivided.
2. DIRECTION IS A VALUE. `along=y|z|normal`. A height field pushes along
one fixed axis; a blob pushes along its own normal — which is the only
reason <shadergradient> could take a sphere and <heightfield> could
not. WHERE the field is sampled is a separate question (`sample=`),
because a flat sheet sampled on its normal would be constant.
3. SHADING IS A SLOT. `mix` is the only colour model: stops along `u`,
optional accent along `v`, optional sun-dot, optional ambient of its
own (`brightness`, which is why these scenes need no <lights>).
Terrain is mix(u=height sun=… shade=…). ShaderGradient topology is
two U endpoints plus accent — mix(u=x v=height) on a sheet, mix(u=y
v=radius) on a blob. Every axis normalises by the field the scene
actually has, measured at build, not by a bound it never reaches. No
shading block, and the author's material stands untouched, which is
what an animated sea needs for transmission and real HDR
reflections.
And no new tag was needed. `<bands>` and a shading block are children that
any primitive can carry, so a sheet is <primitive><geometry type="plane">
and a blob is <polyhedron kind="icosahedron">.
THE OLD TAGS ARE STILL IN THE ENGINE. promos/primitives/terrain/terrain.promo
still runs on its own generator. <shadergradient> does too, but nothing
exercises it any more: all ten of its published presets now stand here as
<bands> + mix (S4, S5 and S44–S51), and the two reels that carried them —
backgrounds/shader-gradients.promo and its rows-form twin — are gone.
FIFTY-ONE SCENES, NINE FAMILIES. S01–S25 are the two old tags' own
territory, re-shot on the unified surface; S26–S43 are `mix` on its own
terms — every lever the colour model has, one per scene; S44–S51 are the
ten published ShaderGradient presets, which now live only here.
S01–S10 SHEETS, BAKED — still, so the field bakes into the geometry:
exact normals, real shadows, nothing per frame. Strata (mix(u=height)
with six stops), mesa (`floor`), crackle (an INVERTED spectrum —
the high band louder than the low, which fBm cannot express
because gain would have to exceed 1), canyon (`fold` on only the
top two bands), basin (every amp negative).
S11–S15 SHEETS IN MOTION — no shading block, so the author's material
owns the look: drifting dunes (`flow="1 0 0"` walks the field
sideways instead of boiling it), silk under two soft-boxes,
molten glass with transmission intact, a checker-roughness metal
shiver, and a wall standing up (`along=z`) raked by an area light.
S16–S20 MIX SHEETS — two U stops + accent, on fields ShaderGradient has
never had. Every one has MORE THAN ONE BAND, which the ten
presets cannot: two-band interference, a fine weave, one enormous
slow tide, a folded churn, an ember crust.
S21–S25 BLOBS — the same tables on a closed surface sampled on