off
ikonic>
OUT 0 B

Glass

GLSL 3D Fractals - Mandelbulb

The Mandelbulb is the 3D extension of the classic Mandelbrot set, discovered by Daniel White and Paul Nylander in 2009. It creates stunning organic, bulbous structures with infinite detail, rendered in real-time using ray marching and distance estimation.

Interactive Demo

Drag to turn the camera and explore the Mandelbulb. Scroll, or pinch on a phone, to zoom in; the closer you get, the more detail the shader computes. The power parameter animates on its own and changes the fractal structure as it moves:

Mathematical Foundation

The Mandelbulb extends the 2D Mandelbrot iteration to 3D using spherical coordinates.

2D Mandelbrot Set

The classic 2D Mandelbrot set uses complex numbers:

$$z_{n+1} = z_n^2 + c$$

Where $z$ and $c$ are complex numbers.

3D Extension: Spherical Coordinates

For 3D, we use spherical coordinates to define a power operation:

vec3 powN(vec3 z, float n) {
    float r = length(z);
    float theta = acos(z.z / r);  // Polar angle
    float phi = atan(z.y, z.x);    // Azimuthal angle
    
    float rn = pow(r, n);
    float ntheta = theta * n;
    float nphi = phi * n;
    
    return rn * vec3(
        sin(ntheta) * cos(nphi),
        sin(ntheta) * sin(nphi),
        cos(ntheta)
    );
}

Mandelbulb Iteration

$$z_{n+1} = \text{powN}(z_n, \text{power}) + c$$

Where $c$ is the initial position in 3D space, and $\text{power}$ is typically 8.

Distance Estimation

For efficient ray marching, we use distance estimation:

const int iterations = 8;

float mandelbulbDE(vec3 pos, float power) {
    vec3 z = pos;
    float dr = 1.0;  // Derivative
    float r = 0.0;
    
    for (int i = 0; i < iterations; i++) {
        r = length(z);
        if (r > 4.0) break;
        
        // Update derivative
        dr = pow(r, power - 1.0) * power * dr + 1.0;
        
        // Iterate
        z = powN(z, power) + pos;
    }
    
    // Distance estimate
    return 0.5 * log(r) * r / dr;
}

The distance estimate formula:

$$d \approx \frac{|z| \cdot \log(|z|)}{|z'|}$$

Where $z'$ is the derivative of the iteration.

Ray Marching

We use the distance estimate to efficiently march rays:

float t = 0.0;
for (int i = 0; i < maxSteps; i++) {
    vec3 p = ro + rd * t;
    float d = mandelbulbDE(p, power);
    
    if (d < epsilon) {
        // Hit surface - calculate lighting
        return shade(p);
    }
    
    t += d * 0.8; // Safety factor
}

Visual Characteristics

  • Power = 2: Creates a sphere (degenerate case)
  • Power = 8: Classic Mandelbulb with organic, bulbous forms
  • Power > 8: More angular, geometric structures
  • Power < 8: Softer, more rounded forms

Optimization Techniques

  1. Bounding sphere: Skip empty space quickly
  2. Early termination: Stop when $|z| > 4.0$
  3. Adaptive iterations: Fewer iterations for distant objects
  4. Safety factor: Use $d \cdot 0.8$ to avoid overshooting

Applications

  • Digital art: Stunning visualizations for galleries
  • Game environments: Procedural alien landscapes
  • Scientific visualization: Exploring mathematical structures
  • Educational: Teaching complex iteration and ray marching

References

Related Articles