What you'll get out of this article: New features and recommended workflows for Shader Graph in Unity that enable you to easily author shaders by building them visually and see the results in real-time. Based on Technical Evangelist Ciro Continisio’s talk at Unite Copenhagen 2019.
What is Shader Graph?
With Shader Graph you can build shaders visually. Instead of writing code, you create and connect nodes in a graph framework. Shader Graph gives instant feedback that reflects your changes. If you’re new to shader creation, this makes shaders easy.
Shader Graph is designed to work with the Scriptable Render Pipelines (SRPs), namely the Universal Render Pipeline (formerly the Lightweight Render Pipeline or LWRP) and the High Definition Render Pipeline (HDRP). Shader Graph has also been used in the latest Unity demos – the FPS Sample and The Heretic.
Shader Graph is ready for production, which means that it’s a verified package* and you can use it in your own projects. (*Is part of an LTS version of Unity)
Here’s a breakdown of a few general improvements in Shader Graph since its initial release.
New master nodes
The master node is the end point of a Shader Graph and it contains the template of the shader that is going to be filled with the data you create on the graph. With the Universal Render Pipeline, you get four master nodes: Unlit and PBR, and if you’re using the 2D Renderer you can also use Unlit Sprite and Lit Sprite.
The High Definition Render Pipeline (HDRP) offers six master nodes. These master nodes allow you to create visuals only achievable in HDRP: for instance, you can use the StackLit master node (which is basically three materials in one) to simulate the coat of a car with multiple layers of paint on top of the original metal surface.
Universal Render Pipeline
- Unlit, PBR
- Unlit Sprite, Lit Sprite
High-Definition Render Pipeline
- Lit, Unlit
- Fabric, Hair, Decal, StackLit
In the future, we plan to add master nodes that work with the user interface (UI) feature, Post Processing Stack, and Visual Effect Graph.
Another addition to Shader Graph is a small drop-down menu that allows you to choose the precision (float or half) of the calculations of your nodes. This means that you can create shaders that target specific devices, such as desktop or mobile, and you can tweak their precision according to your project needs. You can modify the precision at the node, graph, and subgraph levels, and you can set whether the precision is inherited.
Color mode can be used to categorize nodes according to different colors, and it can also be used to visualize the precision of the nodes. It comes in handy when you want to identify nodes that need tweaking or spots where the precision deviates. In fact, it makes sense to switch between different color modes multiple times as you work. This is especially useful for team collaboration – you can assign colors to specific subgraphs or nodes so you can recognize them at a glance.
Extended Sub Graph functionality
Sub Graphs are used to create graphs that can be referenced inside other graphs. This is useful when you wish to perform the same operations multiple times in one graph or across multiple graphs, or if you want to declutter your graphs.
One of the improvements brought to Sub Graphs is the option to name outputs on the Output Node. Whenever you use a specific Sub Graph, you’ll see these properties named accordingly, inside and outside of the Sub Graph.
In addition, the Sub Graph outputs supported are the same as the output types used in a Shader Graph, creating a clearer workflow. You can now also nest Sub Graphs into each other indefinitely, allowing you to put small chunks of functionality into progressively bigger graphs, until the final graph containing the master node.
Adding a custom HLSL code to your Shader Graph
Now you can also add custom HLSL code to your Shader Graph.
You can use HLSL directly inside a node called a Custom Function node or import the HLSL from an external file in .hlsl format, which can then be used as a repository for your custom functions. We recommend you use the file option any time your function requires more than a couple of lines.
The Custom Function node is a premade node that accepts a custom function. This means that you can upgrade your graphs to a newer version of Shader Graph without having to update your custom HLSL code.
In the image above, you can see a simple example of a Custom Function node with embedded HLSL calculating the sum of two numbers. A and B are input ports on the node. Their sum is then outputted in a port called Sum. You can see how the names of the variables in the graph correspond to the ports.
Better error handling
Whenever a graph doesn’t compile, you can now view the error message inside the graph. These are the same error messages you would see in your integrated development environment (IDE). We have also added a wealth of useful tips to help you understand how to change the graph to address the error.
Sticky Notes and Groups
The Sticky Notes feature makes it possible for you to annotate your graph, while Groups lets you link objects or nodes into a group that you can title, providing more context to team members working on the graph. With Groups you can also move and delete nodes in bulk. Both of these features are handy collaboration tools.
Keywords are a special type of variable. On the surface, they look like a normal Boolean property that you would use in a Branch node. However, they allow you to create variants of a shader, so that the engine compiles different shader versions for each branch. This is more efficient at runtime than having a Branch node where both branches are fully executed. The tradeoff is in compile time as each the number of variants grows exponentially with each keyword.
- 1 Bool keyword = 2x the variants
- 5 bool keywords = 32x the variants
- 3 enum keywords with 4 options each = 64x the variants
Keywords can be Boolean or enum, local or global. The different types of keywords are shader feature, multi-compile, predefined, and Material Quality.
Material Quality is a special type of keyword that comes directly from the rendering pipeline. You can have a branching path that adapts to the level of detail, or is used to add and remove effects, depending on the level of quality set by the pipeline. At runtime, you can give your users the ability to switch the level of quality for your game, and then shaders with the Material Quality keyword will react accordingly.
If you want to discuss Shader Graph and the shaders you can make with it, come hang out in the dedicated forum space, or learn more about what you can do with Shader Graph by following these tutorials on Unity Learn.