Skip to content
Русский

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. Like map it 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:

ParamDefaultWhat it does
map_tint0Shifts 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_hue0Rotates 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_tint0The palette-coordinate route, across distance-from-the-skeleton. Anchored, not centred — see below.
root_hue0The 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. So root_tint does not open a spread around your colour the way map_tint does; 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_tint of 1.0 actually buys, measured:

figurereachesso for a full sweep, bind about
spiral0.412.4
fern0.462.2
sierpinski0.502.0
tree0.701.4
dragon1.050.95

A value tuned on the fern and reused on the dragon is wrong by about 2.5×.

Because it is anchored, root_tint spends 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 around root_tint = -0.38 (its coordinate floor was hue_center’s sine trough 0.20 minus hue_spread/2, against a root01 ceiling of 0.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_hue measure that distance directly instead. A preset binding an age_* 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_spread had to come down from 0.16..0.42 to 0.05..0.125 before map_tint read at all; above that the parts smeared into each other and map_tint was a faint wash at any setting.
  • Its map_tint then had to be cut from 0.46 to 0.22 before root_tint improved 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.