Latest news

Unity Shadergraph: How to properly use booleans in a shader?

For those who are not familiar with the Unity shader programming language Shaderlab, or HLSL. Unity created an amazing new system called Shadergraph; A node-based system that allows artists to create shaders and materials the same way they can create textures with Substance Designer or similar software.

But using Shadergraph the same way as a texture in substance designer is a huge trap!

The reason is that a shader is executed in real-time every frame within the GPU of the computer.

But why all this introduction to talk about booleans within a shader? It’s just a TRUE or FALSE, right?

Yes, but the way Shadergraph uses the Boolean node is quite unintuitive and tricky!

See for yourself:

Unity Shadergraph is only showing logical operators to be used with the boolean node, and guide the user to use “Branch”. At first it just look like a simple node that just selects between any value True or False!

Let’s see what it means by right-clicking on the node itself and then opening the documentation of Unity Shadergraph

Here is the problem, it does code branching for every pixel of a mesh, for the people that are not used to code logic and programming, this code below:

void Unity_Branch_float4(float Predicate, float4 TrueValue, float4 FalseValue, out float4 Out)
{
    Out = Predicate ? TrueValue : FalseValue;
}

Is the exact same code than this one:

void Unity_Branch_float4(float Predicate, float4 TrueValue, float4 FalseValue, out float4 Out)
{
    if(Predicate == True) 
    {
        Out = TrueValue;
    }
    else 
    {
        Out = FalseValue;
    }
}

In short (and very simplified), GPU is extremely good at crunching a gigantic amount of math problems as long it’s the same formula and only variables are modified. Still, as soon as you branch, you modify the formula and then reduce its processing power.

Most of the Shadersgraph nodes are executed for every pixel. So, for a 4k screen, it means it will run in the best case 8.294.400 times per frame, so at 60 frames per second, The nodes are executed 497,664,000 times per second.

With that said, it means any variation in the shaders can cause significant impacts on the performances.

If you want to know more about how to avoid Branching on the GPU, you can have a look at the blog post written by Brandon Sean Fogerty HERE.

How to prevent Branching in Shadergraph?

At this time, the latest verified package for Universal RP, including Shadergraph (8.2.0), does not have a dedicated node for converting a boolean variable to something else, but that’s ok; we will do it ourselves.

Let’s do a Custom Function:

1. Create the input variable and call it Value, then select Boolean
2. Create another variable in Outputs called Out and select Vector1
3. change the type to Sting and name it BooleanToVector1, then we will set the Body to:

Out = Value*1;

This is an example of how to use that freshly custom new function:

If we would have to write that down the code, this how it used to look like:


    if(Boolean02 == True) 
    {
        Out = Value1;
    }
    else 
    {
        Out = Value2;
    }

And now it look like this:

Out = lerp(Value1, Value2, Boolean02*1;

That’s much better!

I hope you liked that article, don’t hesitate to share it on Twitter and tag us!

exiinUnity Shadergraph: How to properly use booleans in a shader?