The documentation for noise() simply says that the function returns a value between 0.0 and 1.0.
By contrast, the documentation for random(n) says that the function returns a value between 0.0 (inclusive) and n (exclusive).
Does noise() include 0.0? 1.0? Both? Neither the p5js nor the Processing reference pages are explicit about the inclusiveness of noise().
Thank you for any information you might have!
Norm
1 Like
That is a good question. Typically the range of values generated by perlin noise is from -1 to 1 rather than that and is actually slightly tighter and inclusive of it’s boundaries: The range of Perlin noise - Digital Freepen
However, the p5.js perlin noise algorithm is obviously slightly different because it generates values from 0 to 1, rather than -1 to 1. Coming up with a mathematical proof is beyond me, but I would speculate that you will never get a value of exactly 0 or 1 from noise()
. Here’s the source code if you’re curious:
const PERLIN_YWRAPB = 4;
const PERLIN_YWRAP = 1 << PERLIN_YWRAPB;
const PERLIN_ZWRAPB = 8;
const PERLIN_ZWRAP = 1 << PERLIN_ZWRAPB;
const PERLIN_SIZE = 4095;
let perlin_octaves = 4; // default to medium smooth
let perlin_amp_falloff = 0.5; // 50% reduction/octave
const scaled_cosine = i => 0.5 * (1.0 - Math.cos(i * Math.PI));
let perlin; // will be initialized lazily by noise() or noiseSeed()
p5.prototype.noise = function(x, y = 0, z = 0) {
if (perlin == null) {
perlin = new Array(PERLIN_SIZE + 1);
for (let i = 0; i < PERLIN_SIZE + 1; i++) {
perlin[i] = Math.random();
}
}
if (x < 0) {
x = -x;
}
if (y < 0) {
y = -y;
}
if (z < 0) {
z = -z;
}
let xi = Math.floor(x),
yi = Math.floor(y),
zi = Math.floor(z);
let xf = x - xi;
let yf = y - yi;
let zf = z - zi;
let rxf, ryf;
let r = 0;
let ampl = 0.5;
let n1, n2, n3;
for (let o = 0; o < perlin_octaves; o++) {
let of = xi + (yi << PERLIN_YWRAPB) + (zi << PERLIN_ZWRAPB);
rxf = scaled_cosine(xf);
ryf = scaled_cosine(yf);
n1 = perlin[of & PERLIN_SIZE];
n1 += rxf * (perlin[(of + 1) & PERLIN_SIZE] - n1);
n2 = perlin[(of + PERLIN_YWRAP) & PERLIN_SIZE];
n2 += rxf * (perlin[(of + PERLIN_YWRAP + 1) & PERLIN_SIZE] - n2);
n1 += ryf * (n2 - n1);
of += PERLIN_ZWRAP;
n2 = perlin[of & PERLIN_SIZE];
n2 += rxf * (perlin[(of + 1) & PERLIN_SIZE] - n2);
n3 = perlin[(of + PERLIN_YWRAP) & PERLIN_SIZE];
n3 += rxf * (perlin[(of + PERLIN_YWRAP + 1) & PERLIN_SIZE] - n3);
n2 += ryf * (n3 - n2);
n1 += scaled_cosine(zf) * (n2 - n1);
r += n1 * ampl;
ampl *= perlin_amp_falloff;
xi <<= 1;
xf *= 2;
yi <<= 1;
yf *= 2;
zi <<= 1;
zf *= 2;
if (xf >= 1.0) {
xi++;
xf--;
}
if (yf >= 1.0) {
yi++;
yf--;
}
if (zf >= 1.0) {
zi++;
zf--;
}
}
return r;
};
3 Likes
Thank you! This information helps a lot.
1 Like