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
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 to solve the issue.glDepthRange(200, 2000);
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);