透明效果
在实时渲染中,实现透明效果需要控制模型的透明通道(Alpha Channel)。Unity中通常使用两种方法来控制透明效果:一种是透明度测试(Alpha Test),它其实无法得到真正的半透明效果;另一种是透明度混合(Alpha Blending)。
两种方法的基本原理如下:
- 透明度测试:采用极端机制,如果一个片元的透明度不符合条件(通常是小于某个阈值),对应片元会直接被舍弃;符合条件就会按照不透明物体去处理。即这种方式得到的结果只有完全透明(看不到)和完全不透明的物体。
- 透明度混合:使用透明度与颜色值混合。它需要关闭深度写入(但没有关闭深度测试),即仍然会在深度值不符合条件时不渲染这个片元,但不会更新深度值。对于透明度混合来说,深度值是只读的。
对于不透明物体来说,深度缓存使得渲染顺序可以不被考虑。但如果加入透明效果,情况就会变得复杂。透明度测试不需要关闭深度写入(Zwrite),而透明度混合需要。
关于渲染顺序
使用透明度混合,渲染顺序会对结果产生影响(无论是透明与不透明物体还是两个透明物体)。
渲染引擎会先进行排序:
- 先渲染所有不透明物体,并开启深度测试和深度写入。
- 把半透明物体按照距离摄像机远近进行排序,从后往前渲染。
但半透明物体的排序也会遇到很多问题,比如循环重叠等情况。在Unity中,解决这一问题需要使用渲染队列(Render queue)。使用Subshader中的Queue标签来声明模型将归于哪个渲染队列,每个队列用整数索引号表示其渲染顺序,索引号越小则越早渲染。Unity提前定义了5个队列,在它们中间也可以自定义新的队列:
透明度测试的写法:
SubShader {
Tags {
"Queue"="AlphaTest" }
Pass {
...
}
}
透明度混合的写法:
SubShader {
Tags {
"Queue"="Transparent" }
Pass {
ZWrite Off
...
}
}
透明度测试
透明度测试采用极端机制,如果一个片元的透明度不符合条件(通常是小于某个阈值),对应片元会直接被舍弃;符合条件就会按照不透明物体去处理。即这种方式得到的结果只有完全透明(看不到)和完全不透明的物体。
通常会在片元着色器中使用clip函数来进行透明度测试。当传入clip的参数有任意分量为负,则舍弃当前像素的输出颜色。
在属性中定义:
Properties
{
_Color ("Main Tint", Color) = (1,1,1,1)
_MainTex ("Main Tex", 2D) = "white" {
}
_Cutoff ("Alpha Cutoff", Range(0, 1)) = 0.5