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

A Depth buffer with two different projection matrices

我正在使用默认的 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) 正交

2)视角

但是,当他们使用相同的投影时,无论它是什么,它都可以正常工作。

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

--已更新--

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

我的理解是因为两次投影后,它的NDC形状和下图一样,它乘以2)透视矩阵后的z值不必扭曲。但是,根据 derbass 的好回答,如果将视图坐标中的 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) 正交

2)透视

您不能期望您的顶点的 z 值投影到相同的 window space z 值只是因为您对透视和正交使用相同的近距和远距值投影矩阵。

在预设情况下,眼睛space z 值将双曲线扭曲为NDC z 值。在正交情况下,它只是线性缩放和移动。

如果你的 "Obj2" 正好位于一个平面上 z_eye=const,你可以预先计算它在透视情况下应该具有的扭曲深度。但如果它的深度范围不为零,这将不起作用。我可以想到不同的方法来处理这种情况:

  1. "Fix" 片段着色器中对象二的深度,方法是根据您的 z 缓冲区预期的双曲线失真调整 gl_FragDepth

  2. 使用线性 z 缓冲区,又名。 w buffer.

这些方法在概念上是彼此相反的。在这两种情况下,您都使用 gl_FragDepth 来匹配其他渲染通道的约定。

更新

My understanding is because after both of projections, its NDC shape is same as images below, its z-value after multiplying 2) perspective matrix doesn't have to be distorted.

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

However, according to the derbass's good answer, if z-value in the view coordinate is multiplied by the perspective matrix, the z-value would be hyperbolically distorted in NDC.

透视矩阵应用于完整的 4D 同质眼睛 space 矢量,因此它应用于 z_eye 以及 x_eyey_eye 以及w_eye(通常只有 1,但不是必须的)。

因此透视案例的结果 NDC 坐标被双曲线扭曲为

         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 中) .

If so, if one vertex position, for example, is [-240.0, 0.0, -100.0] in the eye(view) coordinate with [w:480.0,h:320.0], and I clipped it with [-0.01,-100], would it be [-1,0,-1] or [something>=-1,0,-1] in NDC ? And its z value is still same as -1, isn't it? when its z-value is distorted?

远平面上的点总是变换为 z_ndc=1,近平面上的点总是变换为 z_ndc=-1。这就是投影矩阵的构造方式,这正是上图中两个图形相交的地方。所以对于这些微不足道的情况,不同的映射根本无关紧要。但对于所有其他距离,他们会。