Plasmatic! Creating plasma fractals with JavaScript and canvas

This is just a static image. Use controls on the right to create your fractal.
Roughness:
Red:
Green:
Blue:
Draw time: 0ms

Use the controls to modify plasma in real-time! Plasma fractal also known as Random Midpoint Displacement Fractal is not only a cool visual effect but also an extremely useful algorithm often employed in the computer games industry. Also known by its other name - "diamond-square algorithm" is used to create realistic heightmaps for 3D computer graphics and it can also create clouds or smoke effects. But most of all, it creates wicked plasma effect you can see above. And what is cooler than programatically generated plasma? Programatically generated plasma in JavaScript!

Phased plasma rifle in the 40-watt range.
- Anything else?
- Phased plasma rifle in the 40-watt range.
(The Terminator)

Plasma fractal is a visual implementation of the diamond-square algorithm. The algorithm recursively divides canvas into smaller squares, then it locates point in the middle (midpoint) and shifts it randomly within the square. This operation is continued as long as square is bigger then a pixel. Calculated average of the positions of each corner is then saved as a pixel value and finally each pixel is drawn on the canvas.

If you want to read more about the algorithm itself, I highly recommend this article from the Central European Seminar on Computer Graphics.

The Code

The code itself consist of a $plasma class inside of a plasma.js file and it is responsible for initializing the variables, calculating the points color values; it's got a shifting function which moves the midpoint randomly, normalizing function that makes sure random value doesn't go out of bounds, drawing function and finally - actual recursive grid splitting method you can see here (part of the code omitted):

	this.splitRect = function(points, x, y, width, height, p1, p2, p3, p4)
	{  
		var side1, side2, side3, side4, center;
		var transWidth = ~~(width / 2);
		var transHeight = ~~(height / 2);
		
		//as long as square is bigger then a pixel..
		if (width > 1 || height > 1)
		{  
			//center is just an average of all 4 corners
			center = ((p1 + p2 + p3 + p4) / 4);
			
			//randomly shift the middle point 
			center += this.shift(transWidth + transHeight);
			
			//sides are averages of the connected corners
			//p1----p2
			//|     |
			//p4----p3
			side1 = ((p1 + p2) / 2);
			...
			
			//its possible that middle point was moved out of bounds so correct it here
			center = this.normalize(center);
			side1 = this.normalize(side1);
			...
			
			//repear operation for each of 4 new squares created
			//recursion, baby!
			this.splitRect(points, x, y, transWidth, transHeight, p1, side1, center, side4);
			...
		}
		else 
		{
			//when last square is just a pixel, simply average it from the corners
			points[x][y]= (p1 + p2 + p3 + p4) / 4;
		}
	}

You can find full code of the plasma.js in the gist here: https://gist.github.com/2839478

Customization

To control the parameters of the algorithm, I've put together small GUI that allows to set RGB values of the passed colour variables. This way we you can create different plasmas and clouds on the fly. GUI also allows to change the roughness of the edges of the plasma to create even more interesting effects. Below is few more images of random plasmas generated using the GUI above.

Example plasma fractals created using editor above.

Kudos

Finally - huge thanks to Serge Meunier whose code helped me out in my JavaScript implementation. You can find his great blog here where you can check out other amazing fractal generation algorithms implemented in C#.

Social/Code

profile for rochal on Stack Exchange, a network of free, community-driven Q&A sites