我试图理解Perlin噪音,但我有两个主要问题:我从我写的函数中得到的值似乎永远不会达到极值附近的值(0,1)。另一个问题是我吐出的图像与Perlin噪声生成的图像并不相似。代码分为几部分。所有代码都按顺序显示。
种子PNRG用于阵列p
的排列,并添加Math.lerp
和ctx.drawPixel
const SEED = [0x12345678, 0x9ABCDEF0, 0x12345678, 0x9ABCDEF0];
const fade = function (t) {
return t * t * t * (t * (t * 6 - 15) + 10);
};
Math.lerp = function (a, b, f) {
return a + fade(f) * (b - a);
};
Math.seededPNRG = function (a, b, c, d) {
return function() {
a >>>= 0; b >>>= 0; c >>>= 0; d >>>= 0;
let t = (a + b) | 0;
a = b ^ b >>> 9;
b = c + (c << 3) | 0;
c = (c << 21 | c >>> 11);
d = d + 1 | 0;
t = t + d | 0;
c = c + t | 0;
return (t >>> 0) / 4294967296;
}
};
CanvasRenderingContext2D.prototype.drawPixel = function (x,y) {
this.fillRect(x,y,1,1);
};
生成数组的排列(Knuth shuffle)
const random = Math.seededPNRG(...SEED);
const p = [];
{
for (let i=0; i<256; i++)
p[i] = i;
let j, t;
for (let i = 0; i < 255; i++) {
j = i + Math.floor(random() * (256 - i));
t = p[i];
p[i] = p[j];
p[j] = t;
}
p.push(...p);
}
实际Perlin噪音发生器
const perlin = function (x, y, z) {
x = x % 512;
y = y % 512;
z = z % 512;
let xi = x & 255, yi = y & 255, zi = z & 255;
let xf = x - Math.floor(x), yf = y - Math.floor(y), zf = z - Math.floor(z);
let u = fade(xf), v = fade(yf), w = fade(zf);
let aaa, aba, aab, abb, baa, bba, bab, bbb;
{
let inc = n => n+1;
aaa = p[p[p[ xi ]+ yi ]+ zi ];
aba = p[p[p[ xi ]+inc(yi)]+ zi ];
aab = p[p[p[ xi ]+ yi ]+inc(zi)];
abb = p[p[p[ xi ]+inc(yi)]+inc(zi)];
baa = p[p[p[inc(xi)]+ yi ]+ zi ];
bba = p[p[p[inc(xi)]+inc(yi)]+ zi ];
bab = p[p[p[inc(xi)]+ yi ]+inc(zi)];
bbb = p[p[p[inc(xi)]+inc(yi)]+inc(zi)];
}
const grad = function (hash, x, y, z) {
let h = hash & 15;
let u = h < 8 ? x : y;
let v;
if (h < 4)
v = y;
else if (h === 12 || h === 14)
v = x;
else v = z;
return (h & 1 === 0 ? u : -u)+(h & 2 === 0 ? v : -v);
};
let x1, x2, y1, y2;
x1 = Math.lerp(
grad(aaa, xf, yf, zf),
grad(baa, xf-1, yf, zf),
u
);
x2 = Math.lerp(
grad(aba, xf, yf-1, zf),
grad(bba, xf-1, yf-1, zf),
u
);
y1 = Math.lerp(x1, x2, v);
x1 = Math.lerp(
grad(aab, xf, yf, zf-1),
grad(bab, xf-1, yf, zf-1),
u
);
x2 = Math.lerp(
grad(abb, xf, yf-1, zf-1),
grad(bbb, xf-1, yf-1, zf-1),
u
);
y2 = Math.lerp(x1,x2,v);
return (Math.lerp(y1, y2, w) + 1) / 2;
};
画图像
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
const height = canvas.height;
const width = canvas.width;
for (let i=100; i<width-200; i++) {
for (let j=100; j<height-200; j++) {
let k = perlin(i/100, j/100,.5);
ctx.fillStyle = "#"+Math.floor(k * 256).toString(16).repeat(3);
ctx.drawPixel(i, j);
}
}
任何提示赞赏。真的不知道问题可能来自哪里。编辑:这是我使用的“指南”:https://flafla2.github.io/2014/08/09/perlinnoise.html