Explaining Noise

In this article I am going explain what procedural noise is (sorta) and demonstrate some great ways to use it in your games!

What is Noise?

Noise is basically smooth randomness. Random number functions will return random values in a range of your choosing, while with noise functions, you provide a coordinate into the noise space (whether it be 1D, 2D, 3D, 4D, or higher!) and it will return a random value where nearby sampled values will have a similar results.

Now in this tutorial I am not going to cover how these functions work (because I still don't really understand), but more how to use them to create awesome effects in your games!

Fractal Noise

Fractal Noise is made by combining samples of noise with increasing frequencies and decreasing amplitudes. Each successive noise function you add is called an octave. Persistence is what you multiply the amplitude by each time, and lacunarity is what you multiply the frequency by each time. In the following example there are 6 octaves and the lacunarity is set to 2, but it demonstrates the effect of playing with the persistence levels of the function. Also I stole this from somewhere obviously, but the website got taken down so I don't feel that bad.

Frequency 1 2 4 8 16 32
  
Persistence = 1/4 + + + + + =
Amplitude: 1 1/4 1/16 1/64 1/256 1/1024 result
  
Persistence = 1/2 + + + + + =
Amplitude: 1 1/2 1/4 1/8 1/16 1/32 result
  
Persistence = 1 / root2 + + + + + =
Amplitude: 1 1/1.414 1/2 1/2.828 1/4 1/5.656 result
  
Persistence = 1 + + + + + =
Amplitude: 1 1 1 1 1 1 result


Here is a similar example of fractal noise, but in 2D. Each successive iteration the frequency increases and the amplitude decreases, as it goes from left to right, finally combining into a nice fractal result.

+ + + + + =

The actual code for this is pretty simple, here is what it looks like in HLSL:

// good defaults: amplitude 1.0, persistence 0.5, lacunarity 2.0
float fbm(float3 x, int octaves, float frequency, float amplitude, float persistence, float lacunarity) {
    float sum = 0.0;
    for (int i = 0; i < octaves; i++) {
        sum += snoise(x * frequency) * amplitude;
        amplitude *= persistence;
        frequency *= lacunarity;
    }
    return sum;
}

fbm stands for fractal brownian motion, another name for this. And snoise is where you call the original noise function you want to use for this. You can combine any sort of noise this way for different effects. There's a bunch of different ways to write these fractal functions, like you can have the value clamped at the end, or you can have fractional octave values if you want to get super detailed, you can also apply random offsets at each octave to further purify artifacts, but it looks pretty good as is.

References and Additional Reading

The book of shaders: Noise
The book of shaders: Fractal Brownian Motion