Menggabungkan geometri / mesh tanpa kehilangan manfaat


11

Di three.js kita cukup menggabungkan geometri untuk membatasi jumlah panggilan draw dan dengan demikian meningkatkan kinerja. Dalam tes sederhana dengan satu bahan, saya bisa menggambar 50.000 kubus + bayangan @ 60fps pada GPU GTX660 saya. Tanpa penggabungan geometri, 5.000 kubus sudah menyebabkan masalah.

Saya bertanya-tanya bagaimana cara mempertahankan manfaat dari setiap mesh kubus itu sendiri. Sebagai contoh, bagaimana cara memilih mesh kubus ketika semuanya digabung menjadi satu geometri? Secara default itu tentu saja tidak mungkin.

Apakah ada teknik umum untuk masalah ini? Lagipula saya memang memiliki semua objek mesh yang tidak terputus bahkan setelah penggabungan. Jadi harus ada cara untuk memanfaatkannya untuk dipetik?

Singkatnya, apa yang ingin saya lakukan

  • SimCity menyukai game untuk tujuan belajar
  • Setiap rumah adalah jala kubus
  • Ingin merender 50.000 rumah dan dapat menambah & menghapus rumah
  • Pemilihan rumah melalui kursor mouse (memetik) harus dimungkinkan

Saya tidak yakin apakah ini berguna bagi Anda, tetapi saya menyebutkannya untuk kelengkapan. Simplygon memiliki model penetapan harga berbasis royalti untuk pengembang indie dan dapat melakukan banyak penggabungan dan pemartisian mesh ini pada waktu desain.
steeveeet

Jawaban:


11

OK aku mengerti. Setelah menggabungkan seluruh geometri menjadi satu, saya masih memiliki jerat individual dalam sebuah array. Jadi saya bisa menggunakan jerat ini untuk raycasting, meskipun mereka bahkan tidak dirender. Butuh waktu beberapa saat untuk menyadari hal ini.

masukkan deskripsi gambar di sini

Untuk memilih saya menggunakan implementasi octree ini: http://threejs.org/examples/#webgl_octree_raycasting

Ini menurunkan tes persimpangan per pembaruan dari 50.000 menjadi ~ 500. Tanpa octree, fps akan berkurang banyak.

Lambung pemetik oranye yang Anda lihat sebenarnya adalah jaring yang sekarang dirender (+1 draw call) dengan bahan yang diubah dan ukuran yang dimodifikasi.

masukkan deskripsi gambar di sini

Jadi saya kira langkah selanjutnya adalah mengimplementasikan semacam partisi peta. Artinya, pisahkan geometri yang digabungkan menjadi beberapa bagian. Alasan untuk ini adalah bahwa geometri yang digabungkan memiliki sejumlah besar simpul. Itu berarti Jika saya memindahkan peta 99% dari layar, kartu grafis masih harus memproses semua simpul karena geometri masih dalam pandangan, setidaknya 1% darinya. Jadi jika itu rusak, hanya potongan-potongan yang terlihat harus dirender.


Terima kasih banyak atas wawasan ini. Saya telah mencoba menemukan cara untuk melakukan ini juga, dan saya pikir solusi Anda di sini sangat bagus! Pertanyaan singkat: Untuk daftar objek lokal Anda (yaitu Three.Object3D's), sifat apa yang diperlukan agar rayCaster.intersectObjects () berfungsi?
AlvinfromDiaspar

Dilakukan dengan sangat baik.
ClassicThunder

Saya memiliki masalah yang sama, tetapi entah bagaimana tidak bisa mendapatkan pekerjaan raycasting dengan r70. Apakah Anda melakukan sesuatu yang istimewa saat membuat dan menggabungkan kotak? Saya menggunakan kode berikut ( pastebin.com/PStaAF3P ) untuk membuat dan menggabungkan node, tetapi mungkin ada sesuatu yang hilang untuk membuat raycaster berfungsi?
fhahn

Pertanyaan cepat: Saya melakukan sesuatu yang sangat mirip dengan Anda (peta 3d berdasarkan data geoJSON). Dengan metode Anda, setiap kali Anda memutar kamera, apakah Anda perlu memutar jerat bangunan yang sudah ada sebelumnya? Atau apakah Anda hanya menambahkan kotak individual ke tempat kejadian tetapi tidak membuatnya?
Spencer

@Spencer Tidak perlu memutar. Saya menyimpan kotak individual dalam array global dan hanya menambahkan geometri yang digabungkan ke dalam scene. Anda kemudian dapat melakukan raycasting dengan objek dalam array global, karena raycaster tergantung pada matriks kamera dan posisi masing-masing kotak. Kemungkinan besar bukan cara terbaik, ini hanya bukti konsep bagi saya. Tidak melakukan three.js lagi pada saat ini.
user990827

1

Untuk memilih, Anda juga dapat merender ID untuk setiap kubus ke target render lain dan hanya memeriksa apa nilai ID pada kursor. Keuntungannya adalah bahwa pengambilan pixel sempurna dan bekerja secara efisien juga untuk geometri yang lebih kompleks.

Jika semua objek memiliki geometri yang sama, maka Anda dapat menggunakan render yang dipasang. Satu aliran mendefinisikan geometri, sementara yang lain mendefinisikan properti per instance (misalnya transformasi). Untuk pemusnahan frustrasi Anda perlu membangun aliran contoh setiap frame berdasarkan tes visibilitas. Jika Anda memiliki sejumlah besar objek, Anda mungkin ingin meletakkan objek-objek itu ke dalam satu oktree longgar atau sesuatu untuk mempercepat pemusnahan.


0

Saya tidak yakin tentang rincian three.js, tetapi dua kemungkinan babi kinerja muncul dalam pikiran secara umum OpenGL:

  1. Sudahkah Anda mempertimbangkan untuk melakukan instance? Anda hanya perlu satu panggilan undian juga dan menggunakan lebih sedikit VRAM.
  2. Sudahkah Anda memperhatikan algoritma pemilihan? Jika kubus Anda memiliki volume yang terikat dalam daftar, bukan pohon misalnya yang akan menjelaskan perbedaan besarnya itu.

0

Pendekatan lain yang dapat Anda ambil adalah membangun beberapa atribut vertex ke dalam geometri Anda dan memasukkan logika highlight ke shader fragmen Anda. Ini sangat berguna ketika Anda tidak ingin memiliki dua salinan data dalam memori, dan Anda akan memiliki kontrol lebih besar tentang bagaimana sorotan diterapkan.

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.