所以我最近观看了一个关于Z战斗的视频,并且学会了一种简单的方法来处理它 - 主要是。给出的解决方案是实际倾斜投影,以便为更近的物体提供更多空间以进行更精确的深度测试(因为浮体只能如此精确),并且更远的物体被塞入投影的小区域。现在我对OpenGL和图形编程都很陌生(只是慢慢地工作),而且我实际上没有做任何复杂的事情,这对我来说是一个问题,但我可能需要在将来知道这一点。无论如何,所述解决方案所带来的新问题是在远处进行更糟糕的Z战斗(例如天际,鲁斯特等山脉)。有没有更好的解决方案,即使它具有成本效益,也不涉及图形妥协?假设说(因为我对OpenGL管道并不完全熟悉),程序中的Z值是否可以在被钳制进行深度测试之前被加倍?
让我澄清一下。想想天际。注意山有时会闪烁吗?当使用OpenGL渲染场景时,所有对象都被填充或“钳制”到Z值为-1.0到1.0的小坐标平面中。然后对每个物体进行深度测试 - 树木,雪,山脉,动物,房屋,你可以命名它,这样当它们被其他东西覆盖时就不会画出东西。然而,浮点只能达到一定的精度水平,因此将数百个物体夹入一个微小的空间不可避免地导致一些物体具有完全相同的Z坐标,并且这两个物体在屏幕上闪烁在一起,称为“Z” -战斗”。我问的是,每个物体的深度(z-)坐标是否可以投射成双精度,这样它们就具有足够的精度(值得在可忽略的时间段内使用的可忽略的额外记忆),以便以正确的顺序准确地绘制物体,没有夹在一起。
答案 0 :(得分:5)
当使用OpenGL渲染场景时,所有对象都被塞满,或者被夹住"进入一个小坐标平面,Z值从-1.0到1.0。
这只是故事的一部分。另一部分是z
非线性存储:具有最高保真度的部分&#39}。是靠近Z平面的,当您向后行进时,保真度会降低。有关公式,请参阅this page。
OpenGL常见问题解答12. The Depth Buffer在 12.070讨论了这个问题为什么深度缓冲区前面有更多精度?, 12.080 建议多次渲染不同的z距离。
您可以使用glGetIntegerv(GL_DEPTH_BITS, &bits);
查询当前深度缓冲区大小,但(搜索后)似乎没有标准方法可以将其更改为使用更大(或更小)的深度。
远距离物体中的Z战斗可以通过不将它们绘制为3D物体来抵消。例如,如果你的例子中的山脉很远,任何视差效果都是不可见的。因此,在这种情况下,将远处的物体绘制到天空盒上可能会更好。
答案 1 :(得分:2)
您可以解决方法。通常,您可以通过从最近到最近的分类来一次性渲染所有对象。
您可以根据距离将两组中的对象分开,称之为FarGroup
和NearGroup
。
如果您的申请没有某些限制,例如:
您可以使用模板缓冲区解决Z-fight问题。
您设置了模板功能,以便每个绘制的对象设置一点
glStencilOp(GL_KEEP,GL_KEEP, GL_INCR);
glStencilFunc( GL_ALWAYS, 1, 0x01);
然后渲染NearGroup
设置仅在模板位未设置的情况下绘制的模板测试
glStencilOp(GL_KEEP,GL_KEEP, GL_KEEP);
glStencilFunc( GL_NOTEQUAL, 1, 0x01);
渲染FarGroup
您可以通过反转渲染顺序以不使用模板(由于像素过度绘制导致的性能阴影)进行调整,也许您可以将SSAO仅限制为NearGroup
并对远端对象使用烘焙的AO值,但是您可以获得想法,你获得了一些东西,但你失去了做其他事情的能力(有很多变通方法可以限制性能和一些头脑风暴)。
对于相机,你只需设置2个不同的截头体,它们只是在2中切割的原始截头体。
如果您没有太多约束并且您能够使用上述技术,那么与使用32位Z缓冲区(由于GPU的内部优化)相比,您无需进行z-fight和更快的渲染
答案 2 :(得分:1)
首先,一个重要的细节:一个常见的错误是让近平面真的太接近于零。由于z映射是非线性的,因此大多数动力学都在最前面并且在距离处缺失。
答案 3 :(得分:1)
对所有几何体进行排序以绕过Z缓冲区的成本很高。 经典的折衷方案是将场景分成2或3个大层(如前面(驾驶舱/角色/武器),近距离地形和远距离景观),并为每个场景定制znear / zfar(重置Z之间) )。