top of page

TECHNICAL ART: Shader Fundamentals in Unity/Unreal

Writer: Pavel ZosimPavel Zosim

edit v.0.6

 Shader Fundamentals and Rendering Pipeline

Shaders are small programs (with a “.shader” extension in Unity, and .usf/.ush in Unreal) that determine how surfaces interact with light. They perform mathematical calculations and execute a set of instructions (commands) to compute the color of every pixel covering an object. In essence, a shader tells the GPU—whose thousands of small, efficient cores are optimized for parallel processing—how to render objects based on their intrinsic properties. In contrast, the CPU is built for sequential serial processing.


  • Unity: .shader files with HLSL/CG.

  • Unreal: Node-based Material Editor or HLSL via Custom Nodes (.usf files).


Shaders operate within various coordinate spaces—such as UV, world, and screen space—to accurately map textures and calculate lighting across objects.


  • Operates in UV, world, and screen spaces.

  • The output is Defines color, transparency, and lighting for each pixel/vertex.


 

The Rendering Pipeline

Regardless of the rendering pipeline, generating an image requires processing data through several stages:



Input Assembler → Vertex Shader → Tessellation → Geometry Shader → Rasterizer → Pixel Shader → Color Blending (Output Merger)


Each stage contributes to the final image:

  1. Input Assembler: Gathers vertex data.

  2. Vertex Shader: Processes vertex positions, normals, and texture coordinates.

  3. Tessellation & Geometry Shader: (Optional) Modify geometry dynamically.

  4. Rasterizer: Converts vector data into fragments (potential pixels).

  5. Pixel Shader (Fragment Shader): Computes the final color of each pixel.

  6. Color Blending: Combines pixel data for the final output.


Different rendering paths offer various trade-offs between quality and performance.

Rendering Path

Advantages

Use Cases

Forward Rendering

Broad compatibility, mobile-friendly

Default for most projects

Deferred Shading

Efficient handling of multiple dynamic lights

Complex 3D scenes

Legacy Deferred/Vertex Lit

Legacy optimizations, older project support

Backward compatibility

Unreal-Specific:

Mobile Path: Simplified Forward with ES3.1 fallbacks.

Nanite: Meshlet-based rendering (no traditional vertex shaders).


Example:


Unity uses forward rendering by default because it offers greater compatibility with various graphics cards and optimizes the lighting calculation process.
 

Lighting Interaction and Models

The final appearance of an image is strongly influenced by how light interacts with objects. This interaction depends on two main aspects


Lighting Characteristics: (e.g., light type—directional, point, or spot—intensity, and color)

Material Characteristics: (e.g., albedo (base color), metallicity, and smoothness/roughness)


These factors together define the lighting model used by the shader. Lighting calculations can be performed either per-vertex or per-fragment:


  1. Per-Vertex Lighting: Calculated in the vertex shader.

  2. Per-Fragment (Per-Pixel) Lighting: Calculated in the fragment shader.


Lighting Type

Precision

Performance

Per-Vertex

Low

High (mobile)

Per-Fragment (Pixel)

High

Moderate (desktop)

Per-Pixel Example:


Physically Based Rendering (PBR) a very simplified representation of a PBR shading model. It conveys the basic idea that the final color of a material is a combination:


// Unity (Diffuse + Specular):
Final Color = Albedo × (Diffuse + Specular) + Emission

// Unity (Metallic Workflow):
Final Color = Emission + (1 - Metallic) * Albedo * DiffuseTerm + SpecularTerm

// UE5 (Material Graph)  
BaseColor = Lerp(DielectricSpecular, Albedo, Metallic);
 

Shader File Types

Unity organizes shader-related files into several categories, each serving a specific purpose:

File Type

Unity

Unreal

Purpose

Text-Based Shaders

.shader (HLSL/CG)

.usf (Unreal Shader File) / .ush (Unreal Shader Header)

Core shader code with vertex/fragment logic.

Visual Shaders

.shadergraph (Shader Graph)

.uasset (Material/ Material Instance)

Node-based shader creation (no direct code editing).

Custom Functions

.hlsl (standalone HLSL files)

.ush / .usf (HLSL code in Plugins or Engine/Shaders)

Reusable HLSL functions for Shader Graph or C++ integration.

Include Files

.cginc (legacy CG includes) / .hlsl (modern HLSL)

.ush (shared headers, e.g., Common.ush, Definitions.ush)

Reusable code snippets (lighting models, math utilities).

 

Key Corrections & Explanations

1. Text-Based Shaders

  • Unity:

    • .shader files contain ShaderLab code with CGPROGRAM/HLSLPROGRAM blocks.



  • Unreal:

    • .usf files define full shaders (e.g., BasePassPixelShader.usf).

    • .ush files are headers for shared code (e.g., BRDF.ush).


 

2. Visual Shaders

  • Unity:

    • Shader Graph (.shadergraph) is limited to URP/HDRP.

    • Outputs HLSL code automatically.

  • Unreal:

    • Material Editor (.uasset) is the primary tool for 90% of shader work.

    • Node graphs compile to HLSL via the Material Template system.


 

3. Custom Functions

  • Unity:

    • .hlsl files are linked to Shader Graph via the Custom Function Node.

  • Unreal:

    • Custom HLSL is added via the Custom Expression node in the Material Editor.


 

4. Include Files

  • Unity:

    • .cginc (legacy CG) is used in Built-in RP (e.g., UnityCG.cginc).

    • .hlsl includes are standard in URP/HDRP.

  • Unreal:

    • .ush files (e.g., ShadingModels.ush) define shared lighting logic.

    • No equivalent to .cginc – Unreal uses HLSL exclusively.


 
  1. Associations


Unity
graph LR  
A[.shader] --> B[CGPROGRAM]
A --> C[HLSLPROGRAM]  
B --> D[.cginc]  
C --> E[.hlsl]  
F[.shadergraph] --> G[HLSLPROGRAM]

Unreal
graph LR
A[.usf] --> B[HLSL] \
C[.uasset] --> D[Material Template]
D --> E[.ush] 

Important Notes:


Unreal Does NOT Use:

CGPROGRAM blocks or Cg language.

.cginc files – replaced by .ush/.usf.


Unity to Unreal Translation:

Unity’s Surface Shader ≈ Unreal’s Material Domain (e.g., Surface, Deferred Decal).

Unity’s #pragma multi_compile ≈ Unreal’s Static Switches or Shader Permutations.


Pipeline Compatibility:

Unity: .shadergraph only works in URP/HDRP.

Unreal: Materials work across all pipelines (Forward, Deferred, Mobile).


 

Common Architectures

Unity defines several shader structures that simplify the creation process by automatically providing built-in operations:


  • Vertex + Fragment Shader: The traditional approach, where the vertex shader processes vertex data and the fragment shader computes the color for each pixel.

  • Surface Shader: Automatically handles lighting calculations based on a defined surface model, streamlining work with dynamic lighting.

  • Compute Shader: Used for advanced tasks and general-purpose computations on the GPU, extending beyond traditional rendering.

  • Additional Structures: Unity may include other specialized shader structures designed to streamline certain tasks.


Each of these structures has its own set of properties and functions that facilitate the compilation process, making it easier to define and organize your operations.

Structure

Unity

Unreal

Vertex-Fragment

Manual control over stages.

Custom HLSL via CustomExpression.

Surface Shader

#pragma surface surf Standard

DefaultLit material template.

Compute Shader

#pragma kernel CSMain

FRHIComputeShader (C++ integration).


Property Systems

Feature

Unity

Unreal

Toggle

[Toggle] attribute + #pragma.

Static Switch Parameter node.

Enum

[Enum(...)].

Enum Parameter node.

Slider

[Range(min,max)].

Scalar Parameter with min/max.

Unreal Example (Toggle):


Shader Variants

Feature

Unity

Unreal

Multi-Compile

#pragma multi_compile.

Static Permutation (C++-driven).

Keyword

#pragma shader_feature _KEY.

#define in .usf + C++ plumbing.

Unreal Optimization:

  • Fewer Variants: Unreal auto-strips unused permutations.

  • Material Layers: Reduces variant explosion.


 

Programming Languages for Shader Development in Unity

Shader development in Unity involves three main programming languages:


  • HLSL (High-Level Shader Language): The official shader language for Unity (from version 2019 onward) and the preferred language for writing shader code today.

  • Cg (C for Graphics): Developed by NVIDIA, this language compiles into shaders; however, it is considered outdated in current versions of Unity.

  • ShaderLab: A declarative language used by Unity to define the overall structure of a shader, including its properties, subshaders, passes, and fallback instructions.


When creating a shader, the actual shader code is placed inside a CGPROGRAM block (or, in future versions, an HLSLPROGRAM block).


 

Debugging Tools

Tool

Unity

Unreal

Frame Debugger

View per-draw call stages.

GPU Visualizer (full pipeline).

Shader Errors

Console with line numbers.

Material Editor real-time preview.

 

References:

 

Follow my work:

Comments


bottom of page