unable to translate from screen coords to world coords

Hi everyone,

My problem is a very common one, still I cannot figure it out:
I have screen coords and want to get the world coordinates (for one pixel).
I am trying to use glReadPixels to get the depth value required in the gluUnProject method.

I usually get 1 or .0999 something from the readPixel method but even if I enter a depth value manually into
the unProject method, I get about the same value for when I click “near” or “far”. Also I do not understand why my y
coordinate changes when I click in different location, I have a plane.

Maybe it’s best if I post some code so you can see what is going on.

my init method:


public void init(GLAutoDrawable d) {
        GL2 gl = d.getGL().getGL2();
        glu = new GLU();
        renderer = new TextRenderer(new Font("sansserif", Font.BOLD, 64));
        gl.glClearColor(0, 0, 0, 0);
        gl.glClearDepth(1);
        gl.glDepthFunc(GL_LEQUAL);
        gl.glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
        gl.glShadeModel(GLLightingFunc.GL_SMOOTH);
        gl.glEnable(GL2.GL_TEXTURE_2D);
                gl.glEnable( GL_DEPTH_TEST );
                gl.glDepthMask(true);
                gl.glDepthFunc( GL_LEQUAL );
        gl.glMatrixMode(GL_MODELVIEW);
    }

my display method:


public void display(GLAutoDrawable drawable) {
//        some initialization
        GL2 gl = getGL().getGL2();
        glu = new GLU();

//        clearing buffers
        gl.glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        gl.glLoadIdentity();

//        needed for the gluUnProject, initialized below
        int viewport[] = new int[4];
        double mvmatrix[] = new double[16];
        double projmatrix[] = new double[16];
        int realy = 0;// GL y coord pos
        double wcoord[] = new double[4];

//        setting camera position
        glu.gluLookAt(0, 50, -40, 0, 0, -90, 0, 1, 0);

//       translation of the object
        gl.glTranslatef(-50.0f, -25.0f, -80.0f);

//        drawing of the object, a 32x32square consisting of smaller squares (1024 precisely)
        for (int i = 0; i < GROUND_HEIGHT; ++i) {
            for (int j = 0; j < GROUND_WIDTH; ++j) {
                try {
                    drawGround(gl, i, j);
                } catch (Exception e) {
                    e.printStackTrace();
                }                
            }
        }


        renderer.beginRendering(drawable.getWidth(), drawable.getHeight());
        renderer.setColor(1.0f, 0.0f, 0.0f, 0.8f);

        if (Main.killed > 0)
            renderer.draw(Main.killed + "x killed", 1000, 650);

        renderer.endRendering();

//        if a mouse event occures...
        if (mouse != null){
            System.out.println(mouse.getX() + " " + mouse.getY());
//            get its position
            int x = mouse.getX();
            int y = mouse.getY();

//            initialize stuff for gluUnProject
            gl.glGetIntegerv(gl.GL_VIEWPORT, viewport, 0);
            gl.glGetDoublev(gl.GL_MODELVIEW_MATRIX, mvmatrix, 0);
            gl.glGetDoublev(gl.GL_PROJECTION_MATRIX, projmatrix, 0);
            realy = viewport[3] - (int) y - 1;
            System.out.println("Coordinates at cursor are (" + x + ", " + realy + ")");

            FloatBuffer floatBuffer = FloatBuffer.allocate(1);
//            read pixel depth
            gl.glReadPixels( x, y, 1, 1, gl.GL_DEPTH_COMPONENT, gl.GL_FLOAT, floatBuffer);
            float z = floatBuffer.get();

//            translating the coordinates
            glu.gluUnProject((double) x, (double) realy, z
                    , //
                    mvmatrix, 0,
                    projmatrix, 0,
                    viewport, 0,
                    wcoord, 0);

            System.out.println("World coords at z=1.0 are ( " //
                    + wcoord[0] + ", " + wcoord[1] + ", " + wcoord[2]
                    + ")");
        }
    }

my reshape method:


public void reshape(GLAutoDrawable d, int x, int y, int width,
            int height) {
        GL2 gl = getGL().getGL2();
        
        if (height == 0) {
            height = 1;
        }
        
        float aspect = (float) width / height;
        
        gl.glViewport(0, 0, width, height);
//        this is the lens of the camera
        gl.glMatrixMode(GL_PROJECTION);
        glu.gluPerspective(45, aspect, 0.1, 200);
//        this is the position of the camera
        gl.glMatrixMode(GL_MODELVIEW);
        gl.glLoadIdentity();
    }

Try drawing something barely in front of the near clip plane, and then read that back and look at the unprojected depth values.

For a perspective projection, the transformation from linear eye-space Z to window-space Z is very non-linear, causing most of your Z precision to cluster up toward the near clip plane where you typically want it. The consequence is that when moving from near to far, your Z values move pretty quickly up to very near 1.0. So it’s not unusual to do a readback and the window-space Z values are 0.9…something…