两种透明模式:
1.透明度测试,2.透明度混合
透明度测试不能实现半透,只会删除一些片元,看上去像镂空一些面
渲染顺序:
1 | //需要半透 |
上面的相关参数请参照: 这篇文章的Queue和RenderType部分
透明度测试
没什么好讲的,根据条件(比如texcolor.a是否>参数)调用 clip() discard()丢弃片元
透明度混合
书中讲了3种方法,实现了三种效果:
- 单面的半透明[虽然有透明效果,但是未显示背面颜色]
模型交叉时会出错
开启深度写入的单面半透明[模型交叉时,摄像机后方的被遮蔽]
双面渲染的透明[解决单面的半透明看不到底下颜色的问题]
重要命令:Blend
在解释代码前需要了解此命令
请参照: 这篇文章 的Blend部分
实现原理解析
1. 单面渲染
关闭ZWrite,根据Output = SrcAlpha SrcColor + (1-SrcAlpha) DstColor 计算颜色。
计算颜色与之前计算光不同的是,此处color.a为材质上此像素的a,乘以输入的透明度放大系数。
但是由于ZWrite的关闭,有些交叉的模型会出现显示错误1
2
3
4
5
6
7
8
9
10
11
12
13
14Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"}
Pass {
Tags { "LightMode"="ForwardBase" }
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
……
fixed4 frag(v2f i) : SV_Target {
……
return fixed4(ambient + diffuse, texColor.a * _AlphaScale);
}
}
2. 开启深度写入
上者说到显示有错,修改方案为:使用两个Pass,第一个参数开启ZWrite,让其对深度排序,第二个Pass在混合时可以按照之前的深度排序进行透明渲染。
shader重要修改如下1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17SubShader {
Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"}
// Extra pass that renders to depth buffer only
Pass {
ZWrite On
ColorMask 0
}
Pass {
Tags { "LightMode"="ForwardBase" }
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
……
}
}
3.双面渲染
解决方案为使用两个Pass,一个Pass只渲染背面,第二个只渲染正面,由此保证正面在背面之后渲染。实现方式第一个Pass中Cull Front 第二个Cull Back
交叉的模型仍然会出现问题,但是可以解决单面不显示背面颜色的问题。
然而以上三种方法以及合并深度写入与双面渲染,在两个透明物体有部分重叠的时候,都分别有各自不合理之处,详见:三种透明度混合各自的bug 文档