透明渲染:渲染模型时控制它的透明通道(Alpha Channel)
- 透明度测试(Alpha Test)全透明/不透明:不需关闭深度写入(ZWrite),根据透明度来舍弃片元。
- 透明度混合(Alpha Blending)可半透明:关闭深度写入(不关闭深度测试,还是会比较j,从而决定是否混合)用片元的透明度作为混合因子,与颜色缓冲中的颜色值进行混合。
对不透明(opaque)物体,由于深度缓冲(depth buffer,z-buffer),不考虑渲染顺序也能得到正确的排序效果。
深度缓冲:渲染一个片元时,把它的深度值(视锥空间中距离摄像机的距离,范围0-1)和深度缓冲中的值进行比较(如开启深度测试ZTest),通过测试(深度值距离摄像机),则这个片元应该覆盖掉此时颜色缓冲中的像素值,并更新它的深度值到深度缓冲(如果开启了深度写入)。(不开的话,深度缓冲中的值就是只读的)。
关闭深度写入原因:否则测试成功就会写入颜色缓冲区,不进行颜色混合。
渲染顺序:A(黄色)是半透明物体,B(紫色)是不透明物体
透明与不透明物体之间:不透明物体渲染完之后再渲染半透明物体。
- 先B。不透明物体开启了深度测试,此时深度缓冲中没有任何有效数据,因此B首先会写入颜色缓冲和深度缓冲。随后渲染A,透明物体深度测试通过,用A的透明度和颜色缓冲中的B的颜色混合。
- 先A。渲染A时,深度缓冲区中没有数据,A直接写入,但关闭了深度写入不会修改深度缓冲。渲染B时,B进行深度测试写入深度缓存,结果B直接覆盖A的颜色。
半透明物体之间:从后往前
- 先B。B正常写入颜色缓冲,A与颜色缓冲中的B颜色进行混合。
- 先A。混合结果相反,看起来就像B在A的前面。
渲染引擎一般都会先对物体进行排序,再渲染。
常用方法:
1、先渲染所有不透明物体,开启它们的深度测试和深度写入。
2、把半透明物体按它们距离摄像机的远近进行排序,按照从后往前的顺序渲染,开启它们的深度测试,关闭深度写入。
但循环重叠的半透明物体会无法得到正确的半透明效果。
这里的问题是:如何排序?
红色点分别标明了网格上距离摄像机最近的点、最远的点以及网格中点,每个点的深度值可能都不同,选择哪个深度值在某些情况下半透明物体之间一定会出现错误的遮挡问题,解决方法:分割网格。
为减少错误排序的情况,尽可能让模型是凸面体,将复杂的模型拆分成可以独立排序的多个子模型。就算排序错误结果也不会非常糟糕。如果不想分割网格,可以试着让透明通道更加柔和,使穿插看起来并不是那么明显。也可以使用开启了深度写入的半透明效果来近似模拟物体的半透明。
Unity中的渲染排序(Unity已经提供了很好地渲染顺序解决方案,我们拿来用就行了~)
Unity提供了渲染队列(render queue)解决渲染顺序的问题。SubShader的Queue标签决定模型归于哪个渲染队列。
Unity内部用一系列整数索引来表示每个渲染队列,越小表示越早被渲染。
Unity提前定义了5个渲染队列(也可以自定义)。