Shockwave Shader Graph - How to make a shock wave shader in Unity URP/HDRP

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] hey everyone today we're going to be talking about a shock wave effect that's basically a ripple of energy coming out from some point on a sprite or a full screen or even a complex model we're going to be talking about all of that today the reason i even have this tutorial at all today is because somebody requested it in the comments on one of my other videos somebody asked for a shockwave tutorial so here it is that means if you have anything you'd like to see be sure to head down to the comments below ask away also don't forget to subscribe i'm game dev bill let's get started today's tutorial is going to walk through four specific sections first i'm going to show you how to set up a fragment shader so a shader on the pixels of a sprite it's going to be sprite focused and it's going to be a simple radial effect coming out from some point in a sprite next i'm going to take that sprite fragment shader effect and set it up to be a full screen effect there's a little bit we'll tweak to be full screen but for the most part it's actually pretty much the same third i'm going to take that same fragment logic that same shader and apply it to a more complicated model in this case there's some things we're going to tweak some things will work and some things won't quite work right and then fourth we're gonna drop the fragment version and take that same complicated model and do a vertex based movement where we're actually moving the model and changing things around so let's dive in section one how to do this on a sprite start off i'm going to make an unlit shader graph now i'm choosing unlit because this is just going to be a sprite effect and i'm going to use the same shader for the full screen and neither one of them needs any kind of lighting with that shader graph created i'm going to make a material based on it and drag it onto my sprite in the shader graph i do the normal basic thing i've done in basically all my videos add a main text set the reference to underscore main text remember that name is really important and i'm going to make sure here going back to my scene that it actually does what i want which is rendering a sprite so now let's start walking through the logic first i'm going to make a bunch of inputs there's three key inputs i need for this shader at this point the first is focal point this is going to be the point from which our effect emanates i'm going to set the default to 0.5 0.5 because that's the middle of my sprite but you could move that around to wherever you needed to the second one is called size this is going to determine the width of our effect as the ring of the effect moves outwards how wide that effect is and again later i'm going to talk about different shapes and ways to tweak this a little bit but for now it's just going to be a simple single ring and size is going to determine how big that is and the third one is called magnification this is going to determine how strong the effect is so how aggressive that ring warps or mutates what's underneath it quick aside i set the defaults of both of these to be 0.1 i actually want magnification to be negative and i'll talk about why later and actually fix it later and you'll be able to see the difference but i just wanted to let you know now if you're setting this graph up you might want to go ahead and set magnification to be negative from the start the first input i'm going to work with is focal point i'm going to create a node called uv this is the uv of our sprite the coordinates x and y of how we're sampling into the sprite i'm going to start with that uv node and subtract from it focal point this sort of reorients those uvs as if the focal point was the origin i'm going to put it in a group all by itself and name that group direction groups are a really handy way to organize your graph and sort of name variables just like you would if you were writing a code shader i'm going to feed that direction into a length note this tells us how far we are from the center i'm going to call it direction if i expand it here you can see what it looks like it is indeed a distance from the focal point next up we've got to figure out what to do with that distance so i'm going to have something involving time that's going to expand our ring outward slowly so i start with a time node and i feed that into a multiply this multiply is there to determine how quickly time moves so for now i'll just keep it at a 1 and then i need to feed that multiply into a fraction this is going to make the time value go from 0 to 1 snap back to 0 back up to 1 over and over and over i'm going to put all this in a group called time just to stay organized now i'm going to feed this time into an add and a subtract and in both cases i'm going to feed the time into the a input and our size variable into the b input this will create two values where one is time plus size and one is time minus size and that's going to give us the width of our effect so time will be the center and then it will go out size in both directions now i feed both of those into the edges of a smooth step and feed my distance into the input of a smooth step and i can see here i actually did it backwards so i need to reverse those i need the subtract to go into the upper input of the smooth step and the add to go into the lower one and what you can see if i slow down time here is it's a growing circle where it's black before it gets to time minus size then it ramps up from zero to one and then at time plus size it becomes one all right and show you how we're going to turn this single ramp into a ring so i'm going to feed the smooth step into a one minus node which will invert it and then i take that one minus version and the original version and i multiply them and that makes it to where when the original was zero or one the result is zero but where the original was ramping then we get this smooth uh bump of a ring now i don't like spending too much time in shader graph without going back to my scene to make sure my shader is doing something and looking functional so i'm going to feed the output of my multiply into an add node add it to my uvs and feed that into the sampler of my texture if i jump back over to the scene we can see it's doing something it's not doing the right thing but it does have a ring shape inside that ring it's doing some sort of mutation and we can see that the shader compiles and is drawing something roughly in the right direction it's good to do these sanity checks once in a while headed back into shader graph i'm going to rearrange things a little bit disconnect that add i'm going to save it i will be using it later now i'm going to feed off of the direction node that we had earlier and normalize and what this is going to do is it's going to make it so that as we're pointing out from that focal point we have a vector of length one feed that into a multiply and multiply it by our magnitudes this is going to determine how strong is that arrow pointing outwards and and then i multiply that by the ring what this does is it makes it to where my arrow pointing outwards that's been affected by my magnitude is only active within the ring outside the ring is just nothing and then i add that to my uvs now you remember earlier i talked about wishing that i had set the default magnitude to be negative well we'll see right now this is actually going to do inverted of what we want what i want to be doing is reaching into the ring pulling up texture pulling a color out towards me and so to do that i need a negative magnitude but instead i have a positive magnitude right now in this graph which means i'm looking outwards and i'm pulling something in so i'm actually shrinking the art within this ring rather than blowing up the art we'll fix that magnitude in just a moment but first i want to get all the inputs i need set up and there's actually one more i want to add i want to add a speed input earlier if you remember we had our time input and we multiplied it by some value that we could change in the shader since i want to be able to tweak this more easily outside the shader i'm going to create an input called speed and hook it up to my multiply in the time box here heading back into the scene view we can see that it is doing a shock wave effect there's some things we can play with here just to look at it i'll keep the speed 1 but i could set magnification to say 0.4 to get a really strong pull in effect i can set that size down to something small if i want a skinny ring versus bigger if i want to be a big thick ring i can also mess with the focal point if i want to move around where this thing is happening right now it's emanating from the center of the sprite but i could change that to be say the bottom then lastly i'm going to fix that magnification we talked about it right now it's sort of pulling in the colors it's shrinking the colors if i change that to say negative 0.2 it'll pull the colors outward which will be more of a growing shock wave effect which is what we're after that completes what we're going to do for the sprite shader but before i move on to the full screen effect i want to talk a little bit about this shape the shape of that ring not that it's a circle but how it ramps up from zero to uh you know a gray value that you see there and then back down right now it's symmetrical meaning the attack on the front edge of the ring is the same as the decay on the backside but you could change the math a little bit so that the decay was stretched out another thing we could do is take that and multiply it by a slightly modified sine wave to give it more of a ripple with following ripples effect so there's a lot you can do to change this shape tweak it as you want to go i just want to mention that as this is one of the key kind of expansion or modification points for this effect now moving on to this being a full screen effect i've already set up this project to have a framework in place to use shader graphs as full screen effects instructions for that are in one of my previous videos i've got a link right up here for it i'll also have it linked in the description below so if you need to know how to set that up be sure to check out that other video for me it's already set up so i'm going to go here to project settings grab the forward renderer and i can see that my super awesome blit effect is already on there i need to pick the right material so i have to switch to the one we've just set up and then i just turn the effect on and you can see it's currently coming from the bottom of the screen so i'm going to readjust its positioning here but if i look at it in the game view you can see there's one big thing wrong our effect is not a circle it's stretched and i want to talk about that the reason for that is that in my sprite my sprite was square and so when i used uvs of 0 to 1 in both dimensions that worked fine because zero to one meant the same thing in both dimensions in this full screen effect my screen ratio is 16 by nine which means x and y that zero to one mean something different so we need to add one more input i'm going to call it size ratio here by default i'm going to set it to 1.77 because that's 16 divided by 9 that's the ratio of my current screen with that input created i need to have it affect our distance calculation so i take my direction i split it immediately feed it into a combine and then feed that into the distance so in my case because i did the 16 divided by 9 i want to grow the x so i'm going to multiply the x by this screen ratio that i'm doing we can head over to the game view and verify that it does look like a circle which is what we're after with that i'm now going to move on to a more complex model to start i'm going to keep things as a pixel effect just to show you what that would look like sometimes it'll work and sometimes it won't i've got a shield here from infinity pbr i highly recommend checking out their stuff i've got a link in the description with this model in particular there are four textures they sample there's the albedo metallic something in something i have a shader set up already to sample those so we're going to start with that as our baseline from there i'm going to add the same inputs that i had in the sprite version and i'm going to copy paste all the nodes from that sprite version into this one without changing any of the logic in the shader i can see what it looks like in my scene and it looks totally wrong there's two reasons for this one we're going to fix the other one we'll talk about but may not actually be fixable at all the one we're going to fix has to do with the fact that we are basing where our focal point is on the uvs and that assumed that our uvs covered our object at its face but that's not actually the case if we look at the image of this albedo texture for this shield you can see that the face of the shield is actually in the upper corner and other parts of the shield are strewn about throughout this texture so our uvs are going to be totally wrong to use as a baseline what we have to instead base our focal point on is our object space position so in the shader graph i head over to the left where we have the uv minus focal point so i'll disconnect that uv from the subtract node and i need to feed something else into it i'm going to create a node for position and set it to be in object space because i don't actually care where my shield is in the scene i'm going to be wanting to use my focal point relative to a position within that shield take the output of this position feed it into a split and then into a combine in my case the shield is actually modeled such that it's normally flat and i have it lifted up which means the coordinates i care about are the x and the z so in my split i need to pay attention to the x and z and then combine those back and feed that into my subtract with that i go over here and you can see that it is emanating correctly the two different pieces of the shield the two layers of the shield are in unison they're coming from not the space we would have expected because in position 0 0 is actually the middle so if i change my focal point to 0 0 i'm going to be getting this emanating from the middle like i like now the shape of it's a little bit weird and the other thing that we're not going to be able to fix is that at the edges of the shield things look super wonky because the metal that's supposed to be the edge kind of moves off of the edge and comes back and it's going to look a little weird and there's not really a way to fix that if we stick with the fragment shader approach so i'm going to now shift gears and show you what it would look like to do this on a vertex shader instead of a fragment shader so i'm going to come back to my shader graph unhook the uv connection there and set up my position to be modifiable now with the sprite version what we had was we had a flat thing sprite or screen and we wanted to kind of push the pixels outwards which would give the impression of them coming towards the camera because it's flat we can't actually move them towards the camera since we're now in 3d space we can't just move them towards the camera so this actually simplifies our logic a little bit uh what i want to do is take my x z and y coordinates again remember this shield is rotated so y is coming towards the camera and i want to take that y and just move it out towards the camera in my rifle so i'll start with a position node and set it to object space feed that into a split and a combine and then i'm going to mess with the y so i take that y i feed that into an add node and i'm going to use my previous logic to feed in there but i need to change things a little bit so i delete the two nodes at the end that are the adding of the uv and i just feed my noise directly into this ad the second thing i need to change is this normalize here over in the direction box you see i don't actually need this to go outwards that's what the direction was doing was pushing things outwards instead i just wanted to come straight out i only need one value across the whole thing so i'm going to delete the normal line but i'm going to keep this multiply there because i'm going to need it later now we can look at this in the scene view you can see that it is rippling i have the settings to this that magnification is a negative number which is what we wanted when we were doing a sprite effect when we're dealing with vertices we actually want to be positive so i'm going to change my magnitude to be positive when i do that you can see that there's a little bit of a weird artifacting happening in the middle here we could fix that by either tweaking the model or tweaking the shader a little bit but i'm going to do a kind of a simple quick fix to that in that i'm going to have the effect ramp up in strength from being weaker in the middle to stronger at the outside that's something you might want to do anyway and in this case it also gets rid of my weird artifact in the middle now one thing i'm not doing in this sample is i'm not fixing the normals i actually have a written tutorial on how to fix normals in a vertex shader in shader graph on my website i'll link that to the description also i'm planning to make a video about that so if you're watching this in the future there might be a link right up there to video about normals in shader graph but if it's not there yet then you're not far enough into the future it is on the plan again there's a written version but not a video version but i'm not worrying about it in this case the effect is quick enough and small enough that i don't really need to fix those normals so it's not hugely a problem so what i'm going to do is i'm going to come back to the shader graph and i'm going to feed off of this distance i'm going to feed a multiply and an add i want the two inputs of that to add up to 1. so in my case i'm going to do 0.4 and 0.6 the idea being when distance is 0 or at the very center i want my magnification to be 0.6 or 60 percent of what it otherwise would be and then when distance is full i'm going to be having my uh magnification be 100 so i'm going from 60 to 100 so it's how strongly do i want distance to affect my magnification i take this multiply and add and feed it into the multiply that's already on my magnification input and this will give us a little bit of a weaker effect in the middle and stronger out towards the outside one more thing i want to talk about one key next step that we're not going to get to here because it's not that complicated but right now the effect is being driven by time and it's constantly just doing its warp if you were actually using this in a scene and you wanted to react to something then you change that time to an input that you drive from script or something like that that wraps up the shockwave again this was based on a request so please comment below and don't forget to subscribe i really appreciate all of you thanks so much for watching there will be a link to a specific article tied to this video in the description below that article will be over at gamedevbill.com
Info
Channel: GameDevBill
Views: 47,478
Rating: undefined out of 5
Keywords: shockwave shader graph, shock wave shader graph, shockwave urp, shock wave urp, shockwave shader, shock wave shader, shockwave unity, shockwave shader unity, 2d shockwave shader, 2d shockwave effect, 3d shockwave shader, 3d shockwave effect, 2d shockwave unity, 3d shockwave unity
Id: dFDAwT5iozo
Channel Id: undefined
Length: 18min 23sec (1103 seconds)
Published: Tue Dec 08 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.