不透明物体
渲染不透明物体时,即使不去考虑不透明的物体Opaque之间的渲染顺序,也可以得到正确的渲染结果,是由于强大的深度缓冲Depth Buffer/Z-Buffer的存在,深度缓冲用于解决片元可见性问题,即物体哪些部分被渲染在前面,哪些部分被遮挡
-
深度缓冲的基本思想是根据深度缓存中的值来判断当前片元距离摄像机距离的远近,当进行一个片元的渲染时,需要把它的深度值和当前已经存在的深度缓存中的值进行比较(如果开启了深度测试ZTest On)
-
如果它的值距离摄像机的距离更远,则说明它不能被渲染到屏幕上将被舍弃;
-
如果它的值相比已存在的深度缓存中的深度值距离摄像机的距离较小,则说明它距离摄像机距离更近,这个片元便会覆盖掉此时颜色缓冲中的像素值,并把它的深度值更新到深度缓存中(如果开启了深度写入ZWrite On)
透明物体
渲染透明物体时,不仅要关注渲染图元上每个片元的颜色值和深度值,还要关注每个片元的透明度属性,通常有两种方式实现,透明度测试Alpha Test以及透明度混合Alpha Blending
-
透明度测试Alpha Test,使用透明度测试时,根据透明度来舍弃一些片元,不需要关闭深度写入,但是,渲染出来的效果很极端,不能渲染出真正的透明效果
-
透明度混合Alpha Blending,使用时需要关闭深度写入ZWrite Off,所以透明度混合时,渲染顺序十分重要,而且不透明物体之间的渲染顺序也需要正确设置
所以渲染引擎一般都会先对物体排序后再进行渲染,先渲染所有不透明物体,开启它们的深度测试和深度写入;再把半透明物体按距离摄像机的远近进行排序,由远及近的顺序渲染这些半透明的物体,开启深度测试但是关闭深度写入
Unity Shader的渲染顺序
在SubShader中使用“Queue”标签来控制渲染顺序,指定此时渲染的物体属于哪一个渲染队列,Unity在内部使用一系列的整数索引来表示每个渲染队列,索引数越小就越早渲染
渲染队列包括的值有:
- Background:1000。这种类型的顺序会排在所有物体的前面。例如天空盒。
- Geometry:2000。所有不透明物体及大多数物体使用这个类型。
- AlphaTest:2450。使用Alpha Test的物体使用这个类型的渲染顺序。它被排在不透明物体的渲染后面。
- Transparent:3000。排在Geometry和AlphaTest后渲染。所有alpha混合的物体都应该选择这个类型。
- Overlay:4000。这一类是最后渲染的,比前面所有类型都要置后,例如镜头光晕。
- 用户自定义值:比如”Queue”=”Geometry+10”。
例需要使用透明度测试实现透明效果:
SubShader{
Tags{"Queue" = "AlphaTest"
"IgnoreProjector" = "True"
"RenderType" = "TransparentCutout"
}
Pass{
Tags{"LightMode" = "ForwardBase"}
//code elide
}
}
例通过透明度混合实现透明效果:
SubShader{
Tags{"Queue" = "Transparent"
"IgnoreProjector" = "True"
"RenderType" = "Transparent"
}
Pass{
Tags{"LightMode" = "ForwardBase"}
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
//code elide
}
}
透明度测试Alpha Test
一般在片元着色器中使用clip函数来进行透明度测试,只要一个片元的透明度不满足条件(小于某个阈值),那么这个片元就会被舍弃,处理透明度测试时的操作跟对待普通不透明的物体几乎是一样的,只是透明度测试在片元着色器中增加了对透明度判断并裁剪片元的代码
clip函数是CG中的一个函数:
void clip(float4 x){
if(any(x < 0>)){
discard;
}
}
透明度混合Alpha Blending
使用Unity提供的Blend混合命令 Blend SrcFactor DstFactor 开启混合,并设置混合因子,源颜色(片元产生的颜色)乘以SrcFactor,目标颜色(颜色缓冲中的颜色)乘以DstFactor,两者相加后在存入颜色缓冲中
Blend SrcAlpha OneMinusSrcAlpha
使用透明度混合必须要开启Blend,只有开启了Blend命令,在片元着色器中设置的透明通道才有意义,未开启Blend命令的话,设置的透明度将对片元的透明效果没有任何影响。
透明度混合的Shader代码和透明度测试的代码也几乎一样,只是移除了该片元着色器中的透明度判断、裁剪片元代码,设置了该片元着色器中的透明通道(纹理像素的透明通道和参数_AlphaScale的乘积)
REF
文档:
https://docs.unity3d.com/Manual/class-RenderTexture.html
书籍:
OpenGL宝典、Unity Shader入门