Basic Shader Math - Shader Graph Basics - Episode 4

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
today we're doing some basic math in our first shader so let's go [Music] so last week we created our first shader with just a simple color this week we're going to talk about the simple add subtract multiply and divide nodes and how to use them but before we do that i want to recommend that you go back and watch two videos that i created in an earlier series the first one linked right here goes over the basics of pbr or physically based rendering and helps you understand what all the inputs on the root node or master stack in unity are four this is important information that i'm not going to cover again since i already went over it in that video the second video that i'm going to link right here explains what data types are when building a shader different nodes accept various data types as inputs and generate specific data types as outputs so it's important to understand this principle as well so please go back and watch that video so you'll understand what data types are and how they're used one thing that i will mention about data types here is in unity data types are represented by the color of the port and the wire connecting the nodes together blue is for a single channel data type green is for a two channel data type yellow is for a three channel data type and purple or pink is for a four channel data type sometimes you can see the wire change color uh when you wire it from one port to the next for example if i take this four channel data type and wire it into a three channel port you'll see that the wire goes from pink to yellow and what that means is that the engine is automatically converting this data from four channels to three under the hood for you in this case all it's doing is just using the first three channels and throwing the fourth one out and it does that just to make your life easier so you don't have to uh do all kinds of data type manipulation it just handles that automatically for you and converts from three or from four to three but it's something that you should be aware of because if you expect to be using the fourth channel of data here well you'd be disappointed because that data gets thrown away in the process of coming from this node to the master stack here the same thing happens in unreal as well so if i wire the four channel data coming out of the texture into the color socket here which is three channels it's going to throw the fourth channel away but in unreal there's no visual indication that's that that's happening it just happens under the hood but you should definitely be aware that it's happening so you know not to expect your fourth channel to be coming into the base color for example all right next let's talk about the overall structure of the shader graph on the left hand side of the shader we start with nodes that bring data in from outside the shader and then in the middle of the graph we have nodes that process and manipulate that data and here we have the example of the math nodes these are the nodes that we're going to learn about today and they fall into this category of nodes that accept data coming in process it and then spit out the process data on the right hand side and then finally our process data is plugged into the input data ports on the root node or in unity they're plugged into the input ports on the master stack and so we have our input nodes on the left we have our math or processing nodes in the middle and then we output the final process data on the right uh in the root node or in the master stack so our data is flowing from inputs on the left through the middle processing and then being output by the root node or master stack on the right so we're mainly going to be focusing on the math nodes today but i have brought in a couple of data input nodes so that we'll have some data to work with so here i have the uv coordinate node the texture sample node and the time node and don't worry we're going to go over these more in depth in future videos but i just want to explain just briefly what they're doing today so the uv node is bringing in the texture coordinates that are on the surface of the mesh so if i open up the little preview here you can see that i have this data is in two channels it's in a u which is horizontal and it goes from zero to one from left to right and then the v data goes from uh it's vertical data so it goes from zero to one in this vertical axis and then here on the upper right hand side you can see that the data turns yellow where both the green and the red are contributing to the color and it's the same thing in unreal except for the data in this particular preview is going from top to bottom instead of bottom to top so i'm going u from left to right and the v from top to bottom this is data that is on uh the surface of my material so if i plug my uv coordinates right into my color node you can see that this cube is mapped uh from left to right for the u data and from top to bottom for the b data for the v data and each of the sides is mapped individually with these uv coordinates and in unity if i plug this into my color you can see that my preview here is mapped from bottom to top so i have zero in the u to one in the u and then going vertical from zero to 1 in the v coordinate all right with the texture map node i'm able to bring in textures that the shader then can use in lots of ways i can sample the color of the texture using the rgba port here so if we plug that in you can see that now my texture is applied to the preview and i can also look at my texture here or i can sample the textures channels individually using the g b and a ports like this so if i wire the r port in you can see that my results in the preview are going to be black and white and it works the same way in unreal i'll wire my rgba into my base color on the root and get color or if i wire just the red channel i'll get the black and white data from that one single channel and finally we have the time node and time is a value like a clock that continuously increments and is always going up as long as the engine is running and this is a node that i can use to do animated effects or things that depend on time to change what they're doing alright so we talked about our three input nodes texture coordinates texture sample and time now let's do the main portion of our video and talk about these four math nodes add subtract multiply and divide so hopefully each of you are familiar with what addition multiplication subtraction and division are from grade school math and these nodes luckily for you they do the exact same thing in a shader add will combine two values together and sum up the result of the two values multiply will multiply one value by another value and subtract will remove one value from another value and divide will cut a value up into the number of pieces specified by the second value now the first thing that i want to mention is that add and multiply are the two cheapest nodes that you can put in a shader and these nodes are great because add and multiply can sometimes be done together both and add and multiply together in one single instruction that runs in one cycle on the graphics card and so that means add and multiply can be done very very cheaply so if you ever have the option to use a really complex math node or just a single add or a single multiply or maybe an add and multiply together you should always use these nodes because they are the very cheapest nodes that you have available now the next thing that i want to mention is that often when we're dealing with data in a shader we're talking about data that is in the range of zero to one so obviously data can go as high as you want it to you can end up with numbers with uh values of a hundred or more if you want but usually we're working with data in the range of zero to one and the reason for that is that normal colors like this rgb and a value red goes from zero which is black to one which is white so in our texture map here this data here that's black is a value of zero and this data here that is white is a value of one and so when we manipulate this data we're staying within this zero to one range not only that but when i pass the color data into the base color socket it actually gets clamped at one so anything higher than one is basically just getting thrown out so we're staying pretty much within the zero to one range now there are lots of exceptions to that rule but i mention it because values that are in the range of 0 to 1 are the most common now there's an important reason that i bring that up and that is generally when we think of multiplying a number by another number we think about the values getting larger for example if i have a value of 2 and i multiply it by a value of 3 the result is going to be a larger number i'm going to end up with a value of six because two times three is six so the value coming out of here is going to be six but if i plug it into my base color we're just going to end up with white and that is a value of one which means everything above one has been thrown away and just clamped at one because colors can't get brighter than one at least not in the base color channel if i put this in the emissive color channel because we're going above one we'll end up with a value that's really bright and starts to glow and that's pretty cool but that's kind of off the subject anyway getting back to what i was talking about let's change these numbers here to values that are between zero and one let's do like point five and point five now there's an important property of of uh these numbers that that are a little bit different with multiply when they're below one so point five times point five i actually get a result that's 0.25 so it's a smaller number than either of the input numbers because they're less than 1 multiplying them together gives you a lower value than you would normally get and so i'm using multiply in this case to darken the the original value so if i take my red color here coming in and let's just take a look at it the way that it looks originally so you can see that the whites here are nice and bright but then if i multiply that value by let's say 0.1 and then use the result of that you'll see that i end up with something much darker and that's because this multiply by 0.1 is reducing the value instead of increasing it so like i said numbers above 1 will increase but numbers less than 1 are going to darken or decrease the value and this is basically limiting my data here my data in my texture is between 0 and 1 but when i multiply it by 0.1 it means that it won't go any higher than 0.1 so my brightest point on my cube here is going to be 0.1 and then it's just going to go down from there everything else is going to be darker than that all right so that's how multiply works is kind of an interesting property of multiply with values that are less than one and since we're dealing generally in a shader with values that are between zero and one it's important to understand that multiply is going to be darkening our values all right adding nodes together is gonna be pretty much it's it's pretty much doing what you think it's it's gonna brighten them so if i take the data from my red channel and pass it into an ad and then i add 0.5 to that i'll end up with something that's much brighter and so here you can see um the data that used to be 0 is now 0.5 because 0 plus 0.5 is 0.5 and the data that used to be 1 is going above 1 to 1.5 but in this case it's getting clamped going into my base color and ending up with a value of of 1 anyway so the the values above one are just getting thrown away okay so add is working pretty much like you would expect subtract is the same one the same way it's going to decrease values so if i pass my texture value here into the subtract node and i subtract 0.5 pass that into base color now you can see that the areas of my my texture that used to be a value of 1 have now gone down to 0.5 and the values or the areas that used to be a value of 0 have actually gone below zero these areas are negative 0.5 but again it gets clamped when it goes into the base color and so it just ends up as a value of black all right so that's how subtract works the same principle also applies i've been up until now i've been using this single channel but the same principle also applies with color if i add a value of 0.5 to rgb it's gonna add 0.5 to each of the individual channels and brighten it up same with multiply if i multiply rgb by 0.1 it's going to darken all three of the channels so i can multiply red green and blue by point one to darken i can add red green and blue to brighten and i can also do the same thing with subtract so if i wire my red green and blue into my subtract node then i end up with colors that go below zero and end up with values that are just clamped at zero but become black all right i'm going to disconnect the wires here and i want to show you a couple of tricks that we can do with these nodes using them together so let's say i have my red channel color here and i've got this area that's dark and i got this other area over here that's bright what if i want to invert it so that the brights become dark and the darks become bright i can do that using 1 minus the value so i'm going to give myself a constant value of 1 and then i'm going to bring my subtract node over here and i'm going to plug 1 into a and i'm going to plug my texture into b so i'm subtracting 1 minus the value coming in and when i plug that into my base color now you can see that my values are inverted so the areas that used to be bright are dark and the areas that used to be dark are now bright so if i have a value of 0.9 for example 1 minus 0.9 becomes 0.1 and the inverse is also true if i have a value of 0.1 and i 1 minus 0.1 it becomes 0.9 so 1 minus is a way to flip the values coming in from your texture or from any other source for that matter and this is so valuable that there's actually a built-in node for doing it so if i type one minus you can see that there's a node here that does it in a single node instead of uh one subtract and then the result so i can just wire this directly in and then wire it out and i get the same exact result now uh it's just because it's a single node instead of two it doesn't make it any cheaper it's just a little bit cleaner to use in the graph to use the one minus node in that way and in unity it's exactly the same if i hit space bar to bring up the create node menu and type one minus here's my unity one minus node and i can wire my red channel in and then uh the result going out and i get the same result here uh with my values inverted all right one more little trick and then i'm going to show you some more concrete examples sometimes the data in my textures the data in textures is stored in the range of zero to one but i actually want to expand that range to the range of negative one to one for example if i'm dealing with normal map data and so in order to do that the first thing that i need to do is use my multiply and so i'm going to take my data and i'm going to multiply it by 2 and in this case 2 happens to be the default value of the multiply which is convenient and so if i take my 0 to 1 range data and i multiply it by 2 now i have data in the range of 0 to 2. it helps to think of the the results of these nodes in terms of ranges because i don't know exactly what the value coming out of here is because it's actually different for every pixel and so if i think about it in in terms of a range it's a little bit more useful so my my current range is 0 to 1 and then by multiplying it by 2 i've moved it to the range of 0 to 2. now i'm going to grab my subtract node and wire the result of this in here and i'm going to subtract a value of 1 and this is convenient because 1 also happens to be the default and so now i've taken my data that was in a range of zero to two and shifted it down so that it's now in the range of negative one to one and that was the uh the result that i was looking for so multiply by two and subtract one will shift data from the zero to one range to the negative one to one range which is what i need for uh normal map data and and other things like that now normally if you bring in a normal map and you set the type to normal or the equivalent in unreal uh it will handle this times two and minus one for you and so you don't have to do this yourself but if you have a custom texture where you've packed normal that map data into some of the channels and other data into other channels you're going to want to condition that normal map data or times two minus one to expand its range uh to the normal negative one to one range and in order to do that you need to multiply by two and subtract one so there's a nice little trick the inverse is also two if i want to take data in the range of negative one to one and convert it to zero to one in that case i'm going to multiply by 0.5 and then add 0.5 because it's going to shrink the range to negative 0.5 to 0.5 and then add a 0.5 to move it into the 0 to 1. all right so just a couple of tricks uh things that you can do with these simple math nodes uh to manipulate your data change the ranges uh brighten and darken all right now let's take a look at two real world examples and i'm going to walk you through what these examples are doing and for each example i'm going to show you what the multiply add subtract and divide nodes are doing so let's take a look all right so here in this first example i've created a shader that scrolls the uv coordinates or moves the texture across the surface of the model and the way this is working is i've taken my time node and i've multiplied it by a value of 0.2 now this value of 0.2 because i'm multiplying it by time is used to control the speed so if i set this to something like 2 it's going to go really fast because the the curve of time has gotten much steeper and it's just going quicker now because it's multiplied by 2. but if i multiply it by a value of 0.1 for example now it's going slower then i've taken my texture coordinates and i've added time to them so here's my time multiplied by 0.1 so that's the the speed of time and then i've added that value to my texture coordinates which means that every frame the additional value of time is going to be added to the texture coordinates so it's going to continuously move higher and higher and higher and i've added it to both the u and the v so it's moving in the positive direction in u and in v and then i use those texture coordinates with the time added to sample my texture and then i pass the color of the texture into the base color socket now let's switch over to unity and you can see that i've got the same thing i've got my uv coordinates i've got time multiplied by 0.2 and i can slow it down by multiplying by a value of 0.1 and then i've added my time to my uv coordinates and then use my uv coordinates to sample my texture and pass my texture into base color now you can see that the preview cube in unity is mapped a little bit differently and so the data is moving in a different direction the the scrolling is happening in a different direction and it's obvious why that's happening if you look at the uv coordinates on this preview because my zero point is down here in the lower left corner whereas in unreal it's here in the upper left corner so here i'm moving up and to the left and here i'm moving down and to the left so a little bit of a difference between the two engines there but for the most part you can see that the the nodes here are exactly the same and they're doing the same thing all right let's take a look at one more example alright in this simple example you can see that i've taken my uv coordinates and multiplied them by a constant value of six and so in my little preview cube here you can see that my texture is now tiling six times across the surface instead of just being uv coordinates from zero to one now they go from zero to six in the same amount of space so my texture map is tiled six times across the surface then after i sample the texture my wire goes out here and it's connected to this divide and i've divided my value by 4 which is darkening it so whereas values that used to be 1 or white are divided by 4 now so now the maximum brightness is 0.25 so i'm using my multiply with the texture coordinates to tile my uvs before sampling my texture and then i'm using my divide to darken the value of the texture aft after it's been sampled and if we switch over to unity you can see that i'm doing the same thing here i've got my uv coordinates multiplied by six going into my texture sample and then dividing them by a value of four so i get this nice uh texture that's tiled six times across the surface and then darkened down to a maximum value of 0.25 by dividing the output by 4. so pretty cool you can see that unity and unreal are doing the same things and i'm using the math nodes of add subtract multiply and divide to manipulate my incoming uv and texture data oh and we also threw a little bit of time in there as well just for fun all right that's it for this week what i'd like you to do now is put a comment down below about which of the following two topics you'd like to see covered next week we can either go into detail about textures and talk about different texture compression settings and when to use dxt1 versus dxt5 and all of the details about setting up textures or we can talk about the lerp node linear interpolation so i'll let you guys choose based on what i hear down in the comments do you want to learn about what the lerp math node does or do you want to learn all of the details about texture samples let me know in the comments anyway i hope you enjoyed the video and i hope you have a great week everybody thanks a lot for watching [Music] you
Info
Channel: Ben Cloward
Views: 5,033
Rating: undefined out of 5
Keywords: UE4, UE5, Unreal, Unreal Engine, shader, material, material editor, game development, real-time, tutorial, training, Unity, graphics, 3d, GPU, tech art, computer graphics, fundamentals, basics, beginning, learning, shader graph, getting started, math, add, subtract, multiply, divide, scrolling, panning, one minus, invert
Id: bihZJzeuwOU
Channel Id: undefined
Length: 28min 13sec (1693 seconds)
Published: Thu Jul 01 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.