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

OpenGL Сколько VAO

Я пишу приложение OpenGL3 + и немного замешаны в использовании VAO. Прямо сейчас у меня только один VAO, нормализованный квадрат вокруг начала координат. Этот единственный VAO содержит 3 VBOs; один для позиций, один для поверхностных нормалей и один GL_ELEMENT_ARRAY_BUFFER для индексации (поэтому я могу хранить только 4 вершины, а не 6).

Я установил некоторые вспомогательные методы для рисования объектов на сцену, таких как drawCube(), который принимает значения положения и вращения и следует процедуре;

  • Привяжите квадроцикл VAO.
  • На кубической поверхности:
    • Создайте матрицу модели, которая представляет это лицо.
    • Загрузите матрицу модели в переменную uniform mat4 model vertex shader.
    • Вызовите glDrawElements(), чтобы нарисовать квадрат в положение для этого лица.

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

Я только что прочитал вопрос; Лучшие практики OpenGL VAO, в котором говорится, что мой подход неправильный, и что я должен использовать больше VAO для сохранения работы по настройке всей сцены каждый раз.

Сколько VAO должно использоваться? Очевидно, что мой подход с 1 не является оптимальным, должен ли быть VAO для каждой статической поверхности в сцене? Как насчет тех, кто движется?

Я пишу для равномерной переменной для каждой вершины, это правильно? Я читал, что переменные шейдера uniform не должны меняться в середине кадра, если я могу записать разные значения в мою переменную uniform, как униформа отличается от простых переменных in в вершинном шейдере?

4b9b3361

Ответ 1

Ясно, что мой подход с 1 не является оптимальным, должен ли быть VAO для каждой статической поверхности в сцене?

Абсолютно нет. Переключение VAO является дорогостоящим. Если вы выделяете один VAO для каждого объекта в своей сцене, вам нужно переключить VAO перед визуализацией таких объектов. Масштабируйте до нескольких сотен или тысяч объектов, которые в настоящее время видны, и вы получаете столько же изменений VAO. Вопросы состоят в том, что если у вас есть несколько объектов, которые имеют общий макет памяти, т.е. Размеры/типы/нормализация/шаги элементов одинаковы, почему вы хотите определить несколько VAO, которые хранят одну и ту же информацию? Вы управляете смещением, в котором вы хотите начать вытягивать атрибуты вершин напрямую с помощью соответствующего вызова рисования.

Для неиндексированной геометрии это тривиально, так как вы предоставляете first (или массив смещений в аргументе многократного рисования) для gl [Multi] DrawArrays *(), который определяет смещение в ассоциированное хранилище данных ARRAY_BUFFER.

Для индексированной геометрии и если вы храните индексы для нескольких объектов в одном элементе ELEMENT_ARRAY_BUFFER, вы можете использовать gl [Multi] DrawElementsBaseVertex, чтобы обеспечить постоянное смещение индексов или вручную компенсировать ваши индексы, добавив постоянное смещение перед загрузкой их в буферный объект.

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

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

Прежде всего, переменные ввода/вывода формы и шейдера, объявленные как in/out, различаются в разных случаях:

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

  • входные переменные внутри вершинного шейдера заполняются из ARRAY_BUFFER. Униформа внутри однородного блока поддерживается UNIFORM_BUFFER.

  • входные переменные также могут быть записаны непосредственно с помощью семейства функций glVertexAttrib *(). одиночные униформы записываются с использованием семейства функций glUniform *().

  • значения униформы - это состояние программы. значения входных переменных не являются.

Семантическая разница также должна быть очевидной: униформа, как следует из их названия, обычно является постоянной среди набора примитивов, тогда как входные переменные обычно меняются на вершину или фрагмент (из-за интерполяции).

РЕДАКТИРОВАТЬ: пояснить и учесть замечание Николоса Боласа: униформа не может быть изменена приложением для набора вершин, представленных одним вызовом рисования, и атрибуты вершин, вызывающие glVertexAttrib *(). Входы вершинного шейдера, поддерживаемые объектами буфера, будут меняться либо один раз на вершину, либо с определенной скоростью, заданной glVertexAttribDivisor.

EDIT2. Чтобы уточнить, как VAO теоретически может хранить несколько макетов, вы можете просто определить несколько массивов с разными индексами, но с одинаковой семантикой. Например,

glVertexAttribPointer(0, 4, ....);

и

glVertexAttribPointer(1, 3, ....);

может определять два массива с индексами 0 и 1, размером 3 и 4 компонента и оба относятся к атрибутам позиции вершин. Однако, в зависимости от того, что вы хотите визуализировать, вы можете связать гипотетический ввод шейдера вершин

// if you have GL_ARB_explicit_attrib_location or GL3.3 available, use explicit
// locations
/*layout(location = 0)*/ in vec4 Position; 

или

/*layout(location = 1)*/ in vec3 Position;

либо индексировать 0 или 1 явно, либо glBindAttribLocation() и по-прежнему использовать тот же VAO. AFAIK, спецификация ничего не говорит о том, что произойдет, если атрибут включен, но не получен исходным шейдером, но я подозреваю, что реализация просто игнорирует атрибут в этом случае.

Если вы отправляете данные для указанных атрибутов из одного или другого объекта буфера, это еще один вопрос, но, конечно, возможно.

Лично я склонен использовать один VBO и VAO для каждого макета, т.е. если мои данные состоят из одинакового количества атрибутов с одинаковыми свойствами, я помещаю их в один VBO и один VAO.

В общем: вы можете экспериментировать с этим материалом много. Сделай это!