Spikey's Math Lab
Get it? Math Lab.... sounds like Me.... Lab?.... No? ok
So spikeyxxx you're like a super mathematician, I'm doing the Blender Cloud Procedural Shading course and it is super heavy dense in tough, difficult and impossible things and worst of all there's like a lot of math involved. I wanted to use this to bother you a lot and ask you math questions when it comes to procedural shading.
The course is good but Simon goes way too fast and doesn't get into the really basics and assumes you know what happens mathematically under the hood.
*WARNING, HERE BE MATH*

Omar Domenech (dostovel)
So to get started I ask you this Spikey, why when I have a plane and I use the Object coordinate (which starts from the object origin) and I get the X component... ok all good...
But then I add the Y coordinate and it goes diagonal.
Why is that the behavior? What is going on there? I know I can get a diagonal gradient that way but why does it do that? What math is going on beneath it? Help me Obi Spike Kenobi, you're my only hope.

When I was a kid, I wanted to become a math teacher...you sort of make my dream come true...thank you!
I will give it a try; look at this picture:
I put in some numbers. Now the 'points' in the plane are the number on the Xaxis plus the number on the Yaxis. See the yellow lines, where 0.5 = 0.3 + 0.2.
The green line is where all points (x + y) are the same; in this case 0.2. In your picture, where the border between black (all negative numbers) and white is where the sum of x and y is zero.

So, let me see if I understand...
I assume that in the plane the black and white gradient, those pixels have a value. Form what I've seen in the course, just because you see black doesn't mean the value of that pixel is zero (0), it's just that my monitor can only display from 0 to 1, but a black pixel can easily be 5 and a white pixel be 15.
So the numbers you put there on the graph you made, the values of 0, 0.1, 0.2, 0.3, 0.4, 0.5... those can be seen like the values of the pixels on the gradient in the plane. So when I tell Blender with the Separate XYZ Node, please give me the values of X, it goes from one end of the plane to the other, where the object origin is X=0 and Y=0 or (0,0) I guess. So everything left of X=0 is negative and right of X=0 is positive and everything down of Y=0 is negative and up of Y=0 is positive.
When I say, Node, get me the X
And then Node get me the Y
And then....
OH MY GOD!
Spikey, I think I see it. Is it like that? right?

YOU'VE GOT IT!
That is exactly right!

Thank you Spikey.
Now to try and understand what happens when I change the operation to multiply X and Y. But one step at a time, I'll get into that after I do some modeling for the TSFHI.

dostovel only look at this after you've done some top secret modeling!
That is basically the same, apart from the fact that multiplication is a tad more difficult than addition (don't even get me started on division & Co.):
Let me explain what you are looking at here: the red numbers are (some of) the Xvalues and the green numbers (some of) the Yvalues. The yellow numbers are the product of the X and Yvalues and the green curvy thing is where the product is 0.5.
Note that, when you multiply two numbers, that are larger than1, the result will be larger than either one of those numbers and that when you multiply two numbers smaller than 1, the result will be smaller than either one. Nobody knows what will happen when you multiply one number smaller than 1 with one larger than 1,,,
It is also noteworthy, that green times red is the same as red times green (0.5 * 2 = 1 = 2 * 0.5). This is called commutativity by mathematicians, so when you hear someone talk about a commutative ring with 1, you will know at least one third of what he or she is talking about...Sorry, I tend to divert when it comes to math :)

I just created a short animation for the coordinates where the multiplication of "Object X and Y" creates a negative number:

That's cool duerer !

spikeyxxx Handmade with IrfanView (fortunately just 200 screenshots 😉) and then processed in Gimp (Optimization for Gif and then saving as ".gif" with 40ms delay between each frame).

I don't know IrfanView, but did you know that there is a handy Addon in Blender:
I think it comes shipped with Blender.

Instead of using an "Add Node", a "Subtract Node" can also be used in order to create a diagonal which is rotated 90 degress around "Local Z" compared with the use of the "Add Node". It's also important since although the remapping necessary for the "RGB Curves Node" will work for the "Object X Coordinate" it won't work when doing the same remapping for the "Object Y Coordinate" with an "Add Node" after this:
An addition would make everything white when replacing the "Subtract Node" in the node setup above. File is here.

spikeyxxx Thanks, I didn't know that with the "UI Animation" addon 😀! Does it work similar to the abandoned "Blender Screencast"? An alternative would be using "OBS Studio" recording and converting it with Gimp and the "Gap" addon into an image sequence but this would have taken me probably more time than doing it manually with screenshots 😉.

duerer it records the UI whilst playing the Animation (so just like in your GIF) and outputs it into your output path. If your animation is 200 frames, it only records those 200 frames, so you don't have to cut it or so. A lot easier and faster than making 200 screenshots ;)


Ok, you guys talking about math and stuff made me want to try and understand the next step. But first I have a question that has me confused, so I made a graph to see if my mind was in the right place when it came to visualizing this stuff. Is this right? I think it checks out.
I got a little sloppy in the end and didn't really add the pixel value in X and the pixel value in Y, it was just too much, but it yes, it all adds up, I think.

You seem to have understood it well, but you didn't add all the red and green values in the resulting grey picture;
For instance the top right pixel should be 1 + 1 = 2 and in your picture it says 1.
Your diagonal line of zeros is correct, but then to the right of each zero (horizontally) it should be: 0.1 0.2 0.3 0.4 0.5 .....and likewise to the left of each zero: ....0.5 0.4 0.3 0.2 0.1

Yeah yeah, that's what I mean I got sloppy and didn't add all the values in the final picture, I started and then I was like ok ok I get the picture, it pans out.

So, now onto multiplication. I guess I could use the same example of all those squares but instead of adding I'll just multiply and I should get this pattern, right?

Exactly!
In my picture above of the multiplication I added a few values, but was too lazy to put in all...like you say: you get the idea ;)

Wow Spikey you can even see it in the Graph Value tool.
Here you have the X value and it maps exactly one blender unit
As soon as you add X to Y, it goes to two blender units, because at the edges 1 + 1 = 2 and on the opposite side is 1 + 1 = 2
It all checks out, this is amazing.
OK ok, now onto having a mental picture of what multiplication does. I know is very easy just adding stuff, later is where all hell will break loose. But this has been a huge step in having visualizing what the under the hood math was doing. I need to have a mental picture of things to understand them.


I'm trying to understand the pattern duplication:
What are the green and yellow frames doing exactly and why do I need the yellow frame for making the green frame work? File is here.

Okay, with the "Viewer Node", I can visualize the field separation (here into 4 fields):
But why does it work like this?

I don't know dude, I'm not that far in. I watched a lot of chapters before I decided that I needed to step back and understand it to the core before continuing. I'll get to where you are eventually.

Okay, look at the green frame first. from left to right: the first node does nothing when set to 1 (it multiplies all values by 1), so after that we still have the normal Object coordinates (I only write some of the X values so it doesn't get too cluttered):
Then we get the Fraction Node, that does this:
Watch the unexpected way it takes the fraction of negative numbers, but this is advantageous for us.
Then we subtract 0.5 from all values:
And finally multiply by 2 to get:
This way we now have 4 fields with the original Object Coordinates.
If we increase the value in the first Scale Node, we create more, smaller fields like that.
The yellow frame is just to get rid of the Zvalues.

Here is an alternative (and 'cheaper', more intelligent) way to get rid of the Z problem:
Because on a Plane the Object's Z is always 0, but we subtracted 0.5 and then multiplied by 2, making the Z always 1.
When you then calculate the length, you get the square root of (x²+y²+z²),which is the square root of (x²+y²+1) and we want the square root of (x²+y²+0).

Man I'm looking forward to the day I'm like, no Spikey, it's actually (xy*z) and you're like, oh dude yeah, you're right, thanks.

That day will come, Omar! I make mistakes all the time;)

Thanks, spikeyxxx, for the explanations 😀! Now, it's clear 👍! I didn't expect that "Fraction" works for negative numbers as you described it. Is there a mathematical explanation or is it "just" defined like this in order to continue the pattern from the positive numbers with the negative numbers?
spikeyxxx, your method for setting the vector's zcoordinate to zero is obviously smarter since it saves two nodes. Simon Thommes introduces this "zeroing" first (when it has not effect) and then demonstrates how to create a repetitive pattern so that he effectively does the second step before the first one which I find confusing. Thank you again for the clarifications 👍!

spikeyxxx For calculating a random value for each tile of the pattern repetition, Simon Thommes makes use of the "Snap Operator" of the "Vector Math Node". The "Blender 2.92 Manual" here describes it like this:
Snap
The result of rounding A to the largest integer multiple of B less than or equal A.
I understand it like this:
If we have for example a vector A = (4.73, 3,51, 9.48) and vector B = (1, 7, 3), then the result As (="A snapped") should be:
As = (4, 0, 9)
Did I understand it correctly?
And what if vector B also has decimal fractions? Does "largest integer multiple of B" mean rounding the entries of B before the multiplication or are the decimals in the coordinates of B simply cut off?

Great questions like always duerer
Fraction seems to do the following: the Fraction of a number a is: a minus the Floor of a. (the Floor always rounds down to the nearest integer, so the Floor of 0.5 is 1.
I do not know the mathematical definition, but I'm sure it's not used like this in math.
Modulo is one that I don't know what it does exactly; it has nothing (or very little) to do with the mathematical modulo.
Snap??? I've seen it in the dropdown list, but not used it yet. If the Manual definition is corect (and it probably is) then I'd say your interpretation is right and your example should yield those results.
When B is not an integer, for instance 3.7, then the integer multiples of B are ....3.7, 0, 3.7, 7.4, 11.1,.....But I do not know it rounds A down to one of those, or if the result is some integer...Again: this is not math, so who knows what it means ;)
It's probably something used in programming languages (like Modulo in Python,...), so a programmer will know how it works....

duerer this is funny, just released today: a mathematician talking about fractions (not what they are, but you'll see that it's something completely different..., not like the fraction of A is B):

duerer thanks, I will watch that tomorrow; I like his videos ;)

duerer nice video, thanks.
But it seems to me that even Blender doesn't know how to calculate Snap:
Those renders are even quite regular, I've had a lot more chaotic ones...

Actually, that was due to the displacement.
Snapping works as explained above; here it snaps the Xvalue to integer multiples of 0.3:

One day I'll understand all that stuff you guys are saying, one day soon.

Looking at this last screenshot again, I notice something's wrong, x=0.1 should Snap to 0, when increment is set to 0.3.
The integer multiples of 0.3 are the same as the integre multiples of 0.3, but the results of Snap are different:
????


Ok Spikey, I learned my lesson and made a graph for multiplication with less squares and made all the calculations. It's incredible, I can clearly see now why multiplication would be use when you want to repeat a pattern, the values mirror each other. This is awesome.

Well done!
Luckily, now that you understand it, you don't have to fill in all those numbers every time
Sometimes, when I don't understand what's going on, I start filling in a few easy ones, until I see the pattern.


Key takeaways from watching 1. Fundamentals Chapter 11 Colors  Values  Vectors
 There are 2 things, colors and vectors, they can each be converted to values and values can be converted to colors.
 Color managements can influence how the color looks on screen, but that is a post effect, that does not influence the value.
 It is better to tun off Filmic and sRGB for debugging values.
 Colors are clamped from 0 to 1 but values can go negative numbers and beyond 1
 Going from a color to a value has downsides, since colors go by the luminosity, which is a perceived brightness.
 XYZ is interchangeable to RGB

You've got it man!
Just be aware that RGB is 'clamped', but can take values higher than 1, but they can not take negative values, while XYZ can:

Yes, the slider wont go further than 1 but you can punch in the value.
Now onto watch Chapter 12 Vectors and Pixels. But first, do you guy thinks you could create this shape on a plane using nodes proceduraly?

Sure!
Shouldn't be too difficult...the lighting could also be done procedurally, but that might be a bit more advanced...

for instance:

Dang it Spikey, with so few nodes.
I still don't understand how to control de map range node. I know it kinda crunches the levels, but I always click on it like a crazy person until it sorta does what I want.
Let me try and replicate that and see if I get your same result.

Spikey how in the world is that doing that? I went node by node and I don't get it how that ends up being the shape.
You have Y + Y and it gets you this:
Then you subtract X and it gives you this:
And then it gets all sharp and neat with the compare. I call foul, there's like no way this makes sense.

Key is to understand what the Map Range Node is doing.
Maybe this helps:

Actually, this gives a bit of a wrong impression, because I forgot to subdivide the Plane...so Clamping doesn't work as expected...

Another picture; the two Map Range Nodes:
Adding them together:
(Which was not the best idea ever...better would have been to take the Minimum of the two:
)
Then these values for X are Subtracted from the normal X values. So where Y=0, X=0.4 gets the value 0,where X=0.5 it becomes 0.1, and so on.
Now the point (0.7, 0)) has the value 0.3 (while we subtracted 0.4 from the Xvalue) and the point (0.3, 0.5) also has the value 0.3 (while there we subtracted 0 from the original Xvalue).
So if we then compare the values in these two points, both are within 0.25 this is called Epsilon in the Compare Node) distance from 0.000( Value in the Compare Node).

1) So, setting "To Min" to a bigger value than "To Max" makes a gradient run into the opposite direction provided that you keep "From Min" lower than "From Max"?
2) The addition of two "Map Range Nodes" is really insane 🤪😉😁!

duerer the terminology in the Map Range Node is not great; you can basically ignore the Min and Max and read: From A ... to ... and From B ... to ...
The Min and Max aren't even minimum and maximum values when you don't have Clamp checked; it extrapolates outside the interval. And even with Clamp enabled, Min can be larger or smaller than Max.

Ok wait, I'm really confused.
So I've always read the Map Range Node as if the first two (From Min/From Max) are a connected pair that does something and then the second pair (To Min/To Max) as the second pair that does some stuff. By the way I see your explanations Spikey, I'm guessing I'm reading it wrong.
I get what the first picture is trying to describe, and I see why you say that about that the plain isn't subdivided. You wanted to see how it went up and down in Z by driving the displacement, I think.
So if I get your explanation clearly, your trying to show me that the Map Range Node sorta rewrites the values? So what once was zero (0) will now become (2)? Is that is?
From Minimum = 0
To Minimum = 2
So now what you see as a zero (0) remap it to (2)?
And....
From Maximum = 1
To Maximum = 1
So the value of 1 will now be interpreted as a 1?
On that first example though, what I don't get is where that 5 in red comes from? on the lower left side of the plane that makes the plane jump up.
Then on the second picture, you are separating the Y component into two map range nodes, but in the graph you can see Y and X values. Where did X come from if you are separating the Y component only? It looks as if the From Min/From Max are both Y values and To Min/To Max are X values. What's up with that? I am really confused.

You have understood it well, Omar 🤗
Where you are confused is mostly due to my poor explanations. I will try again, but in a nutshell: the 5 in the first example is where 1 gets mapped to when 1 goes to 1 and 0 goes to 2, because the plane stretches beyond that interval, it just keeps going in the direction it already has (if Clamp is off!) so 2 would become 8, and 2 would become 4.
In the second example you say correctly that the X shouldn't change, but I tried to put too much information in one picture and already combined the Yvalues with the X...
Like I said, I will try again, this time with clearer images.

I hope this is clearer:
Only looking at the Yvalues, because, like you correctly said, the Xvalues have at this moment not yet changed.
Does this help?

spikeyxxx So, the original interval is stretched or squeezed (just the values that are attributed to the suface points which keep their positions within the mesh) and the direction for rising values can be switched as well (with "To Min" set to a greater value than "To Max" while "From Min" being lower than "From Max"). "From Min" (should be better named "From Start") is mapped to "To Min" (better ("To Start") and "From Max" (better ("From End") is mapped to "To Max" (better "To End"). The "Input Value" in the "Map Range Node" directly above "From Min" is recalculated taking care of the interval stretching/squeezing and, if any, also the direction switching for rising values.

Yes. duerer
The Map Range gives new values to 2 'old' values; in the above picture: 3 becomes 1 and 1 becomes 2 (see the green arrows).
Then it 'draws a straight line' through those two new values (when set to Linear!). When Clamp is enabled, that line is only drawn between those two values (see the red arrows)

in the above picture: 3 becomes 1 and 1 becomes 2 (see the green arrows).
I can see the 1 becoming a 2 From Min To Min is set to 1 and 2
But 3 becomes 1? or 3 becomes 0? It is set to From Max 3/To Max 0
I think I kind of get what the map rage is doing. This node should be renamed to Remap Range Node. I yet have to see what's the advantage of doing this.
I have a question, because I still can't see the functionality pictured in my head. If I have a plane, I separate the X, now I have a gradient in X that goes from 1 to 1 which seems to be the default, then I plug a Map Range, From Min 1/To Min 1 and From Max 1/To Max 2...…. now my plane will be entirely white and the left most value in the start of the plane will be 1, and the right most value at the end of the plane will be 2, my question is.... what if I had said From Min 5/To Min 2? There were no such values in the plane to begin with, how does the node interpret that?

You're absolutely right, Omar, I wasn#t paying attention: 3 becomes 0 as can be seen in the Map Range and in the picture ;)
When you set it From Min 5 To Min 2, then the Map Range Node sets Where X = 5 to 2 and with From Min 1 To Max 2, it sets where X = 1 to 2...and the interpolates linearly (draws an imaginary line) between those values. So where X = 1 (the left side of your Plane) it would get the value 0.4 ...if you would extend the Plane, it would become 0 at X = 2.

spikeyxxx I think, a visualization would help. The mapping of the end values is clear but even with a linear interpolation I can't simply see where a value in between the two "From" interval limits gets mapped to in the target interval. I suppose that it works with "Linear" interpolation by calculating a percentage in the "From" interval and doing it similarly in the target interval. But what if I change the interpolation type 🤪?!

Man, I should really work on my calculations:
That does not look like 0.4 at X = 1
Don't know what the other interpolations do exactly...

Is it like this Spikey?
In my head I picture it like a bully that goes to the number it's order to and punches it and takes it place and all the other bad guys that follow him in an accordion motion move accordingly. Right?

dostovel Bravo 👏 👌 👍
(To be exact, the Plane now goes from 0.25 to 0.666..., but like you said, you only ballparked it, but the idea is absolutely correct) You've understood it!

Excellent, thanks Spikey.
Now, how did you calculate that those are the exactly values? I would like to understand that if it's not too complicated. And if I do just that and make a render, will the color picker pin that value at 0.25 in the left most pixel and 0.666 at the right most pixel?
EDIT: Ok no, I just tried making the render but if you right click to sample the pixel, it normalizes the values from 0 to 1, it crunches everything.

I would expect the render to get it right, but you should at least set the Color Management to Standard...

Now, how did you calculate that those are the exactly values?
dostovel I got them all wrong!
If you look at the top image, you go from 3 to 4...those are 7 'stops'. Below you go from 1 to 2, which are 3 'stops'.
Going from right to left in the bottom image, you need 7 stops, that are all the same distance away from each other to cover a total distance of 3...which makes the distance between two stops 3/7,...and 7 of those stops would yield 7 * 3/7 = 3, which is exactly what we wanted!
so, again from right to left on the bottom image, the numbers would be 2 (2 3/7) (26/7) (12/7) (15/7) (1/7) (4/7) 1.
Do not read what comes next!
Now 7 is a prime number, so 1/7, written as a decimal number, repeats after a divisor of (7  1), or 6 digits.
10 is congruent 3 mod 7.
10² is congruent 9 is congruent 2 mod 7.
10³ is congruent 3*2 is congruent 1 mod 7.
So 1/7 must repeat after 6 digits. And as 6 is even, the first 3 digits and the second 3 digits add up to 999.
So do a short long division to get 1/7 = 0.142(857)........
This is mathemagic ;)


Key takeaways from Chapter 12: Vectors and Pixels
 I didn't know the image node had an interpolation setting which is set to linear that blurs the texture, you can change it and it will show the texture in full res.
 Image textures are dependent on the pixel resolution, procedural textures are basically infinite in their pattern.
 If you preview the vector info, you can see how it is mapped black in (0, 0) space, up in Y from black to green, X side from black to red and the resulting mixture in shades of yellow up to (1, 1) space.

It's kinda how I felt after coming into this thread! 😃😃

Dude I put it in the title "Math Lab". It's like a warning.


spikeyxxx I'm wondering what Simon Thommes means when saying that the values from the "Color" output of the "Noise" texture node are centered around 0.5. And what's so special about the "Linear Light" blend mode of the "MixRGB" node that it can be used for mixing in that "Color Noise" into your "Texture Coordinates"?

duerer this is what he means with Noise output is centered around 0.5 (just think of this as one of the three RGB channels):
Now Linear Light does not change 0.5 as can be seen here:
This is the same as directly plugging the X in the Displacement Height. So if you pug in a Noise Texture in Color2, in stead of this Value Node, it will preserve the average of the Noise. Mathematically Linear Light does this:
It doubles the strength of the Noise, but doesn't 'shift' the original...

spikeyxxx So, "Linear Light keeps 0.5 in place" means that any RGB value from the "Color" output of the "Noise" texture node won't have any influence on the coordinates since it's multiplied by two which equals 1 that is subtracted at the end of the orange frame above. The "Add" node brings in the texture coordinates.
Simon Thommes, if I remember it correctly, uses a "Vector Math" node in order to subtract 0.5 for all the coordinates from the "Color" output of the "Noise" texture node and scale this up with a "Vector Math" node in "Scale" mode in order to avoid any coordinate shifting by 0.5. In the last step noise and texture coordinates are added together.
So, in other words, we have to take care that the "Midlevel" values of the "Object" texture coordinates and the "Color" output of the "Noise" texture node get synchronized.

spikeyxxx I've just seen the Simon Thommes uses the "Factor" output of the "Noise" texture node with a "Color Ramp" afterwards and plugs the ramp's output into the "To Min" input of a "Map Range" node 😱🤪😵!!!

So, "Linear Light keeps 0.5 in place" means that any RGB value from the "Color" output of the "Noise" texture node won't have any influence on the coordinates
No no no, you plug the output of the Noise Texture into the bottom socket of the MixRGB (set to Linear Light) and almost every RGB value of the Noise will have influence on the top input and usually that are coordinates:
Compared to Mix:
So, in other words, we have to take care that the "Midlevel" values of the "Object" texture coordinates and the "Color" output of the "Noise" texture node get synchronized.
No, we take care that the 'midlevel' or the Noise Texture doesn't change the coordinates.
And yes, you can do that with (Vector) Math nodes as well, but to use one MixRGB node is easier and also has a handy influence slider built in.

Thanks a lot, spikeyxxx, for your explanations 👍😀!

spikeyxxx I just thought about your node setup from above:
If you set the "Value" in the bottom left corner to 0.5, it gets multiplied by 2 which equals 1. This result is added to the X coordinate of the "Object Coordinates". The subtraction of 1 at the end neutralizes the 1 from the beginning which was the result of a calculation with 0.5 as input. So, the input of 0.5 doesn't change the "X Object Coordinate".

Exactly duerer 👍



Adrian, just.... ok, yes? ok good.


First step when trying to explain this:
I start with a gradient in local X direction (note: the local axes of the plane are aligned with the global axes for demonstration purposes).
I want the black protrusion happen at the top between 0.5 and 0.4. So I create a gradient in local Y that only changes in that area. This can be done with a "Map Range" node where I map that interval onto itself and use "Clamp" so that the values at both extremes of that interval are copied outside the interval (here demonstrated with a "Color Ramp"):
End of part 1

For achieving a change in the local X axis gradient between local 0.4 and 0.5, I now need to subtract the first local Y axis gradient from the local X axis gradient:
I can mirror the direction of the protrusion by swapping "To Min" and "To Max" in the "Map Range Node" for the local Y axis gradient:
End of part 2

Yes yes, please continue... Part 3

Ok no WHAT!? How subtracting X gives you that perfectly clean cool slant? What is happening there?

For the bottom end I set "From Min" to 0.5 and "From Max" to 0.4 so that, as in the case of the top part of the protrusion, I'm climbing upwards the Y axis within the bottom protrusion interval. During this Y upwards movement, the bottom part of the protrusion goes into the direction of positive local X (from the current viewpoint to the right) whereas the movement at the top part of the protrusion goes to the left. This inverted direction in the bottom part of the protrusion makes it necessary to swap the "To Min" and "To Max" values from the "Map Range Node" for the top part of the protrusion:
End of part 3

Now, both procedural textures from above can be combined with a "Math Node" set to "Max" so that only points that are black in both textures will be displayed as black in the final texture:
This can be sharpened with a "Math Node" set to "Greater Than" and a "Threshold" of 0:
End of the final part 4 😌😉.
PS: File is here.

Thanks for the tut Ingmar. I'm stuck at trying to understand something, I'll post about it in a short while.

Ok no WHAT!? How subtracting X gives you that perfectly clean cool slant? What is happening there?
dostovel Subtracting local Y from local X gives you a diagonal gradient:
If you now remap the local Y coordinate using "Clamp" the two values at the "To" interval limits are extended outside that interval into infinity so that we subtract a constant value from local X:

DUDE! Now I get it!
That image with the orange lines isolating the diagonal part is where the subtraction happens, which is all due to the map rage limiting it into that zone.
Thanks Ingmar, my mind works like that, I have to see the picture in my head of what is going on, otherwise I wont internalize it.

dostovel I'm happy that I could help you 😀! With me, it's the same: I need to visualize things in order to understand them 🕵️♂️.


I made a bit of a mess of the Nodes, but something like this, dostovel ?

Spikey you should be teaching this stuff. It turned out identical. I here by award you with the CG Cookie honorary master achiever.
My goal is to get to the point that I understand this and make it on my own. At least to start with. Ok, back to trying to understand the basics.

dostovel just wait until duerer finishes explaining the main shape and then we are already mostly done ;)
I repeated a small version of the main shape to the left of it as a Fake shadow.
You already know how to make a diagonal gradient, so basically you can also already make those two light streaks, well, almost...Let's finish the main shape first and then I will guide you through the process (and I am sure that duerer will help with the explanations)

Well, there's also snapping your mind to this way of thinking, I don't know how you guys arrive at this conclusions to do this. That is only achieved with practice and getting into this mindset with lots of trial and error. Right now my mind sees a shape and it tries to follow the contour like if I have a pencil and I want to draw a straight line. But that's not how it is reached when it comes to using nodes, it's like you have to hack it into existence, almost in a boolean way. It's strange to my mind right now, but I'm slowing getting there. I need to take it one small step at a time, trying out simple shapes and getting more complex each time.

Well, there's also snapping your mind to this way of thinking
That is sooo true! Completely different from modeling some shape. Took me some time too to get here and I am still way behind
guys like Simon Thommes and.....luckily many share their knowledge these days.

spikeyxxx I remember Simon Thommes saying in one of his "Procedural Shading" videos that the advantage of a node tree is that you can move the nodes around until you get the desired result. So, he's sometimes also relying on the trial and error method😉.

So, he's sometimes also relying on the trial and error method
Well that is sometimes easier than figuring out the exact order of the Nodes....you can always figure it out afterwards, when you have found the correct way, why it has to be like that 😉


spikeyxxx I'm just reading about the "Mapping Node" and the order of transformations in the "Blender 2.93 Manual":
 Vector Type
The node applies the transformation differently depending on the semantic type of the input vector.
 Point
For this vector type, the node performs a straightforward transformation.
Transforming a texture coordinates is analogous to transforming a UV map. For instance, translating the texture coordinates along the positive X axis would result in the evaluated texture to move in the negative X axis, much like if one translated a UV map. Similarly, scaling the texture coordinates up would result in the evaluated texture to scale down. So transforming the texture coordinates would appear to have the opposite effect on the evaluated texture.
The order of transformation is: Scale –> Rotate –> Translate, which means:
Translation moves the input along the local rotation axis.
Rotation rotates the input around the origin of the space.
Scaling scales the input along the global axis.
 Texture
For this vector type, the node performs an inverse transformation.
Inverse transforming a texture coordinates would, as opposed to the Point type, transform the evaluated texture itself. For instance, translating the texture coordinates along the positive X axis would result in the evaluated texture to move in the positive X axis, as one would expected. Similarly, scaling the texture coordinates up would result in the evaluated texture to scale up, as one would expect.
The order of transformation is: Translate –> Rotate –> Scale, which means:
Translation moves the input along the global axis.
Rotation rotates the input around the translation vector.
Scaling scales the input along the local rotation axis.
I'm wondering what "global axis" and "local rotation axis" are meaning here and why for example "Scaling" in "Point" mode uses the "global axis" whereas in "Texture" mode it uses the "local rotation axis".
And what are the usecases for the "Normal" and "Vector" modes?

The order of transformation is: Scale –> Rotate –> Translate, which means:
Translation moves the input along the local rotation axis.
Rotation rotates the input around the origin of the space.
Scaling scales the input along the global axis.
Just read those 3 lines from bottom to top (in the order they are calculated) then it makes more sense ( I hope...otherwise just ask again and I will try and explain ti better).

And what are the usecases for the "Normal" and "Vector" modes?
I don't know, have never used them...apart from behaving different, all 4 modes get the job done so I just stick to Point, so as not to get confused...there are situations where you want a different order, but then you can use two Mapping Nodes after one another (as explained before in Kent's stylized forest course). Remember that Point is the cheapest version of the Mapping Node; all others must first convert by multiplying with a Matrix...

spikeyxxx And why is it important that the scaling is done along a global axis whereas the translation uses local coordinates?

duerer things are somewhat different than I thought and the Blender Manual is not quite clear....
Scaling scales along the input coordinates axes, not along the World axes! This Cube is rotated 90° around the Zaxis, so the Generated Coordinates have rotated with it:
Point has scaled first along the Cube's Xaxis and then rotated. Texture has first rotated and then scaled along the rotated Xaxis.
Again, seen from the top:
A slightly different setup to show the different X axes when changing the Location:
When set to Vector, that is the same as Point, but without the (ability to change the) Location.
Normal is the same as Vector with inverted Scaling and then the result is normalized (divided by it's length when not zero and left (0, 0, 0), at the Origin (where the length is zero)):
Because the resulting Vectors are normalized, scaling uniformly has no effect:
When to use these? Maybe to create cool effects like:
I don't know. The Manual says:
For this vector type, the node performs the inverse transpose of the transformation and normalize the result. Such transformation ensures correct normals after nonuniform scaling. So this type should be used when transforming normals.
I do not know what they mean by 'transforming normals' 😢
The Cycles Encyclopedia says:
(Btw. did you get the 2.83 version yet?)
So far I have not seen anyone use Vector or Normal yet.
I'll have to rewatch jlampel 's Shading fundamentals. As far as I can tell (but I haven't finished it yet...) he doesn't cover them in his new Texturing course.

And there is a bug:
Changing the Rotation slightly, or the Scale, gives the right result
Only in Cycles, Eevee is correct:

Thank you, spikeyxxx, for these indepth explanations 😀! Now, I have something to study 😉🕵️♂️👨🎓!

spikeyxxx And yet another question: Do you know what the "round" function of the "Math Node" does with a value like 0.5? Does it round up or down?

0.5 is Rounded to 1. (Just like in mathematics 🤗 ):

Oh I understand this one! That's what I do with math grades.

spikeyxxx And I always thought that I have the free choice whether I want to round 0.5 up or down 😉😁! But that's probably because we're living in a "Matrix" 😉😁🕹!


Chapter 13 Coordinate Types takeaway:
 Generated takes into account world coordinates
 Object the world origin
 UV by unwrapping
 Normal by the way normals are pointing perpendicular to the face
 You can separate coordinates XYZ with the node
 Window is fixed to the view, same as Camera I think
 Reflection simulates how and object would reflect based on the angles and stuff
Moving on

 "Generated Coordinates" take into account the "Texture Space Box" (not to confuse with the object's "Bounding Box"!).
 "Object Coordinates" are referring to the origin of an object.


I have a math question.
I am writing a script to add clouds at the press of a button. I have finished the script for one cumulus cloud and it works.
The question, I have added a Vector Curves Node but cannot for the life of me figure out how to adjust the curve in the script, so I was wondering if there was another option, I was thinking of a Separate XYZ Node, do some math, then a Combine XYZ Node, any ideas??
or maybe jlampel or theluthier maybe you could give me a hint on scripting the curve if it is even possible.
Thanks in advance and appreciate the help.
This is what I have. Curve is manually adjusted

Wait, you're doing scripts? so what was that about your head blowing up upon entering this here math domain all about? Adrian just be like ok, and wow because, tssss I mean people here lately are like everyone over achievers. What happened to the days when just being a modeler was enough? Can people even do math in peace these days? jesus.

That's awesome, good for you adrian2301 !
Nodes are... not particularly fun to work with in Python, so I'd actually take a totally different approach and save the nodes in a group in a blend file next to the script and then just append it in.

Thanks jlampel , it's been years since I did any scripting. This was just an exercise to learn scripting with Blender.

adrian2301 treating it as a math question; you can write every curve as a mathematical expression. In your example that would be a cubic formula, but you could approximate it with a quadratic one like so:
You have 3 points given on that curve (I simplified the numbers a bit), so if the expression you are looking for is of the form:
ax² + bx + c
then you get 3 equations:
for x= 0.5: 0.25a + (0.5)b + c = 1
for x=0: c = 0.5
for x= 1: a + b + c = 1
You know c from the second equation, so you are left with a and b, but multiplying the first one with 2 and adding it to the third one gets rid of the b, therefor you can evaluate a and from there you can calculate b.
Had to make a correction, b/c your curve is not quadratic, but cubic, but....
The thing is, in general, if it has to be exact, you're in trouble, but to approximate a curve can be as difficult as how good the approximation has to be ;)

Thanks spikeyxxx , I knew there would be a calculation that could be used instead of the Vector Curve Node, I also knew that you would know that.
This is the node set up for the Cumulus cloud in theluthier clouds course, so the curve doesn't need to be exact. after all a cloud doesn't have an exact shape. ⛅

I figured that it didn't have to be exact in this case ;)
If you know some shapes of basic curves in math, than you can easily approximate what you want; like sine/cosine, tan, quadratic equations,...
This is also usually used to calculate Fresnel (with a fifth power); most famous in CG is Schlick's approximation for the Fresnel curve, but the guy (Schlick) has done more in this area, basically making easier to calculate approximations of difficult functions.

adrian2301 That's really cool what you're doing with scripting. I'm unfortunately not that familiar with Blender and Python despite some basic Python knowledge. But hopefully, I'll get a better understanding of procedural shading and its usage for the creation of 3D objects.
Another point: I'm wondering why Simon Thommes uses the "RGB Curves" node instead of the "Vector Curves" node.

duerer I don't know why, it depends on the situation I guess. They are not exactly the same:
Vector Curves consider the inputs between 1 and 1 and outputs values between 1 and 1. Outside of that range it just keeps going in the direction it has (linear extrapolation:
RGB Curves does the same on the interval 0 to 1:
Now, if you use Generated Coordinates, that go from 0 to 1, Vector Curves only considers that part of the Curve:
While RGB Curves uses the whole Curve:

spikeyxxx So, instead of mapping to the interval [0, 1] and then using an "RGB Curves" node, Simon Thommes could have directly used a "Vector Curves" node ?
One main difference between both nodes is obviously that the "RGB Curves" node has the "C" button to operate on all three channels at the same time.

duerer that depends on what he was doing., what values he was mapping to [0, 1]..(I am not (yet) a Cloud member...)
Yes, you are right of course; that C(olor) button is a major difference, but I thought that so obvious, that I didn't mention it ;)

Thanks, spikeyxxx, your answer was the 123rd reply. Just mention it since we're in a "Math Lab" 😉😁!


Chapter 1:4  Value Control, takeaways:
 When you are controlling values and you see the gradient in a flat plane moving left and right, you'd think that's the only thing that is happening, but actually values are causing a shift in the Z axis as well. The handy value graph is a great tool to visualize the height information.
 The operation Add and Subtract shifts the values up and down.
 The operation Divide and Multiple scale the values.
 There's some talk about linear interpolation along the gradient that I don't quite get. It seems to be something about the gradient just going from left to right.
 The Power operation introduces curvatures and bending.
 The color ramp node is great for remapping a gradient, but even better is the map range node.
 Remapping the values linearly? I don't get that. But I think it has to do with how Spikey has been throwing a straight line in the Cartesian plane sometimes when showing some math.
 The efficiency of the node tree is something to keep in mind since it can bog down a scene with too heavy computation.

dostovel Remapping the values linearly is the same as linear interpolation, which is a fancy way of saying something like: "draw a straight line between the two given points."
Here 0 'goes to' 0.5 and 1 'goes to' 1. Then, because there is a straight line connecting them, 0.5 goes to 0.75, which lies exactly halfway between 0.5 (which is where 0 is 'mapped to') and 1 (where 1 is 'mapped to')
Should you make the line longer (but keep it straight and through those points), then that is called linear extrapolation, to hide the fact that it is just a straight line. Otherwise people might recognize that Math is not so difficult and mathematicians aren't very clever at all....

Ok yeah, thanks Spikey, I thought that was where that linear thing was going, you had mentioned it before and it came to mind when I heard it in the tutorial.


Chapter 21: Noise Textures takeaways:
 It was just describing each noise textures and what they do, giving an advice here and there
 The thing that stood out the most was the noise texture centered around 0.5. I saw Ingmar asking about that and Spikey giving an explanation, but that is to advanced for me right now. For the moment I'll keep in mind that Noise Value Texture values are around 0.5

This is next level! I've got my note pad out
Also very cool that you're writing an instacloud script adrian2301 🙌