แต่ละ glDraw * เป็นการเรียกสาย
1 glDrawArrays คือ 1 การเรียกสาย
1 glDrawElements คือ 1 การเรียกสาย
ไม่สำคัญ (เท่าที่มีการนับจำนวนการโทร) จำนวนจุดยอดหรือดัชนีที่คุณใช้คือ 1 glDraw * คือ 1 การโทร
กรณีง่าย ๆ ของการวาดภาพสี่คน (สมมติว่าเป็นรุ่น GL ที่คุณใช้ไม่ได้ลบหน้าสี่หน้า) หรือรูปสามเหลี่ยมไม่ใช่ตัวอย่างที่ดีสำหรับการเปรียบเทียบสิ่งเหล่านี้เนื่องจากรายการของสี่คนหรือรายการรูปสามเหลี่ยมสามารถวาดด้วยการโทรครั้งเดียว และ glDrawArrays จะมีประสิทธิภาพมากกว่าเนื่องจากไม่มีค่าใช้จ่ายเพิ่มเติมในการจัดทำดัชนี
ลองพิจารณากรณีที่ซับซ้อนขึ้นเล็กน้อย แต่กรณีที่เป็นตัวแทนของสถานการณ์โลกแห่งความเป็นจริงที่มากขึ้น ลองนึกภาพว่าคุณมีรูปแบบประกอบด้วยแถบสามเหลี่ยมและแฟน ๆ หลายแบบ:
glDrawArrays (GL_TRIANGLE_FAN, .....);
glDrawArrays (GL_TRIANGLE_STRIP, .....);
glDrawArrays (GL_TRIANGLE_STRIP, .....);
glDrawArrays (GL_TRIANGLE_FAN, .....);
glDrawArrays (GL_TRIANGLE_STRIP, .....);
glDrawArrays (GL_TRIANGLE_FAN, .....);
ในตัวอย่างนี้การใช้ glDrawArrays ให้การเรียกแบบดึงทั้งหมด 6 ครั้งสำหรับโมเดล อย่างไรก็ตามทั้งแถบและพัดลมสามารถเปลี่ยนเป็นรูปสามเหลี่ยมที่จัดทำดัชนีได้ง่ายดังนั้นเพิ่มดัชนีและกลายเป็น:
glDrawElements (GL_TRIANGLES, .....);
นั่นคือหนึ่งการเรียกร้องสำหรับทั้งรุ่น
ข้อดีของ glDrawElements ผ่าน glDrawArrays เป็นมากกว่าการประหยัดหน่วยความจำซึ่งเป็นวิธีการวัดที่ไร้เดียงสา มีความเป็นไปได้สำหรับการประหยัดหน่วยความจำซึ่งสามารถนำจุดยอดกลับมาใช้ใหม่ได้เนื่องจากโดยทั่วไปดัชนีจะมีขนาดเล็กกว่าจุดสุดยอด (ดังนั้นแม้ว่าคุณจะมีดัชนีจำนวนมากที่มีความสมดุล
ลดจำนวนการเรียกสาย การเรียกแต่ละครั้งจะมีค่าใช้จ่ายเกิดขึ้นจากสถานะการตรวจสอบความถูกต้องการตั้งค่า ฯลฯ และค่าใช้จ่ายส่วนใหญ่นี้เกิดขึ้นที่ด้าน CPU ด้วยการลดจำนวนการเรียกเสมอเราหลีกเลี่ยงค่าใช้จ่ายส่วนใหญ่นี้
จุดยอดกลับมาใช้ใหม่ นี่เป็นมากกว่าการประหยัดหน่วยความจำ GPU ของคุณน่าจะมีแคชจุดสุดยอดของฮาร์ดแวร์ซึ่งสามารถเก็บจุดยอดที่เพิ่งเปลี่ยนได้ หากจุดสุดยอดเดียวกันเข้ามาอีกครั้งและถ้าอยู่ในแคชก็สามารถนำกลับมาใช้ใหม่จากแคชแทนที่จะต้องแปลงอีกครั้ง ฮาร์ดแวร์ของคุณจะตรวจสอบแคชโดยการเปรียบเทียบดัชนีดังนั้นในเทอม OpenGL วิธีเดียวที่คุณจะใช้แคชคือการใช้ glDrawElements
ดังนั้นเพื่อตอบคำถามเฉพาะของคุณ:
glDrawElements จะบันทึกการโทรได้อย่างไร ... ? ในตัวอย่างที่คุณใช้ไม่เป็นเช่นนั้น แต่ละคนมีหนึ่งสายที่โทรออก ขณะที่ฉันพูดถึงข้างต้นตัวอย่างนี้เป็นสิ่งที่แย่มากสำหรับการเปรียบเทียบทั้งสอง
จะใช้ glDrawElements ช่วยประหยัดพื้นที่ได้อย่างไร ... ? เพราะดัชนีมีขนาดเล็กกว่าจุดยอด ดัชนีแบบ 16 บิตคือสองไบต์ตำแหน่งจุดสุดยอด / สี / texcoord คือ 24 ไบต์ 6 จุดยอดคือ 144 ไบต์, 4 จุดยอดบวก 6 ดัชนีคือ 108 ไบต์
ในกรณีที่วาดรูปสี่เหลี่ยมจัตุรัสจากรูปสามเหลี่ยมสองรูป ... หนึ่งและหนึ่ง การเรียก glDraw * เป็นการเรียกแบบดึงครั้งเดียวจำนวนจุดยอดหรือดัชนีที่ใช้ไม่เกี่ยวข้องกับการวัดนี้ แต่ฉันต้องเน้นอีกครั้งนี่เป็นตัวอย่างที่ดีมากสำหรับการเปรียบเทียบทั้งสอง
ท้ายที่สุดและซับซ้อนเพียงเล็กน้อยในขณะที่ glDrawElements กับรูปสามเหลี่ยมเป็นเส้นทางที่ดีที่สุดในเดสก์ท็อป GPU บนมือถือมันอาจแตกต่างกันมาก GPU มือถือบางรุ่นอาจชอบ glDrawArrays ด้วย GL_TRIANGLE_STRIP (คุณจะเพิ่มรูปสามเหลี่ยมที่เสื่อมลงเพื่อเชื่อมต่อแบบดั้งเดิมในกรณีนี้) และฉันไม่ได้สัมผัสหัวข้อขั้นสูงเช่นการรีสตาร์ทแบบดั้งเดิมหรือการวาดหลายครั้ง