Tessellation and Displacement - Shader Graph Basics - Episode 41

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
today we're going to create a tessellation and displacement shader in both unreal and unity let's go [Music] before we get started it's important to understand what tessellation and displacement are and why we would want to use them tessellation and displacement are a dynamic way to add detail to your mesh without needing to store a highly detailed mesh in memory the brute force method for doing this would be to detail your mesh in zbrush or other sculpting software and then bring the base mesh into the engine with millions of triangles this would make a mesh that's really expensive to load into memory and really expensive to render instead of doing that we can create a regular low poly model and a height map that indicates where additional geometry should be displaced and then in the shader we can tell the graphics hardware to subdivide our mesh into millions of triangles but the difference is because we're doing the effect in real time we can create the additional detail only where we specifically need it for every frame so we can dynamically add detail where it's needed and leave it out where it's not visible so tessellation means adding triangles to the model by subdividing it and displacement means moving those extra triangles around so they can make the shape of the model more complex than it was originally this technique works really well on organic models that use mostly uniform size triangles so with that explanation out of the way let's jump right in and create our shader in unity so here we have a brand new material in the hdrp pipeline and the first thing that we need to do in our new material is come over here in the graph inspector and select the graph settings tab now we're going to come down here to tessellation and we're going to turn this box on and when we do what that's going to do is it's going to expose two new items in our master stack in the vertex section here called tessellation factor and tessellation displacement so the first thing that we're going to focus on is tessellation factor and what that means is how many new triangles we're creating in our mesh so for now we're just using this simple sphere mesh here and if i switch over to wireframe view you can see that our sphere mesh is relatively low poly i just have a fairly small set of of vertices here and what we're going to do is increase our tessellation factor and see what happens when we do all right so when i set the tessellation factor to 2 now you can see that our low poly sphere is a little bit higher poly but probably not quite high enough polygon count to actually do some good displacement so let's turn it up a little bit more let's just set it to a value of 32 for now and see what that does now you can see we've got a few extra triangles going on here so this is pretty cool we've got a really densely detailed mesh obviously if we switch to shaded mode you really can't tell the difference between that and the model that we had before but if we look at it in wireframe wow that is a lot of triangles going on right there okay so we've set our textilation factor to 32 and now we need to do uh displacement so for tessellation displacement this is basically uh you specifying the offset of each of the individual vertices uh and where they're going to where they're gonna go so let's start out just by taking the normal vector node and what this is going to do is it's going to tell the model hey i want to offset each of my vertices along the normal so let's just plug this into our tessellation displacement and see what happens so i'll hit save and our sphere is gone but if we zoom out a little bit you can see that our sphere is just a little bit larger so what happens is our normal is unit length which means it's it's a unit of one or one meter and so our vertices have all been displaced outward along the normals of the mesh one additional meter if i want to control how much displacement is taking place what i can do is multiply our normal vector by a value and this value i can use to control uh the the amount of displacement that we're applying so i'm just going to give this a value of 0.1 so we're now displacing the mesh one-tenth of a meter along the normals and so now you can see that uh my sphere is not quite so large it's it's a little bit smaller but if i just uh if i set my multiply to 1 or to 0 rather this is going to give me no displacement and my sphere is going to be back to the original size well this is not really that interesting because all of my vertices are being displaced uniformly and what i really want to do is use a texture to make some vertices displaced more than others and so i'm going to open up my create node menu here and do a search for sample and i want to sample a texture but if i use a sample texture 2d that node doesn't work in the vertex shader i need to use sample texture 2d load there are some features that sample texture 2d uses that only work in the pixel shader and so i need to use sample texture 2d laud because it doesn't use those features all right so i'm going to click here on the picker and i'm gonna pick a height map i'm gonna pick my cobblestone's height map here uh you can see this texture is 256 by 256. uh it's 85.4 kilobytes pretty small i don't need very high resolution in this map because it's just displacing vertices it's not it's not doing its operations per pixel and so i can get away with a fairly low resolution texture here all right so i have my normal vector and i have my multiply here that's controlling uh how far i want to displace things let's just set this to 0.04 and now we're going to multiply by our height map so i'm going to add another multiply in here and for this multiply we're going to wire in our height map and before we do that actually i want to take a look at what this um what this texture actually looks like so you can get an idea for what it's going to do so let's just wire it into base color and let's see what that does okay so you can see that i have these cobblestones that are white where the displacement should be high and it's kind of black where the displacement should be low so that works pretty well although there is a little bit of stretching going on and so i want to modify the uvs just a little bit i'm going to add our uv node to bring in my uv coordinates and then i'm going to multiply my uvs by four and two just to tile this a little bit more so let's plug these uvs into my texture and take a look at our result from that okay now you can see that our cobblestones are a little bit more uniform shape this is not something that you necessarily have to do but it looks just a little better if i do this for for demonstration purposes so this is what our cobblestones are going to look like and let's wire our our height map here into our multiply and then wire the result of that into our tessellation displacement and take a look at what we're going to get now wow cool so you can see that our cobblestones are bumping out of the surface especially it's especially noticeable here on the silhouette and not quite so noticeable here when we're looking straight at the sphere but especially on the angles where the cobblestones overlap each other it's really apparent and it adds a ton of realism uh to our model it makes makes those cobblestones just really pop out of the surface okay so right now we're using our height map to shade our model and that's a little bit unrealistic so i'm going to delete this connection so that our height map is no longer being used for color but one thing that you'll notice when we do that is that our normals no longer look correct because we're bumping out the vertices on the surface of the model but we're not changing the normals at all so in order to fix that that's really simple it's something that we do all the time we just need to add a standard normal map so i happen to have a normal map already that is uh the same shape as my height map it's this cobblestone's normal map here so i can just grab this one and then i can plug this into my normal map socket and just like we do very commonly and then if i hit save here oh i need to use the same uvs here now this is something interesting that i want you to notice i have my uv coordinates here and i'm multiplying them and then passing them into the sampler that's sampling my height map but if i try to take those same uv coordinates and drag them down here to my normal map you notice that these sockets kind of close themselves off and say hey you can't connect to me and the reason for that is because this data is going into our vertex shader but this data is going into our fragment or our pixel shader and so what i need to do is just duplicate these nodes here and now i can use the same nodes but just a copy of them in order to sample my texture uh in my fragment shader and that's because you can't take data from the vertex shader and just use it in the fragment shader like that you need to do some special things in order to pass data back and forth so we're going to keep what's going on in our vertex shader separate from what's happening in our pixel or our fragment shader all right let's take a look at what we've got now oh and there's one thing that i forgot we need to set the type on our texture sampler to a normal map so that it knows to do the special calculations required for a normal map okay and there you go now we have our cobblestones and they're bumping out we're doing tessellation and displacement and if we take a look at our wire frame holy cow do we ever have a ton of triangles uh we can zoom in here and you can see wow we've got triangles to the moon okay this is not specif this is not especially optimized uh and if you were to put a mesh like this into a game uh you just totally destroy your frame rate now the cool thing about tessellation is that we can actually control where these triangles are getting added and how the first way to control uh how they're getting added is based on the distance from the camera and this is something that happens automatically let's switch back to wireframe and we're gonna zoom out here and what i want you to notice is that as we pull further away the triangle count is actually reduced and right now it's so high that maybe you can't even tell but as we're moving further away actually let me dial this back just a little bit so that maybe it's a little more obvious so right now we have our tessellation factor of 32 but i'm just going to set it for 8 for a minute so that you can see the triangle count reduce as we move away yeah that's a little more obvious there so when we're zoomed in we get our full tessellation factor but then as we move farther away um it's reducing the amount of tessellation so now when we're at this size we're back to basically the same triangle count that we were at the beginning but then as we zoom in it's adding more and more triangles for us so the game engine is optimizing our tessellation so that we only need exactly the number of triangles that we're using and not anymore and if we go over to our graph settings on our graph inspector you can tweak these settings over here uh as sub settings under tessellation to control uh how that distance based testolation works i'm not going to go into the details of that right now but you're welcome to take a look at the documentation and play around with these uh to see how that works so we can control the number of triangles that we have based on the distance of the camera to the model and optimize our tessellation that way now the other thing that we can do is if we take a look here and this is something that i mentioned before we don't see the tessellation very much when we're looking straight at our model we mostly see it around the silhouette edges and so what we can do is instead of just setting a hard-coded value here for our tessellation factor we can actually control the tessellation factor based on whether or not the surface is facing toward the camera or perpendicular to the camera so we can do some optimization of our tessellation based on the based on the angle to the camera so let's do that next so the first thing that we need to add in order to create this optimization is a normal vector so i'm going to add a normal vector and now we need to do a dot product between our normal vector and our view direction so i'm going to add a dot product node and now we need our view direction node and so what this is going to do is tell us what the relationship is between these two vectors it's going to return a 1 if the vectors are parallel to each other and it's going to return a 0 if they're perpendicular to each other which basically tells us are we facing the edge or not so just to get a better idea of what this is looking like before we plug it in i'm going to get rid of our normal and our tessellation and let's just plug this value here into our color for now so that we can get a get feedback on what that's looking like okay it's a little bit hard to see because of the lighting but you can see here that we're getting white here where the surface of the model is facing the camera and we're getting black on the edges where it's facing away from the camera and that's exactly what we want but we we want it actually inverted so i'm going to add a one minus node and what the one minus does is it subtracts the result from one and it's basically inverting these results so if we plug this in and save it now you can see we've got this black dot where the surface normals are pointing straight at the camera and then as the normals go more perpendicular to the camera uh we get kind of a white halo around the edge and that's what we want because we want to do our tessellation here on the silhouette and not do it here in the middle now we can adjust this a little bit if we add a power node so we raise this to a power of say like 1.5 and what that will do if i just have a power set to 1 you can see here in the preview it looks very similar to this if i just have the power set to 1 i have the the black dot that's kind of small but if i want to optimize it even further and push the black out toward the edge i can raise this to like a power of two or three or four this might be a little bit too much and so what i'm going to do is go with the value of 1.5 and this is something that you can tweak depending on how optimized you want to make the effect all right let's take this power node and multiply it by our tessellation factor so we have our tessellation factor set to 32 and so what this is going to do is um we have our mask here that falls off on the edges and so by multiplying it by 32 we're going to get a tessellation factor of 32 on the silhouette edge and then it's going to get smaller as we come in here toward the middle so let's plug this into our tessellation factor actually first let's take a look at our wireframe here you can see we still got triangles to the moon but if i plug this into our tessellation factor what it's going to do is tessellate the model pretty heavily on the edges but now in the middle you can see that i'm not very tessellated at all and this is what we're going for this is an optimization so that we're putting triangles where we need them on the silhouette edge but not here in the middle this is the real power of tessellation because it gives us detail where we need it when we're up close to the model and on the edges where it's most visible and we can tell our shader hey i don't need triangles when i'm looking straight at the model we don't need tessellation there so let's remove it from that and i also don't need triangles when i'm further away from the model so go ahead and automatically remove the triangles as i get further away that's the real power of tessellation if i were to bring in a million poly model i wouldn't be able to do that automatically but with tessellation i can so now let's plug our displacement back in and let's plug our normal map back in and uh i'm just going to disconnect this from the base color and maybe make the base color a little bit darker and i'm going to make this smoothness a little bit higher and this is just so that we can see the results a little bit better okay so now you can see in the wireframe that i'm getting really nice tessellation here around the edges and in the middle i'm not using triangles where i don't need them as much so if we switch to shaded view cool now we've got our sphere with tessellated uh geometry shapes and you can especially see them around the outsides um and it still looks the same here in the middle but i'm not actually spending those triangles if we're if we look at right uh wireframe again it's not tessellating our sphere here in the middle where triangles aren't needed now as i rotate this around here you can see things moving a little bit kind of undulating and that's where tessellation is being applied or taken away based on um based on if the model is facing the camera or not and so that's where uh you need to adjust this power value and also adjust this overall tessellation value so these are two parameters that you might want to expose to the material as exposed tweakable parameters so that the so that the artist can can choose these now you want to be careful with this one you want to try to take the um the overall tessellation factor the maximum tessellation factor only as high as you need it you might be able to get away with something as low as eight um but if you're not getting enough uh you know surface shape you can turn this up so this one is going to give you quality versus performance uh trade-off and the same here if you set this to a power of one you know you'll get fewer of those uh little bubbly lines but you'll end up with more triangles if we switch over to wireframe view here you know we have we have more triangles here the higher this power value is the further toward the edges it's pushing the tessellation you know if i were to set this to a power of five i would only be getting tessellation on the very edge but then if we take a look at shaded mode you can see there's some fairly harsh bubbling artifacts here where our tessellation kicks in around the edges so in my case it's working really well to set this power to 1.5 and then our tessellation factor to 32 but like i said these are values that you need to tweak per model to making make sure that you get the right trade-off between quality visuals and performance okay so that's how tessellation works we are controlling how much tessellation to apply um based on the angle of the surface here we're controlling how much displacement to apply based on our height map here that is getting multiplied by our normal vectors oh and then we have this multiply value here this value is defining our maximum amount of tessellation so if i were to turn this up to something like 0.1 say now i'm going to get a ton of tessellation that's probably a little too much you know the lower this number is uh the less of these like bubbly artifacts that you'll see but the less tessellation you'll get as well so this is going to be a trade-off here for my cobblestones a value of 0.04 works really well all right and then we just use a standard normal map to create the normals of the mesh and we end up with a really realistic looking effect cool well let's switch over to unreal and i'll show you how to do the same thing there okay here we are in unreal and the really big thing to understand about unreal is that unreal 5 does not have tessellation and i'm not sure why that is i think maybe epic wants to encourage everybody to use nanite instead and so unreal 4 has tessellation but unreal 5 does not and so in order to do this demo i've switched back to you know in the series we've been using unreal 5 but in order to do the tessellation demo i've switched back to unreal 4.27 so the first thing that we need to do in unreal is we need to come down here to our settings of our material and find the tessellation settings and these settings again do not exist in unreal 5 so we're doing this in unreal 4 instead so by default this is set to no tessellation and i'm just going to set this to either flat tessellation or pn triangles let's go with flat tessellation for now and what that does is it enables us to use world displacement and also tessellation multiplier now here's the next thing that's interesting about unreal the overall tessellation factor that is that we're using is something that's hard coded into the engine uh in unity we were able to set that value and we set it to a value of 32 but that value is hard-coded and there is a place in code where you can change it if you need to but it's really not intended to be changed and so this tessellation multiplier value here is really just intended to be between 0 and 1 as a multiplier for the internal value that's set inside the engine and so what we're doing here instead of specifying um that value of 32 like we did before we're just looking for a value that's between a range of zero and one and so just like we did in unity what i've got here is a dot product between my vertex normal and my view vector so i'm creating a view vector with the camera position node and the absolute world node i just subtract the absolute world position from the camera position and normalize this gives me my view vector then i do a dot product between the vertex normal and my view vector and then i do a one minus x which is uh flipping it or inverting it and let's just let's just disconnect all of these for now and just plug this into my base color node so that you can see what i'm getting if i switch this to unlit you can see that this is the same mask that i was using in unity where i'm getting a dark here in the middle and then as i go toward the edge my value gets brighter and so what this is doing is it's making it so that my tessellation factor along the edge is going to or my tessellation multiplier rather is going to be one along the edge and then as we come in here facing more toward the camera my value is dropping down so uh let's see here i've got my power set to two let's drop this down to 1.5 and you can see with that value i get a little bit less fall off okay so if i disconnect that there and then set this to a wireframe what you can see now is that i've got tessellation around the edges and no tessellation here in the middle but if i disconnect this now i have uniform tessellation everywhere and that's fairly expensive which is why we're going with this optimization to just put the tessellation around the edges where it's most important okay the next thing that i have is this is my height map here if i do a little preview you can see i'm using that same cobblestones height map as i did in unity and i've got my texture coordinates here multiplied by four and two mostly just to make it look a little bit nicer on the sphere and then i'm multiplying my height map here by my vertex normals and my my vertex normals are multiplied by uh by 16 because the units of offset and unreal are different from unity in unity a unit is one meter but in um in unreal it's a hundred centimeters and so this is actually a very short surface normal it's just one centimeter and so i need to multiply it by 16 to get some decent bumps so let's plug this into our world displacement and now you can see that right along the the silhouette edge my bump map is is bumping out if instead of connecting this to the displacement i connect it to the color and then we switch to unlit here you can see some interesting directions this is actually showing me the world space directions uh where i'm pushing my vertices what i actually intended to do was to plug my bump map in so that you can see what the bumps are doing so where where the map is white it's bumping out and where the map is black it's not bumping out so wire this into world displacement and then just like we did in unity i've also got my um my cobblestone's normal map which i can connect to my normal socket and so with everything hooked up my normal map plugged in my displacement map plugged in and my tessellation multiplier plugged in i'm getting some cool looking tessellation and as i zoom away the tessellation is reduced if we look at it in wireframe again see as i get further away there's less tessellation and then as i zoom in i get more tessellation but only around the edges where it's important where it's needed all right cool so that is tessellation and displacement i want to uh subdivide my model but only in the specific areas where it's going to be needed and then i want to use a height map or a bump map to displace the triangles of my model in areas where i want more detail now you can use sculpting software like zbrush for example and export your mesh on the lowest uh subdivision level and then have zbrush calculate the difference between your lowest level and your highest so you can crank it up to like seven subdivisions and put all kinds of extra detail in there that doesn't exist at the lowest level and then you can tell zbrush to calculate the difference between the two and output a displacement map for you then you can use that displacement map here to get all kinds of cool extra dynamic detail that you wouldn't be able to get otherwise so that's kind of how that workflow works and i'll put some links down in the description for um for other tutorials that show how to create content that way anyway i hope you've enjoyed the video and that you're inspired to go out and create some tessellation and displacement models yourself now that you understand a little bit better how to set up a shader that does it well that about wraps it up for this week have a great week everybody and be sure to come back again for more shader goodness next time [Music] you
Info
Channel: Ben Cloward
Views: 19,619
Rating: undefined out of 5
Keywords: UE4, UE5, Unreal, Unreal Engine, Unity, shader, material, material editor, game development, real-time, tutorial, training, graphics, 3d, GPU, tech art, computer graphics, fundamentals, basics, beginning, learning, shader graph, getting started, displacement, height, bump, tessellation, PNtriangles, Phong, subdivision
Id: ycJ434Lh21w
Channel Id: undefined
Length: 32min 52sec (1972 seconds)
Published: Thu Apr 07 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.