glReadPixels() how to get actual depth instead of normalized values?
我正在使用pyopengl来获取深度图。
我能够使用
我尝试过使用
绘制几何图形时,应该使用顶点着色器通过视图/投影矩阵将所有内容转换为归一化的设备坐标(每个分量在-1和1之间)。无法避免这种情况,超出此范围的所有内容都将被裁剪(或启用深度钳位,则被钳位)。然后,将这些设备坐标转换为窗口坐标-将X和Y坐标映射到用
您不能禁用标准化,因为最终值必须在0..1范围内。但是您可以应用逆变换:首先,将深度值映射回-1..1范围(如果您不使用
1 2 | zNorm = 2 * zBuffer - 1 zView = 2 * near * far / ((far - near) * zNorm - near - far) |
(请注意,zView在-near和-far之间为负,因为在OpenGL中,Z轴通常指向相机)。
尽管通常您不只想要深度-想要完整的3D点,所以您也可以在归一化坐标中重建矢量,然后应用逆投影/视图变换。
投影到视口后,场景的坐标为归一化设备坐标(NDC)。规范化的设备空间是一个立方体,其左,下,前坐标为(-1,-1,-1),右,上,后坐标为(1、1、1)。此多维数据集中的几何图形在视口上是"可见的"(除非被覆盖)。
归一化设备空间的Z坐标映射到通常在[0,1]中的深度范围(
视图空间的z坐标如何转换为规格化的设备Z坐标以及深度,取决于投影矩阵。
在正交投影中,Z分量由线性函数计算,在透视投影中,Z分量由有理函数计算。
请参见如何在片段着色器中使用gl_FragCoord.z在现代OpenGL中线性渲染深度?。
这意味着要将深度缓冲区的深度转换为原始Z坐标,投影(正交或透视),并且必须知道近平面和远平面。
以下假定深度范围为[0,1],并且
正射投影
1 2 3 4 5 | n = near, f = far z_eye = depth * (f-n) + n; z_linear = z_eye |
透视投影
1 2 3 4 | n = near, f = far z_ndc = 2 * depth - 1.0; z_eye = 2 * n * f / (f + n - z_ndc * (f - n)); |
如果已知透视投影矩阵,则可以执行以下操作:
1 2 3 | A = prj_mat[2][2] B = prj_mat[3][2] z_eye = B / (A + z_ndc) |
请注意,在任何情况下,通过逆投影矩阵进行转换,都可以将规范化的设备坐标转换为视图空间中的坐标。