OpenGL 中使用抗锯齿拾色?

发布于 2024-11-09 14:33:01 字数 460 浏览 0 评论 0原文

我在 OpenGL 中的颜色选择和抗锯齿方面遇到问题。当 AA 被激活时,glReadPixels 的结果在对象边缘和对象交叉点上明显是错误的。例如:

我在框 #32 (RGBA: 32, 0, 0, 0) 附近渲染框 #28 (RGBA: 28, 0, 0, 0)。使用 AA,由于 AA 算法,我可能会在立方体和三角形重叠处得到错误的 ReadPixel 值(例如 30),或者在框边缘得到 14 的值。

我有大约 400 万个物体需要能够挑选(这是一个拼图游戏)。能够按形状选择对象至关重要。

我尝试使用 glDisable(GL_MULTISAMPLE) 禁用 AA,但它不适用于某些 AA 模式(我读到它取决于 AA 实现 - SS、MS、CS ..)

那么,如何选择底层对象?

  1. 有办法暂时禁用AA吗?
  2. 使用不同的缓冲区甚至渲染上下文?
  3. 还有其他建议吗?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

旧城空念 2024-11-16 14:33:04

我使用这个技巧:不仅选取一个像素,而且选取选取点周围的所有 3x3=9 像素。如果它们都一样,我们就安全了。否则,它一定处于边缘状态,我们可以跳过它。

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
}

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
}
獨角戲 2024-11-16 14:33:03

为什么不使用 FBO 作为您的挑选缓冲区?

Why not use an FBO as your pick buffer?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文