Fast Subsurface scattering shader in Unity URP for mobile

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hola amigos welcome to this video tutorial where we're going to make a subsurface scattering shader using unity's shader graph this can be used to simulate a variety of translucent materials such as snow skin milk or jade for example the shader is configurable and performant enough to be used in mobile games the techniques explained here can also be recreated easily in real or other engines but before we start creating notes let's go through a quick explanation over how this effect works when light hits a translucent medium there are many things that happen some of it is reflected as a specular light while the part that goes inside stumbles and scatters around leaving the surface at many different locations while all rendering engines support transparency and refraction simulating this scattering of the light is way more complex and computationally expensive to implement its ray of light can bounce and split off internally hundreds of thousands of times losing a bit of energy on its bounds so how can we achieve this effect in real time unity supports scattering in its high definition rendering pipeline using a screen space blur to achieve diffusion but is not mobile friendly this method approximates the effect by illuminating the surface from the side opposite to the light taking into account the view direction and the surface normal in this example if we have a light coming from the upper left corner our fake illumination would come from the bottom right if the pure direction vector is l then our opposite leg direction is minus l next we want to consider the b direction a viewer that is perpendicular to the light would see less of it than a viewer that is situated on its opposite side we can use the dot product of these two vectors l and v to get a value that describes the angle between them finally we're going to use the surface direction to modify the direction of the light this represents the property of some translucent materials to propagate light across this surface we'll simply add the normal vector n to the light direction vector let's go back into unity and get it started the first thing to do is to create a shader graph use either the top menu or right click on the asset explorer and select create shader graph universal rendering pipeline or urp and finally lead shader graph now give it a name and double click on it to open the graph editor the first thing we want to do is to get the light direction and its intensity the editor doesn't have that node but we can write around using a custom function node create one of those and change its type from file to a string we are only adding a few lines of code so it will be necessary to create a separate file now give this function a name and add two variables the first one is a vector3 that will store the direction vector we'll call this one main light direction the second one is going to be a float and we'll call it main light intensity i know that intensity should be a vector 3 as well but this will make things a bit simpler for now if you wonder about the pink checkerboard pattern the error pop-up those are happening because the variables that we just created don't have default values yet we'll fix that in a second here's the code for our custom function let's go over how it works the if dev block at the top applies only while in the editor since we don't have a main light we need to assign the full values to the variables we created to get rid of those errors the rest of the code is equally simple main glide direction equals get mine light parenthesis dot direction to assign the direction vector and main line intensity equals the length of get mainlite dot color this is why i mentioned earlier that intensity should be a vector instead of a float once this is done clicking outside the inspector panel will update our custom node and change the preview to this yellow color next create a normal vector node and leave the space the world you can click on the arrows to hide the node previews and make some room on the editor we'll add now these two vectors together first create an add node and connect its b input to the main light direction however we want to control how much the normal affects the light direction to do that add a multiply node and connect one of its inputs to the normal the other one will be a new exposed variable a float that we will call normal influence after renaming the variable drag it into the main editor window and connect it to the other multiply input and then the multiply itself to the previous add node now since we are adding these two vectors together they are no longer a unit vector so we need to add a normalized node and connect it finally as we saw in the diagram earlier we're going to use the opposite direction to the light so we need to add a negate node to keep things a bit more organized we're going to group all these nodes together next add a view direction and a dot product node connect them and connect the output of the negate node as well the order of factors in a dot product doesn't matter so i'll reconnect the wires just to have less of them crossing now add a saturate node to ensure that the values on the vector are between 0 and 1 and after that we have a value that represents the amount of scatter across the surface but to control its intensity and how it ramps we're going to use a power and a multiply node in that order we will also create two new float variables to control these values in this case i call them sss power and sss intensity for subsurface scattering drag both of them to the editor window and connect the first one to the power node and the second one to the multiply node many translucent materials have a different interior color revealed only when light shines to them we can achieve this effect by adding a color variable and multiplying it by the result of the previous operation another thing we can do to achieve a more convincing result is to change the amount of scatter based on the thickness of the object at that point while there is no easy way to calculate thickness in runtime we can use texture map to sample this value some software tools like substance painter can bake thickness maps for any geometry but this can also be approximated with an inverted ambient occlusion baked texture i added a texture to the parameter and a sampler node and yet another multiply connected to the previous result note that there will be more light passing through where the object is thinner so i will need to invert the texture using a 1 minus node place between the sampler and the multiply substance painter uses 1 or white to represent the thickest values but you might not need the 1 minus if your texture values are already inverted the last aspect of the main color is to add the light from the fake scatter to the original color of the surface we will need a new texture to the parameter and a new color parameter we will sample the texture to the and multiply the result by the new color then add the result of that to the result of our previous multiply on the thickness group this is our final color and can be connected already to the base color input on the fragment node but before we go back to our scene we will add a few extra parameters to the shader first another texture 2d with a sampler connected to the ambient occlusion input on the fragment and second a float to control the smoothness value once everything's connected let's go back to the scene and test this shader the easiest way is to right click on the shader and from there select create material this will create a new material based on our shader rename it and drag it to your test model don't worry if it doesn't look right at first that just means that our default parameter values are all zero or empty after spending a couple minutes adjusting the material settings our model looks pretty good at this point i realized that i didn't use the light intensity value let's go back to the editor and fix that in a moment first create a multiply node and connect both the light intensity and the output of the scatter group to its inputs then replace the previous output of that node with a new one now if we go back to our scene we can see that changing the light intensity correctly affects the intensity of the scatter effect and with that our shader is complete if you made it this far thank you for watching the video let me know in the comments if you use this shader in your projects
Info
Channel: Enrique Ventura
Views: 27,475
Rating: undefined out of 5
Keywords: unity, urp, shader, shadergraph, sss, subsurface, scattering, subsurface scattering, mobile, game, lightweight
Id: ipge1K51JJs
Channel Id: undefined
Length: 11min 6sec (666 seconds)
Published: Fri Mar 25 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.