如何使用深度缓冲区的OpenGL正交投影?

时间:2012-01-24 16:51:15

标签: opengl buffer depth orthographic

我使用glFrustum()透视模式渲染了3D场景。然后,我将一个2D对象放在3D场景上,作为特定3D对象的标签。我使用gluProject()计算了3D对象的2D位置,然后放置了我的2D标签对象。使用glOrtho()正交模式渲染2D标签对象。这完美地工作,2D标签对象悬停在3D对象上。

现在,我想要做的是给2D对象一个z值,以便它可以使用深度缓冲区隐藏在场景中的其他3D对象后面。我给2D对象一个z值,我知道它应该被深度缓冲区隐藏,但是当我渲染对象时它总是可见的。

所以问题是,为什么2D对象仍然可见而不是隐藏?

我确实在某处读过正交和透视投影存储不兼容的深度缓冲值。这是真的,如果是这样,我如何在它们之间进行转换?

2 个答案:

答案 0 :(得分:10)

  

我不希望它被转换,而是希望它显示为始终面向相机的平面2D标签,并始终在屏幕上保持相同的大小。但是,如果隐藏在某些东西后面,我希望它隐藏起来。

首先,你应该在你的问题中加上 ;它解释了你所做的比你的问题更多的事情。

要实现这一点,您需要做的是在正投影中找到与您希望标签出现的前投影空间中的z坐标匹配的z坐标。

当您使用gluProject时,您会返回三个坐标。 Z坐标很重要。您需要做的是根据您给glOrtho的zNear和zFar值反向变换Z坐标。

迂腐音符: gluProject不会将Z坐标转换为窗口空间。为此,必须采用glDepthRange参数。它真正做的是假设深度范围接近= 0.0且远= 1.0。

所以我们的第一步是从窗口空间Z转换为规范化设备坐标(NDC)空间Z.我们使用这个简单的等式:

ndcZ = (2 * winZ) - 1

足够简单。现在,我们需要去剪辑空间。这是一个无操作,因为使用正交投影,W坐标假定为1.0。而除以W是剪辑空间和NDC空间之间的差异。

clipZ = ndcZ

但我们不需要剪辑空间Z.我们需要预正投影空间Z(又名:相机空间Z)。这需要您为glOrtho提供的zNear和zFar参数。为了获得相机空间,我们这样做:

cameraZ = ((clipZ + (zFar + zNear)/(zFar - zNear)) * (zFar - zNear))/-2

你已经完成了。在渲染中使用Z位置。哦,并确保您的模型视图矩阵不包括Z方向上的任何变换(除非您使用模型视图矩阵将此Z位置应用于标签,这很好)。

答案 1 :(得分:1)

根据Nicol的回答,您可以简单地将zNear设置为0(这通常对于作为GUI一部分的2D元素有意义),然后您只需:

cameraZ = -winZ*zFar