本节知识架构
1.渲染顺序与渲染队列
如果采用了透明度混合即要是实现半透明效果,那么就要关闭深度写入,那么此时渲染顺序就会变得非常非常重要,不然会出现不正确的遮挡效果。具体的分析可见书中解释
一句话概括就是因为没有写入深度,会导致之后读取的时候没有读取到深度,就可能使其被后面的东西的像素给覆盖。
为了解决渲染顺序问题,Unity中提供了渲染队列来进行排序,索引号越小越提前被渲染
我们可以在代码中加入标识来将物体放入渲染队列中
2.透明度测试
就是在xx透明度以下的片元都进行舍弃
只需要在SubShader下(作用于所有Pass)或者Pass通道下加入如下语句
Tags {"Queue"="AlphaTest" "IgnoreProjector"="True" "RenderType"="TransparentCutout"}
//Queue是命令该Shader为AlphaTest,第二个是代表忽略投影器,第三个设置RenderType为自定义的
//TransparentCutout,这个组是自己定义的名称,常常用于着色器替换来标记所要替换的Shader中的
//全部Pass或者部分Pass
在Pass中使用透明度测试的核心语句就是
// Alpha test
clip (texColor.a - _Cutoff);
// 等价于
//if ((texColor.a - _Cutoff) < 0.0) {
// discard;
//}
效果如下
3.透明度混合
想要进行混合就需要把当前需要渲染的颜色和颜色缓冲区的颜色值进行混合(即之前渲染过的颜色)因此要关闭深度写入和使用ShaderLab的混合命令
书中采用第二个命令
下面给出实现透明度混合的核心代码
首先在属性中设置引入一个变量用来控制透明度
_AlphaScale ("Alpha Scale", Range(0, 1)) = 1
然后设置Tags
Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"}
然后关闭深度写入开启混合
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
最后返回颜色的时候用Alpha Scale来控制透明度
return fixed4(ambient + diffuse, texColor.a * _AlphaScale);
只有我们开启了Blend的时候控制alpha通道的值进而控制透明度才有意义。
效果如下
但其实还是有缺点的,比如在透明玻璃后的黑线我们没有看到,但其地板后面的边界我们却看到了。
这是因为,Unity默认开启了Cull Back,剔除了背面因此看不到,我们可以使用Cull off关闭
4.开启深度写入的透明度混合
我们可以使用两个Pass,第一个Pass开启深度写入但不输出颜色,仅用来输入深度数据给ZBuffer,第二个Pass正常渲染半透明
缺点是,物体与物体之间有正确的半透明与遮挡,物体内部有正确的遮挡关系,但却没有半透明的效果 。
ColorMask可以阻止该Pass写入颜色到某一通道中,ColorMask 0代表什么都不输出
ColorMask R代表仅输入R,ColorMask往往可以用来将一个带有颜色背景的特效图片的背景去掉。具体用法可参考如下链接
https://www.cnblogs.com/jietian331/p/10675265.html
5.ShaderLab 的混合命令(背和查,没啥技术含量)
混合是将RGBA四个通道的值进行混合,必应要开启混合命令(如上),才能进行混合!!!
一句话概括就是设置4个宏来进行加法操作,而这4个宏可以查表
5.1混合等式参数
混合的时候需要两个混合等式,一个用来混合RGB通道,另一个用来混合A通道,默认情况下,混合等式使用的都是加操作。每个等式需要两个因子,所以一共需要四个因子。
若要进行其它运算
,可以使用BlendOp操作符 下图是BlendOp所支持的命令
具体使用案例如下
6.双面渲染的透明效果
一句话说,就是利用Cull的渲染,使得物体自身的背部也能背看到。
透明度测试的双面渲染:首先看下原效果
使用Cull off的透明度测试的双面渲染效果
透明度混合的双面渲染:
这个就要比透明度测试复杂一点了,因为要打开深度写入,而这又容易导致透明效果出现问题。
具体问题分析是这样的。我们想要保证图像是从后往前渲染。对于透明度测试,我们没有关闭深度写入,所以可以按像素的大小进行深度排序,从而保证渲染正确。而一旦关闭深度写入,若我们直接关闭剔除,就无法保证同一物体正面和背面的渲染顺序。
解决方法如下,双面渲染分成两个Pass,第一个Pass只渲染背面,第二个只渲染正面
原效果如下
采用了两次Pass渲染后
舒服了 。