If we fix a complex constant c and plot the escape times for every starting point z0 in the complex plane, each choice of c unfolds its own self-similar fractal world known as a Julia set.
Every Julia set has 180° rotational symmetry around the center. Because squaring a number erases its sign, any starting point z0 and its opposite −z0 land on the exact same value after the first step, giving every spiral arm a matching twin across the origin.
While the Mandelbrot set is a single map, every complex number c produces its own Julia set. When c comes from inside the Mandelbrot set, the Julia set holds together as one connected shape; when c moves outside the boundary, the shape breaks apart into a scattered cloud of isolated points known as Fatou dust.
The equation using complex numbers is:
Each pixel supplies the initial complex coordinate z0:
While the complex parameter c stays fixed across the entire image:
If we expand the complex squaring, the iteration reduces to:
A common way of exploring Julia sets is by putting each pixel's starting (x0, y0) coordinates into the recurrence for a fixed c = (cx, cy) and making note of whether the series:
47.23990.2438Drag z0 across the canvas to watch how points on the spiral filaments wind around the repelling fixed point before crossing the dashed |z| = 2 escape horizon.
Across the complex plane, each parameter c shapes its Julia set into spirals, basilicas, Siegel disks, dendrites, and Cantor galaxies. Zooming toward repelling periodic points and their preimages uncovers the same global motif repeating at every scale.
At shallow magnifications, every pixel runs its own independent escape-time loop inside a WebGL fragment shader using native 32-bit GPU floats, seeding z0 directly from the pixel coordinate and iterating with the fixed complex constant c.
Twin logarithmic spiral arms wind into the repelling α fixed point of the dragon Julia set for c = −0.8 + 0.156i, centred near z = −0.5275 + 0.0759i.
Counter-rotating seahorse tails in the Julia set for c = −0.747 + 0.108i, centred on its repelling fixed point at a 5.8 × 10⁻³ vertical span, separating deep nocturnal basins from luminous filigree curls.
For c ≈ −0.122561 + 0.744862i at the centre of the period-3 bulb, three dark interior basins meet at every preimage of the α fixed point to form the three-eared silhouette named by Adrien Douady.
Near the period-2 basilica parameter c = −0.75 + 0.015i, pinched interior basins and mirrored spires stretch along the real axis like Saint Mark’s Basilica reflected across a flooded Venetian lagoon.
On the main cardioid boundary at c ≈ −0.390541 + 0.586788i, the fixed-point multiplier rotates by the golden mean. Instead of spiraling inward, bounded orbits trace invariant topological disks.
In the Seahorse filigree Julia set for c = −0.7269 + 0.1889i, two intertwined arms wind across the origin while smaller curls repeat at every preimage of the critical orbit.
Centred near z = −0.51498922 + 0.06722602i at a 1.2 × 10⁻³ vertical span in the Julia set for c = −0.77568377 + 0.13646737i, paired logarithmic spirals converge on the repelling α fixed point.
For c = −0.087593732 + 0.65509028i near the upper period-3 bulb, three spiral branches meet at the repelling fixed point z ≈ −0.232992 + 0.446860i and repeat along each tributary arm.
Near the upper period-4 bulb at c = 0.28245 + 0.4831i, four-armed spiral filaments wind into the repelling fixed point z ≈ 0.024743 + 0.508251i, adding a fourth turn to the three-armed rabbit junction.
At the Misiurewicz parameter c = i, the critical orbit lands on a repelling cycle after two steps. With no attracting basin, the Julia set has empty interior and forms a pure, infinitely branched tree.
In the Scepter Valley Julia set for c = −1.25066 + 0.02012i, curled filaments around the repelling fixed point z ≈ −0.725042 + 0.008212i sprout ornate branching spikes.
Once the viewport narrows past 10-3, subpixel spacing approaches the 10-7 rounding step of single-precision float32 shaders. These views step up to compensated double-single (dsAdd / dsMul) Dekker-split shaders and 53-bit significand float64 workers to keep filaments razor-sharp down to the 10-15 IEEE 754 precision floor.
At a 9 × 10⁻⁶ vertical span inside the Julia set for c = −1.768620774 + 0.002428273i, curling filaments around the repelling fixed point form paired logarithmic spirals and nested medallions.
Inside the Elephant Valley Julia set for c ≈ 0.277732 + 0.007345i near the main cardioid cusp, long curved branches curl into tightly wound parabolic trunks around z ≈ 0.478136 + 0.167960i.
Fine, feathery branches in the Julia set for c = −0.658448 − 0.466852i form crystalline snowflake clusters around z ≈ −0.482302 − 0.237632i.
At 10⁻¹⁰ vertical span around the repelling fixed point of the Elephant Valley Julia set (c ≈ 0.277732 + 0.007345i), compensated double-single and perturbation passes resolve fine concentric rings around the spiral core.

At 1.2 × 10⁻¹⁴ vertical span inside the Seahorse Valley Julia set (c = −0.77568377 + 0.13646737i), high-precision reference orbits and Bivariate Linear Approximation keep every spiral filament sharp near the IEEE 754 float64 precision floor.

Because a single Julia set fixes c across the entire complex plane, its richest topological transitions happen when c(t) travels along a path in the Mandelbrot parameter plane. Sweeping c(t) around the main cardioid, across period-doubling necks, onto Misiurewicz filaments, or past the connectedness boundary drives the filled Julia set through continuous bifurcations and Cantor dust transitions at interactive frame rates.
Sweeping c(θ) = ½reiθ − ¼r²e2iθ around the main cardioid boundary rotates the fixed-point multiplier λ = reiθ through a full turn, morphing the filled Julia set from the cusped cauliflower through three-eared rabbit buds, pinched basilica lobes, and golden-mean Siegel spirals.
Crossing the parabolic neck at c = −0.75 from the main cardioid (c = −0.52) into the period-2 basilica bulb (c = −1.0) and period-4 cascade (c = −1.31) pinches the single central basin at every preimage of the α fixed point, splitting one chamber into an infinite chain of paired lobes.
Tracing along the upper period-3 wake from Douady’s Rabbit (c ≈ −0.123 + 0.745i) out along the external ray filament to the Misiurewicz tip c = i collapses the interior basins to zero area, leaving a pure, infinitely branched lightning dendrite.
Crossing the Seahorse Valley boundary from a connected basin web (c = −0.745 + 0.105i) through the dragon filament (c = −0.7757 + 0.1365i) into the escaping basin (c = −0.805 + 0.225i) shatters the connected Julia continuum into an uncountable Fatou Cantor dust of isolated points.
By Koenigs' Linearization Theorem, iterating z² + c near a repelling fixed point αc with multiplier λ = 2αc (|λ| > 1) is conformally conjugate to multiplying by λ. Scaling the viewport by |λ|−mt, counter-rotating by −t·arg(λm), and shifting smooth escape counts by −mt loops a single shallow octave seamlessly without needing arbitrary-precision arithmetic.
Near any repelling fixed point αc = (1 − √(1 − 4c))/2 with multiplier λ = 2αc (|λ| > 1), iterating fcˆm expands each spiral arm onto itself by λm. Applying the cubic inverse Koenigs chart ψ(w) = αc + w + a2w² + a3w³ while scaling by |λ|−mt, counter-rotating by −t·arg(λm), and shifting smooth escape counts by −mt loops a single shallow octave seamlessly forever.
Given a starting point (x0, y0) and a fixed parameter (cx, cy), escape-time coloring records how many iterations the orbit takes to cross the escape circle |z| > 2 along with the complex coordinate where it escapes.
const ESCAPE_THRESHOLD = 4;
const MAX_ITERATIONS = 1024;
function iterateUntilEscape(x0, y0, cx, cy) {
let x = x0, y = y0;
let numIterations = 0;
while ((x * x + y * y <= ESCAPE_THRESHOLD) &&
(numIterations < MAX_ITERATIONS)) {
const xNext = x * x - y * y + cx;
const yNext = 2 * x * y + cy;
x = xNext;
y = yNext;
numIterations++;
}
const escaped = x * x + y * y > ESCAPE_THRESHOLD;
return { numIterations, x, y, cx, cy, escaped };
}To keep high iteration counts near the Julia boundary from bunching into noisy stripes, palettePhase compresses the escape count with a square-root curve before sampling a 512-entry periodic cubic spline interpolated in Oklab color space.
const PALETTE_SIZE = 512;
function palettePhase(value, gScale = 7) {
return (Math.sqrt(Math.max(0, value) + 1) - 1) *
gScale / 55;
}
function samplePalette(value, paletteTable) {
const phase = palettePhase(value);
const position =
(phase - Math.floor(phase)) * PALETTE_SIZE;
const index = Math.floor(position);
const fraction = position - index;
const base0 = index * 4;
const base1 = ((index + 1) % PALETTE_SIZE) * 4;
const sampleChannel = c => {
const c0 = paletteTable[base0 + c];
const c1 = paletteTable[base1 + c];
return Math.round(c0 + (c1 - c0) * fraction);
};
return [
sampleChannel(0),
sampleChannel(1),
sampleChannel(2),
255,
];
}
function getIterationColor(result, paletteTable) {
const { numIterations } = result;
return samplePalette(numIterations, paletteTable);
}Sweeping across the viewport grid maps each pixel to its starting coordinate (x0, y0), runs the recurrence for the fixed parameter (cx, cy), and writes the sampled RGBA color for every escaping orbit while leaving bounded interior points dark.
function drawJuliaSet(
canvasEl, xRange, yRange, cx, cy,
getColor, paletteTable
) {
const canvasWidth = canvasEl.width;
const canvasHeight = canvasEl.height;
const context = canvasEl.getContext('2d');
const canvasImageData =
context.createImageData(canvasWidth, canvasHeight);
const image = canvasImageData.data;
for (let i = 0; i < canvasHeight; i++) {
for (let j = 0; j < canvasWidth; j++) {
const x0 = xRange[0] +
j * (xRange[1] - xRange[0]) / canvasWidth;
const y0 = yRange[0] +
i * (yRange[1] - yRange[0]) / canvasHeight;
const result = iterateUntilEscape(x0, y0, cx, cy);
const pixelIndex = 4 * (i * canvasWidth + j);
if (result.escaped) {
const pixels = getColor(result, paletteTable);
for (let p = 0; p < 4; p++) {
image[pixelIndex + p] = pixels[p];
}
}
}
}
context.putImageData(canvasImageData, 0, 0);
}Here's the central spiral of the dragon Julia set (c = −0.8 + 0.156i) colored from integer iteration counts alone, where each discrete escape step forms a visible contour band.
Running three additional iterations after crossing |z| > 2 and subtracting the doubly logarithmic escape potential turns the integer step count into a continuous escape time mu.
const ESCAPE_RADIUS = 2;
const SMOOTHING_STEPS = 3;
function getMu({ numIterations, x, y, cx, cy }) {
for (let i = 0; i < SMOOTHING_STEPS; i++) {
const xNext = x * x - y * y + cx;
const yNext = 2 * x * y + cy;
x = xNext;
y = yNext;
}
const distanceSquared = x * x + y * y;
return numIterations + SMOOTHING_STEPS + 1 -
Math.log(0.5 * Math.log(distanceSquared)) /
Math.log(ESCAPE_RADIUS);
}
function getSmoothColor(result, paletteTable) {
const mu = getMu(result);
return samplePalette(mu, paletteTable);
}Feeding mu into the same repeating plum, amethyst, champagne, and rose-gold Oklab spline removes the stepped contour seams across the spiral arms.
Inverse iteration and orbit-density methods render Julia sets by plotting either the backward preimages of repelling periodic points or the visit frequency of escaping trajectories across the viewport.
-0.8000 + 0.1560iBecause the Julia boundary Jc is backward-invariant, repeatedly taking both complex square roots zn−1 = ±√(zn − c) from a repelling fixed point lands directly on Jc.
All fractals on the page are interactive and rendered when they're in view. Every image can be expanded into full-screen mode using the button in its bottom-right corner. Full-screen views also display live complex-plane coordinates and let you undo camera steps or reset to the starting view.
As you zoom deeper, each canvas automatically switches to more sophisticated rendering pipelines to stay fast and avoid pixelation. Shallow views run per-pixel escape loops in 32-bit WebGL fragment shaders.
Zooming past 10-3 switches to compensated double-single shaders and 64-bit workers. Beyond 10-14, the renderer switches to perturbation theory and arbitrary-precision decimal math so you can keep zooming without losing detail.
Fractal image controls when hovering