Hey fellow Shader Artists!
I’ve read here and there about how confusing and frustrating it can be to deal with global properties in Shader Graph and decided to gather some information here to the best of my knowledge and understanding.
I might be wrong and will correct and/or add more as I learn new things.
Please reply to this thread if you have any questions or information you want to share on the topic.
Global VS static
Static variables can be used in both ShaderLab and Shader Graph (using a Custom Function node), but they cannot be read nor assigned to from outside shader code.
They are, by definition, shared between all material instances.
Unlike static variables, globals are variables handled in C#, that will be assigned to all materials with a matching definition (name & type).
Global VS Local (Per Material)
In Shader Graph, a property is made local when set as exposed.
If you check Override Property Declaration and set the Shader Declaration dropdown to Global, it will still be a Local (Per Material) property if exposed is checked.
In ShaderLab, a global property is a variable that is declared within the HLSLPROGRAM body.
float _MyCustomProperty;
The variable is made local when it is associated with a Property:
_MyCustomProperty("MyCustomProperty", Float) = 0
Global
A Global variable can be read and assigned to from C# using Shader.GetGlobalFloat(“_MyFloat”) and Shader.SetGlobalFloat(“_MyFloat”, value).
This will change the value in all material instances, except those where the value was overridden using a Property Block.
It cannot be set at material instance level with Material.SetFloat().
Since HLSL doesn’t allow for variable initialization, global variables have no default value, and must be initialized from C#, or else they will always default to zero/black.
Shader Graph allows changing the default value of global variables.
While it allows previewing the effect of a global in Shader Graph, this only gives a preview of what will happen when the variable is assigned to.
Local (Per Material)
A Local variable can be read and assigned to from C# at material instance level, using material.GetFloat(“_MyFloat”) and material.SetFloat(“_MyFloat”, value).
This will change the material’s property value, unless overridden using a Property Block.
It cannot be set at global level with Shader.SetGlobalFloat().
Default Values
Global
Global properties have no default value. They are not serialized and require explicit initialization with Shader.SetGlobalFloat(“_MyFloat”, value).
Local (Per Material)
Changing the default value of an exposed (local) property will not propagate to existing material instances.
That is similar to changing the default value of a MonoBehaviour field, which neither propagates to existing instances of that MonoBehaviour.
Making Material Instances as Material Variants of the Shader Graph (nested) Material allows them to inherit the properties they don’t override, just like Prefabs allows the same for MonoBehaviours.
Reading from Shader
Although a variable can be modified from within shader code, it is worth noting that a variable value read from C# will always returned the last value it was assigned from C#.
In short: what happens on the GPU stays on the GPU.
Say you have a shader global (not exposed) float “_MyFloat”.
Calling Shader.GetGlobalFloat(“_MyFloat”) will only return the last value it was assigned from C#, but not any value that it was assigned from within Shader code.
DOTS Instancing
DOTS allows for another type of property declaration : Hybrid Per Instance.
If you check Override Property Declaration and set the Shader Declaration dropdown to Hybrid Per Instance, the effect of the exposed checkbox differs. Since those variables are by definition per instance, they cannot be global.
Unchecking the exposed checkbox will simply just add a [HideInInpector] attribute to the property, hiding it from the material inspector.
Whether it is visible or not, the property can be read and assigned to using material.GetFloat(“_MyFloat”) and material.SetFloat(“_MyFloat”, value).
This will change the material’s property value, unless overridden using a Property Block.
For more information, see:
Entities Graphics | 1.0.11
Manual: DOTS Instancing shaders
Exceptions / Limitations
Gradients
HLSL doesn’t feature a value type for Gradients. As a result, they can be added to the Blackboard for the purpose of editing them once and use them in several places in a graph, but cannot be exposed in the Material Inspector.
Matrices
ShaderLab doesn’t feature a Property Type for Matrices (float4x4, float3x3, float2x2). As a result, their value cannot be exposed in the Material Inspector.
As with Globals, the preview value is only used within Shader Graph. Material Instances need to be initialized with Material.SetMatrix(), MaterialPropertyBlock.SetMatrix() or Shader.SetGlobalMatrix().
Sampler States
ShaderLab doesn’t feature a Property Type for Sampler States. As a result, they cannot expose their value fields in the Material Inspector.
Array Types
Although ShaderLab allows for arrays (Floats, Vectors and Matrices) that can be set with Shader.SetGlobalFloatArray(), Shader.SetGlobalVectorArray() and Shader.SetGlobalMatrixArray(), Shader Graph doesn’t feature typed arrays properties.
In general, arrays become useful with iterators and are otherwise less performant than Vectors or Matrices.
In other words, it’s good practice to pack floats and vectors in vectors or matrices.
UX Improvements
Shader Graph Property Scope & Visibility settings
We are planning to rework the UX to make the scope and visibility settings easier to work with and enable hiding local properties.
If this is important to you, or want to add comment, please let us know on the Product Board:
https://portal.productboard.com/unity/1-unity-platform-rendering-visual-effects/c/2239-property-scope-visibility
Shader Globals
Having to write a C# component for the sole purpose of initializing shader globals isn’t ideal.
We are considering adding Shader Globals to Project Settings so that users can easily initialize them.
Please let us know what you think about this here on the Product Board.
https://portal.productboard.com/unity/1-unity-platform-rendering-visual-effects/c/2256-shader-globals