depth buffer got by glReadPixels is always 1

后端 未结 2 1816
予麋鹿
予麋鹿 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 16:57

    Well, you missed to past the really relevent parts of the code. Also the status of the depth testing unit has no influence on what glReadPixels delivers. How about you post your rendering code as well.

    Update

    After a buffer swap SwapBuffers the contents of the back buffer are undefined and the default state for frame buffer reads is to read from the back buffer. Technically double buffering happens on only the color component, not the depth and stencil component. But you might run into a driver issue with that.

    I suggest two tests to rule out those:

    • Do a read of the depth buffer with glReadBuffer(GL_BACK); right before the SwapBuffers.

    • Select the front buffer with glReadBuffer(GL_FRONT); for reading after SwapBuffers

    Also please specify in which context (program, not OpenGL, well the later, too) you did your glReadPixels when this problem occours. Also check if you can read color value correctly.

    0 讨论(0)
  • 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 <znear...zfar> 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 <zNear,zFar>
        return -z;
        }
    

    Do not forget that x,y is in pixels and (0,0) is bottom left corner !!! The returned depth is in range <zNear,zFar>. 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
    0 讨论(0)
提交回复
热议问题