Выбор цвета с помощью AntiAliasing в OpenGL? - PullRequest
3 голосов
/ 25 мая 2011

У меня проблема с выбором цвета и сглаживанием в OpenGL. Когда AA активирован, результаты из glReadPixels явно неверны на краях объекта и пересечениях объекта. Например:

Я рендеринг поля № 28 (RGBA: 28, 0, 0, 0) возле поля № 32 (RGBA: 32, 0, 0, 0). С помощью AA я могу получить неправильное значение ReadPixel (например, 30), когда куб и треугольник перекрываются, или значение 14 на краю прямоугольника из-за алгоритма AA.

У меня есть ~ 4000 тысяч объектов, которые мне нужно выбрать (это игра-головоломка). Очень важно иметь возможность выбирать объекты по форме.

Я пытался отключить AA с помощью glDisable (GL_MULTISAMPLE), но он не работает с некоторыми режимами AA (я читал, что это зависит от реализации AA - SS, MS, CS ..)

Итак, как мне выбрать базовый объект?

  1. А как временно отключить АА?
  2. Используете другой буфер или даже контекст рендеринга?
  3. Любое другое предложение?

Ответы [ 2 ]

7 голосов
/ 25 мая 2011

Почему бы не использовать FBO в качестве буфера выбора?

1 голос
/ 12 апреля 2015

Я использую этот хак: выберите не один пиксель, а все 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
}
...