ShaderLab: Anatomy of a Shader
Tutorial
·
Beginner
·
+10XP
·
20 mins
·
(195)
Unity Technologies

In this tutorial, you will learn the Anatomy of a High-Level Shading Language (HLSL) Shader.
Languages available:
1. Anatomy of a Shader
Verified with Unity 2019.4 LTS
When writing Shaders, it’s crucial to understand the parts that compose their functionality. In this tutorial, we will be creating the “Hello World” of Shaders: an unlit Shader with a color input. By the end of this tutorial, we will be able to use this Shader to apply an RGB color to an object.
Any Shader can be broken down into the following blocks (Figure 01):
- Properties: These are similar to the user-defined global (or uniform, per OpenGL) variables that will be used to drive the functions within the Shader.
- SubShader: This block is similar to a Main() function, it is where the Shader’s logic and operations are performed. It usually consists of multiple functions.
- Fallback: In the event that a Shader can not run on the target system, this path directs Unity to an alternative (often less complex) Shader instead.

Figure 01: An unlit Shader consists of several parts, or blocks.
The string that follows the Shader keyword is the path of the Shader.
We can access this Shader by creating a Material, then assigning the Shader to it by navigating to Custom > NewUnlitShader in the Shader drop-down.
Let’s demonstrate this now:
1. Right-click in the Project window and navigate to Create > Material (Figure 02).

Figure 02: Creating a new Material. Shaders must be linked to a Material before they can be applied to objects.
2. Select the Material and in the Inspector window, navigate to Shader > Custom > NewUnlitShader (Figure 03).

Figure 03: Assigning the Shader to our new Material, and a look at its properties in the Inspector
3. To visualize our changes, create a new GameObject (an ordinary Cube will do) and orient it within your Scene. Then apply the new Material to it (Figure 04).

Figure 04: A cube with our new Material attached
Unlit Shaders do not take lighting into account, hence the flat appearance of our cube. Usually, Unlit Shaders are reserved for UI elements or highly artistically driven objects that do not rely on mathematical shading models to compute lighting.
We must explicitly define properties in our Shader so they can be modified in the Inspector.
To add a user-defined property to our property block, we must follow the following syntax (Figure 05).

Figure 05: Property syntax
The property we want to add will be responsible for defining the Shader’s primary color (or tint if it’s used to influence other Shader properties, such as Textures).
4. Next we will add a color value to our property block (Figure 06).

Figure 06: Adding a user defined property to the property block to give the Shader a tint.
If we save the Shader and return to the Material in the Inspector, you will notice that the tint color property has appeared (Figure 07).

Figure 07: Our new property as it appears in the Inspector
Currently, it doesn’t do anything as we haven't told the Shader how to use it. We will address this now:
5. Above the SubShader block, create a variable for the _Tint property we declared earlier (Figure 08).

Figure 08: Creating a variable for the _Tint property
6. Navigate into the SubShader block then to the fixed4 frag function. The frag function is responsible for calculating the final color output of our Shader (Figure 09).

Figure 09: A look at the frag function within the SubShader
We want to pay attention to the fixed4 col variable. This variable defines how the color will be calculated and is returned at the end of the function to display the results to the screen.
Currently, the variable stores the color and UV information of a Texture. The return call then displays this Texture on the surface. When a Texture is not defined in the Inspector, it will default to the color white. We want to have our tint color property influence the color of the Texture as well.
7. Multiply the value in the col variable by _Tint (Figure 10).

Figure 10: By multiplying the Texture by our _Tint property, we are telling the Shader to combine the two properties.
After modifying the tint color and Texture in the Inspector, we can view the results on our cube in the Scene view (Figure 11).

Figure 11: Left: Material with only a modification to the tint property. Right: Material with a modification to both the Texture and tint properties.
2. Conclusion
Shaders can help you create various looks for the surfaces in your project. We’ve taken a very simple look at the process in this tutorial. For a more in-depth look on how Shaders in Unity are written, please refer to the documentation on Writing Shaders.