Halo, Habr! Saya mempersembahkan kepada Anda terjemahan artikel
“Paparan Lokal Dinamis” oleh John Chapman.
Pada artikel ini, saya akan memperkenalkan beberapa ide tentang paparan lokal dinamis dalam rendering HDR. Bart Wronsky sudah memiliki
artikel yang bagus tentang hal ini dan saya sangat merekomendasikan membacanya segera jika Anda belum melakukannya; ide-ide di sini adalah, sebagian besar, berdasarkan artikelnya. Pada akhirnya, saya memasukkan beberapa tautan hebat lainnya.
Rentang Dinamis Rendah / Tinggi
Di masa lalu yang baik (1990-an), game diberikan langsung dalam format
LDR (rentang dinamis sempit) yang ditampilkan (ruang gamma, 8 bit). Itu sederhana dan murah, tetapi, di sisi lain, secara signifikan mengganggu penciptaan gambar yang benar-benar fotorealistik.
Saat ini, terutama dengan munculnya
PBR (render berbasis fisik), game diberikan dengan rentang dinamis raksasa di ruang linear dengan akurasi yang lebih tinggi. Dengan gerakan ini, masalah sebenarnya adalah fotorealisme: bagaimana kita bisa menampilkan gambar
HDR di
LDR ?
Global Auto Exposure
Pendekatan standar untuk kontrol eksposur otomatis adalah untuk mengukur kecerahan rata-rata (atau rata-rata logaritmik) dari pemandangan, secara opsional dengan fungsi
bobot yang lebih menyukai nilai yang dekat dengan bagian tengah gambar. Hal ini dapat dilakukan dengan sangat efisien dengan menggunakan reduksi paralel atau berulang kali
downsampling dalam
mipmap buffer luminance . Pendekatan terakhir memiliki beberapa keunggulan, yang akan saya bahas di bagian selanjutnya.
Kecerahan rata-rata selanjutnya dikonversi ke nilai pencahayaan, misalnya, dengan menghitung kebalikan dari kecerahan maksimum yang diijinkan dari pemandangan:
float Lavg = exp(textureLod(txLuminance, uv, 99.0).x); float ev100 = log2(Lavg * 100.0 / 12.5); ev100 -= uExposureCompensation;
Diperoleh dari standar ISO untuk menghitung kecepatan berdasarkan saturasi, untuk penjelasan lengkap, lihat (3)Karena kecerahan rata-rata potensial tidak stabil dalam kondisi dinamis, maka biasanya diperhalus seiring waktu menggunakan fungsi histeresis eksponensial
(2) :
Lavg = Lavg + (Lnew - Lavg) * (1.0 - exp(uDeltaTime * -uRate));
Komentar PenerjemahFungsi ini perlu diterapkan dalam kecerahan tekstur shader downsampling dan hanya selama perhitungan tingkat mip terakhir (1x1). Lebih lanjut akan ditulis tentang ini, tetapi menurut saya mudah untuk diabaikan.
Karena sifat globalnya, metode ini menderita naungan parah atau sorotan pada area gambar di mana ada penyimpangan dari kecerahan rata-rata:

Meskipun ini sesuai dengan kemampuan mata untuk beradaptasi dengan perubahan tingkat cahaya, efek keseluruhannya cukup jauh dari apa yang sebenarnya kita rasakan di dunia nyata.
AE lokal
Jika kita menghasilkan kecerahan sedang dengan
downsampling , kita memiliki akses ke level mip yang lebih rendah dari
buffer luminance (4) untuk mendapatkan kecerahan rata-rata lokal.
float Lavg = exp(textureLod(txLuminance, uv, uLuminanceLod).x;
Harap dicatat bahwa agar ini berfungsi, histeresis harus diterapkan hanya pada langkah terakhir (saat merekam level 1x1 mip), jika tidak akan ada artefak.Secara teori, ini adalah ide bagus: setiap area gambar dapat memiliki eksposur yang baik, sementara kontras dengan area tetangga. Namun, dalam praktiknya, hasil yang menjijikkan diperoleh:

Yang paling tidak menyenangkan adalah blok "lingkaran cahaya" yang ditemukan di daerah dengan kontras tinggi:

Namun, mereka dapat dihaluskan dengan menyaring
luminance buffer , atau hanya menggunakan pengambilan sampel bikubik:

Itu masih terlihat menjijikkan, tapi sudah lebih baik.
Sampling berbagai tingkat mipmap dalam
pencahayaan mengubah jari-jari lingkaran cahaya. Parameter ini berguna untuk mengendalikan keseluruhan "tampilan" dari hasil, serta untuk meminimalkan efek halo, meskipun karena penurunan umum dalam kontras (menjadi filter perbatasan) atau hilangnya lokalitas kontrol eksposur:

Namun, menghaluskan ghosting tidak cukup. Hasilnya sama sekali tidak alami; terlihat seperti gaya "foto HDR" yang ekstrim, tidak seperti apa yang dilihat seseorang. Namun, dengan menggabungkan nilai-nilai global dan lokal, kita bisa mendapatkan yang terbaik dari kedua dunia:
float Llocal = exp(textureLod(txLuminance, uv, uLuminanceLod).x; float Lglobal = exp(textureLod(txLuminance, uv, 99.0).x; float L = mix(Lglobal, Llocal, uLocalExposureRatio);

Dengan mengubah faktor pencampuran, Anda dapat menyesuaikan paparan lokal sehingga sebagai hasilnya, meminimalkan artefak dan memaksimalkan realisme yang dirasakan:

Rasio Campuran Otomatis
Menyesuaikan
rasio pencampuran secara manual
adalah normal dalam situasi di mana kami memiliki kendali mutlak atas posisi kamera, pencahayaan, dll. Namun, dalam banyak kasus (misalnya, permainan di luar ruangan dengan perubahan dinamis siang dan malam), tingkat kontrol ini tidak mungkin. Dalam hal ini, alangkah baiknya untuk menghasilkan
mix factor secara otomatis.
Pada gambar di bawah ini kami memiliki rentang dinamis yang luas; sebagian besar nilai kecerahan sedang-rendah dan beberapa area dengan intensitas tinggi (langit di jendela):

Tanpa paparan lokal, warna langit akan hilang. Dalam hal ini, saya ingin
rasio pencampuran yang besar:

Sekarang perhatikan gambar di bawah ini, yang memiliki rentang dinamis kecil terutama dengan nilai kecerahan tinggi:

Dalam hal ini, menerapkan paparan lokal mengurangi kecerahan area "cerah" terlalu banyak:

Data pengamatan mengisyaratkan metode sederhana pencampuran nilai-nilai
lokal dan
global : jika perbedaan antara kecerahan rata-rata dan maksimum adegan lebih besar, maka koefisien pencampuran paparan lokal harus lebih besar. Generasi
kecerahan maksimum adegan dapat dilakukan secara sepele selama perhitungan kecerahan, menggunakan histeresis untuk menghaluskan hasilnya dengan cara yang sama seperti untuk nilai rata-rata. Oleh karena itu, kami dapat memperluas fragmen kode sebelumnya sebagai berikut:
float Llocal = exp(textureLod(txLuminance, uv, uLuminanceLod).x; float Lglobal = exp(textureLod(txLuminance, uv, 99.0).x;
Harap dicatat bahwa uLocalExposureMax muncul di input kami untuk mengontrol tingkat pengaruh absolut maksimum dari paparan lokal. Saya mendapat hasil yang baik uLocalExposureMax <0,3 .Kode akhir float Llocal = exp(textureLod(txLuminance, uv, uLuminanceLod).x; float Lglobal = exp(textureLod(txLuminance, uv, 99.0).x;
Kesimpulan
Pendekatan yang diuraikan di atas memberikan beberapa batasan kapan perlu untuk mengukur kecerahan pemandangan. Biasanya pengukuran dilakukan segera setelah penerangan untuk menghindari adaptasi efek
partikel ,
mekar , dll. Namun, ketika kecerahan lokal digunakan, penting bahwa nilai nyata yang berpartisipasi dalam paparan disajikan dalam
peta luminance . Ini berarti bahwa pengukuran kecerahan perlu dilakukan segera sebelum menerapkan pencahayaan. Jika ini tidak dapat diterima, maka solusinya adalah untuk menghasilkan kecerahan lokal secara terpisah dari nilai rata-rata dan maksimum.
Meskipun saya berpikir bahwa menggunakan kecerahan lokal dan global dari adegan bersama adalah pendekatan yang “benar” untuk menciptakan gambar yang seimbang dan tampak alami, kualitas hasilnya jelas subyektif. Apakah metode seperti itu cocok untuk gim tertentu bergantung sepenuhnya pada konten dan gaya visual yang diinginkan. Saya akan tertarik untuk mendengar ide-ide lain dalam hal ini.
Referensi
- Tonemapping Lokal (Bart Wronski)
- Menerapkan Kamera Berbasis Fisik (Padraic Hennessy)
- Memindahkan Frostbite ke PBR (Sébastien Lagarde, et al.)
- Pandangan yang Lebih Dekat pada Pemetaan Ton (Matt Pettineo)
- Pentingnya Menjadi Linear (Larry Gritz, et al.)
- Teknik Canggih dan Optimalisasi Pipa Warna HDR / VDR (Timothy Lottes)
Gambar HDR diambil dari sIBL Archive .