Mandelbrot Set Shader

The Mandelbrot set is a fractal. Fractals are mathematical sets that have a repeating pattern at every scale. For more information look at the bottom of this post.

Due to the intensive native of computing the Mandelbrot set, computing it with the CPU is not fast enough to do more than just render an image to the screen. However using the GPU you can render it much faster and at higher resolutions. The following code was written in processing and GLSL to render the fractal to the screen and allow you to move around in real time.

PShader fractal;
float xC = 0;
float yC = 0;
float zoom = 1;
boolean[] keyDown = new boolean[8];
float zoomSpeed = 0.01;
float movementSpeed = 0.1;
float heightF;
float widthF;

void setup() {
  size(960, 640, P3D);
  fractal = loadShader("shaderFrag.glsl", "defaultVert.glsl");
  heightF = height;
  widthF = width;
  //set shader variables
  fractal.set("windowSize", widthF, heightF);
  fractal.set("cameraPos", xC, yC);
  fractal.set("zoom", zoom);
}

void draw() {
  background(0);
  //set which shader
  shader(fractal);
  //render blank box to use the shader on
  rect(0,0,width,height);
  //handle movement
  movement();
  
  //set shader variables
  fractal.set("windowSize", widthF, heightF);
  fractal.set("cameraPos", xC, yC);
  fractal.set("zoom", zoom);
}


 private void movement() {
  if (keyDown[0] == true) {
    yC += movementSpeed * zoom;
  }
  if (keyDown[1] == true) {
    yC -= movementSpeed * zoom;
  }
  if (keyDown[2] == true) { 
    xC -= movementSpeed * zoom;
  }
  if (keyDown[3] == true) { 
    xC += movementSpeed * zoom;
  }
  if (keyDown[4] == true) { 
    zoom -= zoomSpeed * zoom;
  }
  if (keyDown[5] == true) { 
    zoom += zoomSpeed * zoom;
  }
}

public void keyPressed() {
  if (key == 'w' || (key == CODED && keyCode == UP)) {
    keyDown[0] = true;
  }
  if (key == 's' || (key == CODED && keyCode == DOWN)) {
    keyDown[1] = true;
  }
  if (key == 'a' || (key == CODED && keyCode == LEFT)) {
    keyDown[2] = true;
  }
  if (key == 'd' || (key == CODED && keyCode == RIGHT)) {
    keyDown[3] = true;
  }
  if (key == '=') {
    keyDown[4] = true;
  }
  if (key == '-') {
    keyDown[5] = true;
  }
}

public void keyReleased() {
  if (key == 'w' || (key == CODED && keyCode == UP)) {
    keyDown[0] = false;
  }
  if (key == 's' || (key == CODED && keyCode == DOWN)) {
    keyDown[1] = false;
  }
  if (key == 'a' || (key == CODED && keyCode == LEFT)) {
    keyDown[2] = false;
  }
  if (key == 'd' || (key == CODED && keyCode == RIGHT)) {
    keyDown[3] = false;
  }
  if (key == '=') {
    keyDown[4] = false;
  }
  if (key == '-') {
    keyDown[5] = false;
  }
}

Fragment Shader (where Mandelbrot is rendered)

precision highp float;

uniform sampler2D texture;
uniform vec2 windowSize;
uniform vec2 cameraPos;
uniform float zoom;

varying vec4 vertColor;
varying vec4 vertTexCoord;
varying vec4 pos;

vec3 hsv2rgb(vec3 c)
{
    vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
    vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
    return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
}

void main() {
    vec3 color = vec3(0,0,0);
	vec2 pixel = (pos.xy / windowSize) * zoom; 
    double x0 = ((3.5 * pixel.x)) + (cameraPos.x);
    double y0 = ((2.0 * pixel.y)) + (cameraPos.y);
    double x = 0.0;
    double y = 0.0;
    int iteration = 0;
    int max_iteration = 250;
	double xtemp = 0.0;
    while (x * x + y * y < 4  &&  iteration < max_iteration) {
         xtemp = x*x - y*y + x0;
         y = 2.0 * x*y + y0;
         x = xtemp;
         iteration = iteration + 1;
    }
    if (iteration != max_iteration) {
		  float tmp = float(iteration) / float(max_iteration);
		  color = hsv2rgb(vec3(tmp * 10, 1.0, 1.0));
    }
    gl_FragColor = vec4(color.r, color.g, color.b, 1.0);
}

Vertex Shader

#define PROCESSING_COLOR_SHADER

uniform mat4 transform;
uniform mat4 texMatrix;

attribute vec4 vertex;
attribute vec4 color;
attribute vec2 texCoord;

varying vec4 vertColor;
varying vec4 vertTexCoord;
varying vec4 pos;

void main() {
    gl_Position = transform * vertex;
    pos = transform * vertex;
    vertColor = color;
    vertTexCoord = texMatrix * vec4(texCoord, 1.0, 1.0);
}

Fractal: Click Here

Mandelbrot Set: Click Here 

Processing Shaders: Click Here

Tree Fractal

This is a tree fractal. Fractals are mathematical sets that have a repeating pattern at every scale. Each branching point on the tree branches off at the same angle 

The images above of the tree fractal were created in processing. Source code can be seen below.

//angle that stem one branches off at
float rotationStem1 = - QUARTER_PI / 5;
//angle that stem two branches off at
float rotationStem2 = QUARTER_PI / 5;
//begining branch length
float lineLength = 200;
//depth to generate tree to
int depth = 5;

void setup() {
  size(960, 640, P3D);
  frameRate(30);
}

void draw() {
  background(255);
  strokeWeight(2);
  smooth();
  //draw starting trunk
  line(width/2, height - 10, width/2, height - 10 - lineLength);
  translate(width/2, height - 10 +- lineLength);
  rotateZ(PI);
  //draw stems
  drawStem(0, lineLength / 3 * 2);
  
  //change rotation
  rotationStem1 -= 0.01;
  rotationStem2 += 0.01;
}

//stems recursively
void drawStem(int i, float lengthL) {
  //draw stem one
  rotateZ(rotationStem1);
  line(0,0, 0, lengthL);
  translate(0, lengthL);
  if (i < depth)
    drawStem(i+1, lengthL / 3 * 2); //draw stems that branch off and decrease length
  
  translate(0, -lengthL);
  rotateZ(-rotationStem1);
  
  //draw stem two
  rotateZ(rotationStem2);
  line(0,0, 0, lengthL);
  translate(0, lengthL);
  if (i < depth)
    drawStem(i+1, lengthL / 3 * 2);//draw stems that branch off and decrease length
    
  translate(0, -lengthL);
  rotateZ(-rotationStem2);
}

Fractals: Click Here

Julia Set

The Julia set is a fractal. Fractals are mathematical sets that have a repeating pattern at every scale. For more information look at the bottom of this post. The Julia set is based on the Mandelbrot set, each c constant in the Julia set corresponds to a point in the Mandelbrot set.

The images above of the Julia set were created in processing. Source code can be seen below.

boolean[] keyDown = new boolean[10];
//camera x
float xC = 0.0;
//camera y
float yC = 0.0;
//constant X
float constX = -1.3000027;
//constant Y
float constY = 0.0028000013;
//camera zoom
float zoom =  1.2;// * pow(10, -5)
//zoom speed
float zoomSpeed = 0.01;
//movement speed
float movementSpeed = 0.1;
//constant change speed
float constSpeed = 0.002;

void setup() {
  //have a small resolution if you want to be able to move around
  size(960, 640);
  colorMode(HSB, 360, 100, 100);
}

void draw() {
  //Julia set Escape time algorithm
  for (int x = 0; x < width; x++) {
    for (int y = 0; y < width; y++) {
      float x0 = ((3 * (float)(x) / (float)width) - 1.5) * zoom + xC;
      float y0 = (2 * (float)(y) / (float)height - 1) * zoom + yC;
      int iteration = 0;
      int max_iteration = 1000;
      while (x0*x0 + y0*y0 < 4  &&  iteration < max_iteration) {
        float xtemp = x0*x0 - y0*y0 + constX;
        y0 = 2*x0*y0 + constY;
        x0 = xtemp;
        iteration = iteration + 1;
      }
      if (iteration == max_iteration)
        stroke(color(0, 100, 0));
      else {
          //blue and black color scheme
          stroke(color(230, 100, iteration % 100));
          //multi color scheme
          //stroke(color(iteration % 300, 100, 100));
        }
      point(x, y);
    }
  }
  //movement code
  movement();
}



private void movement() {
  if (keyDown[0] == true) {
    yC -= movementSpeed * zoom;
  }
  if (keyDown[1] == true) {
    yC += movementSpeed * zoom;
  }
  if (keyDown[2] == true) { 
    xC -= movementSpeed * zoom;
  }
  if (keyDown[3] == true) { 
    xC += movementSpeed * zoom;
  }
  if (keyDown[4] == true) { 
    zoom -= zoomSpeed * zoom;
  }
  if (keyDown[5] == true) { 
    zoom += zoomSpeed * zoom;
  }
  if (keyDown[6] == true) { 
    constX -= constSpeed * zoom;
  }
  if (keyDown[7] == true) { 
    constX += constSpeed * zoom;
  }
  if (keyDown[8] == true) { 
    constY -= constSpeed * zoom;
  }
  if (keyDown[9] == true) { 
    constY += constSpeed * zoom;
  }
}

public void keyPressed() {
  if (key == 'w' || (key == CODED && keyCode == UP)) {
    keyDown[0] = true;
  }
  if (key == 's' || (key == CODED && keyCode == DOWN)) {
    keyDown[1] = true;
  }
  if (key == 'a' || (key == CODED && keyCode == LEFT)) {
    keyDown[2] = true;
  }
  if (key == 'd' || (key == CODED && keyCode == RIGHT)) {
    keyDown[3] = true;
  }
  if (key == '=') {
    keyDown[4] = true;
  }
  if (key == '-') {
    keyDown[5] = true;
  }
  if (key == '[') {
    keyDown[6] = true;
  }
  if (key == ']') {
    keyDown[7] = true;
  }
  if (key == ';') {
    keyDown[8] = true;
  }
  if (key == '\'') {
    keyDown[9] = true;
  }
}

public void keyReleased() {
  if (key == 'w' || (key == CODED && keyCode == UP)) {
    keyDown[0] = false;
  }
  if (key == 's' || (key == CODED && keyCode == DOWN)) {
    keyDown[1] = false;
  }
  if (key == 'a' || (key == CODED && keyCode == LEFT)) {
    keyDown[2] = false;
  }
  if (key == 'd' || (key == CODED && keyCode == RIGHT)) {
    keyDown[3] = false;
  }
  if (key == '=') {
    keyDown[4] = false;
  }
  if (key == '-') {
    keyDown[5] = false;
  }
  if (key == '[') {
    keyDown[6] = false;
  }
  if (key == ']') {
    keyDown[7] = false;
  }
  if (key == ';') {
    keyDown[8] = false;
  }
  if (key == '\'') {
    keyDown[9] = false;
  }
  
  //saves frame
  if (key == 'p')
    saveFrame("snapShot-####.png");
  //prints movement, constant and zoom data
  if (key == 'x')
    print("float xC = " + xC +";\nfloat yC = " + yC + ";\nfloat constX = " + constX + ";\nfloat constY = " + constY + ";\nfloat zoom =  " + zoom + ";// * pow(10, -5)");
}

Fractual: Click Here

Julia set: Click Here 

More Info
Lodev: Click Here
Karlsims: Click Here 
Wiki Books: Click Here

Mandelbrot Set

The Mandelbrot set is a fractal. Fractals are mathematical sets that have a repeating pattern at every scale. For more information look at the bottom of this post.

The images above of the Mandelbrot set were created in processing using the pseudo code found on it's wiki. Source code can be seen below.

boolean[] keyDown = new boolean[8];
//camera x position
float xC = -0.3850605;
//camera y position
float yC = 0.5905769;
//zoom amount (1 for 1 to 1)
float zoom = 0.14230743;
//zoom speed
float zoomSpeed = 0.01;
//movement speed
float movementSpeed = 0.1;

void setup() {
  //have a small resolution if you want to be able to move around
  size(960,640);
  colorMode(HSB, 360, 100, 100);
}

void draw() {
  //Mandelbrot set Escape time algorithm
  for (int sX = 0; sX < width; sX++) {
    for (int sY = 0; sY < width; sY++) {
      float x0 = ((3.5 * (float)(sX) / (float)width) - 2.5) * zoom + xC;
      float y0 =((2 * (float)(sY) / (float)height) - 1) * zoom + yC;
      float x = 0;
      float y = 0;
      int iteration = 0;
      int max_iteration = 280;
      while (x*x + y*y < 2*2  &&  iteration < max_iteration) {
        float xtemp = x*x - y*y + x0;
        y = 2*x*y + y0;
        x = xtemp;
        iteration = iteration + 1;
      }
      if (iteration == max_iteration)
        stroke(color(0, 100, 0));
      else {
        //blue and black color scheme
        stroke(color(230, 100, iteration % 100));
        //multi color scheme
        //stroke(color(iteration % 300, 100, 100));
      }
      point(sX, sY);
    }
  }
  //code for movement
  movement();
}

 private void movement() {
  if (keyDown[0] == true) {
    yC -= movementSpeed * zoom;
  }
  if (keyDown[1] == true) {
    yC += movementSpeed * zoom;
  }
  if (keyDown[2] == true) { 
    xC -= movementSpeed * zoom;
  }
  if (keyDown[3] == true) { 
    xC += movementSpeed * zoom;
  }
  if (keyDown[4] == true) { 
    zoom -= zoomSpeed * zoom;
  }
  if (keyDown[5] == true) { 
    zoom += zoomSpeed * zoom;
  }
}

public void keyPressed() {
  if (key == 'w' || (key == CODED && keyCode == UP)) {
    keyDown[0] = true;
  }
  if (key == 's' || (key == CODED && keyCode == DOWN)) {
    keyDown[1] = true;
  }
  if (key == 'a' || (key == CODED && keyCode == LEFT)) {
    keyDown[2] = true;
  }
  if (key == 'd' || (key == CODED && keyCode == RIGHT)) {
    keyDown[3] = true;
  }
  if (key == '=') {
    keyDown[4] = true;
  }
  if (key == '-') {
    keyDown[5] = true;
  }
}

public void keyReleased() {
  if (key == 'w' || (key == CODED && keyCode == UP)) {
    keyDown[0] = false;
  }
  if (key == 's' || (key == CODED && keyCode == DOWN)) {
    keyDown[1] = false;
  }
  if (key == 'a' || (key == CODED && keyCode == LEFT)) {
    keyDown[2] = false;
  }
  if (key == 'd' || (key == CODED && keyCode == RIGHT)) {
    keyDown[3] = false;
  }
  if (key == '=') {
    keyDown[4] = false;
  }
  if (key == '-') {
    keyDown[5] = false;
  }
  
  //save current frame
  if (key == 'p')
    saveFrame("snapShot-####.png");
  //print location and zoom
  if (key == 'x')
    print(xC + "," + yC + " " + zoom + "\n");
}


Fractual: Click Here

Mandelbrot Set: Click Here 

More Info
Lodev: Click Here