Building a Terrain from functions

Started by David Burnett, December 27, 2006, 02:33:47 PM

Previous topic - Next topic

David Burnett

Note to Planetside, I'd appreciate it if someone goes over this and points out any terminology mistakes, and
better ways of doing things as I worked all this out by guess work.

TG2 offers a number of ways to build terrains, and I'm sure most people here have used a height-field and the Power fractal shader. However for the inner geek there is nothing better than building something from the lowest level possible and that means using functions.

So this is what we are heading for


However this tutorial will build it up bit by bit so you understand why all the bits are there.

Load up TG2, click the Terrain button and delete the height field generator and the height field shader.

Click on the Node Network button. This is where we will be working from now on so resize the node network so that's is big enough to work in.

Looking at the node network you'll see it consists of big rectangles, with little rectangles in that are joined together by lines.
The big coloured boxes are called Groups, I guess the small ones are called nodes, the lines represent the flow of data from one node to another.

The Terrain group is the green box at the top left (unless you've fiddled with the colour scheme), make sure you're still got the
Terrain tab selected,  zoom in into the Terrain Group so that all the text is readable. If you don't know how to do that press the H key while the Node Network is selected and a little piece for text will appear with brief instructions.

There should be a single item in the Terrain Group, called 'Compute Terrain'.
If you just deleted the height field shader with deleting the generator first, then an item called something like 'height field generator 01' will be left around too, if so you can just delete it.

You may want to save now, as the Node Network can crash TG2 if you're not careful.

With the mouse somewhere in the Terrain Group box, right click and the context menu will appear.
Have a look around, there's all kinds of fun toys. The option we're interested in is the 'Create Function' option.
Under this option there are a lot things you've not heard of outside a Maths Class. Again the option we want is 'Noise'
and the noise we want is 'Voronoi 3D diff scalar'. A node called 'Voronoi 3D diff scalar 01' should be added to the Terrain Group.
From now on I'll use a path like way to describe what nodes to add so the last one would be 'Create Function/Noise/Voronoi 3D diff scalar'

Voronoi diagrams split a 2D area, based on the closest point in a set of random points, 'Voronoi 3D diff scalar' does a similar thing in 3D however the value, I think based on what the end result looks like, is the distance to the second closest point subtracted from the distance to the closest point.
At the top left of the TG2 window there's a tree view, if you click on the 'Voronoi 3D diff scalar 01' item in the tree view a preview of the node's output appears. It's all black, but that's because we need to feed co-ordinates into the node to get a value out.

Back to the node network. Right click on the Terrain Group, add  'Create Function/Get/Get Position'
I'm not sure what the difference between the three different 'Get Position' Nodes are, but that one
works in this case. Attach the two nodes buy drag clicking between the bottom triangle on the 'Get Position' node
(Output) and the left hand top triangle on 'Voronoi 3D diff scalar' (Input node). The output preview should now go all
spotty, still not very promising, but at least its a pattern. Above the preview there are + and - buttons, these zoom
out and in respectively, if we zoom in down to 3 m you'll to see that we really do have a pattern, its just too small.

So how do we get the pattern up to a reasonable size, each cell is around 1- 2 metres in size, to make it look interesting
using the default camera they need to be 1-2 km.  One way to do it, is to make the random points further apart, but we can't
do that so we need to scale the noise by shrinking the co-ordinates. Add two new nodes, 'Create Function/Multiply/Multiply vector' and 'Create Function/Constant/Constant vector'. 'Multiply vector' takes a vector and multiples it by another vector. If you are not big of Maths just think of vector as a group of values, so for a position there are 3 numbers, the X, Y and Z co-ordinates. a single value one its own is called a scalar.

Double click on 'Constant vector 01' and the setting dialogue should pop up. There are three text boxes waiting for
three values, set them all to 0.001 and close the dialogue.

Connect the 'Constant vector 01' Output to one of the 'Multiply vector' inputs.
Now we're going to connect 'Get Position 01' to the other 'Multiply vector' input. You can do this by drag clicking
from the 'Voronoi 3D diff scalar' input to the 'Multiply vector' input, it you do it right the connection line should
move with the mouse.

Finally connect the 'Multiply vector' output to the left hand 'Voronoi 3D diff scalar' input and your preview will go all
grey. Zoom the preview out to 1 - 3 km and the pattern should be back. You can play with the values in the 'Constant vector'
now and see what different values in the different boxes do.

Now you may want to know why we multiplied by 0.001 rather than divided by 1000. Multiplication is faster to do than division
even for computers if you multiply by a fraction instead of dividing things will render that bit quicker.   
Oh and if you select 'Constant scalar' for the input to the 'Multiply vector' node TG2 does the right thing and multiplies
each of the other input values by the scalar value.

Now we need to apply the pattern to our planet. This step is also one that I've had to guess at. After trying a few ways
of connecting 'Voronoi 3D diff scalar' to 'Compute Terrain' I found out that bridging them with a displacement shader
did the right thing.  Add 'Create Shader/Surface Shader/Displacement Shader' to the node network
Connect 'Voronoi 3D diff scalar' output to 'Displacement Shader 01' function input (the right hand input)
and 'Displacement Shader 01' output  to 'Compute Terrain' input and we've nearly finished.

Click on the renderers button and wait for the 3D preview to render, its still flat. Double click
on 'Displacement Shader 01' and change the Displacement Multiplier, change it to 200 and finally we have
a Voronoi shaped terrain, looking something like this.



VERY! useful.  thx for posting, and for the research effort :)



You can bypass the multiply vector all together by putting the get position on the input node (left connector)  and put the constant vector on the scale node (middle connector) of the voronoi scalar.


Thanks so much.  I think I understand why everything needs to be there to make this work, but (and I'm sorry for the dumb question) I don't understand the "Get position" node.  I know you need to start with something, but what is it "getting it's position" from?  Is it just outputting random numbers?  Why does the Voronoi scalar need this?


took the liberty of taking this one more step:

unfortunately no one actually seems interested.  personally i find this to be very powerful and full of control.  maybe in the future, a talented, and generous, coder will share with us some fractals other than perlin and voronoi. 

windjammer, if i'm not mistaken, get position probably defaults to 0,0,0, unless something else is fed into it.  i think it's like you said, it's just starting somewhere.

David Burnett

The truth is I'm not really sure what the position is, but I'm guessing that by default Get Position provides the co-ordinates in 3D space of the point on the terrain that TG2 is attempting to displace. From what I understand TG2 co-ordinates are linear and based on a single origin, i.e one big grid rather than different grids for the different planets in a scene, or longitude and latitude co-ordinates.

All the noises in TG2 take a 3D co-ordinate and calculate a value based on the individual numbers. The displacement shader then takes that value moves that point on the planet by the value, for the maths inclined it moves it along the normal for that point by that amount, for the non maths people imagine the spot under your feet being moved straight up and remember that my straight up in England is different to some one standing in Australia.  TG2 then moves to the next point and does the same with the new co-ordinates. If 'Get Position' was supplying a default value i.e. 0,0,0 then you would not get the same displacement all over.

David Burnett

Quote from: MooseDog on December 29, 2006, 02:26:33 PM
maybe in the future, a talented, and generous, coder will share with us some fractals other than perlin and voronoi. 

I'm surprised the Perlin node was dumbed down so much, a full on version of the Perlin would have made
function terrains so much more fun.



I like to experiment more with the node network. Unfortunately I don't go into the individual node functions too often...largely because
there arn't too many guides around.

...So thanks


In the last step, it didnt' work for me to connect it to the compute terrain 'input', but it did work when i connected it to the 'function'.  Then I had to zoom out to see the changes.

Great tutorial!


Way to complicated for my stupid brain to handle. I think I'll just stick to 3ds Max.


Awesome tute...dunno how I missed doing this, maybe cuz the  pyramid was somethinfg I wasn't interested in. Much rather hav a pyramid object I can move with 'handles', but this is sorta eye opening...many to part 3
something borrowed,
something Blue.
Ring out the Old.
Bring in the New
Bobby Stahr, Paracosmologist


wooohooo..and in terragen 1..all you have to do is dig holes in the terrain with the terrain sculptor tool..not as sophisticated I admit but a damn sight easier..and yes I agree 3D max..and any other 3D progs will still arrive at your end result with out all the BS that goes with it..ok..I have yelled and screamed but I have only had TG2 for 3 days...have mercy pliz....


This is exactly what I was looking for. Thank you very much.