I have a simple perlin noise function that has the parameters x, y, z, and seed. When I draw the perlin noise to the canvas using the function, the pattern which the perlin noise generates repeats over and over (kinda in a grid pattern) instead of being pseudo-random.
Here is my code:
function perlinNoise(x, y, z, seed) {
function fade(t) {
return t * t * t * (t * (t * 6 - 15) + 10);
}
function lerp(t, a, b) {
return a + t * (b - a);
}
function grad(hash, x, y, z) {
var h = hash & 15;
var u = h < 8 ? x : y,
v = h < 4 ? y : h == 12 || h == 14 ? x : z;
return ((h & 1) == 0 ? u : -u) + ((h & 2) == 0 ? v : -v);
}
function scale(n) {
return ((1 + n) / 2);
}
// Generate the permutation array based on the seed
var p = new Array(512);
var permutation = [];
for (var i = 0; i < 256; i++) {
permutation.push(seed ? (seed + i) % 256 : i);
}
for (var i = 0; i < 256; i++) {
p[256 + i] = p[i] = permutation[i];
}
var X = Math.floor(x) & 255,
Y = Math.floor(y) & 255,
Z = Math.floor(z) & 255;
x -= Math.floor(x);
y -= Math.floor(y);
z -= Math.floor(z);
var u = fade(x),
v = fade(y),
w = fade(z);
var A = p[X] + Y,
AA = p[A] + Z,
AB = p[A + 1] + Z,
B = p[X + 1] + Y,
BA = p[B] + Z,
BB = p[B + 1] + Z;
return scale(lerp(w, lerp(v, lerp(u, grad(p[AA], x, y, z),
grad(p[BA], x - 1, y, z)),
lerp(u, grad(p[AB], x, y - 1, z),
grad(p[BB], x - 1, y - 1, z))),
lerp(v, lerp(u, grad(p[AA + 1], x, y, z - 1),
grad(p[BA + 1], x - 1, y, z - 1)),
lerp(u, grad(p[AB + 1], x, y - 1, z - 1),
grad(p[BB + 1], x - 1, y - 1, z - 1)))));
}
// Helper function for 2d perlin noise
function perlin2D(x, y, seed) {
return perlinNoise(x, y, 0, seed);
}
var scene = document.getElementById("scene");
var ctx = scene.getContext("2d");
scene.width = window.innerWidth;
scene.height = window.innerHeight;
for (var x = 0; x < scene.height / 3; x++) {
for (var y = 0; y < scene.height / 3; y++) {
var perlinValue = perlin2D(x / 10, y / 10, 384);
ctx.fillStyle = `rgb(${perlinValue * 255}, ${perlinValue * 255}, ${perlinValue * 255})`;
ctx.fillRect(x, y, 1, 1);
}
}
*,
*:before,
*:after {
font-family: roboto, Arial, Helvetica, sans-serif, system-ui;
padding: 0px 0px;
margin: 0px 0px;
box-sizing: border-box;
}
canvas {
display: block;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<canvas id="scene"></canvas>
</body>
</html>
(Note: The way I am drawing the perlin noise is very inefficient and take awhile to load).
Strangely, The 1D perlin noise does work using this function.