Typically when generating seamless Simplex noise the strategy is to go to 4-dimensions (a strategy which has worked well for me in the past when using 2-D Simplex), however I am trying to generate a seamless GIF loop using 1-D simplex noise (only interested in the noise specifying the Y-value in a line graph).
I'm curious if I'm either misunderstanding how to make things seamless in 1-D or if I possibly have an error in logic here. Basically, I'm generating a 2-D array, where the first dimension is the Z axis and the second dimension is a list of the points (x-y values) for that Z. I iterate over each z and simply plot each vertex in turn.
What I notice is that, when I hit my maximum Z-value, there is a clear jump indicating that I'm doing something wrong (not seamless).
I'm using the fast-simplex-noise
library (I like it better than P5's built-in noise
function) and specify it as so:
function setup() {
let freq = 0.005;
let octaves = 14;
_noise = new FastSimplexNoise({ frequency: freq, octaves: octaves });
// specify the points:
points = [];
step = 0;
maxSteps = 150;
let r = 1.0;
for (let z = 0; z < maxSteps; z++) {
let t = (1.0 * z) / maxSteps;
points[z] = [];
for (let x = o + 10; x < width - o - 10; x++) {
let _n = _noise.get4DNoise(x, z, r*cos(TWO_PI*t), r*sin(TWO_PI*t));
let _y = height/2 + 250*_n;
points[i].push({ x: x, y: _y });
}
}
}
In the draw
function I simply iterate over each vertex in the points
list and keep track of the current z
value per-draw iteration.
It sounds like you are expecting the change in noise values when jumping from z = maxSteps - 1
to z = 0
to be small. However this is not going to be the case when you specify z
as the second parameter to get4DNoise
because while the third and fourth dimensions will be quite close to each other for these two values of z
(thanks to the use of sine and cosine), the second will differ by maxSteps - 1
. This begs the question: why are you using 4D noise at all? You are trying to vary y
randomly such that it is smoothly changing for changes in either z
or x
and also looping back around. In order to achieve this you simply need to sample noise values along a straight line in 3d space moving around a cylinder.
Here's a visualization of your noise algorithm, and a very similar one that only uses 3d noise. Notice how the cylinder on the left has a seam, but the one on the right has no seam:
const maxSteps = 100;
const scaleFactor = 20;
let texture1;
let texture2;
let _noise;
let cam;
function setup() {
let size = Math.min(windowWidth, windowHeight);
createCanvas(size, size, WEBGL);
noStroke();
cam = createCamera();
cam.setPosition(0, 0, 500);
cam.lookAt(0, 0, 0);
_noise = new FastSimplexNoise({
frequency: 0.005,
octaves: 14
});
texture1 = makeTexture(true);
texture2 = makeTexture(false);
}
function doubleClicked() {
console.log(cam);
}
function makeTexture(use4d) {
let points = [];
// Using an r of 1.0 covers a very small and unchanging region of noise space
let r = use4d ? 1.0 : maxSteps / 2;
for (let z = 0; z < maxSteps; z++) {
let t = z / maxSteps;
points[z] = [];
for (let x = 0; x < maxSteps; x++) {
let _n =
use4d ?
_noise.get4DNoise(x, z, r * cos(TWO_PI * t), r * sin(TWO_PI * t)) :
_noise.get3DNoise(x, r * cos(TWO_PI * t), r * sin(TWO_PI * t));
let _y = 250 * _n;
points[z].push({
x: x,
y: _y
});
}
}
let g = createGraphics(maxSteps, maxSteps);
for (let z = 0; z < maxSteps; z++) {
for (let x = 0; x < maxSteps; x++) {
// x == points[z][x].x
// Using z as x and x as y because of the texture coordinate layout for cylinders
g.set(
z, x,
// Shifting y values upward because they tend to be small resulting in a dark texture
map(points[z][x].y, 0, 250, 100, 300)
);
}
}
// required after set()?
g.updatePixels();
return g;
}
function draw() {
background(255);
orbitControl(2, 1, 0.1);
push();
translate(-150, 0, 0);
texture(texture1);
cylinder(100, 200);
pop();
push();
translate(150, 0, 0);
texture(texture2);
cylinder(100, 200);
pop();
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/fast-simplex-noise.js"></script>