Saya sedang mengembangkan game 2D berbasis sprite untuk platform mobile dan saya menggunakan OpenGL (well, sebenarnya Irrlicht) untuk membuat grafik. Pertama saya mengimplementasikan rendering sprite dengan cara sederhana: setiap objek game dirender sebagai quad dengan panggilan draw GPU-nya sendiri, artinya jika saya memiliki 200 objek game, saya membuat 200 draw draw per frame. Tentu saja ini adalah pilihan yang buruk dan permainan saya benar-benar terikat CPU karena ada sedikit overhead CPU yang dikaitkan dalam setiap panggilan draw GPU. GPU sebagian besar tidak digunakan.
Sekarang, saya pikir saya bisa meningkatkan kinerja dengan mengumpulkan benda-benda ke dalam kelompok besar dan membuat kelompok ini hanya dengan beberapa panggilan menarik. Saya menerapkan batching (sehingga setiap objek game yang berbagi tekstur yang sama diberikan dalam batch yang sama) dan berpikir bahwa masalah saya hilang ... hanya untuk mengetahui bahwa frame rate saya bahkan lebih rendah dari sebelumnya.
Mengapa? Yah, saya punya 200 (atau lebih) objek game, dan mereka diperbarui 60 kali per detik. Setiap frame saya harus menghitung ulang posisi baru (terjemahan dan rotasi) untuk simpul dalam CPU (GPU pada platform seluler tidak mendukung instancing jadi saya tidak bisa melakukannya di sana), dan melakukan perhitungan ini 48000 per detik (200 * 60 * 4 sejak setiap sprite memiliki 4 simpul) sepertinya terlalu lambat.
Apa yang bisa saya lakukan untuk meningkatkan kinerja? Semua objek game bergerak / berputar (hampir) setiap frame jadi saya benar-benar harus menghitung ulang posisi vertex. Hanya optimasi yang dapat saya pikirkan adalah tabel pencarian untuk rotasi sehingga saya tidak perlu menghitungnya. Apakah sprite titik membantu? Adakah hack jahat? Ada yang lain?
Terima kasih.
sumber
Saya akan merekomendasikan memiliki VBO, dengan masing-masing simpul berisi posisi / rotasi dari setiap objek yang diberikan dan batching berdasarkan tekstur seperti yang Anda lakukan. Saya tidak terlalu terbiasa dengan ogl ES, jadi saya tidak yakin versi glsl mana yang didukungnya, tetapi Anda mungkin dapat melakukan batch berdasarkan pada set tekstur, dan menyimpan yang mana dari 4 atau lebih tekstur yang Anda lewati di Anda akan menggunakan bagian dalam simpul. Sprite poin pasti akan meningkatkan kinerja Anda karena akan mengurangi jumlah data yang Anda kirim secara drastis, dan batching tidak boleh menurunkan kinerja jika Anda melakukannya dengan benar. Selain itu, Anda dapat sedikit meningkatkan kinerja dengan menghitung rotasi pada shader dan hanya meneruskan nilai int / float ke params atau di dalam vertex itu sendiri. (Params akan lebih cepat,
sumber
Anda menyebutkan platform seluler yang tidak memiliki instancing. Tapi, Anda masih memiliki vertex shaders, bukan?
Dalam hal ini, Anda masih bisa melakukan pseudo instancing, yang juga sangat cepat. Buat VBO (GL_STATIC_DRAW) dengan titik sudut (relatif terhadap titik tengah sprite, misalnya -1 / -1, 1 / -1, 1/1, -1/1) dan semua koordinat tekstur yang Anda butuhkan, di dalamnya .
Kemudian atur salah satu atribut vertex generik untuk setiap panggilan draw ke titik tengah sprite, dan gambar dua segitiga dengan batas buffer. Di dalam vertex shader, baca atribut vertex generik dan tambahkan koordinat titik tersebut.
Itu akan menghemat Anda memblokir transfer data untuk setiap sprite dan harus jauh lebih cepat. Jumlah aktual panggilan undian tidak begitu penting, pemblokiran / penghentian di antara keduanya.
sumber
Masalahnya terletak pada jumlah data yang Anda kirim ke setiap frame GPU. Cukup buat VBO untuk setiap batch dan isi sekali, lalu terapkan matriks transformasi yang sesuai (via glMultMatrix, atau shader jika Anda menggunakan ES 2.0) saat menggambar batch.
sumber