Loading... #### 关于平面投射阴影,网上已经有很多文章介绍相关原理和优缺点: - https://zhuanlan.zhihu.com/p/31504088 - https://zhuanlan.zhihu.com/p/266174847 这里记录一下在URP中的实现: - 将URP Simple Lit Shader 源码拷贝新建一个Shader - 修改成如下 ``` // Shader targeted for low end devices. Single Pass Forward Rendering. Shader "Custom/URP/Simple Lit" { // Keep properties of StandardSpecular shader for upgrade reasons. Properties { [MainTexture] _BaseMap("Base Map (RGB) Smoothness / Alpha (A)", 2D) = "white" {} [MainColor] _BaseColor("Base Color", Color) = (1, 1, 1, 1) _Cutoff("Alpha Clipping", Range(0.0, 1.0)) = 0.5 _Smoothness("Smoothness", Range(0.0, 1.0)) = 0.5 _SpecColor("Specular Color", Color) = (0.5, 0.5, 0.5, 0.5) _SpecGlossMap("Specular Map", 2D) = "white" {} _SmoothnessSource("Smoothness Source", Float) = 0.0 _SpecularHighlights("Specular Highlights", Float) = 1.0 [HideInInspector] _BumpScale("Scale", Float) = 1.0 [NoScaleOffset] _BumpMap("Normal Map", 2D) = "bump" {} [HDR] _EmissionColor("Emission Color", Color) = (0,0,0) [NoScaleOffset]_EmissionMap("Emission Map", 2D) = "white" {} // Blending state _Surface("__surface", Float) = 0.0 _Blend("__blend", Float) = 0.0 _Cull("__cull", Float) = 2.0 [ToggleUI] _AlphaClip("__clip", Float) = 0.0 [HideInInspector] _SrcBlend("__src", Float) = 1.0 [HideInInspector] _DstBlend("__dst", Float) = 0.0 [HideInInspector] _ZWrite("__zw", Float) = 1.0 [ToggleUI] _ReceiveShadows("Receive Shadows", Float) = 1.0 // Editmode props _QueueOffset("Queue offset", Float) = 0.0 // ObsoleteProperties [HideInInspector] _MainTex("BaseMap", 2D) = "white" {} [HideInInspector] _Color("Base Color", Color) = (1, 1, 1, 1) [HideInInspector] _Shininess("Smoothness", Float) = 0.0 [HideInInspector] _GlossinessSource("GlossinessSource", Float) = 0.0 [HideInInspector] _SpecSource("SpecularHighlights", Float) = 0.0 [HideInInspector][NoScaleOffset]unity_Lightmaps("unity_Lightmaps", 2DArray) = "" {} [HideInInspector][NoScaleOffset]unity_LightmapsInd("unity_LightmapsInd", 2DArray) = "" {} [HideInInspector][NoScaleOffset]unity_ShadowMasks("unity_ShadowMasks", 2DArray) = "" {} } SubShader { Tags { "RenderType" = "Opaque" "RenderPipeline" = "UniversalPipeline" "UniversalMaterialType" = "SimpleLit" "IgnoreProjector" = "True" "ShaderModel"="4.5" } LOD 300 Pass { Name "PlanarShadowCaster" Tags { "RenderType"="Transparent" "Queue" = "Transparent" "RenderPipeline" = "Universal" "LightMode" = "SRPDefaultUnlit" } //用使用模板测试以保证alpha显示正确 Stencil { Ref 0 Comp equal Pass incrWrap Fail keep ZFail keep } //透明混合模式 // Blend SrcAlpha OneMinusSrcAlpha Blend One Zero //关闭深度写入 ZWrite off //深度稍微偏移防止阴影与地面穿插 Offset -1 , 0 HLSLINCLUDE #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl" ENDHLSL HLSLPROGRAM #pragma vertex vert #pragma fragment frag struct appdata { float4 vertex : POSITION; }; struct v2f { float4 vertex : SV_POSITION; float4 color : COLOR; }; float _GroundLevel; // float4 _ShadowColor; // float _ShadowFalloff; float3 ShadowProjectPos(float4 vertPos, Light mainLight) { float3 shadowPos; //得到顶点的世界空间坐标 float3 worldPos = TransformObjectToWorld(vertPos.xyz); _GroundLevel = 0.5; //灯光方向 float3 lightDir = normalize(mainLight.direction.xyz); //阴影的世界空间坐标(低于地面的部分不做改变) shadowPos.y = min(worldPos.y, _GroundLevel); shadowPos.xz = worldPos.xz - lightDir.xz * max(0, worldPos.y - _GroundLevel) / lightDir.y; return shadowPos; } v2f vert(appdata v) { v2f o; Light mainLight = GetMainLight(); //得到阴影的世界空间坐标 float3 shadowPos = ShadowProjectPos(v.vertex, mainLight); //转换到裁切空间 o.vertex = TransformWorldToHClip(shadowPos); //得到中心点世界坐标 float3 center = float3(unity_ObjectToWorld[0].w, _GroundLevel, unity_ObjectToWorld[2].w); //计算阴影衰减 float falloff = 1 - saturate(distance(shadowPos, center) * 0.2); //阴影颜色 o.color = float4(0.18,.18,.18,1); o.color.a *= 1; return o; } half4 frag(v2f i) : SV_Target { return i.color; } ENDHLSL } Pass { Name "ForwardLit" Tags { "LightMode" = "UniversalForward" } // Use same blending / depth states as Standard shader Blend[_SrcBlend][_DstBlend] ZWrite On Cull[_Cull] HLSLPROGRAM // #pragma exclude_renderers gles gles3 glcore // #pragma target 4.5 // ------------------------------------- // Material Keywords #pragma shader_feature_local _NORMALMAP #pragma shader_feature_local_fragment _EMISSION #pragma shader_feature_local _RECEIVE_SHADOWS_OFF #pragma shader_feature_local_fragment _SURFACE_TYPE_TRANSPARENT #pragma shader_feature_local_fragment _ALPHATEST_ON #pragma shader_feature_local_fragment _ALPHAPREMULTIPLY_ON #pragma shader_feature_local_fragment _ _SPECGLOSSMAP _SPECULAR_COLOR #pragma shader_feature_local_fragment _GLOSSINESS_FROM_BASE_ALPHA // ------------------------------------- // Universal Pipeline keywords #pragma multi_compile _ _MAIN_LIGHT_SHADOWS _MAIN_LIGHT_SHADOWS_CASCADE _MAIN_LIGHT_SHADOWS_SCREEN #pragma multi_compile _ _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS #pragma multi_compile _ LIGHTMAP_SHADOW_MIXING #pragma multi_compile _ SHADOWS_SHADOWMASK #pragma multi_compile_fragment _ _ADDITIONAL_LIGHT_SHADOWS #pragma multi_compile_fragment _ _SHADOWS_SOFT #pragma multi_compile_fragment _ _SCREEN_SPACE_OCCLUSION #pragma multi_compile_fragment _ _DBUFFER_MRT1 _DBUFFER_MRT2 _DBUFFER_MRT3 #pragma multi_compile_fragment _ _LIGHT_LAYERS #pragma multi_compile_fragment _ _LIGHT_COOKIES #pragma multi_compile _ _CLUSTERED_RENDERING // ------------------------------------- // Unity defined keywords #pragma multi_compile _ DIRLIGHTMAP_COMBINED #pragma multi_compile _ LIGHTMAP_ON #pragma multi_compile _ DYNAMICLIGHTMAP_ON #pragma multi_compile_fog #pragma multi_compile_fragment _ DEBUG_DISPLAY //-------------------------------------- // GPU Instancing #pragma multi_compile_instancing #pragma instancing_options renderinglayer #pragma multi_compile _ DOTS_INSTANCING_ON #pragma vertex LitPassVertexSimple #pragma fragment LitPassFragmentSimple // #define BUMP_SCALE_NOT_SUPPORTED 1 #include "Packages/com.unity.render-pipelines.universal/Shaders/SimpleLitInput.hlsl" #include "Packages/com.unity.render-pipelines.universal/Shaders/SimpleLitForwardPass.hlsl" ENDHLSL } // Pass // { // Name "ShadowCaster" // Tags // { // "LightMode" = "ShadowCaster" // } // // ZWrite On // ZTest LEqual // ColorMask 0 // Cull[_Cull] // // HLSLPROGRAM // #pragma exclude_renderers gles gles3 glcore // #pragma target 4.5 // // // ------------------------------------- // // Material Keywords // #pragma shader_feature_local_fragment _ALPHATEST_ON // #pragma shader_feature_local_fragment _GLOSSINESS_FROM_BASE_ALPHA // // //-------------------------------------- // // GPU Instancing // #pragma multi_compile_instancing // #pragma multi_compile _ DOTS_INSTANCING_ON // // // ------------------------------------- // // Universal Pipeline keywords // // // This is used during shadow map generation to differentiate between directional and punctual light shadows, as they use different formulas to apply Normal Bias // #pragma multi_compile_vertex _ _CASTING_PUNCTUAL_LIGHT_SHADOW // // #pragma vertex ShadowPassVertex // #pragma fragment ShadowPassFragment // // #include "Packages/com.unity.render-pipelines.universal/Shaders/SimpleLitInput.hlsl" // #include "Packages/com.unity.render-pipelines.universal/Shaders/ShadowCasterPass.hlsl" // ENDHLSL // } Pass { Name "GBuffer" Tags { "LightMode" = "UniversalGBuffer" } ZWrite[_ZWrite] ZTest LEqual Cull[_Cull] HLSLPROGRAM #pragma exclude_renderers gles gles3 glcore #pragma target 4.5 // ------------------------------------- // Material Keywords #pragma shader_feature_local_fragment _ALPHATEST_ON //#pragma shader_feature _ALPHAPREMULTIPLY_ON #pragma shader_feature_local_fragment _ _SPECGLOSSMAP _SPECULAR_COLOR #pragma shader_feature_local_fragment _GLOSSINESS_FROM_BASE_ALPHA #pragma shader_feature_local _NORMALMAP #pragma shader_feature_local_fragment _EMISSION #pragma shader_feature_local _RECEIVE_SHADOWS_OFF // ------------------------------------- // Universal Pipeline keywords #pragma multi_compile _ _MAIN_LIGHT_SHADOWS _MAIN_LIGHT_SHADOWS_CASCADE _MAIN_LIGHT_SHADOWS_SCREEN //#pragma multi_compile _ _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS //#pragma multi_compile _ _ADDITIONAL_LIGHT_SHADOWS #pragma multi_compile_fragment _ _SHADOWS_SOFT #pragma multi_compile_fragment _ _DBUFFER_MRT1 _DBUFFER_MRT2 _DBUFFER_MRT3 #pragma multi_compile_fragment _ _LIGHT_LAYERS // ------------------------------------- // Unity defined keywords #pragma multi_compile _ DIRLIGHTMAP_COMBINED #pragma multi_compile _ LIGHTMAP_ON #pragma multi_compile _ DYNAMICLIGHTMAP_ON #pragma multi_compile _ LIGHTMAP_SHADOW_MIXING #pragma multi_compile _ SHADOWS_SHADOWMASK #pragma multi_compile_fragment _ _GBUFFER_NORMALS_OCT #pragma multi_compile_fragment _ _RENDER_PASS_ENABLED //-------------------------------------- // GPU Instancing #pragma multi_compile_instancing #pragma instancing_options renderinglayer #pragma multi_compile _ DOTS_INSTANCING_ON #pragma vertex LitPassVertexSimple #pragma fragment LitPassFragmentSimple #define BUMP_SCALE_NOT_SUPPORTED 1 #include "Packages/com.unity.render-pipelines.universal/Shaders/SimpleLitInput.hlsl" #include "Packages/com.unity.render-pipelines.universal/Shaders/SimpleLitGBufferPass.hlsl" ENDHLSL } Pass { Name "DepthOnly" Tags { "LightMode" = "DepthOnly" } ZWrite On ColorMask 0 Cull[_Cull] HLSLPROGRAM #pragma exclude_renderers gles gles3 glcore #pragma target 4.5 #pragma vertex DepthOnlyVertex #pragma fragment DepthOnlyFragment // ------------------------------------- // Material Keywords #pragma shader_feature_local_fragment _ALPHATEST_ON #pragma shader_feature_local_fragment _GLOSSINESS_FROM_BASE_ALPHA //-------------------------------------- // GPU Instancing #pragma multi_compile_instancing #pragma multi_compile _ DOTS_INSTANCING_ON #include "Packages/com.unity.render-pipelines.universal/Shaders/SimpleLitInput.hlsl" #include "Packages/com.unity.render-pipelines.universal/Shaders/DepthOnlyPass.hlsl" ENDHLSL } // // This pass is used when drawing to a _CameraNormalsTexture texture // Pass // { // Name "DepthNormals" // Tags // { // "LightMode" = "DepthNormals" // } // // ZWrite On // Cull[_Cull] // // HLSLPROGRAM // #pragma exclude_renderers gles gles3 glcore // #pragma target 4.5 // // #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 _GLOSSINESS_FROM_BASE_ALPHA // // //-------------------------------------- // // GPU Instancing // #pragma multi_compile_instancing // #pragma multi_compile _ DOTS_INSTANCING_ON // // #include "Packages/com.unity.render-pipelines.universal/Shaders/SimpleLitInput.hlsl" // #include "Packages/com.unity.render-pipelines.universal/Shaders/SimpleLitDepthNormalsPass.hlsl" // ENDHLSL // } } SubShader { Tags { "RenderType" = "Opaque" "RenderPipeline" = "UniversalPipeline" "UniversalMaterialType" = "SimpleLit" "IgnoreProjector" = "True" "ShaderModel"="2.0" } LOD 300 Pass { Name "ForwardLit" Tags { "LightMode" = "UniversalForward" } // Use same blending / depth states as Standard shader Blend[_SrcBlend][_DstBlend] ZWrite On Cull[_Cull] HLSLPROGRAM #pragma only_renderers gles gles3 glcore d3d11 #pragma target 2.0 // ------------------------------------- // Material Keywords #pragma shader_feature_local _NORMALMAP #pragma shader_feature_local_fragment _EMISSION #pragma shader_feature_local _RECEIVE_SHADOWS_OFF #pragma shader_feature_local_fragment _SURFACE_TYPE_TRANSPARENT #pragma shader_feature_local_fragment _ALPHATEST_ON #pragma shader_feature_local_fragment _ALPHAPREMULTIPLY_ON #pragma shader_feature_local_fragment _ _SPECGLOSSMAP _SPECULAR_COLOR #pragma shader_feature_local_fragment _GLOSSINESS_FROM_BASE_ALPHA // ------------------------------------- // Universal Pipeline keywords #pragma multi_compile _ _MAIN_LIGHT_SHADOWS _MAIN_LIGHT_SHADOWS_CASCADE _MAIN_LIGHT_SHADOWS_SCREEN #pragma multi_compile _ _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS #pragma multi_compile _ LIGHTMAP_SHADOW_MIXING #pragma multi_compile _ SHADOWS_SHADOWMASK #pragma multi_compile_fragment _ _SHADOWS_SOFT #pragma multi_compile_fragment _ _ADDITIONAL_LIGHT_SHADOWS #pragma multi_compile_fragment _ _SCREEN_SPACE_OCCLUSION #pragma multi_compile_fragment _ _LIGHT_LAYERS #pragma multi_compile_fragment _ _LIGHT_COOKIES #pragma multi_compile _ _CLUSTERED_RENDERING // ------------------------------------- // Unity defined keywords #pragma multi_compile _ DIRLIGHTMAP_COMBINED #pragma multi_compile _ LIGHTMAP_ON #pragma multi_compile _ DYNAMICLIGHTMAP_ON #pragma multi_compile_fog #pragma multi_compile_fragment _ DEBUG_DISPLAY #pragma vertex LitPassVertexSimple #pragma fragment LitPassFragmentSimple #define BUMP_SCALE_NOT_SUPPORTED 1 #include "Packages/com.unity.render-pipelines.universal/Shaders/SimpleLitInput.hlsl" #include "Packages/com.unity.render-pipelines.universal/Shaders/SimpleLitForwardPass.hlsl" ENDHLSL } Pass { Name "PlanarShadowCaster" Tags { "RenderType"="Opaque" "Queue" = "Opaque" "RenderPipeline" = "Universal" "LightMode" = "SRPDefaultUnlit" } //用使用模板测试以保证alpha显示正确 Stencil { Ref 0 Comp equal Pass incrWrap Fail keep ZFail keep } //透明混合模式 Blend SrcAlpha OneMinusSrcAlpha //关闭深度写入 ZWrite off //深度稍微偏移防止阴影与地面穿插 Offset -1 , 0 HLSLINCLUDE #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl" ENDHLSL HLSLPROGRAM #pragma vertex vert #pragma fragment frag struct appdata { float4 vertex : POSITION; }; struct v2f { float4 vertex : SV_POSITION; float4 color : COLOR; }; float _GroundLevel; float4 _ShadowColor; float _ShadowFalloff; float3 ShadowProjectPos(float4 vertPos, Light mainLight) { float3 shadowPos; //得到顶点的世界空间坐标 float3 worldPos = TransformObjectToWorld(vertPos.xyz); //灯光方向 float3 lightDir = normalize(mainLight.direction.xyz); //阴影的世界空间坐标(低于地面的部分不做改变) shadowPos.y = min(worldPos.y, _GroundLevel); shadowPos.xz = worldPos.xz - lightDir.xz * max(0, worldPos.y - _GroundLevel) / lightDir.y; return shadowPos; } v2f vert(appdata v) { v2f o; Light mainLight = GetMainLight(); //得到阴影的世界空间坐标 float3 shadowPos = ShadowProjectPos(v.vertex, mainLight); //转换到裁切空间 o.vertex = TransformWorldToHClip(shadowPos); //得到中心点世界坐标 float3 center = float3(unity_ObjectToWorld[0].w, _GroundLevel, unity_ObjectToWorld[2].w); //计算阴影衰减 float falloff = 1 - saturate(distance(shadowPos, center) * _ShadowFalloff); //阴影颜色 o.color = _ShadowColor; o.color.a *= falloff; return o; } half4 frag(v2f i) : SV_Target { return i.color; } ENDHLSL } // Pass // { // Name "ShadowCaster" // Tags // { // "LightMode" = "ShadowCaster" // } // // ZWrite On // ZTest LEqual // ColorMask 0 // Cull[_Cull] // // HLSLPROGRAM // #pragma only_renderers gles gles3 glcore d3d11 // #pragma target 2.0 // // // ------------------------------------- // // Material Keywords // #pragma shader_feature_local_fragment _ALPHATEST_ON // #pragma shader_feature_local_fragment _GLOSSINESS_FROM_BASE_ALPHA // // // ------------------------------------- // // Universal Pipeline keywords // // // This is used during shadow map generation to differentiate between directional and punctual light shadows, as they use different formulas to apply Normal Bias // #pragma multi_compile_vertex _ _CASTING_PUNCTUAL_LIGHT_SHADOW // // #pragma vertex ShadowPassVertex // #pragma fragment ShadowPassFragment // // #include "Packages/com.unity.render-pipelines.universal/Shaders/SimpleLitInput.hlsl" // #include "Packages/com.unity.render-pipelines.universal/Shaders/ShadowCasterPass.hlsl" // ENDHLSL // } Pass { Name "DepthOnly" Tags { "LightMode" = "DepthOnly" } ZWrite On ColorMask 0 Cull[_Cull] HLSLPROGRAM #pragma only_renderers gles gles3 glcore d3d11 #pragma target 2.0 #pragma vertex DepthOnlyVertex #pragma fragment DepthOnlyFragment // Material Keywords #pragma shader_feature_local_fragment _ALPHATEST_ON #pragma shader_feature_local_fragment _GLOSSINESS_FROM_BASE_ALPHA #include "Packages/com.unity.render-pipelines.universal/Shaders/SimpleLitInput.hlsl" #include "Packages/com.unity.render-pipelines.universal/Shaders/DepthOnlyPass.hlsl" ENDHLSL } } Fallback "Hidden/Universal Render Pipeline/FallbackError" CustomEditor "UnityEditor.Rendering.Universal.ShaderGUI.SimpleLitShader" } ``` 最后修改:2022 年 05 月 21 日 © 允许规范转载 赞 0