วัตถุประสงค์ของ Vertex Array Objects คืออะไร?


36

ฉันเพิ่งเริ่มต้นด้วย OpenGL ฉันยังไม่เข้าใจจริงๆว่า Vertex Array Objects คืออะไรและสามารถใช้งานได้อย่างไร

ถ้า Vertex Buffer Object ถูกใช้เพื่อจัดเก็บข้อมูลจุดสุดยอด (เช่นตำแหน่งและพิกัดพื้นผิว) และ VAOs จะมีเฉพาะสถานะแฟล็กซึ่งสามารถใช้งานได้ที่ไหน? วัตถุประสงค์ของพวกเขาคืออะไร?

เท่าที่ฉันเข้าใจจากวิกิพีเดีย (ไม่สมบูรณ์และไม่ชัดเจน) VAOs จะใช้ในการตั้งค่าสถานะ / สถิติสำหรับทุกจุดสุดยอดตามคำสั่งที่อธิบายไว้ใน Element Array Buffer แต่วิกินั้นคลุมเครือเกี่ยวกับมันและฉัน ' m ไม่แน่ใจจริงๆเกี่ยวกับสิ่งที่ VAOs ทำจริงๆและฉันจะจ้างพวกเขาได้อย่างไร

คำตอบ:


49

ฉันคิดว่าคุณจะเข้าใจวัตถุประสงค์ของพวกเขาดีขึ้นด้วยตัวอย่าง โดยการอ่านความคิดเห็นที่คุณจะเข้าใจวิธีการใช้ VAOs

// 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 () หรือไม่
Piku

คุณจะจัดการกับบรรทัดฐานในตัวอย่างนี้ได้อย่างไร ฉันหมายถึงถ้าคุณเพิ่มGLfloat normal[3]คลาส Vertex ของคุณและต้องการอัพโหลดบรรทัดฐานให้กับลูกค้า
linello

1

VAO นั้นมีประโยชน์เพราะคุณไม่จำเป็นต้องตั้งค่าคุณลักษณะทุกครั้ง นอกจากนี้ควรเร็วขึ้นเพียงผูก VAO หนึ่งรายการแทนที่จะตั้งค่าคุณลักษณะทั้งหมด


1

นี่คือลิงค์โปรดของฉัน: http://www.songho.ca/opengl/gl_vertexarray.html

มันจะช่วยให้คุณเข้าใจความแตกต่างระหว่าง VAO และ VBO ได้ดีขึ้น นอกจากนี้ Id แนะนำให้อ่านบทใน OpenGL ที่ยอดเยี่ยมในหัวข้อนี้ มันเป็นการทำงานที่ดีในการอธิบายพื้นฐานเหล่านี้อย่างละเอียดและเป็นตัวอย่าง


6
บทความที่คุณเชื่อมโยงไม่ครอบคลุมของ VAO เฉพาะอาร์เรย์จุดสุดยอด (ซึ่งได้รับรอบนานกว่า) ฉันงงกับความแตกต่างเฉพาะระหว่างสองคนนี้
Steven Lu

มีความแตกต่างไม่มาก VAO เพียงแค็ปซูลรัฐทั้งหมดที่เกี่ยวกับอาร์เรย์จุดสุดยอดและการใช้งานและรูปแบบของพวกเขายกเว้นข้อมูลอาร์เรย์ตัวเองซึ่งถูกเก็บไว้ใน VBOs แต่คุณพูดถูกในคำตอบนี้ (หรือลิงค์) ไม่ได้พูดถึง VAO
Chris บอกว่า Reinstate Monica

0

การบรรยายที่ 9 ที่นี่http://nccastaff.bournemouth.ac.uk/jmacey/CA1/index.htmlมีเนื้อหาบางอย่างเกี่ยวกับมัน (เช่นเดียวกับส่วนที่เหลือของบันทึกย่อของฉัน) และหากคุณดูห้องสมุด NGL ในเว็บไซต์เดียวกันฉันมี คลาสที่ล้อมรอบพฤติกรรมของ VAO

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.