Shader "BrewMonster/UnlitWithShadows" { Properties { _BaseMap ("Texture", 2D) = "white" {} _Color ("Color", Color) = (1,1,1,1) _ShadowStrength ("Shadow Strength", Range(0, 1)) = 0.5 [Toggle(_ALPHATEST_ON)] _AlphaClip("Alpha Clip", Float) = 0 _Cutoff("Alpha Cutoff", Range(0.0, 1.0)) = 0.5 // BlendMode options [Enum(UnityEngine.Rendering.BlendMode)] _SrcBlend("Src Blend Mode", Float) = 1 [Enum(UnityEngine.Rendering.BlendMode)] _DstBlend("Dst Blend Mode", Float) = 0 [Enum(Off, 0, On, 1)] _ZWrite("Z Write", Float) = 1 // Surface options [Enum(UnityEngine.Rendering.CullMode)] _Cull("Cull Mode", Float) = 2 [Toggle(_ALPHAMODULATE_ON)] _AlphaModulate("Alpha Modulate", Float) = 0 // Material type [HideInInspector] _Surface("__surface", Float) = 0.0 } // Helper to set render queue and render type based on alpha mode CustomEditor "BrewMonsterUnlitShaderGUI" SubShader { Tags { "RenderPipeline" = "UniversalPipeline" "RenderType" = "Opaque" "Queue" = "Geometry" } LOD 100 // Main pass Pass { Name "ForwardLit" Tags { "LightMode"="UniversalForward" } Blend [_SrcBlend] [_DstBlend] ZWrite [_ZWrite] Cull [_Cull] HLSLPROGRAM #pragma vertex vert #pragma fragment frag // Shadows #pragma multi_compile _ _MAIN_LIGHT_SHADOWS _MAIN_LIGHT_SHADOWS_CASCADE #pragma multi_compile _ _SHADOWS_SOFT #pragma multi_compile _ _ADDITIONAL_LIGHT_SHADOWS // Fog #pragma multi_compile_fog // Alpha features #pragma shader_feature_local_fragment _ALPHATEST_ON #pragma shader_feature_local_fragment _ALPHAMODULATE_ON #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl" TEXTURE2D(_BaseMap); SAMPLER(sampler_BaseMap); CBUFFER_START(UnityPerMaterial) float4 _BaseMap_ST; half4 _Color; half _ShadowStrength; half _Cutoff; CBUFFER_END struct Attributes { float4 positionOS : POSITION; float2 uv : TEXCOORD0; float3 normalOS : NORMAL; }; struct Varyings { float4 positionCS : SV_POSITION; float2 uv : TEXCOORD0; float3 positionWS : TEXCOORD1; float3 normalWS : TEXCOORD2; float fogCoord : TEXCOORD3; }; Varyings vert(Attributes input) { Varyings output; // Transform position VertexPositionInputs vertexInput = GetVertexPositionInputs(input.positionOS.xyz); output.positionCS = vertexInput.positionCS; output.positionWS = vertexInput.positionWS; // Transform normal VertexNormalInputs normalInput = GetVertexNormalInputs(input.normalOS); output.normalWS = normalInput.normalWS; // UV output.uv = TRANSFORM_TEX(input.uv, _BaseMap); // Fog output.fogCoord = ComputeFogFactor(vertexInput.positionCS.z); return output; } half4 frag(Varyings input) : SV_Target { // Sample the texture half4 mainTex = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, input.uv); half4 color = mainTex * _Color; // Alpha test #ifdef _ALPHATEST_ON clip(color.a - _Cutoff); #endif // Alpha modulate mode (for special effects) #ifdef _ALPHAMODULATE_ON color.rgb *= color.a; #endif // Shadow calculation float4 shadowCoord = TransformWorldToShadowCoord(input.positionWS); Light mainLight = GetMainLight(shadowCoord); half shadowAttenuation = mainLight.shadowAttenuation; // Apply shadow half shadow = lerp(1.0, shadowAttenuation, _ShadowStrength); color.rgb *= shadow; // Apply fog color.rgb = MixFog(color.rgb, input.fogCoord); return color; } ENDHLSL } // Shadow caster pass Pass { Name "ShadowCaster" Tags { "LightMode"="ShadowCaster" } ZWrite On ZTest LEqual ColorMask 0 Cull [_Cull] HLSLPROGRAM #pragma vertex ShadowPassVertex #pragma fragment ShadowPassFragment // Alpha clipping for shadows #pragma shader_feature_local_fragment _ALPHATEST_ON #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Shadows.hlsl" TEXTURE2D(_BaseMap); SAMPLER(sampler_BaseMap); CBUFFER_START(UnityPerMaterial) float4 _BaseMap_ST; half4 _Color; half _ShadowStrength; half _Cutoff; CBUFFER_END struct Attributes { float4 positionOS : POSITION; float3 normalOS : NORMAL; float2 texcoord : TEXCOORD0; }; struct Varyings { float4 positionCS : SV_POSITION; float2 uv : TEXCOORD0; }; float3 _LightDirection; float4 GetShadowPositionHClip(Attributes input) { float3 positionWS = TransformObjectToWorld(input.positionOS.xyz); float3 normalWS = TransformObjectToWorldNormal(input.normalOS); float4 positionCS = TransformWorldToHClip(ApplyShadowBias(positionWS, normalWS, _LightDirection)); #if UNITY_REVERSED_Z positionCS.z = min(positionCS.z, UNITY_NEAR_CLIP_VALUE); #else positionCS.z = max(positionCS.z, UNITY_NEAR_CLIP_VALUE); #endif return positionCS; } Varyings ShadowPassVertex(Attributes input) { Varyings output; output.positionCS = GetShadowPositionHClip(input); output.uv = TRANSFORM_TEX(input.texcoord, _BaseMap); return output; } half4 ShadowPassFragment(Varyings input) : SV_TARGET { #ifdef _ALPHATEST_ON half4 mainTex = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, input.uv); half alpha = mainTex.a * _Color.a; clip(alpha - _Cutoff); #endif return 0; } ENDHLSL } // Depth pass for receiving shadows Pass { Name "DepthOnly" Tags { "LightMode"="DepthOnly" } ZWrite On ColorMask 0 Cull [_Cull] HLSLPROGRAM #pragma vertex DepthOnlyVertex #pragma fragment DepthOnlyFragment // Alpha clipping for depth #pragma shader_feature_local_fragment _ALPHATEST_ON #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" TEXTURE2D(_BaseMap); SAMPLER(sampler_BaseMap); CBUFFER_START(UnityPerMaterial) float4 _BaseMap_ST; half4 _Color; half _Cutoff; CBUFFER_END struct Attributes { float4 position : POSITION; float2 texcoord : TEXCOORD0; }; struct Varyings { float4 positionCS : SV_POSITION; float2 uv : TEXCOORD0; }; Varyings DepthOnlyVertex(Attributes input) { Varyings output; output.positionCS = TransformObjectToHClip(input.position.xyz); output.uv = TRANSFORM_TEX(input.texcoord, _BaseMap); return output; } half4 DepthOnlyFragment(Varyings input) : SV_TARGET { #ifdef _ALPHATEST_ON half4 mainTex = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, input.uv); half alpha = mainTex.a * _Color.a; clip(alpha - _Cutoff); #endif return 0; } ENDHLSL } } FallBack "Universal Render Pipeline/Lit" }