Mandelbrot Deep Zoom Tutorial

Visual Quality

The Aliasing Problem

When rendering the Mandelbrot set, each pixel gets exactly one sample. The GPU computes the iteration count at the pixel's center and assigns a color. But at the boundary of the set, the iteration count can change dramatically between adjacent pixels — creating harsh, jagged "staircase" edges.

Key Insight

The Mandelbrot boundary has infinite detail at every scale. No matter how high your resolution, one sample per pixel will always miss sub-pixel detail along the boundary. The fix: take multiple samples per pixel, but only where it matters.

This is the same problem as aliasing in any computer graphics — when a signal (the fractal boundary) has higher frequency than our sampling rate (pixel grid). The standard solution is supersampling: evaluate multiple points within each pixel and average the results. But doing this for every pixel is expensive. Adaptive supersampling detects which pixels are on the boundary and only supersamples those.

edge_strength = |dFdx(iteration)| + |dFdy(iteration)| if edge_strength > threshold: color = average of 4x4 sub-pixel samples else: color = single center sample
Iterations: 200
Samples/px: 1
Before — 1 sample per pixel
Iterations: 200
Samples/px: adaptive
After — Adaptive supersampling
Parameters
GLSL
JS
Enable adaptive AA
Show edge detection
Show sample count heatmap
Lower = more pixels get supersampled (slower but smoother)
Higher = sharper edges but slower rendering