Ответ 1
нетЭто правильное использование VAO?
Нет 1.
glVertexAttribPointer
использует объект буфера, который был привязан к GL_ARRAY_BUFFER
в момент вызова функции, Поэтому вы не можете этого сделать:
glVertexAttribPointer(...);
glBindBuffer(GL_ARRAY_BUFFER, bufferObject);
glDrawArrays(...);
Это не будет использовать bufferObject
; он будет использовать все, что было привязано к GL_ARRAY_BUFFER
, когда изначально был вызван glVertexAttribPointer
.
VAO захватывают это состояние. Таким образом, VAO будет для каждого атрибута вершины хранить любой объект буфера, привязанный к GL_ARRAY_BUFFER
, когда он был вызван. Это позволяет вам делать такие вещи:
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, buffer1);
glVertexAttribPointer(0, ...);
glVertexAttribPointer(1, ...);
glBindBuffer(GL_ARRAY_BUFFER, buffer2);
glVertexAttribPointer(2, ...);
Атрибуты 0 и 1 будут получены из buffer1
, а атрибут 2 - от buffer2
. ВАО теперь захватывает все это состояние. Для рендеринга вы просто делаете это:
glBindVertexArray(VAO);
glDraw*();
Короче говоря, если вы хотите изменить место хранения атрибутов в OpenGL, вы также должны изменить его формат. Даже если это тот же формат, вы должны снова вызвать glVertexAttribPointer
.
1: В этом обсуждении предполагается, что вы не используете новый ARB_vertex_attrib_binding. Или, как известно, " Точно как Direct3D связывает атрибут вершин." Если вы используете реализация, которая предлагает это расширение, вы можете эффективно делать то, о чем говорите, потому что формат атрибута не связан с хранилищем объектов буфера. Кроме того, мучительная логика glVertexAttribPointer
исчезла.
В общем, способ, которым мы решаем это в мире OpenGL, заключается в том, чтобы как можно больше вещей в одном и том же объекте буфера. В противном случае просто используйте один VAO для каждого объекта.