Mandelbrot Tutorial

Sun 08 May 2022 by Top Shelf Technology

First lets include the needed libraries

#include <SDL2/SDL.h>
#include <numeric>
#include <complex>

Now we're going to need a function to decide if some complex number c is in the set.

We're going to define a function int is_in_set(std::complex<double> c) this function will decide if the complex number c is in the set and return to us 0 if it is or some number depending on how many iterations it took to decide if it was not.

int is_in_set(std::complex<double> c)
{
    std::complex<double> z(0,0);
    for(int i = 0; i < 2500; i++)
    {
        z = std::pow(z,2) + c;
        if(std::norm(z) > 10)
        {
            return i;
        }
    }
    return 0;
}

This function is all you need to decide if some point c is in the set or not. We take a c initialize z to (0,0) then iterate 250 times to see if the squared magnitude of z ever exceeds 10 (an arbitrary number I made up, feel free to change it to whatever you want).

Next we're going to loop over x and y and run the is_in_set function for every x,y to see if the x,y combination lands in the set.

int iters = 0;
for(double x = -2.0; x < 2.0; x+=0.001)
{
        for(double y = -2.0; y < 2.0; y+=0.001)
        {
                iters = is_in_set(std::complex<double>(x,y);
                // If iters == 0 paint this point black.
                // Otherwise paint the point
                // a color depending on the number of iters
        }
}

doing this will give you something similar to this.

Mandelbrot fractal

The full source code is available below:

#include <SDL2/SDL.h>
#include <numeric>
#include <complex>

int is_in_set(std::complex<double> c)
{
    std::complex<double> z(0,0);
    for(int i = 0; i < 2500; i++)
    {
        z = std::pow(z,2) + c;
        if(std::norm(z) > 10)
        {
            return i;
        }
    }
    return 0;
}

int main()
{
    SDL_Init(SDL_INIT_EVERYTHING);
    SDL_Window* window = nullptr;
    SDL_Renderer* renderer = nullptr;
    SDL_CreateWindowAndRenderer(1000*2,1000*2,0, &window, &renderer);
    SDL_RenderSetScale(renderer,2,2);

    for(double x = 0.0; x < 1.0; x+=0.001)
        for(double y = 0.0; y < 1.0; y+=0.001)
        {
            double point_x = std::lerp(-2.0, 2.0,x);
            double point_y = std::lerp(-2.0, 2.0,y);
            int iters = is_in_set(std::complex<double>(point_x, point_y));
            if(iters == 0)
            {
                SDL_SetRenderDrawColor(renderer,0,0,0,255);
                SDL_RenderDrawPointF(renderer, static_cast<float>(x * 1000.0),  static_cast<float>(y * 1000.0));
            }
            else{
                SDL_SetRenderDrawColor(
                    renderer,
                    static_cast<Uint8>(3 * iters % 255),
                    static_cast<Uint8>(3 * iters % 255),
                    static_cast<Uint8>(3 * iters % 255),
                    255);
                SDL_RenderDrawPointF(renderer, static_cast<float>(x * 1000.0), static_cast<float>(y * 1000.0));
            }
        }

    SDL_RenderPresent(renderer);
    SDL_Delay(10000);
}

A video demo is available here:


Fork me on GitHub