Building code-free shaders in Unity with Shader Graph

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
foreign Pals welcome back to a new video today I wanted to talk about Shader graph Shader graph is a tool inside of unity that allows you to basically with visual scripting create your own shaders shaders can be a little tricky for game developers especially ones who are starting out because they require a different programming language to c-sharp to actually create it's either hlsl or glsl but using Shader graph you can get some pretty effective visual effects on your Sprites and on your models without doing too much setup so I want to show you this tool today and give you some examples of how you can use it to up the level of visual presentation in your game okay let's get straight into it here we have kind of like a mock scene from my game it's using assets from my game it's not actually in engine and you can see here that uh you know it's it's looking nice I'm happy with the way it looks but I'm not 100 uh happy with the way some of these assets combine on the screen for example armin's arms here get kind of cut off a little bit by the colors like there's there's such little distance between them that they're almost invisible and if we were to change the scene into like a more nighttime scene you know I like this tile set but the contrast between the tile set at the front and the background is way too high like I'd want to like bring this down so there are things that we can do using shaders to change both of these things without having to redraw our assets or duplicate our assets with different kind of export settings you know changing the brightness or whatever so basically all you need to do is if you've got the package in unity which I believe is now currently standard and you have the universal render pipeline kind of setup that you should be able to go create Shader Universal render Pipeline and then in this case we're going to use a Sprite unlit Shader graph you can use lit as well it just the lit ones will take on brightness changes from lights around them and we're going to call this uh first Shader just to play around so when you click on this essentially this will take you to an editor and that editor is Shader graph Shader graph has a few different kind of like properties that you should be aware of the first is the Blackboard here on the left this is the set of inputs to the Shader asset there are some defaults here that you need to expose those will become basically nodes that you can then work with then you have the outputs whatever you plug into these is going to be what's shown you have a visual preview of your of your image and you have the inspector for whatever node you're currently selecting what we're going to do is just sort of get something going so the first thing you want to do is have your texture 2D okay this can be cool whatever you want and the node setting to this is what's really important so shaders have what's called references this is like a variable name and inside of unity in our inspector the properties on things like a Sprite renderer will refer to those Shader properties for example Sprite is the main text property and color is the vertex color so here when we click on our texture 2D this reference if we write underscore capital M main capital T text that will basically link to whatever it is you've plugged in there it won't show up in the preview but when the Shader is actually active and on that Sprite whatever's in this slot here in the Sprite renderer that's what will show up in this property here so we can take our texture 2D and we can drag out from this little node and we could say sample texture 2D okay what this does is it creates a node that previews this texture the way these nodes work is they take inputs and they have outputs everything out from here is a color and in fact everything to the right of a node that is a sample texture 2D node only affects the color for example if I take this output here there are five channels here one of them is the combined red green blue Alpha it's the entire color of what's being sampled and then there's also just each of the channels separated out so this is like a vector four it's like a color variable and this is just a bunch of um you know floats for the value of each of those channels so the amount of red green blue and the amount of alpha we can preview this by dragging out and just typing add and add is just an addition but if you add nothing you'll get the preview you can see that the alpha here is zero or black where there's transparency and white or one where there is opacity here we don't see that Alpha just because of the way that it samples it in the preview for the sample texture 2D but we know that if we sample this and we check it out here we can see that this is actually what's coming through so the way that this works is every single node in this kind of like um fragment side of the Shader and there's two halves of a Shader a vertex and a fragment function everything that's going to lead into this base color or this Alpha anything that goes over here every note along the way deals explicitly with adding multiplying and transforming colors it can't move things left and right it can't do anything to do with changing what the output of this is and the output of this is basically just you know a series of pixels we can change the color of the pixels we can change the brightness the opacity but we can't change their positions all of that has to happen before this in the UV so if we want to turn this into a functional Shader all we have to do is get something into this output I can take this output here throw it over here and immediately we can see something but there's no color information coming in so we just know that there's some transparency and then we can take our rgba pass it out and that gives us the most basic kind of Shader you can have by default this will be sphere which looks kind of awkward so you can right click it and press quad and that will give you a rectangle basically to place the Shader on so this is your first Shader this will essentially just take your texture and it will output the image onto the material uninterrupted so we can save that we can minimize it again and if we apply this SATA to our Sprite nothing will look different which is uh success so the way to get a Shader onto a Sprite is to create a material you'll notice if we go to our character sprite there's no Shader property but there's a material property the way to create a material is we can just create that as an asset create material okay so that'll give you this to apply the Shader to the material you just drag it on there we go and then we can just drag the material into the material property in the inspector now we have something we can work with if we go to our Shader and we make any kind of changes those changes when we save will be used to update what we see in our output here we don't need to keep this in a window here but just to prove that it works what I want to do is instead of outputting the color of a texture let's just create a color node basic color and pick a random color and just pass that in instead so we're just saying take red pass it in so it's just full red and then clip the alpha to what the Sprites Alpha is so that'll give us a red character if we minimize this there it is the Shader compiles and it's red so if you can do that you know you've got a functional Shader that you've created in Shader graph congratulations okay so from here you can imagine we can start doing some some maths right we could take our our GBA we can add to it we can take the output of this and plug that in and instead of adding nothing maybe we could add the color to this and so you can see that all of the red got applied over armin's colors and they all shifted in the direction of white so when you add things in a Shader space right all of the colors have a value between zero and one when you add them they approach one because anything plus anything unless it's a negative number goes up right towards one so colors will get brighter when you add them another thing is we could multiply okay let's multiply instead what do you think will happen when we multiply usually when we think of multiplying we think of things becoming bigger but they actually get darker in Shader space because everything in Shader space that's not bright white is less than one and if you multiply something by less than one you're actually getting smaller like 0.5 times 0.5 is 0.25 it's not one and so when you multiply things it gets darker now what do you think will happen if we divide it gets brighter but it gets brighter in the opposite direction of the color that we divided by so you could just try to you know play around with things and see what you get it's a little unintuitive at start but once you play around enough you'll find that there are a series of things that you can think about and ways of understanding colors that are intuitive it does figure itself out eventually and you'll become more comfortable with it it's just a matter of practice so we've been talking about colors so far the UV is the set of coordinates that the art kind of lives on now if we go back just for a second to the scene you can see here there's a rectangle if I press T this is the actuals like Sprite itself right this is the the texture a Shader cannot draw outside of this texture but you can do some maths to this to shift or you know scale or transform the Sprite within the context of this Browning box we can take a default node called UV so you right click create node UV and this represents uh that space okay it represents like the default uh position space of your Sprite and if you pass then this in here is actually the default value but you can do some math to this as well we can add to this UV to do things like shifting so instead of rendering you know right where the pivot is we're rendering it off to the side so knowing that you can make operations happen to the coordinate space of the image and knowing that you can do operations over the color space of the image that kind of opens up the possibilities for literally anything that you've seen in a video game with shaders and a lot of that stuff if it's animated you know we'll use time right to as part of the operation so you know maybe a color increasing over time or a noise space being sampled through time so you can have noise has a gradient and you can sample the color via noise over time for example we could say take a UV and we can add to that UV so We're translating by time but let's just say on the x-axis so we could we could say Vector two and just on the x-axis we want to have a number that's time on the x-axis and zero on the y-axis and add that and then we could pass that in to the UV and we can now scroll through the noise space so the noise space is being offset on the x-axis by time okay this seems a little crazy if you've never seen this before and you might think well what do I do with that so if we want like a really crazy thing we could do we could just pass that directly into the sample for our character uh maybe that's a little too crazy I don't blow your mind too much we've entered the Almond verse here with the with the Sandler um you could you could divide this or multiply by a very small number like 0.1 and then you could add this to the original UV so that we got something that still looks like our character and then you can have it sort of like look like water right if we could increase the scale of this and uh that's how you do you know puddles and and waves so these are really common techniques that get used in games all the time to do things like procedural natural effects now I've shown you a lot of cool stuff but I want to show you something more practical so we started at the very beginning with our character in the scene and I want to try to make the character stand out a little bit more so let's create an outline Shader for our character outline shaders are a little little much but I I believe in you I think you're going to be able to handle it so what is an outline okay let's come back to a Sprite for a second and just think about what an outline does we Trace along the edges of a Sprite and anywhere that we see an edge we basically add a pixel and the way that this works inside of the actual a Sprite tool if you press shift o it will give you these directions right above below left and right and by default it's just those but if you go you know in the corners as well it will kind of make it a little more Square but you can see if we take some of these away that's just this one what are we doing we're actually just outlining to the right of the character we're taking the entire Sprite and we're shifting it almost like shifting a black version of the Sprite one pixel to the right and putting it behind the character all right and then we could take that and duplicate it and put it on the left side of the character and above the character and below the character that is an outline it's a darker version behind the character or a colored single color version of what we're seeing on the edge here and putting it behind the character that's essentially how you do outlining in games so we're going to create a Shader that performs that so how might we try to create a colored version of the character that's behind the character well we've sampled the character once but there's no reason why we can't sample it again so let's just create another sample and let's instead of using the default UV here let's shift it so we can add to this UV sum distance okay and that moves it across and if we could get it right like 0.01 we might be moving over exactly one pixel in a Direction now rather than just take you know this Sprite let's just take the the alpha of the Sprite so let's take this and let's add it to the default Alpha okay it's going to look a little bit wider so you can see that the amount that we've shifted by is not perfect right we haven't moved by one pixel because there's kind of like a bit of a step in the middle like a little short Gap so we need to know how much to move this by now this is in kind of like UV space and in UV space one is the entire width of this thing and 0.01 would be 1 100th of the thing so if this was a 100 by 100 pixel 0.01 would be correct but it's not correct I know that the Sprite is 64 by 64. so if I did 1 divided by 64 and put that in the X offset here that would be correct but there's an easy way to do this which is it's called Texel size the textile size is the size of our texture now I think in actual Shader terms it's one divided by the amount of pixels but in this case the output of this node is actually just the amount of pixels that we've got so to make this work what we want to do is we want to create a node that is a vector 4 and that's going to be plugged into this and we're only going to change the X amount right so what we need to do is take this and also turn this into a vector width to go into the X the height to go into the Y this is just allowing us to do some maths with both of these properties at once and I want to divide 1 into this number okay so we're going to create another node which is a vector 2 as well I'm going to plug this into the top half of this and this now if we put a pixel into this or a pixel value that will offset it by that much if I press 1 that will then sorry don't need that uh so if we go directly into this we can then move this by a number of pixels and we can see it shifting so this one pixel two pixels three pixels and you can see it here right then the size of this is perfect this is the core of our little outline here now unfortunately it's not very pretty but in order to make this work in four directions you have to copy it four times what we want is to create a a essentially a function out of just this part here I'm going to take all of this that we've done so far and I'm going to convert it to a sub graph and we're going to call this outline component offset component so what that's done is it's basically taken that code that we selected and it's given it its own Shader graph editor it's created an asset and we're now inspecting that asset this is sort of like a function right in normal c-sharp scripting it's a piece of functionality that we can then give some parameters and turn into something more modular and then reuse elsewhere what this needs is a property right because we want to have the four different components being up down left and right so we need here maybe a vector two and we're going to call this offset and then we're going to plug this Vector to offset replacing this and uh that's that's it basically we don't really need to do the ad we could just pass this out there and this gives us a nice white Alpha offset okay so this one we could say one and then we can make four of these and if you like you can collapse them too that makes it a little bit easier okay so we're going to have one and then minus one and then one on the y-axis and then minus one on the y-axis now if we add all of these together now we've got this thing right which is basically a flattened version of the whole thing now unfortunately uh they've been turned into spheres when we do this so we won't be able to see the output very nicely offsetting in an easy way but you can see here we can see it on the sphere rotating so we know that it works the best thing we can do I guess at this point is pass this into the output to preview it properly and it works um and it's a little bit chunkier now so uh that's not quite our outline just yet let's delete this here so we have like a clear understanding of what our thing is actually doing if we pass the same value into the color and the alpha it looks like it's all white but it's not really all white because value is greater than one don't appear any whiter than full white but those values are still there and because we added a bunch of numbers together the parts where they overlap the most those parts will be definitely much much greater than one and the parts where they overlap the least those parts will be exactly one so right in the center there's like an almond shaped thing which has got a value of probably like four and then all around the outsides there's a value of one we could probably test that actually let's take this and we could subtract from this four so basically this is the part where there is full overlap where all of the outlines overlap with the original uh but there's something here that I don't like either and that is that you can see it's not actually a perfect silhouette of almond it's actually based on the brightness of the elements inside of that so I'm actually going to go back to our offset and I'm going to do what's called a step function to essentially take all of the values that are less than one and bump them up to one if they're greater than some value that's what step does you can see here it returns one so it makes it white if the value of the input n is greater than or equal to the value of input Edge okay so the edge value in this case is let's make it like 0.01 so any pixels that are brighter than 0.01 they're just going to be considered white which means we know that because our Alpha is completely zero outside of the silhouette what comes out of here is exactly going to be white if we close this and go back here [Music] save it do we get anything different it is different actually we had different parts of the feet visible before and we can change this value you can see here in the subtraction we're actually getting different layers visible depending on the subtraction value but if we don't want that to happen if we just want the output of this to be just like a solid color we can take this and we can clamp it right between zero and one so anything that's greater than than one will be considered exactly one and anything that's less than zero will be considered exactly zero so this is effectively our Alpha representation of the outline for the character the only thing that we need to do now is isolate the original from this so that we can then put almond inside of it we want to kind of like subtract the original Alpha first so that we get this like Hollow version of this of this thing here so when what do we want to take away first from this well we want to take this away from this we're going to subtract this and this gives us lo and behold her outline now in this case I have got an issue with my Sprite where I've got the character drawn directly on the bottom so nothing can get drawn outside of the texture because almond here is outside of it I have to bring him up a little bit if I wanted to make that work we're just going to ignore that for now I've got to fix that in my game but what have we done we've we've gotten all of those additions right left right up down we've added them all together we've flattened them down so that they're all white one color and we've subtracted the original silhouette from that so all of these are now zero all of these pixels where almonds silhouette really was is zero and only the stuff that we added by shifting left right up down remains and that's an outline it's perfect but we want to put almond inside of that so let's just add to this are actual colors for almond so we can just add this to that with this as the alpha and there you have it so the clamped fully outlined version that had the solid inside Center which was this one here that can be our Alpha because we still want almond to be fully opaque inside and so that's fine there and then we're just combining for the color section almonds original Sprite and and the outline that has no Center so maybe it would be a bit better here if we just sort of like talk about this one more time and I'll break it down and annotate it as well so let's just break down what we did so first what do we do we sample the original Sprite and then we offset the silhouette in all four directions and then we added them together and then we clamped them and that flattened them down so we have this big fat flat version that's all white and then we subtracted the original silhouette from that so that we just get the hollow outline and then we add that back to the original here and that gives us our outline so if we want to take this output which is the white outline and before we add it we want to color it you could just multiply any white color by a color and it'll create that color okay because you're multiplying something by one so let's just add a color as a property here it is pass this in and then multiply plug it in here and then we need to give it an actual value here first so let's give it a lovely green if we want the outline looks really good but we've got a little bit of leaking going on right something happening around the outside so it's a bit brighter near the brighter parts of his arm and a bit more blue near the blue parts so we've got some of the color that's kind of like making its way into our outline when we do this addition and the way to fix that is to take the alpha and invert it so 1 minus gives you the opposite of that number so 1 minus 0.25 gives you 0.75 okay so we subtract the the inverted Alpha from the original color that makes all of the colors that were kind of like in a halo around Almond here in these spaces here makes them completely black and then we clamp that number between zero and one so we went some of those numbers are now negative because we subtracted all of this white which is one from something which was invisible but still there so all of this color here which gets interpreted here by unity even though it's empty maybe it's the way that it's encoded through a Sprite who knows all of that color we just subtract right this this all of this white gets taken away cut out from this now we know there's absolutely nothing here but those that nothing isn't a negative right there are some negative colors in here that are darker than black so to fix that we clamp the whole thing between zero and one so now this everything we see here is no brighter than white and no Darker Than Black in fact the black is zero and the white there's no white but if it would be it would be exactly one then we can pass that in here and immediately it fixes it so the green is pure green it's not being added to anything this I'll just call this like sanitize color and that's just to yeah get rid of any kind of like leaking colors that were outside of that and that's it that's your outline Shader so this is you know kind of complicated there's quite a few operations that we had to do to get here but uh hopefully it's starting to come together as something that makes sense what's cool about this is that if we if we save it and we go back to our scene we can see the result is here and it means that we can go to this Shader and we can change this color property to whatever we want and once you've got this outline you could do it to anything right I could outline the terrain if I want we could take that material and we could give it something that's a little more earthy you know we could even calculate this procedurally so that we know based on you know the average colors of the scene we could change it to be a bit more uh you know appropriate you know we've got options now and shaders give you that power so this I'm sure felt like a lot and uh if you were able to follow along I really appreciate your patience uh it is definitely something that's a little more programming than it is Art but in a way it's kind of cool that shaders have this interesting intersection between the two and once you get really comfortable making your own shaders you can start looking at games or thinking about effects that you want to see and very easily combining them together and putting them together here in Shader graph to create some really interesting cool effects of your game I've got stuff where I wipe upwards from the bottom to the top of the character over time reflection shade is that kind of Shimmer and and flash when you walk past them I've got all kinds of stuff so hopefully if you're interested in this kind of content I can make more uh Shader examples and make videos out of those let me know what kind of stuff you want to see and I'll see if I can make it here in Shader graph I'll show you how to do it and I'll catch you in the next one hey pal thanks for watching and thanks most especially to the patrons and twitch Subs who support this Channel and my gamedev project Insignia to find out more click the links in the description below and if you like this video tell YouTube by clicking the like button and then YouTube will tell me and then I'll make more videos that's nice thanks again and until next time
Info
Channel: AdamCYounis
Views: 47,520
Rating: undefined out of 5
Keywords: game development, pixel art, game dev, game, video game, indie games, stream, shader graph, tutorial, shader
Id: mRDG5sQYjdo
Channel Id: undefined
Length: 30min 2sec (1802 seconds)
Published: Sun Dec 18 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.