This weekend I decided to play around with OpenCL, something I had never used before. As first project I built a Mandelbrot set renderer. This seemed fitting, since in high school I wrote an extremely slow version in TI Basic on a TI84 graphic calculator. Rendering a single image took about 45 minutes.

The math behind the Mandelbrot set is relatively simple. A point $$c$$ on the complex plane is included in the set if the sequence $$z_{n+1} = z_n^2 + c$$ with $$z_0 = 0$$ is bounded. For simplicity we interpret “bounded” as $$\vert z\vert < 4$$ after 256 iterations. To add some nice coloring to the points outside of the set, we can count how many iterations it takes for the sequence to go “unbounded”.

I translated the pseudo code from Wikipedia into the following OpenCL kernel:

__kernel void mandelbrot(__write_only image2d_t out) {
int2 pos = (int2)(get_global_id(0), get_global_id(1));
int2 size = get_image_dim(out);

// Scale x to -2.5 to 1
float x0 = (float)pos.x / size.x;
x0 = x0*3.25 - 2;

// Scale y to -1 to 1
float y0 = (float)pos.y / size.y;
y0 = y0*2.0 - 1.0;

float x = 0.0;
float y = 0.0;

uint max_its = 256;
uint i = 0;
float d = 0.0;

while (i < max_its && d < 4.0){
float xtemp = x*x - y*y + x0;
y = 2*x*y + y0;
x = xtemp;

d = x*x + y*y;
i++;
}

uint4 color = (255, 255, 255, 255);

if (d < 4.0){
color.xyz = (uint3)(0, 0, 0);
} else {
color.xyz = get_color(i);

}

write_imageui(out, pos, color);
}

The complete code can be found on my GitHub repo. 