All example project files for this and future tutorials can be found here https://www.dropbox.com/s/e3kio1s5q3hlvp7/Unreal_Tutorials.zip?dl=0

Please download and follow along with the examples and experiment - always the best way to learn!

Firstly we're going to be looking at the various Math nodes available in the Unreal Material editor and give a few examples of how they might be used within our shaders.

 

Add/Subtract

The most basic functions but used all the time in Shader writing.  Note you can add a 3 Channel Vector to a Scalar but not add a 3 Channel to a 2 Channel.  Adding a Scalar to a Vector just adds the Scalar value to every value in the Vector.

(quick aside on terminology:  a Vector is anything containing more than one value - 2, 3, or 4.  A Scalar is just a single value.  Colours are a 3 channel vector: RGB or a 4 channel vector RGBA - trying to do maths between vectors of different lengths with often create errors but Unreal will inform you when this is the case.)

Each channel is added separately so 1,0,0 + 0,1,0 = 1,1,0 or Red + Green = Yellow to put it in colour terms.  

Useful for combining masks or for overlaying a glowing part of a material.

Multiply/Divide

Used just as much as add and subtract and the same limitations for Vector length apply.  

Again each channel is multiplied separately so 1,0,0 * 0,1,0 = 0,0,0 or Red * Green = Black.

Useful for combining mask or for tinting colours - set up a tint by multiplying by a Vector Parameter set to default at 1,1,1 

OneMinus

This is basically a special case node that is the same as using a Subtract Node but included for legacy/convenience reasons.  

Simply it just takes the input away from 1 - this has the result of inverting a black and white mask.

Note this doesn't need to take a Clamped input but values over 1 when OneMinus'd will result in negative numbers which might not be desired.

Fmod - Floating Point Remainder

This is a more obscure math function and one that I personally hardly every use.  It returns the floating point remainder of a division.  Which in this example means that 4.4 is divided by 2, which goes 2 full times, and the 0.4 remainder is returned.  

Can be useful for returning repeating fractional parts of a Time or Sine function but i tend to use Frac for that (which we'll cover shortly).

Power

Something to the power of 2, or x^2 as it's written, means x multiplied by itself 2 times.  This has the effect of creating more contrast in an image, as values close to black (0) get smaller proportionally more than values close to white (1).  Note values over 1 will get larger as they are being multiplied by values over 1, and also anything to the Power of 0 is technically infinite (or not a number) which will create HUGE bloom if it accidentally gets into your Shader.

Very useful node for controlling contrast and falloff of masks.

Abs or Absolute

The absolute of a value just means to take the value and make it positive, ignoring any negatives.  I.e. abs(-4) = 4

This is occasionally useful when creating masks using complex math or for creating a bouncing motion from a Sine wave.

Mask and Clamp

There are two new nodes here - Mask and Clamp.  Mask just takes an input vector and only outputs some of its components - in this case it's taking the RGB of the texture and just outputting the R value.  Clamp similarly takes an input value and Clamps the output to a specified range, in this case 0-0.5.  Any values above of below the range are just discarded and the Max/Min is returned.  

Both of these are super useful and used all the time for splitting Vectors into smaller components or ensuring values don't fall out of a useful range, for example before Powering or Lerping. 

Note we could have just pulled a wire off the Red pin of the Texture instead of using the Mask node. 

Max and Min

Two comparison nodes which return the Maximum or Minimum of the two inputs per pixel.  

Useful for creating strange masks, such as seen here, or for creating pseudo random motion - for example on a graphic equaliser shader you could take the Max of two out of phase Sine waves to create semi realistic pseudo random movement.  

Ceil, Floor and Frac

These three nodes are similar:  Ceil or Ceiling takes an input and returns the next integer rounding up, Floor does the same but rounding down and Frac or Fraction just returns the floating point part of the value.  (quick aside on terminology: an Integer is a whole number ie, 1,3,-2 etc. a Floating Point or Float is a number with a decimal i.e. 1.25, 3.5 etc.  generally in shaders we only use Floats and not Ints, unlike in Code or Blueprints)

Note in the example I've taken a gradient from a UV layout (I'll get to this in the next tutorial) and multiplied it by 5 to get a larger range.  Unreal doesn't have bloom in the material editor so the preview only shows White even though the values are over 1.  After the Ceil or Floor I divide back by 5 to get a visible result.  Note the Black in the Floor example and the White in the Ceil, due to rounding down and up.  

Frac is the most useful here generally returning repeating values from something like Time or Sine but Floor and Ceil have their uses too.  

IF

This node looks more complex due to having more inputs but really is quite simple.  Basically it compares two input values A and B and returns a different input value if A>B (A is greater than B) or if A<B.  There is also a special case for A=B which is basically never really needed in shader writing (it defaults to A=>B if this pin is unconnected.)

Try connecting the Time Sine Abs nodes to the B input to see how this animates.  

This node is somewhat useful - generally better used to mask areas off due to the hard edge it creates.  I'll show you a better method for creating nice soft masks later in the tutorial.  

Lerp or Linear Interpolate

Now we're talking - this node just takes two inputs and blends between them, based on an input value (0-1).  Values of 0 will result in input A and values of 1 input B.  This is a real workhorse of a node in shader writing, being used all the time for any manner of things.  Try plugging the Time Sine Abs nodes into the Alpha input.  

Note this will accept values greater than 1 into the Alpha and will just extrapolate out linearly from the inputs it's given.  This can be useful, if you're using a Black input in A for example, when the results make sense, but Lerping between two colours, such as here, would probably give  undesirable results with values over 1 - try it and see what happens.  

Append

This node is basically the opposite to the Mask node we covered earlier.  It take two inputs and outputs them combined, such as in the example where we're combining three scalar values into a Vector 3 or Colour.  

Another indispensable node when working with Scalars and Vectors. 

Time and Sine/Cosine

The Time node returns the current game time in milliseconds - very useful for creating animated shaders.  Generally we have to process this somehow to create a repeating value so we don't just have values that get bigger indefinitely.  This is usually done with a Frac, to get a repeating 0-1, or with a Sine, to get a oscillating -1 to 1.  Combining two or three Sine waves, with different periods, together can create a very believable approximation to random motion.  

Note the Constant Bias Scale node - this is basically just an Add and Multiply node combined into a single node for ease of use.  The default settings of 1, 0.5 remap the -1 to 1 range of a Sine wave to 0-1, personally I don't use them often as you can't see the values inside the node from the shader network view, making it harder to read the shader but it's up to you.  

Masking

Finally no new nodes but an example of how we can combine a few math nodes to create a nice soft masking effect - here we're subtracting some input value from our noise texture and then clamping back to remove any negative numbers we've created.  Finally we multiply by the reciprocal or our input value to remap the range back to 0-1.  

This is a super useful technique for creating easily controllable soft edge masks from a texture.  Similarly if we wanted to harden up the mask we could multiply by a value and then clamp 0-1 again and remove anything over 1, resulting in a harder mask, but keeping the soft edges, compared to using an If node - try it out for yourself.