Shader "NLD_URP/NLD_Vehicle" { Properties { [MainTexture] _MainTex ("Texture", 2D) = "white" {} _MaskTex ("Mask", 2D) = "white" {} _OutlineColor("Outline Color",color)=(0.18,0.1098,0.0549,1) _Outline("Thick of Outline",range(0,0.1))=0.008 _Factor("Factor",range(0,1)) = 0.32 _shadowScale("ShadowScale", range(0, 1.0)) = 0.5 _specularScaleG("SpecularScaleG", range(0, 10.0)) = 2.0 _specularScaleB("SpecularScaleB", range(0, 10.0)) = 2.0 _AlphaClip ("Alpha Clip", Range(0,1)) = 0.1 _fadeAlpha("FadeAlpha", range(0, 1.0)) = 1.0 [MaterialToggle(_RECEIVE_SHADOW_ON)] _ReceiveShadow ("Receive Shadow", Float) = 1 [Toggle] _ForceTransparent ("Force Transparent", Float) = 0.0 [Enum(Off,0,On,1)] _ZWrite("ZWrite", Float) = 1 } SubShader { Tags { "RenderType"="Opaque" "RenderPipeline" = "UniversalPipeline" } LOD 100 HLSLINCLUDE #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl" struct appdata { float4 positionOS : POSITION; float3 normal : NORMAL; float4 tangent : TANGENT; float2 uv : TEXCOORD0; }; struct v2f { float2 uv : TEXCOORD0; float4 positionHCS : SV_POSITION; #if defined(_RECEIVE_SHADOW_ON) float3 normalWS : TEXCOORD1; float3 positionWS : TEXCOORD02; #endif }; TEXTURE2D(_MainTex); SAMPLER(sampler_MainTex); TEXTURE2D(_MaskTex); SAMPLER(sampler_MaskTex); CBUFFER_START(UnityPerMaterial) float4 _MainTex_ST; float4 _MaskTex_ST; float4 _BaseMap_ST; float _specularScaleB; float _specularScaleG; float _shadowScale; float _Outline; float4 _OutlineColor; float _Factor; float _AlphaClip; float _ForceTransparent; float _fadeAlpha; CBUFFER_END ENDHLSL Pass { Name "ForwardLit" Tags { "LightMode" = "SRPDefaultUnlit" "RenderType" = "Opaque" } Cull Back ZWrite [_ZWrite] ZTest Less Blend SrcAlpha OneMinusSrcAlpha Stencil { Ref 2 Comp Always Pass Replace Fail Keep ZFail Keep ReadMask 255 WriteMask 255 } HLSLPROGRAM #pragma vertex vert #pragma fragment frag #pragma shader_feature_local _ _RECEIVE_SHADOW_ON #if defined(_RECEIVE_SHADOW_ON) #pragma multi_compile _ _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS #pragma multi_compile _ _MAIN_LIGHT_SHADOWS #pragma multi_compile _ _MAIN_LIGHT_SHADOWS_CASCADE #pragma multi_compile _ _ADDITIONAL_LIGHT_SHADOWS #pragma multi_compile _ _SHADOWS_SOFT #endif v2f vert (appdata v) { v2f o; o.positionHCS = TransformObjectToHClip(v.positionOS.xyz); o.uv = TRANSFORM_TEX(v.uv, _MainTex); #if defined(_RECEIVE_SHADOW_ON) o.positionWS = TransformObjectToWorld(v.positionOS); o.normalWS = TransformObjectToWorldNormal(v.normal); #endif return o; } half4 frag (const v2f i) : SV_Target { if (_fadeAlpha <= 0.01) { discard; } half4 color = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv); if (color.a <= _AlphaClip) discard; half4 colorMask = SAMPLE_TEXTURE2D(_MaskTex, sampler_MaskTex, i.uv); float r = colorMask.r; half shadow = 1.0; #if defined(_RECEIVE_SHADOW_ON) float4 SHADOW_COORDS = TransformWorldToShadowCoord(i.positionWS); shadow = MainLightRealtimeShadow(SHADOW_COORDS); #endif if (r < 0.5) { shadow = 0; } // 阴影强度跟随 fadeAlpha 渐变(fadeAlpha 越低,阴影越弱) half shadowStrength = (1.0h - shadow) * _fadeAlpha; color.xyz *= lerp(1, _shadowScale, shadowStrength); if (colorMask.b > 0.5) { color.xyz *= _specularScaleB; } if (colorMask.g > 0.5) { color.xyz *= _specularScaleG; } if (_ForceTransparent) { color.a = 0.2 * _fadeAlpha; } else { color.a = _fadeAlpha; } return color; } ENDHLSL } Pass { Name "Outline" Tags { "LightMode" = "Outline" } Cull Front ZTest Less ZWrite [_ZWrite] Blend SrcAlpha OneMinusSrcAlpha HLSLPROGRAM #pragma vertex vert #pragma fragment frag v2f vert (appdata v) { v2f o; o.uv = TRANSFORM_TEX(v.uv, _MainTex); float3 dir = TransformObjectToWorldNormal(v.normal); float3 dir2 = v.normal; float D = dot(dir, dir2); dir = dir*sign(D); dir = dir*_Factor + dir2*(1-_Factor); v.positionOS.xyz += dir*_Outline; o.positionHCS = TransformObjectToHClip(v.positionOS.xyz); return o; } half4 frag (v2f i) : SV_Target { if (_fadeAlpha <= 0.01) { discard; } half4 color = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv); if (color.a < _AlphaClip) discard; half4 mask = SAMPLE_TEXTURE2D(_MaskTex, sampler_MaskTex, i.uv); if (mask.a < 0.1) discard; half4 c = _OutlineColor; c.a = _fadeAlpha; return c; } ENDHLSL } Pass { Name "ShadowCaster" Tags { "LightMode" = "ShadowCaster" } ZWrite On ZTest LEqual Cull Back HLSLPROGRAM #pragma target 2.0 #pragma vertex vert #pragma fragment frag v2f vert (appdata v) { v2f o; o.positionHCS = TransformObjectToHClip(v.positionOS.xyz); o.uv = TRANSFORM_TEX(v.uv, _MainTex); return o; } half4 frag (v2f i) : SV_Target { // 当 fadeAlpha >= 0.99 时,跳过纹理采样和 dithering,直接投射阴影 if (_fadeAlpha >= 0.99h) { return 1; } // 完全透明时不投射阴影 if (_fadeAlpha <= 0.01h) { discard; } // 仅在渐隐状态下进行纹理采样和 alpha 裁剪 half texAlpha = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv).a; clip(texAlpha - _AlphaClip); // Dithering 实现渐隐阴影效果 half2 p = floor(i.positionHCS.xy); half2 p2 = floor(p * 0.5h); half2 p4 = floor(p2 * 0.5h); half d = frac(dot(p, half2(0.5h, 0.25h)) + dot(p2, half2(0.125h, 0.0625h)) + dot(p4, half2(0.03125h, 0.015625h))); half dither = d * 0.984375h + 0.015625h; half fade = _fadeAlpha * _fadeAlpha * (3.0h - 2.0h * _fadeAlpha); clip(fade - dither); return 1; } ENDHLSL } } }