简体   繁体   English

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

[英]How to use OpenGL orthographic projection with the depth buffer?

I've rendered a 3D scene using glFrustum() perspective mode. 我使用glFrustum()透视模式渲染了3D场景。 I then have a 2D object that I place over the 3D scene to act as a label for a particular 3D object. 然后,我将一个2D对象放在3D场景上,作为特定3D对象的标签。 I have calculated the 2D position of the 3D object using using gluProject() at which position I then place my 2D label object. 我使用gluProject()计算了3D对象的2D位置,然后放置我的2D标签对象。 The 2D label object is rendered using glOrtho() orthographic mode. 使用glOrtho()正交模式渲染2D标签对象。 This works perfectly and the 2D label object hovers over the 3D object. 这完美地工作,并且2D标签对象悬停在3D对象上。

Now, what I want to do is to give the 2D object az value so that it can be hidden behind other 3D objects in the scene using the depth buffer. 现在,我想要做的是给2D对象的az值,以便它可以使用深度缓冲区隐藏在场景中的其他3D对象后面。 I have given the 2D object az value that I know should be hidden by the depth buffer, but when I render the object it is always visible. 我已经给出了我知道应该被深度缓冲区隐藏的2D对象az值,但是当我渲染对象时它总是可见的。

So the question is, why is the 2D object still visible and not hidden? 所以问题是,为什么2D对象仍然可见而不是隐藏?

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? 这是真的,如果是这样,我如何在它们之间进行转换?

I don't want it to be transformed, instead I want it to appear as flat 2D label that always faces the camera and remains the same size on the screen at all times. 我不希望它被转换,而是我希望它看起来像是平面的2D标签,它总是面向相机,并且始终保持在屏幕上的相同尺寸。 However, if it is hidden behind something I want it to appear hidden. 但是,如果隐藏在某些东西背后,我希望它隐藏起来。

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. 要实现这一点,您需要做的是在正交投影中找到与您希望标签出现的前投影空间中的z坐标匹配的z坐标。

When you used gluProject , you got three coordinates back. 当你使用gluProject ,你有三个坐标。 The Z coordinate is important. Z坐标很重要。 What you need to do is reverse-transform the Z coordinate based on the zNear and zFar values you give to glOrtho . 您需要做的是根据您给glOrtho的zNear和zFar值反向变换Z坐标。

Pedantic note: gluProject doesn't transform the Z coordinate to window space. 迂腐: gluProject不会将Z坐标转换为窗口空间。 To do so, it would have to take the glDepthRange parameters. 为此,它必须采用glDepthRange参数。 What it really does is assume a depth range of near = 0.0 and far = 1.0. 它真正做的是假设深度范围接近= 0.0且远= 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: 所以我们的第一步是从窗口空间Z转换为规范化设备坐标(NDC)空间Z.我们使用这个简单的等式:

ndcZ = (2 * winZ) - 1

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. 这是一个无操作,因为使用正交投影,W坐标假定为1.0。 And the division by W is the difference between clip space and NDC space. W的除法是剪辑空间和NDC空间之间的差异。

clipZ = ndcZ

But we don't need clip space Z. We need pre-orthographic projection space Z (aka: camera space Z). 但是我们不需要剪辑空间Z.我们需要预拼图投影空间Z(又名:相机空间Z)。 And that requires the zNear and zFar parameters you gave to glOrtho . 这需要你给glOrtho的zNear和zFar参数。 To get to camera space, we do this: 为了获得相机空间,我们这样做:

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

And you're done. 而且你已经完成了。 Use that Z position in your rendering. 在渲染中使用Z位置。 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). 哦,并确保您的模型视图矩阵不包括Z方向上的任何变换(除非您使用模型视图矩阵将此Z位置应用于标签,这很好)。

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

cameraZ = -winZ*zFar

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM