Skip to content

Instantly share code, notes, and snippets.

@intrueder
Forked from rochal/plasma.js
Created November 25, 2013 22:31
Show Gist options
  • Save intrueder/7650103 to your computer and use it in GitHub Desktop.
Save intrueder/7650103 to your computer and use it in GitHub Desktop.
/***************************************************************************
* Do What THe Fuck You Want To Public Licence 2 *
* *
* JavaScript implementation by Piotr Rochala (http://rocha.la/) *
* Based on C# work of Serge Meunier (http://www.smokycogs.com/) *
* *
* Check this code in action on http://rocha.la/javascript-plasma-fractal *
* *
**************************************************************************/
//plasma.js
var $plasma = function()
{
var roughness, totalSize;
var width, height, canvas, ctx;
var types = { PLASMA: 0, CLOUD: 1 };
this.colorModif = [255, 255, 255];
this.init = function(canvasId, w, h, rough, type)
{
//initialize local variables
width = w;
height = h;
roughness = rough;
plasmaType = type;
canvas = document.getElementById(canvasId);
canvas.width = width;
canvas.height = height;
ctx = canvas.getContext("2d");
//generate points
this.points = this.getPoints(width, height, roughness);
//draw points
this.draw();
}
this.draw = function()
{
ctx.clearRect(0, 0, canvas.width, canvas.height);
for (var x = 0; x < width; x++)
{
for (var y = 0; y < height; y++)
{
//get color for each pixel
var color = this.getColor(this.points[x][y], plasmaType);
ctx.fillStyle = "rgb("+color.r+","+color.g+","+color.b+")";
ctx.fillRect(x, y, 1, 1);
}
}
}
this.getPoints = function(width, height, rough)
{
var p1, p2, p3, p4;
var points = [];
for (var x = 0; x < width; x++)
{
points[x] = [];
}
//give corners random colors
p1 = Math.random();
p2 = Math.random();
p3 = Math.random();
p4 = Math.random();
roughness = rough;
totalSize = width + height;
this.splitRect(points, 0, 0, width, height, p1, p2, p3, p4);
return points;
}
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);
side2 = ((p2 + p3) / 2);
side3 = ((p3 + p4) / 2);
side4 = ((p4 + p1) / 2);
//its possible that middle point was moved out of bounds so correct it here
center = this.normalize(center);
side1 = this.normalize(side1);
side2 = this.normalize(side2);
side3 = this.normalize(side3);
side4 = this.normalize(side4);
//repear operation for each of 4 new squares created
//recursion, baby!
this.splitRect(points, x, y, transWidth, transHeight, p1, side1, center, side4);
this.splitRect(points, x + transWidth, y, width - transWidth, transHeight, side1, p2, side2, center);
this.splitRect(points, x + transWidth, y + transHeight, width - transWidth, height - transHeight, center, side2, p3, side3);
this.splitRect(points, x, y + transHeight, transWidth, height - transHeight, side4, center, side3, p4);
}
else
{
//when last square is just a pixel, simply average it from the corners
points[x][y]= (p1 + p2 + p3 + p4) / 4;
}
}
this.normalize = function(val)
{
return (val < 0) ? 0 : (val > 1) ? 1 : val;
}
this.shift = function(smallSize)
{
return (Math.random() - 0.5) * smallSize / totalSize * roughness;
}
this.getColor = function(c, type)
{
var red = 0, green = 0, blue = 0;
switch (type)
{
case types.CLOUD:
if (c < 0.3)
red = c;
red = green = c;
blue = 1;
break;
case types.PLASMA:
//r
if (c < 0.5)
red = c * 2;
else
red = (1.0 - c) * 2;
//g
if (c >= 0.3 && c < 0.8)
green = (c - 0.3) * 2;
else if (c < 0.3)
green = (0.3 - c) * 2;
else
green = (1.3 - c) * 2;
//b
if (c >= 0.5)
blue = (c - 0.5) * 2;
else
blue = (0.5 - c) * 2;
break;
default:
red = green = blue = c;
break;
}
return {
r: ~~(red * this.colorModif[0]),
g: ~~(green * this.colorModif[1]),
b: ~~(blue * this.colorModif[2])
};
}
return this;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment