Подтвердить что ты не робот

OpenGL, VAO и несколько буферов

Я пишу небольшой графический движок, используя OpenGL (через OpenTK с С#).

Чтобы определить атрибуты вершин, у меня есть класс VertexDeclaration с массивом структур VertexElement, которые сопоставляются с вызовами glEnableVertexAttribArray/glVertexAttribPointer.

Кроме того, для поддержки нескольких вершинных потоков у меня есть специальная структура, содержащая буфер вершин, объявление вершин, смещение вершин и частота экземпляра (например, структура XNA VertexBufferBinding).

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

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

Это правильное использование VAO?

4b9b3361

Ответ 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 для каждого объекта.