Mục đích của các đối tượng Vertex Array của OpenGL là gì?


36

Tôi mới bắt đầu với OpenGL Tôi vẫn chưa thực sự hiểu đối tượng Vertex Array là gì và làm thế nào để sử dụng chúng.

Nếu Đối tượng đệm của Vertex được sử dụng để lưu trữ dữ liệu đỉnh (chẳng hạn như vị trí và tọa độ kết cấu của chúng) và VAO chỉ chứa các cờ trạng thái, chúng có thể được sử dụng ở đâu? Mục đích của họ là gì?

Theo như tôi hiểu từ GL Wiki (rất không đầy đủ và không rõ ràng), VAO được sử dụng để đặt cờ / stats cho mọi đỉnh, theo thứ tự được mô tả trong Element Array Buffer, nhưng wiki thực sự mơ hồ về nó và tôi Tôi không thực sự chắc chắn về những gì VAO thực sự làm và làm thế nào tôi có thể sử dụng chúng.

Câu trả lời:


49

Tôi nghĩ bạn sẽ hiểu mục đích của họ tốt hơn với một mẫu. Bằng cách đọc các bình luận, bạn sẽ hiểu cách sử dụng 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
Tôi có thể làm điều này với dữ liệu bộ đệm GL_DYNAMIC_DRAW không? Phần kết xuất sẽ chỉ chứa glBindVertexArray (), glBufferData () và sau đó là glDrawElements ()?
Piku

Làm thế nào để bạn đối phó với bình thường trong ví dụ này? Ý tôi là nếu bạn thêm một GLfloat normal[3]lớp trong lớp Vertex của bạn và muốn tải lên các thông số cho khách hàng thì sao?
linello

1

VAO rất hữu ích, vì bạn không phải thiết lập mọi lúc mọi thuộc tính. Nó cũng sẽ nhanh hơn khi chỉ liên kết một VAO thay vì thiết lập tất cả các thuộc tính.


1

Đây là liên kết yêu thích của tôi: http://www.songho.ca/opengl/gl_vertexarray.html

Nó sẽ giúp bạn hiểu rõ hơn về sự khác biệt giữa VAO và VBO. Ngoài ra, Id khuyên bạn nên đọc một chương trong OpenGL tuyệt vời về chủ đề này. Nó làm một công việc tốt trong việc giải thích những điều cơ bản này ở độ dài và với các ví dụ.


6
Bài viết bạn liên kết không đề cập đến VAO, chỉ các mảng đỉnh (đã tồn tại lâu hơn một chút). Tôi đang hoang mang về sự khác biệt cụ thể giữa hai bản thân mình.
Steven Lu

Không có nhiều khác biệt. VAO chỉ gói gọn tất cả các trạng thái liên quan đến các mảng đỉnh và tập quán và định dạng của chúng, ngoại trừ chính dữ liệu mảng, được lưu trữ trong VBO. Nhưng bạn nói đúng rằng câu trả lời này (hoặc liên kết) không thực sự nói về VAO.
Chris nói Phục hồi lại

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.