具有两个不同投影矩阵的深度缓冲区

时间:2015-07-29 05:54:43

标签: opengl matrix rendering opengl-es-2.0

我使用默认的OpenGL值,如glDepthRangef(0.0,1.0);, gldepthfunc(GL_LESS);和glClearDepthf(1.f);因为我的投影矩阵会将右手坐标更改为左手坐标。我的意思是,我的近平面和远平面z值在NDC中应该是[-1,1]。

问题是当我在包含相同RBO的一个FBO上绘制两个对象时,例如,如下面的代码,

    glEnable(GL_DEPTH_TEST);
    glClearDepthf(1.f);
    glClearColor(0.0,0.0,0.0,0.0);
    glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);

    drawObj1(); // this uses 1) the orthogonal projection below 
    drawObj2(); // this uses 2) the perspective projection below

    glDisable(GL_DEPTH_TEST);

总是,object1位于object2之上。

1)正交enter image description here

2)透视enter image description here

然而,当他们使用相同的投影时,它工作正常。

你认为我应该过哪一部分?

- 更新 -

将眼睛坐标转换为NDC到屏幕坐标,究竟发生了什么?

我的理解是因为在两个投影之后,其​​NDC形状与下面的图像相同,其乘以2)透视矩阵后的z值不必失真。然而,根据德巴斯的好答案,如果视图坐标中的z值乘以透视矩阵,则z值将在NDC中双曲线扭曲。

如果是这样,例如,如果一个顶点位置在[w:480.0,h:320.0]的眼睛(视图)坐标中是[-240.0,0.0,-100.0],我用[-0.01]剪切它,-100],在NDC中会是[-1,0,-1]还是[something> = - 1,0,-1]?它的z值仍然与-1相同,不是吗?当它的z值失真时?

1)正交enter image description here

2)观点enter image description here

1 个答案:

答案 0 :(得分:3)

您不能期望顶点的z值投影到相同的窗口空间z值,因为您对透视和正交投影矩阵使用相同的近和远值。

在预先设定的情况下,眼睛空间z值将双曲线地扭曲为NDC z值。在正交情况下,它只是过度缩放和移位。

如果你的" Obj2"只是在一个平面z_eye = const中,你可以预先计算它在透视情况下应该具有的扭曲深度。但如果它具有非零深度,则无效。我可以想出处理这种情况的不同方法:

  1. "修正"通过根据z缓冲区预期的双曲线失真调整gl_FragDepth,片段着色器中对象2的深度。

  2. 使用线性z缓冲区,也就是说。一个w buffer

  3. 这些方法在概念上是彼此相反的。在这两种情况下,您都可以使用gl_FragDepth,以便它与其他渲染过程的约定相匹配。

    <强>更新

      

    我的理解是因为在两个投影之后,它的NDC形状   与下面的图像相同,它是在乘以2)透视后的z值   矩阵不必扭曲。

    嗯,这些图像显示了从剪辑空间到NDC的转换。而这种透明化就是透视划分所遵循的投影矩阵。当它处于标准化的设备坐标中时,不会发生进一步的失真。它只是根据glDepthRange()设置线性转换为窗口空间z。

      然而,根据   如果视图坐标中的z值相乘,那么德巴斯的答案很好   通过透视矩阵,z值将是双曲线的   在NDC中扭曲。

    透视矩阵应用于完整的4D同质眼空间矢量,因此它应用于z_eye以及x_eyey_eyew_eye(通常只有1,但不必)。

    因此,透视情况的最终NDC坐标是hyberbolically扭曲到

             f + n        2 * f * n              B
    z_ndc = ------- + ----------------- = A + -------
             n - f     (n - f) * z_eye         z_eye
    

    而在正交情况下,它们只是线性转换为

             - 2              f + n    
    z_ndc = ------- z_eye - --------- = C * z_eye + D
             f - n           (f - n) 
    

    对于n=1f=10,它看起来像这样(请注意,我将范围部分绘制在平截头体之外。当然,剪切将阻止GL中出现这些值)。 plot of z_clip as function of z_eye for perspective and orthogonal projection

      

    如果是这样,例如,如果一个顶点位置为[-240.0,0.0,-100.0]   在眼睛(视图)坐标与[w:480.0,h:320.0],我剪了它   使用[-0.01,-100],它会是[-1,0,-1]还是[something&gt; = - 1,0,-1] in   NDC?它的z值仍然与-1相同,不是吗?当它的z值   被扭曲了吗?

    远处平面上的点始终转换为z_ndc=1,并指向近似平面z_ndc=-1。这就是投影矩阵的构造方式,这正是上图中两个图相交的位置。因此,对于这些微不足道的案例,不同的映射根本不重要。但对于所有其他距离,他们会。