Screen Coords?

Is there a way to use the feedback buffer to get the (x,y,z) world space location of a (x,y) screen coordinate?

You can use a function called gluUnProject().

int gluUnProject(GLdouble winx, GLdouble winy, GLdouble winz, const GLdouble modelMatrix[16], const GLdouble projMatrix[16], const GLint viewport[4], GLdouble *objx, GLdouble *objy, GLdouble *objz)

It should work by passing the windowcoordinate of the point you want to unproject, modelview and projectionmatrices, viewport and pointers to where you want the worldcoordinate to be stored, like this.

GLint viewport[4];
GLdouble mvmatrix[16], projmatrix[16];
GLdouble wx, wy, wz;

glGetIntegerv(GL_VIEWPORT, viewport);
glGetDoublev(GL_MODELVIEW_MATRIX, mvmatrix);
glGetDoublev (GL_PROJECTION_MATRIX, projmatrix);

gluUnProject((GLdouble)x, (GLdouble)y, (GLdouble)z, mvmatrix, projmatrix, viewport, &wx, &wy, &wz);

Since the point on screen appears on a 2D plane in 3D space, you cannot pass x and y coordinates and get x, y and z back. You must pass a z-coordinate too, and that coordinate is the distance from the plane (screen) to the point, or rather the value you find in the depthbuffer at <x,y>.

And what is the good way to read in the depth buffer. Can’t gluUnProject() or sthg like that read itself into the z-buffer to know the z coordinate ?

Sorry, was wrong about one thing in my post. It’s about the winz-coordinate. This is what the Red Book is saying:

There are inherent difficulties in trying to reverse the transformation process. A two-dimensional screen location could have originated from anywhere on an entire line in three-dimensional space. To disambiguate the result, gluUnProject() requires that a window depth coordinate (winz) be provided and that winz be specified in terms of glDepthRange(). For the default values of glDepthRange(), winz at 0.0 will request the world coordinates of the transformed point at the near clipping plane, while winz at 1.0 will request the point at the far clipping plane.


Wow! thanks a lot Bob, that was exactly what i was looking for.

Ok, this is definitly the function i want to use, but i have looked all over and cant seem to find any documentation on it? I want to find the exact x,y,z that the mouse is over…so if the mouse location is MouseX, and MouseY, how could i set this up, here is what i have can you tell me if it is correct or if i should change anything:

GLint Viewport[4];
GLdouble MVMatrix[16], ProjMatrix[16];
GLdouble wx, wy, wz;

glGetIntegerv(GL_VIEWPORT, Viewport);
glGetDoublev(GL_MODELVIEW_MATRIX, MVMatrix);
glGetDoublev (GL_PROJECTION_MATRIX, ProjMatrix);

gluUnProject((GLdouble)MouseX, (GLdouble)MouseY, (GLdouble)1.0, MVMatrix, ProjMatrix, Viewport, &wx, &wy, &wz);


The problem with unproject is that you HAVE to pass a specific z-coord in order to get a specific point in 3D space. If you pass 1.0 as z-coord, you will get the point in worldcoord that lies on the far clipping plane (0.0 will return the point on the near clipping plane).
However, you can use the point on the far clipping plane to calculate a line, on which all point lies that will be projected on the screen at <x,y>.

You can also see the screen as the near clipping plane (well, any plane will do), and therefore, if you click on <x,y>, you click somewhere on the plane. Then use gluUnProject to obtain that point on the plane.


P.S. Hmm, maybe this was a bit too messy…

Mmmhh… The best way to get the screen coordinates still seems to do the transformations ourselves.
But if you use gluUnproject, be careful about the MouseY coordinate, because the Y axis for the mouse is waying down the screen (is it english ?). For exemple, when i use gluPickMatrix, if must pass MouseX as x coordinate, and Viewport[3]-MouseY as Y coordinate (where Viewport is the array you retrieve with glGetIntegerv(GL_VIEWPORT)).

How could i calculate that line?

Hmm, will try to give it a shot and describe how to calculate the line. Was a while since I read about linear algebra .

c = cameraposition
p = point projected on far clippingplane

v.x = p.x - c.x
v.y = p.y - c.y
v.z = p.z - c.z

| x = c.x + t * v.x
| y = c.y + t * v.y
| z = c.z + t * v.z

x, y and z is the point in space you get
t is a constant
t=0 gives you the camerapoint
t=1 gives you the point on far clipping plane
t=0.5 gives you the point halfway from camera to far clippingplane

Hope that was correct.

You can do a glReadPixel(x,y,1,1,GL_DEPTH_COMPONENT,GL_UNSIGNED_INT,*pixels) to get the depth under the mouse pointer.
Preferred destination values are ULONG (0 - 2**32-1). Scale the result to lie in the proper depth range 0.0 to 1.0 afterwards.

Originally posted by Antoche:
And what is the good way to read in the depth buffer. Can’t gluUnProject() or sthg like that read itself into the z-buffer to know the z coordinate ?