2015-10-04 33 views
3

所以我最近观看了Z战的视频,并且学会了一种简单的方式来照顾它 - 主要是。给出的解决方案是实际上歪斜投影,以便为更精确的深度测试提供更多空间(因为浮点只能如此精确),并且将更远的物体塞入投影的一小部分区域。现在,我对OpenGL和图形编程还很陌生(只是慢慢地开展工作),实际上我没有做出任何足够复杂的工作,但这对我来说是个问题,但我将来可能需要知道这一点。无论如何,上述解决方案带来的新问题更加严重的是在远距离的Z-战斗(例如,天际山,铁锈山等)。是否有更好的解决方案,即使它具有性价比,也不涉及图形折衷?假设地说(因为我对OpenGL管线还不是很舒服),程序中的Z值在进行深度测试之前是否可以加倍加倍?如何避免Z距离战斗?

让我澄清。想想天际。注意山脉有时会闪烁吗?当使用OpenGL渲染场景时,所有对象都会被挤压或“夹”到Z值为-1.0到1.0的小坐标平面中。然后对每个物体进行深度测试 - 树木,雪,山脉,动物,房屋,您可以对其进行命名,以便在被其他物体覆盖时不会绘制任何物体。然而,浮点只能达到一定的精度,因此将数百个物体夹在一个小空间中不可避免地会导致某些物体具有完全相同的Z坐标,并且这两个物体在屏幕上一起闪烁,称为“Z -战斗”。我在问每个对象的深度(z-)坐标是否可以转换为双精度,以便它们具有足够的精度(值得为可忽略的一段时间使用可忽略的额外内存),以便按正确的顺序精确绘制对象,而不会相互剪切。

+0

不错的问题,但“铸造”到一个更大的类型不会自动增加细节。如果您将Pi的值存储在float中并稍后将其转换为double,则它不会自动获得更有意义的数字。 – usr2564301

+0

不会,只有在z值被强制调整之前,它们才会使z值增加一倍 - 这样当它们夹在-1.0和1.0之间时,精度就会高得多,而且不会像重复的Z值那么容易。 –

+1

您必须记住OpenGL的深度缓冲区需要为每个像素*存储深度值*。增加其保真度的唯一方法是将其深度设置为使用更多字节。 (并且请注意,一些OpenGL实现对此大小有限制。)您可能需要阅读https://www.opengl.org/archives/resources/faq/technical/depthbuffer.htm。 – usr2564301

回答

3

当使用OpenGL渲染场景时,所有对象都会被挤压或“夹”到Z值为-1.0到1.0的小坐标平面中。

这只是故事的一部分。另一部分是z以非线性方式存储:具有最高“保真度”的部分是接近Z平面的部分,保真度随着您向后移动而降低。有关公式,请参阅this page

OpenGL常见问题解答12. The Depth Buffer中讨论了这个问题12.070为什么在深度缓冲区的前端有更高的精度?12.080提出了针对不同z距离的多遍渲染。

您可以使用glGetIntegerv(GL_DEPTH_BITS, &bits);查询当前深度缓冲区大小,但(搜索后)似乎没有标准方法将其更改为使用更大(或更小)的深度。

Z战斗在遥远的物体可以通过不绘制他们作为3D对象反击。例如,如果你的例子中的山脉很远,任何视差效果都将看不见。所以在那种情况下,你可能会更好地将远处的物体拖到天空盒上。

+2

默认帧缓冲区的深度缓冲区的位深度不由GL控制,而是由操作系统控制。它是窗口的一个属性(或者任何可用的drawable),因此必须使用平台的GL接口API(如windows上的wgl,unix/X11上的glX等)来设置它。尽管如此,不要期望在普通硬件上看到超过24位(整数)的广泛支持。但是,在使用FBO时,通常可以使用32位浮点深度缓冲区。 – derhass

1

您可以解决。通常,您通过从最近到最近进行排序来一次渲染所有对象。

您可以改为根据距离分成两组,分别称为FarGroupNearGroup

如果应用程序没有一定的限制,如:

  • 你不使用模板缓存的东西
  • 你不需要特殊效果(屏幕空间环境光遮蔽,景深等深度)

您可以使用模板缓冲区来解决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

你可以通过反转渲染顺序来调整不使用模具(由于像素透支性能penality),也许你可以限制SSAO只到NearGroup,并使用烘焙AO值远的对象,但你明白了,你获得了一些东西但是你失去了做别的事情的能力(有很多解决方法来限制性能和头脑风暴的成本)。

的相机,你只安装2个不同的视锥至极只是原来的截锥2

切片如果你没有太多的限制,你可以使用上面的tecnique你既没有Z-斗争并且还比使用32位Z缓冲器更快地渲染(由于GPU的内部优化)

0

首先,一个重要细节:频繁的错误是让近平面真的太接近于零。由于z映射是非线性的,因此大部分动力学都位于最前面,并且在距离处缺失。

0

对所有几何体进行排序以绕过Z缓冲区的成本很高。 一个典型的折衷办法是将场景分为2层或3层(如前方(驾驶舱/角色/武器),近地形和远景),并为其中的每一层定制znear/zfar(将Z in之间)。