Fill Shader - Shader Graph

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello and welcome to yet another tutorial on YouTube about how to make a fill effect or for like a progress bar or something like that using Shader graph um there are a lot of tutorials out there that are going to show you how to kind of make this kind of effect happen um but what I hope to accomplish with this video is to explain the basic logic behind how you would build this if your background is coming from programming and you're not familiar with shaders or rendering techniques or any of the kind of differences that may uh you might come across when you're initially learning how to use shaders or Shader graph so what I'm going to do is I'm going to explain this technique first of all using C sharp and then we're going to work our way into shared graph a little bit later on so this is all this uh does it we have this one value that we can change here on the slider and really what this does is it just replaces one color with another one very simple so in order to uh get the the basic idea of this across what I'm going to do is I'm going to hide this and I'm going to create a new object which I'm going to use as a sort of a fill manager and I'm going to just um I already produced a few objects here before I'm going to disable you enable you that should give us a bunch of spheres yeah okay so what I'm going to do is I'm going to try to replicate this effect uh having all these spheres change color sort of uh together top to bottom almost as if they're like pixels on the screen as we saw in that um that other sphere that I was that I was manipulating so my field manager here is going to hold on to the script that's going to control all these objects so with that said let me just build a little quick c-sharp script here I'm going to call it build manager and I'm going to open it in Visual Studio all right so I'm going to get ready to start here and uh just put this together real quick and then I'll explain to her what's going on so I'm going to take uh an array of all my game objects this is going to be uh the um I'll just call it game objects I'm going to serialize the field so that it appears in the inspector despite being private and now for each of these game objects for each game object uh sure Geo in game objects I am going to add another float in here this will be a public bloat um fill height okay uh for each of these objects a Geo in game objects I want to check if the game object looks like the geo.transform dot position y position that's uh you know on the up and down axis is greater than or you know what is less than Bill height [Music] yeah let's go with that of course I have to add a semicolon up here what am I what's wrong here Bill height and oh you know what I'm going to call this film manager too I was doing some testing before I started recording and so the film manager already exists in the project um okay and if it is what I'm going to do is quite simply go Dot uh not gonna get component uh renderer we're going to take the um material color and we're going to set it to create some old coloring so if the Y position of our object is higher or sorry is less than Bill height I'm going to set this to the fill color so um so the fill color is going to be sort of on the bottom of the object and if it's not I'm just going to set it to the default color okay now in theory that should be all we need to do in order to get this quick effect in the game we just got to populate all our game objects so I'm probably after this uh compiles I'm probably going to speed this part of the video up a little bit okay and now our object is filled up with the references to all these spheres I'm just going to set our fill color let's say to I don't know red and default color I'm going to make like sort of a just a gray now when we run it here you can see that when the center of the object is below our fill height it becomes filled up with the with the red kind of like what we're showing off with that other sphere if I can just bring in my demosphere object here just to kind of play around with you can see the same sort of logic is happening here right we got one color above we got another color below and it's all based on um sort of the relative position of each of these pixels to the height of this line so let me explain that going back into the code this update Unity message method here runs every frame that the game is rendered right and within the for each Loop basically what we're doing is for every frame we're iterating on every object and then determining uh through a simple rule whether or not it should be the fill color or it should be the default color so in other words the game is constantly resetting what this color is like making an assignment for every object in every frame which you would think is wasteful and it is this is a terrible this is a terrible way to a program logic in your game because the CPU doesn't like a repetition like this when repetition is not needed however the GPU is very different and in graphics programming typically whatever you see on your monitor whatever is in this video here like even the um the unity interface here is being redrawn completely every frame and gpus are very happy with that the hardware is designed to solve very different problems from CPUs and so they're very happy to perform repetitive tasks over and over again and uh are and don't have a whole lot of processing ability for uh switching uh tasks or or threading uh much like a CPU does so when we're building our Shader it's completely normal to expect that every frame every single one of these pixels is going to be treated kind of like how we're treating the game objects in our code here we're saying this is wasteful here but the normal procedure is when drawing an object and determining whether each pixel should be above or you know one color Or Another We're actually redrawing this object every single frame by Design so if you're coming from a programming in video game stuff and you're fairly new to Graphics processing this might be a little bit of a new news for two so I want to get that out of the way to explain sort of what shaders do so here I'm going to hide my demosphere I'm going to rebuild this entirely from scratch in Shader graph using sort of what we've kind of explained is going on here so I'm going to create a brand new sphere nice and uh foregrounded there I like that and in my assets folder I'm going to create a new material I just pressed M for material I'm going to call it fill matte and I'm going to create a Shader graph here I'm going to go hdrp yeah it'll be a lit Shader graph I'm going to call this a fill Shader I'm now going to take my fill Shader I'm going to drag it onto the film mat assigning the shade of the material I'm going to take the material I'm going to drop it onto my object so a quick little explanation why I did that every object in the game can have one or more materials which is kind of what holds on to the um it holds on to a set of variables that can be tied to a Shader as well as the Shader itself so in my earlier explanation of showing that I had a sphere that you could fill and there was like a little slider on it that you could move around the material holds on to the value of that slider as well as the Shader that it's feeding it into so like Shader plus these other parameters together makes a material so that's why we have materials and shaders um so now I've uh dragged the Shader onto the material the material onto the object so the Shader is attached to this object I'm going to double click on fill Shader which gives me this empty hdrp Shader graph and I'm going to start off by adding a float up here in my uh my parameters I'm going to call this uh let's see uh fill height yeah so this is remember King what we had in our code here the fill height float which we are using to determine whether or not we should be drawing an object in a certain color or not now here's where you get to this part and if you haven't worked with Shader graph too much this kind of this is where people sometimes get lost because we can basically assume that this is a program that runs once for every pixel we said however uh taking a logic like this and applying it to a system of nodes doesn't seem intuitive off the bat to everybody and I totally get it so uh this is where I'd like to try to make the comparison using what we have in our c-sharp code so let's consider that the Shader graph really begins here and it ends here the uh for each Loop go over each game object we're treating each game object like a pixel so we can just assume that that's kind of the emulation here but this is really what we're trying to replicate so if the position the Y component of the object's position or the pixel's position is less than a fill height we're going to do something so first of all what we have to do is we have to figure this part out in the Shader graph and what we can we can call this a predicate it's actually a condition but um we can sort of um treat this as like a little um as comparison right we're going to actually uh come in here I want to point out if I hit spacebar here and go to position I have some notes here that have something to do with position and specifically this input geometry position here allows me to access the position of the um the pixel that is being rendered in this frame in this this um run of the Shader it's going to render the whole object every frame but this particular the work we're doing on this particular pixel um per in every iteration is going to give me the um the relative position of that uh that pixel According to some kind of space that we want to choose but anyway so now we have the position as a um well if I just kind of go go transform uh dot uh position we know that this is a vector three right you can see here I'll blow it up in in the video but this is a vector three and we want we're only interested in the Y component so where I hit Ctrl s for saving so what we do here is we grab our Vector 3 and there is a node which we call the split node this allows us to sort of get each of the individual components um by themselves now this here shows out three there's basically three floats that uh we could pull out split isn't really smart enough to recognize to only give us like three outputs this so uh this um uh fourth one down here is pretty useless now even though this is a position in X Y and Z the split node calls this r g and B but really it's going to map one to one in the in the order that the components are stored within the vector so our height is actually G here so I'm going to take our G and I already know that we're heading into a comparison where we want to compare this value to the fill height to determine whether it should be one color or another so I'm going to start typing comparison and now we have comparison ba and we have comparison B now because I was grabbing the G component here basically what this is going to do is it's going to draw me a comparison node but it's going to automatically plug into either a or b as I I choose so I'm going to just go with a although it doesn't really matter now in our parameters up here I'm going to grab this fill height I'm going to drag it onto this the scene here I'm going to plug it into B so now I can compare these two values if height is let's say below fill height so less than this is going to give me an output which is a Boolean which is the true or false essentially that leads into either the first block or the second block now here's why I was drawn to call this a predicate a little bit earlier uh technically a predicate is like a a function that takes in some different data makes a decision and then outputs a very simple result such as a true or false okay kind of an extrapolated condition um it's not super obvious here we could rewrite this to be much a little bit more complicated and really demonstrate what that might look like but just know that we can take this Boolean result we pass that in as the the input to a uh what do we call this one a branch I'm going to pass this in as the predicate to the branch here now this is where um it might look a little different from C sharp Unity stuff if you um if either you haven't worked with predicates before or um again you're you're fairly new to Shader graph but what this does is this Branch node is going to receive either the true or false signal depending on whether the pixel we're drawing this instance of running through the Shader program um like whether or not it is above or below the fill height and then from there we can plug in a value to true or end a value to false and this is where we're going to add our colors so I'm actually going to create you know what I'm going to make it a I'm going to build it into our parameters here so this is going to be our fill color I'm going to add a default color now what I'm going to do is when this comparison is true I want to grab our fill color which by the way is defaulting to Black so I'm going to set that to red right now and then our default color is going to plug into there and you know what instead of black I'm going to give it a little bit of of um Luminosity so here you can already see what's going on um in this view the position that is rendering is going to basically be zero that the like RG and B are all going to be equal to zero for the preview when this is actually running um it's it's going to be have a different value depending like whether it's um rendering sort of the um the topmost pixel in our sphere or the bottom most pixel in our sphere this is going to be a very negative number this is going to be a very positive number um so you're really just kind of seeing the preview set at zero here but you can see we're generally getting the thing that we want in fact just for breaking Ben's sake I'm going to uh take this fill height here I'm going to plug in just a literal value here just so I can change this and I can show you that it does in fact work let me delete that and put it back and now that we have this color figured out I'm just going to drag this into the base color element of our fragment Shader I'm not going to talk about what a Vertex Shader I know what a fragment Shader is in this video at all just know that this top stuff controls the shape of your object whereas this part down here controls what happens for every pixel that's being drawn so here we're talking about the appearance of how to color something and then up here we're talking about how to determine the final shape of something two very different problems that are solved within the same interface but anyway that should pretty much cover us here I'm actually before we move on just going to click on fill height here and I'm going to set this mode to a slider and I'm going to set the minimum to negative 0.5 and the pause the maximum to positive 0.5 and I'll explain in just a moment why that is save that go back to our scene whoa what's going on with our colors here okay so a quick explanation there I left the editor in play mode so um changing one of the shaders just kind of made everything written in the rendered scene just kind of go a little bit uh funny because you know I was writing to something that was being read so all I had to do is just stop playback and then and now we're back to to okay so anyway I'm going to run the scene now and uh let's uh test our our new custom sphere here which was it the last one I made was it this one so I'm gonna create a brand new sphere ah no it was this guy over here which one are you your sphere one four okay so actually you know it probably wasn't this one but either way I'm just going to reapply the material because uh can't be bothered to remember what I did so earlier I mentioned that I was setting the uh the bounds uh minimum maximum of our slider to negative five which leaves it completely empty and positive five which fills it excuse me which fills it up all the way and now the reason I chose this these numbers is because the sphere by default has a diameter of one in-game unit you can see kinda like here if you look at the grid down here if I drop this down let's see if I can I'm not going to line it up perfectly but um you could see there you go something like that that it's about as wide as these squares are are wide and and that's uh true along every uh axis so and with that I hope to have explained sort of how I came about writing this I think the key when you're starting out is uh remembering that this is a program that you're building that runs per pixel and so if you treat it kind of like a um you know a big old for each Loop that uh renders each pixel kind of like we rendered each of our game objects in our in our initial example then hopefully this will make a little bit more sense to you so I'd like to thank you if you made it to the end here um like the video If you enjoyed what you saw if you have any questions about anything that I went over or there's anything that you'd like a um me to try my hand at describing for you or or whatnot please leave comment and explain what you'd like to see in in a future video If you uh want to hear my explanations on the regular please feel free to subscribe to my channel and that will encourage me to make more of these videos and take care
Info
Channel: Omi
Views: 2,747
Rating: undefined out of 5
Keywords: shader, shader graph, shadergraph, shader graph unity, fill, fill shader, unity, unity3d, game, games, game development, programming, c#, csharp, game dev, gamedev, make games, make game, how to, urp, hdrp
Id: 0e_6tcS44M0
Channel Id: undefined
Length: 25min 54sec (1554 seconds)
Published: Fri Mar 10 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.