0% found this document useful (0 votes)
134 views12 pages

Introduction To Replacement Shaders & Shader Keywords PDF

Uploaded by

gb288602
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
134 views12 pages

Introduction To Replacement Shaders & Shader Keywords PDF

Uploaded by

gb288602
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 12

10/13/2020 Introduction To Replacement Shaders & Shader Keywords

Bitshift Programmer : Game Development, VFX & C# Blog

Introduction To Replacement Shaders & Shader


Keywords
on December 22, 2018

What is a replacement shader?

A replacement shader is a shader that gets applied to every object


being rendered.
Since the camera determines what objects end up being shown on
screen, The functionality for setting up replacement shaders are in

the camera class as well.

A good use case of a replacement shader would be in making e ects


like SSAO.
Here we need access to the normals and the depth information so a
replacement shader that displays only the normals can be rendered (
stored in a render texture ) and then another shader that displays the
depth information ( stored in a render texture ) and then the nal
image is rendered with the SSAO e ect by taking the two render
textures as input and doing a bunch of calculations.

Another use case would be to visualize the environment di erently


for various reasons like how they did in City Skylines.

https://www.bitshiftprogrammer.com/2018/12/introduction-to-replacement-shaders-and-shader-keywords.html 1/12
10/13/2020 Introduction To Replacement Shaders & Shader Keywords

Bitshift Programmer : Game Development, VFX & C# Blog

The function that performs shader replacement is:


Camera.SetReplacementShader( Shader shader, string
replacementTag )

Takes in a shader as parameter which will be the shader applied


for replacing.
The replacementTag is sort of like a lter that applies the

replacement only on objects which have a sub-shader that has a

similar tag.
If you keep the replacementTag as "" (empty) then the shader

will be applied to all the objects in the scene. 

So that now we have an understanding of what a replacement shader


does we now have to look at what shader keywords are.

What is a shader keyword?

A shader keyword is used to enable or disable certain preprocessor

directives and thereby have multiple shader variants be generated.


Each shader variant is basically a di erent shader except it shares the

same properties and all the variations are de ned in one shader le.

Let's look at some code on to create, enable and disable shader


keywords.

First a sample shader.

https://www.bitshiftprogrammer.com/2018/12/introduction-to-replacement-shaders-and-shader-keywords.html 2/12
10/13/2020 Introduction To Replacement Shaders & Shader Keywords

Shader "BitshiftProgrammer/ExampleReplacement"
{ Programmer : Game Development, VFX & C# Blog
Bitshift
SubShader
{
Tags { "RenderType"="Opaque" }
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma shader_feature YELLOW_COL // Shader keyword
#pragma shader_feature RED_COL // Shader keyword
#include "UnityCG.cginc"

struct appdata
{
float4 vertex : POSITION;
};

struct v2f
{
float4 vertex : SV_POSITION;
};

v2f vert (appdata v)


{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
return o;
}

fixed4 frag (v2f i) : SV_Target


{
#if RED_COL
return fixed4(1,0,0,1); // Red if keyword enabled
#endif
#if YELLOW_COL
return fixed4(1,1,0,1); // Yellow if keyword enabled
#endif
return fixed4(1,1,1,1); // White if no keyword enabled
}
ENDCG
}
}
}

Shader keywords work just like conditional complation pre-processor

directives.

We have to explicitly say #pragma shader_feature


SHADER_KEYWORD other wise it won't work in that sub-shader.

If you are not familiar with pre-processor directives in C#, I would

suggest this : C# Fundamentals Pre-Processor Directives

The functions that are involved with shader replacement are:


https://www.bitshiftprogrammer.com/2018/12/introduction-to-replacement-shaders-and-shader-keywords.html 3/12
10/13/2020 Introduction To Replacement Shaders & Shader Keywords

Shader.EnableKeyword(string keyword)
Bitshift Programmer : Game Development, VFX & C# Blog
Global state set to 'enabled' for that keyword and any shader that uses

that keyword will be a ected.


Shader.DisableKeyword(string keyword)

Global state set to 'disabled' for that keyword and any shader that

uses that keyword will be a ected.

So inorder to output red color you would write:

Shader.EnableKeyword("RED_COL");

Then to show yellow you would write


Shader.EnableKeyWord("YELLOW_COL");

But you will still see red because the YELLOW_COL keyword was

not disabled.

So for that, we have to write


Shader.DisableKeyword("RED_COL");

Example of replacement shaders and shader


keywords in action

Replacement shaders are a really good debugging tool as well.


Here is an example of what I mean.

Example 1 : Render all objects in various ways. ( Using shader

keywords to get di erent outputs )

Here we are seeing:


Unlit shading, UVs, Local position, World position, Depth, Local-

space normal, World-space normal

https://www.bitshiftprogrammer.com/2018/12/introduction-to-replacement-shaders-and-shader-keywords.html 4/12
10/13/2020 Introduction To Replacement Shaders & Shader Keywords

Bitshift Programmer : Game Development, VFX & C# Blog

Example 2 : Render only objects that have a sub-shader with a


speci c replacement tag.

( Using shader keywords to get di erent outputs )

As you can see the ground  and the cubes are not rendered as the tag

was only found on the trees and house.

Now we will actually implement this with the help of 2 shaders and 1

C# script.

We need 2 shaders :

https://www.bitshiftprogrammer.com/2018/12/introduction-to-replacement-shaders-and-shader-keywords.html 5/12
10/13/2020 Introduction To Replacement Shaders & Shader Keywords

1)The shader that actually gets replaced when replacing with tag
Bitshift Programmer : Game Development, VFX & C# Blog
2)The shader that will be put in it's place

So now we will look at the shader which will be used to render by

default but then get replaced.

"BitshiftProgrammer/ShaderToBeReplacedWithTag"
{
Properties
{
_MainTex ("Base (RGB)", 2D) = "white" {}
}

SubShader
{
Cull off
Tags { "RenderType"="Opaque" "MyTag"="OnlyColors" } // Tagged with "MyTag"

CGPROGRAM
#pragma surface surf Lambert noforwardadd

sampler2D _MainTex;
struct Input
{
float2 uv_MainTex;
};

void surf (Input IN, inout SurfaceOutput o)


{
fixed4 c = tex2D(_MainTex, IN.uv_MainTex);
o.Albedo = c.rgb;
o.Alpha = c.a;
}
ENDCG
}
Fallback "Mobile/VertexLit"
}

So as you can see it's a simple lit surface shader but with an extra tag

called "MyTag".
Now the shader that will replace that one.

Shader "BitshiftProgrammer/Replacer"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
}

SubShader
{
Tags { "RenderType"="Opaque" }
https://www.bitshiftprogrammer.com/2018/12/introduction-to-replacement-shaders-and-shader-keywords.html 6/12
10/13/2020 Introduction To Replacement Shaders & Shader Keywords

Pass
Bitshift{ Programmer : Game Development, VFX & C# Blog
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma shader_feature UV_VIS
#pragma shader_feature LOCAL_POS_VIS
#pragma shader_feature WORLD_POS_VIS
#pragma shader_feature DEPTH_VIS
#pragma shader_feature LOCAL_NORMAL_VIS
#pragma shader_feature WORLD_NORMAL_VIS
#include "UnityCG.cginc"

struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
float3 normal : NORMAL;
};

struct v2f
{
float2 uv : TEXCOORD0;
float3 worldPos : TEXCOORD1;
float3 localPos : TEXCOORD2;
float depth : TEXCOORD3;
float3 normal : TEXCOORD4;
float4 vertex : SV_POSITION;
};

sampler2D _MainTex;
float4 _MainTex_ST;

v2f vert (appdata v)


{
v2f o;
o.localPos = v.vertex;
o.vertex = UnityObjectToClipPos(v.vertex);
o.worldPos = mul(unity_ObjectToWorld, v.vertex);
o.worldPos = normalize(o.worldPos);
o.depth = -mul(UNITY_MATRIX_MV, v.vertex).z * _ProjectionParams.w;
o.uv = v.uv;
o.normal = v.normal;
#if WORLD_NORMAL_VIS
o.normal = mul(unity_ObjectToWorld, o.normal);
#endif
return o;
}

fixed4 frag (v2f i) : SV_Target


{
#if UV_VIS
return fixed4(i.uv, 0, 1);
#endif
#if LOCAL_POS_VIS
return fixed4(i.localPos, 1.0);
#endif
#if WORLD_POS_VIS
return fixed4(i.worldPos, 1.0);
#endif
https://www.bitshiftprogrammer.com/2018/12/introduction-to-replacement-shaders-and-shader-keywords.html 7/12
10/13/2020 Introduction To Replacement Shaders & Shader Keywords

#if DEPTH_VIS
return i.depth;
Bitshift Programmer
#endif : Game Development, VFX & C# Blog
#if LOCAL_NORMAL_VIS || WORLD_NORMAL_VIS
return fixed4(normalize(i.normal) * 0.5 + 0.5,1.0);
#endif
return tex2D(_MainTex, i.uv); //If no shader feature is enabled
}
ENDCG
}
}
SubShader
{
Tags { "RenderType"="Opaque" "MyTag"="OnlyColors" } //Subshader with same tag

Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma shader_feature UV_VIS
#pragma shader_feature LOCAL_POS_VIS
#pragma shader_feature WORLD_POS_VIS
#pragma shader_feature DEPTH_VIS
#pragma shader_feature LOCAL_NORMAL_VIS
#pragma shader_feature WORLD_NORMAL_VIS
#include "UnityCG.cginc"

struct appdata
{
float4 vertex : POSITION;
};

struct v2f
{
float4 vertex : SV_POSITION;
};

v2f vert (appdata v)


{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
return o;
}

fixed4 frag () : SV_Target


{
#if UV_VIS
return fixed4(1,0,0,1);
#endif
#if LOCAL_POS_VIS
return fixed4(0,1,0,1);
#endif
#if WORLD_POS_VIS
return fixed4(0,0,1,1);
#endif
#if DEPTH_VIS
return fixed4(1,1,0,1);
#endif
#if LOCAL_NORMAL_VIS
return fixed4(1,0,1,1);
https://www.bitshiftprogrammer.com/2018/12/introduction-to-replacement-shaders-and-shader-keywords.html 8/12
10/13/2020 Introduction To Replacement Shaders & Shader Keywords
#endif
#if WORLD_NORMAL_VIS
Bitshift Programmer : Game Development, VFX & C# Blog
return fixed4(0,1,1,1);
#endif
return fixed4(1,1,1,1);
}
ENDCG
}
}
}

You can see the same shader keywords have been used in both
subshaders but di erent outputs have been described so that we know
what is happening.

Now the C# script that will allow us control how everything is being
rendered.

By looking at the C# script you will be able to understand exactly what


is happening.

using UnityEngine;
public class ReplacementShaderTest : MonoBehaviour
{
public Shader replaceShader;
private string[] KeyWords = new string[] { "UV_VIS", "LOCAL_POS_VIS", "WOR

private void Update()


{
if (Input.GetKeyDown(KeyCode.A))
GetComponent().SetReplacementShader(replaceShader, ""); // All obj
else if (Input.GetKeyDown(KeyCode.W))
GetComponent().SetReplacementShader(replaceShader, "MyTag"); // On
else if (Input.GetKeyDown(KeyCode.S))
GetComponent().ResetReplacementShader(); // Removes all applied re
else if (Input.GetKeyDown(KeyCode.Z))
EnableKeyWord(0);
else if (Input.GetKeyDown(KeyCode.Alpha1))
EnableKeyWord(1);
else if (Input.GetKeyDown(KeyCode.Alpha2))
EnableKeyWord(2);
else if (Input.GetKeyDown(KeyCode.Alpha3))
EnableKeyWord(3);
else if (Input.GetKeyDown(KeyCode.Alpha4))
EnableKeyWord(4);
else if (Input.GetKeyDown(KeyCode.Alpha5))
EnableKeyWord(5);
else if (Input.anyKeyDown)
EnableKeyWord(-1); // Goto default functionality of sub-shader ( b
}

private void EnableKeyWord(int index) // Only one shader keyword will be e


{
https://www.bitshiftprogrammer.com/2018/12/introduction-to-replacement-shaders-and-shader-keywords.html 9/12
10/13/2020 Introduction To Replacement Shaders & Shader Keywords
for (int i = 0; i < KeyWords.Length; i++)
{
Bitshift Programmer : Game
if (i Development, VFX & C# Blog
== index)
Shader.EnableKeyword(KeyWords[i]);
else
Shader.DisableKeyword(KeyWords[i]);
}
}
}

For the Unity package go: HERE


That's it! Hope you learned something. Support Bitshift Programmer

by leaving a like on
Bitshift Programmer Facebook Page and be updated as soon as there

is a new blog post.


If you have any questions that you might have about shaders or Unity
development, in general, don't be shy and leave a message on my

facebook page or down in the comments.


For the source code, go: HERE

For more Shader development tutorials, go: HERE


For Unity development tutorials, go: HERE
 

https://www.bitshiftprogrammer.com/2018/12/introduction-to-replacement-shaders-and-shader-keywords.html 10/12
10/13/2020 Introduction To Replacement Shaders & Shader Keywords

Copyright © Bitshift Programmer 2020. All rights reserved.


Bitshift Programmer : Game Development, VFX & C# Blog

https://www.bitshiftprogrammer.com/2018/12/introduction-to-replacement-shaders-and-shader-keywords.html 12/12
10/13/2020 Introduction To Replacement Shaders & Shader Keywords

Popular Posts
Bitshift Programmer : Game Development, VFX & C# Blog

Access Re ection Probe Data For Custom Shaders

The Unity shader documentation regarding re ection probes is pretty


minimal and not at all comprehensive.
This short tutorial is intended to bring re ection probe functionalities to
the forefront your future shader writing endevors which is a fancy way of…

Tri-Planar Terrain Shader

How The Tri-Planar Terrain Shader Looks Like Apart from the manually
drawn tile footpath the cli walls and grass has been generated through a
tri-planar shader. How The Tri-Planar Terrain Shader Works The shader
that we make will work with the existing terrain system and no need for …

Assets Worth Checking Out

Traversal
 Catsoft Stu...
★★★★★

Asset Store Buy $30

POLYGON

Powered by Blogger

https://www.bitshiftprogrammer.com/2018/12/introduction-to-replacement-shaders-and-shader-keywords.html 11/12

You might also like