Functions, Colors And Displacement a.k.a confusion, pain, agony, and despair

Started by keyframe, January 18, 2011, 03:41:01 PM

Previous topic - Next topic

keyframe

Hello Everyone,

My apologies for the somewhat vague posting - i'm trying really hard to wrap my head around some of the concepts of the TG2 demo - and it seems that I'm failing.  Perhaps someone could shed some light on this for me.  I am familiar with PRman shader writing, and manipulating noise functions to create 'stuff'.

I have a series of questions that are somewhat related, but if you could bear with me, I would really appreciate it.

-What data type is returned by the displacement functions? (Alpine Fractal, for example)
-What data type is expected as input to the displacement functions (They seem to be able to operate both with, and without input -- does having an input imply Base_fractal+New_fractal?)
-Can that data type (Displacement? Vector?  Scalar? foo?) be manipulated by using the 'Functions' (for instance, can I multiply the result of Alpine Fractal, by 2), and still have it be a 'valid displacement'? (my tests seem to indicate that it cannot - the minute that I append any multiply node after Alpine Fractal, my terrain disappears).
-What data type is returned by the 'color functions' (Power Fractal for instance)?
-What is the relationship between the 'combo nodes' color and displacement parameters?  (PF, for instance, has both color AND displacement controls -- which suggests to me that they are handled separately -- gut instinct: displacement scalar, color vector)
-Where are the frequency controls? (I've noticed that some functions have a 'Tweak noise' parameter (PF), and some do not (AF)).

I've scoured the forums for clues - and the answer I most typically find is "What are you trying to achieve specifically" (people in this community seem very generous with their time and knowledge - this is fantastic to see).  In my case, i'm not really attempting to achieve anything (yet?!), I just want to understand the inner working of this system.

If someone has a few minutes to address my questions, I would really appreciate it.

Best,

G

Tangled-Universe

Welcome to the forums :)

Quote from: keyframe on January 18, 2011, 03:41:01 PM

I've scoured the forums for clues - and the answer I most typically find is "What are you trying to achieve specifically" (people in this community seem very generous with their time and knowledge - this is fantastic to see).  In my case, i'm not really attempting to achieve anything (yet?!), I just want to understand the inner working of this system.


I understand your frustrations and feelings of "where the hell do I start". We all had to go through this, but admittedly, it shouldn't be so hard as it often is for many.

However, I think it is really the wrong way around to first want to understand the inner workings of TG2 and then start working from there.
In my opinion you can already learn a lot by playing around and especially doing a lot of mini-projects, which basically means trying to achieve one specific effect (cumulus cloud, detailed fake stone etc. etc.). This way you learn the workflow and the functions in small chewable steps.

At some point it is important to understand what kind of data each input accepts/requires exactly, but I think (almost want to assure you) that's the least of concern for someone starting TG2.

Anyway, I'll try to answer some of your questions. I always try to explain by examples so that you can reproduce the idea and understand it better. Also, it shows that through experimentation you certainly can deduce much of TG2's inner working as there's luckily enough logic in the system :)
It's clarity on things which lacks, so let's try to work on that from here:

Quote
What data type is returned by the displacement functions? (Alpine Fractal, for example)

First question, first exceptions in the answer already :)

The alpine fractal is an advanced fractal function like the powerfractal v3 shader and only generates displacement (vectors). However, the powerfractal v3 shader can also generate colour, hence the colour tab inside.
This way you can have colour (shading) match your displacements, for example.
The alpine fractal can not. The alpine fractal only outputs displacement.

The colour tab in the powerfractal v3 shader does NOT affect the displacement.
Open a new default project and generate a terrain from a powerfractal and enable high and low colour in the powerfractal.
Play with colour, contrast, offset etc. No effect.

So I discussed briefly an Alpine shader and powerfractal v3 shader, but there's also a displacement shader.
Here things change a bit.
The left input of the shader accepts displacement and colour and is meant to link the displacement shader in the network.
The right input (named "function") requires colour/scalar input from which it calculates displacement.
However, it does NOT accept displacement. So when you connect a powerfractal with colours unchecked, the displacement shader does nothing.
The strength of the displacement is determined by the displacement factor inside the displacement shader.
So, as it requires colour/scalar you can use a powerfractal with its colours enabled as (right!) input of the displacement shader.
Now the colour tweaks DO have effect. Change contrast, offset etc. and the displacement will look different.
That is because you tweak the colour function and thus tweak the displacement function consequently.

Quote
What data type is expected as input to the displacement functions (They seem to be able to operate both with, and without input -- does having an input imply Base_fractal+New_fractal?)

Generally the red nodes in TG2 have a main input to the right which always accepts displacement and colour. You need this in order to pass data through to the next node.
Most nodes perform an operation by default and thus affect outcome when they are connected in your network.
The displacement shader, for instance, does nothing if you don't have a function connected to its right "function" input.
Data just passes through the node, unaffected, then.

I'm not really sure to what you are referring to when you say "displacement functions". For instance, the surface layer also has a displacement function input port.
For the record, this input works similar to the displacement shader.

Quote
Can that data type (Displacement? Vector?  Scalar? foo?) be manipulated by using the 'Functions' (for instance, can I multiply the result of Alpine Fractal, by 2), and still have it be a 'valid displacement'? (my tests seem to indicate that it cannot - the minute that I append any multiply node after Alpine Fractal, my terrain disappears).

Certainly.
You would require to use a merge shader and conect that after your Alpine fractal. Inside the merge shader go to the "merge mode" tab and choose "multiply (Input * A's diffuse colour) as merge mode for displacement. As that is what you would like to affect.
Hey, wait a minute, "A's diffuse colour". It seems we need a constant colour value to multiply with. Create and connect a "constant colour" function to the "Shader A" input of the merge shader.
Give the constant colour any value you would like the fractal to be multiplied with.

Logically, you're now manipulating the displacement multiplier/amplitude.
The easiest way, without having to use any extra node, is to simply increase the "displacement amplitude" setting in the Alpine/Power fractal.
So, if you wanted to multiply with 1.5 then enter a 1.5x greater value as displacement amplitude.
You'll see that the result is exactly the same as using a merge shader in multiply mode with a constant colour.

You can create function networks which create displacement. It's pretty much to explain, but there's a nice tutorial about that here:
http://forums.planetside.co.uk/index.php?topic=1166.0

Quote
What data type is returned by the 'color functions' (Power Fractal for instance)?

This should be a bit more clear by now. The answer isn't very surprising, a colour function outputs colour.
You should keep in mind that you disable displacement and enable colour in a powerfractal when you explicitly only want to use its colour output.
I guess that would make sense.

Quote
What is the relationship between the 'combo nodes' color and displacement parameters?  (PF, for instance, has both color AND displacement controls -- which suggests to me that they are handled separately -- gut instinct: displacement scalar, color vector)

I also discussed that already a bit. May of your questions are inter-related. Yes, they are separate and do not affect each other.
As I mentioned it could be useful to have colours generated along with displacement, to get a match or other interesting effects.

Quote
Where are the frequency controls? (I've noticed that some functions have a 'Tweak noise' parameter (PF), and some do not (AF))

The frequency controls are in the "scale" tab and "tweak noise" tab. Both tabs control the noise-function generated by the fractal.

The scales are determined by a "feature scale", "lead-in scale" and "smallest scale".
These 3 values determine how many octaves of noise will be generated. Octaves mean how many iterations, thus the amount of detail.
Low octaves is less detail, many octaves is much detail.

The lowest limit of detail is determined by the smallest scale. The most dominant scale of shapes is determined by "feature scale" and the "lead-in scale" defines the total range of scales being used.

In the tweak tab you can choose which noise-flavour you would like to use, but also there are controls to modulate the frequencies/scales.
The precise workings of these functions have never been documented or explained by the staff.
With the noise variation you can kind of localize the noise to patches (by increasing the value quite a lot, say >5-10)
Or make it very evenly distributed in regard to scales, by making it <0-1.
The variation methods are a bit unclear, still.
Multi-scale modulator probably mixes an extra iteration of the same multifractal in some way, which you can control with the noise variation setting.
The other two, (un)clamped multi-fractal basically mean that you don't want to use the multi-scale modulator and either want to use the multi-fractal itself, being it clamped or unclamped.

The Alpine Fractal does not have these tweak parameters as you can consider the Alpine Fractal as an advanced powerfractal, probably a fancy combination of powerfractal noise with other clever elements. The UI for this shader is probably simplified to make it useable and probably also to avoid that the user will render TG2 useless as the shader already is very "heavy" without all of these (extra) fancy controls (with which you're likely to make it even worse if you don't know what you're doing).

Clamped means that the colour output is restricted to range from 0 to 1.
Unclamped means that it can go beyond these values, without limits. (probably there are, but not that I know).



Ok, this took a bit more than a few minutes, but hopefully things are a bit more clear now.
Time for a drink, might change little things later, but this is primarily how I think when using TG2.

Cheers,
Martin

airflamesred


keyframe

Wow Martin,

Thank you so much for the detailed discussion!

I think part of my confusion is that in 'our' world (Houdini), data is a little bit more fluid.

A function returns 'values' - how you map it, is completely up to the user.  You can use the result of perlin noise (whether 1D, 2D, or 3D), and map the results to displacement, color, or use as a basis for yet another function.  I suppose I was looking for an analogue in the TG world, but I suppose that's a bad approach on my part.

imagine:


x = perlin3d(P);                               // Compute the value of the perlin noise at (P) - returns a vector3
x2 = perlin1d(P.x);                            // Compute the value of the perlin noise at (P) - returns a scalar
x_ranged = fit(x, -0.5, 0.5, 0,1);        // Perlin returns noise typically found on [-0.5, 0.5]
x_clamp = clamp(x_ranged, 0.2, 0.8);  // Clamp the noise on [0.2, 0.8] - we try not clamp shader code as it introduces aliasing
P += x;                                          // Displace the micropolygon by x
P = P + N*x2;                                 // Displace the micropolygon by x2 in the direction of the normal
Cd = x_clamp;                                 // Finally stuff the clamped result into Colour


All this great information will obviously take me a little while to absorb, as I try to work through the examples that you've provided.
Hopefully, I'll be able to ask more intelligent questions in the future.

Thank you again for taking the time to share your experience.  Very nice of you.

G

Volker Harun

In my opinion your questions were quite advanced ... and TU's answers even more ,-)
He pointed out the trying is a good approach ... I double this.

Your code looks interesting though I do nut fully understand the fit and clamp-commands for the colour information.
If you can show a resulting screenshot, it would be possible to underline TU's explanations with a workflow.

Volker

keyframe

Quote from: Volker Harun on January 19, 2011, 02:27:34 AM
Your code looks interesting though I do nut fully understand the fit and clamp-commands for the colour information.

Heya Volker,

Thanks for the encouragement.

This is precisely the point I was attempting to make.  In my previous experience (which i'm happy to acknowledge is mostly useless in this context), the fit and clamp commands are context agnostic.
They operate on 'data' of some type - the value of the result doesn't 'become' colour until it has been assigned to the Cd global variable (final color).  Casting data from a color-vector, to a direction-vector, to a normal-vector is a trivial operation.

In this context though, they operate on a per-vector-component basis (since the result is initially a vector3).  The fit will take in the 'x' variable, break it into components (in this case x.x, x.y, and x.z - please forgive the poor choice of variable), adjust the values, and rebuild the vector.

This is definitely semantics (also the reason why I was asking about the data type that 'displacement' (in the TG context) returns).  I suppose I expected to be able to 'just multiply the result of AF by 0.5', and carry on going about my business.

Thanks again for the feedback - I will keep investigating.

Best,

G

Tangled-Universe

You can perform per vector base component operations.
You would need a vector function and convert that to scalars by using the "X/Y/Z to scalar" nodes (under function node -> convert).
After that you can perform operations on each component separately and later rebuilt the vector with a "build vector" node.

These vector functions, as a base, are derived from function-node-based networks. In TG2 this means they are made of the blue function node.
As far as I know you can't extract vector specific data from a red node like the PF or AF. So breaking the output of those nodes into separate components is not possible as far as I know.

This is quite a technical discussion, so I hope Matt can chime in here some time soon to check if things thought by us (more advanced) users is still correct (though).

keyframe

Quote from: Tangled-Universe on January 19, 2011, 10:52:29 AM
As far as I know you can't extract vector specific data from a red node like the PF or AF. So breaking the output of those nodes into separate components is not possible as far as I know.

This is quite a technical discussion, so I hope Matt can chime in here some time soon to check if things thought by us (more advanced) users is still correct (though).

Hello Martin,

Thanks again for keeping the disucssion going -- i'm learning lots.  You are very generous with your time.  If you ever decide to delve into the world of houdini, I'll be happy to return the favour.

I've recently started to suspect that the 'displacement' output of the 'red nodes' is in fact a scalar value [like a heightfield - the magnitude of displacement] (and not a vector [magnitude AND direction]).  I base this on the notion that certain nodes ask for a direction by which to displace the geometry (vertical, along normal, lateral, etc).  I could, of course, be on crack  :)

Will keep digging!

Best,

G

Tangled-Universe

You're welcome, the pleasure is mine too.

Well, to be honest I never really understood the fundamental difference between a vector and scalar. Maybe you're wondering how the hell I know the other stuff then, well, please don't ask :) lol
Anyway, you've made that clear to me now, thanks :)

Your comment makes sense, but I'm not sure if the output would be scalar. I guess the internals are scalar, but being able to choose which direction you control the vector component it seems to me the output is not scalar only. The output would then be the scalar information + the direction defined by the settings you mention (you probably mean "along normal/vertical/lateral etc.")?

freelancah

This thread is very informative. Certainly sheds some light to things I've been wondering about.. I also wonder if there is a good book on the subject? Not terragen related but in general..

Keep it up guys!

keyframe

Heya Freelancah,

One of bibles on this subject is: "Texturing and Modelling: A Procedural approach"

http://www.elsevierdirect.com/product.jsp?isbn=9781558608481
[edit: Much cheaper through Amazon: http://www.amazon.com/Texturing-Modeling-Third-Procedural-Approach/dp/1558608486/ ]
I HIGHLY recommend this book.  It's implementation agnostic for the most part, but does provide examples in Pixar's Renderman format.

Some of the author's name might sound familar  ;)

Best,

G

ps: Just as a bit of side note - it does presume a certain comfort level with math, but none of it is, pardon the reference, rocket science.


cyphyr

Quote from: keyframe on January 19, 2011, 12:17:18 PM
Heya Freelancah,

One of bibles on this subject is: "Texturing and Modelling: A Procedural approach"

http://www.elsevierdirect.com/product.jsp?isbn=9781558608481
[edit: Much cheaper through Amazon: http://www.amazon.com/Texturing-Modeling-Third-Procedural-Approach/dp/1558608486/ ]
I HIGHLY recommend this book.  It's implementation agnostic for the most part, but does provide examples in Pixar's Renderman format.

Some of the author's name might sound familar  ;)

Best,

G

ps: Just as a bit of side note - it does presume a certain comfort level with math, but none of it is, pardon the reference, rocket science.



Pretty sure this book has been mentioned by the planetside guys :)
Thanks TU, very well answered, I kept "nearly" answering and then deleting the post, there's so much I assume and so little I actually know lol
Richard
www.richardfraservfx.com
https://www.facebook.com/RichardFraserVFX/
/|\

Ryzen 9 5950X OC@4Ghz, 64Gb (TG4 benchmark 4:13)

Volker Harun

 ;D

Okay, I try to add some informations based on the Perlin noise of TG2.
The node is called Perlin 3D scalar and it has three inputs.

1. The input called 'Input'. Here you normally plug in one of the 'Get position'-nodes, which give a vector of the certain point that is calculated.
You can use here a simple Powerfractal, too, as TG2 converts colour information to vectors where applicable. Of course a PF has a limited range of Colour information. Which is nice to have sometimes ,-) But just asume that we use a 'Get position' for having the 3D coordinates of the TG2 world.

2. The scale describes the main size of the Perlin noise. Using a contant scalar is nice, using a PF for a variety in size is nicer (change the colour inside the PF: Low Colour: 10, High Colour 20 and then adjaust the Colour roughness and contrast to your needs). If you feed in a vector, the Perlin noise uses the vector's length as a scalar.

3. The seed ... it needs integer numbers, any change here gives a heavy change in the Perlin noise.

The Output of the Perlin noise is nothing but a range of scalars from -1 to 1. There is no displacement anywhere, just scalars, that can be displayed as a grey-image (partly, as any scalar information below 0 is shown black). Your Perlin1d(P)

But you can plug this into a Displacement shader's Function input and change the displacement's amount by any (un-)reasonable number ;)
And of course you can use the output of the Perlin 3D noise for anything else ... plugging it into the inputs of any shader to give it a try.

To get use of the displacement but, you will need a Compute terrain node after the above mentioned displacement shader. And only a new 'Get position node will give you the vector of the Perlin 3D noise, depending on the amount of displacement in the displacement shader.
This will be your perlin3d(P).

,-) Volker

keyframe

Quote from: Volker Harun on January 19, 2011, 12:45:26 PM
1. The input called 'Input'. Here you normally plug in one of the 'Get position'-nodes, which give a vector of the certain point that is calculated.
You can use here a simple Powerfractal, too, as TG2 converts colour information to vectors where applicable. Of course a PF has a limited range of Colour information. Which is nice to have sometimes ,-) But just asume that we use a 'Get position' for having the 3D coordinates of the TG2 world.

2. The scale describes the main size of the Perlin noise. Using a contant scalar is nice, using a PF for a variety in size is nicer (change the colour inside the PF: Low Colour: 10, High Colour 20 and then adjaust the Colour roughness and contrast to your needs). If you feed in a vector, the Perlin noise uses the vector's length as a scalar.

3. The seed ... it needs integer numbers, any change here gives a heavy change in the Perlin noise.

The Output of the Perlin noise is nothing but a range of scalars from -1 to 1. There is no displacement anywhere, just scalars, that can be displayed as a grey-image (partly, as any scalar information below 0 is shown black). Your Perlin1d(P)

But you can plug this into a Displacement shader's Function input and change the displacement's amount by any (un-)reasonable number ;)
And of course you can use the output of the Perlin 3D noise for anything else ... plugging it into the inputs of any shader to give it a try.

To get use of the displacement but, you will need a Compute terrain node after the above mentioned displacement shader. And only a new 'Get position node will give you the vector of the Perlin 3D noise, depending on the amount of displacement in the displacement shader.
This will be your perlin3d(P).

Soooo.... much... new... information...

Brain... exploding!  ;)

Thank you so much, Volker, for taking the time to add this valuable insight!  Much appreciated!

Best,

Gene

keyframe

I think I might be getting somewhere ;)

I've attached a simple file showing a crater carved into an alpine terrain.

From what i'm able to gather at the moment:

- 'get position' returns X and Z coordinates by default
- one can separate the X and Z axis terms from 'get position' by using the 'x to scalar' and 'z to scalar' functions. (note that I've also attempted to use 'Red to scalar' and got the same result as 'x to scalar', which leads me to believe that vector data (color, position, normal, etc - is in fact one and same, despite having specific functions to deal with each)
- the Y term is 'undefined' at this stage (you can confirm this by plugging the output of 'y to scalar' into the first input of 'smooth step').

At some point Both Martin, and Volker may have mentions the 'compute terrain' node - which allows one access to the Y-term (among other useful things like normal, and slope (and i'm assuming surface derivatives dpds/dpst).  I've attempted to add it between 'AF' and 'merge shader', but it didn't seem to affect the result returned by 'get position'.

Can anyone clue me in?

Best,

Gene

[edit: just for completeness sake, in most systems the reason a distinction exists between different types of vectors (color-vector, point-vector, normal-vector, etc) is that certain operations 'transform' certain types of vectors (imagine a rotation of the terrain by 45deg).  You would want point, and normal vector to be transformed along with the operations, while 'other vectors' [ie: color] to be left alone.  I have no idea whether this is the case with TG or not.  Just speculating, and trying to fill in some blanks.   ;)