2012-08-06 6 views
80

Я только начинаю изучать OpenGL сегодня из этого урока: http://openglbook.com/the-book/
Я добрался до главы 2, где я рисую треугольник, и я все понимаю, кроме VAO (это аббревиатура ОК?). Учебник имеет следующий код:Что такое объекты вершинного массива?

glGenVertexArrays(1, &VaoId); 
glBindVertexArray(VaoId); 

Хотя я понимаю, что код надо, я понятия не имею, что он делает. Хотя я никогда не использую VaoId за этот момент (кроме его уничтожения), код не работает без него. Я предполагаю, что это связано с тем, что требуется связать, но я не знаю, почему. Этот точный код просто должен быть частью каждой программы OpenGL? Руководство объясняет, как VAOs:

A Vertex массив объектов (или ВАО) является объектом, который описывает, как атрибуты вершин хранятся в объекте вершинного буфера (или VBO). Это означает, что VAO не является фактическим объектом, хранящим данные вершин, а дескриптором данных вершин. Атрибуты вершины могут быть описаны функцией glVertexAttribPointer и ее двумя сестринскими функциями glVertexAttribIPointer и glVertexAttribLPointer, первый из которых мы рассмотрим ниже.

Я не понимаю, как VAO описывает атрибуты вершин. Я никоим образом не описал их. Получает ли он информацию из glVertexAttribPointer? Думаю, это и должно быть. Является ли VAO просто пунктом назначения для информации из glVertexAttribPointer?

На боковой ноте, является ли учебное пособие приемлемым? Есть ли что-нибудь, за чем я должен следить или лучше следовать учебнику?

ответ

77

«Объект Vertex Array» представлен вам подкомитетом OpenGL ARB для глупых имен.

Подумайте об этом как о объекте геометрии. (Как старый программист SGI Performer, я называю их георешетками.) Переменные экземпляра/члены объекта - ваш указатель вершин, нормальный указатель, указатель цвета, указатель N указателя, ...

Когда VAO является первым вы назначаете этих членов по телефону

glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer...; 
glEnableClientState(GL_NORMAL_ARRAY); glNormalPointer...; 

и так далее. Какие атрибуты включены, а указатели, которые вы поставляете, хранятся в VAO.

После этого, когда вы снова привязываете VAO, все атрибуты и указатели также становятся текущими. Таким образом, один вызов glBindVertexArray эквивалентен коду, который ранее использовался для настройки всех атрибутов. Это удобно для прохождения геометрии вокруг функций или методов без необходимости создавать свои собственные структуры или объекты.

(Одна установки времени, многократное использование является самым простым способом использовать VAOs, но вы можете также изменить атрибуты только путем связывания его и делать больше включить/указатель вызовов. VAOs не являются константами.)

Более подробной информации в ответ на вопросы Патрика:

По умолчанию для вновь созданного VAO установлено, что он пуст (AFAIK). Никакой геометрии вообще, даже не вершин, поэтому, если вы попытаетесь ее нарисовать, вы получите ошибку OpenGL. Это разумно разумно, как в «инициализировать все до False/NULL/zero».

Вам нужно только glEnableClientState, когда вы настраиваете вещи. VAO запоминает состояние включения/выключения для каждого указателя.

Да ВАО будет хранить glEnableVertexAttribArray и glVertexAttrib. Старые массивы vertex, normal, color, ... аналогичны массивам атрибутов, вершине == # 0 и т. Д.

+41

«Объект вершинного массива» представлен вам подкомитетом OpenGL ARB для глупых имен. Да, такое глупое имя для ** объекта **, который хранит ** vertex ** ** array ** привязки. –

+0

Если я правильно вас понимаю, вызывая 'glGenVertexArrays (1, & VaoId);' и 'glBindVertexArray (VaoId);' создает VAO со стандартными значениями по умолчанию, чтобы спасти вас от 'glEnableClientState'? Или я полностью вас недопонимаю? В будущем, скорее всего, я буду использовать много 'glEnableClientState'? – Patrick

+2

Кроме того, VAO вообще связаны с 'glVertexAttribPointer' – Patrick

8

Vertex Array Объекты похожи на макросы в программах обработки текстов и т.п. Хорошее описание here.

Макросы просто запомнить действий, которые вы делали, например, активировать этот атрибут, связать этот буфер, и т.д. Когда вы звоните glBindVertexArray(yourVAOId), это просто повторов тех атрибуты указателей привязки и буфера привязок.

Итак, ваш следующий призыв к розыгрышу использует все, что было связано с VAO.

VAO не храните данные вершин. Нет. Вершинные данные хранятся в вершине буфера или в массиве клиентской памяти.

+12

-1: Они не похожи на макросы. Если бы они были, то привязка нового VAO не приведет к отключению вершинных массивов, разрешенных предыдущим VAO, если новое VAO не «записало» вас * явно * отключив эти массивы. VAO, как * все * объекты OpenGL, удерживают * состояние *, а не команды. Команды просто * изменяют * состояние, но объекты имеют заданное состояние по умолчанию. Вот почему привязка вновь созданного VAO будет * всегда * отключать все атрибуты. –

4

VAO - это объект, представляющий этап выборки вершины конвейера OpenGL и используемый для подачи ввода в вершинный шейдер.

Вы можете создать вершинный массив объектов, как этот

GLuint vao; 
glCreateVertexArrays(1, &vao); 
glBindVertexArray(vao); 

Сначала давайте делать простой пример. Рассмотрим такой входной параметр в коде шейдера

layout (location = 0) in vec4 offset; // input vertex attribute 

Для заполнения этого атрибута мы можем использовать

glVertexAttrib4fv(0, attrib); // updates the value of input attribute 0 

Хотя массив вершин объектов хранит эти статические значения атрибутов для вас, он может сделать много Больше.

После создания объекта массива вершин мы можем начать заполнять его состояние. Мы попросим OpenGL заполнить его автоматически, используя данные, хранящиеся в буферном объекте, который мы поставляем. Каждый атрибут вершины получает выборку из буфера, связанного с одним из нескольких привязок буфера вершин. Для этого воспользуемся glVertexArrayAttribBinding(GLuint vao, GLuint attribindex, GLuint bindingindex). Также мы используем функцию glVertexArrayVertexBuffer() для привязки буфера к одному из привязок буфера вершин. Мы используем функцию glVertexArrayAttribFormat() для описания макета и формата данных, и, наконец, мы включаем автоматическое заполнение атрибута, вызывая glEnableVertexAttribArray().

Если атрибут вершина включена, OpenGL будет передавать данные в вершинный шейдер на основе информации о формате и месте вы снабженным glVertexArrayVertexBuffer() и glVertexArrayAttribFormat(). Когда атрибут отключен, вершинный шейдер будет снабжен статической информацией, которую вы предоставляете, с вызовом glVertexAttrib*().

// First, bind a vertex buffer to the VAO 
glVertexArrayVertexBuffer(vao, 0, buffer, 0, sizeof(vmath::vec4)); 

// Now, describe the data to OpenGL, tell it where it is, and turn on automatic 
// vertex fetching for the specified attribute 
glVertexArrayAttribFormat(vao, 0, 4, GL_FLOAT, GL_FALSE, 0); 

glEnableVertexArrayAttrib(vao, 0); 

И код шейдера

layout (location = 0) in vec4 position; 

В конце концов вам нужно позвонить в glDeleteVertexArrays(1, &vao).


Вы можете прочитать OpenGL SuperBible, чтобы лучше понять его.

+2

Приятно видеть людей, продвигающих использование OpenGL в стиле DSA. –