Рисовать выбранные экземпляры 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,

Другие вопросы по тегам