Setiap glDraw * adalah panggilan undian.
1 glDrawArrays adalah 1 panggilan draw.
1 glDrawElements adalah 1 panggilan draw.
Tidak masalah (sejauh menyangkut penghitungan panggilan), berapa banyak simpul atau indeks yang Anda gunakan, 1 glDraw * adalah 1 panggilan draw.
Kasus-kasus sederhana menggambar paha depan (dengan asumsi versi GL yang Anda gunakan belum menghapus paha depan) atau segitiga bukan contoh yang baik untuk membandingkan ini, karena daftar paha depan atau daftar segitiga dapat ditarik dengan satu panggilan ke salah satu, dan glDrawArrays akan tampak lebih efisien karena tidak memiliki overhead pengindeksan tambahan.
Mari kita ambil kasus yang sedikit lebih rumit, tetapi yang mewakili skenario dunia nyata. Bayangkan Anda memiliki model yang terdiri dari beberapa strip segitiga dan kipas:
glDrawArrays (GL_TRIANGLE_FAN, .....);
glDrawArrays (GL_TRIANGLE_STRIP, .....);
glDrawArrays (GL_TRIANGLE_STRIP, .....);
glDrawArrays (GL_TRIANGLE_FAN, .....);
glDrawArrays (GL_TRIANGLE_STRIP, .....);
glDrawArrays (GL_TRIANGLE_FAN, .....);
Dalam contoh ini, menggunakan glDrawArrays memberi Anda total 6 panggilan draw untuk model. Namun, strip dan kipas dapat dengan mudah dikonversi menjadi segitiga yang diindeks, jadi tambahkan indeks dan itu menjadi:
glDrawElements (GL_TRIANGLES, .....);
Itu satu panggilan undian, untuk seluruh model.
Kelebihan glDrawElements dibandingkan glDrawArrays lebih dari sekadar penghematan memori, yang merupakan cara naif untuk mengukurnya. Ada potensi untuk menghemat memori di mana simpul dapat digunakan kembali, karena indeks biasanya lebih kecil dari simpul (jadi bahkan jika Anda memiliki banyak indeks pada keseimbangan mereka akan lebih kecil), tetapi keuntungan lainnya termasuk:
Jumlah panggilan undian berkurang. Setiap draw call mengeluarkan beberapa overhead dari memvalidasi state, mengatur segalanya, dll, dan banyak overhead ini terjadi di sisi CPU. Dengan mengurangi jumlah panggilan draw, kami menghindari banyak overhead ini.
Vertex digunakan kembali. Ini jauh lebih dari sekedar penghematan memori. GPU Anda kemungkinan memiliki cache vertex perangkat keras, tempat simpul yang baru diubah dapat disimpan; jika titik yang sama masuk lagi, dan jika ada di cache, itu dapat digunakan kembali dari cache daripada harus mengubah lagi. Perangkat keras Anda akan memeriksa cache dengan membandingkan indeks, jadi dalam istilah OpenGL satu-satunya cara Anda menggunakan cache adalah dengan menggunakan glDrawElements.
Jadi untuk menjawab pertanyaan spesifik Anda:
bagaimana glDrawElements menyimpan panggilan draw ...? Dalam contoh yang Anda gunakan, tidak. Masing-masing memiliki satu panggilan undian. Seperti yang saya diskusikan di atas, contoh ini sangat buruk untuk membandingkan keduanya.
bagaimana menggunakan glDrawElements menghemat ruang ...? Karena indeks lebih kecil dari simpul. Indeks 16-bit adalah dua byte, posisi / warna / texcoord adalah 24 byte. 6 simpul adalah 144 byte, 4 simpul ditambah 6 indeks adalah 108 byte.
Dalam hal menggambar persegi dari 2 segitiga ...? Satu dan satu. Panggilan glDraw * adalah panggilan satu kali, jumlah simpul atau indeks yang digunakan tidak relevan untuk pengukuran ini. Tetapi saya harus menekankan kembali, ini adalah contoh yang sangat buruk untuk membandingkan keduanya.
Akhirnya, dan hanya sedikit memperumit masalah, sementara glDrawElements dengan segitiga adalah jalur optimal pada GPU desktop, pada seluler mungkin sangat berbeda. Beberapa GPU seluler mungkin lebih suka glDrawArrays dengan GL_TRIANGLE_STRIP (Anda akan menambahkan segitiga yang merosot untuk menggabungkan primitif dalam kasus ini), dan saya bahkan belum menyentuh topik yang lebih maju seperti restart primitif atau multi-draw.