OpenGL: เป็นไปได้ไหมที่จะใช้ VAO โดยไม่ระบุ VBO


12

ในแบบฝึกหัดทั้งหมดที่ฉันพบเกี่ยวกับ VAO (Vertex Array Objects) พวกเขาแสดงวิธีการใช้พวกเขาโดยการกำหนดค่าคุณลักษณะจุดสุดยอดและผูก VBO (Vertex Buffer Object) แต่ฉันต้องการสร้าง VAO ที่จะกำหนดค่าสำหรับชุด VBO's ร่วมกับ shader คงที่ซึ่งแต่ละบัฟเฟอร์ใช้รูปแบบข้อมูลเดียวกัน (จุดยอด, UV, สี, ฯลฯ ) ดังนั้นฉันต้องการสร้างหนึ่ง VAO สำหรับ VBO หลายรายการที่จะถูกวาดโดยใช้หนึ่ง shader

ฉันไม่พบตัวอย่างใด ๆ เกี่ยวกับเรื่องนี้ดังนั้นฉันจึงตัดสินใจลองทำดู แต่มันไม่ทำงานและล้มเหลวในการglDrawArrayโทร ดูเหมือนว่า VBO จะไม่ถูกผูกไว้ นี่คือรหัสที่ฉันใช้:

การแสดงผล:

/* Prepare vertex attributes */
glBindVertexArrayOES(vao);

/* Upload the buffer to the GPU */
glBindBuffer(GL_ARRAY_BUFFER, pool->next());
glBufferSubData(GL_ARRAY_BUFFER, 0, parts * buffer.stride() * 6, buffer.getBuffer());

/* Draw the triangles */
glDrawArrays(GL_TRIANGLES, 0, parts * 6);

glBindVertexArrayOES(0);

การสร้าง VAO:

glBindVertexArrayOES(vao);

glEnableVertexAttribArray(ls.position);
glVertexAttribPointer(ls.position, 2, GL_FLOAT, GL_FALSE, buffer.stride(), 0);

glEnableVertexAttribArray(ls.color);
glVertexAttribPointer(ls.color, 3, GL_FLOAT, GL_FALSE, buffer.stride(), GL_BUFFER_OFFSET(buffer.dataTypeSize * 2));

glBindVertexArrayOES(0);

ที่ไหนlsเป็นแบบง่ายstructที่เก็บตำแหน่งแอตทริบิวต์

ในส่วนของการเรนเดอร์การสลับglBindBufferและglBindVertexArrayOESรอบ ๆ ใช้ไม่ได้

ดังนั้นคำถามคือ: มันเป็นไปได้ที่จะทำเช่นนั้นหรือฉันจะต้องสร้าง VAO แต่ละบัฟเฟอร์หรือไม่ และถ้าฉันต้องสร้าง VAO สำหรับแต่ละ VBO เป็นไปได้หรือไม่ที่จะอัปเดตข้อมูล VBO ที่ใช้glBufferSubDataร่วมกับ VAO

คำตอบ:


18

VAOs ไม่มีสถานะ "glBindBuffer" ด้วยข้อยกเว้นของGL_ELEMENT_ARRAY_BUFFERสถานะการรวมของ สิ่งที่คุณไม่เข้าใจก็คือglBindBuffer(GL_ARRAY_BUFFER) ไม่ทำอะไรเลย มันไม่ได้ทำอะไรเลยเท่าที่เรนเดอร์เกี่ยวข้อง ลองมัน; ก่อนเรียก glDraw *, call glBindBuffer(GL_ARRAY_BUFFER, 0); การแสดงผลของคุณจะทำงานได้ดี

วิธีการglVertexAttribPointerทำงานคือว่ามันมีลักษณะที่สิ่งที่ถูกผูกไว้กับ GL_ARRAY_BUFFER ในช่วงเวลาที่glVertexAttribPointerเรียกว่า ไม่ใช่เวลาเรนเดอร์ ไม่ช้า ในช่วงเวลาที่แน่นอนนั้น มันต้องใช้วัตถุบัฟเฟอร์อะไรก็ตามที่อยู่ที่นั่นและเก็บไว้ในสถานะ OpenGL อีกส่วนหนึ่งซึ่งถูกหุ้มไว้ภายใน VAO

โดยทั่วไปคุณมีสองตัวเลือกหนึ่งในนั้นคือใหม่และอาจไม่ควรใช้ ณ เวลานี้

ตัวเลือกแรกของคุณคือการวางวัตถุทั้งหมดที่ใช้รูปแบบจุดสุดยอดเดียวกัน(เช่น: ทุกอย่างยกเว้นวัตถุบัฟเฟอร์และออฟเซ็ต) ในวัตถุบัฟเฟอร์เดียวกัน โดยพื้นฐานแล้วสร้างอาร์เรย์ขนาดยักษ์ที่มีจุดยอดทั้งหมดสำหรับวัตถุทั้งหมดที่ใช้รูปแบบเดียวกัน

เมื่อถึงเวลาที่ต้องเรนเดอร์คุณสามารถเรนเดอร์ส่วนหนึ่งของจุดยอดได้ glDrawArraysใช้องค์ประกอบหลายอย่างในการแสดงผลและคุณสามารถปรับดัชนีของคุณglDrawElementsให้เป็นแบบเดียวกันได้ หรือคุณสามารถใช้glDrawElementsBaseVertexเพื่อตั้งค่าจุดยอดเพื่อเพิ่มออฟเซ็ตในแต่ละดัชนี ออฟเซ็ตนี้คือจำนวนของจุดยอดก่อนหน้าจุดยอดนั้นในอาร์เรย์ขนาดใหญ่

อีกทางเลือกหนึ่งคือการใช้ระบบแยกแอตทริบิวต์รูปแบบใหม่ที่เพิ่มใน GL 4.3 มันจะช่วยให้คุณเปลี่ยนบัฟเฟอร์โดยไม่ต้องรีเซ็ตรูปแบบ ดังนั้นคุณจะผูก VAO glBindVertexBufferเดียวแล้วเพียงแค่ทดแทนในบัฟเฟอร์ที่แตกต่างกันตามความจำเป็นด้วย สิ่งนี้ยังมีอยู่ใน ES 3.1


1
ตอนนี้ไดรเวอร์ NV GL4.3 ได้รับการเผยแพร่เต็มรูปแบบแล้ว
Maximus Minimus

ขอบคุณมากที่อธิบายวิธีการทำงานของ glVertexAttribPointer นั่นคือความกระจ่างแจ้งและอธิบายว่าทำไมและวิธีการทำงาน
Martijn Courteaux

5

VAO เก็บสถานะ glVertexAttribPointer การเปลี่ยน VAO ไม่ส่งผลกระทบต่อ glBindBuffer ปัจจุบันหรือการเปลี่ยนแปลง glBindBuffer จะส่งผลต่อ VAO เฉพาะการเรียก glVertexAttribPointer เท่านั้นที่มีผลต่อ VAO โดยการบันทึกบัฟเฟอร์ที่ใช้ในการโทร

ดังนั้นคำตอบสำหรับคำถามของคุณคือไม่

ตัวเลือกหนึ่งถ้าคุณต้องการลดจำนวนวัตถุคือการใส่ข้อมูล mesh ทั้งหมดของคุณลงใน VBO ขนาดใหญ่และระบุตำแหน่งที่ข้อมูลตาข่ายอาศัยอยู่ใน VBO ในการเรียกใช้ glDrawArrays โดยใช้อาร์กิวเมนต์ 'แรก' และ 'นับ'


บทความทั้งหมดบนอินเทอร์เน็ตในรายการ VAO ที่เชื่อม VAO ผูก VBO โดยอัตโนมัติ ดังนั้นฉันคิดว่า VAO คือการกำหนดค่าที่มีทั้ง glVertexAttribPointer และสถานะglBindBuffer และใช่ผูก VBO เมื่อ VAO ถูกผูกไว้เปลี่ยน VAO ฉันกำลังบอกสิ่งนี้เพราะฉันทดสอบสิ่งนี้และทำอย่างมีประสิทธิภาพ ข้อมูลนี้มาจากไหน
Martijn Courteaux

2
@MartijnCourteaux: " บทความทั้งหมดบนอินเทอร์เน็ตในรายการ VAO ที่มีผลผูกพัน VAO ผูก VBO โดยอัตโนมัติ " ไม่พวกเขาไม่ OpenGL Wiki บนข้อมูลจำเพาะจุดสุดยอดไม่ได้ แน่นอนแสดงบทความเดียวบนอินเทอร์เน็ตที่บอกว่าglBindBufferรัฐใด ๆยกเว้น GL_ELEMENT_ARRAY_BUFFERมีการเปลี่ยนแปลงโดยการผูก VAO
Nicol Bolas

คำตอบอื่น ๆ อธิบายได้ดีว่าวิธีการ glVertexAttribPointer ทำงานอย่างไร มันใช้ VBO ที่ถูกผูกไว้ในเวลานั้น คุณพูดถูก! ขอบคุณฉันเข้าใจทันที
Martijn Courteaux
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.