-
-
Save intrueder/7650103 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*************************************************************************** | |
* 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