Некоторая терминология немного неправильная:
- A
Vertex Array
- это просто массив (обычно float[]
), содержащий данные вершин.Это не должно быть связано с чем-либо.Не путать с Vertex Array Object
или VAO, о которых я расскажу позже - A
Buffer Object
, обычно называемый Vertex Buffer Object
при хранении вершин, или VBO для краткости, это то, что вы 'Вызывая просто Buffer
. - Ничего не сохраняется обратно в массив вершин,
glVertexAttribPointer
работает точно так же, как glVertexPointer
или glTexCoordPointer
работа, просто вместо именованных атрибутов вы можете указать числоэто определяет ваш собственный атрибут.Вы передаете это значение как index
.Все ваши glVertexAttribPointer
звонки ставятся в очередь на следующий раз, когда вы наберете glDrawArrays
или glDrawElements
.Если у вас есть привязка к VAO, VAO сохранит настройки для всех ваших атрибутов.
Основная проблема заключается в том, что вы путаете атрибуты вершин с VAO.Атрибуты вершин - это просто новый способ определения вершин, текстовых координат, нормалей и т. Д. Для рисования.ВАОс магазин гос.Сначала я объясню, как рисование работает с атрибутами вершин, а затем объясню, как можно сократить количество вызовов методов с помощью VAO:
- Вы должны включить атрибут, чтобы использовать его вшейдер.Например, если вы хотите отправить вершины в шейдер, вы, скорее всего, отправите его в качестве первого атрибута, 0. Поэтому перед рендерингом вам необходимо включить его с помощью
glEnableVertexAttribArray(0);
. - И теперь мы можем определить атрибут -
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
.В порядке параметра: 0 - это атрибут, который вы определяете, 3 - размер каждой вершины, GL_FLOAT
- тип, GL_FALSE
означает не нормализовать каждую вершину, последние 2 нуля означают отсутствие шага или смещения.на вершинах. - Нарисуйте что-нибудь с ним -
glDrawArrays(GL_TRIANGLES, 0, 6);
- Следующее, что вы рисуете, может не использовать атрибут 0 (реально это будет, но это пример), поэтому мы можем отключитьit -
glDisableVertexAttribArray(0);
Оберните это в glUseProgram()
вызовов, и у вас есть система рендеринга, которая работает с шейдерами должным образом.Но скажем, у вас есть 5 различных атрибутов, вершин, текстовых координат, нормалей, координат цвета и карты освещения.Прежде всего, вы будете делать один glVertexAttribPointer
вызов для каждого из этих атрибутов, и вам придется заранее включить все атрибуты.Допустим, вы определяете атрибуты 0-4, как я их перечислил.Вы бы включили все из них следующим образом:
for (int i = 0; i < 5; i++)
glEnableVertexAttribArray(i);
И затем вам придется связывать разные VBO для каждого атрибута (если вы не сохраните их все в одном VBO и не используете смещения / шаг), тогда вам нужносделать 5 различных вызовов glVertexAttribPointer
, от glVertexAttribPointer(0,...);
до glVertexAttribPointer(4,...);
для вершин и координат карты освещения соответственно.
Надеемся, что эта система имеет смысл.Теперь я собираюсь перейти к VAO, чтобы объяснить, как их использовать, чтобы сократить количество вызовов методов при выполнении этого типа рендеринга.Обратите внимание, что использование VAO не обязательно.
A Vertex Array Object
или VAO используется для хранения состояния всех вызовов glVertexAttribPointer
и VBO, которые были нацелены, когда был сделан каждый из вызовов glVertexAttribPointer
.
Вы генерируете один вызов glGenVertexArrays
.Чтобы хранить все, что вам нужно, в VAO, свяжите его с glBindVertexArray
, а затем выполните полный вызов ничьей Все вызовы draw bind перехватываются и сохраняются VAO.Вы можете отменить привязку VAO с помощью glBindVertexArray(0);
Теперь, когда вы хотите нарисовать объект, вам не нужно повторно вызывать все привязки VBO или glVertexAttribPointer
, вам просто нужно привязатьVAO с glBindVertexArray
, затем вызовите glDrawArrays
или glDrawElements
, и вы будете рисовать точно так же, как если бы вы делали все эти вызовы методов.Возможно, вы захотите потом отменить привязку VAO.
Как только вы открепите VAO, все состояние вернется к тому, что было до того, как вы связали VAO. Я не уверен, сохраняются ли какие-либо изменения, которые вы вносите во время привязки VAO, но это легко определить с помощью тестовой программы. Я думаю, вы можете думать о glBindVertexArray(0);
как о привязке к "по умолчанию" VAO ...
Обновление: Кто-то обратил мое внимание на необходимость фактического розыгрыша. Как выясняется, при настройке VAO вам на самом деле не нужно выполнять FULL-вызов, только все связывающие вещи. Не знаю, почему я думал, что это было необходимо раньше, но сейчас это исправлено.