// Example Shader for Universal RP // Written by @Cyanilux // https://www.cyanilux.com/tutorials/urp-shader-code /* This example reacts to Main Directional Light & Ambient/Baked light. Ignores additional lights. Diffuse/Lambert shading model. No specular/smoothness/metallic/etc. */ Shader "Cyanilux/URPTemplates/DiffuseLitShaderExample" { Properties { _BaseMap ("Example Texture", 2D) = "white" {} _BaseColor ("Example Colour", Color) = (0, 0.66, 0.73, 1) [Toggle(_ALPHATEST_ON)] _AlphaTestToggle ("Alpha Clipping", Float) = 0 _Cutoff ("Alpha Cutoff", Float) = 0.5 } SubShader { Tags { "RenderPipeline"="UniversalPipeline" "RenderType"="Opaque" "Queue"="Geometry" } HLSLINCLUDE #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" CBUFFER_START(UnityPerMaterial) float4 _BaseMap_ST; float4 _BaseColor; float _Cutoff; CBUFFER_END ENDHLSL Pass { Name "ForwardLit" Tags { "LightMode"="UniversalForward" } HLSLPROGRAM #pragma vertex LitPassVertex #pragma fragment LitPassFragment // Material Keywords #pragma shader_feature_local _NORMALMAP #pragma shader_feature_local_fragment _ALPHATEST_ON #pragma shader_feature_local_fragment _ALPHAPREMULTIPLY_ON #pragma shader_feature_local_fragment _EMISSION #pragma shader_feature_local_fragment _METALLICSPECGLOSSMAP #pragma shader_feature_local_fragment _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A #pragma shader_feature_local_fragment _OCCLUSIONMAP #pragma shader_feature_local_fragment _SPECULARHIGHLIGHTS_OFF #pragma shader_feature_local_fragment _ENVIRONMENTREFLECTIONS_OFF #pragma shader_feature_local_fragment _SPECULAR_SETUP #pragma shader_feature_local _RECEIVE_SHADOWS_OFF // URP Keywords #pragma multi_compile _ _MAIN_LIGHT_SHADOWS #pragma multi_compile _ _MAIN_LIGHT_SHADOWS_CASCADE // Note, v11 changes this to : // #pragma multi_compile _ _MAIN_LIGHT_SHADOWS _MAIN_LIGHT_SHADOWS_CASCADE _MAIN_LIGHT_SHADOWS_SCREEN #pragma multi_compile _ _SHADOWS_SOFT #pragma multi_compile _ _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS #pragma multi_compile_fragment _ _ADDITIONAL_LIGHT_SHADOWS #pragma multi_compile _ LIGHTMAP_SHADOW_MIXING // v10+ only, renamed from "_MIXED_LIGHTING_SUBTRACTIVE" #pragma multi_compile _ SHADOWS_SHADOWMASK // v10+ only // Unity Keywords #pragma multi_compile _ LIGHTMAP_ON #pragma multi_compile _ DIRLIGHTMAP_COMBINED #pragma multi_compile_fog // GPU Instancing (not supported) //#pragma multi_compile_instancing // Includes #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl" // Structs struct Attributes { float4 positionOS : POSITION; float4 normalOS : NORMAL; float2 uv : TEXCOORD0; float2 lightmapUV : TEXCOORD1; float4 color : COLOR; }; struct Varyings { float4 positionCS : SV_POSITION; float2 uv : TEXCOORD0; DECLARE_LIGHTMAP_OR_SH(lightmapUV, vertexSH, 1); float3 normalWS : TEXCOORD2; float3 positionWS : TEXCOORD3; float4 color : COLOR; }; // Textures, Samplers & Global Properties TEXTURE2D(_BaseMap); SAMPLER(sampler_BaseMap); // Vertex Shader Varyings LitPassVertex(Attributes IN) { Varyings OUT; VertexPositionInputs positionInputs = GetVertexPositionInputs(IN.positionOS.xyz); OUT.positionCS = positionInputs.positionCS; OUT.positionWS = positionInputs.positionWS; VertexNormalInputs normalInputs = GetVertexNormalInputs(IN.normalOS.xyz); OUT.normalWS = normalInputs.normalWS; OUTPUT_LIGHTMAP_UV(IN.lightmapUV, unity_LightmapST, OUT.lightmapUV); OUTPUT_SH(OUT.normalWS.xyz, OUT.vertexSH); OUT.uv = TRANSFORM_TEX(IN.uv, _BaseMap); OUT.color = IN.color; return OUT; } // Fragment Shader half4 LitPassFragment(Varyings IN) : SV_Target { half4 baseMap = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, IN.uv); #ifdef _ALPHATEST_ON // Alpha Clipping clip(baseMap.a - _Cutoff); #endif // Get Baked GI half3 bakedGI = SAMPLE_GI(IN.lightmapUV, IN.vertexSH, IN.normalWS); // Main Light & Shadows float4 shadowCoord = TransformWorldToShadowCoord(IN.positionWS.xyz); Light mainLight = GetMainLight(shadowCoord); half3 attenuatedLightColor = mainLight.color * (mainLight.distanceAttenuation * mainLight.shadowAttenuation); // Mix Realtime & Baked (if LIGHTMAP_SHADOW_MIXING / _MIXED_LIGHTING_SUBTRACTIVE is enabled) MixRealtimeAndBakedGI(mainLight, IN.normalWS, bakedGI); // Diffuse half3 shading = bakedGI + LightingLambert(attenuatedLightColor, mainLight.direction, IN.normalWS); half4 color = baseMap * _BaseColor * IN.color; return half4(color.rgb * shading, color.a); } ENDHLSL } // UsePass "Universal Render Pipeline/Lit/ShadowCaster" // UsePass "Universal Render Pipeline/Lit/DepthOnly" // Would be nice if we could just use the passes from existing shaders, // However this breaks SRP Batcher compatibility. Instead, we should define them : // ShadowCaster, for casting shadows Pass { Name "ShadowCaster" Tags { "LightMode"="ShadowCaster" } ZWrite On ZTest LEqual HLSLPROGRAM #pragma vertex ShadowPassVertex #pragma fragment ShadowPassFragment // Material Keywords #pragma shader_feature_local_fragment _ALPHATEST_ON #pragma shader_feature_local_fragment _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A // GPU Instancing #pragma multi_compile_instancing //#pragma multi_compile _ DOTS_INSTANCING_ON // Universal Pipeline Keywords // (v11+) This is used during shadow map generation to differentiate between directional and punctual (point/spot) light shadows, as they use different formulas to apply Normal Bias #pragma multi_compile_vertex _ _CASTING_PUNCTUAL_LIGHT_SHADOW #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/CommonMaterial.hlsl" #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/SurfaceInput.hlsl" #include "Packages/com.unity.render-pipelines.universal/Shaders/ShadowCasterPass.hlsl" // Note if we do any vertex displacement, we'll need to change the vertex function. e.g. : /* #pragma vertex DisplacedShadowPassVertex (instead of ShadowPassVertex above) Varyings DisplacedShadowPassVertex(Attributes input) { Varyings output = (Varyings)0; UNITY_SETUP_INSTANCE_ID(input); // Example Displacement input.positionOS += float4(0, _SinTime.y, 0, 0); output.uv = TRANSFORM_TEX(input.texcoord, _BaseMap); output.positionCS = GetShadowPositionHClip(input); return output; } */ ENDHLSL } // DepthOnly, used for Camera Depth Texture (if cannot copy depth buffer instead, and the DepthNormals below isn't used) Pass { Name "DepthOnly" Tags { "LightMode"="DepthOnly" } ColorMask 0 ZWrite On ZTest LEqual HLSLPROGRAM #pragma vertex DepthOnlyVertex #pragma fragment DepthOnlyFragment // Material Keywords #pragma shader_feature_local_fragment _ALPHATEST_ON #pragma shader_feature_local_fragment _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A // GPU Instancing #pragma multi_compile_instancing //#pragma multi_compile _ DOTS_INSTANCING_ON #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/CommonMaterial.hlsl" #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/SurfaceInput.hlsl" #include "Packages/com.unity.render-pipelines.universal/Shaders/DepthOnlyPass.hlsl" // Note if we do any vertex displacement, we'll need to change the vertex function. e.g. : /* #pragma vertex DisplacedDepthOnlyVertex (instead of DepthOnlyVertex above) Varyings DisplacedDepthOnlyVertex(Attributes input) { Varyings output = (Varyings)0; UNITY_SETUP_INSTANCE_ID(input); UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output); // Example Displacement input.positionOS += float4(0, _SinTime.y, 0, 0); output.uv = TRANSFORM_TEX(input.texcoord, _BaseMap); output.positionCS = TransformObjectToHClip(input.position.xyz); return output; } */ ENDHLSL } // DepthNormals, used for SSAO & other custom renderer features that request it Pass { Name "DepthNormals" Tags { "LightMode"="DepthNormals" } ZWrite On ZTest LEqual HLSLPROGRAM #pragma vertex DepthNormalsVertex #pragma fragment DepthNormalsFragment // Material Keywords #pragma shader_feature_local _NORMALMAP #pragma shader_feature_local_fragment _ALPHATEST_ON #pragma shader_feature_local_fragment _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A // GPU Instancing #pragma multi_compile_instancing //#pragma multi_compile _ DOTS_INSTANCING_ON #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/CommonMaterial.hlsl" #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/SurfaceInput.hlsl" #include "Packages/com.unity.render-pipelines.universal/Shaders/DepthNormalsPass.hlsl" // Note if we do any vertex displacement, we'll need to change the vertex function. e.g. : /* #pragma vertex DisplacedDepthNormalsVertex (instead of DepthNormalsVertex above) Varyings DisplacedDepthNormalsVertex(Attributes input) { Varyings output = (Varyings)0; UNITY_SETUP_INSTANCE_ID(input); UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output); // Example Displacement input.positionOS += float4(0, _SinTime.y, 0, 0); output.uv = TRANSFORM_TEX(input.texcoord, _BaseMap); output.positionCS = TransformObjectToHClip(input.position.xyz); VertexNormalInputs normalInput = GetVertexNormalInputs(input.normal, input.tangentOS); output.normalWS = NormalizeNormalPerVertex(normalInput.normalWS); return output; } */ ENDHLSL } } }