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.
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.