bayangan stensil - doom 3 engine - kesalahan presisi - celah bayangan - mengapa?

8

Saya menguji batas-batas mesin Doom 3 - dalam hal ukuran peta maksimum.

Saya perhatikan beberapa kesalahan presisi stensil bayangan yang menjadi lebih jelas ketika objek semakin jauh dari asal peta.

pada posisi: -10901 -18214 -11204 Contoh 1

pada posisi: -10802 -26483 -19383 contoh2

pada posisi: -10802 -34683 -27540 contoh3

Saya percaya kesalahan ini telah disebut sebagai "retakan bayangan" tetapi saya tidak yakin apa artefak ini sebelumnya disebut.

Hampir semua artefak muncul di sepanjang batas lampu / bayangan - yang dapat dilihat di sini: masukkan deskripsi gambar di sini

Adakah yang pernah melihat jenis artefak grafis ini sebelumnya dengan bayangan stensil? Mereka dipanggil apa? Apa penyebabnya?

Lebih banyak contoh: misc1 misc2

Ini adalah vanilla Doom 3 Engine seperti yang ditemukan di sini: https://github.com/TTimo/doom3.gpl

Saya perhatikan ketika menguji cvar r_useOptimizedShadows (yang menangani volume bayangan dari geometri worldspawn) bahwa artefak menghilang. Lalu saya bekerja untuk fungsi ini:

R_LinkLightSurf( &vLight->globalShadows, tri, NULL, light, NULL, vLight->scissorRect, true /* FIXME? */ );

yang saya ubah menjadi ini:

R_LinkLightSurf( &vLight->globalShadows, tri, NULL, light, NULL, vLight->scissorRect, false /* FIXME? */ );

Itu menghilangkan artefak - tetapi sekarang mengasumsikan bahwa kita tidak pernah berada di dalam volume bayangan geometri worldspawn. Jadi setiap kali kita masuk ke dalam volume bayangan, volume bayangan itu tidak ditampilkan dengan benar.

Stepan1010
sumber
1
Tidak yakin tentang implementasi spesifik ini tetapi floating point kehilangan presisi semakin jauh Anda pergi dari nol.
concept3d
2
Sepakat. 7 digit hanya tentang jumlah maksimum presisi yang dapat Anda harapkan dari angka floating point 32-bit (alias C / C ++ float). Anda dengan mudah menghabiskan 5 dari itu. en.wikipedia.org/wiki/…
snake5
@ concept3d - Saya kira mengonversi float yang relevan ke ganda akan membantu? Jika seseorang memiliki pengetahuan teknis untuk melakukan itu. Bahkan jika itu akan menghasilkan waktu render yang lebih lama.
Stepan1010
1
@ glampert Saya memperbarui pertanyaan. Ini adalah mesin vanilla Doom 3.
Stepan1010
1
Apa yang terjadi ketika Anda mengubah perhitungan volume bayangan? (Misalnya hanya skala semua volume bayangan dengan nilai kecil) Apakah artefak masih muncul / berubah / hilang?
Roy T.

Jawaban:

3

Saya akhirnya menemukan solusi - sebenarnya beberapa solusi berbeda. Saya tidak mengetahui penyebab sebenarnya dari artefak dari perspektif pemrograman grafis - tetapi saya memang menemukan beberapa solusi.

Seperti yang saya katakan sebelumnya dalam pertanyaan saya, tampak bahwa artefak itu hanya terjadi pada volume bayangan pra-komputasi dari geometri statis worldspawn (yang pada dasarnya adalah geometri yang diketahui mesin tidak akan pernah bergerak sehingga pra-perhitungan di depan -waktu volume bayangan dan hal-hal lain dengan perintah yang dimasukkan di konsol yang disebut "dmap"). Saya tidak tahu mengapa itu hanya pada bayangan geometri worldspawn statis dan tidak pada model ASE atau LWO.

Sekarang, hal yang saya perhatikan adalah bahwa sebenarnya ada banyak parameter yang dapat digunakan dengan perintah dmap - salah satu dari parameter ini disebut "shadowOpt" - yang harus mewakili tingkat optimisasi bayangan. Parameter ini menetapkan enum - tampaknya ada beberapa level optimisasi bayangan yang berbeda:

typedef enum {
    SO_NONE,            // 0 // NOTE: I haven't tried this one yet - should test this one.
    SO_MERGE_SURFACES,  // 1 // NOTE: this was the original default one - it causes some artifacts - the ones I have been trying to fix.
    SO_CULL_OCCLUDED,   // 2 // NOTE: this one works the best - takes a bit longer - but it has alot of unnecessary print statements that could probably be removed.
    SO_CLIP_OCCLUDERS,  // 3 // NOTE: I haven't tried this one yet - but it is not used anywhere.
    SO_CLIP_SILS,       // 4 // NOTE: I haven't tried this one yet - should test this one.
    SO_SIL_OPTIMIZE     // 5 // NOTE: this one doesn't seem to work well at all - and it takes an extrememly long amount of time - was probably an expirimental version.
} shadowOptLevel_t;

Saya telah sukses dengan opsi 2 - "SO_CULL_OCCLUDED". Ini memperbaiki semua artefak - ini membutuhkan waktu sedikit lebih lama untuk dijalankan - tapi saya percaya banyak waktu ini dihabiskan untuk mencetak banyak informasi ke konsol - cetakan ini mungkin dapat dikurangi atau dihilangkan dengan.

Salah satu tempat yang memberi saya beberapa petunjuk adalah komentar di sini di tr_stencilshadow.cpp:

// if we are running from dmap, perform the (very) expensive shadow optimizations
// to remove internal sil edges and optimize the caps
if ( callOptimizer ) {

Sekarang, masalah dengan hanya melakukan optimisasi bayangan "ekstra" selama "dmap" adalah bahwa jika ada dari lampu-lampu ini yang pernah dipindahkan (yang selalu mungkin tergantung pada jenis proyek yang Anda lakukan) - maka ia akan secara default kembali ke proses pembuatan volume bayangan bayangan waktu nyata (yang tidak dioptimalkan) (untuk lampu yang dipindahkan) dan artefak akan muncul kembali untuk lampu itu. Jadi satu-satunya cara untuk menjamin bahwa artefak ini tidak akan muncul adalah dengan selalu menjalankan proses optimisasi yang sangat mahal untuk bayangan duniawi statis ini. Ini sebenarnya sangat mahal sehingga ini akan menjadi pilihan terakhir jika Anda tidak dapat menemukan solusi grafis yang tepat. (jika Anda melakukannya, pastikan untuk mengirim solusi Anda di sini.)

Saya akan merekomendasikan bagi siapa pun yang membuat peta besar untuk mesin vanilla Doom 3 - dan menggunakan worldspawn geometry - agar mereka membuat cvar yang dapat mereka ubah tergantung pada kebutuhan mereka untuk pembuatan volume bayangan bayangan yang dioptimalkan secara waktu nyata. Saya menyebut cvar r_useExpensiveShadowOptimizations - yang tampaknya merupakan oxymoron. Sebagai contoh:

// if we are running from dmap, perform the (very) expensive shadow optimizations
// to remove internal sil edges and optimize the caps
if ( callOptimizer || r_useExpensiveShadowOptimizations.GetBool() ) {

Saya juga merekomendasikan bahwa tergantung pada seberapa besar peta Anda (dan dengan asumsi lampu tidak akan bergerak), Anda meningkatkan tingkat optimasi volume bayangan statis dengan parameter "shadowOpt" untuk dmap.

Jadi pada dasarnya semua hal yang Anda butuhkan untuk memiliki peta besar dan tidak memiliki artefak bayangan ada untuk Anda, Anda hanya perlu memutuskan mana yang perlu Anda gunakan. Melakukannya secara real time sangat mahal dan hanya boleh dilakukan sebagai upaya terakhir jika Anda tidak dapat menemukan solusi grafis yang tepat. Melakukannya dalam DMAP sangat masuk akal karena memecahkan masalah dan hanya membutuhkan beberapa detik lagi untuk dikompilasi oleh peta.

Stepan1010
sumber
2

Ini bisa menjadi kesalahan presisi pointer mengambang, karena Doom digunakan floatuntuk rendering (terutama batasan OpenGL). Namun, mengotak-atik sekitar tr_stencilshadow.cpp, saya perhatikan komentar ini yang mungkin terkait dengan masalah ( PointsOrdered()fungsi dalam ):

// vectors that wind up getting an equal hash value will
// potentially cause a misorder, which can show as a couple
// crack pixels in a shadow

....

// in the very rare case that these might be equal, all that would
// happen is an oportunity for a tiny rasterization shadow crack

Jadi begitulah. Mungkin juga merupakan batasan yang diketahui tentang cara rendering bayangan diimplementasikan. Sejujurnya, kodenya sangat berantakan dan sulit dibaca, jadi saya tidak bisa memberi tahu Anda dengan pasti. Anda dapat mencoba mengirim devs untuk mendapatkan info lebih lanjut.

Glampert
sumber
1
Saya juga melihat komentar itu. Namun, ketika saya berkomentar kode fungsi itu dan hanya mengembalikannya benar (atau salah - tidak masalah) - tampaknya tidak membuat perbedaan visual untuk apa pun. Apakah Anda pikir ada devs yang akan merespons jika saya mengirim email kepada mereka? Saya merasa mereka mungkin tidak akan menanggapi. Saya kira saya bisa mencobanya jika semuanya gagal.
Stepan1010
@ Stepan1010 Yah, tidak tahu, Carmack adalah orang yang keren, saya pernah mengiriminya tentang sesuatu yang tidak terkait dengan pemrograman dan dia menjawab. Saya kira tidak ada salahnya mencoba ... Tapi mungkin Anda harus mengirim pengelola repo, karena Carmack tidak lagi menjadi anggota idSoftware. Jika Anda menunjukkan masalah yang sah dan pekerjaan yang Anda lakukan, mereka mungkin tertarik.
glampert