Какова цель объектов Vertex Array в OpenGL?


36

Я только начал с OpenGL. Я до сих пор не понял, что такое Vertex Array Objects и как их можно использовать.

Если объект буфера вершин используется для хранения данных вершин (таких как их позиции и координаты текстуры), а VAO содержат только флаги состояния, где их можно использовать? Какова их цель?

Насколько я понял из (очень неполной и неясной) GL Wiki, VAO используются для установки флагов / статусов для каждой вершины, следуя порядку, описанному в элементном буфере массива, но вики действительно была неоднозначна, и я Я не совсем уверен в том, что на самом деле делают ВАО и как я могу их использовать.

Ответы:


49

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

// BEGIN INITIALIZATION
// Define some vertex data 
struct Vertex {
  GLfloat position[3];
  GLfloat texcoord[2];
};
Vertex vertexdata[NUM_VERTS] = { ... };
GLubyte indexdata[NUM_INDICES] = { 0, 1, 2, ... };

// Create and bind a VAO
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);

// Create and bind a BO for vertex data
GLuint vbuffer;
glGenBuffers(1, &vbuffer);
glBindBuffer(GL_ARRAY_BUFFER, vbuffer);

// copy data into the buffer object
glBufferData(GL_ARRAY_BUFFER, NUM_VERTS * sizeof(Vertex), vertexdata, GL_STATIC_DRAW);

// set up vertex attributes
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, position));
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, texcoord));

// Create and bind a BO for index data
GLuint ibuffer;
glGenBuffers(1, &ibuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibuffer);

// copy data into the buffer object
glBufferData(GL_ELEMENT_ARRAY_BUFFER, NUM_INDICES * sizeof(GLubyte), indexdata, GL_STATIC_DRAW);

// At this point the VAO is set up with two vertex attributes
// referencing the same buffer object, and another buffer object
// as source for index data. We can now unbind the VAO, go do
// something else, and bind it again later when we want to render
// with it.

glBindVertexArray(0);

// END INITIALIZATION

// BEGIN RENDER LOOP

// This is it. Binding the VAO again restores all buffer 
// bindings and attribute settings that were previously set up
glBindVertexArray(vao);
glDrawElements(GL_TRIANGLES, NUM_INDICES, GL_UNSIGNED_BYTE, (void*)0);

// END RENDER LOOP

2
Могу ли я сделать это с буферными данными GL_DYNAMIC_DRAW? Будет ли часть рендеринга содержать только glBindVertexArray (), glBufferData () и затем glDrawElements ()?
Пику

Как вы справляетесь с нормалями в этом примере? Я имею в виду, что если вы добавите a GLfloat normal[3]в свой класс Vertex и хотите загрузить нормали к клиенту?
linello

1

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


1

Это моя любимая ссылка: http://www.songho.ca/opengl/gl_vertexarray.html

Это должно помочь вам лучше понять различия между VAO и VBO. Кроме того, я рекомендую прочитать главу в OpenGL Superbible по этой теме. Он хорошо объясняет эти основы подробно и с примерами.


6
Статья, на которую вы ссылаетесь, не охватывает VAO, а только массивы вершин (которые были где-то дольше). Я ломаю голову над определенными различиями между этими двумя непосредственно.
Стивен Лу

Там нет большой разницы. VAO просто инкапсулирует все состояния, касающиеся массивов вершин, их использования и форматов, за исключением самих данных массива, которые хранятся в VBO. Но вы правы в том, что этот ответ (или ссылка) на самом деле не говорит о ВАО.
Крис говорит восстановить Монику

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.