You can toggle the Blackboard on and off using the button in the top-right of the window. We could calculate the Fresnel using the calculations we mentioned earlier, but Unity provides a Fresnel node out of the box, so drop one onto your graph. You’ll be asked to create a new asset - I called mine MainLighting.shadersubgraph. Returns a reflection vector using input In and a surface normal Normal. With a couple of default values applied on the Blackboard, the graph should look like this: We can use default values to visualise the output. We’re writing a cel-shader, so we need to interact with Unity’s lighting engine. For normalized input vectors, the Dot Product node returns 1 if they point in exactly the same direction, -1 if they point in completely opposite directions and 0 if the vectors are perpendicular. We need the Wrap mode to be set to Clamp so that lighting values above 1 don’t cause strange lighting effects. It will be a dot product of the normal vector of our mesh and light direction. Returns the transposed value of the matrix defined by input In. We’ll connect a new Normal Vector node (in world-space) to its Normal input and leave the default value for the View Dir input. We’re going to create a cel-shading effect using Shader Graph, aiming for a result that looks like the lighting used in The Legend of Zelda: Breath of the Wild or The Wind Waker. You can right-click on the preview window to swap the shape of the preview mesh to a cube, quad, sphere and a handful of others. The first step will be, of course, to create a new shader graph. The whole project is available at my public repository. Splits a square matrix defined by input In into vectors. For normalized input vectors, the Dot Product node returns 1 if they point in exactly the same direction, -1 if they point in completely opposite directions and 0 if the vectors are perpendicular. As always, there are a few steps to follow. We’ll have to use a Custom Function node instead. The shading becomes darker where the sphere is not in direct light. Now, we will have to normalize the output of the Dot Product to be in the range of 0 to 1. We’ll start off with ambient lighting because Unity provides a node for us. There’s a node for that - Transform. Ethan also comes with a normal map, which we can use to vastly improve the lighting. A cel-shading light model is one where the lighting has hard ‘cuts’ where light transitions to dark. Connect the Split node the X component of a Vector2 node and leave the Y value as 0. However, we’re missing a lot of detail. We’ll then use Unity’s built-in functions to determine how we will retrieve lighting information. This is comprised of values the Camera's GameObject, such as Position and Direction, as well as various projection parameters.. Returns a sawtooth wave from the value of input In. After the Power node, we’ll do something a bit strange and create an Add node but leave the second argument as zero - we don’t need to use this yet, but later on we’re going to add the Fresnel lighting using this node. Finally, your PBR Master node sits in the centre. The easiest type of light to model is ambient light, which is a measure of indirect light on an object. We can define its inputs and outputs as well as the code of that function. And with that, we won’t need to do any more scripting for the rest of the article. Remaps the value of input In from between the values of input Out Min Max to between the values of input In Min Max. Drag the property onto the graph and use it as the Texture pin of a Sample Texture 2D node - not the LOD variant, this time we want Unity to handle mipmapping automatically - and leave the UV and Sampler fields with the default values. Returns the sum of both partial derivatives. Ramp texture is nothing more than a texture with a height of 1px and a width of how much you want. We can use Sub Graphs to organise code effectively. Then, we can plug in the colour we want to use for the material into the Emission channel. Stick a Transform node on the graph to transform between Tangent and World space, with Type set to Direction. For our purpose, we have to use the Unlit Shader Graph. Returns the result of input A divided by input B. If we set the Albedo colour to black and the Metallic and Smoothness values to 0, Unity will strip out some of the lighting-related code from the compiled shader code. Each node has clearly labelled inputs and outputs so it’s a lot easier to get to grips with than code. float4x4 _WorldToShadowCascadeMatrices[5]; Now we have to include the (0,0,0,0) → 4 conversion, which we can do by starting with 4 and subtracting the dot product of the isolated flag with (4,3,2,1). We’ll also create a View Direction node with its Space set to World, pass its output to a Normalize node (which sets the vector’s length to 1), then pass that into the other Add input. Your main preview should now update to show a material with diffuse shading! Therefore, we will obtain the value 1 when there is no snow at the output of the Remap Node.Likewise, the output value of the Remap Node will be -1 if the amount of snow is high. Now we’ll handle diffuse light, which is a bit more complicated. First, we’ll add a new property called Smoothness of type Vector1 to let us set the amount of specularity in the material Inspector - give it a default value of 0.5 and make sure Exposed is ticked. We can connect it to the Dot Product node. Noise Sine Wave We need another directive to do this, which we will nest inside the else-block of the first directive. For this, let’s apply the material to a more complicated model than a sphere - we’ll bring out the Ethan model that used to be included in Unity’s Standard Assets package. But that won’t be important for us. You can minimise most of these previews to keep the graph concise, but it’s extremely useful to see what your material looks like at key stages. Returns the sine of the value of input In. Sawtooth Wave Returns the determinant of the matrix defined by input In. Ports Let’s call it “Toon Shading Shader Graph” and open it. Once you’ve created a graph, name it whatever you want then double-click it to open up the Shader Graph editor tab - you should see a single node called PBR Master. Programming geek with love to clean high-quality code. Returns the result of 1 divided by the square root of input In. Our model is currently missing texture, and I think we should do something about it. Returns -1 if the value of input In is less than zero, 0 if equal to zero and 1 if greater than zero. Keywords give us a way to introduce branches into our shader in a safe way; if-statements in shaders often slow them down because the hardware can’t use prediction techniques, but with a keyword we can compile two versions of the shader - one which uses Rim Strength for the Fresnel, and the other that just returns zero. Connecting Normal Vector and Dot Product nodes. Unity then applies lighting to the object based on these properties. Click the cog menu in the top-right corner of the node to configure the inputs and outputs - we’ll need a Vector3 in the Inputs section, followed by two Vector3s and a Vector1 for the Outputs.