Metode Efisien Rendering Medan Masif di XNA


10

Saya membuat game XNA yang membutuhkan ruang besar untuk pemain. Saat ini, heightmap tes yang saya gunakan adalah 4096x4096, dan disimpan sebagai BMP 4-bit.

Apa yang saya coba lakukan adalah mengambil file heightmap yang sangat besar dan merendernya di dalam game. Masalah yang saya hadapi adalah kenyataan bahwa tidak efisien untuk memuat seluruh medan ke memori sekaligus, karena akan menggunakan sebagian besar memori yang tersedia.

Masalah lain yang saya temui adalah bahwa saya tidak dapat membuat semua medan dalam satu primitif karena batasan keras yang ditetapkan dalam XNA.

Dengan itu, saya telah menemukan sejumlah solusi, yang semuanya telah saya cantumkan di bawah ini:

  • Rendering berdasarkan lokasi pengguna saat ini - pada dasarnya menggambar kotak di sekitar pengguna tidak peduli orientasi mereka di dunia. Ini juga bukan yang saya inginkan, karena Anda masih memberikan ruang yang tidak dilihat pengguna.
  • Rendering berdasarkan orientasi dan posisi pengguna - Saya menemukan rumus untuk mengambil segitiga yang seharusnya memiliki piksel dari peta ketinggian apa yang seharusnya dirender, tetapi ini terbukti sangat sulit.
  • Membagi medan menjadi beberapa bongkahan dan merender yang paling dekat dengan pengguna - Masih tidak terlalu efisien karena Anda masih merender bongkahan yang tidak akan dilihat orang. Dan ini pekerjaan yang intensif karena saya harus membagi tinggi peta saya menjadi beberapa bagian, dan skalabilitas menjadi masalah besar.

Setelah mencoba solusi itu, saya kehabisan ide untuk apa yang harus dilakukan. Saya telah menerima beberapa jawaban di mana orang-orang mengatakan kepada saya untuk melakukan algoritma yang kompleks ini, tetapi saya tidak tahu bagaimana cara melakukannya.

Jadi pada dasarnya saya meminta cara yang sederhana dan langsung untuk memberikan medan yang sangat besar di XNA dengan efisiensi maksimal.

Saya agak baru dalam pengembangan game pada umumnya, tetapi saya bersedia untuk meneliti jika tampaknya menjanjikan.

Pembaruan 1: Setelah meneliti metode geoclipmapping, saya mulai membuat kode dengan itu. Saya sudah menyelesaikan semua matematika, dan permainan berjalan. Namun, ini sangat tidak efisien - yang mungkin merupakan pengkodean yang buruk di pihak saya. Ini berjalan pada 2FPS dan menggunakan seluruh inti CPU saya. Saya akan mencoba dan meningkatkan kodenya, tetapi saya pikir saya akan memerlukan lebih banyak bantuan, jadi ini adalah Pastebin dari kode untuk kelas manajer Terrain. Saya akan memposting kembali dengan hasil lebih banyak nanti jika saya membuatnya lebih efisien.


1
Menariknya, teknik yang Anda bicarakan tampaknya mirip dengan yang digunakan ID Software di game mereka yang akan datang, Rage. Mereka menggunakan 'megatexture' dan kemudian mengalirkan bagian-bagiannya yang diperlukan ke dalam GPU. Dia sudah melakukan pembicaraan tentang hal itu, tetapi di sini adalah artikel wikipedia, ini mungkin inspiratif: en.wikipedia.org/wiki/MegaTexture

Jawaban:


5

Pendekatan potongan biasanya apa yang digunakan. Jarang itu efisien untuk menguji setiap segitiga dari ratusan ribu untuk melihat apakah Anda harus merendernya. Alih-alih, sebagian besar algoritme penguraian medan menggunakan struktur data spasial untuk merender bagian-bagian medan yang terlihat secara dinamis.

Struktur data yang mudah diimplementasikan disebut quadtree . Singkatnya, untuk menggunakan quadtree Anda akan menemukan frustum penglihatan pemain, memotongnya terhadap tingkat atas quadtree, dan untuk setiap bongkahan yang dapat dilihat sebagian (yaitu, pesawat frustum memotong bilik) Anda membagi dan menguji semua anak potongan, menghilangkan yang di luar frustum. Ini akan memberikan perkiraan yang cukup dekat dengan geometri nyata yang terlihat dengan hanya beberapa tingkat rekursi.

Penyaji medan yang lebih maju menggunakan algoritme untuk menyempurnakan tidak hanya geometri yang dapat dilihat, tetapi juga detail geometri itu. Geomipmapping (dan geoclipmapping relatif) relatif populer saat ini untuk melakukan itu tetapi bukan hal yang sepele untuk diterapkan.

sunting: Berikut adalah deskripsi yang layak untuk geoclipmapping dan frustum culling.

Saya juga memiliki keraguan apakah 4 bit untuk heightmap sebenarnya cukup untuk menghasilkan medan yang terlihat bagus kecuali jika Anda melakukan banyak penghalusan pada hasilnya.


Saya telah melihat artikel itu, dan saya telah memutuskan bahwa saya akan pergi dengan metode geoclipmapping terlebih dahulu, karena sepertinya itu akan menjadi yang paling efisien dalam menampilkan sejumlah besar medan. Saya akan memposting kembali dengan hasil saya.

3

Setiap pendekatan yang mengharuskan Anda melakukan pekerjaan per-bingkai untuk memuat data ke GPU akan cacat.

Berikut ini adalah garis besar kasar dari satu pendekatan yang harus dilakukan dengan baik:

Anda harus membagi medan Anda menjadi bongkahan (cukup besar), memuat bongkahan itu ke buffer vertex tetap (kedalaman bit dari peta ketinggian Anda tidak masalah!). Buffer vertex itu hanya akan duduk di memori GPU, menunggu untuk dirender. Anda harus bereksperimen dengan ukuran bongkahan yang sesuai, tetapi 128x128 mungkin merupakan tempat yang baik untuk memulai.

Untuk medan 4096x4096 Anda sedikit di luar batas dari apa yang saya nyamankan memuat ke GPU sekaligus - itu mungkin beberapa ratus MB data vertex (meskipun Anda bisa turun ke ~ 64MB jika Anda pintar). Jadi, Anda mungkin harus memuat dan menurunkan buffer vertex dari GPU di latar belakang.

(Jika Anda menerapkan pemuatan latar belakang potongan, ini harus sangat scalable!)

Setelah Anda memiliki data vertex pada GPU, ini adalah waktu yang tepat untuk melakukan pemusnahan visibilitas berdasarkan per-chunk . Tidak perlu mengirim perintah untuk merender, jika Anda tahu itu ada di belakang kamera.

Anda seharusnya hampir tidak pernah melakukan pemusnahan per-segitiga pada CPU!

GPU akan menyisihkan segitiga yang berada di luar layar jauh lebih cepat daripada yang pernah Anda bisa.

Untuk informasi lebih lanjut tentang kinerja, lihat jawaban ini di situs Game Dev.


0

Saya bukan ahli di XNA dengan cara apa pun jadi tolong perbaiki saya jika saya salah tetapi saya mendapat kesan bahwa sebenarnya ada optimasi yang dibangun untuk situasi seperti ini. Saya tahu Anda dapat mengatur jarak render dan setelah titik itu tidak membuat apa pun, dalam kasus Anda ini akan menjadi medan yang tersisa. Namun ini meninggalkan tepi yang tidak menarik untuk dunia yang Anda buat, jadi Anda harus menerapkan sesuatu seperti fogging yang dimiliki sebagian besar game dunia terbuka.


Ada solusi bawaan, tetapi masalah yang saya hadapi adalah saya mencoba membuat satu primitif besar, yang melebihi batas pada poligon untuk primitif. Karena itu, itu tidak akan menarik, hanya melempar pengecualian.
sammarks
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.