Skip to content

Distance and slope: shading with a derivative

Escape time tells you when an orbit left; it says nothing about the geometry it left behind. But the renderer can also track how fast the orbit responds to a nudge in cc — its derivative. Differentiate the rule zn+1=zn2+cz_{n+1} = z_n^2 + c with respect to cc and the chain rule hands you a second recurrence to run alongside the first:

zn+1=2znzn+1,z0=0z'_{n+1} = 2\,z_n\,z'_n + 1, \qquad z'_0 = 0

(in the Julia plane, differentiate with respect to z0z_0 instead: the same recurrence without the +1+1, seeded z0=1z'_0 = 1). One extra multiply-add per step — almost free — and two more ways of seeing open up. Same view, three treatments:

Seahorse filaments with plain smooth colouring
Smooth colouring. The baseline: exterior coloured by fractional escape count alone. c ≈ −0.743643887 + 0.1318259042i · span 1.5×10⁻³ · open this view in Mandala →

Smooth colouring is the baseline from the escape-time chapter: palette by fractional escape count, nothing else.

The same view with crisp dark boundary lines from distance estimation
Distance shading. The orbit’s derivative estimates how far each pixel is from the set; darkening by that distance inks the boundary like an etching. c ≈ −0.743643887 + 0.1318259042i · span 1.5×10⁻³ · open this view in Mandala →

Distance estimation combines the orbit's final size with that derivative into an estimate of the distance from the pixel to the set itself:

d    znlnznzn.d \;\approx\; \frac{\lvert z_n \rvert \, \ln \lvert z_n \rvert}{\lvert z'_n \rvert}.

The intuition: lnzn\ln|z_n| measures how far along the escape the orbit is, and dividing by zn|z'_n| converts that to distance in the cc-plane — where the derivative is huge, a tiny step in cc swings the orbit wildly, so the boundary must be close. Classical function theory (the Koebe distortion theorem) makes this honest: the estimate is correct up to a small constant factor — near the set it never lies by more than about 4×, so darkening pixels by dd inks the boundary like an etching. Filaments far too thin for any escape-time palette to resolve become crisp lines. This is the mode that shows you where the set actually is.

Its limitation is inherited from the families chapter: the formula needs a complex derivative. For the non-analytic families (Burning Ship, Tricorn, Celtic, Phoenix), Mandala carries the analytic degree factor as an approximation for a useful boundary-highlight aesthetic; it does not pretend that the conformal-distance guarantee survives the folds.

The same view lit like relief terrain
Slope shading. Treat escape height as terrain and light it from an angle: the same derivative becomes a surface normal. c ≈ −0.743643887 + 0.1318259042i · span 1.5×10⁻³ · open this view in Mandala →

Slope shading reads the same derivative as terrain. Treat the smooth escape count as a height field over the plane; its gradient — assembled from znz_n and znz'_n, no extra iteration needed — gives a surface normal, and lighting that normal from a chosen angle turns the exterior into relief, like a raking-light photograph of a carved surface.

In the implementation the complex direction u=zn/znu=z_n/z'_n is normalised to n^\hat n, then a Lambert-like term controls brightness:

s=clamp ⁣(n^L+h1+h,0,1).s=\operatorname{clamp}\!\left( \frac{\hat n\cdot L+h}{1+h},0,1\right).

LL is the chosen light direction and hh is the ambient-height term: raising hh flattens the relief; lowering it deepens the shadow side.

Details that keep it honest

The interior stays solid black in every mode — Mandala never invents structure where the mathematics says "bounded". Distance shading converts dd from complex units to screen pixels before applying its ramp, so a one-pixel line remains visually one pixel wide as you zoom. Width, falloff and an invert option control whether the boundary becomes dark ink or a bright glowing line. Slope exposes light angle and relief depth.

Both modes run on the GPU, f64f64 CPU and double-double CPU tiers. At the extreme perturbation tier Mandala currently does not perturb the derivative; it passes a zero derivative and both modes degrade safely to ordinary smooth colouring. Newton and Nova also bypass exterior shading because their basin/ hybrid colour paths are not escape-distance fields. Exports preserve whichever supported treatment is actually visible on screen.