Artefak Pemetaan Shadow

8

Saya telah bermain-main dengan pemetaan bayangan di OpenGL menggunakan tekstur kedalaman. Tekstur kedalamannya baik-baik saja dan saya bisa memetakannya ke tempat kejadian tetapi saya memiliki beberapa artefak aneh di belakang objek:

Sphere memberi bayangan, dengan artefak di belakang

Pertanyaan saya adalah apa yang menyebabkan ini dan bagaimana saya bisa memperbaikinya?

Shader fragmen yang saya gunakan cukup mudah (saya menghapus warna untuk kesederhanaan jika Anda bertanya-tanya mengapa tidak ada biru di sini):

in vec4 vShadowCoord;

uniform sampler2DShadow shadowMap;

out vec4 fragColor;

void main()
{
    float bias = 0.005;
    float visibility = 1.0;
    if (texture(shadowMap, vec3(vShadowCoord.xy, vShadowCoord.z / vShadowCoord.w)) < (vShadowCoord.z - bias) / vShadowCoord.w)
        visibility = 0.25;

    fragColor = vec4(visibility);
}

Sunting: Seperti yang diminta, tangkapan layar contoh kerja minimum yang hanya menggunakan kode di atas (tidak ada warna).

Bola yang sama, warna minus

Blarglenarf
sumber
1
Bisakah Anda mengkonfirmasi apakah kode yang ditampilkan (dengan warna biru dihapus) juga menyebabkan artefak? Jika Anda telah mempersempit kode maka menampilkan gambar dari kode yang dipersempit akan membantu mengecualikan detail yang tidak relevan dan menyoroti masalah.
trichoplax
Ya, saya pikir saya akan mengambil screenshot dengan warna di sana kalau tidak, itu terlihat lebih jelek :)
Blarglenarf
Saya bisa memahaminya, tetapi karena kejelekannya Anda meminta bantuan, Anda mungkin memiliki peluang lebih baik untuk melihat masalah jika Anda menyertakan tangkapan layar yang juga sesuai dengan kode.
trichoplax
1
Cukup adil. Saya telah menambahkan tangkapan layar ekstra.
Blarglenarf
Sudahkah Anda mencoba bermain-main sedikit lebih banyak dengan bias?
cifz

Jawaban:

11

Masalah ini terlihat seperti artefak jerawat bayangan peta standar. Selain itu persamaan pencahayaan Anda tidak lengkap atau salah. Cahaya seharusnya tidak memengaruhi wajah dengan normals yang menghadapinya. Ini juga berarti bahwa dengan persamaan yang tepat, sisi "gelap" bola seharusnya tidak memiliki artefak jerawat.

Ada tiga sumber artefak jerawat:

  • Sumber jerawat pertama adalah ketelitian peta bayangan. Pastikan bidang dekat dan jauh dari cahaya pengecoran bayangan sekencang mungkin. Semua objek sebelum pesawat yang dekat dapat dilipat, karena kedalamannya yang sebenarnya tidak penting.
  • Sumber jerawat kedua adalah resolusi bayangan peta. Untuk cahaya arah, Anda harus melakukan cascade shadow map dengan setidaknya 3 cascade 1024x1012 untuk ~ 100-200m jarak shadow. Sulit untuk menutupi jarak bayangan yang sama dengan satu peta bayangan dengan proyeksi seragam.
  • Sumber jerawat ketiga adalah filter peta bayangan lebar seperti PCF, karena menggunakan nilai perbandingan kedalaman kedalaman tunggal di kernel yang luas tidak cukup. Ada banyak metode untuk memperbaikinya, tetapi tidak ada yang kuat.

Singkatnya, frustum yang ketat dengan beberapa kaskade dan beberapa penyesuaian bias sudah cukup untuk membuat case umum bekerja (directional light). Mulai tweaker dengan menonaktifkan filter bayangan dan tweak untuk memfilter hanya ketika peta bayangan dasar cukup kuat.

Selain terlepas dari bias kedalaman konstan (yang saat ini Anda gunakan), Anda juga harus menambahkan bias kedalaman lereng dan bias kedalaman lereng maksimum. Keduanya dapat diimplementasikan baik sebagai status render atau sebagai kode shader selama rendering shadowmap. Bias kedalaman lereng hanyalah nilai bias ajaib yang diskalakan dengan titik (normal, lightDir).

Ada beberapa metode tambahan yang menarik dan sebagian besar diimplementasikan dalam demo yang sangat baik: Matt Pettineo - "Contoh teknik bayangan" .

  • Flip culling selama rendering bayangan peta (tukar jerawat untuk Peter panning).
  • Pemetaan bayangan offset normal menghasilkan keajaiban untuk masalah bias, tetapi harus memiliki vertex normals sekitar selama naungan.
  • Metode berbasis varians (ESM, VSM, EVSM) sepenuhnya menghapus masalah bias, tetapi memiliki kelemahan lainnya (kebocoran ringan dan / atau masalah kinerja).
Krzysztof Narkowicz
sumber