A function only landscape

Started by David Burnett, February 18, 2007, 08:19:57 AM

Previous topic - Next topic

David Burnett

This is the TGD file for the image posted at http://forums.planetside.co.uk/index.php?topic=828.0
It's an attempt to create a reasonable image solely using functions for the terrain (plus the requisite displacement shader)

Eventually, if there is any interest, my intentions are to break this down and post a tutorial to supplement my older tutorial
@ http://forums.planetside.co.uk/index.php?topic=195 

Dave

Edit: Ooops, this time I've actually attached the file

Will

Thanks :)

EDIT: um where is it?

Regards,

Will
The world is round... so you have to use spherical projection.

groverwa

Gday Dave

Thanks for tgd - very interesting - had a bit of a play already - see attachment

Yes, please do make a tutorial of your tgd/ functions, explain what each part does and why and what will happen if constants for example are changed

Mike

David Burnett

To make a pyramid using a function, we need an algorithm that represents a pyramid.

So lets look at a rough plan of an upside down pyramid.

[attachimg=2]

The 'height' of the upside down pyramid at any point is highest distance between the x or y co-ordinate
and the y or x axis repectively, i.e. z = max(x, y).
We then limit the size of the pyramid by stopping the measurements at a
maximum value of x and y, oh and we need to turn it the right way around.

Right let fire up TGTP and don't forget to save often.

So lets see how we make a pyramid. First we need to extract the 'x' and 'y' values.
In TG2 the co-ordinate system has X and Z as the co-ordinates on the plane and Y is up - down.
so what we really need is the X and Z co-ordinates.

To get the current co-ordinates we use the Get Position Function (Create Function/Get/Get Position).
To extract the individual ordinates there are three functions in Create Function/Convert

  • X to scalar
  • Y to scalar
  • Z to scalar

These take the in a vertex, and output the individual ordinates as scalar values.
We will use 'X to scalar' and 'Z to scalar' feeding Get Position into both.

We want the distance between the ordinate and the adjacent axis, which effectively mean we want to
throw away the ordinates sign. This is called the absolute value, and the function that gets the absolute value
for a scalar is Create Function/Clamp/Abs scalar. There also a Create Function/Clamp/Abs vector that we could use
on the output from Get Position, but I'm going to change things up there later.  So add two Create Function/Clamp/Abs vector nodes and attach one to 'X to scalar' and the other to 'Z to scalar', call them Absolute X and Absolute Z

So now I know the distances, I need to pick the maximum distance. There is no function called max though, what this is is the conditional scalar (Create Function/Conditional scalar).  This function asks if...then...else.... If has 4 inputs and a setting.


  • The first input (Input node) is the left hand side of the condition.
  • The setting is the condition (is greater than, is less than etc.).
  • The second input (Comparison value) is the right hand side of the condition.
  • The third input (If result) is the value output if the condition is true.
  • The final input (Else result) is the value output is the the condition is false.

The condition we want is 'if x is greater than z then x else z' so the feed from Absolute X goes in Input Node and If result, Absolute Z goes in Comparison value and Else result. The Condition is set to greater than.

Our upside down pyramid currently goes on forever, so we need to clamp it.
There are a lot of clamping functions, you can find them in Create Function/Clamp
We've already used Abs scalar. Now we are going to use a clamping functions,


  • Clamp 0   means that any value less than 0 is forced to zero
  • Clamp 0 1 means that any value less than 0 is forced to zero, values greater than 1 are forced to 1
  • Clamp     clamps between the two input values

We need to clamp between 0 and our max pyramid height. So we need two constants
(Create Function/Constant/Constant scalar) one set to Zero and the other to our max pyramid height.
Add a 'Clamp scalar' function and connect the zero constant to min and the max pyramid height to max.
Connect the Conditional Scalar to the Clamp scalar input. 

Finally we need to turn our upside pyramid the right way around, this is easy. Our pyramid goes from 0 to x, we need it to go from x to 0., and we do this by subtracting the height so far from the max height.

Add a subtract function (Create Function/Subtract/Subtract scalar)  attach the max pyramid height we connected to the clamp node to the left hand input node, and then connect the clamp node to the right hand input node  (Input 2).

We now have a pyramid, but we need to use it to change the landscape. To do this add a Displacement shader, connect it to the compute terrain node in the Terrain Group. Finally attach the Subtraction Function to the Displacement Shader Function Input Node.

You should have something like this....

[attachimg=1]

Now, depending on how big your pyramid is, the camera is probably in the middle of it, so to 'find' it set the camera to 0,2xmax pyramid height,0 and the rotation to -90,0,0 and your pyramid should be right below you.



groverwa

Gday Dave

Thanks for the tutorial - much appreciated

Mike

old_blaggard

Great job!  This is going to be very useful.  Thanks.
http://www.terragen.org - A great Terragen resource with models, contests, galleries, and forums.

Tangled-Universe

Thanks for sharing us insight in the function nodes and your workflow, very useful!

Martin

David Burnett

#7
Linear dunes.

To add linear dunes to a scene we again need an algorithm.

The idealised cross section of a dune looks like this...

[attachimg=1]

It has a straight line rise and then a concave fall.
The formula for a straight line is y = mx + c where m is the gradient and c is the position
on the y-axis where the line crosses the axis.

Lot of different algorithms could give us the concave part of the equation, but I want a simple one,
plus my maths is not that hot this days, so its back to my 'O'-level Maths.
The first thing that came to mind was a quadratic equation, most school kids probably know these, but as a refresher its the
ax2 + bx + c type of equation that you get to try an resolve into (dx + e)(fx + g)
e.g.   2x2 + 5x + 2 = (2x + 1)(x + 2) . Plotting one gives a line that looks like a U or a V.

The equations I picked where y = 0.2x and y = x2 - 2x + 1 which conveniently resolves to (x-1)(x-1)

If you plot these two equations you get.

[attachimg=2]

If we just use the lowest value of the two plot lines for any value of x we can see something which looks like our cross section
between x = 0 and x = 1. You may notice that I've gone for a quadratic equations of the form
(ax - a)(ax - a) as I know that at x = 1 the y value will be 0. If you increase 'a' from 1.0 to 2.0 you get a steeper concave slope.
So using (2x-2)(2x-2) instead you get this...

[attachimg=3]

I'll add a way of adjusting this easily in the node tree so you can play with the values
later and pick a values that gives the nicest looking dunes.

So the algorithm we end up with is y = min(0.2x, (x-1)(x-1)) which looks like this...

[attachimg=5]

As you can see the sand dune cross section  sits between x = 0 and x = 1, outside of those
values we basically have a big slope, so we'll need to restrict the x values somehow. 

Now we need to use that algorithm in TG2. First we need the x co-ordinate and we've been there before.


  • Add a Get Position node and X to Scalar node.


To restrict the x value to between 0 and 1 we could use clamp, but there's a more interesting option
the Modulo Scalar node (Get Function/Divide/Modulo Scalar). Modulo return the reminder from a division
so 3.5 modulo 3.0 returns 0.5 . If we use 1.0 then we restrict the value between 0 and 1. It also has the
added bonus of repeating, so 0.5 mod 1 is 0.5, 1.5 mod 1 is 0.5, so we get a linear dune for every unit where as
Clamp Scalar would have given just one dune. 

Add a Modulo Scalar and a Constant Scalar set to 1.0.
Connect the X to Scalar node to the Modulo Scalar left hand side input (Input node) and the Constant Scalar to the right hand side input (Input 2).

The rest is simple maths, first we need to multiple x by 0.2. The next new node in the tutorial is
the Multiply Scalar node (Get Function/Multiply/Multiply Scalar) it multiplies two scalar values. 


  • Add a Multiply Scalar
  • Feed the Modulo Scalar into one input.
  • Add a Constant Scalar node set to 0.2 to the other multiply input node.
  • Name this 'Linear' so we can refer to it later.

(x-1)(x-1) breaks down to two steps,subtract 1 from x, then multiply the result by itself. However
I'm going to use three steps, multiply x by 1, subtract 1, then multiply the result by itself.


  • Add a Multiply scalar node and a Constant Scalar Node set to 1.0 .

The next new node is the Subtract Scalar node (Get Function/Subtract/Subtract Scalar), like the multiply node does exactly
what it sounds like and subtracts two scalars.


  • Add a Subtract Node.
  • Connect the Modulo Scalar node to the Multiply Scalar node.
  • Connect the Multiply Scalar node to the left hand input on the Subtract node.
  • Connect the Constant Scalar Node to the multiply AND the right hand input Subtract node.

By connecting the Constant Scalar Node to the multiply and the Subtract node it's easy to change the steepness of the
concave slope by changing the value of the Constant Scalar. The Constant Scalar is the a in (ax - a).

TG2 provides us with a Square Scalar node (Get Function/Power/Square Scalar) which takes a single input
and squares it, which will does the next step nicely.


  • Add a Square Scalar Node.
  • Connect the Subtract node to its input node, rename the node 'Quadratic'.

Finally we need a min function which, as you may be able to guess if you've read Part 1 of this Tutorial, is the Conditional Scalar Node.
The condition we want is 'if Linear is Less than Quadratic then Linear else Quadratic' so the feed from


  • Add a  Conditional Scalar Node.
  • Attach 'Linear' to Input Node and If result, 'Quadratic' to Comparison value and Else result.
  • The Condition is set to 'Less than'.

Finally...


  • Attach the Conditional Scalar Node to a Displacement Node.
  • Attach the  Displacement Node to the Compute Terrain Node.
  • Set the Camera 'Y' co-ordinate to 2.0

If you followed all that you should end up with this node tree.

[attachimg=4]

Render the image to find a row and rows of perfectly linear sand dunes that run as far as the eye can see.

To make them less linear see the next part of the tutorial.




§ardine

ah... I need more of this...
stretching my mind on well explained (with illustrations at that) TG2 math functions that do something 8)

Quote from: David Burnett on February 27, 2007, 05:13:06 PM
Lot of different algorithms could give us the concave part of the equation, but I want a simple one,
plus my maths is not that hot this days, so its back to my 'O'-level Maths.

You think your math skills aren't as good as they used to be,
I'll be reading this more than a couple of times before I get my mind around it  ;D

Thanks a lot for your time and effort here David! I will be using this.

~§ardine

dhavalmistry

"His blood-terragen level is 99.99%...he is definitely drunk on Terragen!"

king_tiger_666

<a href="www.hobbies.nzaus.co.nz/">My  Terragen Downloads & Gallery</a>

David Burnett

Tell me where you get lost and I'll try and clarify the bit's you don't understand.

Dave

old_blaggard

While it's very complicated, it's extremely well explained in my opinion.  I think you should stick these posts up in the "User-contributed tutorials" section.
http://www.terragen.org - A great Terragen resource with models, contests, galleries, and forums.

Dark Fire

It's complicated, but I think I understand...

RedSquare

QuoteI think you should stick these posts up in the "User-contributed tutorials" section.
I second that, too valuable to be lost in a forum.