glReadPixels only works close to the origin

Started by
20 comments, last by michaeljmcd 17 years, 8 months ago
I've been trying to do some color-coded selection (rendering the entire scene in unique colors on the back buffer, then reading the pixels in order to ID the object selected), but when I glReadPixels it only works near (100-200 pixels away in both x and y directions) OpenGL's origin. Within this small area, glReadPixels reads and stores the pixel data as it should. Outside this area (which is most of the scene), glReadPixels does not alter the pixel array passed to it. What is causing this?
Advertisement
Small error in the previous post: it works about 0-200 pixels away, not 100-200.
Post code.
C Code:

#include <stdio.h>
#include <GL/gl.h>
#include <GL/glut.h>

void ordinary_render();
void color_render();
void mouse_handler(int, int, int, int);

int main (int argcp, char* argv[])
{
glutInit(&argcp, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutCreateWindow("Pickin'");

glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glutDisplayFunc(ordinary_render);
glutMouseFunc(mouse_handler);
glutMainLoop();
return 0;
}

void ordinary_render()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glColor3ub(255, 255, 255);

glutSolidCube(0.075);

glTranslatef(0.0, 0.04, 0.0);
glRotatef(90, 0.0, 1.0, 0.0);
glRotatef(-90, 1.0, 0.0, 0.0);

glutSolidCone(0.035, .1, 15, 15);

glRotatef(90, 1.0, 0.0, 0.0);
glRotatef(-90, 0.0, 1.0, 0.0);
glTranslatef(0.0, -.04, 0.0);

glutSwapBuffers();
}

void color_render()
{
glColor3ub(255, 0, 0);
glutSolidCube(0.075);

glTranslatef(0.0, 0.04, 0.0);
glRotatef(90, 0.0, 1.0, 0.0);
glRotatef(-90, 1.0, 0.0, 0.0);

glColor3ub(0, 255, 0);
glutSolidCone(0.035, .1, 15, 15);

glRotatef(90, 1.0, 0.0, 0.0);
glRotatef(-90, 0.0, 1.0, 0.0);
glTranslatef(0.0, -.04, 0.0);
}

void mouse_handler(int button, int state, int x, int y)
{
if (button == GLUT_LEFT_BUTTON && state == GLUT_UP)
{
int viewport[4] = {1, 2, 3, 4};
unsigned char pixel[3] = {12, 17, 1};

glGetIntegerv(GL_VIEWPORT, viewport);

glDisable(GL_DITHER);
color_render();
glEnable(GL_DITHER);

glReadPixels(x, viewport[3] - y, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, (void*)pixel);

printf("RGB vals: %u, %u, %u\n", (unsigned int)pixel[0], (unsigned int)pixel[1], (unsigned int)pixel[2]);
}
else
return;
}
----------------------------------------------------------------------------------------------------------
Basically, it's just a sample program that I wrote to work out the issues before integrating the ideas in the larger program. It draws a cone on top of a cube. On a mouse click, it prints out (or is supposed to) the RGB values of the back buffer location corresponding to that selfsame mouseclick. When the mouse is clicked, the pixel array remains unchanged unless the click is near the OpenGL origin as I posted earlier.
Tried the code and it works as expected; red when picking the cube, blue when picking the cone and black otherwise.
Which compiler were you using? I am running gcc version 3.4.6 on Gentoo Linux (kernel version 2.6), and the values remain unaltered except near the lower left hand corner.
The behaviour is not dependent on the compiler, but the OpenGL implementation. After all, it's glReadPixel not working as expected, and that function isn't provided by the compiler. I'm using the latest drivers from NVIDIA for Windows. Try update your drivers if possible (or go back to older ones if you already have the latest, or just to check the behaviour) The code you provided is correct.
Wait, I just realized what could be wrong the second I posted the reply. When drawing the colored image for selection, you don't clear the buffer. After presenting the back buffer to the front buffer, the content of the back buffer is undefined. Then you draw the colored image to a back buffer with undefined content, so the result is also undefined. Clear the back buffer before drawing the colored selection image.

So the code isn't correct, and my implementation just happened to give the expected result, but that was just luck.
Adding glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); to the top of color_render() failed to alter the result at all. Unless I am mistaken, that is the method to clear the back buffer.
Then try changing drivers and see what happens. Also try read back the entire window and dump to an image and see what you get. Try reading both the whole window in one call, and for each pixel individually and see if there is any difference. Also check glGetError.

This topic is closed to new replies.

Advertisement