开发者

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?

  1. A way do temporary disable AA?
  2. Using a different buffer or even rendering context?
  3. 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
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜