如果要渲染半透明物体,那么就需要用到透明度混合。
需要注意的有这几点:
1.设置标签:Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"}
将物体放在合适的渲染队列中
2.关闭深度写入:ZWrite Off
具体原因见下面
3.Blend混合命令:Blend SrcAlpha OneMinusSrcAlpha
意思是:最终颜色 = 源颜色(该像素颜色) * SrcAlpha + 目标颜色(颜色缓冲中的颜色) * (1 - SrcAlpha)
AlphaBlend.shader
1 Shader "Custom/AlphaBlend" 2 { 3 Properties 4 { 5 _MainTex ("Texture", 2D) = "white" {} 6 _AlphaScale ("Alpha Scale", Range(0, 1)) = 1 7 } 8 SubShader 9 { 10 Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"} 11 12 Pass 13 { 14 ZWrite Off 15 Blend SrcAlpha OneMinusSrcAlpha 16 17 CGPROGRAM 18 #pragma vertex vert 19 #pragma fragment frag 20 21 #include "UnityCG.cginc" 22 23 struct appdata 24 { 25 float4 vertex : POSITION; 26 float2 uv : TEXCOORD0; 27 }; 28 29 struct v2f 30 { 31 float2 uv : TEXCOORD0; 32 float4 vertex : SV_POSITION; 33 }; 34 35 sampler2D _MainTex; 36 float4 _MainTex_ST; 37 fixed _AlphaScale; 38 39 v2f vert (appdata v) 40 { 41 v2f o; 42 o.vertex = mul(UNITY_MATRIX_MVP, v.vertex); 43 o.uv = TRANSFORM_TEX(v.uv, _MainTex); 44 return o; 45 } 46 47 fixed4 frag (v2f i) : SV_Target 48 { 49 fixed4 col = tex2D(_MainTex, i.uv); 50 col.a = col.a * _AlphaScale; 51 return col; 52 } 53 ENDCG 54 } 55 } 56 }
效果如下:
那么,回到问题,为什么进行透明度混合时要关闭深度写入呢?
可以做些测试:
1.在上图的基础上,白色物体开启深度写入,会发现没任何变化。因为红色物体先渲染,白色物体后渲染,即使开启深度写入,由于后面没有其他物体要渲染了,也就不会影响后面的深度测试
2.在白色物体和红色物体之间放一个灰色物体,其shader复制上面的,然后修改渲染队列为"Transparent+1",白色物体关闭深度写入。可以看到,效果还是正常的
3.白色物体开启深度写入,如下图,这时效果就不对了。渲染顺序为:红色->白色->灰色,当渲染灰色物体时,不能通过深度测试,导致重叠的那部分像素被舍弃掉
因此,进行透明度混合时要关闭深度写入,从而让比半透明物体还要后渲染的物体能正确地显示出来。不过因为关闭深度写入,会破坏深度缓冲的工作机制,在某些十分特殊的情况(如自身重叠交叉的半透明物体)下会出现遮挡错误的问题