Search code examples
c++visual-studioopenglglutglreadpixels

glReadPixels depth_buffer_component always returns 1


I'm trying to get world coordinates from any of my rendered vertices in OpenGL window (I prefer to use GLUT library). The problem is when I'm calling glReadPixels function to get depth value of a vertex, it always returns a 1 value, when I'm clicking my mouse anywhere.

I am stuck on this point, have already read a ton of articles, but didn't get any answer.

Here is my code:

display function

void display(){

 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 glEnable(GL_DEPTH | GL_DEPTH_TEST);
 glDepthFunc(GL_LEQUAL);
 glDepthRange(200, 2000);

 //here i put some glBegins and glEnds

 glutSwapBuffers();}

main function

int main(int argc, char **argv){   

 glutInit(&argc, argv);
 glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
 glutInitWindowSize(1280, 720);
 glutInitWindowPosition(50, 86);
 glutCreateWindow("2D correlation function");
 glClearColor(1,1,1,1.0);

 glMatrixMode(GL_MODELVIEW);
 glLoadIdentity();
 glFrustum(-150, 150, -150, 150, 200, 2000);
 glutMouseFunc(mouse);
 glutMotionFunc(motion);
 glutKeyboardFunc(keyboard);
 gluLookAt(200,400,200,0,0.0,0.0,0.0,0.0,1.0);
 glScalef(0.4, 0.4, 0.4);
 glutDisplayFunc(display);
 timer();
 glutMainLoop();


 return 0;}

mouse clicking function

void mouse(int button, int state, int x, int y){

 GLdouble objX, objY, objZ;
 GLdouble matModelView[16], matProjection[16];
 GLint viewport[4];
 glGetDoublev(GL_MODELVIEW_MATRIX, matModelView);
 glGetDoublev(GL_PROJECTION_MATRIX, matProjection);
 glGetIntegerv(GL_VIEWPORT, viewport);
 GLfloat winX = x;
 GLfloat winY = viewport[3] - y;
 GLfloat winZ = 0;
 glReadPixels(winX, winY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &winZ);
 cout << winX << " " << winY << " " << winZ << " " <<endl;
 gluUnProject(winX, winY, winZ, matModelView, matProjection, viewport, &objX, &objY, &objZ);
 cout << objX << " " << objY << " " << objZ << " " <<endl;}

Because of this, my world coordinates are displayed incorrectly:

example of mouse clicking

another example

I think i'm doing something wrong in display procedure


Solution

  • The parameter to glEnable has to be a single enumerator constant. The parameter is not a bit field.

    The following is not valid and will generate a GL_INVALID_ENUM error, which can be detected by glGetError or Debug Output:

    glEnable(GL_DEPTH | GL_DEPTH_TEST);
    

    It has to be

    glEnable(GL_DEPTH_TEST);
    

    Anyway GL_DEPTH is not a valid parameter for glEnable, but it is possibly an parameter to glCopyPixels.
    Note, the value of the enumerator constant GL_DEPTH_TEST is 0x0B71 and the value of GL_DEPTH is 0x1801. A binary or (|) operation of the both constants won't make any sense.

    Because of this the depth test has never been enabled and nothing was written to the depth buffer.


    Further note, that the values which are accepted for the depth range glDepthRange have to be in the range [0, 1]. The values which are passed to the glDepthRange are both clamped to this range before they are accepted.

    This means, that

    glDepthRange(200, 2000);
    

    is equal to

    glDepthRange(1, 1);
    

    so the depth range is [1, 1] and all values returned by glReadPixels are 1, too.

    Skip glDepthRange(200, 2000); to solve the issue.


    glGetDoublev(GL_MODELVIEW_MATRIX, matModelView) gets the current model view matrix from the GL_MODELVIEW matrix stack. glGetDoublev(GL_PROJECTION_MATRIX, matProjection) gets the current projection matrix from the GL_PROJECTION matrix stack.

    So you should put the projection matrix on the GL_PROJECTION matrix stack and the view matrix on the GL_MODELVIEW matrix stack (see glMatrixMode):

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glFrustum(-150, 150, -150, 150, 200, 2000);
    
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    gluLookAt(200,400,200,0,0.0,0.0,0.0,0.0,1.0);