Skip to main content

Mandelbrot Set with WebGL

Plotting the Mandelbrot set with a GLSL fragment shader.

I’ve translated the code I wrote for plotting the Mandelbrot set with p5.js to a GLSL 1.0 fragment shader. The main difference is that I’m using vec2 to represent complex numbers, which makes things a bit more concise.

Grayscale

Mandelbrot set with an escape radius of 4.0, and a maximum of 40 iterations.

In this version we’re mapping the number of iterations for each pixel (in the range [0, maxIterations]) to a brightness value (in the range [0,1]).

Histogram

Mandelbrot set with an escape radius of 4.0, a maximum of 40 iterations, and a procedurally generated palette.

In this version we’re mapping the number of iterations for each pixel (in the range [0, maxIterations]) to a color, using these two functions:

vec3 palette(float t, vec3 a, vec3 b, vec3 c, vec3 d) {
  return a + b * cos(6.28318 * (c * t + d));
}

vec3 color(float t) {
  vec3 a = vec3(0.5);
  vec3 b = vec3(0.5);
  vec3 c = vec3(1.0);
  vec3 d = vec3(0.0, 0.1, 0.2);
  return palette(fract(t + 0.5), a, b, c, d);
}

How the heck does that code generate a color palette? Read this article by its author, Iñigo Quilez.

Continuous

Mandelbrot set with an escape radius of 4.0, a maximum of 40 iterations, and a procedurally generated palette.

This version uses an algorithm known as normalized iteration count to smooth the transition between colors. The formula for obtaining that fractional count is:

$$ n + 1 - {\frac {log(log(|z_n|))}{log(2)}} $$

Applying some vector and logarithm rules, we can turn it into what you see in my code:

$$ n + 1 - log_2({\frac {log(z \cdot z)}{2}}) $$

Resources

See also