四、开启深度写入的透明效果
对比下面两种渲染效果:
前面提到过,透明物体的渲染顺序非常重要,对于一个复杂的透明物体,若不进行网格分割,那么几乎不可能得到正确的渲染结果,就如图一
但是也有一个折中的方案,那就是使用两个 Pass 来渲染模型,第一个 Pass 开启深度写入,把所有被遮挡的片元剔除掉,第二个 Pass 正常渲染,这样就可以得到图二的效果,代码在下:
Shader "Jaihk662/AlphaTest1"
{
Properties
{
_DiffuseColor ("DiffuseColor", Color) = (1.0, 1.0, 1.0, 1.0)
_SpecularColor ("SpecularColor", Color) = (1.0, 1.0, 1.0, 1.0)
_MainTex ("MainTex", 2D) = "white" {}
_Gloss ("Gloss", Range(8.0, 256)) = 20
_AlphaScale ("AlphCutOff", Range(0, 1)) = 1
}
SubShader
{
LOD 200
Tags { "Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent"}
PASS
{
ZWrite On ColorMask 0
}
PASS
{
//和前一章代码一摸一样
}
}
FallBack "Transparent/VertexLit"
}
尽管这也不太正确,但是相对于第一个表现要好很多
- ColorMask R|G|B|A:ColorMask 可以设置任何 RGBA 组合,目的是设置颜色通道的写掩码(write mask),当 ColorMask 设定为0时,意味着该 Pass 不写入任何颜色通道
这个 Pass 为空,同等于顶点着色器和片段着色器中不进行顶点变换外的任何运算,当然它们肯定是存在的
一些重点,可以解决一些疑惑:
- 关于深度测试:如果开启了混合,那么深度测试通过后,当前片段相对当前深度值距离摄像机更远,就不再进行混合操作,否则进行混合
- 未进行优化时,每个物体的每个 Pass 都会是一次 drawcall,假设当前有4个物体应用了上面的 shader,就会有8次 drawcall
五、双面渲染
对于透明的物体,理论上是可以看到它的“内部”的,或是看到反面,就像下图的对比,右边效果更真实
这里需要提前了解的是:OpenGL基础32:面剔除
想要实现右边的效果,理论只需要关闭面剔除就可以了,但是没有那么简单,因为这个时候渲染顺序就非常重要了,如果背面(内部)后渲染,那么就会出现很明显的渲染错误,所以还需要保证背面先被渲染:
Shader "Jaihk662/AlphaTest1"
{
Properties
{
_DiffuseColor ("DiffuseColor", Color) = (1.0, 1.0, 1.0, 1.0)
_SpecularColor ("SpecularColor", Color) = (1.0, 1.0, 1.0, 1.0)
_MainTex ("MainTex", 2D) = "white" {}
_Gloss ("Gloss", Range(8.0, 256)) = 20
_AlphaScale ("AlphCutOff", Range(0, 1)) = 1
}
SubShader
{
LOD 200
Tags { "Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent"}
PASS
{
Tags { "LightMode" = "ForwardBase" }
ZWrite Off Blend SrcAlpha OneMinusSrcAlpha
Cull Front //先进行正面剔除,渲染背面
//…… 和之前一样的代码
}
PASS
{
Tags { "LightMode" = "ForwardBase" }
ZWrite Off Blend SrcAlpha OneMinusSrcAlpha
Cull Back
//…… 和之前一样的代码
}
}
FallBack "Transparent/VertexLit"
}
六、常见混合类型
本部分完全照搬于 UnityShader 入门精要
- Blend SrcAlpha OneMinusSrcAlpha:正常混合
- Blend OneMinusDstColor One:柔和相加(Soft Additive)
- Blend DstColor Zero:正片叠底(Multiply),即相乘
- Blend DstColor SrcColor:两倍相乘(2x Multiply)
- BlendOp Min Blend One One:变暗(Darken)
- BlendOp Max Blend One One:变亮(Lighten)
- Blend OneMinusDstColor One:滤色(Screen)
- Blend One One:线性减淡(Linear Dodge)