我使用glFrustum()
透视模式渲染了3D场景。然后,我将一个2D对象放在3D场景上,作为特定3D对象的标签。我使用gluProject()
计算了3D对象的2D位置,然后放置了我的2D标签对象。使用glOrtho()
正交模式渲染2D标签对象。这完美地工作,2D标签对象悬停在3D对象上。
现在,我想要做的是给2D对象一个z值,以便它可以使用深度缓冲区隐藏在场景中的其他3D对象后面。我给2D对象一个z值,我知道它应该被深度缓冲区隐藏,但是当我渲染对象时它总是可见的。
所以问题是,为什么2D对象仍然可见而不是隐藏?
我确实在某处读过正交和透视投影存储不兼容的深度缓冲值。这是真的,如果是这样,我如何在它们之间进行转换?
答案 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