Color picking with AntiAliasing in OpenGL?
I'm having a problem with color picking and antialiasing in 开发者_如何转开发OpenGL. When AA is activated results from glReadPixels are obviously wrong on object edges and object intersections. For example:
I render a box #28 (RGBA: 28, 0, 0, 0) near a box #32 (RGBA: 32, 0, 0, 0). With AA, I can get a wrong ReadPixel value (e.g. 30) where the cube and triangle overlap, or value of 14 on boxes edge, due to the AA algorithm.
I have ~4000 thousand objects I need to be able to pick (it's a jigsaw puzzle game). It is vital to be able to select objects by shape.
I've tried to disable AA with glDisable(GL_MULTISAMPLE) but it does not works with certain AA modes (I read it depends on AA implementation - SS, MS, CS ..)
So, how do I pick an underlying object?
- A way do temporary disable AA?
- Using a different buffer or even rendering context?
- Any other suggestion?
Why not use an FBO as your pick buffer?
I use this hack: pick not just one pixel, but all the 3x3=9 pixels around the picking point. If they are all same, we are safe. Otherwise, it must be on edge and we can skip that.
int renderer::pick_(int x, int y)
{
static_assert(__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__,
"only works on little-endian architecture");
static_assert(sizeof(int) == 4,
"only works on architecture that has int size of 4");
// sort of edge detection. selection only happens at non-edge
// since the edge may cause anti-aliasing glitch
int ids[3*3];
glReadPixels(x-1, y-1, 3, 3, GL_RGBA, GL_UNSIGNED_BYTE, ids);
for (auto& id: ids) id &= 0x00FFFFFF; // mask out alpha
if (ids[0] == 0x00FFFFFF) return -1; // pure white for background
// prevent anti-aliasing glitch
bool same = true;
for (auto id: ids) same = (same && id == ids[0]);
if (same) return ids[0];
return -2; // edge
}
精彩评论