-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added separated image class and generator class
can now generate a Perlin noise image that can re-blend r, g, and b values upon request
- Loading branch information
Showing
5 changed files
with
430 additions
and
0 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
function Generator() | ||
{ | ||
this.perlin = new ClassicalNoise(); | ||
} | ||
|
||
//generates and returns a seperated image using perlin noise | ||
//w -> width | ||
//h -> height | ||
//blockSize -> number of screen pixels per color block | ||
//noise detail (optional) -> smaller is smoother noise | ||
Generator.prototype.generateBackground = function (w, h, blockSize, noiseDetail) | ||
{ | ||
if( typeof(noiseDetail) == 'undefined' ) noiseDetail = 0.05; | ||
img = new SeparatedImage(w, h); | ||
|
||
//get drawing contexts for each image | ||
var ctxBW = img.getCTX('bw'), | ||
ctxR = img.getCTX('r'), | ||
ctxG = img.getCTX('g'), | ||
ctxB = img.getCTX('b'); | ||
|
||
|
||
//create empty image data for images | ||
var dataBW = ctxBW.createImageData( w, h ), | ||
dataR = ctxR.createImageData( w, h ), | ||
dataG = ctxG.createImageData( w, h ), | ||
dataB = ctxB.createImageData( w, h ); | ||
|
||
//fill image datas with noise | ||
var pixel, byte, r, g, b; | ||
for(var pY = 0; pY < h; pY += blockSize) | ||
{ | ||
for(var pX = 0; pX < w; pX += blockSize) | ||
{ | ||
r = 75 + 150 * this.perlin.noise( pX * 0.01, pY * 0.01 ); | ||
g = 75 + 150 * this.perlin.noise( pX * 0.01 + 1000, pY * 0.01 + 1000 ); | ||
b = 75 + 150 * this.perlin.noise( pX * 0.01 + 2000, pY * 0.01 + 2000 ); | ||
|
||
//do pixelsize x pixelsize | ||
for(var oY = 0; oY < blockSize; oY++) | ||
{ | ||
for(var oX = 0; oX < blockSize; oX++) | ||
{ | ||
var nX = Math.min( pX + oX, w - 1 ); | ||
var nY = Math.min( pY + oY, h -1 ); | ||
|
||
pixel = nY * w + nX; | ||
byte = pixel * 4; | ||
|
||
dataR.data[byte] = r; | ||
dataG.data[byte+1] = g; | ||
dataB.data[byte+2] = b; | ||
|
||
//greyscale | ||
dataBW.data[byte] = dataBW.data[byte + 1] = dataBW.data[byte + 2] = (r+g+b)/3; | ||
|
||
//alpha | ||
dataBW.data[byte+3] = dataR.data[byte+3] = dataG.data[byte+3] = dataB.data[byte+3] = 255; | ||
|
||
} | ||
} | ||
} | ||
} | ||
|
||
//set images | ||
ctxBW.putImageData(dataBW, 0, 0); | ||
ctxR.putImageData(dataR, 0, 0); | ||
ctxG.putImageData(dataG, 0, 0); | ||
ctxB.putImageData(dataB, 0, 0); | ||
|
||
//return separated image | ||
img.blend(1, 1, 1); | ||
return img; | ||
} | ||
|
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
function SeparatedImage(w, h) | ||
{ | ||
//final composite image | ||
this.imgComp = document.createElement('canvas'); | ||
this.ctxComp = this.imgComp.getContext('2d'); | ||
|
||
//black and white image | ||
this.imgBW = document.createElement('canvas'); | ||
//this.ctxBW = imgMain.getContext('2d'); | ||
|
||
//canvas to blend on | ||
this.imgBlend = document.createElement('canvas'); | ||
this.ctxBlend = this.imgBlend.getContext('2d'); | ||
|
||
//separate components | ||
this.imgR = document.createElement('canvas'); | ||
this.imgG = document.createElement('canvas'); | ||
this.imgB = document.createElement('canvas'); | ||
|
||
//set sizes | ||
this.w = this.imgComp.width = this.imgBlend.width = this.imgR.width = this.imgG.width = this.imgB.width = this.imgBW.width = w; | ||
this.h = this.imgComp.height = this.imgBlend.height = this.imgR.height = this.imgG.height = this.imgB.height = this.imgBW.height = h; | ||
} | ||
|
||
//passes back the drawing context for the requested canvas | ||
//possible values are r, g, b, and bw | ||
SeparatedImage.prototype.getCTX = function(color) | ||
{ | ||
switch(color) | ||
{ | ||
case 'r': | ||
return this.imgR.getContext('2d'); | ||
case 'g': | ||
return this.imgG.getContext('2d'); | ||
case 'b': | ||
return this.imgB.getContext('2d'); | ||
case 'bw': | ||
return this.imgBW.getContext('2d'); | ||
} | ||
} | ||
|
||
//blends its r, g, and b components to the given percentages | ||
//pass in values from 0 to 1 | ||
SeparatedImage.prototype.blend = function(r, g, b) | ||
{ | ||
//draw black and white to composite | ||
this.ctxComp.save(); | ||
this.ctxComp.drawImage(this.imgBW, 0, 0, this.w, this.h); | ||
|
||
//blend r, g, b values | ||
this.ctxBlend.save(); | ||
this.ctxBlend.clearRect(0, 0, this.imgBlend.width, this.imgBlend.height); | ||
|
||
this.ctxBlend.globalCompositeOperation = 'screen'; | ||
this.ctxBlend.globalAlpha = r; | ||
this.ctxBlend.drawImage(this.imgR, 0, 0, this.w, this.h); | ||
this.ctxBlend.globalAlpha = g; | ||
this.ctxBlend.drawImage(this.imgG, 0, 0, this.w, this.h); | ||
this.ctxBlend.globalAlpha = b; | ||
this.ctxBlend.drawImage(this.imgB, 0, 0, this.w, this.h); | ||
this.ctxBlend.restore(); | ||
|
||
//blend onto composite image | ||
this.ctxComp.globalCompositeOperation = 'color'; | ||
this.ctxComp.drawImage(this.imgBlend, 0, 0, this.w, this.h); | ||
this.ctxComp.restore(); | ||
} | ||
|
||
SeparatedImage.prototype.getImage = function() | ||
{ | ||
return this.imgComp; | ||
} |
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
// Ported from Stefan Gustavson's java implementation | ||
// http://staffwww.itn.liu.se/~stegu/simplexnoise/simplexnoise.pdf | ||
// Read Stefan's excellent paper for details on how this code works. | ||
// | ||
// Sean McCullough banksean@gmail.com | ||
|
||
/** | ||
* You can pass in a random number generator object if you like. | ||
* It is assumed to have a random() method. | ||
*/ | ||
var ClassicalNoise = function(r) { // Classic Perlin noise in 3D, for comparison | ||
if (r == undefined) r = Math; | ||
this.grad3 = [[1,1,0],[-1,1,0],[1,-1,0],[-1,-1,0], | ||
[1,0,1],[-1,0,1],[1,0,-1],[-1,0,-1], | ||
[0,1,1],[0,-1,1],[0,1,-1],[0,-1,-1]]; | ||
this.p = []; | ||
for (var i=0; i<256; i++) { | ||
this.p[i] = Math.floor(r.random()*256); | ||
} | ||
// To remove the need for index wrapping, double the permutation table length | ||
this.perm = []; | ||
for(var i=0; i<512; i++) { | ||
this.perm[i]=this.p[i & 255]; | ||
} | ||
}; | ||
|
||
ClassicalNoise.prototype.dot = function(g, x, y, z) { | ||
return g[0]*x + g[1]*y + g[2]*z; | ||
}; | ||
|
||
ClassicalNoise.prototype.mix = function(a, b, t) { | ||
return (1.0-t)*a + t*b; | ||
}; | ||
|
||
ClassicalNoise.prototype.fade = function(t) { | ||
return t*t*t*(t*(t*6.0-15.0)+10.0); | ||
}; | ||
|
||
// Classic Perlin noise, 3D version | ||
ClassicalNoise.prototype.noise = function(x, y, z) { | ||
// Find unit grid cell containing point | ||
var X = Math.floor(x); | ||
var Y = Math.floor(y); | ||
var Z = Math.floor(z); | ||
|
||
// Get relative xyz coordinates of point within that cell | ||
x = x - X; | ||
y = y - Y; | ||
z = z - Z; | ||
|
||
// Wrap the integer cells at 255 (smaller integer period can be introduced here) | ||
X = X & 255; | ||
Y = Y & 255; | ||
Z = Z & 255; | ||
|
||
// Calculate a set of eight hashed gradient indices | ||
var gi000 = this.perm[X+this.perm[Y+this.perm[Z]]] % 12; | ||
var gi001 = this.perm[X+this.perm[Y+this.perm[Z+1]]] % 12; | ||
var gi010 = this.perm[X+this.perm[Y+1+this.perm[Z]]] % 12; | ||
var gi011 = this.perm[X+this.perm[Y+1+this.perm[Z+1]]] % 12; | ||
var gi100 = this.perm[X+1+this.perm[Y+this.perm[Z]]] % 12; | ||
var gi101 = this.perm[X+1+this.perm[Y+this.perm[Z+1]]] % 12; | ||
var gi110 = this.perm[X+1+this.perm[Y+1+this.perm[Z]]] % 12; | ||
var gi111 = this.perm[X+1+this.perm[Y+1+this.perm[Z+1]]] % 12; | ||
|
||
// The gradients of each corner are now: | ||
// g000 = grad3[gi000]; | ||
// g001 = grad3[gi001]; | ||
// g010 = grad3[gi010]; | ||
// g011 = grad3[gi011]; | ||
// g100 = grad3[gi100]; | ||
// g101 = grad3[gi101]; | ||
// g110 = grad3[gi110]; | ||
// g111 = grad3[gi111]; | ||
// Calculate noise contributions from each of the eight corners | ||
var n000= this.dot(this.grad3[gi000], x, y, z); | ||
var n100= this.dot(this.grad3[gi100], x-1, y, z); | ||
var n010= this.dot(this.grad3[gi010], x, y-1, z); | ||
var n110= this.dot(this.grad3[gi110], x-1, y-1, z); | ||
var n001= this.dot(this.grad3[gi001], x, y, z-1); | ||
var n101= this.dot(this.grad3[gi101], x-1, y, z-1); | ||
var n011= this.dot(this.grad3[gi011], x, y-1, z-1); | ||
var n111= this.dot(this.grad3[gi111], x-1, y-1, z-1); | ||
// Compute the fade curve value for each of x, y, z | ||
var u = this.fade(x); | ||
var v = this.fade(y); | ||
var w = this.fade(z); | ||
// Interpolate along x the contributions from each of the corners | ||
var nx00 = this.mix(n000, n100, u); | ||
var nx01 = this.mix(n001, n101, u); | ||
var nx10 = this.mix(n010, n110, u); | ||
var nx11 = this.mix(n011, n111, u); | ||
// Interpolate the four results along y | ||
var nxy0 = this.mix(nx00, nx10, v); | ||
var nxy1 = this.mix(nx01, nx11, v); | ||
// Interpolate the two last results along z | ||
var nxyz = this.mix(nxy0, nxy1, w); | ||
|
||
return nxyz; | ||
}; |
Oops, something went wrong.