Unity自定义Shader为何透显场景网格?已设不透明仍未解决
问题描述
在Unity编辑器Scene视图中,使用默认URP Lit Shader的物体可正常遮挡场景网格,但自定义简单Shader的物体无法遮挡,场景网格会透显。已为Shader添加URP不透明材质的常规设置:
ZWrite On ZTest LEqual Blend Off
但问题依旧,关闭Scene视图网格并非可行方案,需让自定义Shader和默认URP Lit Shader一样实现遮挡效果。
注:测试用的两个球体Y轴位置均为0,仅右侧使用自定义Shader的球体沿X轴偏移1单位,视觉上看似在网格后方,但实际位置与左侧球体一致。
用户提供的自定义Shader代码:
Shader "Custom/SimpleShader" { Properties { base_color ("Base Color", Color) = (1,1,1,1) } SubShader { Tags { "RenderType"="Opaque" "Queue"="Geometry" "RenderPipeline"="UniversalPipeline" } LOD 100 Pass { ZWrite On ZTest LEqual Blend Off HLSLPROGRAM #pragma target 2.0 #pragma vertex vert #pragma fragment frag #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl" struct attributes { float4 position_os : POSITION; float3 normal_os : NORMAL; }; struct varyings { float4 position_cs : SV_POSITION; float3 position_ws : TEXCOORD0; float3 normal_ws : TEXCOORD1; }; CBUFFER_START(UnityPerMaterial) float4 base_color; CBUFFER_END varyings vert (attributes input) { varyings output; output.position_cs = TransformObjectToHClip(input.position_os.xyz); output.position_ws = TransformObjectToWorld(input.position_os).xyz; output.normal_ws = TransformObjectToWorldNormal(input.normal_os); return output; } half4 frag (varyings input) : SV_Target { Light main_light = GetMainLight(); float3 light_color = main_light.color.rgb; float3 light_direction_ws = normalize(main_light.direction.xyz); float3 normal_ws = normalize(input.normal_ws); float normal_dot_light = max(0,dot(normal_ws, light_direction_ws)); float3 diffuse = light_color * normal_dot_light; float3 ambient = SampleSH(input.normal_ws); float4 lighting = float4(diffuse + ambient, 1); float4 final_color = base_color * lighting; return final_color; } ENDHLSL } } }
解决方案
问题核心是自定义Shader缺少深度通道渲染Pass:URP的Scene视图网格依赖深度缓冲判断遮挡,默认URP Lit Shader包含DepthOnly Pass,会提前将物体深度信息写入缓冲;而你的自定义Shader仅包含颜色渲染Pass,即使开启ZWrite On,也可能因Scene视图渲染顺序问题,导致网格渲染时读取不到物体深度。
只需在SubShader中添加DepthOnly Pass即可解决,修改后的Shader代码如下:
Shader "Custom/SimpleShader" { Properties { base_color ("Base Color", Color) = (1,1,1,1) } SubShader { Tags { "RenderType"="Opaque" "Queue"="Geometry" "RenderPipeline"="UniversalPipeline" } LOD 100 // 添加深度渲染Pass Pass { Name "DepthOnly" Tags { "LightMode" = "DepthOnly" } ZWrite On ColorMask 0 HLSLPROGRAM #pragma vertex vert #pragma fragment frag #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" struct Attributes { float4 positionOS : POSITION; UNITY_VERTEX_INPUT_INSTANCE_ID }; struct Varyings { float4 positionCS : SV_POSITION; UNITY_VERTEX_OUTPUT_STEREO }; Varyings vert(Attributes input) { Varyings output; UNITY_SETUP_INSTANCE_ID(input); UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output); output.positionCS = TransformObjectToHClip(input.positionOS.xyz); return output; } half4 frag() : SV_Target { return 0; } ENDHLSL } Pass { ZWrite On ZTest LEqual Blend Off HLSLPROGRAM #pragma target 2.0 #pragma vertex vert #pragma fragment frag #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl" struct attributes { float4 position_os : POSITION; float3 normal_os : NORMAL; }; struct varyings { float4 position_cs : SV_POSITION; float3 position_ws : TEXCOORD0; float3 normal_ws : TEXCOORD1; }; CBUFFER_START(UnityPerMaterial) float4 base_color; CBUFFER_END varyings vert (attributes input) { varyings output; output.position_cs = TransformObjectToHClip(input.position_os.xyz); output.position_ws = TransformObjectToWorld(input.position_os).xyz; output.normal_ws = TransformObjectToWorldNormal(input.normal_os); return output; } half4 frag (varyings input) : SV_Target { Light main_light = GetMainLight(); float3 light_color = main_light.color.rgb; float3 light_direction_ws = normalize(main_light.direction.xyz); float3 normal_ws = normalize(input.normal_ws); float normal_dot_light = max(0,dot(normal_ws, light_direction_ws)); float3 diffuse = light_color * normal_dot_light; float3 ambient = SampleSH(input.normal_ws); float4 lighting = float4(diffuse + ambient, 1); float4 final_color = base_color * lighting; return final_color; } ENDHLSL } } }
内容的提问来源于stack exchange,提问作者Sonic Slonik
相关产品推荐
相关产品推荐

