urp-hlsl-templates
GitHub提供适用于Unity URP的HLSL/ShaderLab生产级代码模板,支持SRP Batcher。涵盖核心规则(如使用HLSLPROGRAM、CBUFFER、URP宏)及Unlit示例,用于编写或转换自定义着色器。
Trigger Scenarios
Install
npx skills add NeverSight/learn-skills.dev --skill urp-hlsl-templates -g -y
SKILL.md
Frontmatter
{
"name": "urp-hlsl-templates",
"description": "Production-ready URP HLSL\/ShaderLab code templates with SRP Batcher compatibility for Unity"
}
URP HLSL Shader Code Templates
TRIGGER
Use this skill when the user wants to write a Unity shader in HLSL/ShaderLab code (not Shader Graph) for Universal Render Pipeline. Triggers include: "URP shader", "HLSL", "ShaderLab", "write a shader", "custom shader", "vertex fragment shader", "SRP Batcher", "CBUFFER", "custom lit shader", "unlit shader", or any code-based shader authoring in URP. Also trigger when converting Built-in pipeline shaders to URP, or when the user references Cyanilux templates, phi-lira gists, or NedMakesGames tutorials.
CORE RULES — URP HLSL
-
Always use
HLSLPROGRAM/ENDHLSL, neverCGPROGRAM/ENDCG. URP uses HLSL, not CG. CG blocks will compile but miss URP-specific includes and macros. -
All material properties must be in a
CBUFFER_START(UnityPerMaterial)/CBUFFER_ENDblock for SRP Batcher compatibility. Without this, each material breaks batching and gets its own draw call. -
Include URP Core, not legacy Unity includes.
// CORRECT (URP) #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl" // WRONG (Built-in / legacy) #include "UnityCG.cginc" #include "Lighting.cginc" -
Use URP transform macros, not legacy ones:
// URP // Legacy equivalent TransformObjectToHClip(posOS) // UnityObjectToClipPos(v.vertex) TransformObjectToWorld(posOS) // mul(unity_ObjectToWorld, v.vertex) TransformObjectToWorldNormal(nOS) // UnityObjectToWorldNormal(v.normal) TransformWorldToHClip(posWS) // mul(UNITY_MATRIX_VP, float4(posWS, 1)) GetVertexPositionInputs(posOS) // (convenience struct) GetVertexNormalInputs(nOS, tanOS) // (convenience struct) -
Tags must include
"RenderPipeline" = "UniversalPipeline"or the shader won't be recognized by URP. -
Use
TEXTURE2DandSAMPLERmacros instead ofsampler2D:TEXTURE2D(_MainTex); SAMPLER(sampler_MainTex); // Sample with: half4 col = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, uv);
TEMPLATE: URP UNLIT (MOBILE-READY)
Minimal unlit shader with SRP Batcher compatibility. Use as starting point for mobile shaders:
Shader "Custom/URP_Unlit_Mobile"
{
Properties
{
_BaseMap ("Base Map", 2D) = "white" {}
_BaseColor ("Base Color", Color) = (1, 1, 1, 1)
}
SubShader
{
Tags
{
"RenderType" = "Opaque"
"RenderPipeline" = "UniversalPipeline"
"Queue" = "Geometry"
}
Pass
{
Name "ForwardLit"
Tags { "LightMode" = "UniversalForward" }
HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_fog
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
// SRP Batcher compatible: all properties in CBUFFER
CBUFFER_START(UnityPerMaterial)
float4 _BaseMap_ST;
half4 _BaseColor;
CBUFFER_END
TEXTURE2D(_BaseMap);
SAMPLER(sampler_BaseMap);
struct Attributes
{
float4 positionOS : POSITION;
float2 uv : TEXCOORD0;
};
struct Varyings
{
float4 positionCS : SV_POSITION;
float2 uv : TEXCOORD0;
half fogFactor : TEXCOORD1;
};
Varyings vert(Attributes input)
{
Varyings output;
VertexPositionInputs posInputs = GetVertexPositionInputs(input.positionOS.xyz);
output.positionCS = posInputs.positionCS;
output.uv = TRANSFORM_TEX(input.uv, _BaseMap);
output.fogFactor = ComputeFogFactor(posInputs.positionCS.z);
return output;
}
half4 frag(Varyings input) : SV_Target
{
half4 color = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, input.uv) * _BaseColor;
color.rgb = MixFog(color.rgb, input.fogFactor);
return color;
}
ENDHLSL
}
// Shadow caster pass (required for objects to cast shadows)
Pass
{
Name "ShadowCaster"
Tags { "LightMode" = "ShadowCaster" }
ZWrite On ZTest LEqual ColorMask 0
HLSLPROGRAM
#pragma vertex ShadowPassVertex
#pragma fragment ShadowPassFragment
#include "Packages/com.unity.render-pipelines.universal/Shaders/ShadowCasterPass.hlsl"
ENDHLSL
}
// Depth pass (required for depth-based effects)
Pass
{
Name "DepthOnly"
Tags { "LightMode" = "DepthOnly" }
ZWrite On ColorMask R
HLSLPROGRAM
#pragma vertex DepthOnlyVertex
#pragma fragment DepthOnlyFragment
#include "Packages/com.unity.render-pipelines.universal/Shaders/DepthOnlyPass.hlsl"
ENDHLSL
}
}
Fallback "Universal Render Pipeline/Unlit"
}
TEMPLATE: URP LIT WITH MAIN LIGHT
Adds Lambert diffuse lighting from the main directional light:
Shader "Custom/URP_SimpleLit_Mobile"
{
Properties
{
_BaseMap ("Base Map", 2D) = "white" {}
_BaseColor ("Base Color", Color) = (1, 1, 1, 1)
}
SubShader
{
Tags
{
"RenderType" = "Opaque"
"RenderPipeline" = "UniversalPipeline"
"Queue" = "Geometry"
}
Pass
{
Name "ForwardLit"
Tags { "LightMode" = "UniversalForward" }
HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile _ _MAIN_LIGHT_SHADOWS _MAIN_LIGHT_SHADOWS_CASCADE
#pragma multi_compile _ _SHADOWS_SOFT
#pragma multi_compile_fog
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
CBUFFER_START(UnityPerMaterial)
float4 _BaseMap_ST;
half4 _BaseColor;
CBUFFER_END
TEXTURE2D(_BaseMap);
SAMPLER(sampler_BaseMap);
struct Attributes
{
float4 positionOS : POSITION;
float3 normalOS : NORMAL;
float2 uv : TEXCOORD0;
};
struct Varyings
{
float4 positionCS : SV_POSITION;
float2 uv : TEXCOORD0;
float3 normalWS : TEXCOORD1;
float3 positionWS : TEXCOORD2;
half fogFactor : TEXCOORD3;
};
Varyings vert(Attributes input)
{
Varyings output;
VertexPositionInputs posInputs = GetVertexPositionInputs(input.positionOS.xyz);
VertexNormalInputs normInputs = GetVertexNormalInputs(input.normalOS);
output.positionCS = posInputs.positionCS;
output.positionWS = posInputs.positionWS;
output.normalWS = normInputs.normalWS;
output.uv = TRANSFORM_TEX(input.uv, _BaseMap);
output.fogFactor = ComputeFogFactor(posInputs.positionCS.z);
return output;
}
half4 frag(Varyings input) : SV_Target
{
half4 baseColor = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, input.uv) * _BaseColor;
// Main light (directional)
float4 shadowCoord = TransformWorldToShadowCoord(input.positionWS);
Light mainLight = GetMainLight(shadowCoord);
half3 normal = normalize(input.normalWS);
half NdotL = saturate(dot(normal, mainLight.direction));
half3 diffuse = baseColor.rgb * mainLight.color * NdotL * mainLight.shadowAttenuation;
// Ambient
half3 ambient = SampleSH(normal) * baseColor.rgb;
half3 finalColor = diffuse + ambient;
finalColor = MixFog(finalColor, input.fogFactor);
return half4(finalColor, baseColor.a);
}
ENDHLSL
}
// Include ShadowCaster and DepthOnly passes (same as unlit template above)
UsePass "Custom/URP_Unlit_Mobile/ShadowCaster"
UsePass "Custom/URP_Unlit_Mobile/DepthOnly"
}
Fallback "Universal Render Pipeline/Simple Lit"
}
BUILT-IN → URP CONVERSION CHEAT SHEET
| Built-in | URP Equivalent |
|---|---|
#include "UnityCG.cginc" |
#include ".../Core.hlsl" |
#include "Lighting.cginc" |
#include ".../Lighting.hlsl" |
UnityObjectToClipPos(v) |
TransformObjectToHClip(v.xyz) |
UnityObjectToWorldNormal(n) |
TransformObjectToWorldNormal(n) |
_WorldSpaceLightPos0 |
GetMainLight().direction |
_LightColor0 |
GetMainLight().color |
UNITY_LIGHTMODEL_AMBIENT |
SampleSH(normal) |
SHADOW_COORDS / TRANSFER_SHADOW |
TransformWorldToShadowCoord(posWS) |
SHADOW_ATTENUATION(i) |
GetMainLight(shadowCoord).shadowAttenuation |
tex2D(_Tex, uv) |
SAMPLE_TEXTURE2D(_Tex, sampler_Tex, uv) |
sampler2D _Tex |
TEXTURE2D(_Tex); SAMPLER(sampler_Tex); |
UNITY_FOG_COORDS / APPLY_FOG |
ComputeFogFactor() / MixFog() |
v2f struct convention |
Varyings struct convention |
appdata struct convention |
Attributes struct convention |
Tags { "LightMode" = "ForwardBase" } |
Tags { "LightMode" = "UniversalForward" } |
Surface shader #pragma surface |
No equivalent — write vertex/fragment manually |
MULTI-PASS AND ADDITIONAL PASSES
URP requires explicit pass names for the renderer to recognize them:
| LightMode Tag | Purpose |
|---|---|
UniversalForward |
Main rendering pass |
ShadowCaster |
Shadow map generation |
DepthOnly |
Depth prepass |
DepthNormals |
Depth + normals prepass (for SSAO, depth-normals effects) |
Meta |
Lightmap baking |
Universal2D |
2D renderer pass |
SRPDefaultUnlit |
Fallback when no LightMode matches |
COMMON PITFALLS
-
Forgetting CBUFFER → Breaks SRP Batcher. Every draw call becomes unique. Check with Frame Debugger > SRP Batcher column.
-
Using
sampler2Dinstead ofTEXTURE2Dmacro → Works but loses cross-platform sampler control and may break on some platforms. -
Missing ShadowCaster pass → Object won't cast shadows. Always include it or use
UsePass/Fallback. -
Missing DepthOnly pass → Depth-based effects (fog, post-processing, water depth) won't see this object.
-
Using
multi_compileinstead ofshader_feature→multi_compilecompiles ALL keyword variants.shader_featureonly compiles variants used by materials in the build. For material-specific toggles, always useshader_feature.
REFERENCE REPOS AND GISTS
- Cyanilux URP Code Templates (CC0) — https://github.com/Cyanilux/URP_ShaderCodeTemplates
- Cyanilux URP Shader Code Tutorial — https://www.cyanilux.com/tutorials/urp-shader-code/
- phi-lira URP Lit Template — https://gist.github.com/phi-lira/225cd7c5e8545be602dca4eb5ed111ba
- NedMakesGames 9-Part URP HLSL Series — https://nedmakesgames.medium.com/
- Halftone Toon URP Gist — https://gist.github.com/wonkee-kim/3b5c1821975b8414f420f93ef6cdf5a0
- Wide Outlines URP Gist — https://gist.github.com/ScottJDaley/6cddf0c8995ed61cac7088e22c983de1
- Toon Shader URP 11 Gist — https://gist.github.com/FaultyPine/08306e52971d77081ea159128cb3e5b5
- URP Custom Lit BlinnPhong — https://gist.github.com/xCyborg/2923ce9e57e65af9d417706dda4db4be
- ColinLeung-NiloCat URP Toon Lit — https://github.com/ColinLeung-NiloCat/UnityURPToonLitShaderExample
SOURCES
- Cyanilux: URP Shader Code Templates — https://github.com/Cyanilux/URP_ShaderCodeTemplates
- NedMakesGames: Writing URP Shaders with Code — https://nedmakesgames.medium.com/
- Catlike Coding: Custom SRP — https://catlikecoding.com/unity/tutorials/
- Daniel Ilett: Shader Graph + HLSL — https://danielilett.com/
- ColinLeung-NiloCat: Mobile URP Toon — https://github.com/ColinLeung-NiloCat/UnityURPToonLitShaderExample
- Unity: Shader Performance — https://docs.unity3d.com/Manual/SL-ShaderPerformance.html
Version History
- e0220ca Current 2026-07-05 23:20


