Apa saja teknik optimasi render umum untuk lintasan geometri dalam penyaji bayangan yang ditangguhkan? [Tutup]

16

Saya telah mengembangkan mesin permainan menggunakan OpenGL 3 dan C ++ (dan glfw untuk manajemen jendela). Saya telah maju sejauh ini, menyelesaikan sebagian besar hal kecuali entitas yang sehat dan optimisasi. Mesinnya menggunakan penangguhan yang ditangguhkan sehingga karena penangguhan ditangguhkan itu sendiri merupakan proses yang melelahkan untuk GPU rata-rata, saya ingin mengoptimalkan proses rendering sebanyak mungkin.

Sistem saat ini terdiri dari Adegan, yang berisi Renderer dan Dunia saat ini dan Dunia memegang entitas dan entitas pencahayaan sebagai terpisah std::vectors.

Jadi pada dasarnya setiap kali Scene dipanggil ->render(), dan ia memanggil Renderer, melewati dunia sebagai parameter dan mendapatkan entitas iterator dari dunia, menariknya ke FBO dan kemudian melewati entitas pencahayaan untuk pass kedua. Dan saya pikir ini tidak cukup.

Algoritme saya saat ini berulang melalui semua bahkan jika entitas tidak di ruang layar. Saya memikirkan cara untuk mengoptimalkan algoritma rendering saat ini sehingga hanya memanggil fungsi API hanya untuk objek yang terlihat, jadi apa teknik umum untuk mengoptimalkan renderer seperti itu?

deniz
sumber

Jawaban:

41

Peneduhan yang ditangguhkan hanyalah teknik untuk "menunda" operasi peneduhan yang sebenarnya untuk tahap selanjutnya, ini bisa bagus untuk mengurangi jumlah lintasan yang diperlukan (misalnya) untuk membuat 10 lampu yang membutuhkan 10 lintasan. Maksud saya adalah terlepas dari teknik rendering yang Anda gunakan ada kemungkinan optimasi rendering tertentu yang mengurangi jumlah objek (simpul, normals dll) yang perlu diproses oleh pipa rendering Anda.

Tidak ada standar de facto untuk memberikan optimasi, melainkan sejumlah teknik yang dapat digunakan secara bergantian atau bersama-sama untuk mencapai karakteristik kinerja tertentu. Menggunakan setiap teknik sangat tergantung pada sifat adegan yang diberikan.

Render yang ditangguhkan mencoba untuk memecahkan masalah ketika jumlah lampu meningkat, yang dalam rendering yang maju mungkin membuat jumlah lintasan meledak.

Teknik-teknik tersebut tidak secara langsung mengoptimalkan bagian naungan yang ditangguhkan, tetapi menurut deskripsi Anda, bagian naungan yang ditangguhkan bukanlah masalah Anda. Masalah Anda adalah Anda mengirimkan seluruh adegan ke rendering pipeline. Jadi mesin Anda harus memproses (misalnya semua 100 juta simpul) dalam adegan Anda hanya untuk dapat mengirimkan hasilnya ke buffer-g, sementara sebagian besar dari 100 juta simpul ini secara sepele dapat disingkirkan secara sepele, dan tidak diserahkan kepada pra-proses verteks dan fragmen berlalu.

Dalam hal renderer maju, simpul N akan diproses oleh tahap simpul sebagai total vertex count*lights countdan oleh tahap fragmen sebagai total fragments count*number Lights, naungan ditangguhkan secara efektif mengurangi ini hanya vertex countuntuk tahap verteks dan fragments countuntuk jumlah fragmen, sebelum menyelesaikan naungan aktual. Tetapi masih N bisa terlalu banyak untuk diproses, terutama ketika sebagian besar dari mereka dapat disingkirkan sepele.

Ini membuat pemusnahan lebih efektif dalam hal render maju / beberapa lintasan. Tetapi perlu diingat bahwa sebagian besar mesin akan menggunakan pendekatan render ganda, karena peneduhan ditangguhkan saja tidak dapat menyelesaikan objek transparan, ini membuat menggunakan optimasi tersebut suatu keharusan, saya tidak tahu ada mesin komersial yang tidak melakukan semuanya.

Frustum Culling

Hanya Objek yang sepenuhnya atau sebagian termasuk dalam tampilan frustum, yang perlu diserahkan ke jalur render. Ini adalah konsep dasar dari pemusnahan frustum, sayangnya memeriksa apakah mesh masuk / keluar dari tampilan frustum bisa menjadi operasi yang mahal, jadi alih-alih, perancang mesin menggunakan perkiraan volume pembatas seperti (AABB) Axis Aligned bounding box atau bounding sphere , meskipun ini mungkin tidak seakurat menggunakan mesh yang sebenarnya, perbedaan akurasi tidak sepadan dengan kesulitan memeriksa dengan mesh yang sebenarnya.

masukkan deskripsi gambar di sini

Bahkan dengan volume pembatas, Anda tidak benar-benar perlu memeriksa masing-masing, atau Anda dapat membangun hierarki volume pembatas untuk melakukan pemusnahan sebelumnya, menggunakan ini sangat tergantung pada kompleksitas adegan.

Ini adalah teknik yang bagus dan sederhana untuk mesin yang lebih kecil, dan hampir digunakan di setiap mesin yang pernah saya gunakan. Saya sarankan menggunakan "Normal" Bounding Volume / Frustum memeriksa tanpa hierarki jika mesin Anda tidak memerlukan rendering adegan yang sangat kompleks.

Hierarki Volume Terikat

Wajah kembali dimusnahkan

Ini suatu keharusan, mengapa menggambar wajah yang tidak akan terlihat? rendering APIs menyediakan antarmuka untuk menghidupkan / mematikan pemusnahan wajah kembali. Kecuali Anda memiliki alasan kuat mengapa tidak menyalakannya, seperti beberapa aplikasi CAD yang perlu menarik mundur dalam keadaan tertentu, ini adalah hal yang harus dilakukan.

Penyisihan Culling

Menggunakan Z-buffer Anda dapat menyelesaikan penentuan visibilitas. Tetapi masalahnya adalah bahwa buffer-Z tidak selalu hebat dalam hal kinerja, karena buffer-Z hanya dapat diselesaikan pada tahap akhir dari pipa, objek yang tersumbat harus dirasterisasi dan mungkin ditulis ke buffer-Z dan Buffer warna sebelum gagal tes Z.

Penyisihan oklusi memecahkan masalah ini, dengan melakukan beberapa tes awal untuk menyisihkan objek yang tersumbat yang ada dalam rendering frustum. Salah satu implementasi praktis dari oklusi pemusnahan adalah menggunakan query berbasis titik dan memeriksa apakah objek tertentu terlihat dari tampilan titik tertentu. Ini juga dapat digunakan untuk memilah lampu yang tidak berkontribusi pada gambar akhir. Ini sangat berguna dalam mesin penyaji yang ditangguhkan.

masukkan deskripsi gambar di sini

Sebuah contoh dunia nyata yang hebat dari teknik semacam itu adalah di GTA5, di mana gedung pencakar langit ditempatkan secara stratigis di pusat kota, tidak hanya dekorasi, tetapi mereka juga bekerja sebagai penghambat, secara efektif menutup bagian kota yang lain dan mencegahnya menjadi bagian dari kota. dirasterisasi.

Tuhan

Tingkat Detail

Level detail adalah teknik yang banyak digunakan, idenya adalah menggunakan versi mesh yang lebih sederhana ketika mesh tersebut kurang berkontribusi pada adegan. ada dua implementasi umum; seseorang hanya mengganti mesh dengan yang lebih sederhana ketika tidak lagi berkontribusi besar, mesh dipilih berdasarkan beberapa faktor seperti jarak dan jumlah piksel (area pada scree) yang ditempati mesh. Versi lain secara dinamis men-tellellasikan mesh, ini banyak digunakan dalam rendering medan.

masukkan deskripsi gambar di sini

Bagaimana jika semua ini tidak berhasil?

Nah, itu pertanyaan yang bagus.

Hal pertama yang perlu Anda lakukan adalah membuat Profil aplikasi Anda menggunakan profiler grafis, dan menentukan di mana hambatannya. Perlu diingat bahwa bottleneck dapat berubah karena konten yang diberikan berubah. Kemacetan mungkin juga menjadi bagian dari kode yang berjalan pada CPU sehingga Anda perlu mengukurnya juga.

Setelah itu, Anda perlu melakukan beberapa optimasi pada bottleneck, perlu diingat bahwa tidak ada jawaban yang tepat untuk ini, dan akan berbeda dari perangkat keras yang lain.

Beberapa trik optimasi GPU yang umum:

  • Hindari bercabang di shader.
  • Coba struktur vertex yang berbeda misalnya {VNT}disisipkan dalam array yang sama atau {V},{N},{T}dalam array yang berbeda.
  • Gambar adegan depan ke belakang.
  • Matikan Z-buffer di beberapa titik misalnya jika gambar tidak perlu pengujian Z.
  • Gunakan tekstur terkompresi.

Beberapa trik pengoptimalan CPU yang umum:

  • Gunakan fungsi sebaris untuk fungsi kecil.
  • Gunakan SIMD (Instruksi tunggal beberapa data) bila memungkinkan.
  • Hindari cache dari lompatan memori yang tidak ramah.
  • Gunakan VBO dengan jumlah data "benar". (tergantung pada perangkat keras Anda) tetapi biasanya lebih sedikit panggilan yang ditarik lebih baik.

Tapi bagaimana jika kemacetan saya dalam naungan ditangguhkan?

Dalam hal ini, karena peneduhan yang ditangguhkan lebih mementingkan lampu maka bagian yang paling jelas adalah untuk mengoptimalkan perhitungan peneduhan yang sebenarnya. beberapa poin yang harus diperhatikan:

  • Jadikan lampu yang benar-benar memengaruhi gambar akhir. Dengan kata lain cull lampu yang tidak berkontribusi. Ini dapat diimplementasikan secara efektif menggunakan oklusi pemusnahan yang saya sebutkan sebelumnya.
  • Apakah lampu ini membutuhkan komponen specular atau lainnya? Mungkin tidak.
  • Apakah bayangan cahaya ini melemparkan? Beberapa lampu tidak perlu membuat bayangan.
  • Apakah kontribusi ringan ini dapat dihitung sebelumnya? Jika tidak bergerak mungkin beberapa aspek dapat dihitung sebelumnya.
concept3d
sumber
Maaf, ini tidak ada hubungannya dengan peneduhan yang ditangguhkan, mereka sebenarnya masalah kinerja yang tepat bahwa teknik mitigasi secara efektif dan oleh karena itu optimasi paling tidak berguna untuk membuat, fokus harus berada pada jalur pencahayaan karena jika biaya pencahayaan tidak pengambil waktu yang dominan, peneduhan yang ditangguhkan mungkin adalah pilihan yang salah.
MickLH
@MickLH Sayangnya, tampaknya Anda tidak membaca pertanyaan itu, masalahnya terutama karena ia mengulangi seluruh adegan setiap kali, dan ia tidak menyebutkan hambatan apa pun terkait naungan yang tertunda. Saya sebutkan pada awalnya bahwa shading yang tertunda memecahkan masalah ledakan saat memiliki banyak lampu / bahan. Tetapi saya kemudian menambahkan bahwa itu adalah optimasi yang harus dilakukan untuk mesin apa pun terlepas dari teknik naungan maju atau tertunda. Mengenai bahwa ini adalah masalah yang tepat bahwa teknik bermigrasi saya sangat tidak setuju, saya tidak bisa mengatasi seluruh poin di sini (berikut)
concept3d
itu benar-benar bodoh untuk membangun mesin yang ditangguhkan tanpa frustasi culling misalnya, jadi mesin akan memproses misalnya (100 juta vertex) hanya untuk dapat mengirimkan hasilnya ke buffer-g. Bayangan yang berbeda memecahkan masalah yang berbeda, yang bukan masalahnya, masalahnya adalah menyerahkan semua geometri ke pipa.
concept3d
meskipun saya setuju pada bagian bahwa beberapa optimasi harus terjadi pada perhitungan pencahayaan, dan jika perhitungan cahaya tidak dominan maka ditangguhkan adalah cara yang salah untuk melangkah. tapi sekali lagi itu bukan masalahnya.
concept3d
Saya akan menarik kembali downvote saya jika Anda memperjelas bahwa optimasi ini sebenarnya paling tidak efektif untuk penyaji yang ditangguhkan, karena Anda belum menunjukkan kepada googler bahwa masalah kinerja tidak ada hubungannya dengan naungan tertunda.
MickLH
6

Masalah Anda tidak terkait dengan naungan ditangguhkan apa pun , Anda perlu menerapkan elemen inti dasar penyaji sebelum Anda mencoba untuk mempercepat beberapa bagian tertentu.

Ketika Anda telah selesai dengan apa yang telah dijelaskan oleh concept3d, jika Anda benar-benar menemukan bahwa Anda perlu mengoptimalkan shader yang ditangguhkan itu sendiri (sebagai lawan dari seluruh rasterisasi pass) Anda dapat menerapkan Tile-Based Deferred Shading.

Jika Anda tidak dibatasi oleh jumlah lampu yang dinamis yang harus Anda pertimbangkan mengapa Anda menggunakan shading ditangguhkan sama sekali, tetapi jika Anda adalah maka Anda akan ingin mencoba optimasi yang membuat Battlefield 3 mungkin. (Mereka memberi isyarat di slide 10 dari PDF publik mereka: http://dice.se/wp-content/uploads/GDC11_DX11inBF3_Public.pdf )

MickLH
sumber