【入门精要】008-透明效果
透明度有两种实现方法:一种是透明度测试(AlphaTest),一种是透明度混合(AlphaBlending)。
透明度测试:如果片元不满足条件,则该片元就会被舍弃。被舍弃的片元不会对颜色缓冲有任何影响。如果满足条件,则会按照普通的不透明物体来进行渲染。透明度测试不需要关闭深度写入。其结果要么完全透明,要么完全不透明。
透明度混合:实现半透明效果,需关闭深度写入。他会将当前的半透明片元与颜色缓冲中的颜色值做混合,得到新颜色。由于关闭了深度写入,需格外注意渲染顺序。虽然关闭了深度写入,但这不代表我们关闭了深度测试。当深度测试检测不透明物体在半透明物体之前,则会掩盖半透明物体。
为什么渲染顺序很重要?
因为如果我们的半透明物体被提前渲染,则会导致深度测试时,半透明物体后的不透明物体因深度测试通过而覆盖渲染结果,造成渲染的排序错误。
半透明物体,要从后往前渲染,先渲染远的,再渲染近的。

渲染顺序:
unity为了解决相关问题提供了渲染队列(Render Queue),我们可以在Tag中添加Queue标签决定物体的渲染队列。
Background(1000):在其他物体之前渲染,多用于背景。
Geometry(2000):默认渲染队列,不透明物体渲染队列。
AlphaTest(2450):需要进行透明度测试的物体的队列。
Transparent(3000):在小于3000的队列渲染完成后,从后往前渲染,用于半透明物体。
Overlay(4000):用于实现一些叠加效果,需要在最后渲染的物体的队列。
因此,如果我们想实现半透明效果,应该为shader添加如下条件:
Tags{ "Queue" = "AlphaTest" } 或 Tags{ "Queue" = "Transparent" }
ZWrite Off(关闭深度写入):关闭深度写入,用于半透明物体,常写于Pass通道内。

透明度测试:
透明度测试是CG语言中的一个函数(Clip),如果传入Clip的值中(如:float4)任何一个值小于0,则舍弃该片元,用于片元着色器中。
首先声明标签:
Tags {
"Queue" = "AlphaTest" //设置渲染队列
"RenderType"="TransparentCutout" //对应改为Cutout
"ForceNoShaderCasting"="True" //关闭阴影投射
"IgnoreProjector"="True" //不响应投射器
}
然后在Pass通道内声明标签
Tags { "LightMode"="ForwardBase" }
最后在片元着色器中添加方法:
clip(“传入的值”);
设置好合适的Fallback,即可。

透明度混合:
透明度混合和透明度测试不一样,两者可共存。
透明度混合可以实现真正的透明度效果。他会使用当前片元的透明度作混合因子,与颜色缓冲中的颜色值做混合,得到结果。但由于我们关闭了深度写入,这使得我们要格外注意排序。
为了实现效果,unity为我们提供了一个混合命令:Blend。
Blend的工作就是把当前自身的颜色与颜色缓冲中的颜色作混合,混合的方法由相应指令决定。
举例:
BlendOp Add //混合方法为Add
Blend SrcAlpha OneMinusSrcAlpha //(当前源的透明度乘以当前源颜色) 与 (一减当前源的透明度的值乘以颜色缓冲后的值) 相加
实现方法:
添加Tag:
Tags {
"Queue" = "Transparent" //修改渲染顺序
"RenderType"="Transparent" //对应改为Transparent
"ForceNoShaderCasting"="True" //关闭阴影投射
"IgnoreProjector"="True" //不响应投射器
}
关闭深度写入:
ZWrite Off
Pass通道内添加混合模式:
BlendOp [“计算方法”]
Blend [“当前源颜色”] [“深度缓冲颜色”]
设置好合适的Fallback,即可。

开启深度写入的半透明效果:
由于关闭了深度写入,造成了模型渲染排序的错误。如何解决这个问题呢?
我们可以用两个Pass通道来解决。
第一个Pass通道不渲染,开启深度写入,只输出深度值。
第二个Pass通道关闭深度写入,正常渲染。
实现方法:
Pass{
ZWrite On //开启深度写入
ColorMask 0 //当ColorMask为0时,不输出任何颜色
}
Pass{
同透明度混合;
}
设置好合适的Fallback,完成。

ShaderLab混合命令:
之前提到了Blend,现在我们来详细了解一下。
混合是如何实现的:当片元着色器产生一个颜色时,可以选择与颜色缓存中的颜色进行混合,得到混合后的结果。
Blend [源颜色x混合因子] [颜色缓存x混合因子]
命令:
Blend SrcFactor DstFactor:开启混合,源颜色乘以SrcFactor,颜色缓存乘以DstFactor,两者默认相加。
Blend SrcFactor DstFactor,SrcFactorA DstFactorA:开启混合,源颜色(rgb)乘以SrcFactor,颜色缓存(rgb)乘以DstFactor,两者默认相加。源颜色透明度(a)乘以SrcFactorA,颜色缓存透明度(a)乘以DstFactorA,两者默认相加。两者区别只是将颜色通道和透明度分开计算。
混合参数(Blend):
One:因子为1
Zero:因子为0
SrcColor:因子为源颜色值,RGB通道与A通道分开混合。
SrcAlpha:因子为源颜色的A通道。
DstColor:因子为目标颜色值,RGB通道与A通道分开混合。
DstAlpha:因子为目标颜色的A通道。
OneMinusSrcColor:因子为(1-源颜色值),RGB通道与A通道分开混合。
OneMinusSrcAlpha:因子为(1-源颜色的A通道)。
OneMinusDstColor:因子为(1-目标颜色值),RGB通道与A通道分开混合。
OneMinusDstAlpha:因子为(1-目标颜色的A通道)。
混合操作(BlendOp):
Add:将混合后的源颜色和目标颜色相加
Sub:将混合后的源颜色减去目标颜色
RevSub:将混合后的目标颜色减去源颜色
Min:取二者最小(逐分量比较取值)
Max:取二者最大(逐分量比较取值)
常见混合类型:
Blend SrcAlpha OneMinusSrcAlpha:正常的透明度混合
Blend OneMinusDstColor One:柔和相加
Blend DstColor Zero:正片叠底
Blend DstColor SrcColor:两倍相乘
Blend One One(BlendOp Min):变暗
Blend One One(BlendOp Max):变亮
Blend OneMinusDstColor One:滤色
Blend One OneMinusSrcColor:滤色
Blend One One:线性减淡

双面渲染:
大多渲染情况下,我们只渲染了物体正面。而想要渲染反面,或者两面都渲染,则需要使用Cull指令来完成。
Cull有三种指令:Front(剔除正面)、Back(剔除反面)、Off(不剔除)
使用方法同Blend,如
Cull Off
即可。