Attractor depth: the camera, depth_fade, depth_hue, spin
The 3-D families — thomas and lorenz — are seen through the shared
camera that plexus, waterfall and the space curves use
(ADR-0260).
yaw turns it round the figure, pitch raises it, distance moves it in and
out and fov is its field of view; focus and aperture are its lens. Each
roster entry is first brought to unit radius by its own measured framing, so
distance is in figure radii and means the same on every entry: at 1.5,
the bottom of its range, a test holds every 3-D entry clear of the camera’s
near plane. Lorenz Knot’s bass hit reaches about 1.43, below what that test
covers. A particle nearer the camera than the near plane is dropped. The engine-wide
zoom divides the field of view (the angle, not its tangent), and pan_x /
pan_y slide the picture; on these two families pan_x is measured in frame
heights, so a value written for a flat family drifts 16/9 as far on a 16:9
target. The default pitch is 0.25, so an unbound 3-D preset is seen slightly
from above.
The camera turns the figure in place. It orbits the figure’s centre, so a
yaw sweep or a spin no longer slides the figure round the frame: over a full
turn a Lorenz figure’s projected centroid moves about 0.12 NDC at a camera
matched to the old perspective = 0.25, where that setting swung it 0.20.
perspective is retired, and binding it is a load error that names
distance and fov. An old preset moves onto the camera by an exact mapping,
with E the entry’s depth half-extent in figure radii and p the old value:
distance = E / p, tan(fov / 2) = p / (scale * E * zoom) with the camera’s
zoom left at 1, and pitch = 0. A preset that sat at perspective = 0
takes a long distance and a matching narrow fov — the shipped fragment_sumi
layer uses distance = 20, fov = 0.13 — which is as near to orthographic as
the camera goes.
focus and aperture act on the camera’s real lens. focus places the
focal plane in the figure’s depth, 0 at its nearest point and 1 at its
farthest; aperture is the blur of the far side in pixels, and a sprite off the
focal plane draws wider and dimmer, so its light stays the same. A sprite’s size
is stated at the figure’s centre, so moving focus never resizes one; nearer
sprites draw larger and farther ones smaller, as nearer material should.
fog darkens a sprite with its depth, on the scale focus uses: at 1 the
figure’s farthest point is black and its nearest keeps all its light, and 0
is off. It takes light and never size, at the particle’s own depth, so the trace
behind a particle keeps the light it had where it was. Its scale is the figure
brought to unit radius, so it reads the same on every roster entry. depth_fade is the older cue on the same idea, measured on the entry’s
depth half-extent; the two multiply. solid is not an attractor parameter: a
sprite has no line to paint over another.
The camera, depth_fade and depth_hue are exact no-ops on every flat
family, the same way a b c d already carry family-specific meanings. On
de_jong, clifford and the five IFS figures they are exactly the identity:
those maps have no third coordinate, so they keep their in-plane path and every
depth cue collapses to a no-op. Binding them there is not an error and produces
no warning — it produces nothing at all. (Verified by capture: at any setting,
zero pixels differ — asserted in core/tests/attractor.rs.)
depth_fadeis a no-op on a flat family too, and the arithmetic is why it once was not (design-backlog 0067). The haze is1 − depth_fade · (1 − depth01(dn)), and a flat family’sdn ≡ 0would put the multiplier at1 − depth_fade/2, sodepth_fade = 0.9would dim a flat figure 45 % everywhere with no depth gradient (measured onattractor_dissolve: 20.1 % of pixels moved, max channel delta 97, whiledepth_huemoved zero). The fade term is now multiplied by the family’s has-depth flag, so all three cues are the identity together. If an old draft leaned on the dimming as an undocumented brightness trim on a flat family, it silently brightened back —exposureis the parameter that means “dimmer” and says so.
spin is the exception and reaches every family. The flat ones rotate
in-plane through the same angle, so an audio-driven spin is a real look on
De Jong today, and a fern that rocks a couple of degrees either side of upright
reads as wind. That asymmetry is deliberate; do not read it as an oversight.
| Param | What it does | Range that means something |
|---|---|---|
distance | How far the camera sits from the figure’s centre, in figure radii. Nearer exaggerates the perspective: near material grows and far material shrinks, position and sprite size together. | 1.5 .. 8; the shipped 3-D presets run from 1.5 (Plexus Cyanotype at its nearest; Lorenz Knot reaches 1.52 on a bass hit) to 5. The range documents and does not clamp |
fov | The vertical field of view, in radians. A narrow fov at a long distance flattens the figure toward orthographic. | 0.2 .. 2 |
depth_fade | Attenuates brightness with distance — the substitute for occlusion, which this scene does not do. 1 takes the far end to black. | 0 (off) .. 1 |
depth_hue | Shifts the palette coordinate by ±depth_hue/2 across the depth range, so distance moves colour as well as contrast — on a ramp that travels in hue at roughly constant lightness. On a dark-to-light ramp (which is what the 3-D presets have shipped) it duplicates depth_fade instead, and under ink_amount = 1 it is structurally dead, like saturation. design-backlog 0062 | 0 (off) .. 2 * min(hue_center, 1 - hue_center), past which the offset wraps on the LUT’s repeat sampler and far material lands on the near colour |
spin | Rate multiplier on the display rotation. 1 is unchanged, 0 holds the figure still, negative reverses it. | any |
Four things you cannot discover by binding them:
- The near-to-far magnification is set by
distancealone. A figure of radius 1 seen fromdistanceDmagnifies its near side over its far side by(D + 1) / (D - 1):3gives 2:1,2gives 3:1, and1.5gives 5:1.fovandzoomchange how large the whole figure is, not that ratio, so to keep a figure’s size while deepening it, shortendistanceand widenfovtogether. spinturns the figure,yawplaces the camera, and they add. The spin phase is subtracted fromyaw, so a positivespinturns the figure the same way it always has, and a fixedyawoffsets where the turn starts.spinis a multiplier on 0.18 rad/s (spin = 1is one revolution per 34.9 seconds), and its usable ceiling is set byfade, not by taste —spinandfadeare one look. A frame of trail drawn while the figure turns is a frame of rotational smear: push the pair too far and the accumulation stops being a trace of the trajectory and becomes concentric arcs, which destroys exactly the volume the camera is there to show. Measured: atfade = 0.932(~15 frames of trail) the rendered ladder1 / 2 / 3 / 5 / 8reads crisp, crisp, softening, smeared, scribble — usable peak about 1.9; atfade = 0.955(~22 frames, what the retired Thomas ran) the ceiling is correspondingly lower, about 1.3. The arithmetic agrees: holding the smear under ~5° needsrate < 0.087 / (frames / 60)rad/s, so the ceiling falls asfaderises. (This bullet used to say2–4is where the rotation becomes legible — true for a trail-free scene, wrong for every attractor preset that ships; design-backlog 0063.) The phase is integrated, so aspinbound to audio accelerates the figure rather than snapping it to a new angle — but the integration fixes the discontinuity, not the range: a wide binding like1 + bass * 5swings the figure through most of a revolution between transients and reads as tumbling, not drive. The 3-D presets have modulated narrowly (the since-retired Lorenz1.0–1.8, Thomas1.0–1.3).- The illusion has a density limit and haze does not remove it. Nothing
occludes anything here — two strands crossing simply sum — so as
[particles] densityrises the figure reads more and more as X-ray whatever these are set to. If depth stops reading, lowerdensitybefore shorteningdistance, and try apitchthat separates the strands.
Built from f4f807a at version 0.178.0. This site tracks main and is not versioned per release.