Unity URP距离透明化Shader失效,求解决方案
问题分析与解决思路
你的Shader无法正常工作主要有以下几个核心问题,对应修改方案如下:
- 距离计算坐标不匹配:你在片元着色器里用
i.vertex(裁剪空间坐标)和_WorldSpaceCameraPos(世界空间坐标)计算距离,两者空间维度不同,结果完全错误。需要在顶点着色器中将顶点转换为世界空间坐标,传递给片元着色器用于距离计算。 - 透明渲染状态缺失:仅设置
Queue="Transparent"不够,还需要开启混合模式、关闭深度写入,否则透明效果会出现渲染顺序错乱、重叠显示异常等问题。 - 未声明
_MainTex属性:代码中使用了_MainTex但Properties里没有定义,会导致纹理采样失效,要么补上该属性,要么移除不必要的纹理采样代码。 - URP适配不足:原Shader没有添加URP专属标签,且Fallback使用了内置管线的"Diffuse",会导致URP环境下兼容性问题。
修改后的完整Shader代码
Shader "Custom/DistanceFade" { Properties { _Color("Color", Color) = (1,1,1,1) _Threshold("Fade Threshold", float) = 5 _MainTex("Main Texture", 2D) = "white" {} // 补上缺失的纹理属性 } SubShader { Tags { "Queue" = "Transparent" "RenderType" = "Transparent" "RenderPipeline" = "UniversalPipeline" // 适配URP的专属标签 } LOD 200 Pass { Blend SrcAlpha OneMinusSrcAlpha // 开启标准透明混合 ZWrite Off // 关闭深度写入,避免遮挡后续透明物体 CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; float2 texcoord : TEXCOORD0; }; struct v2f { float4 vertex : SV_POSITION; float2 texcoord : TEXCOORD0; float3 worldPos : TEXCOORD1; // 新增变量存储世界空间坐标 }; sampler2D _MainTex; float4 _MainTex_ST; // 纹理缩放偏移变量,采样时需用到 float4 _Color; float _Threshold; v2f vert(appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex); // 标准化纹理坐标 o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz; // 将顶点转换为世界空间 return o; } fixed4 frag(v2f i) : SV_Target { fixed4 col = tex2D(_MainTex, i.texcoord); float distanceToCam = distance(_WorldSpaceCameraPos, i.worldPos); // 使用世界空间坐标计算距离 // 计算透明度:距离小于阈值时完全不透明,超出阈值后完全透明,中间平滑过渡 col.a = saturate((_Threshold - distanceToCam) / _Threshold); return col * _Color; } ENDCG } } FallBack "Hidden/Universal Render Pipeline/FallbackError" // URP专属 fallback }
额外说明
- 如果不需要纹理,可以直接移除
_MainTex相关代码,将col初始化为_Color即可。 - 若需要更自然的过渡效果,可以将透明度计算代码替换为:
col.a = saturate(1 - smoothstep(0, _Threshold, distanceToCam));
内容的提问来源于stack exchange,提问作者Nasan
相关产品推荐
相关产品推荐

