Saya memiliki dunia berbasis kubus seperti Minecraft dan saya bertanya-tanya apakah ada cara untuk membangun kubus dengan kurang dari 24 simpul sehingga saya dapat mengurangi penggunaan memori.
Sepertinya tidak mungkin bagi saya karena 2 alasan: normals tidak akan keluar dengan benar dan tekstur per-wajah tidak akan berfungsi.
Apakah ini masalahnya atau saya salah? Mungkin ada beberapa teknologi DX11 baru yang mewah yang dapat membantu?
Sunting: Hanya untuk memperjelas, saya memiliki 2 persyaratan: Saya perlu normals permukaan untuk setiap permukaan kubus untuk melakukan pencahayaan yang tepat dan saya perlu cara untuk mengatasi indeks berbeda dalam array tekstur untuk setiap permukaan kubus
Jawaban:
Jika Anda hanya membutuhkan normal per-wajah, dan jika texcoords Anda untuk wajah benar-benar 0/0, 0/1, 1/0, 1/1 (atau mirip dengan tata letak Anda) maka Anda dapat membuat kubus dengan 8 verts dan 30 (strip dengan restart) atau 36 (daftar) indeks. Ambil normals dan texcoords menggunakan pencarian array konstan berdasarkan SV_VertexID di vertex shader Anda.
Melakukan ini berarti Anda bahkan tidak perlu memasukkan texcoords atau normals ke dalam buffer vertex Anda, yang akan memberi Anda lebih banyak penghematan memori.
Lebih jauh, Anda masih bisa mencapai 24 verts per kubus tetapi juga menggunakan instancing. Setiap kubus akan menjadi ukuran tetap dalam buffer verteks Anda (1x1x1) dan Anda akan memiliki faktor penskalaan dan posisi (dengan asumsi kubus Anda tidak berputar, matriks jika mereka lakukan) sebagai data per instance. Dalam kasus non-rotating Anda memiliki biaya sekali pakai dari 24 verts, tetapi kemudian setiap kubus hanya perlu 6 floats untuk sepenuhnya ditentukan. Dalam kasus berputar Anda melihat 16 pelampung, tetapi bahkan itu adalah penghematan besar (Anda lebih cenderung untuk bottleneck sisi-CPU pada transformasi matriks dalam kasus ini - untuk kasus yang tidak berputar membangun matriks dengan cepat di vertex shader Anda - bahkan jika itu dilakukan per-vertex, sangat cepat sehingga Anda bahkan tidak perlu khawatir tentang hal itu).
Untuk tekstur per-wajah, cukup gunakan array tekstur. Anda perlu memastikan bahwa setiap tekstur dalam array memiliki ukuran yang sama, tentu saja, dan Anda masih harus memecah batch Anda saat ini jika array itu sendiri perlu diubah, tetapi jika tidak maka akan melakukan pekerjaan dengan baik. Tambahkan texcoord ketiga ke definisi vertex Anda yang mendefinisikan irisan array yang digunakan untuk setiap wajah.
Anda tidak memerlukan GS dengan ini, dan itu harus berjalan lebih cepat daripada menggunakan satu karena memiliki tahap geometri shader diaktifkan akan membebankan biaya tambahan tambahan itu sendiri.
Saya memiliki kode benchmark di mesin saya yang hanya menggambar sekelompok kubus menggunakan metode ini, dan saya dapat dengan mudah mengunyah lebih dari 300.000 kubus sambil masih membersihkan 60fps, pada GPU yang relatif rendah, dan tanpa melakukan hal lain untuk mengoptimalkan proses . Memang saya bukan pencahayaan atau texturing mereka, tapi saya memang telah mengaktifkan alpha blending, backface culling dinonaktifkan, dan secara keseluruhan itu menyeimbangkan terhadap bagian "tidak melakukan hal lain untuk mengoptimalkan", jadi itu harus memberi Anda ide yang masuk akal dari jenis rata-rata Anda dapat menekan dengan metode ini.
sumber
Saya pikir optimasi utama yang dapat Anda buat, didasarkan pada kenyataan bahwa tidak setiap kubus benar-benar membutuhkan semua 24 simpul . Bahkan, satu-satunya kubus yang membutuhkan 24 simpul adalah orang-orang yang mengambang di udara, yang mungkin merupakan kejadian langka.
Secara umum, hanya menghasilkan paha depan untuk wajah yang bersentuhan dengan udara . Ini berarti bahwa jika dua kubus saling bersentuhan, Anda tidak perlu membuat simpul untuk wajah tempat mereka bersentuhan.
Gambar di bawah ini menunjukkan konsep ini, tetapi dalam 2D untuk memudahkan pemahaman. Dalam gambar ada 11 blok yang ditempati (diwakili oleh lingkaran abu-abu yang diisi), yang biasanya membutuhkan 4 x 11 = 44 tepi untuk diwakili (4 karena itu persegi, bukan kubus). Tapi seperti yang Anda lihat, Anda hanya perlu menggambar tepinya saat bersentuhan dengan kotak kosong, yang dalam hal ini, hanya 8 tepi.
Jika contoh sederhana dalam 2D berhasil mengurangi 44 edge menjadi 8 edge, bayangkan keuntungan di dunia 3D besar ...
Ini adalah pendekatan yang dijelaskan dalam artikel ini , yang saya sarankan Anda baca, meskipun ditujukan untuk OpenGL. Konsepnya harus cukup universal.
Anda mungkin juga dapat menggunakan geometri shader untuk menghasilkan simpul dengan cepat pada GPU, menghilangkan kebutuhan untuk menyimpannya dalam memori, tetapi saya tidak memiliki pengalaman dengan itu, saya juga tidak tahu seberapa baik kinerjanya untuk yang besar dunia.
sumber