Basic Perlin Noise questions

This topic is 2911 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

Recommended Posts

Hello, In order to get a nice terrain (and clouds) I tried to delve into the field of Perlin Noise. Most of my knowledge I got from this article: http://freespace.virgin.net/hugo.elias/models/m_perlin.htm This article has code for a 1 dimensional perlin noise function:
 function Noise1(integer x)
x = (x<<13) ^ x;
return ( 1.0 - ( (x * (x * x * 15731 + 789221) + 1376312589) & 7fffffff) / 1073741824.0);
end function

function SmoothedNoise_1(float x)
return Noise(x)/2  +  Noise(x-1)/4  +  Noise(x+1)/4
end function

function InterpolatedNoise_1(float x)
integer_X    = int(x)
fractional_X = x - integer_X

v1 = SmoothedNoise1(integer_X)
v2 = SmoothedNoise1(integer_X + 1)

return Interpolate(v1 , v2 , fractional_X)
end function

function PerlinNoise_1D(float x)
total = 0
p = persistence
n = Number_Of_Octaves - 1

loop i from 0 to n
frequency = 2^i
amplitude = p^i

total = total + InterpolatedNoisei(x * frequency) * amplitude
end of i loop

end function

To check if I understood everything I'm gonna recap the code in my own words and you please tell me if I am right (or wrong): You have a function Noise1 which returns a pseudo random number in interval [-1,1] for an integer. For example it returns 0.3 for 2, -0.8 for 3 and so on. To get values BETWEEN these integer values you have the function InterpolatedNoise_1. These function returns values in [-1,1] for all fractional values. The main function PerlinNoise_1D does this: It adds n octaves, where each octave has twice the frequency than the previous octave and the amplitude gets smaller. For every octave you use an another InterpolatedNoise function. Becuase if you used the same InterpolateNoise function for every octave you would sample the same "graph" again and again (just with other frequency). Is this correct? My other questions: 2) In the whole document nothing is mentioned about gradients or vectors. In some other papers I have read that Perlin Noise uses gradients in a integer grid. Now I am confused what Perlin Noise is really about. Does the cited article from hugo elias really describe pure Perlin Noise? Is Perlin Noise just "adding up functions with increasing frequency and decreasing amplitude"? 3) I am not sure how I could use Perlin Noise to generate a heightmap. I mean the Perlin Noise function returns me a value for EVERY float. I get a value for 2, for 2.33, for 10433.2 and so on. How is this related to my heightmap resolution?

Share on other sites
Hugo Elias' page does not actually describe perlin noise.

What he calls InterpolatedNoise_1 is generally termed 'value noise', and what he calls PerlinNoise_1D is actually 'fractal brownian motion'.

Share on other sites
I'm certainly no expert here, but it sounds right so far. It doesn't sound like you've read the entire page though, as he goes on to define the necessary function Noise(x, y) as well as the cubic interpolation function for it, which is what you will use for heightmap creation.

Share on other sites
Quote:
 3) I am not sure how I could use Perlin Noise to generate a heightmap. I mean the Perlin Noise function returns me a value for EVERY float. I get a value for 2, for 2.33, for 10433.2 and so on. How is this related to my heightmap resolution?

for (int z = 0; z < length_of_heightmap; z += step){for (int x = 0; x < width_of_heightmap; x += step){int y = getValueFromPerlinNoise(x, z);vector3(x, y, z); // actual heightmap position}}

you meant something like this?
what you get is basically a grid with different heights that correspond to the perlin noise

Share on other sites
Since its the first time for me to deal with this topic I have to believe what I read.
Can anyone confirm swiftcoder statement that hugo elias' doesnt describe perlin noise (though his article is called perlin noise)?

@BLiTZWiNG: I've read the whole article and of course I've seen his code for the 2D case. Though I am still not 100% sure how to use this 2D code for my heightmap generation.
Take a look at projectghost's code. He iterates over the grid and executes the perlin noise at every integer position (x and z are integer values). But when I sample the noise function only at integer positions there would never be some form of interpolation, wouldnt it?

Share on other sites
Quote:
 Original post by schupfCan anyone confirm swiftcoder statement that hugo elias' doesnt describe perlin noise (though his article is called perlin noise)?
That page is single-handedly responsible for the widespread misunderstanding of perlin noise.

Perlin noise (as you mentioned at the outset) is gradient noise, where as Hugo Elias' noise is value noise. The difference is fairly subtle until you take the first derivative (i.e. derive a normal map), when you will see that Perlin/Simplex noise is continuous in its first derivative, while value noise is not.

See Perlin's own presentation for a quick overview of perlin noise.
Quote:
 Take a look at projectghost's code. He iterates over the grid and executes the perlin noise at every integer position (x and z are integer values). But when I sample the noise function only at integer positions there would never be some form of interpolation, wouldnt it?
Generally one would scale those integer coordinates, so as to sample the noise function omn the range [0,1]. You are correct that sampling on an integer grid will look like pure noise, rather than interpolated noise.

Share on other sites
If you use Perlin's gradient noise, sampling on the grid will result in values of 0 across the board, as gradient noise is always 0 at integer boundaries. It might benefit you to write a general-case function to map any given range of noise into your buffer:

Buffer: 2D array of samples, heightfieldWidth/Height: dimensions of BufferNoise(x,y) : Noise functionx1,y1,x2,y2 : Desired mapping rangefor i=0 to Width-1 do  for j=0 to Height-1 do    s = i/(Width-1)    t = j/(Height-1)    nx=x1 + s*(x2-x1)    ny=y1 + t*(y2-y1)    Buffer[j]=Noise(nx,ny)  endend

With a generalized function, you can change the domain by changing (x1,y1) and (x2,y2), and thus change the size of the area of noise that is sampled as the heightfield.

For a good description of both gradient and simplex noise, see this paper.

Share on other sites
Quote:
 Original post by swiftcoderThat page is single-handedly responsible for the widespread misunderstanding of perlin noise.

Oh, I see. It was the first article I've read about Perlin Noise and as a beginner you have to believe what you read. Thanks for clarifying that Hugos article is very misleading.

@JTippetts: I think I've understood your code. The variables x1,y1,x2,y2 define the range in which the value noise function is sampled. The first octaves define the "macro" structure of the terrain. If I want a terrain with only a few big mountains I choose a small range and if I want a terrain with a lot of big mountains I choose a big range. Please tell me if I am wrong.