Sign in to follow this  
Mantear

glReadPixels()

Recommended Posts

Greetings, I'm attempting to use glReadPixels() to get the color of the object I've just drawn. (I'm trying to use this to determine which object was selected). I have two problems in doing this. 1 - I'm using VBOs. Is there an easy way to temporarily change the color of the object? The only thing I can think of would be to create a copy of the color buffer, set it to the desired color, generate and bind the buffer, use it, then delete it. This seems rather cumbersome and was wondering if there was a better way. 2 - I can't seem to get the correct values back from glReadPixels(). I have a different rendering path that is called when a mouse is clicked, causing all objects to be drawn with a color that corresponds to an ID number, lights turned off, etc. However, when I read the buffer I get back, it is the colors that correspond to the normally drawn items. I've tried combinations of glReadBuffer(GL_FRONT/BACK), glFlush(), glFinish, SwapBuffers(), etc, but always with the same results.

Share this post


Link to post
Share on other sites
1)If you want to draw the whole object with a single color, just disable the client state for color arrays and set the color with glColor3f() before rendering the VBO.

2)Post code.

Share this post


Link to post
Share on other sites

RenderUniqueColorScene();

// Read bits from color buffer
glPixelStorei(GL_PACK_ALIGNMENT, 1);
glPixelStorei(GL_PACK_ROW_LENGTH, 0);
glPixelStorei(GL_PACK_SKIP_ROWS, 0);
glPixelStorei(GL_PACK_SKIP_PIXELS, 0);

// Get the current read buffer setting and save it. Switch to
// the front buffer and do the read operation. Finally, restore
// the read buffer state
int lastBuffer;
unsigned char* pBits;
pBits = (unsigned char*)malloc(3*3*3*sizeof(unsigned char));
glGetIntegerv(GL_READ_BUFFER, &lastBuffer);

glReadBuffer(GL_FRONT);
glReadPixels(MouseX1 - 1, pMainWindow->GetViewport()[3] - MouseY1 - 1, 3, 3, GL_RGB, GL_UNSIGNED_BYTE, pBits);

glReadBuffer(GL_BACK);
glReadPixels(MouseX1 - 1, pMainWindow->GetViewport()[3] - MouseY1 - 1, 3, 3, GL_RGB, GL_UNSIGNED_BYTE, pBits);

glReadBuffer(lastBuffer);
free(pBits);


I'm grabbing a 3x3 buffer of color around where the mouse was clicked. The RenderScene() function (is supposed to) draws each object with its own unique color. However, I always end up getting the colors that would be expected if the scene had been drawn normally.

I tried disabling the client state and setting the color via glColor3f(), but it didn't seem to be working. I switch to immediate mode, but have the same results. So, using my VBOs and just disabling the client state is probably working, I just have an error somewhere else.

Share this post


Link to post
Share on other sites
Ok, so the whole problem is that for some reason you can't draw the objects with a single color. I can't help you with that by looking at the code you posted. Post the part of the code where you render the VBO's instead.

Share this post


Link to post
Share on other sites
I found the error I was having. I'm converting my code over from using the GL_SELECT mode to select the objects in my scene. I was still calling glRenderMode(GL_SELECT) before rendering the scene with my unique colors. Apparently, this mode does not write to the color buffer. Therefore, I was already read the color buffer of the normally rendered scene.

Share this post


Link to post
Share on other sites
Unfortunately, my problems are not completely gone. I can now pick by ID/color. However, it now seems that there is a race condition. Some of the time I get back the expected ID/color when I read the pixel color. Some times I get the color from the normal rendering path. I tried putting calls to glFinish() at different places to make sure I wasn't reading the color buffer from a previous call to render the scene, but that doesn't seem to work.

Share this post


Link to post
Share on other sites
glReadPixels implicitly forces a pipeline flush, so it can't be a server-side race condition (your not using a set of beta drivers are you?). I would try using a seperate P-Buffer, it would be quite good because it has it own state variables. You could just use wglShareLists and go that way, this would allow you to render to a smaller output window for a bit of speed (eg, 512x512).
Mind you the context switch would be relativly expensive, but you might gain parralellism which would otherwise be impossible because of your current serial rendering.

BTW, Showing more of rendering code would be helpful.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this