如何将 OpenGL 正交投影与深度缓冲区一起使用?
我使用 glFrustum()
透视模式渲染了 3D 场景。然后,我将一个 2D 对象放置在 3D 场景上,作为特定 3D 对象的标签。我使用 gluProject() 计算了 3D 对象的 2D 位置,然后在该位置放置 2D 标签对象。 2D 标签对象使用 glOrtho()
正交模式渲染。这工作得很好,2D 标签对象悬停在 3D 对象上。
现在,我想做的是给 2D 对象 az 值,以便可以使用深度缓冲区将其隐藏在场景中其他 3D 对象后面。我已经给出了 2D 对象 az 值,我知道该值应该被深度缓冲区隐藏,但是当我渲染该对象时,它始终可见。
那么问题来了,为什么2D对象仍然可见而不是隐藏呢?
我确实在某处读到正交投影和透视投影存储不兼容的深度缓冲区值。这是真的吗?如果是,我该如何在它们之间进行转换?
I've rendered a 3D scene using glFrustum()
perspective mode. I then have a 2D object that I place over the 3D scene to act as a label for a particular 3D object. I have calculated the 2D position of the 3D object using using gluProject()
at which position I then place my 2D label object. The 2D label object is rendered using glOrtho()
orthographic mode. This works perfectly and the 2D label object hovers over the 3D object.
Now, what I want to do is to give the 2D object a z value so that it can be hidden behind other 3D objects in the scene using the depth buffer. I have given the 2D object a z value that I know should be hidden by the depth buffer, but when I render the object it is always visible.
So the question is, why is the 2D object still visible and not hidden?
I did read somewhere that orthographic and perspective projections store incompatible depth buffer values. Is this true, and if so how do I convert between them?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
首先,您应该将那个放入您的问题中;它比你的问题更能解释你想要做什么。
为此,您需要做的是在正交投影中找到与您希望标签出现的位置的预投影空间中的 z 坐标相匹配的 z 坐标。
当您使用
gluProject
时,您得到了三个坐标。 Z 坐标很重要。您需要做的是根据您为glOrtho
提供的 zNear 和 zFar 值对 Z 坐标进行反向变换。迂腐的注释:
gluProject
不会将 Z 坐标转换为窗口空间。为此,它必须采用glDepthRange
参数。它真正做的是假设深度范围近 = 0.0 和远 = 1.0。因此,我们的第一步是从窗口空间 Z 转换到标准化设备坐标 (NDC) 空间 Z。我们使用这个简单的方程:
足够简单。现在,我们需要进入剪辑空间。这是一个空操作,因为在正交投影中,W 坐标被假定为 1.0。除以W就是剪辑空间和NDC空间的差。
但我们不需要剪辑空间 Z。我们需要预正交投影空间 Z(又名:相机空间 Z)。这需要您为
glOrtho
提供的 zNear 和 zFar 参数。为了进入相机空间,我们这样做:然后你就完成了。在渲染中使用该 Z 位置。哦,并确保您的模型视图矩阵不包含 Z 方向上的任何变换(除非您使用模型视图矩阵将此 Z 位置应用于标签,这很好)。
First, you should have put that in your question; it explains far more about what you're trying to do than your question.
To achieve this, what you need to do is find the z-coordinate in the orthographic projection that matches the z-coordinate in pre-projective space of where you want the label to appear.
When you used
gluProject
, you got three coordinates back. The Z coordinate is important. What you need to do is reverse-transform the Z coordinate based on the zNear and zFar values you give toglOrtho
.Pedantic note:
gluProject
doesn't transform the Z coordinate to window space. To do so, it would have to take theglDepthRange
parameters. What it really does is assume a depth range of near = 0.0 and far = 1.0.So our first step is to transform from window space Z to normalized device coordinate (NDC) space Z. We use this simple equation:
Simple enough. Now, we need to go to clip space. Which is a no-op, because with an orthographic projection, the W coordinate is assumed to be 1.0. And the division by W is the difference between clip space and NDC space.
But we don't need clip space Z. We need pre-orthographic projection space Z (aka: camera space Z). And that requires the zNear and zFar parameters you gave to
glOrtho
. To get to camera space, we do this:And you're done. Use that Z position in your rendering. Oh, and make sure your modelview matrix doesn't include any transforms in the Z direction (unless you're using the modelview matrix to apply this Z position to the label, which is fine).
根据 Nicol 的回答,您可以简单地将 zNear 设置为 0(这通常对于充当 GUI 一部分的 2D 元素有意义),然后您只需:
Based on Nicol's answer you can simply set zNear to 0 (which generally makes sense for 2D elements that are acting as part of the GUI) and then you simply have: