คำศัพท์บางคำอาจไม่ถูกต้อง:
- A
Vertex Array
เป็นเพียงอาร์เรย์ (โดยทั่วไปคือ a float[]
) ที่มีข้อมูลจุดยอด ไม่จำเป็นต้องผูกพันกับสิ่งใด ไม่ต้องสับสนกับ a Vertex Array Object
หรือ VAO ซึ่งฉันจะพูดถึงในภายหลัง
- A
Buffer Object
โดยทั่วไปเรียกว่าVertex Buffer Object
เมื่อเก็บจุดยอดหรือ VBO สั้น ๆ คือสิ่งที่คุณเรียกว่าเป็นเพียงไฟล์Buffer
.
- ไม่มีสิ่งใดถูกบันทึกกลับไปยังอาร์เรย์จุดสุดยอด
glVertexAttribPointer
ทำงานเหมือนglVertexPointer
หรือglTexCoordPointer
ทำงานได้ทุกประการแทนที่จะเป็นแอตทริบิวต์ที่ตั้งชื่อคุณจะต้องระบุตัวเลขที่ระบุคุณลักษณะของคุณเอง index
คุณผ่านค่านี้เป็น ทั้งหมดของคุณglVertexAttribPointer
โทรได้คิวขึ้นสำหรับครั้งต่อไปที่คุณโทรหรือglDrawArrays
glDrawElements
หากคุณมี VAO ผูกไว้ VAO จะจัดเก็บการตั้งค่าสำหรับแอตทริบิวต์ทั้งหมดของคุณ
ปัญหาหลักคือคุณกำลังสับสนแอตทริบิวต์จุดยอดกับ VAO แอตทริบิวต์จุดยอดเป็นเพียงวิธีใหม่ในการกำหนดจุดยอดเท็กซ์คูร์บรรทัดฐาน ฯลฯ สำหรับการวาด สถานะร้านค้า VAO ก่อนอื่นฉันจะอธิบายว่าการวาดภาพทำงานกับแอตทริบิวต์จุดยอดอย่างไรจากนั้นอธิบายว่าคุณสามารถลดจำนวนวิธีการเรียกด้วย VAO ได้อย่างไร:
- คุณต้องเปิดใช้งานแอตทริบิวต์ก่อนจึงจะใช้ใน shader ได้ ตัวอย่างเช่นถ้าคุณต้องการที่จะส่งไปยังจุด Shader คุณกำลังส่วนใหญ่มีแนวโน้มจะส่งเป็นแอตทริบิวต์แรก 0.
glEnableVertexAttribArray(0);
ดังนั้นก่อนที่จะทำให้คุณต้องเปิดการใช้งานด้วย
- เมื่อเปิดใช้งานแอตทริบิวต์แล้วคุณต้องกำหนดข้อมูลที่จะใช้ เพื่อที่จะทำดังนั้นคุณจำเป็นต้องผูก VBO คุณ
glBindBuffer(GL_ARRAY_BUFFER, myBuffer);
-
- และตอนนี้เราสามารถกำหนดแอตทริบิวต์
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
- ตามลำดับของพารามิเตอร์: 0 คือแอตทริบิวต์ที่คุณกำลังกำหนด 3 คือขนาดของจุดยอดแต่ละจุดGL_FLOAT
คือประเภทGL_FALSE
หมายถึงการไม่ทำให้จุดยอดแต่ละจุดเป็นปกติเลขศูนย์ 2 ตัวสุดท้ายหมายความว่าไม่มีการก้าวข้ามหรือหักล้างจุดยอด
- วาดบางอย่างด้วย -
glDrawArrays(GL_TRIANGLES, 0, 6);
- สิ่งต่อไปที่คุณวาดอาจไม่ใช้แอตทริบิวต์ 0 (ตามความเป็นจริงจะเป็น แต่นี่เป็นตัวอย่าง) ดังนั้นเราจึงสามารถปิดใช้งานได้ -
glDisableVertexAttribArray(0);
รวมสิ่งนั้นไว้ในการglUseProgram()
โทรและคุณมีระบบการแสดงผลที่ทำงานร่วมกับเฉดสีได้อย่างเหมาะสม แต่สมมติว่าคุณมี 5 แอตทริบิวต์จุดยอดเท็กซ์คอยด์บรรทัดฐานสีและพิกัดไลท์แมปที่แตกต่างกัน ก่อนอื่นคุณจะglVertexAttribPointer
โทรเพียงครั้งเดียวสำหรับแต่ละแอตทริบิวต์เหล่านี้และคุณต้องเปิดใช้งานแอตทริบิวต์ทั้งหมดก่อน สมมติว่าคุณกำหนดแอตทริบิวต์ 0-4 ตามที่ฉันระบุไว้ คุณจะเปิดใช้งานทั้งหมดดังนี้:
for (int i = 0; i < 5; i++)
glEnableVertexAttribArray(i);
และจากนั้นคุณจะต้องผูก VBOs แตกต่างกันสำหรับแต่ละแอตทริบิวต์ (เว้นแต่คุณจะเก็บไว้ทั้งหมดในหนึ่ง VBO และการใช้ชดเชย / กางเกง) แล้วคุณจะต้องทำให้แตกต่างกัน 5 glVertexAttribPointer
สายจากglVertexAttribPointer(0,...);
ไปglVertexAttribPointer(4,...);
สำหรับจุดพิกัด Lightmap ตามลำดับ
หวังว่าระบบนั้นจะสมเหตุสมผล ตอนนี้ฉันจะไปยัง VAO เพื่ออธิบายวิธีใช้เพื่อลดจำนวนการเรียกใช้เมธอดเมื่อทำการเรนเดอร์ประเภทนี้ โปรดทราบว่าไม่จำเป็นต้องใช้ VAO
A Vertex Array Object
หรือ VAO ใช้เพื่อจัดเก็บสถานะของการglVertexAttribPointer
โทรทั้งหมดและ VBO ที่กำหนดเป้าหมายเมื่อมีการglVertexAttribPointer
โทรแต่ละครั้ง
glGenVertexArrays
คุณสร้างหนึ่งที่มีการเรียกร้องให้ ในการจัดเก็บทุกสิ่งที่คุณต้องการใน VAO ผูกมันด้วยแล้วทำโทรวาดเต็มรูปแบบglBindVertexArray
การโทรผูกการดึงทั้งหมดจะถูกดักจับและจัดเก็บโดย VAO คุณสามารถยกเลิกการผูก VAO ด้วยไฟล์glBindVertexArray(0);
ตอนนี้เมื่อคุณต้องการวาดวัตถุคุณไม่จำเป็นต้องเรียกการผูก VBO ทั้งหมดหรือการglVertexAttribPointer
โทรอีกครั้งคุณเพียงแค่ต้องผูก VAO ด้วยglBindVertexArray
แล้วโทรglDrawArrays
หรือจากนั้นglDrawElements
คุณจะวาดสิ่งเดียวกันทุกประการราวกับว่าคุณ กำลังทำการเรียกเมธอดเหล่านั้นทั้งหมด คุณอาจต้องการยกเลิกการผูก VAO ในภายหลังเช่นกัน
เมื่อคุณเลิกผูก VAO แล้วสถานะทั้งหมดจะกลับสู่สภาพเดิมก่อนที่คุณจะผูก VAO ฉันไม่แน่ใจว่าการเปลี่ยนแปลงใด ๆ ที่คุณทำในขณะที่มีการผูก VAO ไว้หรือไม่ แต่สามารถคำนวณได้อย่างง่ายดายด้วยโปรแกรมทดสอบ ฉันเดาว่าคุณคงคิดว่าglBindVertexArray(0);
มีผลผูกพันกับ VAO "default" ...
อัปเดต: มีคนแจ้งให้ฉันทราบถึงความจำเป็นในการเรียกเงินจริง ปรากฎว่าคุณไม่จำเป็นต้องทำการโทรแบบเต็มรูปแบบเมื่อตั้งค่า VAO เพียงแค่สิ่งที่มีผลผูกพันทั้งหมด ไม่รู้ว่าทำไมฉันถึงคิดว่ามันจำเป็นก่อนหน้านี้ แต่ตอนนี้แก้ไขแล้ว