1
GenerativeArt–MadewithUnity
Best Practices for
Shader Graph
2
Charles Sanglimsuwan
Developer Relations Engineer
What we'll cover today
 Motivations
 Demo
 How Shader Graph works
 Choosing the right Master Node
 Optimizations
 Workflow
 What’s next
3
Motivations
4
5
Democratize
Development
Solve Hard
Problems
Enable
Success
6
Brief History
 Early work started in May 2017
 Preview package released in Unity 2018.1
 23 updates since
7
How Shader Graph works
8
Scriptable Render Pipeline
 Shader Graph requires SRP
 High Definition Render Pipeline (HDRP)
 Lightweight Render Pipeline (LWRP)
 VR Lightweight Render Pipeline (VR LWRP)
9
The Master Node
10
Shader Generation Process
 Each Render Pipeline has a shader backend
 Shader backends include subshader generators for supported Master
Nodes
 Not all Master Nodes supported by every RP
11
Subshader Generators
 Each Master Node has a per-pipeline template
 Templates have many injection points
 Your Shader Graph is traversed, and injection points are replaced with
node values
 Final outcome is a shader (written in ShaderLab)
12
Shader Anatomy
13
Properties
Subshader
{
Tags
Pass
{
Material Options
Includes & Defines
Graph Functions
Surface Description Input Struct
Surface Description Output Struct
Surface Description Function
Vertex Input Struct
Vertex Output Struct
Vertex Shader
Fragment Shader
}
}
14
Shader Graph
15
Properties
Subshader
{
Tags
Pass
{
Material Options
Includes & Defines
Graph Functions
Surface Description Input Struct
Surface Description Output Struct
Surface Description Function
Vertex Input Struct
Vertex Output Struct
Vertex Shader
Fragment Shader
}
}
Shader Graph
16
Properties
Subshader
{
Tags
Pass
{
Material Options
Includes & Defines
Graph Functions
Surface Description Input Struct
Surface Description Output Struct
Surface Description Function
Vertex Input Struct
Vertex Output Struct
Vertex Shader
Fragment Shader
}
}
Shader Graph
17
Properties
Subshader
{
Tags
Pass
{
Material Options
Includes & Defines
Graph Functions
Surface Description Input Struct
Surface Description Output Struct
Surface Description Function
Vertex Input Struct
Vertex Output Struct
Vertex Shader
Fragment Shader
}
}
Shader Graph
18
void Unity_Multiply_float (float3 A, float3 B, out float3 Out)
{
Out = A * B;
}
struct SurfaceDescriptionInputs
{
float3 WorldSpaceTangent;
}
struct SurfaceDescription
{
float3 Albedo;
}
SurfaceDescription PopulateSurfaceData (SurfaceDescriptionInputs IN)
{
SurfaceDescription surface = (SurfaceDescription)0;
float _Vector1_1EF2E600_Out = 2;
float3 _Multiply_E1E37A64_Out;
Unity_Multiply_float(IN.WorldSpaceTangent,
_Vector1_1EF2E600_Out.xxx,
_Multiply_E1E37A64_Out)
surface.Albedo = _Multiply_E1E37A64_Out;
return surface;
}
Example: Surface Description
19
void Unity_Multiply_float (float3 A, float3 B, out float3 Out)
{
Out = A * B;
}
struct SurfaceDescriptionInputs
{
float3 WorldSpaceTangent;
}
struct SurfaceDescription
{
float3 Albedo;
}
SurfaceDescription PopulateSurfaceData (SurfaceDescriptionInputs IN)
{
SurfaceDescription surface = (SurfaceDescription)0;
float _Vector1_1EF2E600_Out = 2;
float3 _Multiply_E1E37A64_Out;
Unity_Multiply_float(IN.WorldSpaceTangent,
_Vector1_1EF2E600_Out.xxx,
_Multiply_E1E37A64_Out)
surface.Albedo = _Multiply_E1E37A64_Out;
return surface;
}
Example: Surface Description
20
void Unity_Multiply_float (float3 A, float3 B, out float3 Out)
{
Out = A * B;
}
struct SurfaceDescriptionInputs
{
float3 WorldSpaceTangent;
}
struct SurfaceDescription
{
float3 Albedo;
}
SurfaceDescription PopulateSurfaceData (SurfaceDescriptionInputs IN)
{
SurfaceDescription surface = (SurfaceDescription)0;
float _Vector1_1EF2E600_Out = 2;
float3 _Multiply_E1E37A64_Out;
Unity_Multiply_float(IN.WorldSpaceTangent,
_Vector1_1EF2E600_Out.xxx,
_Multiply_E1E37A64_Out)
surface.Albedo = _Multiply_E1E37A64_Out;
return surface;
}
Example: Surface Description
21
void Unity_Multiply_float (float3 A, float3 B, out float3 Out)
{
Out = A * B;
}
struct SurfaceDescriptionInputs
{
float3 WorldSpaceTangent;
}
struct SurfaceDescription
{
float3 Albedo;
}
SurfaceDescription PopulateSurfaceData (SurfaceDescriptionInputs IN)
{
SurfaceDescription surface = (SurfaceDescription)0;
float _Vector1_1EF2E600_Out = 2;
float3 _Multiply_E1E37A64_Out;
Unity_Multiply_float(IN.WorldSpaceTangent,
_Vector1_1EF2E600_Out.xxx,
_Multiply_E1E37A64_Out)
surface.Albedo = _Multiply_E1E37A64_Out;
return surface;
}
Example: Surface Description
22
Properties
Subshader
{
Tags
Pass
{
Material Options
Includes & Defines
Graph Functions
Surface Description Input Struct
Surface Description Output Struct
Surface Description Function
Vertex Input Struct
Vertex Output Struct
Vertex Shader
Fragment Shader
}
}
Shader Graph
23
Properties
Subshader
{
Tags
Pass
{
Material Options
Includes & Defines
Graph Functions
Surface Description Input Struct
Surface Description Output Struct
Surface Description Function
Vertex Input Struct
Vertex Output Struct
Vertex Shader
Fragment Shader
}
}
Shader Graph
Choosing a Master Node
24
Master Node Overview
25
UnlitHD Lit PBR
PBR Master Node
 Works with all Render Pipelines
 Good starting point for prototyping
 Feature ready for many scenarios
26
HD Lit Master Node
 Compatible only with HDRP
 More features than PBR
 Easy to add needless complexity
27
28
Unlit Master Node
 Works with all Render Pipelines
 Very lightweight
 Good for effects, vertex modifications
29
Unlit Master Node
Possible to add custom lighting:
1. Create nodes to calculate lighting
from desired shading model (e.g., Blinn-Phong)
2. Connect output color to the Color port
30
Master Node Review
 PBR is the most versatile node
 Use HD Lit only when applicable and necessary
 Consider Unlit for particle effects, UI, etc.
31
Unity Optimizations
32
Built-in Optimizations
1. Where ever possible, Shader Graph will not add unused features to
output shader
 Changing the default value will mark the feature active
 Connecting any node will mark the feature active
2. The shader compiler will compile out no-op features
33
Optimization Example: Coat Mask
34
No CoatMask code will be present in the output
ShaderLab code if the value is zero
Optimization Example: Metallic
35
If the Metallic is set to zero, that code block will
be compiled out by the shader compiler
Optimization Example: Emission
36
If the Emission is set to Black, and disabled in
Material, that code block will be compiled out by
the shader compiler
Built-in Optimizations
1. Where ever possible, Shader Graph will not add unused features to
output shader
 Changing the default value will mark the feature active
 Connecting any node will mark the feature active
2. The shader compiler will compile out no-op features
37
Draw Call Batching
 GPU instancing is supported in shaders
 Needs to be enabled on the material
 Requires hardware support
 All generated shaders are compatible with the SRP Batcher (2018.3)
38
GPU Instancing
39
SRP Batcher
 New batching solution, designed for SRP
 Improved rendering performance
 Works with SkinnedMeshRenderers!
 Requires per-material parameters to be stored in a constant buffer
40
Render Faster with the SRP Batcher
41
0
5
10
15
20
25
30
35
Scene: 1024 materials Scene: 1 material
RenderTime(ms)
5.26x Faster 1.27x Faster
SRP
Legacy
Lower is better
Graph Optimizations
42
Node Decimation
 Eliminate no-op nodes
 Bake values back into the textures
 Examples: gradients, noise
 Combine nodes when possible
43
Example: Texture Modification
44
Example: Power
45
46
47
48
Data Formats
 Each node has a memory cost
 Use smaller data structures when possible
 Modifying precision
 Requires code modification
49
50
public enum OutputPrecision
{
@fixed,
@half,
@float
}
private OutputPrecision m_OutputPrecision = OutputPrecision.@float;
Modifying Precision
AbstractMaterialNode.cs
Reduce Math Operations
 Multiply scalar values before vector values
 Prefer blending results, instead of branching
 Research impact of certain math operations
 Prefer constants when possible
51
Example: Reciprocal
52
Fast mode requires Shader Model 5
Reduce Math Operations
 Multiply scalar values before vector values
 Prefer blending results, instead of branching
 Research impact of certain math operations
 Prefer constants when possible
53
Example: Properties
54
Workflow: Manual Optimizations
 Hand-optimizing shaders is a one-way path
 Don’t manually optimize too early
 Copy or view shader code in Master Node menu
55
Workflow: Manual Optimizations
56
Workflow: Faster Iterations
 Nodes not connected to Master Node aren’t evaluated
 Can keep them in view for quick iterations
 Create a Preview node that isn’t attached to the Master Node
 Editing these nodes will be much faster
57
Workflow Summary
1. Prototype with PBR Master Node
 Move to HD Lit if necessary
2. Start optimization
1. Optimize nodes
2. Convert properties to inline values
3. Near the end of the project, start hand optimizing shaders
58
Exploratory
59
Custom API
 Create your own nodes
 Examples: specialized noise functions, custom lighting, etc.
 Full documentation available on GitHub
60
Vertex Modification
 Low-impact on CPU performance
 Good for animating foliage, water, or cloth
61
62
Foliage
63
Animating Water
What’s next
64
Roadmap
2019.1
 First official, verified release
 Completely overhauled Node API
 Key bug fixes, UX improvements
65
Available Resources
 Plentiful samples abound:
 Andy Touch
 Keijiro Takahashi
 Video tutorials on YouTube
 Source available on GitHub
66
Questions?
67
68
Thank you

Best Practices for Shader Graph

  • 1.
  • 2.
    GenerativeArt–MadewithUnity Best Practices for ShaderGraph 2 Charles Sanglimsuwan Developer Relations Engineer
  • 3.
    What we'll covertoday  Motivations  Demo  How Shader Graph works  Choosing the right Master Node  Optimizations  Workflow  What’s next 3
  • 4.
  • 5.
  • 6.
  • 7.
    Brief History  Earlywork started in May 2017  Preview package released in Unity 2018.1  23 updates since 7
  • 8.
  • 9.
    Scriptable Render Pipeline Shader Graph requires SRP  High Definition Render Pipeline (HDRP)  Lightweight Render Pipeline (LWRP)  VR Lightweight Render Pipeline (VR LWRP) 9
  • 10.
  • 11.
    Shader Generation Process Each Render Pipeline has a shader backend  Shader backends include subshader generators for supported Master Nodes  Not all Master Nodes supported by every RP 11
  • 12.
    Subshader Generators  EachMaster Node has a per-pipeline template  Templates have many injection points  Your Shader Graph is traversed, and injection points are replaced with node values  Final outcome is a shader (written in ShaderLab) 12
  • 13.
  • 14.
    Properties Subshader { Tags Pass { Material Options Includes &Defines Graph Functions Surface Description Input Struct Surface Description Output Struct Surface Description Function Vertex Input Struct Vertex Output Struct Vertex Shader Fragment Shader } } 14 Shader Graph
  • 15.
    15 Properties Subshader { Tags Pass { Material Options Includes &Defines Graph Functions Surface Description Input Struct Surface Description Output Struct Surface Description Function Vertex Input Struct Vertex Output Struct Vertex Shader Fragment Shader } } Shader Graph
  • 16.
    16 Properties Subshader { Tags Pass { Material Options Includes &Defines Graph Functions Surface Description Input Struct Surface Description Output Struct Surface Description Function Vertex Input Struct Vertex Output Struct Vertex Shader Fragment Shader } } Shader Graph
  • 17.
    17 Properties Subshader { Tags Pass { Material Options Includes &Defines Graph Functions Surface Description Input Struct Surface Description Output Struct Surface Description Function Vertex Input Struct Vertex Output Struct Vertex Shader Fragment Shader } } Shader Graph
  • 18.
    18 void Unity_Multiply_float (float3A, float3 B, out float3 Out) { Out = A * B; } struct SurfaceDescriptionInputs { float3 WorldSpaceTangent; } struct SurfaceDescription { float3 Albedo; } SurfaceDescription PopulateSurfaceData (SurfaceDescriptionInputs IN) { SurfaceDescription surface = (SurfaceDescription)0; float _Vector1_1EF2E600_Out = 2; float3 _Multiply_E1E37A64_Out; Unity_Multiply_float(IN.WorldSpaceTangent, _Vector1_1EF2E600_Out.xxx, _Multiply_E1E37A64_Out) surface.Albedo = _Multiply_E1E37A64_Out; return surface; } Example: Surface Description
  • 19.
    19 void Unity_Multiply_float (float3A, float3 B, out float3 Out) { Out = A * B; } struct SurfaceDescriptionInputs { float3 WorldSpaceTangent; } struct SurfaceDescription { float3 Albedo; } SurfaceDescription PopulateSurfaceData (SurfaceDescriptionInputs IN) { SurfaceDescription surface = (SurfaceDescription)0; float _Vector1_1EF2E600_Out = 2; float3 _Multiply_E1E37A64_Out; Unity_Multiply_float(IN.WorldSpaceTangent, _Vector1_1EF2E600_Out.xxx, _Multiply_E1E37A64_Out) surface.Albedo = _Multiply_E1E37A64_Out; return surface; } Example: Surface Description
  • 20.
    20 void Unity_Multiply_float (float3A, float3 B, out float3 Out) { Out = A * B; } struct SurfaceDescriptionInputs { float3 WorldSpaceTangent; } struct SurfaceDescription { float3 Albedo; } SurfaceDescription PopulateSurfaceData (SurfaceDescriptionInputs IN) { SurfaceDescription surface = (SurfaceDescription)0; float _Vector1_1EF2E600_Out = 2; float3 _Multiply_E1E37A64_Out; Unity_Multiply_float(IN.WorldSpaceTangent, _Vector1_1EF2E600_Out.xxx, _Multiply_E1E37A64_Out) surface.Albedo = _Multiply_E1E37A64_Out; return surface; } Example: Surface Description
  • 21.
    21 void Unity_Multiply_float (float3A, float3 B, out float3 Out) { Out = A * B; } struct SurfaceDescriptionInputs { float3 WorldSpaceTangent; } struct SurfaceDescription { float3 Albedo; } SurfaceDescription PopulateSurfaceData (SurfaceDescriptionInputs IN) { SurfaceDescription surface = (SurfaceDescription)0; float _Vector1_1EF2E600_Out = 2; float3 _Multiply_E1E37A64_Out; Unity_Multiply_float(IN.WorldSpaceTangent, _Vector1_1EF2E600_Out.xxx, _Multiply_E1E37A64_Out) surface.Albedo = _Multiply_E1E37A64_Out; return surface; } Example: Surface Description
  • 22.
    22 Properties Subshader { Tags Pass { Material Options Includes &Defines Graph Functions Surface Description Input Struct Surface Description Output Struct Surface Description Function Vertex Input Struct Vertex Output Struct Vertex Shader Fragment Shader } } Shader Graph
  • 23.
    23 Properties Subshader { Tags Pass { Material Options Includes &Defines Graph Functions Surface Description Input Struct Surface Description Output Struct Surface Description Function Vertex Input Struct Vertex Output Struct Vertex Shader Fragment Shader } } Shader Graph
  • 24.
  • 25.
  • 26.
    PBR Master Node Works with all Render Pipelines  Good starting point for prototyping  Feature ready for many scenarios 26
  • 27.
    HD Lit MasterNode  Compatible only with HDRP  More features than PBR  Easy to add needless complexity 27
  • 28.
  • 29.
    Unlit Master Node Works with all Render Pipelines  Very lightweight  Good for effects, vertex modifications 29
  • 30.
    Unlit Master Node Possibleto add custom lighting: 1. Create nodes to calculate lighting from desired shading model (e.g., Blinn-Phong) 2. Connect output color to the Color port 30
  • 31.
    Master Node Review PBR is the most versatile node  Use HD Lit only when applicable and necessary  Consider Unlit for particle effects, UI, etc. 31
  • 32.
  • 33.
    Built-in Optimizations 1. Whereever possible, Shader Graph will not add unused features to output shader  Changing the default value will mark the feature active  Connecting any node will mark the feature active 2. The shader compiler will compile out no-op features 33
  • 34.
    Optimization Example: CoatMask 34 No CoatMask code will be present in the output ShaderLab code if the value is zero
  • 35.
    Optimization Example: Metallic 35 Ifthe Metallic is set to zero, that code block will be compiled out by the shader compiler
  • 36.
    Optimization Example: Emission 36 Ifthe Emission is set to Black, and disabled in Material, that code block will be compiled out by the shader compiler
  • 37.
    Built-in Optimizations 1. Whereever possible, Shader Graph will not add unused features to output shader  Changing the default value will mark the feature active  Connecting any node will mark the feature active 2. The shader compiler will compile out no-op features 37
  • 38.
    Draw Call Batching GPU instancing is supported in shaders  Needs to be enabled on the material  Requires hardware support  All generated shaders are compatible with the SRP Batcher (2018.3) 38
  • 39.
  • 40.
    SRP Batcher  Newbatching solution, designed for SRP  Improved rendering performance  Works with SkinnedMeshRenderers!  Requires per-material parameters to be stored in a constant buffer 40
  • 41.
    Render Faster withthe SRP Batcher 41 0 5 10 15 20 25 30 35 Scene: 1024 materials Scene: 1 material RenderTime(ms) 5.26x Faster 1.27x Faster SRP Legacy Lower is better
  • 42.
  • 43.
    Node Decimation  Eliminateno-op nodes  Bake values back into the textures  Examples: gradients, noise  Combine nodes when possible 43
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
    Data Formats  Eachnode has a memory cost  Use smaller data structures when possible  Modifying precision  Requires code modification 49
  • 50.
    50 public enum OutputPrecision { @fixed, @half, @float } privateOutputPrecision m_OutputPrecision = OutputPrecision.@float; Modifying Precision AbstractMaterialNode.cs
  • 51.
    Reduce Math Operations Multiply scalar values before vector values  Prefer blending results, instead of branching  Research impact of certain math operations  Prefer constants when possible 51
  • 52.
    Example: Reciprocal 52 Fast moderequires Shader Model 5
  • 53.
    Reduce Math Operations Multiply scalar values before vector values  Prefer blending results, instead of branching  Research impact of certain math operations  Prefer constants when possible 53
  • 54.
  • 55.
    Workflow: Manual Optimizations Hand-optimizing shaders is a one-way path  Don’t manually optimize too early  Copy or view shader code in Master Node menu 55
  • 56.
  • 57.
    Workflow: Faster Iterations Nodes not connected to Master Node aren’t evaluated  Can keep them in view for quick iterations  Create a Preview node that isn’t attached to the Master Node  Editing these nodes will be much faster 57
  • 58.
    Workflow Summary 1. Prototypewith PBR Master Node  Move to HD Lit if necessary 2. Start optimization 1. Optimize nodes 2. Convert properties to inline values 3. Near the end of the project, start hand optimizing shaders 58
  • 59.
  • 60.
    Custom API  Createyour own nodes  Examples: specialized noise functions, custom lighting, etc.  Full documentation available on GitHub 60
  • 61.
    Vertex Modification  Low-impacton CPU performance  Good for animating foliage, water, or cloth 61
  • 62.
  • 63.
  • 64.
  • 65.
    Roadmap 2019.1  First official,verified release  Completely overhauled Node API  Key bug fixes, UX improvements 65
  • 66.
    Available Resources  Plentifulsamples abound:  Andy Touch  Keijiro Takahashi  Video tutorials on YouTube  Source available on GitHub 66
  • 67.
  • 68.