A function only Landscape : Part Three - A Detour into Perlin's Noise

Started by David Burnett, March 25, 2007, 02:28:39 PM

Previous topic - Next topic

David Burnett

Ken Perlin's noise function forms the basis of much that is good about Terrain Generators, from
Ken Musgrave's early images to the quite possibly the last thing you rendered in TG2.

At its heart it's very simple, it just interpolates between a grid of random vectors, and
it creates noise that looks like this.

Figure 1.

Not very terrain like is it. To make it more interesting Perlin introduced Turbulence.
Given a function perlin(x, y, z) we then add 0.5 * perlin (x*2.0, y*2.0, z*2.0)
then 0.25 * perlin (x*4.0, y*4.0, z*4.0) and so on....

value =
   perlin(x, y, z)  +
   0.5     * perlin (x*2.0,  y*2.0,  z*2.0) +
        0.25    * perlin (x*4.0,  y*4.0,  z*4.0) +
        0.125   * perlin (x*8.0,  y*8.0,  z*8.0) +
        0.0625 * perlin (x*16.0, y*16.0, z*16.0)

Each line is called an octave, a word you might have seen on the power fractal shader.
The effect of each octave is to shrink the grid of random vectors, adding more detail to
the noise. This is why decreasing the smallest scale on the Power Fractal Shader increases the number of
Noise Octaves and vice versa, to add more detail you need to add more octaves.

Figure 2.

The Perlin Function in T2TP is very simple, there's no turbulence to make things interesting
unless you willing to manually create a node tree to do it. This however does not make it totally unless,
and I'll use it twice for the function only image we're creating.

Let's a see see what we can do with it first.

Start with a new TGD, delete the height field shader and generator.
Add the Displacement Shader and join it to Compute Terrain.

Add the Perlin noise function, Create Function/Noise/Perlin 3D scalar
Connect it to the Displacement Shader function input [the right hand input]

The 3D preview will still be flat, we need to feed it co-ordinates.

Add a Get Position function
Connect it the the left hand input (input node) on the Perlin 3D scalar function.

It still looks flat, but you may notice some patterning. The problem is the camera is
too high, we start a 1000 metres up, bring into down to 10 metres, and volia bumps
on the ground. If you move your cursor over the preview you'll notice that the bumps
are around metre apart. This gives a degree of predictabilty and makes it useful for distorting things.
It's also the reason you need turbulence to make interesting terrains.

The Perlin 3D scalar function has two other inputs, the first is scale. This scales the co-ordinates going into the noise.
The second is seed, which changed the random value generation, change it an you get another variation on the same noise.

Add a Get Constant Scalar function. Set the value to 2.
Attach it to the scale input of the  Perlin 3D scalar function

The distance between peaks should now be around 2 metres. Change the constant to 10, the peaks are now 10 metres apart,
and the terrian has a more gentle look to it.

Scale does not have to be a constant, lets have some fun.

Move the Render camera to 0,10,0 with a rotation of -90,0,0 which is looking straight down.
Disconnect the Constant from the scale input.
Add a Sin function (Get Function/Trig/Sin Scalar).
Connect the Sin function to the scale input of the Perlin 3D scalar.
Connect the Get Position function  to the Sin node as well as the Perlin 3D scalar node.

If you select the Sin function you'll see you get a series of rings in the noise preview.

In the 3D preview the peaks are close together where the Sin function returns small values,
and further part where the Sin function returns larger values. A rendered version looks like this...

Figure 3.

Another common use for Perlin's Noise is to distort things. There's a number of ways to do this. We could
simply add the noise to roughen things up, add the noise to co-orinates going into other functions or shaders
or to simply add the noise to other parameters into into functions.

Lets start from scratch.

Add a Get Position Function, an X to Scalar Function, and a Sin scalar function, and join them together
in that order.
Add a Displacement shader and join the Sin function to the function input of the Displacement shader and the output
of ther Displacement to the Compute Terrain as usual.
Change the Camera to position 0,25,0 with a rotation of -90,0,0.
Change the Sun to a angle of 45.

You should have a ploughed field look. Let's add some noise to the X co-ordinate.

Add a Perlin 3D scalar and an Add Scalar function.
Connect the Get Position to the Perlin 3D scalar, The Perlin 3D Scalar and the X to Scalar to the Add Scalar.
Connect the Add Scalar node to the Sin Scalar node.

There should now be indentations now (Fig 4 'a') 

Add a Constant Scalar, set to 20, and connect it to the Scale input of the Perlin 3D scalar.

The smoothnes is back, but you may notice some subtle distortions, the poughing is not as straight as
it used to be. Set the Camera to 0,100,0 to see it a little better. (Fig 4 'b')

Perlin noise tends to give values between -1.0 and +1.0 so lets increase those and see what happens.

Add a Mulitply Scalar. Connect the Perlin 3D scalar and the Constant Scalar to the Multiply scalar.
Use the Multiply Scalar output to replace the Perlin 3D Scalar input to the Add Scalar.

That distortion is not so subtle now is it (Fig 4 'c') :-)

Now lets change things around.

Delete the Multiply Scalar node and the Constant Scalar.
Connect the X to Scalar node back directly to the Sin Scalar node, and feed the Sin Scalar node
and Perlin 3D Scalar node into the Add Node. The Add Node now feeds into the Displacemet Shader.

This looks like the original distored render but is subletly different (Fig 4 'd').

Figure 4.


Hi, I have attempted to add the sin function to the scale input of the perlin noise node and the result is a black preview.  Any ideas what I am overlooking?  The constant node produces the expected result.  Thanks for an awesome tutorial.

David Burnett

Hi, you didn't overlook anything, I did. The Get Position Node needs connecting to the Sin node, as well as the Perlin Node. I've corrected the tutorial. Thanks, Dave


A small error. I think that you should connect the output of the Perlin noise to the right input of the Displacement shader!

David Burnett


The tutor is right, nothing is missing ,i've stopped at fig 4-c that what iwas looking for ... thank
Le peu que je sais, c'est à mon ignorance que je le dois.


hey, I followed the steps to achieve image 4a (Get Position => Perlin 3D Scalar => Add Scalar / X to scalar => Add Scalar / Add scalar => Sin scalar ) but I dont get the same image. Am I over looking something? =)

David Burnett

I've noticed that in TG 2.1 you need the camera slightly higher, around 12 should do it, or you get a black image for a render even though the 3D preview looks fine.