Какая стратегия выбора мыши для миллионов примитивов?

Я выполняю рендеринг моделей, основанных на миллионах (до десяти) треугольников, используя VBO, и мне нужно определить, на какой из этих треугольников может щелкнуть пользователь.

Я пытаюсь прочитать и понять, как работают "стек имен" и "уникальный цвет". Я обнаружил, что стек имен может содержать максимум 128 имен, в то время как уникальный цвет может иметь до 2^(8+8+8) = 16777216 возможных разных цветов, но иногда могут быть некоторые приближения, поэтому он может получить изменен..

Какая стратегия лучше всего подходит для моего случая?

2 ответа

Решение

В основном, у вас есть 2 класса вариантов:

  1. "Уникальный цветовой путь на треугольник", который означает, что вы прикрепляете идентификатор к каждому треугольнику и выводите идентификаторы для отдельной цели рендеринга. Это может быть 32 бита (8 для rgb, 8 для a), но вы можете добавить второй для еще большего количества идей. Получить идентификатор для каждого треугольника будет непросто, но его относительно легко реализовать. Хотя может быть весьма вредным для производительности (fillrate).

  2. Правильная трассировка лучей. Вы почти наверняка хотите иметь ускоряющую структуру (octree, kd,...), но, вероятно, у вас уже есть такая для отбраковки усеченного конуса. Один луч действительно не много, этот метод должен быть очень быстрым.

  3. Гибридный. вероятно, самый простой в реализации. Визуализируйте идентификатор буфера вершин ("уникальный цвет на буфер:), и когда вы знаете, какой буфер вершин был выбран", просто проведите луч против всех треугольников.

В общем случае, я бы сказал, 2) это лучший вариант. Если вы хотите, чтобы что-то работало быстро, перейдите к 3). 1) вероятно довольно бесполезно.

Если ваша видеокарта имеет OpenGL 4.2, вы можете использовать функцию imageStore() в GLSL, чтобы отметить треугольник Id на изображении. В моем случае мне нужно обнаружить все треугольники за предопределенным окном на экране. Выбор (выбор визуализированных треугольников в окне) работает аналогично. Выбор выполняется в режиме реального времени для меня.

Максимальный размер изображения (или текстуры) должен>= 8192x8192 = 64 м. Таким образом, можно использовать до 64 М примитивов (и даже больше, если мы используем 2, 3 изображения).

Сохранение всех идентификаторов треугольников за экраном может быть выполнено с помощью этого фрагментного шейдера:

uniform  uimage2D id_image;

void main() 
{
    color_f = vec4(0)
    ivec2 p;
    p.x = gl_PrimitiveID % 2048;
    p.y = gl_PrimitiveID / 2048;
    imageStore(id_image, p, uvec4(255));
}

Чтобы сохранить все идентификаторы треугольников, отображаемые на экране: сначала мы предварительно вычисляем буфер глубины, затем используем немного другой фрагментный шейдер:

uniform  uimage2D id_image;

**layout(early_fragment_tests) in;** //the shader does not run for fragment > depth

void main() 
{
    color_f = vec4(0)
    ivec2 p;
    p.x = gl_PrimitiveID % 2048;
    p.y = gl_PrimitiveID / 2048;
    imageStore(id_image, p, uvec4(255));
}
Другие вопросы по тегам