Section 12 of 14

Deep zoom rendering

Every picture in this project's main galleries is computed in double-precision floating point, the 64-bit number format a processor does arithmetic in natively. This is fast and efficient, but it breaks down when you zoom deeply enough into the Mandelbrot set. Past a certain point, neighboring samples round to the same number and whole groups of pixels compute the same orbit. The result is blocky discretization artifacts that have nothing to do with the fractal, and they get worse the deeper you go.

The frame computed in double precision: horizontal bars and flat blocks of color where neighboring pixels round to the same coordinate, with the shapes of the true picture only roughly visible through them.

Double precision

The same frame computed by perturbation: fine spirals and filigree in navy, blue, and white, sharp down to the pixel.

Perturbation

The same deep frame computed in double precision (left), where the picture breaks into flat blocks because neighboring pixels round to the same coordinate, and computed by perturbation (right).

It's possible, but expensive, to switch to higher-precision arithmetic: 128-bit floats, or arbitrary-precision libraries such as rug in Rust or mpmath in Python. Fortunately, the deep-zoom community has developed clever mathematics that looks much deeper into the Mandelbrot set far more efficiently. I go over it briefly at the end of this page. Deeper frames also need a slower, more deliberate way of browsing, which the Deep tab of the Mandelnaut Explorer provides.

Here is a video of a deep descent, down to a frame about 3.5 × 10−15 wide. It was made with builder/zoom.py, which computes a high-precision field once at each halving of the width and colors it separately.

Midway

Midway

Final frame

Final frame

A zoom from the whole Mandelbrot set into the seahorse valley. It then descends into a minibrot and repeats the same sequence inside the minibrot's own seahorse valley.

More videos are on the Deep zoom videos page.

Deep frames have wildly varying escape times, and getting a rendering that conveys their full range of detail often takes more exploration and parameter tweaking. The percentile stretch from rendering fundamentals spreads the palette linearly between each frame's own 0.5th and 99.5th percentiles. At extreme depths escape counts run into the tens of thousands, and the stretch leaves most of the picture inside a few percent of the palette. For deep frames an absolute scale generally works best: the smooth count passes through a logarithm or a power curve, and the palette then repeats at a fixed period. The figure below shows the video's final frame under several such colorings.

The video's final frame on the leveled scale: the spiral in dark red and orange over broad fields that run from deep blue to pale yellow.

Leveled

The same frame at a longer period: fewer, wider bands, so the spiral reads as orange and yellow arms over blue.

Higher period

The same frame and pass in a palette of blues: the spiral in pale lavender and white over deep blue.

Palette switch

The same frame in a palette of greens: the spiral in pale green and white over dark green, flecked with fine points of light.

Another palette

The video's final frame under four more colorings of the same field.

What depth adds to a picture

With some deliberate choices guiding the descent, deeper parts of the Mandelbrot set and related fractals produce much richer detail and patterns in regions that look plain and smooth at shallower depths. In the shallow parts of the Mandelbrot set, the smooth rendering approach often leaves large areas with only a smooth gradient. For most of the gallery I used alternative rendering modes (especially tia and stripe) to add detail to these regions, but it's also possible to find extremely deep areas of these fractals that contain beautiful fractal richness where the shallower levels would be smooth. The figure below compares a shallow frame with a deep frame inside it.

A frame at the same center 10⁻¹² wide: two spirals joined in an S by chains of cream and orange filigree over broad smooth fields of dark red and black, the center on a small four-armed knot where the chains meet.

Shallowwidth 10⁻¹²

The deep frame at the center of the shallow one: rings of small curled spirals around a dark eye, in rust, cream, and black, with a field of finer filigree at lower left.

Deepwidth 2.3 × 10⁻¹⁷

A shallow frame (left) and a deep frame inside it (right): a region that is smooth at the shallow depth fills with detail further down.

Minibrot descents

Small copies of the set, minibrots, lie all along the boundary: every filament passes infinitely many of them, at every depth, smaller and more numerous the further down you go. From outside, a copy looks like a small black body with the familiar bulbs and hairs. If you zoom into the copy's neighborhood, you see more than that. The copy's own seahorse valleys and spirals are laid over the structure you were already in, so a region that looked smooth from further out fills with filigree. Close to a copy, that filigree often arranges into what look like whole Julia sets, the embedded Julia sets that deep-zoom artists steer toward. The figure below follows one descent of this kind, six steps down a chain of components nested one inside the next. Each step frames the next component in the chain, and the last frame is about a billionth of the complex plane wide.

The whole Mandelbrot set, black on banded color.

Whole setwidth 3

The seahorse valley between the main cardioid and the large disk, centered on a copy too small to see.

Seahorse valleywidth 0.05

A small copy of period 27, a black speck ringed with filigree.

Period 27width 1.9 × 10⁻⁵

The copy's own large disk, of period 54, with the filigree around it.

Period 54width 2 × 10⁻⁶

The edge of the period-54 disk, lined with its tiny satellite bulbs, the one of period 972 at the center, under a band of filigree.

Period 972width 5 × 10⁻⁸

The last frame, about a billionth wide: a tiny copy among dense spirals in purple and blue.

Last stepwidth 1.3 × 10⁻⁹

Six steps down one descent, each frame centered on the next component in a chain nested one inside the next. Filigree from each copy appears in regions that were smooth one step earlier.

Descents like the one in the video can be composed by hand or automated. The neighborhood of a minibrot is a small, turned copy of the whole set, so every place in the set has a twin inside every minibrot, smaller and slightly distorted. That means any frame can be carried into any minibrot: find the minibrot, then find the frame's twin inside it. Simply scaling and turning the frame by the minibrot's size and angle misses the twin badly at any real depth, often by thousands of frame widths, so I solve for the twin directly instead. The Dive block at the top of the fractal explorer's Deep tab does all of this in one press. You choose where to search for minibrots (the current view, a view you paste in, or a random wallpaper) and what to do with the ones it finds: land on one, stop at its symmetry point, carry a second view inside it, or collect the largest of them. Pressing it again from where it lands keeps descending, and since the periods multiply at every step, the nesting can keep going until the iteration cap runs out. Keep diving repeats the dive with fresh random draws until you stop it, and every result collects in a Dive results list that you can browse and save from.

The Dive block on the explorer's dark panel: “Search for minibrots near” a small picture of the Mandelbrot set marked random, with Random lit under Here and Paste; “then dive into” in a dropdown; a second picture of the set marked random, with Random lit under None, Here, and Paste; a Go button; and under them two boxes, New coloring on arrival and Keep diving, both ticked.
The Dive block in the Deep tab.

Nesting one minibrot inside another lets you choose what kind of detail you get. Take two frames, A and B, each centered on a minibrot. Framing A inside A's copy, B inside A's, A inside B's, or B inside B's gives four different pictures from the same two places.

Spiral arms of filigree in blue, orange, and pale green winding round a center whose copy is too small to see.

Aperiod 28, width 4.2 × 10⁻⁶

A small black copy of the set at the center of a cross of filigree, between broad smooth fields of blue.

Bperiod 18, width 1.4 × 10⁻⁴

A's spirals again, inside A's own copy and turned by 134 degrees, their smooth fields now grained with finer filigree.

A then Aperiod 784, width 1.4 × 10⁻¹³, turned 134°

B's cross and its copy again, inside A's copy and turned by 134 degrees, the blue fields grained with finer filigree.

A then Bperiod 504, width 4.7 × 10⁻¹², turned 134°

A's spirals again, inside B's copy and turned by 52 degrees, with finer filigree grained through the smooth fields.

B then Aperiod 504, width 2.5 × 10⁻¹¹, turned 52°

B's cross and copy again, inside B's own copy and turned by 52 degrees, its fields grained with finer filigree.

B then Bperiod 324, width 8.4 × 10⁻¹⁰, turned 52°

Two frames, A and B (top), and the four ways to nest one inside the other (bottom).

How a deep frame is computed

The Deep tab in the fractal explorer computes one orbit at high precision, the reference orbit, for the center of the frame, using fixed-point arithmetic with as many bits as the frame's width requires. Every pixel then iterates only its small offset from that orbit. Write a pixel's orbit as zn = Zn + δn, where Zn is the reference orbit, and let Δc be how far the pixel's c is from the center's c. For z ↦ z2 + c the offset then obeys

and the higher degrees follow from the binomial expansion in the same way. The offsets are tiny, but a double keeps its relative precision at any magnitude, so δ fits comfortably in an ordinary double even where the coordinates themselves do not. This is perturbation, and it is how every modern deep-zoom renderer works.

The reference orbit is only a good anchor while a pixel's orbit stays near it. When the full value Zn + δn passes closer to zero than δn itself, the offset has become the larger quantity and precision starts to drain away. To fix this I use rebasing, which comes from Zhuoran on fractalforums.org. At that step the pixel takes its whole current value as a new offset and restarts from the beginning of the same reference orbit. With rebasing, one reference orbit serves the entire frame. A pixel that never escapes can stop early as interior only when that can be proved: a small disk around its orbit has to map back inside itself. Otherwise it runs to the iteration cap. The fractal explorer draws the multibrot families up to degree six, on both the parameter and dynamical planes, using the smooth rendering mode. Its iteration cap follows the same depth rule as the rest of the engine, up to a ceiling of a million, or two million when you set the count yourself, and a probe raises it when too many samples reach it. Frames can go down to about 10−112 wide. Close to a minibrot the iteration ceiling usually runs out much sooner, around 10−30, because every nested copy multiplies the period. Renderers that also extend the exponent range of their offsets go far deeper.

Rendering speed

By default the fractal explorer renders deep frames on the CPU, in WebAssembly, across the browser's worker threads. The inner loop is vectorized by hand, so each thread advances two pixels at once, with a plain version for browsers without WebAssembly SIMD. The same kernel lives in fractal-wallpapers, where it also draws Deep tab links from the command line. On one six-core desktop, the video's final frame takes about 6 seconds at 1280 by 720 with one sample per pixel, averaging about fifteen thousand iterations a sample. On the same machine, Fraktaler 3, a mature open-source deep-zoom renderer, takes about 50 seconds on the CPU with its acceleration on and about 100 without it. Compared like for like (CPU, doubles, plain perturbation), the fractal explorer does about eighteen times as many iterations per second. I think the reason is specialization rather than a better algorithm: Fraktaler 3 interprets general formulas and tracks derivatives at every step, while my kernel runs one fixed update, two pixels at a time. The two agree on more than 99.7% of pixels.

GPUs are clearly faster at this kind of independent per-pixel work. On the same machine Fraktaler 3's GPU path draws the frame in under 3 seconds, in single precision. The browser's GPU interface, WebGPU, has no double precision at all, so the explorer's GPU path stores every number as a pair of single-precision floats, which recovers most of a double's precision at four to nine times the cost of single precision. Plain single precision turned out to be limited by the length of the orbit rather than the depth: over tens of thousands of iterations the rounding error grows until the picture drifts, so it is only good enough for previews. The GPU works in short bursts, so the rest of the screen never waits long on it and the operating system never takes it for hung, and the CPU finishes the few pixels that run longest. The GPU path is the GPU (experimental) box in the Deep tab, and it is off by default. On my desktop it is faster than the CPU kernel on most deep frames, but on a laptop's integrated GPU it was slower everywhere except very deep, heavy frames.

Deep-zoom renderers usually add bilinear approximation, which skips many iterations at once by applying a precomputed linear map. I left it out of the CPU kernel, because on the frames worth looking at it wasn't much faster, and it changed the picture. On frames with visible structure it ranged from about 20% slower than plain perturbation to about 2.6 times faster. At every tolerance tried it also moved escape counts, and on some frames it moved the boundary of the interior, so the pictures stopped matching what the engine draws. It paid off handsomely only on frames that were almost entirely interior. Fraktaler 3 shows the same pattern on the video's final frame: its approximation buys a factor of about 1.3 to 2 and moves a fifth of the pixels by more than one iteration. On the GPU path it does pay off on very deep frames, and there it moves the picture no further than single-precision arithmetic already does. It is used there only on frames narrower than about 10−30, and only while it skips at least 2% of the steps.

The multibrots

The deep rendering techniques on this page work on the multibrots and their Julia sets too, though each iteration costs more as the degree rises. Their deep areas are full of rich detail, and learning to navigate them well is a key part of making fractal artwork.

A tiny copy of the Mandelbrot set at the center of a pinwheel of spiral arms in magenta, violet, and pale blue.

Mandelbrot setwidth 2.4 × 10⁻¹⁵

The Julia set for that point, zoomed in close to it: a four-armed pinwheel of spirals in violet and magenta around a small black island.

Julia setwidth 10⁻¹³

A small black copy of the degree-3 multibrot in a ring of gold filigree, with branching arms on amber.

Degree 3width 2.4 × 10⁻¹⁵

The degree-3 Julia set for that point, zoomed in close to it: two large spirals of gold filigree on amber and brown.

Degree 3 Julia setwidth 4.6 × 10⁻¹⁴

A small black copy of the degree-4 multibrot at the center of spiral arms of filigree in green and white.

Degree 4width 3.8 × 10⁻¹⁴

The degree-4 Julia set for that point, zoomed in close to it: pinwheels of green and white filigree around a tiny black island.

Degree 4 Julia setwidth 1.3 × 10⁻¹²

A small black copy of the degree-5 multibrot in a pentagonal frame of filigree, with spirals around it in blue and white.

Degree 5width 5.7 × 10⁻¹⁸

The degree-5 Julia set for that point: rings of pale blue filigree around dark blue pools, with spirals at the sides.

Degree 5 Julia setwidth 7.3 × 10⁻³

Spiraling arms of red and white filigree dotted with tiny black copies, around a pale center.

Degree 6width 3.6 × 10⁻¹⁴

The degree-6 Julia set for that point, at the same center and width: a six-armed star of red and white filigree.

Degree 6 Julia setwidth 3.6 × 10⁻¹⁴

Deep locations on the Mandelbrot set and the degree-3 to degree-6 multibrots (top to bottom). Each row shows a location on the parameter plane (left) and a view of the Julia set for that location's c (right). The neighborhoods look alike, much as they do at the Misiurewicz points, but these are not Misiurewicz points, and the two sides do not match exactly.

Random dives

I designed the walks, their parameters, and the judges entirely for the double-precision range, where rendering is fast enough to search at scale. But understanding the shallow regions well turns out to also be valuable for generating deep fractal artwork because it helps you descend into the beautiful parts of each multibrot. A random dive starts from one of those places and carries it down a chain of minibrots, so running dives continuously is a straightforward way to approximate the whole process at depth. The results are impressive even with no filtering beyond dropping blank frames, and no judge looking at the deep frames. The figure below shows some I picked by eye; the Deep tab's Random dives list holds a thousand more, unpicked, alongside a hand-picked gallery.

A small black copy of the set in a ring of filigree, among spiral arms in orange, cream, and deep purple.

Mandelbrot setwidth 6.7 × 10⁻⁸

Chains of small spirals in pink and white filigree over rose and dark blue.

Mandelbrot setwidth 1.4 × 10⁻¹⁰

A small black copy of the set in a cross of gold and copper filigree, with spirals at its tips, on deep blue.

Mandelbrot setwidth 8.4 × 10⁻¹⁴

A small black copy of the set ringed by petals of white and gray, inside a frame of copper spirals on dark blue.

Degree 4width 5.3 × 10⁻¹⁷

A wide spiral of teal and gold filigree, its arms made of rows of smaller spirals.

Mandelbrot setwidth 2.4 × 10⁻¹¹

A small black copy of the set among swirls of pale blue and white filigree on dark blue.

Degree 4width 5.7 × 10⁻¹⁵

A winding chain of spirals in pink and pale blue across a near-black ground.

Degree 3width 4.8 × 10⁻¹⁵

One broad spiral of pale green filigree over mottled green.

Mandelbrot setwidth 1.5 × 10⁻¹¹

A small black copy of the set at the center of four-fold spiral arms in red, white, and periwinkle.

Mandelbrot setwidth 5 × 10⁻¹³

Clusters of bright green bulbs and small spirals across dark green.

Degree 3width 5.8 × 10⁻¹³

A tiny copy of the set at the center of a star of cream and orange filigree, with spirals at the corners.

Mandelbrot setwidth 3.3 × 10⁻¹⁵

The edge of a dark blue region lined with seahorse spirals, fading to pale violet on the right.

Degree 4width 1.6 × 10⁻¹³

Chains of pale blue seahorse spirals winding around dark navy pools on white.

Mandelbrot setwidth 4 × 10⁻¹³

A lattice of tiny spirals in pink, blue, and plum, circling one center at the upper left.

Mandelbrot setwidth 1.6 × 10⁻¹²

A small black copy of the set among spirals of mauve filigree on pale pink.

Degree 4width 1.7 × 10⁻¹³

Deep frames from random dives, picked by eye.

I had hoped the location, wallpaper, and gallery judges, trained only on shallow pictures, would carry over to depth and could rank these dives. So I scored 817 dive candidates with each of them and compared their rankings with the 15 best frames I picked by eye, shown in the figure above. The location judge, which sees only the shape of a place, makes a reasonable coarse ranking: twelve of my fifteen land in its top fifth. The wallpaper and gallery judges do barely better than ranking frames by how little of them is interior, and recoloring the same frames reshuffles their rankings almost entirely.

The top 15 of the 817 according to each judge

Location judge

In the neutral palette, a small dark copy ringed in white, among chains of pale blue spirals on purple.

Rank 1 ★

In the neutral palette, a black copy of the set among spirals of pale blue filigree on dark purple.

Rank 2

In the neutral palette, a tiny black copy on a thin thread of blue filigree, with spirals at the edges, on purple.

Rank 3

In the neutral palette, chains of pale blue spirals with bright centers, on purple.

Rank 4

In the neutral palette, arms of pale blue filigree spiraling out from a bright center at the left, on dark purple.

Rank 5

In the neutral palette, one large spiral with a red center among chains of blue filigree, on purple.

Rank 6

In the neutral palette, a small black copy in a triangle of pale blue filigree, among spirals on purple.

Rank 7

In the neutral palette, a tiny black copy at the center of five large white spirals, on dark purple.

Rank 8

In the neutral palette, one wide spiral of pale blue filigree with a red center, on purple.

Rank 9

In the neutral palette, a spiral of pale blue filigree with a dark red center, its arms reaching across purple.

Rank 10

In the neutral palette, spirals of pale blue filigree, two with red centers, on dark purple.

Rank 11

In the neutral palette, one large spiral of white and pale blue filigree with a red center, on purple.

Rank 12

In the neutral palette, a small dark copy in a ring of red, at the center of pale blue pinwheel spirals on purple.

Rank 13

In the neutral palette, one spiral of pale blue filigree with a red center, on dark purple.

Rank 14

In the neutral palette, a black copy of the set among four arms of pale blue filigree, on purple.

Rank 15

Wallpaper judge

A small black copy of the set in a ring of filigree, among spiral arms in orange, cream, and deep purple.

Rank 1 ★

Rows of spirals in coral, cream, and brown filigree over orange-red.

Rank 2

A small black copy of the set in a ring of pale gold filigree, among mauve spirals on dark plum.

Rank 3

A small black copy of the set in a web of pale blue filigree over dark navy clouds.

Rank 4

Chains of small blue spirals across dark slate, with one large spiral at the right.

Rank 5

A four-armed pinwheel of peach filigree around a small dark copy, on brown.

Rank 6

A small copy of the set framed in rings of purple and white filigree, on violet and pale blue.

Rank 7

Two large spirals of cream and amber filigree on dark brown.

Rank 8

A small black copy of the set in a cross of rose and navy filigree, with spirals at its tips, on pale peach.

Rank 9 ★

A small black copy of the set in a lattice of magenta filigree over pale pink.

Rank 10

The edge of a broad black region lined with seahorse spirals, among teal and cream filigree.

Rank 11

A small black copy of the set among curls of sky-blue filigree.

Rank 12

A small black copy of the set among spirals of blue filigree on pale ice blue.

Rank 13

A small black copy of the set at the center of spiral arms in lavender, blue, and pink.

Rank 14

One large spiral of pink filigree beside smaller ones, over rose and deep maroon.

Rank 15

Gallery judge

A tiny copy of the set in square rings of lilac filigree, on periwinkle and near-black.

Rank 1

A four-armed pinwheel of peach filigree around a small dark copy, on brown.

Rank 2

A tiny copy of the set at the center of a star of cream and orange filigree, with spirals at the corners.

Rank 3 ★

A small black copy of the set in a web of cream filigree over orange and red.

Rank 4

A small black copy of the set in a ring of filigree, among spiral arms in orange, cream, and deep purple.

Rank 5 ★

Curls of mint filigree over dark teal.

Rank 6

A tiny copy of the set at the center of pinwheel spirals in lavender, violet, and magenta.

Rank 7

A tiny copy of the set in pentagonal rings of mint and dark teal filigree.

Rank 8

Two large spirals of cream and amber filigree on dark brown.

Rank 9

A small black copy of the set among spiral arms of gold filigree on yellow.

Rank 10

A small black copy of the set at the center of a four-armed pinwheel in rust, cream, and pale pink.

Rank 11

A small black copy of the set ringed in aqua filigree, among spirals on dark teal.

Rank 12

A small black copy of the set in a chain of cream and teal filigree, between dark teal pools and patches of ochre.

Rank 13

A small black copy of the set in a cross of rose and navy filigree, with spirals at its tips, on pale peach.

Rank 14 ★

A small black copy of the set among spirals of blue filigree on pale ice blue.

Rank 15

Each judge's top 15 of 817 dive candidates. A star marks one of my 15 picks shown above.

As an extra experiment, here are about 500 of these dives, picked by the location judge, each with the Julia set at its center: 500 dives and their Julia sets.

Every figure on this page links to its frame in the explorer, the deep ones in the Deep tab, and the tab's links carry the frame and its coloring.