Shader Development¶
Choosing a Shader Workflow¶
Shader Graph (Primary - URP/HDRP)¶
Node-based visual editor. Use for the majority of shader work: - Material effects (dissolve, outline, hologram, water) - Artist-facing shaders that need visual tweaking - Rapid prototyping and iteration - Custom Function nodes for injecting HLSL where needed
ShaderLab + HLSL (Code-based)¶
Use for performance-critical shaders, custom render passes, and advanced techniques that Shader Graph cannot express: - Custom Render Graph passes - Compute shaders - Procedural geometry shaders - Full control over shader variants and keywords
Surface Shaders (Legacy - Built-in only)¶
Surface shaders (#pragma surface) are a Built-in Render Pipeline feature. Since BiRP is deprecated in Unity 6.5, surface shaders should not be used for new projects. They do not work with URP or HDRP.
HLSL Shader Structure for URP¶
All modern Unity shaders use HLSLPROGRAM blocks. The legacy CGPROGRAM is deprecated for scriptable render pipelines.
Shader "Custom/BasicUnlit"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_Color ("Color", Color) = (1, 1, 1, 1)
}
SubShader
{
Tags
{
"RenderType" = "Opaque"
"RenderPipeline" = "UniversalPipeline"
"Queue" = "Geometry"
}
Pass
{
HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
struct Attributes
{
float4 positionOS : POSITION;
float2 uv : TEXCOORD0;
};
struct Varyings
{
float4 positionCS : SV_POSITION;
float2 uv : TEXCOORD0;
};
TEXTURE2D(_MainTex);
SAMPLER(sampler_MainTex);
CBUFFER_START(UnityPerMaterial)
float4 _MainTex_ST;
half4 _Color;
CBUFFER_END
Varyings vert(Attributes input)
{
Varyings output;
output.positionCS = TransformObjectToHClip(input.positionOS.xyz);
output.uv = TRANSFORM_TEX(input.uv, _MainTex);
return output;
}
half4 frag(Varyings input) : SV_Target
{
half4 texColor = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, input.uv);
return texColor * _Color;
}
ENDHLSL
}
}
Fallback "Universal Render Pipeline/Unlit"
}
Key Shader Conventions¶
SRP Batcher Compatibility¶
Wrap per-material properties in a CBUFFER to enable SRP Batcher:
CBUFFER_START(UnityPerMaterial)
float4 _MainTex_ST;
half4 _Color;
half _Metallic;
half _Smoothness;
CBUFFER_END
Property Naming¶
All shader properties use underscore prefix: _MainTex, _Color, _Metallic, _Smoothness, _BumpMap.
Shader Keywords and Variants¶
Use shader_feature for keywords that are set per material, multi_compile for global keywords:
Minimize variants to reduce build time and memory. Use shader_feature_local over shader_feature when the keyword is material-specific.
Precision¶
Use half precision where full float is unnecessary, especially on mobile:
half4 color; // 16-bit, sufficient for colors
float3 position; // 32-bit, needed for positions
half3 normal; // 16-bit, usually sufficient for normals
Shader Graph Patterns¶
Custom Function Node¶
Inject HLSL into Shader Graph:
- Create an .hlsl file with your function
- Add a Custom Function node, select "File" mode, point to the file
- Define inputs and outputs to match function parameters
// CustomFunctions.hlsl
#ifndef CUSTOM_FUNCTIONS_INCLUDED
#define CUSTOM_FUNCTIONS_INCLUDED
void Dissolve_float(float alpha, float threshold, float edge, out float result)
{
result = smoothstep(threshold, threshold + edge, alpha);
}
#endif
Common Effects¶
- Dissolve: Noise texture + clip/alpha threshold
- Outline: Vertex extrusion + inverted normals pass or post-process edge detection
- Hologram: Fresnel + scanline + vertex displacement
- Water: Sine-based vertex displacement + normal map scrolling + depth-based transparency
- Toon/Cel: Step function on NdotL for discrete shading bands
Render Graph Custom Passes¶
For advanced rendering effects in Unity 6, use Render Graph compatible passes instead of extra cameras:
public class CustomRenderPass : ScriptableRenderPass
{
public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData)
{
// Record rendering commands using the Render Graph API
}
}
Extra cameras are now considered a legacy performance anti-pattern. Use Render Graph passes for custom rendering effects.
GPU Instancing¶
Enable instancing for shaders that will be used on many identical objects: