depth buffer got by glReadPixels is always 1

后端 未结 2 1831
予麋鹿
予麋鹿 2020-11-28 16:16

I\'m using glReadPixels to get depth value of select pixel, but i always get 1, how can i solve it? here is the code:

    glEnable(GL_DEPTH_TEST);
    ..
            


        
2条回答
  •  一整个雨季
    2020-11-28 17:04

    I think you are reading correctly the only problem is that you are not linearize the depth from buffer back to range hence the ~1 value for whole screen due to logarithmic dependence of depth (almost all the values are very close to 1).

    I am doing this like this:

    double glReadDepth(double x,double y,double *per=NULL)                  // x,y [pixels], per[16]
        {
        GLfloat _z=0.0; double m[16],z,zFar,zNear;
        if (per==NULL){ per=m; glGetDoublev(GL_PROJECTION_MATRIX,per); }    // use actual perspective matrix if not passed
        zFar =0.5*per[14]*(1.0-((per[10]-1.0)/(per[10]+1.0)));              // compute zFar from perspective matrix
        zNear=zFar*(per[10]+1.0)/(per[10]-1.0);                             // compute zNear from perspective matrix
        glReadPixels(x,y,1,1,GL_DEPTH_COMPONENT,GL_FLOAT,&_z);              // read depth value
        z=_z;                                                               // logarithmic
        z=(2.0*z)-1.0;                                                      // logarithmic NDC
        z=(2.0*zNear*zFar)/(zFar+zNear-(z*(zFar-zNear)));                   // linear 
        return -z;
        }
    

    Do not forget that x,y is in pixels and (0,0) is bottom left corner !!! The returned depth is in range . The function is assuming you are using perspective transform like this:

    void glPerspective(double fovy,double aspect,double zNear,double zFar)
        {
        double per[16],f;
        for (int i=0;i<16;i++) per[i]=0.0;
        // original gluProjection
    //  f=divide(1.0,tan(0.5*fovy*deg))
    //  per[ 0]=f/aspect;
    //  per[ 5]=f;
        // corrected gluProjection
        f=divide(1.0,tan(0.5*fovy*deg*aspect));
        per[ 0]=f;
        per[ 5]=f*aspect;
        // z range
        per[10]=divide(zFar+zNear,zNear-zFar);
        per[11]=-1.0;
        per[14]=divide(2.0*zFar*zNear,zNear-zFar);
        glLoadMatrixd(per);
        }
    

    Beware the depth accuracy will be good only for close to camera object without linear depth buffer. For more info see:

    • How to correctly linearize depth in OpenGL ES in iOS?

    If the problem persist there might be also another reason for this. Do you have Depth buffer in your pixel format? In windows You can check like this:

    • Getting a window's pixel format

    Missing depth buffer could explain why the value is always 1 (not like ~0.997). In such case you need to change the init of your window enabling some bits for depth buffer (16/24/32). See:

    • What is the proper OpenGL initialisation on Intel HD 3000?

    For more detailed info about using this technique (with C++ example) see:

    • OpenGL 3D-raypicking with high poly meshes

提交回复
热议问题