2015-12-26 5 views
2

Я экспериментирую с рендерингом мира, подобного Minecraft, в OpenGL. Мир разделен на куски (каждый из них содержит N^3 блока), и эти куски получают каждый кадр.GL_ARB_vertex_attrib_binding и индексированный чертеж

В настоящее время я использую один VAO за кусок. Я всегда думал, что это немного странно, поскольку каждый кусок использует тот же формат вершин - почему я не могу использовать один VAO, а затем рисовать каждый кусок, изменяя привязки буфера индекса и вершин?

Недавно я натолкнулся на расширение GL_ARB_vertex_attrib_binding, которое находится в ядре 4.3 и, похоже, решает эту проблему - привязки VAO и VBO теперь могут быть разделены. Но нет никаких упоминаний о привязках буферов индекса, которые все еще являются частью состояния VAO, что делает расширение бесполезным с индексированным рендерингом. Единственное, о чем я могу думать, это обновление содержимого связанного индексного буфера для каждого изменения привязки буфера и вершинного буфера при рендеринге, но это мало смысла.

Мой вопрос в том, что я понимаю, что расширение делает правильно? Если я это сделаю, есть ли другой метод, который я могу использовать, чтобы избежать использования VAO в каждом блоке без слияния буферов индексов per-chunk в один большой IBO (так как это могло бы затруднить управление потоком пакетов) ?

ответ

3

Вы ... частично неправильно поняли назначение привязки атрибутов вершин.

Да, он создает separation между vertex format и buffer bindings. Однако это разделение находится только на уровне API. То есть у вас есть такие функции, как glVertexAttribFormat, которые задают формат, и glBindVertexBuffer, который устанавливает буферы.

Но все эти функции все еще изменяют состояние VAO.

Однако нет необходимости менять VAO только потому, что вы меняете состояние в пределах VAOs. Причина, по которой существует привязка привязки вершины, заключается в том, что изменение состояния формата вершин дорого. В то время как изменение состояния связывания буфера не является (или, по крайней мере, это не как дорого). Так что дешевле позвонить glBindVertexBuffer, чем позвонить glVertexAttribFormat.

Именно поэтому функция существует: чтобы вы не делали дорогой звонок, просто чтобы выполнить дешевую операцию.

Так что вы хотите сделать, это нормально; вы можете просто привязать VAO, затем сделайте glBindVertexBuffer и glBindBuffer(GL_ELEMENT_ARRAY_BUFFER) звонки по своему усмотрению. Да, они изменят состояние в ВАО, но что? Пока вы не касаетесь формата вершин в VAO, вы в порядке.

Это означает, что если ваша цель - производительность, вы, вероятно, не должны менять состояние привязки буфера на кусок в любом случае. Поместите все ваши куски (или, по крайней мере, большие группы из них) в разные области одного и того же буфера. Все индексы для групп кусков также должны жить в одном буфере. Индексы должны относиться к началу данных этого куска, поэтому вы должны иметь возможность использовать 16-разрядные индексы GLshort.

Когда придет время для рендеринга определенного фрагмента, используйте BaseVertex-based rendering, чтобы выбрать, какой индивидуальный фрагмент вы хотите визуализировать. base_vertex используется для обеспечения смещения индекса. Это смещение должно основываться на максимальном размере куска.

Таким образом, для рендеринга с группой кусков вы минимизируете количество операций привязки буфера, которое вы делаете. И, следовательно, минимизируйте количество изменений состояния между вызовами рисования.

+0

Оказывается, я был в замешательстве. Я думал, что, поскольку привязка IBO является частью состояния VAO (почему?), Она «заблокирована» и не может быть изменена. С вашей помощью и прочитав другие ответы, я наконец понял отношения между VAO, VBOs и IBOs, теперь моя реализация одного VAO работает так, как должна. Очень подробный ответ, большое спасибо (за подсказку производительности тоже)! – yzsolt

Смежные вопросы