Urp hlsl templates
Skill adevra/unity-shader-agent-skills/skills/urp-hlsl-templates
Curated agent skills for Unity shader development targeting mobile GPUs and WebGL browsers.
npx -y skills add adevra/unity-shader-agent-skills --skill urp-hlsl-templatesAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 8 stars8 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Production-ready URP HLSL/ShaderLab code templates with SRP Batcher compatibility for Unity
SKILL.md
12.9 KB, as published. Nobody here has run it
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