Biasanya ada dua metode untuk menangani ini. Saat ini, mereka disebut rendering maju dan rendering ditangguhkan. Ada satu variasi pada keduanya yang akan saya bahas di bawah ini.
Penerusan ke depan
Berikan setiap objek satu kali untuk setiap cahaya yang mempengaruhinya. Ini termasuk cahaya sekitar. Anda menggunakan mode campuran aditif ( glBlendFunc(GL_ONE, GL_ONE)
), sehingga kontribusi setiap lampu ditambahkan satu sama lain. Karena kontribusi lampu yang berbeda bersifat aditif, framebuffer akhirnya mendapatkan nilai
Anda bisa mendapatkan HDR dengan merender ke framebuffer floating-point. Anda kemudian mengambil lintasan terakhir adegan untuk menurunkan skala nilai pencahayaan HDR ke rentang yang terlihat; ini juga akan menjadi tempat Anda menerapkan bloom dan efek pasca lainnya.
Peningkatan kinerja umum untuk teknik ini (jika adegan memiliki banyak objek) adalah dengan menggunakan "pra-pass", di mana Anda membuat semua objek tanpa menggambar apa pun ke framebuffer warna (gunakan glColorMask
untuk mematikan penulisan warna). Ini hanya mengisi buffer kedalaman. Dengan cara ini, jika Anda merender objek yang berada di belakang objek lain, GPU dapat dengan cepat melewati bagian-bagian itu. Itu masih harus menjalankan vertex shader, tetapi dapat melewati perhitungan fragmen shader yang biasanya lebih mahal.
Ini lebih mudah untuk dikodekan dan lebih mudah divisualisasikan. Dan pada beberapa perangkat keras (terutama GPU seluler dan tertanam), ini bisa lebih efisien daripada alternatifnya. Tetapi pada perangkat keras kelas atas, alternatif umumnya menang untuk adegan dengan banyak lampu.
Render yang ditangguhkan
Render yang ditangguhkan sedikit lebih rumit.
Persamaan pencahayaan yang Anda gunakan untuk menghitung cahaya untuk suatu titik pada permukaan menggunakan parameter permukaan berikut:
- Posisi permukaan
- Permukaan normals
- Permukaan warna menyebar
- Permukaan warna specular
- Permukaan specular shininess
- Mungkin parameter permukaan lainnya (tergantung pada seberapa kompleks persamaan pencahayaan Anda)
Dalam rendering maju, parameter ini sampai ke fungsi pencahayaan fragmen shader baik dengan dilewatkan langsung dari vertex shader, ditarik dari tekstur (biasanya melalui koordinat tekstur yang dilewatkan dari vertex shader), atau dihasilkan dari seluruh kain dalam fragmen shader berdasarkan pada parameter lainnya. Warna difus dapat dihitung dengan menggabungkan warna per-simpul dengan tekstur, menggabungkan beberapa tekstur, apa pun.
Dalam rendering yang ditangguhkan, kami menjadikan ini semua eksplisit. Pada pass pertama, kami me-render semua objek. Tapi kami tidak membuat warna . Sebagai gantinya, kami membuat parameter permukaan . Jadi setiap piksel pada layar memiliki satu set parameter permukaan. Ini dilakukan melalui rendering ke tekstur di luar layar. Satu tekstur akan menyimpan warna difus sebagai RGB-nya, dan mungkin kilau specular sebagai alfa. Tekstur lain akan menyimpan warna specular. Yang ketiga akan menyimpan yang normal. Dan seterusnya.
Posisi ini biasanya tidak disimpan. Alih-alih disusun kembali dalam lulus kedua dengan matematika yang terlalu rumit untuk masuk ke sini. Cukuplah untuk mengatakan, kita menggunakan buffer kedalaman dan posisi fragmen ruang layar sebagai input untuk mengetahui posisi ruang kamera dari titik di permukaan.
Jadi, sekarang karena tekstur ini pada dasarnya menyimpan semua informasi permukaan untuk setiap piksel yang terlihat dalam adegan, kami mulai membuat paha depan layar penuh. Setiap lampu mendapat render layar penuh quad. Kami sampel dari tekstur parameter permukaan (dan menyusun kembali posisi), lalu gunakan saja untuk menghitung kontribusi cahaya itu. Ini ditambahkan (lagi glBlendFunc(GL_ONE, GL_ONE)
) ke gambar. Kami terus melakukan ini sampai kami kehabisan lampu.
HDR lagi adalah langkah pasca-proses.
Kelemahan terbesar dari rendering yang ditangguhkan adalah antialiasing. Dibutuhkan sedikit lebih banyak kerja untuk antialias dengan benar.
Keuntungan terbesarnya, jika GPU Anda memiliki banyak bandwidth memori, adalah kinerja. Kami hanya merender geometri aktual satu kali (atau 1 + 1 per cahaya yang memiliki bayangan, jika kami melakukan pemetaan bayangan). Kami tidak pernah menghabiskan waktu pada piksel atau geometri tersembunyi yang tidak terlihat setelah ini. Semua waktu berlalu pencahayaan dihabiskan untuk hal-hal yang benar-benar terlihat.
Jika GPU Anda tidak memiliki banyak bandwidth memori, maka pass cahaya benar-benar dapat mulai sakit. Menarik dari 3-5 tekstur per piksel layar tidak menyenangkan.
Pra-Lintasan Ringan
Ini adalah semacam variasi pada rendering yang ditangguhkan yang memiliki tradeoff yang menarik.
Seperti halnya dalam rendering yang ditangguhkan, Anda membuat parameter permukaan Anda ke sejumlah buffer. Namun, Anda telah menyingkat data permukaan; satu-satunya data permukaan yang Anda pedulikan saat ini adalah nilai buffer kedalaman (untuk merekonstruksi posisi), normal, dan kekakuan specular.
Kemudian untuk setiap cahaya, Anda hanya menghitung hasil pencahayaan. Tidak ada multiplikasi dengan warna permukaan, tidak ada. Hanya titik (N, L), dan istilah specular, sepenuhnya tanpa warna permukaan. Istilah specular dan difus harus disimpan dalam buffer terpisah. Istilah specular dan difus untuk setiap cahaya dirangkum dalam dua buffer.
Kemudian, Anda merender ulang geometri, menggunakan perhitungan pencahayaan specular total dan difus untuk melakukan kombinasi akhir dengan warna permukaan, sehingga menghasilkan keseluruhan pantulan.
Sisi baiknya di sini adalah Anda mendapatkan multisampling kembali (setidaknya, lebih mudah daripada dengan ditangguhkan). Anda melakukan rendering per objek lebih sedikit daripada rendering maju. Tetapi hal utama yang ditangguhkan adalah bahwa ini menyediakan waktu yang lebih mudah untuk memiliki persamaan pencahayaan yang berbeda untuk permukaan yang berbeda.
Dengan rendering yang ditangguhkan, Anda biasanya menggambar seluruh adegan dengan shader per-light yang sama. Jadi setiap objek harus menggunakan parameter material yang sama. Dengan pra-lintasan cahaya, Anda dapat memberi masing-masing objek shader yang berbeda, sehingga dapat melakukan langkah pencahayaan terakhir sendiri.
Ini tidak memberikan kebebasan sebanyak kasus rendering maju. Tetapi itu masih lebih cepat jika Anda memiliki bandwidth tekstur untuk cadangan.