The (smooth) Mandelbrot Set

After experimenting with ChatGPT to create fractal generators, I decided to make one myself. I did so with the help of a wikipedia article called "Plotting the Mandelbrot Set". If you're new to coding and looking for a fun, low effort/high reward project to work on I'd definitively give the Mandelbrot set a try, I've attempted to make a tutorial on the bottom of the page. This is my most polished, and longest running project I've been working on, and also the only fun one :).

Controls

Arrow keys/drag the mouse to move

Q/E to zoom in/out

+/- to in/decrease the maximum amount of iterations

A/Z to in/decrease samples

B to toggle biomorphs

[/] to change the biomorph value

O/P to in/decrease the bailout value

S to toggle smooth coloring

R to "respawn"

1/2/3/4/5 to change fractal

Tap/hold J to explore julia sets

U/I to downscale the image

F11 to toggle fullscreen

Compile with:g++ mandel.cpp -o mandel -lGL -lGLU -lglut -Ofast

How it works

So, the general idea of plotting the mandelbrot set is to run the formula "z=z^2+c" for a limited amount of iterations, for every pixel. The variables "z" and "c" are complex numbers. Z is initialized to be (0,0i), and c is a certain value, like a coordinate grid. To do this in code without using complex numbers, but simple numbers, is quite tricky. People have found a way to do it, I put it in the tutorial below. I am not quite sure how it works, but it sure does :).

How to plot the Mandelbrot set using C++/openGL glut.h

cool image

What you get if you follow the tutorial/copy the code

This small tutorial thing was only tested on Linux. Small modifications might be neccesary for Windows/macOS. On Linux, first install some dependencies with (for Debian based systems with Aptitude): sudo apt install gcc g++ freeglut3-dev This command installs openGL glut, a long obsolete package but I like it for its decent simplicity.

Start your program with this basic OpenGL start project code: (I personally use this code for any new project)


#include <GL/glut.h> // Includes openGL
#include <cmath>  // Needed for some math functions later
const int WIDTH=800,HEIGHT=600; // Define your resolution.
void display(){ // Display function. This 
  glBegin(GL_POINTS);
  for (int x = 0; x < WIDTH; x++) {
    for (int y = 0; y < HEIGHT; y++) {
      // Drawing logic will be implemented here later.
      glColor3f(0.5,0.5,0.5); // Temporary gray color
      glVertex2i(x,y); // Plots the pixel.
    }
  }
  glEnd();  // | Writes the plotted pixels to the display
  glFlush();// |
}
int main(int argc, char** argv){
  glutInit(&argc,argv); // Inits OpenGL
  glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);

  glutInitWindowSize(WIDTH,HEIGHT); // Sets the window size
  glutCreateWindow("OpenGL Mandelbrot"); // Creates the window and gives it a name

  glViewport(0, 0, WIDTH, HEIGHT); // Changes some werid openGL settings
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  glOrtho(0, WIDTH, 0, HEIGHT, -1, 1);
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();

  glutDisplayFunc(display); // Uses the display function to update the screen

  glutMainLoop(); // Calls for the display function each frame.
}

This should output a grey window called "OpenGL Mandelbrot". Let's add some actual Mandelbrot code now.

Initialize some variables after including cmath and before the display function:


const int maxIter=250; // Higher value means more detail at higher zoom levels.
long double xPos=-3.2;
long double yPos=-2.0; // Feel free to adjust these values!
long double zoom= 150; // Zoom level. Higher is more zoomed-in

long double cReal,cImag,zReal,zImag,zrTemp,iter; // predefinitions

All of these values can be changed to modify the end-product. Now, go to the display function and modify it as follows.


void display(){
  glClear(GL_COLOR_BUFFER_BIT);
  glBegin(GL_POINTS);
  for (int x = 0; x < WIDTH; x++) {
    for (int y = 0; y < HEIGHT; y++) {
      iter=0;
      cReal=(x/zoom)+xPos; // | Maps the current pixel to a grid,
      cImag=(y/zoom)+yPos; // |
      zReal=0;
      zImag=0;
      while(iter<maxIter&&zReal*zReal+zImag*zImag<4){ // Checks if the iter value exceeds maxIter, or if the point gets out of bounds.
          zrTemp=((zReal*zReal)-(zImag*zImag))+cReal; // Calculates the real part of Z
          zImag=2*zImag*zReal+cImag; // Calculates the imaginary part of Z
          zReal=zrTemp; // Sets zReal to the calculated value.
          iter++; // Changes the iterations variable.
      }
      if(iter==maxIter){
        glColor3f(0,0,0);}// Makes the point black if it didn't go out of bounds in the set number of maximum iterations
      else{
        glColor3f(10*iter/maxIter,10*iter/maxIter,10*iter/maxIter); // Makes the point a grey color
      }
      glVertex2i(x,y);
    }
  }
  glEnd();
  glFlush();
}

That should be it! You should have a nice mandelbrot image on your screen! I encourage you to make your own little modifications, like adding more interesting colors, or perhaps change the fractal a bit!

Some images

picture picture picture picture picture picture



copyleft go steal it or something