Яка мета об’єктів вершинного масиву 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.