Объекты буфера вершин (VBOs) содержат данные вершин. Вы устанавливаете указатели на указатели, которые определяют, как эти данные должны быть доступны и интерпретированы для того, чтобы нарисовать вершину - сколько компонентов есть в каждой вершине, как они хранятся (например, GL_FLOAT) и т. Д.
Объект вершинного массива (VAO) сохраняет все эти атрибуты. Их цель - позволить вам настроить эти атрибуты один раз, а затем восстановить их с одним изменением состояния, когда вам нужно их использовать.
Преимущество этого в том, что вы можете легко установить несколько состояний и восстановить их - если я хочу нарисовать куб и треугольник, это два разных состояния - я создаю VAO для каждого, а VAO сохраняет состояние для каждого из них. Когда я хочу нарисовать куб, я восстанавливаю состояние только для куба.
Настройка
Установка имеет четыре шага:
- Создание ВАО
- свяжи VAO
- Настройка состояния
- Unbind в ВАО
Создание ВАО очень просто:
GLuint vao_name;
glGenVertexArrays(1, &vao_name);
Это создаст один массив вершин, и сохранить его имя в vao_name.
После того, как ваш VAO создается вам необходимо связать его:
glBindVertexArray(vao_name);
Теперь любые изменения, вносимые в указатели атрибутов или привязок в буфер массива элемент будет сохранен. Это призыв к любому из следующих действий:
- glVertexAttribPointer (...)
- glEnableVertexAttribArray (...)
- glDisableVertexAttribArray (...)
- glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, ...)
Всякий раз, когда вы совершаете один из этих вызовов, соответствующее состояние сохраняется в текущем связанном VAO. И когда вы позже свяжете VAO, состояние будет восстановлено.
Как только вы настроили состояние, вы можете развязать VAO. Сделайте это, связывая VAO 0:
glBindVertexArrays(0);
Вы также можете связать другое VAO и настроить для этого другое состояние. В этом случае безопасно вносить изменения в указатели атрибутов, не нарушая прежнее состояние.
Рисунок
Если вы хотите сделать что-то все, что вам нужно сделать, это восстановить ВАО:
glBindVertexArray(cube_vao)
glDrawArrays(GL_TRIANGLES, 0, 36);
glBindVertexArray(triangle_vao);
glDrawArrays(GL_TRIANGLES, 0, 3);
glBindVertexArray(0); //Unbind the VAO
Edit:
Вот некоторые ответы, которые помогли мне, когда я был пытаясь понять ВАО: glVertexAttribPointer overwrite, glVertexAttribPointer clarification, When should glVertexAttribPointer be called?
Кроме того, спецификация OpenGL объясняет это хорошо, как только вы получили вашу голову вокруг основы: https://www.opengl.org/registry/
Это было задано в аналогичной форме много раз раньше. См. Например, мой ответ здесь: http://stackoverflow.com/questions/26552642/when-is-what-bound-to-a-vao/26559063#26559063. Или здесь: http://stackoverflow.com/questions/26228498/glvertexattribpointer-overwrite/26229019#26229019. –
Я обнаружил, что эта концепция на самом деле не очень хорошо покрыта, недавно она сама обняла меня. Существует информация об этом, но она фрагментирована и либо не появляется при поиске, либо похоронена под существенным шумом. – Francis