Unity URP中2D纹理数组与阴影地图结合的问题排查
解决Unity 6.4 URP中2D纹理数组与阴影结合的Shader问题
问题1:头文件冲突编译错误
同时引入Lighting.hlsl和UnityCG.cginc触发PackHeightmap重定义错误,核心原因是两个头文件重复定义了相同工具函数。
解决方案
URP的HLSL环境无需依赖UnityCG.cginc的UNITY_DECLARE_TEX2DARRAY宏,直接使用URP原生HLSL资源声明方式即可:
- 用
TEXTURE2D_ARRAY(_TerrainLayers);替代UNITY_DECLARE_TEX2DARRAY(_TerrainLayers); - 用
SAMPLER(sampler_TerrainLayers);声明采样器 - 用
SAMPLE_TEXTURE2D_ARRAY(_TerrainLayers, sampler_TerrainLayers, uv, layerIndex)完成采样
彻底移除UnityCG.cginc引入,仅保留URP的Lighting.hlsl,即可解决冲突。
问题2:旧API无阴影显示
使用Legacy的Lighting.cginc和AutoLight.cginc无法在URP中正常渲染阴影,添加LightweightForward标签后材质变洋红,原因是Legacy光照管线与URP不兼容,LightweightForward为URP早期废弃标签。
解决方案
放弃Legacy API,改用URP原生HLSL写法:
- 确保SubShader添加
"RenderPipeline" = "UniversalPipeline"标签 - 使用URP提供的
GetVertexPositionInputs、GetShadowCoord等函数处理阴影坐标 - 添加正确的阴影编译宏(如
_MAIN_LIGHT_SHADOWS_CASCADE) - 必须添加URP规范的ShadowCaster Pass,否则物体无法投射阴影
问题3:URP HLSL写法出现阴影级联边缘Artifacts
阴影级联边缘出现异常,核心原因是世界空间位置计算错误,且阴影采样未处理级联过渡。
解决方案
关键代码修正点:
- 正确计算世界空间位置:原代码中
OUT.positionWorld = IN.positionOS;直接使用模型空间坐标,需改为:OUT.positionWorld = TransformObjectToWorld(IN.positionOS.xyz); - 使用URP内置阴影过渡函数:用
MainLightShadowing替代MainLightRealtimeShadow,自动处理级联阴影边缘过渡 - 添加软阴影编译宏:增强阴影平滑度,减少边缘锯齿
- 添加ShadowCaster Pass:确保物体能正确投射阴影
修正后的完整Shader代码:
Shader "Proc Env/Terrain" { Properties { _TerrainLayers ("Layers", 2DArray) = "" {} _LayerWeights("Weight Map", 2D) = "white" {} _UVScale ("UVScale", Float) = 1.0 } SubShader { Tags { "RenderType" = "Opaque" "RenderPipeline" = "UniversalPipeline" } // 主渲染Pass Pass { HLSLPROGRAM #pragma vertex vert #pragma fragment frag #pragma require 2darray // 阴影相关编译宏 #pragma multi_compile _ _MAIN_LIGHT_SHADOWS #pragma multi_compile _ _MAIN_LIGHT_SHADOWS_CASCADE #pragma multi_compile _ _SHADOWS_SOFT #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl" struct Attributes { float4 positionOS : POSITION; float3 normal : NORMAL; float2 uv : TEXCOORD0; }; struct Varyings { float4 positionHCS : SV_POSITION; float2 uv : TEXCOORD0; float3 positionWorld : TEXCOORD1; float4 shadowCoords : TEXCOORD2; float3 normalWorld : TEXCOORD3; }; Varyings vert(Attributes IN) { Varyings OUT; // 正确转换裁剪空间坐标 OUT.positionHCS = TransformObjectToHClip(IN.positionOS.xyz); OUT.uv = IN.uv; // 正确计算世界空间位置 OUT.positionWorld = TransformObjectToWorld(IN.positionOS.xyz); // 转换法线到世界空间 OUT.normalWorld = TransformObjectToWorldNormal(IN.normal); // 正确获取阴影坐标 VertexPositionInputs positionInputs = GetVertexPositionInputs(IN.positionOS.xyz); OUT.shadowCoords = GetShadowCoord(positionInputs); return OUT; } TEXTURE2D_ARRAY(_TerrainLayers); SAMPLER(sampler_TerrainLayers); float _UVScale; half4 frag (Varyings IN) : SV_Target { // 应用UV缩放 float2 sampleUV = IN.positionWorld.xz * _UVScale; // 采样2D纹理数组 half4 layerColor = SAMPLE_TEXTURE2D_ARRAY(_TerrainLayers, sampler_TerrainLayers, sampleUV, 2); // 获取主光照和阴影衰减,自动处理级联过渡 Light mainLight = GetMainLight(IN.shadowCoords); half shadowAttenuation = mainLight.shadowAttenuation; // 简单漫反射计算(可选,增强光照效果) half3 normal = normalize(IN.normalWorld); half diffuse = saturate(dot(normal, mainLight.direction)); half4 finalColor = layerColor * diffuse * mainLight.color * shadowAttenuation; return finalColor; } ENDHLSL } // URP阴影投射Pass Pass { Name "ShadowCaster" Tags { "LightMode" = "ShadowCaster" } HLSLPROGRAM #pragma vertex vert #pragma fragment frag #pragma multi_compile_shadowcaster #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl" struct Attributes { float4 positionOS : POSITION; float3 normal : NORMAL; }; struct Varyings { float4 positionHCS : SV_POSITION; float4 shadowCoord : TEXCOORD0; }; Varyings vert(Attributes IN) { Varyings OUT; VertexPositionInputs positionInputs = GetVertexPositionInputs(IN.positionOS.xyz); OUT.shadowCoord = GetShadowCoord(positionInputs); OUT.positionHCS = TransformWorldToHClip(ApplyShadowBias(positionInputs.positionWS, IN.normal)); return OUT; } half4 frag(Varyings IN) : SV_Target { // 阴影投射输出 return 0; } ENDHLSL } } }
额外URP设置优化:
- 在URP Asset的Quality面板中,调整Shadow Cascade的
Split Distances,增加过渡区域长度 - 开启Soft Shadows,并适当提高阴影分辨率
内容的提问来源于stack exchange,提问作者Aleksander Mendoza-Drosik
相关产品推荐
相关产品推荐

