Saya mengajukan pertanyaan ini karena saya belum menemukan jawaban pasti untuk itu.
Biarkan saya pertama-tama menyatakan beberapa hal tentang permainan dan apa yang telah saya lakukan. Gim ini akan menjadi set RTS di dunia yang dihasilkan secara prosedural menggunakan noise Simplex. Dunia terdiri dari bongkahan yang berukuran 16 x 16 yang terbuat dari sprite yang berukuran 64 x 64. Saya telah berhasil memuat dan membongkar bongkahan secara dinamis, yang berfungsi dengan baik. Dunia akan terlihat sedikit seperti Rimworld, jadi top-down dengan berbagai lapisan sprite (medan pertama, sprite transisi, pohon, decals, dll). Dunia yang baru dihasilkan dapat berisi entitas yang dapat memengaruhi lingkungan (mis. Desa yang telah menjadi kota) dan dengan demikian bagian itu. Saya yakin ini bisa dihitung menggunakan semacam fungsi, tapi itu sesuatu yang perlu diperhatikan.
Masalah utama yang saya miliki adalah ketika saya memperkecil, semakin banyak ubin yang ditarik yang sangat mempengaruhi kinerja. Pada sekitar 30000 sprite, bagian undian mengambil 8 ms yang merupakan setengah dari yang diperlukan untuk dijalankan pada 60 FPS. Dan itu hanya medannya. Saya menggunakan atlas tekstur untuk membatasi jumlah undian (30000 sprite digambar dalam 6 jumlah).
The Tujuan adalah untuk dapat tampilannya keluar dari kota / desa / kota semua jalan untuk dapat melihat seluruh negeri. Ini memiliki harus dilakukan secara dinamis (misalnya. Tidak dengan mengklik pada icon minimap, tetapi hanya gulir kembali seperti di Panglima Tertinggi).
Saya telah membaca banyak artikel tentang masalah ini, tetapi saya belum menemukan atau melihat contoh yang jelas tentang di mana ia akan bekerja. Berikut adalah daftar teknik yang saya temukan yang seharusnya berfungsi:
- Persegi panjang kotor, seperti yang dijelaskan di sini , di mana Anda hanya menggambar barang baru dan menyimpan sisanya di backbuffer. Ini sangat masuk akal, tapi saya tidak mengerti bagaimana menerapkannya di Monogame.
- Pilihan pilihan saya: gunakan RenderTarget secara ekstensif, seperti dijelaskan di sini , tempat Anda menggambar RenderTarget dan kemudian simpan sebagai tekstur. Dalam kasus saya potongan 16 x 16 yang terdiri dari 64 x 64 akan menghasilkan tekstur 1024 x 1024. Saya benar-benar ragu ini akan bekerja dalam hal kinerja, tetapi hasilnya akan terdiri dari tekstur yang sangat rinci dan juga bagus untuk digunakan mengingat fakta bahwa sebagian besar itu statis (medan / pohon dll), dan tidak berubah banyak. Tapi ini juga berarti bahwa setiap kali perubahan dilakukan ke chunk, Texture2D harus diubah menggunakan SetData, yang dari apa yang saya alami cukup intensif dengan CPU. Namun jika teksturnya 16 x 16 mungkin benar-benar berfungsi, dan itu juga akan mengurangi penggunaan memori dan disk.
- Til tekstur dengan menentukan SourceRectangle di SpriteBatch. Untuk padang rumput besar / lautan ini adalah nilai tambah, karena hanya satu sprite yang diambil. Namun untuk medan terperinci dengan warna berbeda dan sprite berbeda dicampur bersama (transisi bioma dan bioma), saya khawatir itu tidak akan membuat perbedaan besar.
- Solusi saya sendiri, yang mengkompromikan detail, adalah dengan menggunakan ubin putih standar 64 x 64, beri warna 4 ubin di sekitarnya dan kemudian skala sehingga mencakup 4 ubin sebelumnya. Perbedaannya di sini (selain ubin memiliki warna polos) adalah bahwa lanskap tampak berubah. Saya juga harus menyebutkan bahwa hutan masih harus digambar secara individual karena tidak sepenuhnya berbentuk bujur sangkar.
Jika ada yang tahu cara mengatasi masalah ini, bahkan jika itu berarti kompromi hal-hal tertentu (seperti detail, atau menggunakan sprite 16 x 16), saya akan senang mendengarnya.
Jawaban:
Kartu grafis dioptimalkan untuk menggambar beberapa hal berkali-kali daripada sebaliknya.
Dalam kasus Anda, Anda memiliki banyak hal (tekstur berbeda) yang ingin Anda gambar berkali-kali (jumlah ubin).
IMO, optimisasi paling sederhana yang dapat Anda lakukan untuk mendapatkan keuntungan kinerja yang signifikan adalah:
Saya akan merekomendasikan melakukan kedua hal tersebut. Semoga berhasil.
sumber
Saya menemukan bahwa SpriteBatch tidak cocok untuk menggambar ubin. Salah satu alasannya adalah bahwa sprite dimaksudkan untuk objek dinamis dan digunakan untuk berbagai tujuan. Alasan lain adalah karena sangat terikat dengan CPU , mis. seperti yang dijelaskan dalam gambar deskripsi 30.000 objek biaya 8 ms (sedangkan chipset saya maksimal 30%). Juga, hingga 3000 sprite dapat ditarik sebelum penarikan panggilan baru harus dilakukan ke GPU (batched and all).
Solusinya adalah menggambar ubin saya sendiri menggunakan paha depan bertekstur . Ini dikombinasikan dengan VertexBuffer memungkinkan saya untuk menggambar hingga 500.000 ubin bertekstur dalam 1 panggilan draw di mana metode draw menghabiskan sekitar 1/20 dari satu milidetik. Tentu saja saya mungkin tidak perlu menggambar sebanyak itu, tetapi bagaimanapun saya akhirnya mendapatkan GPU saya memiliki beban kerja 75% pada tingkat stabil 60 fps.
sumber