4

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

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

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

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

4

2 回答 2

10

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

首先,你应该把放在你的问题中;它比你的问题更能解释你想要做什么。

为此,您需要做的是在正投影中找到与您希望标签出现的预投影空间中的 z 坐标相匹配的 z 坐标。

当你使用 时gluProject,你得到了三个坐标。Z坐标很重要。您需要做的是根据您提供给的 zNear 和 zFar 值对 Z 坐标进行反向转换glOrtho

学究式注意: gluProject不会将 Z 坐标转换为窗口空间。为此,它必须采用glDepthRange参数。它真正做的是假设深度范围为near = 0.0 和far = 1.0。

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

ndcZ = (2 * winZ) - 1

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

clipZ = ndcZ

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

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

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

于 2012-01-24T17:52:58.973 回答
1

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

cameraZ = -winZ*zFar
于 2012-01-26T11:47:01.497 回答