Shader sederhana untuk lampu titik dalam kabut

Saya membutuhkan shader sederhana dan cepat untuk membuat kabut, diterangi oleh sumber cahaya titik. Untuk mengimplementasikannya, saya menulis efek ruang layar, yang hasilnya ditunjukkan di bawah ini. Konveyor hampir sesederhana untuk sumber titik biasa. Tidak memerlukan struktur volume data, ray marching, dan dapat dengan mudah dihubungkan ke shader pencahayaan yang ada.

Prinsip yang paling penting adalah bahwa Anda dapat menghitung dalam bentuk tertutup cahaya yang berasal dari kabut, seolah-olah itu diterangi oleh sumber titik penerangan. Solusi saya adalah menemukan formula dan substitusi di shader.


Adegan kecil dengan pesawat ruang angkasa dibuat dalam kabut menggunakan teknik saya

Pengaturan dasar

Model kabut


Shader membuat beberapa asumsi tentang kabut yang sedang kami tangani. Bahkan, ia menganggap setiap pecahan kabut permukaan hamburan putih kecil tembus.

  • Shader menunjukkan bahwa kabut menyebarkan cahaya secara merata ke segala arah. Kabut atau asap asli tidak selalu memiliki sifat ini, tetapi ini merupakan perkiraan yang bagus untuk gambar yang kita tuju.
  • Shader menyarankan agar semua panjang gelombang cahaya berinteraksi dengan kabut dengan cara yang sama. Pada kenyataannya, ini sering tidak terjadi. Misalnya, hamburan Rayleigh membuat langit biru, hamburan cahaya biru lebih dari panjang gelombang lainnya.
  • Cahaya yang memancar dari kabut bervariasi tergantung pada kuadrat terbalik jarak dari sumber cahaya ke kabut. Pada kenyataannya, ini tidak terjadi, tetapi terlihat normal. Ada banyak sumber yang menjelaskan bagaimana kabut benar-benar mencerai-beraikan pencahayaan, dan saya yakin Anda dapat menambah metodologi saya dengan formula ini.

Namun. hasilnya terlihat masuk akal bahkan ketika menggunakan penyederhanaan ini.

Solusi analitik


Biarkan ada potongan kabut yang sangat kecil (bayangkan kubus kecil kabut). Lalu cahaya yang dipancarkan oleh fragmen kabut ini di sistem saya akan terlihat seperti:

light=1(distance from light to fog fragment)2


Rumus ini menunjukkan bahwa cahaya yang datang dari setiap pecahan kabut berkurang ketika kuadrat terbalik jaraknya ke sumber cahaya, seperti halnya dengan cahaya yang datang dari permukaan hamburan cahaya.

Untuk kenyamanan, kami menulis ulang persamaannya:

d=distance from light to fog fragment


light=1d2


∫view linelight atxdx


Atau, jika lebih resmi:

L=light position


w=world fragment position


c=camera position


light arriving at camera=∫cw1|xβˆ’L|2dx



Integral ini mengekspresikan apa yang kita butuhkan, tetapi perhitungannya lebih rumit dari yang kita butuhkan. Karena semua variabel pada gambar di atas adalah vektor dengan tiga nilai, kita pada dasarnya harus berurusan dengan 12 variabel. Saya akan menghilangkan sebagian besar variabel-variabel ini dengan melakukan reparameterisasi sederhana.

Tentukan ruang baru yang disebut " ruang cahaya "

  • Sumbu x adalah garis pandang
  • Sumbu Y untuk penerangan


Sekarang, alih-alih integral linear dalam ruang tiga dimensi, saya hanya melakukan integrasi sepanjang sumbu X dari kamera ke sebuah fragmen dunia. Selanjutnya kita perlu menulis ulang integralnya. Jarak dari titikx pada sumbu x ke sumber cahaya h2+x2. Oleh karena itu, garis integral pandangan mengambil bentuk

∫1h2+x2dx


Memecahkannya secara manual atau di sistem aljabar komputer favorit Anda, kami dapatkan:

∫1h2+x2dx=tanβˆ’1(xh)h


Yaitu, untuk mendapatkan pencahayaan yang berasal dari kabut untuk garis pandang tertentu, saya menghitung integral ini dari kamera ke sebuah fragmen dunia. Jika kamera masukx=a, dan sebuah fragmen dunia di x=b, maka iluminasi yang memasuki piksel dari kabut yang menyala di sepanjang garis pandang memiliki bentuk:

∫ab1h2+x2dx=tanβˆ’1(bh)hβˆ’tanβˆ’1(ah)h


Pikiran tentang implementasi


Saya berhasil menerapkan shader ini di pipeline shader tertunda saya tanpa modifikasi besar. Untuk melakukan ini, perlu menambahkan sekitar sepuluh baris kode GLSL. Jika konveyor sudah menghitung iluminasi difus + specular dengan sumber titik cahaya, maka shader sumber titik harus sudah memiliki akses ke posisi kamera. sumber cahaya dan piksel saat ini di dunia, dan hanya itu yang Anda butuhkan!

Memproses banyak sumber cahaya sangat sederhana. Cukup dengan meringkas efek hamburan cahaya dengan kabut untuk setiap sumber. Agar sistem menjadi efektif untuk banyak sumber, perlu untuk menghitung integral hanya untuk piksel yang begitu dekat dengan sumber cahaya sehingga dapat berkontribusi pada jumlah cahaya yang terlihat secara visual dalam pemandangan. Misalnya, dalam pipa shader tertunda, Anda dapat membuat jaring bulat di sekitar sumber cahaya sehingga shader hanya menghitung efek cahaya untuk piksel di dekat sumber itu.

Saya menemukan bahwa bagian paling sulit dari penerapan shader ini adalah lokasi kamera yang benar dan sebuah fragmen dunia dalam ruang pencahayaan, sehingga kita dapat menggunakan integral yang disederhanakan.

hasil



Hasilkan Worlds level rendah dengan sedikit pencahayaan kabut


Jika ada lebih banyak sumber, efeknya menjadi lebih kuat


Jika Anda juga melacak informasi tentang arah sumber cahaya, Anda dapat membuat pencahayaan berpola indah di kabut

Bacaan tambahan


Pengantar Hamburan Cahaya: Suatu Perspektif Ilmu Pencitraan

Sebuah Model Praktis Hamburan Analitik Tunggal untuk Penentuan Waktu Nyata

Algoritma hamburan atmosfer dan volumetrik Kabut Bagian 1

All Articles