Что такое объекты массива вершин?


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

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

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

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

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

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

3 85

3 ответа:

" объект массива вершин " доставляется вам подкомитетом OpenGL ARB для глупых имен.

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

когда ВАО сначала привязывается, вы назначаете эти члены, вызывая

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

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

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

(однократная настройка, многократное использование-это самый простой способ использовать VAOs, но вы также можете изменить атрибуты просто связывая его и делая больше вызовов enable/pointer. ВАО не являются константами.)

дополнительная информация в ответ на вопросы Патрика:

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

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

да ВАО будет хранить glEnableVertexAttribArray и glVertexAttrib. Старая вершина, нормальная, цветная ... массивы такие же, как массивы атрибутов, vertex == #0 и так далее.

объекты массива вершин похожи на макрос в текстовых программах и тому подобное. Хорошее описание найдено здесь.

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

поэтому ваш следующий вызов draw использует все, что было связано с ВАО.

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

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 чтобы понять это лучше.