glReadPixels()

Started by
5 comments, last by silvermace 18 years, 7 months ago
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.
Advertisement
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.
RenderUniqueColorScene();// Read bits from color bufferglPixelStorei(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 stateint 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.
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.
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.
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.
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.
"I am a donut! Ask not how many tris/batch, but rather how many batches/frame!" -- Matthias Wloka & Richard Huddy, (GDC, DirectX 9 Performance)

http://www.silvermace.com/ -- My personal website

This topic is closed to new replies.

Advertisement