Рисовать выбранные экземпляры VAO (glDrawArraysInstanced)
Я использую glDrawArraysInstanced, чтобы нарисовать несколько экземпляров дерева в разных позициях, чтобы создать лес.
Есть ли способ нарисовать выбранные экземпляры? Например: я получил 100 деревьев с разными атрибутами. Из-за выбраковки я хочу нарисовать только экземпляры 3, 65, 89 и 95.
Возможность нарисовать один экземпляр уже будет достаточно.
1 ответ
Есть несколько подходов, которые вы можете использовать:
1. Отключение процессора
Используйте отдельный буфер для атрибута (ов) для каждого экземпляра и заполните его в каждом кадре экземплярами, которые проходят ваш тест видимости. Это имеет то преимущество, что очень прост. Если у вас много тысяч деревьев, вы не должны генерировать значительный трафик шины, загружая это в память GPU каждый кадр. Вы также можете использовать иерархическую схему деления пространства (например, quadtree) для более эффективной работы frustum-cull. Основным недостатком является то, что вы можете легко выполнять отбраковку усеченного конуса. Отбор окклюзии потребует гораздо больше работы.
2. Отбор на GPU с использованием геометрического шейдера
Даниэль Ракос описывает метод - выборку экземпляров с использованием геометрических шейдеров - для использования геометрического шейдера и преобразования обратной связи для создания буфера, содержащего данные для каждого экземпляра, только для видимых экземпляров.
Как он отмечает в конце статьи, она была написана для версии OpenGL, в которой не было glVertexAttributeDivisor
, так что вы можете игнорировать предложение использовать единообразные или текстурные буферные объекты для хранения данных для каждого экземпляра.
Несмотря на то, что описанная методика выполняет только выборку усеченного конуса, я думаю, что вы могли бы провести некоторые дополнительные тесты видимости, если у вас уже есть рендеринг ландшафта в текстуру глубины. Вы можете вычислить мировую позицию вершины дерева и проверить ее z-значение по сравнению со значением уже в буфере. Если верхняя часть дерева закрыта, то остальная часть дерева также будет (вам может понадобиться использовать точку где-то над верхушкой дерева, чтобы учесть форму дерева и рельефа местности, а также каким-то образом учесть ситуацию, когда верх дерева за кадром, но остальное может не быть).
3. Используйте окклюзионные запросы и условный рендеринг
Я не уверен, насколько практично это использовать с большим количеством деревьев. Вам придется создать объект запроса для каждого экземпляра дерева и выполнить вызов отрисовки с простой геометрией для каждого дерева между вызовами glBeginQuery
а также glEndQuery
, Затем вы должны были бы выполнить вызов отрисовки для реальной геометрии каждого дерева между вызовами glBeginConditionalRender
а также glEndConditionalRender
,
Обратите внимание, что хотя это приводит к большому количеству вызовов отрисовки (вы больше не будете использовать glDrawArraysInstanced
), которые не должны быть слишком дорогими, так как вам не нужно много менять состояние между вызовами - просто установите форму преобразования.
Кроме того, вам, вероятно, будет лучше использовать индексированные данные вершин и glDrawElementsInstanced
вместо glDrawArraysInstanced
,