Plasmatic! Creating plasma fractals with JavaScript and canvas
Roughness: 

Red: 

Green: 

Blue: 

Draw time: 0ms  
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  "diamondsquare 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!
 Anything else?  Phased plasma rifle in the 40watt range. (The Terminator)

Plasma fractal is a visual implementation of the diamondsquare 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 //p1p2 //  //p4p3 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.
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#.
Comments
There are some interesting
There are some interesting points in time in this article but I don't know if I see all of them center to heart. There is some validity but I will take hold opinion until I look into it further. Good article , thanks and we want more! Added rocha.la to FeedBurner as well
There are some interesting
There are some interesting points in time in this article but I don't know if I see all of them center to heart. There is some validity but I will take hold opinion until I look into it further. Good article , thanks and we want more! Added rocha.la to FeedBurner as well
tnx!
Thanks for the great work.
I've adapted your library slightly so now I can use it to generate a heightmap for my imaginary worlds
:)
cheers,
Jerry
Comment