Buffer vertex besar vs beberapa panggilan draw

14

Saya baru memulai dengan OpenGL, dan saya mencoba menggunakannya untuk membuat game 2D. Dalam permainan ini, saya memiliki kisi heksagonal yang terdiri dari berbagai macam heksagon berwarna sangat besar. Sebagai programmer OpenGL pemula, saya melihat dua cara menggambar kotak ini:

  1. Menggunakan vertex buffer dengan data untuk hexagon tunggal, kemudian menggunakan nilai offset yang seragam dan mengulangi pada CPU untuk menggambar program yang sama berkali-kali sampai saya memiliki grid.
  2. Membuat buffer vertex tunggal yang sangat besar yang dihitung sebelumnya yang menarik semua segi enam dalam satu panggilan.

Apa metode yang paling efisien? Apakah ada cara yang lebih baik untuk melakukan ini?

Alexis King
sumber
Buffer vertex pra-dihitung Anda hanya perlu memperpanjang melewati layar dengan satu segi enam, Anda kemudian dapat memalsukannya dengan menggulir dengan lancar sampai Anda pergi segi enam penuh dan kemudian "melengkung" kembali, seperti untuk warna dalam skenario itu, Anda dapat menyimpan Tekstur 2D pada GPU, baca di vertex shader, dan sisipkan rata ke dalam fragmen shader.
MickLH
Pass biasanya merujuk pada situasi di mana satu operasi render bergantung pada hasil operasi sebelumnya. Apa yang Anda tanyakan dalam pertanyaan ini sebenarnya terkait dengan mengurangi jumlah panggilan seri dalam satu pass. Saya tahu kedengarannya luar biasa, tetapi sangat penting untuk memahami perbedaannya jika tidak, algoritma multi-pass tidak akan masuk akal;)
Andon M. Coleman
@ AndonM.Coleman Hmm, terima kasih, saya jelas tidak akrab dengan terminologi grafis. Jadi, dalam hal ini, bagaimana saya menggambarkannya? Beberapa panggilan shader / program?
Alexis King
Anda dapat segera mengatakan bahwa ini adalah algoritma sekali pakai karena tidak ada ketergantungan pesanan; Anda dapat menggambar segi enam ini dalam urutan apa pun dan masih mendapatkan hasil yang sama. Anda mungkin menerima beberapa panggilan undian untuk memasok OpenGL dengan data yang diperlukan untuk membuatnya, tetapi OpenGL secara efektif bebas untuk menggambar semuanya secara paralel karena tidak ada dependensi. Jika multi-pass , maka segi enam B mungkin memerlukan hasil segi enam A sebelum dapat ditarik, atau Anda mungkin perlu menggambar segi enam yang sama beberapa kali dan menggabungkan hasilnya.
Andon M. Coleman

Jawaban:

9

Memang ada beberapa cara untuk membuat kotak seperti itu.

Cara yang paling efisien adalah memasang. Dengan cara ini Anda membuat segi enam Anda hanya sekali dalam VBO, dan membuat ini seratus, seribu atau sejuta kali. Anda dapat melakukannya secara manual menggunakan shader dengan seragam seperti yang Anda katakan pada poin 1, tetapi ada juga fungsionalitas OpenGL bawaan untuk itu. Untuk itu, lihatlah glDrawElementsInstanced .

Perhatikan bahwa instance hanya lebih cepat daripada metode lain jika Anda menggambar lebih dari jumlah objek instances tertentu. Misalnya menggambar 300 bisa lebih cepat menggunakan 1 VBO besar, tetapi menggambar 2 juta bisa lebih cepat jika Anda menggunakan render instan.

Jika Anda menggunakan render instan, Anda dapat mengirim data per-objek menggunakan Pembagi Atribut . Dalam kasus Anda, Anda ingin mengirim posisi dan warnanya.

Tutorial yang bagus tentang render yang dipasang: klik

Benar-benar cara terbaik adalah dengan mencoba kedua metode, dan periksa jumlah milidetik yang diperlukan untuk menggambar 1 bingkai. Dengan cara ini Anda juga mempelajari kedua cara, yang selalu baik.

Perhatikan juga bahwa rendering yang dipasang adalah fungsi OpenGL modern, dan Anda harus menggunakan shader untuk menggunakannya. Tetapi selalu terbaik untuk mempelajarinya dengan cara yang benar sejak awal.

Basaa
sumber
2
Instancing belum tentu yang paling efisien; dalam banyak implementasi, saya telah melihat profil, dukungan instancing ditempelkan pada kesesuaian tetapi lebih lambat daripada secara individual menggambar banyak objek (memang, itu mungkin hanya loop yang diimplementasikan buruk pada driver melakukan hal itu). Ini adalah pilihan, dan pilihan yang bagus, tetapi orang harus berhati-hati untuk profil dan menguji pada OS target / perangkat keras sebelum membuat asumsi tentang "paling efisien."
Sean Middleditch
Sepakat. Saya telah melihat kinerja yang berbeda pada Windows / Linux dan Ati / nVidia misalnya. Terima kasih untuk tambahannya.
Basaa
1
Faktanya. Jika Anda menggambar beberapa kisi gabungan dalam satu vbo (yang berbagi ruang yang sama). Tidak mungkin instancing bisa lebih cepat. Masalah dengan instancing adalah: simpul tidak dihitung secara paralel misalnya lintas. Ini hanya menghilangkan gpu / cpu / gpu sync / drawcall. Jadi lebih cepat untuk menggambar satu buffer vertex yang berisi 1000 bola daripada menggambar 1000 bola dengan pemasangan perangkat keras. (tidak ada optimisasi culling / pengoptimalan jarak objek yang terlibat)
Jeroen van Langen
3

Metode 1 lebih mudah dikodekan dan akan baik-baik saja selama Anda tidak memiliki terlalu banyak segi enam sekaligus. Anda mungkin ingin tetap menggunakan ini karena Anda baru menggunakan OpenGL, untuk menghindari terlalu banyak kerumitan pada piring Anda sekaligus.

Jika ada sejumlah besar segi enam (seperti beberapa ratus atau lebih dari seribu) yang dilihat sekaligus, metode overhead yang lebih rendah akan diperlukan untuk menghindari overhead CPU dalam melakukan begitu banyak undian individu. Metode 2 akan bekerja untuk ini, atau bahkan lebih baik, gunakan instancing. Saya berharap instancing lebih cepat daripada metode 2, atau tentu saja tidak lebih buruk, karena Anda hanya perlu memperbarui buffer data per-instance daripada buffer (jauh lebih besar) dari data vertex untuk semua instance.

Nathan Reed
sumber