Advanced Screen Space Shaders: Godot Guide

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments

120% excellent dude. Instantly a best tutorial I've seen on Shaders and Godot.

  • You zoomed into the code!!!
  • super clear tutorial
  • perfect audio
  • source included
👍︎︎ 3 👤︎︎ u/Glycerine 📅︎︎ May 24 2020 🗫︎ replies

Yup, tutorial gold confirmed.

👍︎︎ 2 👤︎︎ u/krystofklestil 📅︎︎ May 25 2020 🗫︎ replies
Captions
today we're going to be looking at advanced screen space shaders in Godot so we're going to be passing in where items are on a canvas as a parameter to your shader this will let you highlight specific areas for example with a crosshair or showing areas in focus and having everything else have a Gaussian blur applied to it or alternatively having a screen wipe that is centered on a specific point in your screen this covers some fundamentals to do with how you've ease our handle and will be very helpful in your shader life going forwards I am Bram and today over your Godot guide some fundamental knowledge that's required is how UV is work a shader stores where it currently is in a vector - which is a UV this has an X and a y-coordinate and both of these vary from zero to one where zero is the minimum and one is the maximum so if we display that as a gradient so white is where you veto X is full at one and black is where you veto X is at its minimum at zero you can see we get a gradient going from left to right we can do the same using UV Y being displayed as white and black and you can see we've got black at the top and white at the bottom this is very important because it means if we want to compare UV space to where an object is we need to first of all convert an object's location into where it is on our screen and then after that divide that by the width of the screen and the height of the screen so that it's a value between 0 and 1 the simplest example of displaying a position on a screen space shader is going to be using the mouse as our source because that's already in the correct format to show where it is on our screen and just on our screen as opposed to being a global position so let's create a scene I'll call it simple Mouse demo and a canvas layer and our color rect fill everything and then add a shader material and add a shader that I cover this process in more length in my full screen textures video so a straightforward thing to display using a position on a screen is a crosshair focused on where our position is so let's create a canvas item shader and we're going to want to export a few variables they're going to be the target position which is what we're going to pass in our mouse position - and our intensity which is going to control how visible our effect is so we can control it later on I'm going to define the target initially just as a vector2 with 0.5 that will start as the middle of the screen but we're going to update it later on and I'm going to provide a hint range to the intensity so that it can only be a float value between 0 and 1 we can then get cracking on our fragment shader and I'm just going to block out our color as being white with the full Alpha Channel if you pass just one variable into a vector 4 it will populate every field with that value we're then going to want to draw our crosshair itself and we're going to do that by comparing the distance from where we are to the middle of the screen and we're going to use that as a divisor for the entirety of the screen pixel size on the x-axis when we're checking our distance on the x-axis this is going to get us a value the saturates at around 1 pixel away from the middle of the screen and then ears out so it's a bit of a smoother effect and we can do the same thing on the y-axis so this boils down to taking screen pixel size X or Y dividing it by the distance from where we currently are which is UV and to target X and you V dot Y that only checks the distance in the x-axis because the UV dot Y is the same as the UV dot Y in the other part of the distance function and that's the same vice-versa for the y version of this we can then clip out what we don't want to see so we're going to set the Alpha Channel of our color which is already white to be X plus y multiplied by our intensity so it's going to be 1 ish everywhere that's a pixel way from the middle of our screen on the x axis and a little screen on the y axis we can then mozi our way on over to a script that we will add to our route mode and what this is going to do is it's going to get our mouse position relative to the viewport using get viewport and get Mouse position this will return the Mouse's position on the screen which is very easy to convert into the same format as a UV so we need to do is divide the x-values which currently ranges between 0 and 1920 by the width of the screen which is 1920 we're then going to want to update our shader parameter with where a mouse currently is by just passing in the target as T let's run that and see how it looks sweet because we checked the distance it has a minor glow effect to it which is quite nice as you can see it follows the mouse round and the mouse already has some tracking built into it so if you move it off the screen the position will remain where it is and it won't start to do weird things because our targets are screen so that's our base case we now want to try and figure out how passing in a global position to this shader works before we continue lets us save that material for use later on for your convenience I've already created a very simple scene that will be applying these effects - this is because screen space shaders are much easier to see when there's a background because I'm gonna be doing stuff like blurring so the background I've created is red named Magritte's Empire of light as drawn by someone who doesn't have very much time I've created a simple player controller which is the Godot icon and it has a five line movement system that just means when I move the arrow keys and we've left right up and down additionally I added a small shader to the background clouds make them bob up and down just to give a little bit of life to the scene so let's dive into what we're actually doing now as with the mouse scene we're going to want a canvas layer a color rect make it fill everything I'm gonna rename the color rect so it's crosshair and I'm gonna drag the material from the last crosshair scene in we're then also going to want a tween and this is what we're going to use to animate our shader turning on and off we're going to want to get our player icon we're going to do this so we can pass its global position into our shader later on and then going to set a variable called toggle which will say whether or not our effect is on and then going to export a path which is going to be a node path this is important because we're going to have a few shaders and we're going to want to be able to select which one we're actively using when we run the scene and then also going to call a variable node which is going to store the node obtained from the node past so now we can focus on our process function node to DS like our sprite have in addition to having a global position on a local position they also have a function built-in which is get global transform with canvas this like getting the mouse's position on the canvas gets where that position is on our canvas but it's then saved in a variable that object returns called origin so if we get that we get our position on the screen just like with the mouse however we guarantee here that our object is on the screen so in order to make our shaders make sense I'm going to clamp our value so that the minimum is 0 and the maximum is the screen width that means if our object is off the screen at the left it will just display the leftmost possible point on our screen once we've clamped it we can then divide the value by our X size of our viewport and our Y size of our viewport and just like with the mouse position we will have values that range from 0 to 1 in exactly the same way as our UV does we can then pass that into the shader pram as before and let's have a look at how this one works nice that's all working next let's try a Gaussian blur that focuses on one point has had another color rect make it full rect call it blur make the other one invisible and let's set our route mode to have the blurs path set as the main node of our scene instead of the crosshair so a Gaussian blur is very very straightforward to implement in Godot thanks to the texture LOD function which actually just applies a Gaussian blur in a very lightweight fashion so thanks developers all we need to do is set our value to be texture Lord of our screen texture and screen UV and then change a parameter for how blurred we will be I've found suitable values for this to be varying between 0 and 6 so I'm going to multiply our intensity by 6 and I'm going to then multiply that by the distance from where our sprite is so that means where our sprite is is going to have a very small number so it's going to be a very clean image and then the further we get away the more the Gaussian blur is going to be applied to our screen we are going to divide the distance by the square root of 2 and the reason we're going to do that is because it normalizes things as I will explain now so because we're dealing with a position on the screen our maximum distance isn't quite 1 so I'm going to show you a graph here where on the Left we are increasing our UV dot Y from 0 to 1 and on the bottom we're increasing our UV dot x from 0 and the bottom left to 1 in the bottom right and let's assume we can have our player icon be at any position in here well the two furthest points will always be opposite corners on the diagonal and we have a very friendly friend in mathematics called Pythagoras who has a good way of defining the length of a triangles hypotenuse a squared plus B squared equals C squared so what we can do is we can square our bottom and write values which at their maximum are 1 we can add them together and we can square root it what we get in there 1 squared is very easy to do we get 1 plus 1 which is the square root of 2 so therefore the 2 furthest points away from each other are the square root of 2 apart so when we divide our value by the square root of 2 it normalizes and now if I apply this effect you might just about be able to make out that the edges are blurred if I go down to the bottom left as the top rights the furthest point you can see it gets a very blurred and if I turn it on off you can see a very stark difference between how in focus that area is so this works about as I expected quite nice all in all and onto our last effect which is going to be a circular screen wipe we're going to add a color rect in exactly the same way as the crosshair and the blur and we're going to set it to be the main note of our scene call it wipe make the other two layers invisible and we're off to the races I have to thank discord user at go million for helping me with this one because my brain wasn't good enough to figure out how to make circles rather than ellipses we're going to copy over our space shader as before and we're going to add an extra variable that we can call color and this is going to be the color of our white circle making an ellipsis in a shader is rather straightforward because all you really need to do is compare your distance of where you currently are to where you're looking at and then hollow that out in the Alpha Channel but making your circle have consistent dimensions is fiddly because the screen pixel size of your shape isn't constant what I mean by that is it's wider than it is tall so that means of moving along the x axis will have more ground you've covered the moving across the y axis in order to accommodate this we're going to need to figure out the resolution of our shape you could do that by passing your scales in but you can do it within the shader what you can do is you can take a value we'll call resolution set it to be 1f / our screen pixel size so what we can do then is we can multiply our screen UV by this resolution and it will get us our current pixel in appropriate dimensions to how far it is along the screen and down the screen so it will actually be a rectangle rather than a square we can then find our target pixel in the same way but we're going to need to do a bit of processing on our target because we're going to want to invert our y-value so it goes 1 1 to 0 rather than 0 to 1 we can then take the distance between these two pixels and we can compare that to a radius later on to find out whether or not we should draw and when we do draw it'll be a circle so then we're going to want to calculate what the radius of our shape should be and we're going to do that by multiplying our intensity by the length of our resolution and length will do a Pythagorean function on this vector 2 it will grab that hypotenuse for us so it's figured out the maximum length our screen can be then we can set our color to be color which is black by default so because this is a layer we're drawing over the top of our canvas you'll have everything covered by black and then if we want to make the wipe happen what we can do is we can hollow out the area we want to be a transparent whole by setting the alpha channel in the area of a circle around the point we're looking at by taking one adding our distance and subtracting the radius that will then set an area which is set to be no greater than what our radius is and it will hollow it out and there we have it we can move around we can activate or deactivate our screen wipe if we're off the screen or still set it to a valid point that's on the screen and we have everything we want thanks for watching like and subscribe and all that jazz for more content from me in the future Cheers
Info
Channel: Bramwell Williams
Views: 10,759
Rating: undefined out of 5
Keywords: Godot, shader, screen space, gaussian blur, tutorial
Id: sZlX9o9uF7o
Channel Id: undefined
Length: 13min 9sec (789 seconds)
Published: Sun May 24 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.