# Procedural Noise

## Intro

A core component of computer graphics, noise functions offer powerful advantages over traditional texture maps, including:

• Infinite resolution - zoom in or out without artifacts such as pixelation or blurriness
• Computed at the bit precision of the graphics hardware. In most cases, this will be 32 bits per pixel, as opposed to the 8 bits you get from an uncompressed texture, or 4/5 bits you get from a DDS compressed texture.
• Fully animatable
• They occupy no storage space on your RAM, VRAM or HDD/SSD

Noise functions can be used in computer graphics for a nearly endless number of uses. On a GPU, you should consider noise functions where texture resolution or bit depth is problematic, or where you want endless/cheap variation. A common technique used in effects shaders is to use one texture to distort the UV lookups of another (water, fire, etc); noise can have particular advantages here, as bit depth and texture compression look particularly bad in these shaders.

## Generating Noise

Here is an example of two copies of a noise function, with one noise distorting the other noise.

While there are multiple techniques to generate procedural noise textures available, they all follow a basic high level principal. First, you generate several pseudo random values for several interpolation points around the pixel being processed, then you interpolate between these values to produce the value for the current pixel.

The first challenge on a GPU is producing the pseudo random numbers; because a GPU has no rand() function. This is actually a deep and complex topic, better covered by some of the referenced material below, but the simplest version (used in this example) uses the sin() function with a high enough frequency that it's results begin to look random.

To generate noise for the current pixel, we need to determine a standard set of points around the pixel, so that the pixels near us will use the same set of points and random numbers for their value. For this, we use the Floor node to give us the integer component of our UV coordinate, and the frac node to give us the fractional part. This if our UV coordinate is 0.5, 1.6, our floor would be 0, 1 and the frac would be 0.5, 0.6.

So, we generate our pseudo random numbers using the floor(uv), floor(uv) + 0,1, floor(uv) + 1,1, and floor(uv) + 1,0. This gives the pseudo random values for a square around out pixel. Then we can lerp between these results with our fractional component to produce a smooth gradient between the values!

If you've reconstructed the shader above to this point, you will have some very blocky looking noise - this is because Lerp provides linear interpolation, which doesn't look that great. What we want is a non-linear interpolation, such as a hermite curve. Luckily, this is pretty easy to add; simply take the fractional part (f) and perform a hermite function on it using the formula f = f * f * (3 - 2 * f);

This will give you an aesthetically pleasing noise.

## Performance

Performance will obviously depend on the platform and scene being drawn, but on a PC computing a single noise function entirely in the shader is between 1.4 and 2 times as slow as using a texture. Note that you can speed this up considerably by using more advance hashing (random) functions, or by replacing the random function with a texture lookup into a specially constructed texture (where the value in each texture channel is equal to the result of one of our four random values).

And here is the final shader in case you'd like to play with it; be warned, it can take a while to load. File:ValueNoise.shader