วิธีที่เร็วที่สุดในการวาดล่ามใน OpenGL ES?


22

ฉันใช้ OpenGL ES 2.0 ฉันมีกลุ่มที่จะต้องวาดรูปฉันชอบที่จะสามารถส่งผ่านเพียง 4 จุดต่อรูปสี่เหลี่ยมราวกับว่าฉันกำลังใช้ GL_QUADS แต่โดยทั่วไปฉันต้องการทราบวิธีที่ดีที่สุดในการวาดรูป พวงของคณะสี่คนแยกกัน

จนถึงสิ่งที่ฉันได้พบว่าฉันสามารถทำได้: -GL_TRIANGLES (6 ยอดต่อหนึ่งรูปสี่เหลี่ยม) - สร้าง GL_TRIANGLE_STRIP (6 จุดต่อรูปสี่เหลี่ยม)

ความเป็นไปได้ที่ฉันได้พบ: -GL_TRIANGLE_STRIPS ด้วยค่าดัชนีพิเศษที่รีเซ็ตแถบสี่เหลี่ยม (ซึ่งหมายถึง 5 ดัชนีต่อหนึ่งรูปสี่เหลี่ยม แต่ฉันไม่คิดว่าเป็นไปได้คือ OpenGL ES 2.0)

คำตอบ:


33

เพียงใช้ดัชนีบัฟเฟอร์และ GL_TRIANGLES ในกรณีนี้คุณต้องมี 4 vertices + 6 ดัชนีต่อ Quad (6 ดัชนีเพิ่มเติมอาจฟังค่าใช้จ่ายขนาดใหญ่ แต่ในความเป็นจริงมันไม่ได้ - เมื่อคุณสร้างบัฟเฟอร์ดัชนีของคุณแล้วคุณไม่ต้องแตะอีกครั้ง) ดูหน้านี้สำหรับข้อมูลเพิ่มเติม (ค้นหา glDrawElements)

รหัสตัวอย่างง่าย ๆ :

GLfloat vertices[] = {-1, -1, 0, // bottom left corner
                      -1,  1, 0, // top left corner
                       1,  1, 0, // top right corner
                       1, -1, 0}; // bottom right corner

GLubyte indices[] = {0,1,2, // first triangle (bottom left - top left - top right)
                     0,2,3}; // second triangle (bottom left - top right - bottom right)

glVertexPointer(3, GL_FLOAT, 0, vertices);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, indices);

นอกจากนี้หากคุณวาดรูปสี่เหลี่ยมเพียงหนึ่งรูปสี่เหลี่ยมคุณต้องมีจุดยอด 4 จุดเพื่อวาดด้วยแถบสามเหลี่ยม ( ดังที่แสดงในวิกิพีเดีย ) แต่ฉันเดาว่าคุณรู้เรื่องนี้แล้ว


เคล็ดลับดั้งเดิมสำหรับการรวมแถบสามเหลี่ยมหลาย ๆ อันไว้ในแถบเดียวคือ "สามเหลี่ยมเสื่อม": ทำซ้ำองค์ประกอบสุดท้ายของหนึ่งแถบและองค์ประกอบแรกของแถบถัดไปสร้าง 2 สามเหลี่ยมที่มีพื้นที่ศูนย์ซึ่งไม่ได้วาดอะไรเลย พิจารณาดัชนีรูปสี่เหลี่ยมที่สอง (4, 5, 6, 7) ดัชนีบัฟเฟอร์สำหรับ GL_TRIANGLE_STRIP จากสอง quads อาจเป็น: {0, 1, 2, 3, 3, 4,4, 5, 6, 7} สามเหลี่ยมเลวอยู่และ3,3,4 3,4,4การทำเช่นนี้คุ้มค่าหรือไม่ ไม่เว้นแต่ล่ามของคุณมักจะมาเป็นคู่ (หรือมากกว่า) ที่มีขอบทั่วไป ถ้ารูปสี่เหลี่ยม 2 คือ {3, 2, 4, 5} {0,1,3,2,5,4}แล้วแถบคือ
ToolmakerSteve

8
และจะทำให้เรื่องนี้ชัดเจนให้กับทุกคนที่มาพร้อมและความต้องการที่จะดึงพวงของล่าม A: เพื่อประโยชน์ในการปฏิบัติงานไม่ได้คัดลอกรหัสข้างต้นและทำให้ glDrawElements โทรครั้งเดียวสำหรับแต่ละ QUAD ให้สร้างอาร์เรย์ของจุดยอดหนึ่งจุดและสร้างดัชนีหนึ่งแถวซึ่งรวมถึงคณะสี่คนทั้งหมดที่คุณต้องการวาด ใช้ GL_TRIANGLES สองล่ามอาจมีดัชนีหรือเป็นสิ่งที่ดีอย่างเท่าเทียมกัน{0,1,2, 0,2,3, 4,5,6, 4,6,7} {0,1,2, 2,3,0, 4,5,6, 6,7,4}ชั้นดีที่จะช่วยนี่คือglText-Android / SpriteBatch
ToolmakerSteve

6

ใช้บัฟเฟอร์ดัชนีจะไม่จำเป็นต้องเร็วขึ้นตามที่ระบุไว้ในเอกสารแอปเปิ้ล"สำหรับประสิทธิภาพที่ดีที่สุดรุ่นที่ท่านควรจะส่งเป็นแถบสามเหลี่ยมเดียว unindexed ใช้ glDrawArrays"

ดังนั้นในขณะที่GL_TRIANGLE_STRIPจะทำมันใน 4 จุดโดยไม่จำเป็นต้องบัฟเฟอร์ดัชนีและคุณสามารถใช้บัฟเฟอร์ดัชนีก็ง่อยสวยที่จะพยายามที่จะ "บันทึก" การทำซ้ำ2 จุด ด้วยเหตุนี้ผมขอแนะนำให้คุณวาด 2 แยกต่างหากGL_TRIANGLESและทำซ้ำ 2 จุดบนเส้นทแยงมุม


8
อืมไม่. สิ่งที่หมอพูดคือโมเดลของคุณจะถูกส่งเป็นแถบสามเหลี่ยม INDEXED เดียว และประโยคถัดไปคือ "เพื่อหลีกเลี่ยงการระบุข้อมูลสำหรับจุดสุดยอดเดียวกันหลาย ๆ ครั้งในบัฟเฟอร์จุดสุดยอดใช้บัฟเฟอร์ดัชนีแยกและวาดแถบสามเหลี่ยมโดยใช้ฟังก์ชั่น glDrawElements" ซึ่งเป็นสิ่งที่คุณตัดสินใจว่า 'ง่อย'
davidf2281

3
ระบุว่าตอนนี้ย่อหน้า doc หมายถึง glDrawElements แทนที่จะเป็น glDrawArrays มันอาจจะถูกเขียนใหม่ตั้งแต่คำตอบนี้ อย่างไรก็ตามจุดที่หมอกำลังทำอยู่นั้นสำหรับประสิทธิภาพนั้นให้แถบเดี่ยว (แทนที่จะเป็นหลายแถบดังนั้นหลาย gl จึงเรียก) ในสถานการณ์เช่นนี้ผมเชื่อว่าความแตกต่างระหว่างการใช้ดัชนีหรือไม่คือไม่มีนัยสำคัญ ; สิ่งที่สำคัญคือทำให้ทุกอย่างกลายเป็นจุดสุดยอดอาเรย์เดียว (บวกกับอาเรย์เสริมที่เป็นทางเลือก) เพื่อที่คุณจะสามารถโทรได้เพียงครั้งเดียว
ToolmakerSteve

0

กำไรขนาดใหญ่บนเดสก์ท็อปคือการย้ายข้อมูลไปยัง GL_STATIC_DRAW VBOs สมมุติว่านี่เป็นความจริงบน MBX GPU ของ iPhone ด้วย


-2

ใช้GL_TRIANGLE_FANสำหรับรูปสี่เหลี่ยมใช้ 4 จุดยอดไม่ใช่ 6


ใช่ แต่GL_TRIANGLE_STRIPเป็นเช่นนั้นเช่นเดียวกับคำตอบอื่น ๆ ที่ชี้ให้เห็นแล้ว
Anko

@นาย. Blah - ท่านยังพลาดจุดของคำถามซึ่งเป็นวิธีการที่มีประสิทธิภาพทำพวงของล่าม เราไม่ควรทำการเรียก gl สำหรับแต่ละ quad แต่รวมกันหลาย quads เป็นอาร์เรย์เดียวที่สามารถวาดด้วยการเรียก gl เดียว GL_TRIANGLE_FAN จะไม่ช่วยในเรื่องนี้ดังนั้นจึงไม่ค่อยมีประโยชน์ในการเรนเดอร์ประสิทธิภาพสูง
ToolmakerSteve
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.