Understanding 2D Perlin noise

Hello,

I know this topic was discussed before here, but I would like to understand, how Perlin Noise in 2D is implemented in Processing, so that I can use it consciously.

In other topics it was mentioned before, that Perlin Noise is repeating after certain numbers:

On this side it was mentioned Perlin noise repeats every 256 units in each coordinate direction:
stackoverflow.x/questions/9577259/perlin-noise-function-returning-same-results-for-different-inputs/9577407#9577407
x= com
However, that seems to be for Java.

When I map the 2D Perlin noise(i,j) in Processing (picture 1 below) I see repetition every 16 points in x direction but there is an offset by one y in y direction. For y there is repetition every 256 points.
That makes me believe that in Processing only 16x256 tiles are created for 2D noise. Is that correct?

Often it is mentioned that using smaller values “fixes” the issue of repetition. But that is not really the case. Zooming into a part of the Perlin function (by using smaller numbers) just reduces the part of the Perlin noise I can see on the screen. So when I have 4 repetitions when using i,j to create noise, then, when using i/2, j/2 instead, I get 2 repetitions (picture 2). At the same time the landscape gets flatter, because now 4 points have the same value that had one point before. However, when I adjust my point size (picture 3) I get the features back but the repetitions as well, so it is really irrelevant, what numbers I am using to create the noise.
Large numbers should not help as well, because if I multiply by any number I still have only 16/256 numbers available.

It is also often mentioned that changing the octave weight and frequency would change anything.
However, based on this website:
blog.hirnschall.x/perlin-noise/
x=net

Perlin noise is a fractal function, so the same function is summed up with different frequencies, so weighing smaller octaves stronger will just create the same function with a different frequency, so it does not necessarily solve the problem, when I zoom in with smaller values and increase higher frequency octaves to get more features I will end up with the same problem again.

Is my assumption correct, that Processing uses 16x256 grids for 2D Perlin noise?
Is there a reason for the offset by 1 point in y direction?
If that is true wouldn’t be the only solution to get non-repeating pattern to randomize the input i and j, so that every step i+1 andj+1 is different in size from the previous one?

Picture 1:

Picture 2:
I can only put one picture in.

Picture 3:
I can only put one picture in.

Check out Sebastian Lagues playlist for unity.

The language is similar enough to java for you to be able to make use of the code providing you understand what to change, and he touches on most of the things you would want to do with perlin noise including dealing with the boundaries.

There is a lot to take in so take your time.

Hi Paul,

thanks for sharing the videos. I watched episodes 1-3, which are showing the use of Perlin noise, the rest was more optimizing the terrain.

Here is what I got out of this:

He mentions in the second video that integer value give you always the same value. I have heard that in other videos as well but for Processing that is not right (might be different in Unity).
I created my picture above with integers and it does not create a flat surface. Even when reducing to a single octave, there is no flat surface.

At 5:35 in the third video he shows the effect of octaves, persistence and lacunarity, especially when he switches the latter two. What you see is that the blurriness is changing with persistence, adding more or less granularity and that the granularity is shifting in the xy directions with changing lacunarity.
However the underlaying black structure stays the same.
I see the same, when changing the number of octaves with noiseDetail(). The long range structure and with that the pattern repetition stays the same, because it is defined by the 1st octave while the three parameters only add detail in the short range.

What he finally does to get a random distribution (without explaining why that is necessary) is to create an octave offset, which is created randomly.

The final variable he enters now in the noise function looks like this:
i = x/scale*frequency + offset

x is the coordinates 1++
Scale is larger 1, in his example 27 and the frequency/lacunarity is 0.5, so these three variables together are smaller then 1. The offset is randomly generated from -10000 to 10000, so it totally dominates the variables that are entered in the noise function as if I would just add random x and y to it. Not sure why one should go through all the optimization with scale and lacunarity, when I then add a huge random number to wipe out the details.

Don’t get me wrong I love the terrain he creates. It looks really cool but there is very little to learn from a Perlin noise perspective.

Is still would like to know if the Perlin noise function in Processing is limited to 256 steps and therefore repeats beyond that.

The repetition after 16 steps in x direction looks like a bad glitch. I learned that when creating a 2D Perlin noise function from scratch you have to check for unwanted regularity. Not sure, if that was missed in the implementation. Maybe there are other explanations?

You can take a look at Processing’s implementation here.

Thank you. I will take a look at it.
Just to confirm the values, which comes out of the noise function, are the same for points, which look the same in my picture.
For noise(i,j256) I get vertical lines, that means all y values are the same, for noise(i256*16,j) I get horizontal lines, that means all x values are the same.

I am not sure, if anybody, except me, is interested in it, but I will report here, what I learned going through the file.
Any comments, either confirmation or disapproval, are appreciated, because I am just going with what I am seeing and I never learned Java, so I might have missed things.

In general the code works as follows:

An array of random 4096 random numbers is created.
If you call your noise function with the values x, y, z, these are taken and their integer value separated from the decimal values.
The integer values are used to create a number, which acts as index number for the random number array.
It is calculated with x + 16 * y + 256 * z.
This way the 4096 random numbers are distributed over cube of 16x16x16 coordinates.
The calculated index is then used to get 8 numbers around the coordinate and interpolate with a cosine between them using the decimal values of x, y, z as input to create the return value.

Pattern repetition:
For 2D noise the same equation is used, that means that only an area of 16x16 creates unique values, everything else is a repetition. For x,y =10,10 or 26,9, 42,8 the same index number of 170 is calculated. That explains the repetition after x+16 and y-1. The repetition after 256 * y and 256 * 16 * x is simply due to reaching the maximum of the random number array. You can expand your 16x16 by scaling down, e.g. by x * 0.05 but that just gives you a cosine interpolation as noise, not real noise. It would be nice, if there would be a different case, that when z is not assigned a value, x + 64 * y is used to get at least a 64x64 area before the noise values are repeated.

In general, this type of noise is value noise (random number lattice with cosine interpolation) and not Perlin Noise(which is a gradient noise). So it does not follow the Perlin implementation as mentioned in the reference.

I would also say, that the octave implementation is not ideal. With every octave the coordinates are doubled. I think it would be better to half them with every octave. This way they would create more detail in the short-range as they should. And it would be nice to be able to set this frequency.

On a side note: The modulo in the cosine function is not necessary. i * PI is always smaller PI and therefore the modulo always returns the i * PI value.

4 Likes