Opengl es opengles中深度缓冲区的精度

Opengl es opengles中深度缓冲区的精度,opengl-es,precision,framebuffer,depth-buffer,Opengl Es,Precision,Framebuffer,Depth Buffer,我试图从深度缓冲区(渲染为彩色纹理,然后用glReadPixels读取)中获得适当的Z值,然后取消投影以获得真实的3D空间坐标。在iPadAir上,它可以完美地工作,但在iPad3或iPad4上则不行 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_LEQU

我试图从深度缓冲区(渲染为彩色纹理,然后用glReadPixels读取)中获得适当的Z值,然后取消投影以获得真实的3D空间坐标。在iPadAir上,它可以完美地工作,但在iPad3或iPad4上则不行

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上我们可以看到:


在iPad 3/4上:

深度缓冲区中的值可能很好,但这是采样过程中的精度问题

您是否检查了GLSL中深度纹理采样器的声明,并确保声明为“highp”


如果您要求的精度太低,无法满足您的需要(或者由于您没有设置精度而被默认为lowp),某些设备可能会提供超出您要求的精度,并掩盖遗漏。

我的案例中有两个问题:
1.
nearZ
farZ

2.我尝试使用精度较低的
gl_FragCoord.z
。这是通过渲染到帧缓冲区来解决的,帧缓冲区只有深度分量(没有颜色缓冲区!),然后在第二遍渲染深度纹理的结果到另一个帧缓冲区,该帧缓冲区使用颜色渲染缓冲区和着色器,该着色器具有与上述相同的
pack
功能。

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深度空间中占据的切片比在靠近视图体积后部的NDC深度空间中占据的切片更大

总之,透视图分割的性质使靠近视图体积前部的Z精度高于靠近后部的Z精度

12.080标准大小的深度缓冲区不可能有足够的精度来满足我天文般大的场景。我的选择是什么?


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

我所知道的Apple A7 GPU和以前的PowerVR SGX GPU之间唯一的精度差异是,A7上的
lowp
mediump
是相同的(均为16位)。较旧的型号有
lowp
=12位和
mediump
=16位。@AndonM.Coleman好的,如果它是正确的-那么我不能使用gl_FragCoord.z,因为它不准确。我曾尝试使用顶点着色器中的坐标,但这并没有太大帮助。您建议尝试什么?谢谢,这解决了我的web gl问题。我使用了mat4.perspective,其值为:近=0和远=100。它造成了奇怪的人工制品。现在,值为0.01和0.4时,一切都很好。@User1很高兴它能帮助您:)@SAKrisT:您能为点#2渲染到帧缓冲区发布一些代码吗?帧缓冲区刚刚为深度组件附加了纹理(没有颜色缓冲区!)然后用附加的颜色renderbuffer将这个深度纹理渲染到另一个帧缓冲区?@deblocker这是一系列使用两个帧缓冲区的操作,很难在这里发布简单易懂的内容。