Godot Spatial Shaders - A Gentle Introduction

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello folks welcome to the age of asparagus so i wanted to create a very simple shader for my 3d top-down shooter series and i found it way more difficult than i was expecting it to be so i thought i would create a very gentle introduction to spatial shaders for anyone else out there who might have hit the same wall that i did we'll be using godot's node-based visual shaders to create a material that causes an object's color to be related to its position in 3d space and specifically related to its depth on the z-axis i'll do my best to explain every step along the way so i'm hoping this can be useful to anyone who has never touched 3d shaders before i'm new to shaders myself so i'll probably be oversimplifying a lot of concepts but we can learn more about those later when we want to do more complicated stuff okay i've got a new project open and we're going to create a new 3d scene and in the scene let's add a mesh we'll add a mesh instance and in that mesh instance we'll give it a new cube mesh and let's go down into the material and we'll create a new shader material we'll click the material and for the shader we're going to add a new visual shader and if you click the visual shader we'll get the node editor here at the bottom if you used blender before this should be fairly familiar because it works in a lot of the same ways it's a little less flexible but it's really helpful if you have that experience so the first thing i'd like to try and explain is how does this work how does this visual shader these nodes these three different processor functions how do they work so to start let's just do something simple here by default they put us in the fragment processor and the fragment processor despite its odd name is actually where the color of the pixels are calculated the code we'll put here will run on each screen pixel that our object with this material touches so let's start with something really simple now in godot we know the albedo output albedo is what's going to set the actual color of our object so if i click this add node or i can also right click in the node area i'm going to look at that right at the top i've got color and let's just drill down here common color operation we can see we have some operations here different things we could do with colors and i see that's a vc3 so that tells me it's going to return a vector 3 but let's go here variables color constant that's what we want okay so of course you could also search color here and you'll get a list here if you knew what you were searching for color constant this gives us a nice color picker let's choose a color something red say and i'm going to connect the vector 3 output and the vector 3's here show up as this pink magenta color and i'm going to connect that to the albedo and our object should turn red and if i change this color you should see the object change as well if we wanted to change the transparency of our object we could connect the alpha value of this node to the alpha of the output and then if we adjusted the alpha of this color we would actually also change the transparency of our node but what i actually want to try and do here which seems like it should be pretty simple is i just want the color to vary based on the vertex's position in space so for example if vertex is over here would have one color and a vertex is over here it would have another color but to do that somehow we need to get the information of where the vertex is into this fragment processor and we can do that by switching to a different processor so the first processor that occurs is the vertex processor and i'm going to switch over to it now how this works is the vertex processor this function which we're basically building here visually will run its calculations on every vertex this one then this one then this one and this one in some order and then once it's done it will take its output and provide it as input into the fragment processor and these are the outputs here so when we go to the fragment processor we can get all of this data and use that in our fragment processor in that loop and then similarly all the outputs from our fragment processor are taken and provided as inputs to the light processor and then that function runs so here we are in the the vertex processor in here we can manipulate the position and the data that is stored at each of these vertices i'm just going to switch back to the fragment and disconnect the alpha there and give it a nice bright red color okay so in the vertex say for example we wanted to take each vertex and just add one to the z value of every vertex so for example this vertex would be shifted over by one this vertex would be shifted over by one this one down here below the line all these vertices would be shifted over by one and we would expect our cube basically just to be translated one in the z axis so let's try that so the first thing we need to do is we need to get their current position the current position the xyz coordinates of each of these vertices so if we right click in here and this time let's see if we can find the vertex so we're looking for inputs here okay so if i remove my search here and if i just go under inputs you can see there's a whole bunch of different inputs we can use different data in our scene that we can use as part of this function as part of this processor so under vertex here we just have the vertex so it's an input parameter for the vertex and fragment shader nodes okay so let's get this and if we connect it up to the vertex output we wouldn't expect anything to happen because it's just taking where it currently is and saying go there but what if we try and add a value to it if we right click here we can type add and we can see the different operations to add let's see what the scalar ad will do this is just like a plus we're just going to add two values that's not what we want because we have a vector 3 here so what if we try the vector add okay this might work let's punch in the vertex's position as the first vector and then for the second vector we want to add one in the z direction so we'll put that there and if we make the output of this operator the new position there we go it shifted one on the z-axis and you can imagine we could shift it on the x-axis and move it wherever we wanted to and similarly you could do other operations to rotate it or scale it or any combination of those okay so now instead of manipulating the position of the vertices i actually want to connect a vertex's position to its color data here and we can disconnect that it's not doing anything now this isn't going to change the color of your material because this is just a piece of data that's held on each vertex so this vertex would have some color data this vertex would have some color data so here we have a vector 3 right it's saying we have a vector 3 this is going to be some xyz position we are providing it to the color output which is also expecting a vector3 you can see because it's pink here but as you can imagine color is actually expecting a red green blue value and so what's actually happening here is we're saying the red value is going to be whatever the x position of that vertex is and the green value is going to be the y position and the blue value is going to be the z position so let's go over to the fragment processor and use that color data that each vertex holds now so if we right click here we can go to the inputs and if we go to the fragment inputs we should be able to find color or you can just search color there and what do you think is going to happen if we connect this to our albedo all right well that's pretty cool so let me just take a moment to explain here in case it's not obvious what's happening so i'm just going to expand the 3d view just temporarily here and make sure that this makes sense so let's pick a vertex let's pick this vertex right here sticking way out so what is its xyz position remember here is the x-axis and you can also see it up here but x is red oh wow isn't that convenient so if we're converting x to red the red value is going to be 1 right because it's right there and the y value is also 1 and the z value of that vertex is 1 as well that's the point 1 1 1 this vector here coming from the origin out to that vertex in 3d space so if this is the xyz vector3 vertex position and we're providing this as input and saying i want you to be this color r g b well this albedo is going to be on a scale from zero to one so one is going to be full and of course one one one rgb is white and we get a white vertex and we could pick a different point now remember that this cube is centered on the origin here it's it goes one in the positive x direction and then one in the negative x direction for all of these so let's take this point right here so this point what is the vertex position of that point well x is zero y is 0 and z is positive 1. if we made this an rgb color instead of an xyz position we'll have a blue vertex and that's what we have a blue vertex right there and of course anything where y and x are negative will also be blue anything kind of down in this quadrant down there right is going to be blue now i'm working in 3d space here so that's kind of hard to draw but if the red or green is going to be anything negative negative one-half negative whatever it's just going to be cropped to zero when it's converted to a color similarly if we get a value that is higher than one say 25 it's actually just going to be scaled down to one because color is only red from zero to one in the shaders here okay so you could imagine obviously that this position is going to be one zero zero right rgb so that's going to be the red vertex and anything down that way is also going to be red and this vertex here would be x is one y is zero z is one which in rgb would be red and blue which are going to comply combine to make magenta right or like purple so and anything where green is negative anything where the y is negative down that way is also going to be purple or magenta and you can imagine all the normal colors and combinations of colors we find yellow up here we find cyan here blue magenta red and then green white is going to be this corner and you can imagine the origin the origin is going to be 0 0 0 and that's going to be black so if we rotate this thing around we should find a whole section of our cube that is black and there it is of course the blacks part would start at the origin and anything here where x y and z are all negative this kind of not quadrant because we're working in 3d i don't know is this called an octant so this octant we'll say is uh is going to be all black whoop okay well i just looked it up and actually it is called an octant so that's cool okay so let's try something now i'm going to select my mesh and i want to duplicate it so i'm going to ctrl d and i'm going to move it over and actually i'm going to hit 7 to go into top view and i'm going to move this into the top left quadrant here or you'll see in a moment we're going to put one cube in each octant so i'm gonna duplicate that again over here uh i'll select both of these i'm holding control and then to select both and then ctrl d and i'm gonna move them duplicate them down and then if i hold shift i should be able to select all four of those i'm going to leave the middle one i'm going to move those up and then i'm going to ctrl d and move these down so i have one cube in each octant and then i have one still at the origin and that's just going to let us play around and see what's happening to our cubes okay so let's go back to our material here and our shader so one thing you'll notice obviously is that the vertex coordinates are local coordinates right when i move these cubes these cubes in different positions they all have the same colors on the same vertices this here which we know is one one one xyz because it's one one one rgb white but that's the same as the one down here so i don't want that this wasn't what i was trying to do what i want is an object that is way down here in the z axis or way positive in the z axis would actually have a different color so what we need to do is convert our local coordinates into global coordinates so let's go back to the vertex processor and we're going to do a little math on the local vertex position and it might just be good to think of this as a formula because it's going to work but it involves a little bit of matrix algebra and it's not really important to understand so let's right click here and under input we're going to find the world vector let's just type it in world vector and we're going to multiply the world matrix with the local vector and that will just convert it to a global vector so instead of the instead of giving it 1 1 1 for this point locally we'd be giving it whatever vector that is from the global origin now let's right click and we'll look for some sort of multiplication we want transform multiplication that's not the one we want because this you can see more transforms show up as orange and we want to multiply a transform with a vector so let's go there we go transform vector operator let's try that so we're going to plug in the world we're going to plug in the vertex and the output this output here will be the global coordinate of each vertex and we don't actually want to plug it into vertex that would be interesting um we want to plug it into what's going to happen i want to do it anyway oh it scales them out neat okay that's not what we wanted what we actually want to do is plug it into the color so i'm going to disconnect that by dragging it out and then i'm going to take the this here the global coordinate of each vertex and i'm going to save it in the color output and because we already connected the color output to the albedo now we actually do get each cube taking the color you would expect from its octant which is pretty awesome now the reason they're full colors is because as i mentioned before the rgb only goes from zero to one so everything beyond one is going to be just fully saturated in that color so because our cubes are kind of like way out much far beyond one unit in fact one unit is encompassed fully by that middle cube and you should notice the colors transition as you cross over into any value from zero to one so if i take our red cube here and i slowly cross it this way you'll see you should see the vertices change there you go right there you go look it's turning magenta and it should be fully magenta basically anything that is one or higher similarly our black if we moved it up should turn green once it passed the one mark so here it's going to be zero and then it's going to slowly turn green until boom if we hit uh if we looked in front view here we don't have a grid but once it hits y equals one it'll be fully green so hopefully by now you should have a feel how we can use the position of a vertex to manipulate its color okay so i'm just going to get rid of actually all of these except for our first one and i'm going to hit 7 on my number pad and i'm just going to duplicate this ctrl d and i'm going to move it out and i'm just going to have a little gap so we can see the position and control d here and we'll just go out to about 10. so remember this is 10 units so positive 10 units negative 10 units there we go and we're still using the same shader so that's kind of what we'd expect let's go back to our material here and i'm going to move this up a bit because we're going to need some room now this perspective is going to get a little wonky that's okay so now instead of using the full vertex position i actually just want to use the z value of the vertex's position i don't want it to change color this way or up or down or left or right i want to change it in depth along the z axis which whoa i place these in the wrong spot that's annoying i want them on the blue z axis so i'm going to select them all here and if i go to 7 top view i'm going to rotate them and let's control z that i'm going to turn on snap and i'm going to rotate them here that's what i wanted on the z axis okay back to the material we'll zoom in and try and get a decent view here so let's take this color input which is just holding the vertex positions now the global vertex position and let's break it up into xyz and we can do that with a decompose node vector decompose so that's just going to give us access to the xyz values and instead of plugging in all of them i just want to plug in the z value but the z value is a scalar it's just a number so when i try and plug that into a vector the good o is just going to convert that for me so it's going to oh your z value is 1 for example well i'm just going to give it 1 1 1 then so that's why it goes white past that equals positive 1 and it goes black when's that equals 0 or less so we're going to take the z i'm going to move this over here we're going to take the z and we're going to create a new vector so what i want to do is i want to give it a foreground color and a background color and i want it to transition based on the vertex's z coordinate globally i want it to be background or foreground color so we need a way to add background and foreground colors and we can do that using what are called uniform variables in shader scripting and visual shaders and those are the equivalent of like godot's export variables so when we use a uniform variable it'll actually show up in our inspector and allow us to change it so let's right click here and i'm going to click type uniform and there's a bunch of different uniform values you can see the normal boolean a scalar there's a whole bunch here and so let's just pick color uniform we're going to add a color uniform and for now let's just take the output of the color uniform and we'll put it right into the albedo so it's black here but over in our inspector you'll notice a new section called shader param shader parameters and if we expand that our color uniform variable will appear and we can change it which is pretty cool we can also rename it so let's actually call this one our foreground color and it'll change here we'll set it to let's say red that didn't work red good and let's duplicate that ctrl d and i'm going to make a background color and it won't appear here in your inspector under shader parameters until you've actually connected it somewhere so i'm just going to temporarily connect it here and you can see background color appears now too and let's make that blue ish okay so how do we combine these two it'll click and pull up here to pan around we'll move these up top here so we have an a vector color here rgb a vector color here rgb and we want to mix these two based on the z values so there's actually a vector mix let's look up mix okay there we go let's do a mix s i believe linear interpolation between two vectors using a scalar that's exactly what we want so we're going to have our foreground color we're going to have our background color and right now it's mixing it half and half so if we plugged the result into albedo we should expect like a purple yeah excellent which is probably magenta except for our skies adding an additional blue right now instead of weighting it always 0.5 although we could set it to 1 and we would expect it to be our foreground color whoops which is our background color blue okay and if we set it to zero it will be our foreground color okay so what if we take our z value and use that as the weight not bad not bad so when our z value is 1 it'll be all our background color and when the z value is 0 which is here or negative it will be all our foreground color which is backwards because this is the positive z direction over here so why don't we just switch these foreground and background that's not what i was expecting there there we go so now it actually is our foreground and background colors well i hope that was uh not too painful i know the pace was slow i hope you learned something if you're here for the 3d top down shooter we're actually gonna let's save this and we're going to use this and import it into our game we'll also be adding a few more parameters for example we don't want it only to scale between 0 and 1. we want it to mix the colors from the farthest depth to the nearest foreground right like we want only this cube to be red and only that cube to be blue in it to scale all the way along so we'll be dealing that in the in the regular part of this 3d top down shooter series so let's finally let's go to actually let's go back here and this let's save this whole material so we're going to go here let's save this material and we'll call it i'm going to call it fg shader material for foreground background shader material and that's the shader we'll be using as a starting point for our 3d top down shooter
Info
Channel: Age of Asparagus
Views: 2,003
Rating: undefined out of 5
Keywords: AgeOfAsparagus, Godot, Shaders, Tutorial
Id: edITKOiqpHE
Channel Id: undefined
Length: 22min 34sec (1354 seconds)
Published: Sun Apr 11 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.