更深层次的深度测试(由混合所引出)
。。这个blog标题有点长 =_=
学习混合的时候,偶然发现了深度测试存在的一些问题(也可以说是特性)。经过google之后明白了问题所在,对深度测试也有了进一步的了解。
如上所示,在进行混合的时候,发现有一些本该因为透明度混合出现的窗却没有出现,进一步观察又会发现,有的透明度混合窗口却照常出现。
结合前面的知识,我们可以联想到,这是开启了深度测试的结果。
在OpenGL中,物体的绘制顺序是无序的。现在,我们不妨假设第一个窗口的深度是80,最后一个窗口的深度是100(并非值),并且先假设渲染第一个窗口:
z-buffer初始化为1.0, 第一个窗口的z-value小于1.0,此时Z-Write会将第一个窗口的depth-value(z-value)自动写入Z-Buffer(也称depth buffer),之后根据Z-Buffer渲染像素点。
接下来渲染第二个窗口,此时因为第二个窗口的z-value大于第一个窗口,所以Z-Write并不会将其深度值写入Z-Buffer之中,也就不会去渲染它(即深度测试失败)。
这就是上述情况出现的原因,当然,实际渲染由于是无序的,所以有时候我们可以看到窗口后面的窗口,有时候又看不到。
如何解决这种情况呢?能不能把深度测试关了? 显然不能,对于一些不透明的物体,深度测试还是很有必要的。
因此我们从根源入手,可以考虑对半透明物体的渲染顺序根据Z-value从大到小进行排序,也就是先渲染后面的物体,再渲染前面的物体,由于深度测试不能一次比较多个(三个以上)物体,我们可以很顺利的将所有半透明物体在不受深度测试的影响下都绘画出来。
还有一种方法,便是渲染半透明物体的时候,关闭深度写入(深度缓冲先全初始化为1),这样子也可以达到绘制所有物体的目的。
PS:如果物体深度之间有重叠的话,有些渲染顺序会有误(排序无用),这个时候关闭深度写入,会使得渲染错误影响小很多。
因此对于场景中的多个不透明物体和半透明物体,渲染顺序是:
- 先渲染不透明物体
- 根据Z值对半透明物体进行排序
- 渲染半透明物体
参考:
[1]Milo Yip的回答
[2]王滕昊的回答