Halo, Habr! Saya mempersembahkan kepada Anda terjemahan artikel
"Pseudo Lens Flare" oleh John Chapman.
Lens suar (lens suar) adalah artefak fotografi yang timbul dari hamburan dan pembiasan cahaya dalam sistem lensa. Meskipun ini adalah artefak, ada banyak alasan untuk menggunakan
suar lensa dalam grafik komputer:
- itu meningkatkan kecerahan yang dirasakan dan rentang dinamis gambar yang terlihat.
- suar lensa sering ditemukan dalam foto, sehingga ketidakhadirannya bisa mencolok
- itu dapat memainkan peran penting dalam gaya atau drama, atau dapat menjadi bagian dari gameplay dalam game (bayangkan silau membutakan pemain)
Secara tradisional,
suar lensa secara realtime telah diimplementasikan menggunakan teknologi berbasis sprite. Meskipun sprite memberikan hasil yang mudah dikontrol dan sangat realistis, mereka harus ditempatkan secara eksplisit dan membutuhkan data oklusi untuk ditampilkan dengan benar. Di sini saya akan menjelaskan efek ruang layar yang sederhana dan relatif murah yang menciptakan
suar lensa semu dari buffer warna input. Ini tidak didasarkan pada fisika, sehingga hasilnya sedikit berbeda dari yang fotorealistik, tetapi dapat digunakan dalam kombinasi dengan (atau sebagai pengganti) untuk efek berbasis sprite tradisional.
Algoritma
Terdiri dari 4 tahap:
- Downsample / ambang batas.
- Generasi elemen suar lensa .
- Kabur
- Kelas atas / blending dengan gambar asli.
1. Downsample / Ambang Batas
Downsampling - optimisasi untuk mengurangi biaya langkah selanjutnya. Selain itu, kami ingin memilih subset piksel paling terang di gambar asli. Menggunakan
skala / bias (skala / bias) menyediakan cara yang fleksibel untuk mencapai ini:
uniform sampler2D uInputTex; uniform vec4 uScale; uniform vec4 uBias; noperspective in vec2 vTexcoord; out vec4 fResult; void main() { fResult = max(vec4(0.0), texture(uInputTex, vTexcoord) + uBias) * uScale; }

Penyesuaian
skala / bias adalah cara utama untuk menyesuaikan efek; pengaturan terbaik akan tergantung pada rentang dinamis buffer warna, serta seberapa tipis Anda ingin melihat hasilnya. Karena fakta bahwa tekniknya adalah pendekatan, kehalusan lebih cenderung terlihat lebih baik.
2. Generasi elemen suar lensa
Elemen
suar lensa cenderung berputar di tengah gambar. Dengan mensimulasikan efek ini, kita dapat memperluas hasil tahap sebelumnya secara horizontal / vertikal. Ini mudah dilakukan pada tahap pembuatan elemen dengan memperluas koordinat tekstur:
vec2 texcoord = -vTexcoords + vec2(1.0);
Ini tidak perlu; pembuatan elemen bekerja dengan baik dengan dan tanpa itu. Namun, hasil perubahan koordinat tekstur membantu memisahkan secara visual efek
suar lensa dari gambar asli.
Hantu
"
Hantu " (hantu) mengulangi sorotan yang mencerminkan area terang di buffer warna, terbentang relatif ke tengah gambar. Pendekatan yang saya pilih untuk menghasilkan adalah untuk mendapatkan vektor dari piksel saat ini ke tengah layar, dan kemudian membuat beberapa pilihan di sepanjang vektor ini.

uniform sampler2D uInputTex; uniform int uGhosts;
Perhatikan bahwa saya menggunakan
fract () untuk memastikan bahwa koordinat tekstur membungkus; ekuivalen Anda dapat menggunakan mode bungkus
GL_REPEAT untuk tekstur.
Inilah hasilnya:

Anda dapat meningkatkan hasilnya dengan hanya mengizinkan area terang lebih dekat ke tengah gambar untuk menghasilkan hantu. Kami dapat mencapai ini dengan menambahkan bobot yang akan berkurang dari pusat sampel:
vec4 result = vec4(0.0); for (int i = 0; i < uGhosts; ++i) { vec2 offset = fract(texcoord + ghostVec * float(i)); float weight = length(vec2(0.5) - offset) / length(vec2(0.5)); weight = pow(1.0 - weight, 10.0); result += texture(uInputTex, offset) * weight; }
Fungsi beratnya sesederhana mungkin - linier. Alasan kami menghitung berat di dalam loop adalah karena area terang di tengah gambar input dapat "melemparkan" hantu ke perbatasan, tetapi area terang di perbatasan tidak dapat melemparkan hantu ke tengah.

Peningkatan terakhir adalah perubahan warna radial hantu, sesuai dengan tekstur 1D:

Ini diterapkan setelah siklus untuk mempengaruhi warna akhir hantu:
result *= texture(uLensColor, length(vec2(0.5) - texcoord) / length(vec2(0.5)));
HALOS (lingkaran cahaya)
Jika kita mengambil vektor ke tengah gambar, seperti dalam perhitungan
hantu , tetapi memperbaiki panjang vektor, kita mendapatkan efek yang berbeda: gambar asli terdeformasi secara radial:

Kita dapat menggunakan ini untuk membuat "halo" dengan mengalikan berat dengan sampel, sehingga membatasi kontribusi gambar cacat ke cincin yang jari-jarinya dikendalikan oleh
uHaloWidth :

DISTORSI KROMATIK (distorsi warna)
Beberapa suar lensa memiliki distorsi warna yang disebabkan oleh variasi dalam refraksi cahaya pada panjang gelombang yang berbeda. Kita dapat mensimulasikan ini dengan membuat fungsi yang memilih saluran merah, hijau, dan biru secara terpisah dengan offset yang sedikit berbeda di sepanjang vektor sampel:
vec3 textureDistorted( in sampler2D tex, in vec2 texcoord, in vec2 direction,
Ini dapat digunakan sebagai pengganti langsung untuk
tekstur panggilan
() dalam daftar sebelumnya. Saya menghitung
arah dan
distorsi sebagai berikut:
vec2 texelSize = 1.0 / vec2(textureSize(uInputTex, 0)); vec3 distortion = vec3(-texelSize.x * uDistortion, 0.0, texelSize.x * uDistortion); vec3 direction = normalize(ghostVec);
Meskipun fungsi pengambilannya sederhana, biaya sampel x3 dari tekstur, meskipun mereka semua harus ramah cache kecuali Anda mengatur
uDistortion ke beberapa nilai raksasa.
Dengan generasi elemen, semuanya. Inilah hasilnya:

3. Kabur
Tanpa buram, elemen
suar lensa (khususnya, hantu) cenderung mempertahankan tampilan gambar. Dengan menambahkan blur ke elemen
suar lensa , kami melemahkan frekuensi tinggi dan dengan demikian mengurangi kontras dengan gambar input, yang membantu kami menjual efeknya.

Saya tidak akan memberi tahu cara membuat buram; Anda dapat membacanya di berbagai sumber daya Internet (Gaussian blur).
4. Kelas atas / menyatu dengan gambar asli
Jadi, kita memiliki elemen
suar lensa kita, kabur dengan baik. Bagaimana kita bisa menggabungkannya dengan gambar sumber asli? Ada beberapa pertimbangan penting mengenai seluruh pipa render:
- Setiap kekaburan gerakan atau kedalaman bidang selanjutnya harus diterapkan sebelum digabungkan dengan suar lensa , sehingga elemen suar lensa tidak akan ikut serta dalam efek ini.
- Suar lensa harus diterapkan sebelum melakukan pemetaan ton . Ini masuk akal secara fisik, karena tonemapping meniru respons film / CMOS terhadap cahaya yang masuk, di mana suar lensa merupakan bagian integral.
Dengan mengingat hal itu, ada beberapa hal yang dapat kita lakukan pada tahap ini untuk meningkatkan hasilnya:
LENS DIRT
Pertama, Anda perlu memodifikasi elemen
suar lensa dengan tekstur kotor dalam resolusi penuh (yang banyak digunakan di Battlefield 3):

uniform sampler2D uInputTex;
Kunci untuk ini adalah tekstur yang sangat kotor pada lensa. Jika kontrasnya rendah, bentuk
suar lensa cenderung mendominasi hasilnya. Dengan meningkatnya kontras, elemen
suar lensa teredam, yang memberikan tampilan estetika yang berbeda dan juga menyembunyikan beberapa cacat.
STARBURST DIFFRACTION
Sebagai peningkatan tambahan, kita dapat menggunakan tekstur
starburst dengan menambahkannya ke
kotoran lensa :

Sebagai tekstur,
starburst tidak terlihat sangat bagus. Namun demikian, kita dapat meneruskan matriks transformasi ke shader, yang akan memungkinkan kita untuk memutar / merusak
starburst setiap frame dan mendapatkan efek dinamis yang diinginkan:
uniform sampler2D uInputTex;
Matriks transformasi
uLensStarMatrix didasarkan pada nilai yang diperoleh dari orientasi kamera sebagai berikut:
vec3 camx = cam.getViewMatrix().col(0);
Ada cara lain untuk mendapatkan nilai camrot; yang paling penting, itu harus berubah terus menerus ketika kamera diputar. Matriks itu sendiri dibangun sebagai berikut:
mat3 scaleBias1 = ( 2.0f, 0.0f, -1.0f, 0.0f, 2.0f, -1.0f, 0.0f, 0.0f, 1.0f, ); mat3 rotation = ( cos(camrot), -sin(camrot), 0.0f, sin(camrot), cos(camrot), 0.0f, 0.0f, 0.0f, 1.0f ); mat3 scaleBias2 = ( 0.5f, 0.0f, 0.5f, 0.0f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, ); mat3 uLensStarMatrix = scaleBias2 * rotation * scaleBias1;
Matriks
skala dan
bias membutuhkan offset asal tekstur sehingga kita dapat memutar
starburst relatif ke tengah gambar.
Kesimpulan
Jadi sekarang semuanya! Metode ini menunjukkan bagaimana proses pos yang relatif disederhanakan memberikan
suar lensa yang tampak layak. Ini tidak sepenuhnya fotorealistik, tetapi jika digunakan dengan benar, itu dapat menghasilkan hasil yang sangat baik.

UPDPenulis juga menerbitkan
artikel dengan sedikit optimasi.
Kode sumber dapat dilihat di
sini dan di
sini .