To implement Perlin Noise in JavaScript, the common approach is to generate a noise function that returns a random value for each point in a grid. We can use a combination of random functions and interpolation to create a smoother noise function.
function perlinNoise(x, y) {
function fade(t) {
return t * t * t * (t * (t * 6 - 15) + 10);
}
function lerp(a, b, t) {
return (1 - t) * a + t * b;
}
function grad(hash, x, y) {
const h = hash & 3;
const u = h < 2 ? x : -x;
const v = h < 1 || h == 3 ? y : -y;
return u + v;
}
const permutation = [
151, 160, 137, 91, 90, 15, 131, 13, 201, 95, 96, 53, 194, 233,
7, 225, 140, 36, 103, 30, 69, 142, 8, 99, 37, 240, 21, 10, 23, 190,
6, 148, 247, 120, 234, 75, 0, 26, 197, 62, 94, 252, 219, 203, 117,
35, 11, 32, 57, 177, 33, 88, 237, 149, 56, 87, 174, 20, 125, 136,
171, 168, 68, 175, 74, 165, 71, 134, 139, 48, 27, 166, 77, 146, 158,
231, 83, 111, 229, 122, 60, 211, 133, 230, 220, 105, 92, 41, 55, 46,
245, 40, 244, 102, 143, 54, 65, 25, 63, 161, 1, 216, 80, 73, 209, 76,
132, 187, 208, 89, 18, 169, 200, 196, 135, 130, 116, 188, 159, 86,
164, 100, 109, 198, 173, 186, 3, 64, 52, 217, 226, 250, 124, 123,
5, 202, 38, 147, 118, 126, 255, 82, 85, 212, 207, 206, 59, 227, 47,
16, 58, 17, 182, 189, 28, 42, 223, 183, 170, 213, 119, 248, 152, 2,
44, 154, 163, 70, 221, 153, 101, 155, 167, 43, 172, 9, 129, 22, 39,
253, 19, 98, 108, 110, 79, 113, 224, 232, 178, 185, 112, 104, 218,
246, 97, 228, 251, 34, 242, 193, 238, 210, 144, 12, 191, 179, 162,
241, 81, 51, 145, 235, 249, 14, 239, 107, 49, 192, 214, 31, 181, 199,
106, 157, 184, 84, 204, 176, 115, 121, 50, 45, 127, 4, 150, 254, 138,
236, 205, 93, 222, 114, 67, 29, 24, 72, 243, 141, 128, 195, 78, 66,
215, 61, 156, 180,
];
const p = new Array(512);
for (let i = 0; i < 256; i++) {
p[i] = permutation[i];
p[256 + i] = permutation[i];
}
const xi = Math.floor(x) & 255;
const yi = Math.floor(y) & 255;
const g1 = p[p[xi] + yi];
const g2 = p[p[xi + 1] + yi];
const g3 = p[p[xi] + yi + 1];
const g4 = p[p[xi + 1] + yi + 1];
const xf = x - Math.floor(x);
const yf = y - Math.floor(y);
const n1 = grad(g1, xf, yf);
const n2 = grad(g2, xf - 1, yf);
const n3 = grad(g3, xf, yf - 1);
const n4 = grad(g4, xf - 1, yf - 1);
const u = fade(xf);
const v = fade(yf);
const ix1 = lerp(n1, n2, u);
const ix2 = lerp(n3, n4, u);
const iy = lerp(ix1, ix2, v);
return iy;
}
Once we have the Perlin Noise function, we can use it to generate random patterns, textures, and terrain height maps. One of the popular use cases for Perlin Noise in web development is to draw smooth curves and shapes on the HTML canvas.
Here's a basic example of using Perlin Noise to generate a grayscale noise map on a canvas:
This code generates a 2D noise map by iterating over each pixel on the canvas, passing the (x, y) coordinates to the Perlin Noise function, and using the resulting value to set the color of the pixel on a grayscale gradient. The noise map will look smooth and random, but will have no repeating patterns or sharp edges, making it useful for creating organic-looking visual effects.