OpenGL ES上的深度缓冲区精度

时间:2014-04-18 15:36:58

标签: opengl-es precision framebuffer depth-buffer

我正在尝试从深度缓冲区获取正确的Z值(将其渲染为颜色纹理,然后使用glReadPixels读取),然后取消投影以获得真实的3D空间坐标。在iPad Air上它可以很好地工作,但不适用于iPad 3或iPad 4。

iPad 3/4和iPad Air有:
OpenGL ES 2.0 IMGSGX554-97.7和OpenGL ES 2.0 Apple A7 GPU - 27.23
GLSL版本OpenGL ES GLSL ES 1.00
OpenGL深度位24 - 在所有设备上

glDepthFunc(GL_LEQUAL);
glDepthRangef(0, 1.0);
glClearDepthf(1.0);

在片段着色器中:

precision highp float;  

// .... some code and variables  

const float maxnum = 256.0;

vec4 pack (float depth)
{

    const vec4 bitSh = vec4(maxnum * maxnum * maxnum,
                            maxnum * maxnum,
                            maxnum,
                            1.0);
    const vec4 bitMsk = vec4(0,
                             1.0 / maxnum,
                             1.0 / maxnum,
                             1.0 / maxnum);
    vec4 comp = fract(depth * bitSh);
    comp -= comp.xxyz * bitMsk;
    return comp;
}

void main()
{
   gl_FragColor = pack(gl_FragCoord.z);
}

在iPad Air上我们可以看到:
enter image description here

在iPad 3/4上:
enter image description here

2 个答案:

答案 0 :(得分:2)

我的案子中有2个问题:
 1. nearZfarZ之间的距离很远  2.我试图使用精度较低的gl_FragCoord.z。它是通过渲染到帧缓冲区来解决的,帧缓冲区只有深度组件(没有颜色缓冲区!),然后在第二遍中渲染深度纹理的结果到另一个帧缓冲区,颜色渲染缓冲区和着色器具有相同的pack函数问题。

enter image description here

Answer is here on OpenGL.org FAQ

12.050为什么我的深度缓冲精度如此差?

眼睛坐标中的深度缓冲精度受zFar与zNear,zFar剪裁平面的比率以及物体离zNear剪裁平面的距离的影响很大。

您需要尽一切可能将zNear剪裁平面推出并尽可能拉入zFar平面。

12.070为什么深度缓冲区前面的精度更高?

在投影矩阵变换剪辑坐标之后,XYZ顶点值除以其剪辑坐标W值,这导致标准化的设备坐标。这一步被称为透视鸿沟。剪辑坐标W值表示距眼睛的距离。随着与眼睛的距离增加,1 / W接近0.因此,X / W和Y / W也接近零,导致渲染的图元占据更少的屏幕空间并且看起来更小。这就是计算机模拟透视图的方式。

实际上,朝向或远离眼睛的运动对已经在远处的物体的影响不大。例如,如果你移动六英寸靠近面前的电脑屏幕,它的表面尺寸应该会非常显着地增加。另一方面,如果计算机屏幕距离您已经20英尺,那么移动6英寸距离对其表观尺寸几乎没有明显的影响。透视鸿沟将此考虑在内。

作为透视分割的一部分,Z也被W除以相同的结果。对于已经靠近视图体背面的对象,与对象靠近视图体积的前端相比,一个坐标单元的距离变化对Z / W的影响较小。换句话说,对象坐标Z单元占据视图体积前端附近的NDC深度空间的较大切片,而不是视图体积背面附近。

总之,视角的划分,就其本质而言,会使靠近视野前方的Z精度高于靠近后方的精度。

12.080标准尺寸的深度缓冲区无法为我的天文大场景提供足够的精度。我有什么选择?

典型的方法是使用多通道技术。应用程序可能会将几何数据库划分为Z中不会相互干扰的区域。然后,从最远的区域开始渲染每个区域中的几何图形,并在渲染每个区域之前清除深度缓冲区。这样,每个区域都可以使用整个深度缓冲区的精度。

答案 1 :(得分:0)

也许深度缓冲区中的值很好,但在采样过程中这是一个精确的问题?

您是否检查过GLSL中深度纹理采样器的声明,并确保声明为'highp'?

如果您要求的精度太低而无法满足您的需求(或因为您没有设置而导致默认为低压),某些设备可能会给您超出您的要求并掩盖遗漏。