Perlin Noise and TurbulenceWritten by Paul Bourke
It is not uncommon in computer graphics and modelling to want to use a random function to make imagery or geometry appear more natural looking. The real world is not perfectly smooth nor does it move or change in regular ways. The random function found in the maths libraries of most programming languages aren't always suitable, the main reason is because they result in a discontinuous function. The problem then is to dream up a random/noisy function that changes "smoothly". It turns out that there are other desirable characteristics such as it being defined everywhere (both at large scales and at very small scales) and for it to be band limited, at least in a controllable way.
The most famous practical solution to this problem came from Ken Perlin back in the 1980's. His techniques have found their way in one form or another into many rendering packages both free and commercial, it has also found its way into hardware such as the MMX chip set. At the bottom of this document I've included the original (almost) version of the C code as released by Ken Perlin and on which most of the examples in the document are based.
The basic idea is to create a seeded random number series and smoothly interpolate between the terms in the series, filling-in the gaps if you like. There are a number of ways of doing this and the details of the particular method used by Perlin need not be discussed here. Perlin noise can be defined in any dimension, most common dimensions are 1 to 4. The first 3 of these will be illustrated and discussed below.1 Dimensional
A common technique is to
create 1/fn noise which is known to occur often in natural
processes. An approximation to this is to add suitably scaled harmonics
of this basic noise function.
For the rest of this discussion the Perlin noise functions will be
referred to as Noise(x) of a variable x which may
a vector in
1, 2, 3 or higher dimension. This function will return a real (scalar) value.
A harmonic will be Noise(b x) where "b" is some positive number
greater than 1, most commonly it will be powers of 2.
While the Noise() functions can be used by themselves, a more common
approach is to create a weighted sum of a number of harmonics of
these functions. These will be refered to as NOISE(x)
and can be defined as
Where N is typically between 6 and 10. The parameter "a" controls how rough the final NOISE() function will be. Small values of "a", eg: 1, give very rough functions, larger values give smoother functions. While this is the standard form in practice it isn't uncommon for the terms ai and bi to be replaced by arbitrary values for each i.
The following shows increasing harmonics of 1 dimensional Perlin noise along with the sum of the first 8 harmonics at the bottom. In this case a and b are both equal to 2. Note that since in practice we only ever add a limited number of harmonics, if we zoom into this function sufficiently it will become smooth.
The following show the same progression but in two dimensions. This is also a good example of why one doesn't have to sum to large values of N, after the 4th harmonic the values are less than the resolution of a grey scale image both in terms of spatial resolution and the resolution of 8 bit grey scale.
As earlier, a and b are both set to 2 but note that there are an infinite number of ways these harmonics could be added together to create different effects. For example, if in the above case one wanted more of the second harmonic then the scaling of that can be increased. While the design of a particular image/texture isn't difficult it does take some practice to become proficient.3 Dimensional
Perlin noise can be created in 3D and higher dimensions, unfortunately it is harder to visualise the result in the same way as the earlier dimensions. One isosurface of the first two harmonics are shown below but it hardly tells the whole story since each point in space has a value assigned to it.
Perhaps the most common use of 3D Perlin noise is generating volumetric textures, that is, textures that can be evaluated at any point in space instead of just on the surface. There are a number of reasons why this is desirable.
In order to effectively map the values returned from the noise functions one needs to know the range of values and the distribution of values returned. The original functions and therefore the ones presented here both have Gaussian like distributions centered on the origin. Noise() returns values between about -0.7 and 0.7 while NOISE() returns values potentially between -1 and 1. The two distributions are shown below.
The possibilities are endless, enjoy experimenting.
Donald Hearn and M. Pauline Baker
David Ebert, et al (Chapter by Ken Perlin)
Perlin, K., Hoffert, E.