Яка мета об’єктів вершинного масиву OpenGL?


36

Я щойно розпочав роботу з OpenGL, я все ще не дуже розумів, що таке об’єкти Vertex Array і як їх можна використовувати.

Якщо об'єкт буферних вершин використовується для зберігання даних вершин (таких як їх положення та координати текстури), а VAO містять лише прапори стану, де їх можна використовувати? Яке їх призначення?

Наскільки я зрозумів із (дуже неповної та незрозумілої) GL Wiki, VAO використовуються для встановлення прапорів / statūs для кожної вершини, дотримуючись порядку, описаного в буфері елементів масиву елементів, але вікі про це дійсно неоднозначно, і я ' я не дуже впевнений у тому, чим реально займаються ВАО і як я міг би їх використовувати.

Відповіді:


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 ()?
Піку

Як ви в цьому прикладі ставитесь до норм? Я маю на увазі, що якщо ви додасте 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. Але ви праві, що ця відповідь (або посилання) насправді не говорить про VAO.
Кріс каже, що повернеться до Моніки

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.