OpenGL中的反走样颜色选择?

3
我在OpenGL中遇到了颜色选择和抗锯齿的问题。当启用抗锯齿时,glReadPixels的结果在物体边缘和交叉处明显错误。例如:
我渲染了一个盒子#28(RGBA:28,0,0,0)和一个盒子#32(RGBA:32,0,0,0)附近。使用抗锯齿,我可能会得到一个错误的ReadPixel值(例如30),其中立方体和三角形重叠,或者在盒子边缘上的14的值,由于AA算法。
我有大约4000个对象需要能够选择(这是一个拼图游戏)。能够按形状选择对象至关重要。
我尝试使用glDisable(GL_MULTISAMPLE)禁用AA,但它不适用于某些AA模式(我读过它取决于AA实现-SS、MS、CS等)。
那么,如何选择底层对象?
1. 临时禁用AA的方法? 2. 使用不同的缓冲区甚至渲染上下文? 3. 其他建议?

1
大多数图形驱动程序都有强制抗锯齿选项,可以忽略您的设置。尝试使用FBO - Piotr Praszmo
不妨考虑将拾取功能与光栅化器/OpenGL分离实现?有一些易于使用、高性能的库可用于射线-三角形相交测试,例如OPCODE http://www.codercorner.com/Opcode.htm。 - datenwolf
@datenwolf 因为他正在处理拼图游戏(我会将其实现为经过 alpha 测试的四边形或类似物),所以我认为这对他行不通。 - Christian Rau
@Christian:但是在OpenGL之外,测试甚至更容易(将拾取坐标转换为Jigsaw纹理的坐标,并在那里测试alpha值,绕过缓慢的OpenGL读回往返)。老实说,我正在考虑一个3D拼图游戏。 - datenwolf
@datenwolf 好的,我没有考虑到那一点。但是他的颜色选择方法应该会更容易一些,因为如果不进行一些空间分割检查,检查4000个部分将不会那么高效。 - Christian Rau
2个回答

7
为什么不使用FBO作为您的拾取缓冲器?

我已经使用颜色和深度附加项(用于拾取和解除投影)搭建了FBO,效果非常好。谢谢! - Kromster
1
唯一的缺点是有些GPU不支持FBO但却支持AA,那么我需要回退到主缓冲区颜色选择,问题就会出现。 - Kromster

2
我使用这个技巧:不仅选择一个像素,而是选择选取点周围的所有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
}

谢谢,我一直在尝试找到一种处理p5.js中抗锯齿的方法,而这种3x3采样技术是一个非常有创意的解决方案! - Andor

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接