Bird
Raised Fist0
Unityframework~10 mins

Custom shader fundamentals in Unity - Step-by-Step Execution

Choose your learning style10 modes available
Concept Flow - Custom shader fundamentals
Start Shader
↓
Define Properties
↓
Write SubShader
↓
Set Pass
↓
Write Vertex Shader
↓
Write Fragment Shader
↓
Compile & Apply
↓
Render Object with Shader
This flow shows the steps to create a custom shader: define properties, write subshader with vertex and fragment shaders, compile, and apply to render.
Execution Sample
Unity
Shader "Custom/SimpleColor" {
  Properties {
    _Color ("Color", Color) = (1,0,0,1)
  }
  SubShader {
    Pass {
      CGPROGRAM
      #pragma vertex vert
      #pragma fragment frag
      fixed4 _Color;
      struct appdata { float4 vertex : POSITION; };
      struct v2f { float4 pos : SV_POSITION; };
      v2f vert(appdata v) { v2f o; o.pos = UnityObjectToClipPos(v.vertex); return o; }
      fixed4 frag(v2f i) : SV_Target { return _Color; }
      ENDCG
    }
  }
}
This shader colors an object with a solid color defined by _Color property.
Execution Table
StepActionCode PartResult/State
1Start shader definitionShader "Custom/SimpleColor" {Shader named Custom/SimpleColor created
2Define color propertyProperties { _Color ("Color", Color) = (1,0,0,1) }_Color set to red (1,0,0,1)
3Begin SubShaderSubShader {SubShader block started
4Begin PassPass {Pass block started
5Start CGPROGRAMCGPROGRAMBegin shader program
6Set vertex and fragment shaders#pragma vertex vert #pragma fragment fragVertex shader 'vert' and fragment shader 'frag' set
7Declare _Color variablefixed4 _Color;_Color variable available in shader
8Define input structstruct appdata { float4 vertex : POSITION; };Input vertex data defined
9Define output structstruct v2f { float4 pos : SV_POSITION; };Output data for vertex shader defined
10Vertex shader codev2f vert(appdata v) { v2f o; o.pos = UnityObjectToClipPos(v.vertex); return o; }Vertex positions transformed to clip space
11Fragment shader codefixed4 frag(v2f i) : SV_Target { return _Color; }Fragment outputs solid color _Color
12End CGPROGRAMENDCGShader program ended
13End Pass}Pass block ended
14End SubShader}SubShader block ended
15End Shader}Shader definition complete
16Apply shader to objectMaterial.shader = Custom/SimpleColor;Object rendered with solid red color
💡 Shader compiled and applied; rendering uses _Color property for solid color output.
Variable Tracker
VariableStartAfter Step 2After Step 7After Step 11Final
_Colorundefined(1,0,0,1) red(1,0,0,1) red(1,0,0,1) red(1,0,0,1) red
vertexundefinedundefinedinput vertex positiontransformed clip positiontransformed clip position
posundefinedundefinedundefinedclip space positionclip space position
Key Moments - 3 Insights
Why do we define _Color in Properties and also declare it in the shader code?
Properties define what the user can change in the editor (step 2), while declaring _Color in code (step 7) makes it available inside the shader program.
What does UnityObjectToClipPos do in the vertex shader?
It transforms the object's vertex position from model space to clip space for rendering (step 10), which is necessary for the GPU to place the vertex on screen.
Why does the fragment shader just return _Color?
Because this shader colors every pixel with the same solid color defined by _Color (step 11), no lighting or texture is applied.
Visual Quiz - 3 Questions
Test your understanding
Look at the execution table at step 2. What is the initial value of _Color?
A(1,0,0,1) red
B(0,0,0,1) black
C(1,1,1,1) white
Dundefined
💡 Hint
Check the 'Result/State' column at step 2 in the execution_table.
At which step does the vertex position get transformed to clip space?
AStep 7
BStep 10
CStep 11
DStep 15
💡 Hint
Look for the vertex shader code action in the execution_table.
If you change _Color in Properties to blue (0,0,1,1), what changes in variable_tracker?
Avertex values change to blue
B_Color remains (1,0,0,1) because code is fixed
C_Color values change to (0,0,1,1) after step 2 and remain same
Dpos values change to blue
💡 Hint
Properties set initial _Color value; see variable_tracker _Color row.
Concept Snapshot
Custom Shader Basics in Unity:
- Define Properties for user inputs
- Write SubShader with Pass
- Use CGPROGRAM for vertex and fragment shaders
- Vertex shader transforms vertices
- Fragment shader sets pixel color
- Compile and apply to objects
Full Transcript
This visual execution shows how to create a simple custom shader in Unity. We start by defining a shader and its color property. Then we write a SubShader with a Pass that includes vertex and fragment shaders in CGPROGRAM. The vertex shader transforms object vertices to clip space for rendering. The fragment shader outputs a solid color from the _Color property. We track how _Color and vertex positions change step-by-step. Key points include the difference between Properties and shader variables, the role of UnityObjectToClipPos, and how the fragment shader colors pixels. The shader compiles and applies to render objects with the chosen color.

Practice

(1/5)
1. What is the main purpose of a custom shader in Unity?
easy
A. To control exactly how objects look by writing small programs
B. To create 3D models from scratch
C. To write game logic and rules
D. To manage user input events

Solution

  1. Step 1: Understand the role of shaders

    Shaders define how surfaces appear by controlling colors, lighting, and textures.
  2. Step 2: Identify what custom shaders do

    Custom shaders let you write small programs to control object appearance beyond built-in options.
  3. Final Answer:

    To control exactly how objects look by writing small programs -> Option A
  4. Quick Check:

    Custom shader = control object look [OK]
Hint: Shaders control object appearance with code [OK]
Common Mistakes:
  • Confusing shaders with 3D modeling
  • Thinking shaders handle game logic
  • Assuming shaders manage input
2. Which of the following is the correct way to start a simple Unity shader code block?
easy
A. ShaderBegin
B. StartShader
C. CGPROGRAM
D. ProgramCG

Solution

  1. Step 1: Recall Unity shader syntax

    Unity shaders use CGPROGRAM to start the programmable shader code block.
  2. Step 2: Check options for correct keyword

    Only CGPROGRAM is the valid keyword to begin the shader code section.
  3. Final Answer:

    CGPROGRAM -> Option C
  4. Quick Check:

    Shader code block starts with CGPROGRAM [OK]
Hint: Look for CGPROGRAM to start shader code [OK]
Common Mistakes:
  • Using made-up keywords like StartShader
  • Confusing CGPROGRAM with other terms
  • Misspelling the keyword
3. What will be the output color of this simple shader fragment code?
fixed4 frag() : SV_Target {
    return fixed4(1, 0, 0, 1);
}
medium
A. Solid red color
B. Solid green color
C. Solid blue color
D. Transparent black color

Solution

  1. Step 1: Analyze the returned color vector

    The function returns fixed4(1, 0, 0, 1), which means red=1, green=0, blue=0, alpha=1.
  2. Step 2: Interpret color components

    Red is full intensity, green and blue are zero, alpha is fully opaque.
  3. Final Answer:

    Solid red color -> Option A
  4. Quick Check:

    fixed4(1,0,0,1) = red [OK]
Hint: RGBA (1,0,0,1) means solid red [OK]
Common Mistakes:
  • Mixing up color channel order
  • Ignoring alpha channel
  • Assuming zero means white
4. Identify the error in this shader snippet:
Shader "Custom/Simple" {
    Properties {
        _Color ("Color", Color) = (1,1,1,1)
    }
    SubShader {
        Pass {
            CGPROGRAM
            fixed4 frag() : SV_Target {
                return _Color;
            }
            ENDCG
        }
    }
}
medium
A. Missing semicolon after _Color property declaration
B. _Color cannot be used directly in fragment shader
C. frag function missing input parameters
D. Incorrect use of ENDCG keyword

Solution

  1. Step 1: Check Properties block syntax

    The property declaration is correct: no semicolon needed, parentheses balanced.
  2. Step 2: Verify shader code block

    Properties like _Color must be declared inside CGPROGRAM as 'uniform fixed4 _Color;' to be used; direct use causes undeclared identifier error.
  3. Final Answer:

    _Color cannot be used directly in fragment shader -> Option B
  4. Quick Check:

    Properties need uniform declaration [OK]
Hint: Declare Properties as uniforms in CGPROGRAM [OK]
Common Mistakes:
  • Assuming semicolons are needed in Properties
  • Not declaring uniform for _Color
  • Thinking ENDCG is incorrect
5. You want to write a custom shader that colors an object red only if its x-coordinate is positive, otherwise blue. Which fragment shader code correctly implements this?
hard
A. fixed4 frag() : SV_Target { if (POSITION.x > 0) return fixed4(1,0,0,1); else return fixed4(0,0,1,1); }
B. fixed4 frag(float3 pos) : SV_Target { if (pos.x > 0) return fixed4(1,0,0,1); else return fixed4(0,0,1,1); }
C. fixed4 frag(float3 pos : TEXCOORD0) : SV_Target { return pos.x > 0 ? fixed4(1,0,0,1) : fixed4(0,0,1,1); }
D. fixed4 frag(float3 pos : POSITION) : SV_Target { return pos.x > 0 ? fixed4(1,0,0,1) : fixed4(0,0,1,1); }

Solution

  1. Step 1: Understand input semantics

    To access vertex position in fragment shader, use input parameter with semantic POSITION.
  2. Step 2: Check code correctness

    fixed4 frag(float3 pos : POSITION) : SV_Target { return pos.x > 0 ? fixed4(1,0,0,1) : fixed4(0,0,1,1); } correctly declares pos with POSITION semantic and uses conditional operator to return red or blue.
  3. Step 3: Identify errors in other options

    fixed4 frag(float3 pos) : SV_Target { if (pos.x > 0) return fixed4(1,0,0,1); else return fixed4(0,0,1,1); } lacks semantic, fixed4 frag(float3 pos : TEXCOORD0) : SV_Target { return pos.x > 0 ? fixed4(1,0,0,1) : fixed4(0,0,1,1); } uses TEXCOORD0 which is wrong for position, fixed4 frag() : SV_Target { if (POSITION.x > 0) return fixed4(1,0,0,1); else return fixed4(0,0,1,1); } uses POSITION as variable incorrectly.
  4. Final Answer:

    fixed4 frag(float3 pos : POSITION) : SV_Target { return pos.x > 0 ? fixed4(1,0,0,1) : fixed4(0,0,1,1); } -> Option D
  5. Quick Check:

    Use POSITION semantic for position input [OK]
Hint: Use POSITION semantic to get vertex position [OK]
Common Mistakes:
  • Missing POSITION semantic in input
  • Using wrong semantic like TEXCOORD0
  • Referencing POSITION as variable directly
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard