Saya mengembangkan game 2D, dan saya memiliki banyak sprite. Saya menggunakan animasi dan model 3D untuk dirender menjadi 2D, untuk memberi mereka tampilan "Fallout" atau "Diablo". Ini juga lebih mudah daripada menggambar dengan tangan, lol.
Saya harus memotong framerate menjadi 15fps, yang merupakan level terendah yang dapat saya turunkan tanpa membuat mereka memiliki tampilan yang berombak. Namun, itu menyedihkan karena betapa 24 frame terlihat sangat halus.
Ada dua alasan saya melakukan ini:
1) Kurangi ruang HDD. Semakin sedikit gambar, semakin kecil total game saya.
2) Kurangi konsumsi RAM. Semakin sedikit gambar dimuat, semakin besar kemungkinan saya untuk menghindari masalah kembung keterbatasan RAM saya.
Namun, jika ada cara untuk memampatkan gambar di ruang HDD dan RAM, saya akan melakukannya. Saya telah mengujinya sebelumnya, dan sebagian besar tidak menerima perubahan kualitas ketika memberikan dari RGBA8888 ke RGBA5555 dan hanya sedikit hit ketika mengkonversi ke RGBA4444 dalam program TexturePacker saya. Saya tidak melakukan ini saat ini, karena SFML tampaknya menggunakan jumlah memori yang sama terlepas dari jenis gambar .PNG itu. Saya mencari cara untuk memuatnya secara berbeda, tetapi gagal menemukan apa pun pada subjek.
Saya telah membaca banyak tentang cara menangani video game 2D. Konsensusnya luar biasa: Kemas Sprite Anda ke dalam Tekstur yang Lebih Besar untuk kinerja hebat! Jadi saya mengemas sprite kecil saya menjadi spritesheet yang jauh lebih besar menggunakan TexturePacker.
Namun, saya berencana memiliki 10-15 animasi per karakter, 5 arah untuk dipindahkan, dan 15-40 frame per animasi (mungkin rata-rata 24). Dengan 15 animasi, 5 arah, dan rata-rata 24 frame per animasi; Itu adalah 1800 frame individu per karakter. Jika dikemas dalam lembar sprite, itu hanya 75 gambar saja. (Satu lembar sprite per Animasi, per Arah. 15 * 5)
Untuk satu karakter bos besar dalam game, saya tidak bisa menggunakan spritesheet dan harus memprogram cara untuk memuat dalam satu gambar pada satu waktu. Saya tidak tahu apakah saya bisa melakukan ini untuk kinerja.
Untuk karakter, saya sudah mengemasnya dalam spritesheet. Untuk satu karakter berjalan-jalan, ini sepertinya bekerja sebagian besar waktu, meskipun kadang-kadang berhenti. Namun, saya mengaitkannya dengan kode saya yang salah yang menukar tekstur alih-alih membuka semua tekstur untuk karakter itu.
Jika saya melakukan preload tekstur, masuk akal untuk sprite sheet. Saya hanya akan membayangkan itu ide buruk untuk memuat lebih awal 1800 gambar kecil untuk setiap karakter.
Namun, saya membayangkan streaming mereka keluar dan masuk memori satu per satu akan sangat cepat, jadi saya hanya perlu memiliki satu gambar dalam memori pada satu waktu. Bukankah ini berarti bahwa setiap saat saya hanya akan meminta masing-masing karakter mengkonsumsi beberapa KB, bukannya 45 + MB?
Saya membayangkan ini akan membunuh kinerja saya, karena streaming harus sangat cepat (15 gambar masuk dan keluar dari memori dan rendering, per detik) dan meskipun gambar akan sangat kecil-itu mungkin ide yang lebih baik untuk memuat spritesheets karakter ke dalam memori saja. Tapi saya harus mengkode sistem render seperti stream gambar tunggal untuk karakter bos saya yang lebih besar.
Saya telah bereksperimen, tetapi itu bukan proses yang sederhana. Terutama mengingat fakta saya sedang mengerjakan bagian-bagian lain dari mesin permainan yang tidak berurusan dengan grafik sekarang.
Jawaban:
Kami memiliki kasus serupa dengan Remake RTS kami. Semua unit dan rumah adalah sprite. Kami memiliki 18.000 sprite untuk unit, rumah, dan medan, ditambah 6.000 lainnya untuk warna tim (diterapkan sebagai topeng). Jangka panjang kami juga memiliki sekitar ~ 30 000 karakter yang digunakan dalam font.
Jadi alasan utama di balik atlas adalah:
Apa yang tidak berhasil bagi kami:
Sekarang kita memiliki segalanya yang dikemas dalam beberapa lusin 1024x1024 atlas (GPU modern mendukung dimensi yang lebih besar) dan itu bekerja dengan baik hanya memakan ~ 300mb memori, yang cukup baik untuk gim PC. Beberapa optimasi yang kami miliki:
Ketika Anda serius mempertimbangkan untuk pindah ke perangkat seluler, Anda akan khawatir tentang kendala. Untuk sekarang, mainkan saja gim dan tarik pemain! ;)
sumber
Saya memiliki jawaban yang berhubungan secara tangensial di sini , tetapi ide umumnya adalah, jika Anda memuat dan menggambar tekstur pada waktu yang berbeda (Anda tidak memuat tekstur tambahan saat Anda merender), maka ada dua tempat di mana Anda lakukan akan mempengaruhi kinerja Anda:
Memuat waktu:
Ini adalah saat di mana Anda mengunggah tekstur Anda ke dalam memori. The seluruh jumlah data yang mengirim ke VRAM adalah apa yang sebagian besar akan menentukan berapa lama waktu pemuatan Anda akan. Membuat tekstur Anda memiliki format yang lebih kecil, seperti RGBA4444, akan membuatnya lebih cepat. Namun, kecuali Anda mengunggah tekstur dalam ratusan megabyte ke VRAM, Anda mungkin tidak akan mengalami hambatan di sini. Jika Anda melakukannya, layar memuat yang bagus dapat memudahkan menunggu.
Menggabungkan tekstur Anda ke atlases akan berdampak kecil, karena seluruh jumlah informasi yang Anda kirim ke VRAM akan sama. Bahkan, jika Anda menghilangkan tekstur Anda, dan Anda harus meninggalkan ruang kosong di atlas Anda, maka Anda akan benar-benar mengirim lebih banyak data ke dalam VRAM, dan karena itu bagian ini akan lebih lambat!
Kinerja rendering:
Setelah semua tekstur Anda di VRAM, jumlah tekstur yang Anda miliki tidak akan memengaruhi kinerja rendering. Ada empat elemen yang mempengaruhi kinerja rendering Anda:
Perubahan status render : Setiap kali Anda mengubah gambar yang ingin Anda render, akan secara serius meningkatkan waktu yang diperlukan untuk merendernya. Secara umum, Anda ingin meminimalkan jumlah perubahan status, dan Anda dapat mengurangi jumlah perubahan status dengan mengelompokkan beberapa gambar yang akan Anda gambar secara berurutan, menjadi atlas tekstur.
Atlasing saja tidak cukup. Anda harus atlas dengan cara di mana perubahan negara dikurangi, untuk mendapatkan keuntungan kinerja. Sebagai contoh, orang mungkin berpikir bahwa memiliki karakter utama Anda dalam sprite sheet akan membuat Anda mendapatkan peningkatan kinerja, tetapi jika Anda hanya menggambar satu sprite dari sprite sheet per frame, Anda tidak akan mendapatkan peningkatan kinerja dibandingkan dengan memiliki masing-masing sprite dalam file terpisah.
Atlasing yang tepat bukanlah hal sepele, tetapi secara umum Anda dapat dengan aman mengelompokkan sprite dari lapisan yang sama. Misalnya, memiliki semua item GUI dalam satu lembar sprite adalah ide yang sangat menjanjikan, sementara mengelompokkan monster secara alfabet mungkin tidak.
Panggilan undian : Secara umum, Anda mungkin ingin menjaga agar panggilan undian Anda minimum. Aturan praktis yang baik adalah bahwa jika tidak ada perubahan render state antara dua panggilan draw, Anda dapat menggabungkannya menjadi satu draw draw. Untuk peningkatan kinerja yang lebih lanjut, Anda dapat menggunakan, katakanlah, 8 sampler tekstur, dan panggilan undian grup untuk setiap 8 tekstur, sehingga Anda hanya perlu mengubah tekstur setiap 8 tekstur.
Jumlah segitiga: Faktanya, semakin banyak segitiga yang Anda gambar, semakin lama waktu yang dibutuhkan untuk menggambarnya. Namun, di komputer modern, dan untuk sebagian besar game 2D, Anda akan sangat jauh dari memaksimalkan ini. Anda dapat dengan aman menggambar ratusan ribu sprite per frame dan masih mendapatkan framerate yang bagus. Anda mungkin akan lebih terikat dengan CPU jika Anda menggambar sprite ekstrim sebelum Anda mendapatkan masalah dengan GPU Anda.
Pengaturan API: Jika Anda melakukan semuanya dengan benar, dan Anda masih mendapatkan framerate yang sangat rendah, periksa pengaturan yang digunakan untuk menggambar sprite Anda. Saya tidak tahu SFML, tetapi misalnya, di Direct3D 9, membuat buffer vertex
D3DUSAGE_DYNAMIC
, atau diD3DPOOL_MANAGED
dapat dengan mudah meningkatkan waktu rendering Anda sepuluh kali lipat. Tentu saja, menggunakan vSync akan membatasi framerate Anda pada kecepatan refresh monitor Anda. Juga, menggunakan FVF yang tidak selaras dapat menurunkan kinerja di beberapa GPU. Ini juga untuk Direct3D 9.Dalam kasus Anda, periksa dokumentasi untuk API yang Anda gunakan.
Jika Anda hanya memiliki jumlah tekstur yang rendah hingga sedang (kurang dari 1GB), dan Anda menggambar jumlah sprite yang rendah (kurang dari satu juta per frame), maka hal pertama yang akan saya perhatikan adalah mengubah pengaturan API, dan kemudian mengurangi jumlah status render dan membuat panggilan.
sumber