具有两个不同投影矩阵的深度缓冲区
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,你可以预先计算它在透视情况下应该具有的扭曲深度。但如果它的深度范围不为零,这将不起作用。我可以想到不同的方法来处理这种情况:
"Fix" 片段着色器中对象二的深度,方法是根据您的 z 缓冲区预期的双曲线失真调整 gl_FragDepth
。
使用线性 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_eye
、y_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=1
和 f=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
。这就是投影矩阵的构造方式,这正是上图中两个图形相交的地方。所以对于这些微不足道的情况,不同的映射根本无关紧要。但对于所有其他距离,他们会。
我正在使用默认的 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,你可以预先计算它在透视情况下应该具有的扭曲深度。但如果它的深度范围不为零,这将不起作用。我可以想到不同的方法来处理这种情况:
"Fix" 片段着色器中对象二的深度,方法是根据您的 z 缓冲区预期的双曲线失真调整
gl_FragDepth
。使用线性 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_eye
、y_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=1
和 f=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
。这就是投影矩阵的构造方式,这正是上图中两个图形相交的地方。所以对于这些微不足道的情况,不同的映射根本无关紧要。但对于所有其他距离,他们会。