Chapter8 透明效果

实现透明的方法

unity中通常使用两种方式实现透明效果

1.透明度测试(alpha test),(无法实现真正的半透明)

2.透明度混合(alpha blending)

使用深度测试,可以不考虑渲染顺序,但是使用透明度混合时,需要关闭ZWrite,关闭了深度写入

虽然透明度测试不需要关闭,但是它的机制是如果透明度不满足某个阈值(通常小于),直接舍弃该片元。

  • 为什么关闭ZWrite?

由于深度测试丢弃远处被遮挡部分,但是透明物体的机制是"可以透过并看见远处的物体"。

关闭了ZWrite,渲染顺序则成了问题。

流程

1.渲染时,会进行深度测试,如果先渲染后面的不透明b,将b写入颜色缓冲和深度缓冲;然后渲染前面的透明a,a写入颜色缓冲,会发生透明混合,显示正确。

2.如果先渲染a,进行深度测试,写入颜色缓冲,但是关闭了ZWrite,无法写入深度值,然后渲染b,写入深度值,写入颜色缓冲,b的颜色覆盖a,只能看见b。

3.半透明物体之间亦然。

Alpha Test

Unity Shader解决方案为SubShader 中的Tags

以下为透明度测试alpha test示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
SubShader{
Tags{"Queue"="AlphaTest" "IgnoreProjector" = "True" "RenderType" = "TransparentCutout"}
Pass{
Tags{"LightMode" = "ForwardBase"}
...
//alpha test
clip(texColor.a - _Cutoff);
// Equal to
// if (( exColor - _Cutoff) < 0 . 0) {
// discard; }
...
}
...
}

每块的透明度都不同,根据面板调整_Cutoff可以看出哪个更低,低的那个会直接被剔除

结果图

uTools_1660983793621

Alpha Blend

1
2
3
4
5
6
7
8
9
10
SubShader{
//alpha blend
Tags{"Queue"=/*"AlphaTest"*/"Transparent" "IgnoreProjector" = "True" "RenderType" = "TransparentCutout"}
Pass{
Tags{"LightMode" = "ForwardBase"}
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha //P170
...
}
//去掉clip

解决排序问题

一般先开启深度测试、写入,先渲染不

透明物体,然后关闭写入,对不透明物体排序,先渲染后面的物体

  • 但是仍然存在很大问题。

比如一个物体,各个部分互相遮挡,又或者多个物体,相互遮挡,而深度排序是像素级别的。

问题在于

现在开启ZWrite

1
2
3
4
5
6
 Pass{
ZWrite On
ColorMask 0//ColorMask RGB 、 A 、 0 、其他任何rgba的组合
//0表示不写入任何颜色通道,即只写入深度缓存,不输出颜色

}

新添加一个Pass通道。该Pass专门用来写入深度缓冲,并且先执行。

Pass通道中加上//Cull Front/Back/Off 需要双面渲染时关闭剔除

注意如果关闭了深度写入,此时再双面渲染就会出现半透明错误渲染