目标:两个cube,cube1在前,默认不透明白色,cube2在后,蓝色,部分被cube1遮挡
被遮挡部分也要显示,并显示为绿色
如下图:

一步一步来,我们先实现被遮挡部分能显示
Shader代码:

Shader "Custom/TestZwriteAlpha" { Properties{ _MainColor("Main Color", color) = (0,0,1,0.3) _OutColor("Out Color", color) = (1,1,0,0.5) } SubShader { Tags{"queue" = "transparent"} pass { blend srcalpha oneminu***calpha ztest greater //1. zwrite on //2. CGPROGRAM #pragma vertex vert #pragma fragment frag #include "unitycg.cginc" fixed4 _MainColor; fixed4 _OutColor; struct v2f { float4 pos:POSITION; }; v2f vert(appdata_base v) { v2f o; o.pos = mul(UNITY_MATRIX_MVP, v.vertex); return o; } fixed4 frag(v2f IN):COLOR { return _OutColor; } ENDCG } }}

效果如下图:

如图,只有被遮挡的地方显示出来了,没被遮挡的地方不见了。
先看显示出来的部分
先看这一句

zwrite on //2.

查看官方文档:点击查看

是否写入深度缓冲区,默认是on,所以这句这里不写也是一样的。

ztest greater //1.

实现这个效果就在这一句,深度测试
看看unity官方文档里怎么说的:点击查看

Less小于,Greater大于,LEqual小于等于,GEqual大于等于,Equal等于,NotEqual不等于,Always总是
默认是LEqual小于等于,解释是绘制距离小于等于此物体的物体,在此物体后面的被遮挡隐藏
也就是说默认情况下,只绘制能挡住它的物体以及它本身不被挡住的部分,而被它挡住的物体不绘制。
而本例用了ztest greater,大于
那就是相反的,只绘制它被挡住的部分,且在fragment中返回了一个绿色的_OutColor,
所以就出现了上图的效果,没有被遮挡的部分就不会被绘制,也就消失不见了。
那么,为了能让没有被遮挡的部分也能显示,显然要再加一个pass通道

pass { blend srcalpha oneminu***calpha ztest less //3. zwrite on CGPROGRAM #pragma vertex vert #pragma fragment frag #include "unitycg.cginc" fixed4 _MainColor; fixed4 _OutColor; struct v2f { float4 pos:POSITION; }; v2f vert(appdata_base v) { v2f o; o.pos = mul(UNITY_MATRIX_MVP, v.vertex); return o; } fixed4 frag(v2f IN) :COLOR { return _MainColor; } ENDCG }

注意,这里用了

ztest less //3.

如上所述,把该物体没被遮挡的部分也绘制出来,使用_MainColor,即我们给的蓝色。