Colouring by what made a point, and by how far into the figure it is
Every particle carries two extra values, and neither is guessable from the param name, so read this before reaching for them (ADR-0087, ADR-0088).
map— which part of the figure a point belongs to. It is the index of the affine map applied on that particle’s most recent step, which makes it a property of position rather than of history: it names which sub-copy of the figure the point currently sits in. On the fern those four sub-copies are the stem, the body, the left frond and the right frond. So colouring by it genuinely separates the parts of the plant; it is not a per-particle identity that would read as noise.root— how far a point is from the figure’s own skeleton. The distance to the nearest of the drawn maps’ fixed points — the places the figure contracts toward, which on the fern are the stem base and the frond origins — normalised by how far apart those points are. Likemapit is a property of position rather than of history, recomputed every step from where the particle now is, so an old particle sitting near a fixed point reads the same near-zero a freshly restarted one does. That is what makes the gradient permanent rather than a startup animation.
Each reaches the picture by two routes, which is four params:
| Param | Default | What it does |
|---|---|---|
map_tint | 0 | Shifts the particle’s palette coordinate by ±map_tint/2 across the four sub-copies. Rides your own [palette], so a custom ramp, palette_mix and saturation all reach it for free. |
map_hue | 0 | Rotates the hue of the colour the palette returned, by ±map_hue/2 across the same four. Leaves the coordinate alone, so it nudges a part of the figure off your ramp without editing the ramp. 1.0 is a full turn of the wheel. |
root_tint | 0 | The palette-coordinate route, across distance-from-the-skeleton. Anchored, not centred — see below. |
root_hue | 0 | The hue-rotation route, across the same distance. Anchored the same way, and the escape when your palette coordinate is already spent. |
root_*is anchored at zero;map_*is centred. This is the one place two params on the same page behave differently, so do not generalise from the row above. A particle on a fixed point takes no shift at all — the stem base keeps exactly the colour your ramp already gave it — and the figure ramps away from there. Soroot_tintdoes not open a spread around your colour the waymap_tintdoes; it pushes one direction, and it only ever pushes.Its effective range is per figure, and that will surprise you. The channel is normalised by the figure’s own skeleton, and four of the five figures reach less than half of it. The fraction of the palette a
root_tintof1.0actually buys, measured:
figure reaches so for a full sweep, bind about spiral0.412.4fern0.462.2sierpinski0.502.0tree0.701.4dragon1.050.95A value tuned on the fern and reused on the dragon is wrong by about 2.5×.
Because it is anchored,
root_tintspends the ramp’s bright end by construction — it only ever pushes the coordinate up. On a palette that already ends bright (most of them here) it whitens exactly the regions that were already brightest, which is why neither shipped IFS preset binds it. A negative value is legal and is the obvious escape: it ramps down the ramp’s dark end instead. But the coordinate is sampled by a repeating LUT, so once it crosses zero the darkest points wrap to the ramp’s brightest stop and a cream speckle appears where the figure should be darkest. On the since-retired Barnsley fern preset that was aroundroot_tint = -0.38(its coordinate floor washue_center’s sine trough0.20minushue_spread/2, against aroot01ceiling of0.46). Do the same arithmetic for your own preset before going negative.
There are no
age_*params. Colouring by how many steps since a particle last restarted proxies distance-from-the-restart-points badly: the proxy decays after about ten steps and renders as per-particle speckle with no gradient anywhere.root_tint/root_huemeasure that distance directly instead. A preset binding anage_*name gets the usual unknown-param warning.
Which route do you want? They are not peers — *_tint is the default and
*_hue is the special case. *_tint keeps the figure inside the ramp you
authored, so a fern stays botanical and merely separates; *_hue throws a part
clear of the ramp entirely (on the retired Barnsley fern’s greens it sent the
fronds to teal and periwinkle), which is striking and fights a palette you spent five
stops on. Reach for *_hue when your palette is a narrow band and you want one
part out of it — or when the palette coordinate is already full, which is the
next thing on this page.
The palette coordinate is a fixed budget, and this is the one that will cost
you a session. Three params write it — hue_spread per particle at random,
map_tint per part, root_tint per distance — so adding one means taking
authority away from another, not stacking a third term on top. Twice measured on
the Barnsley fern preset, since retired:
- Its
hue_spreadhad to come down from0.16..0.42to0.05..0.125beforemap_tintread at all; above that the parts smeared into each other andmap_tintwas a faint wash at any setting. - Its
map_tintthen had to be cut from0.46to0.22beforeroot_tintimproved the picture. Stacked at full strength the plant washes out and the stock preset looks better.
Each time you are trading one kind of structure for another, which is a real
choice rather than a bug. *_hue is the escape: it does not touch this
coordinate at all, so a figure that is out of budget can still take a depth cue
or a part separation through the hue route.
And on the fern, the escape is what shipped — so do not read the 0.22
above as the tuning in the file. Rendered against each other, root_hue at the
fern’s full map_tint = 0.46 beat the split: the body cools to jade, the
frond origins stay warm, and the part separation the narrowed hue_spread paid
for is not given back. Every shipped IFS preset binds root_hue and none binds
root_tint. The budget rule is real and the 0.22 measurement stands; the
conclusion drawn from it is that when a coordinate is spent you take the other
route rather than pay.
And all four are inert on the four map families: nothing but an IFS writes
either channel, so binding them on de_jong does nothing at all rather than
doing something subtle.
The recycling’s rate is not an instrument, but its ramp is. A beat cannot
restart a burst of particles — that was a deliberate call, and reseed is the
percussive lever on this family. What you can set is emergence: how long a
just-restarted particle takes to fade up to full brightness, in steps
(default 8, which is about 0.13 s at the fixed step). It exists because a
longer fade integrates the four restart points over more frames, so a ramp
that hides the recycling at fade = 0.86 may not at 0.94 — if you push the
trail long and start seeing four bright dots appear, raise this. Values below
one step are clamped silently, because a particle’s age advances in whole steps.
Built from 13c7582 at version 0.158.0. This site tracks main and is not versioned per release.