Plasma Fractals

Generating Plasma Fractals with Processing.js

Plasma Fractals

Plasma Fractals are cloud-like fractals generated using the "mid-point displacement algorithm". The mid-point algorithm starts by setting a value or color to each corner and averaging the values recursively to on an increasingly smaller grid off-setting the mid color with a random factor. It's a very neat effect which is used to generate terrain in movies and games, not to mention cloud textures, water displacement maps and eye-candy for hippies. It is also a superb lesson in recursive graphics, as the function calls itself until it has completed, making extremely simple work of grid division.

Converting a Java Applet to Processing.js

The demo above is a code-conversion from a Java applet I found on the net by Justin Seyster. If you would like to see the original code and application, please go to http://www.ic.sunysb.edu/Stu/jseyster/plasma/. I updated the code by adding the option to change your plasma's resolution, gamma and noise just to give you some creative input on the process.

// Plasma Fractal Generator
// Converted by F1LT3R @ Hyper-Metrix.com from original at http://www.ic.sunysb.edu/Stu/jseyster/plasma/

void setup(){
  size(320, 320);
  background(0);
  noStroke();
  plasma(0,0, width, height, random(1.0), random(1.0), random(1.0), random(1.0));  
}

// Variables I added to aid demonstration - F1LT3R 
int gridSize = 5;
int gamma = 510;

int edge1, edge2, edge3, edge4, midPoint;
int newWidth, newHeight;

void draw(){}
  
void mousePressed(){
  plasma(0,0, width, height, random(1.0), random(1.0), random(1.0), random(1.0));    
}

void plasma(float x, float y, float width, float height, float c1, float c2, float c3, float c4){
    
    float edge1, edge2, edge3, edge4, midPoint;    
   	float newWidth = width / 2;
		float newHeight = height / 2;
    
    if (width > gridSize || height > gridSize) {	
			
			//Randomly displace the midpoint!
      midPoint = (c1 + c2 + c3 + c4) / 4 + Displace(newWidth + newHeight);
			
      //Calculate the edges by averaging the two corners of each edge.
      edge1 = (c1 + c2) / 2;	
			edge2 = (c2 + c3) / 2;
			edge3 = (c3 + c4) / 2;
			edge4 = (c4 + c1) / 2;

	    //Make sure that the midpoint doesn't accidentally "randomly displaced" past the boundaries!
			if (midPoint < 0) { midPoint = 0; } 
      else if (midPoint > 1.0f) { midPoint = 1.0f; }
					
  			//Do the operation over again for each of the four new grids.			
  			plasma(x, y, newWidth, newHeight, c1, edge1, midPoint, edge4);
  			plasma(x + newWidth, y, newWidth, newHeight, edge1, c2, edge2, midPoint);
  			plasma(x + newWidth, y + newHeight, newWidth, newHeight, midPoint, edge2, c3, edge3);
  			plasma(x, y + newHeight, newWidth, newHeight, edge4, midPoint, edge3, c4);		
		  
    } else { //This is the "base case," where each grid piece is less than the size of a pixel.
    
  			//The four corners of the grid piece will be averaged and drawn as a single pixel.
  		  float c = (c1 + c2 + c3 + c4) / 4;
          
        float Red = 0, Green = 0, Blue = 0;
  
    		if (c < 0.5f) {
    			Red = c * gamma;
    		} else {
    			Red = (1.0f - c) * gamma;
    		}
    		
    		if (c >= 0.3f && c < 0.8) {
    			Green = (c - 0.3f) * gamma;
    		} else if (c < 0.3f) {
    			Green = (0.3f - c) * gamma;
    		} else {
    			Green = (1.3f - c) * gamma;
        }
    		
    		if (c >= 0.5f) {
    			Blue = (c - 0.5f) * gamma;
    		} else {
    			Blue = (0.5f - c) * gamma;
        }

        fill(Red, Green, Blue);        
        /* I added a gridsize variable and rect() call to allow faster
        rendering that would maintain fill. - F1LT3R */
        rect(int(x), int(y), gridSize, gridSize);
		}
}

float Displace(float num){
		float max = num / (width + height) * 3;		
		return (random(1.0)- 0.5f) * max;
}

Feel free to use my code "licenselessly", though you should probably ask Justin Seyster too if you don't like being sued.