Unity Shader之遮挡透明

发表于2018-10-17
评论0 3.5k浏览
这篇文章介绍了Unity遮挡透明渐变的实现,其中当物体遮挡住主角时,该物体会变成半透明显示出主角。这篇文章同样给大家介绍下遮挡透明的功能,不过,要借助shader要实现的是主角变成半透明,确切来说是主角被遮挡的那一部分变成半透明。

先放出结果图:  

当被遮挡时,遮挡部分透明处理,那么需要涉及渲染深度的知识。引擎是如何判断哪个物体在前面哪个物体在后面呢?

深度:每个像素有自己的深度值,离摄像机近的深度小,远的深度大
深度缓冲区:存储每个像素的深度
颜色缓冲区:存储每个像素的颜色

过程:首先比较像素的深度与深度缓冲区同一位置的深度,如果前者小于后者,则未通过深度测试;否则,通过深度测试,将前者写入后者,将该像素的颜色写入到颜色缓冲区。将颜色缓冲区像素颜色显示到屏幕上。

通过这个过程即可把深度小的像素剔除掉,将深度大的显示到屏幕上,从而实现物体的前后顺序。  
UnityShader提供了ZWrite和ZTest对应深度写入和深度测试。

调整ZWrite可以控制是否将深度写入到深度缓冲区,当然,前提是深度测试通过,如果没通过测试,那么肯定是无法写入的

调整ZTest可以定义上述中前者与后者的比较关系,默认为LEqual即小于等于时通过测试

那么可以得到一种实现思路,用两个PASS:
第一个PASS:ZTest为Greater,ZWrite为Off,当该像素被遮挡即深度大于深度缓冲区对应位置深度时执行该PASS,那么就可以在该PASS中实现被遮挡像素的效果。
第二个PASS:ZTest为LEqual,ZWrite为On,这个PASS与上述PASS是互斥的,在这个PASS中实现未被遮挡像素的效果。

设置ZWrite是为了防止两个PASS都执行,如果第一个PASS的ZWrite为On,某一像素未被遮挡时,执行第一个PASS,将像素深度写入深度缓冲区,然后轮到第二个PASS进行深度测试时也会通过,因为小于等于嘛。

被遮挡像素透明实现用了边缘光使得更炫酷。边缘光公式大概如下:
  fixed   rim=1-saturate(dot(worldNormalDir,worldViewDir));
  fixed3 finalCol=_RimColor.xyz*pow(rim,_RimPower)*_RimIntensity  

通过第一个公式可以得到一个参数rim,顶点法线方向与视角方向契合度越高则rim越小,否则rim越大,即越靠近边缘rim越大。
第二个公式中pow是为了提高边缘光硬度。

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引