2

I am trying to implement object picking. I have code to render the objects as solid, unlit colors, then I read the pixels in the screen buffer. I interpret the readings from glReadPixels() to determine which object the cursor is currently on. Finally, I re-render everything lit, textured, and colored.

    gl.glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    gl.glMatrixMode(GL_MODELVIEW);
    gl.glLoadIdentity();
    gl.glPushMatrix();

    //Picking render goes here...

    gl.glPopMatrix();



    //The following code reads the current pixel color at the center of the screen
    FloatBuffer buffer = FloatBuffer.allocate(4);

    gl.glReadBuffer(GL_FRONT);
    gl.glReadPixels(drawable.getWidth() / 2, drawable.getHeight() / 2, 1, 1, GL_RGBA, GL_FLOAT, buffer);
    float[] pixels = new float[3];
    pixels = buffer.array();
    float red = pixels[0];
    float green = pixels[1];
    float blue = pixels[2];
    System.out.println(red + ", " + green + ", " + blue);



    gl.glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    gl.glMatrixMode(GL_MODELVIEW);
    gl.glLoadIdentity();
    gl.glPushMatrix();

    //Final render goes here...

    gl.glPopMatrix();

The problem is that the call to glReadPixels() returns me the pixel color of the FINAL render, rather than the picking render. I would appreciate an explanation of how to read the picking render pixels.

I am aware that I can use the OpenGL name stack, but frankly I find it inconvenient and ridiculous.

Joshua Hyatt
  • 1,300
  • 2
  • 11
  • 22
  • 1
    Are you using a single buffered surface? The `glReadBuffer(GL_FRONT)` call seems unusual. Are you drawing to the front buffer? – Reto Koradi May 10 '14 at 21:06
  • @Reto Koradi Thank you! I copy/pasted the readPixels code from some website. I didn't know what that call did. I changed it to `gl.glReadBuffer(GL_BACK);` to read from the back buffer (which makes sense in hindsight). It works now, thank you! Please post this as the answer! – Joshua Hyatt May 10 '14 at 21:09

1 Answers1

2

The problem is that you render to the back buffer, but your glReadPixels() call reads from the front buffer. If you render to a double buffered surface (which you almost always want when using OpenGL), your rendering goes to the back buffer by default. You have this call in your code:

gl.glReadBuffer(GL_FRONT);

This tells the following glReadPixels() call to read from the front buffer, which is the buffer you are not drawing to.

You should be able to simply remove the glReadBuffer() call, as GL_BACK is the default read buffer for a double buffered default rendering surface.

Reto Koradi
  • 53,228
  • 8
  • 93
  • 133
  • 1
    @Josh: Some window systems even make reading from the front buffer *undefined*. The swap technique used (e.g. copy vs. exchange vs. discard) will dictate whether or not you get anything meaningful by reading the front buffer, but GL itself has no control over this. Nevertheless, the ***front*** buffer is usually at least one frame old in a double-buffered or triple-buffered pixel format. – Andon M. Coleman May 10 '14 at 23:41