THE ITERATION
Everything on this page is generated by one map on the complex plane:
The Mandelbrot set is the set of parameters c for which the orbit of z₀ = 0 stays bounded forever. A Julia set fixes c instead and asks the same question of every starting point z₀. One theorem makes the orbit easy to test: if |zn| ever exceeds 2, the orbit escapes to infinity. Each pixel simply runs the iteration until escape or until the iteration budget runs out — pixels that never escape are painted black.
THE DUALITY
The two sets are two slices of the same four-dimensional object. The Mandelbrot set is an atlas of every Julia set: a classical theorem of Fatou and Julia says the Julia set for c is connected exactly when c lies inside the Mandelbrot set, and shatters into dust the moment c leaves it. That is what the live thumbnail shows — your cursor picks c, and the most intricate Julia sets appear when c rides the boundary.
SMOOTH COLOUR
Colouring by the raw escape iteration count n gives ugly discrete bands. The renormalised, real-valued escape count removes them:
ν is then fed through a cosine palette t ↦ a + b·cos 2π(t + d) — three coefficient sets give VOID, EMBER and ACID — with a pinch of per-pixel dither noise to kill any residual banding, a gamma curve to crush the darks, and an exponential fade so the far exterior melts into black.
THE GPU
Every pixel is an independent computation, which is exactly what a GPU is for. The iteration runs in a WebGL fragment shader: your graphics card executes it for millions of pixels in parallel, every frame. That is why the Julia thumbnail can morph in real time as the mouse moves — each frame is a complete re-computation of the whole fractal. Nothing is precomputed and nothing is fetched from the server: the page you downloaded is the entire program.
GOING DEEP
GPU floats carry a 24-bit mantissa, so adjacent pixels become numerically identical at around ×20 000 zoom and the image dissolves into blocks. Past that point this page switches to double-float arithmetic (Dekker 1971): every coordinate is carried as an unevaluated sum of two float32s,
with error-free transforms (twoSum, and Dekker’s 4097-split product) keeping the low word honest through every multiplication. That extends the usable zoom to roughly ×10⁹–×10¹⁰, about a million times deeper than naive floats — at the cost of ~10× more arithmetic per pixel, which is why the deep path only engages when needed. The iteration budget also grows with depth, up to 2 200 iterations per pixel.
THE CONTROLS
MOVE over the Mandelbrot set to morph the linked Julia · CLICK to lock c · CLICK THE THUMBNAIL to swap which set fills the screen · SCROLL to zoom, DRAG to pan · ESC resets the view.