Skip to content

Instantly share code, notes, and snippets.

@tdreyno
Created June 8, 2012 00:46
Show Gist options
  • Save tdreyno/2892708 to your computer and use it in GitHub Desktop.
Save tdreyno/2892708 to your computer and use it in GitHub Desktop.
Perlin Noise
/**
* PerlinNoise
*
* Tiling Exsample
* (perlinNoise.noise(x, y, z) * (w - x) * (h - y) + perlinNoise.noise(x - w, y, z) * x * (h - y) +
* perlinNoise.noise(x - w, y - h, z) * x * y + perlinNoise.noise(x, y - h, z) * (w - x) * y) / (w * h)
*
* @param seed
* @see http://mrl.nyu.edu/~perlin/noise/
* @see http://freespace.virgin.net/hugo.elias/models/m_perlin.htm
*/
function PerlinNoise(seed) {
this.seed(seed);
}
PerlinNoise.prototype = {
_permutation: null,
_octaves: 4,
_fallout: 0.5,
seed: function(seed) {
var p = this._permutation = window.Uint8Array ? new Uint8Array() : [];
var r = new MultiplyWithCarry(seed);
var i, j, tmp;
for (i = 0; i < SIZE; i++) {
p[i] = i;
}
for (i = 0; i < SIZE; i++) {
j = Math.abs(r.nextInt() % MASK);
tmp = p[j];
p[j] = p[i];
p[i] = tmp;
}
for (i = 0; i < SIZE; i++) {
p[SIZE + i] = p[i];
}
},
octaves: function(octaves) {
if (arguments.length === 0) return octaves;
this._octaves = octaves;
},
fallout: function(fallout) {
if (arguments.length === 0) return fallout;
this._fallout = fallout;
},
noise: function(x, y, z) {
var f = 1; // frequency
var a = 0.5; // amplitude
var n; // noise function
var fallout = this._fallout;
var result = 0;
switch (arguments.length) {
case 1 : n = function() { return noise.call(this, x * f); }; break;
case 2 : n = function() { return noise.call(this, x * f, y * f); }; break;
case 3 : n = function() { return noise.call(this, x * f, y * f, z * f); }; break;
}
for (var i = 0, o = this._octaves; i < o; ++i) {
result += a * (1 + n.call(this)) * 0.5;
a *= fallout;
f *= 2;
}
return result;
}
};
function noise(x, y, z) {
var d = arguments.length;
var p = this._permutation;
var ix = Math.floor(x) & MASK;
x -= Math.floor(x);
var fx = fade(x);
if (d === 1) {
return lerp(fx, grad1d(p[ix], x), grad1d(p[ix + 1], x - 1));
}
var iy = Math.floor(y) & MASK;
y -= Math.floor(y);
var fy = fade(y);
var a = p[ix] + iy;
var b = p[ix + 1] + iy;
if (d === 2) {
return lerp(
fy,
lerp(fx, grad2d(p[a], x, y), grad2d(p[b], x - 1, y)),
lerp(fx, grad2d(p[a + 1], x, y - 1), grad2d(p[b + 1], x - 1, y - 1))
);
}
var iz = Math.floor(z) & MASK;
z -= Math.floor(z);
var fz = fade(z);
var aa = p[a] + iz;
var ab = p[a + 1] + iz;
var ba = p[b] + iz;
var bb = p[b + 1] + iz;
return lerp(
fz,
lerp(
fy,
lerp(fx, grad3d(p[aa], x, y, z), grad3d(p[ba], x - 1, y, z)),
lerp(fx, grad3d(p[ab], x, y - 1, z), grad3d(p[bb], x - 1, y - 1, z))
),
lerp(
fy,
lerp(fx, grad3d(p[aa + 1], x, y, z - 1), grad3d(p[ba + 1], x - 1, y, z - 1)),
lerp(fx, grad3d(p[ab + 1], x, y - 1, z - 1), grad3d(p[bb + 1], x - 1, y - 1, z - 1))
)
);
}
function grad1d(hash, x) {
return (hash & 1) === 0 ? -x : x
}
function grad2d(hash, x, y) {
var v = (hash & 1) === 0 ? x : y;
return (hash & 2) === 0 ? -v : v
}
function grad3d(hash, x, y, z) {
var h = hash & 15;
var u = h < 8 ? x : y;
var v = h < 4 ? y : h === 12 || h === 14 ? x : z;
return ((h & 1) === 0 ? u : -u) + ((h & 2) === 0 ? v : -v)
}
function fade(t) {
return t * t * t * (t * (t * 6 - 15) + 10);
}
function lerp(t, a, b) {
return a + t * (b - a);
}
// add global
window.PerlinNoise = PerlinNoise;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment