Alla fine ho trovato una soluzione, in realtà alcune soluzioni diverse. Ho fatto non capire la vera causa del manufatto da una grafica di programmazione punto di vista - ma ho trovato alcune soluzioni.
Come ho affermato in precedenza nella mia domanda, sembrava che il manufatto si stesse verificando solo sui volumi d'ombra precalcolati della geometria statica generata dal mondo (che è fondamentalmente geometria che il motore sa che non si muoverà mai, quindi pre-calcola in anticipo -time i volumi shadow e altre cose con un comando inserito nella console chiamato "dmap"). Non ho capito perché fosse solo sulle ombre della geometria statica generata dal mondo e non su nessuno dei modelli ASE o LWO.
Ora, la cosa che ho notato è che in realtà esiste una pletora di parametri che possono essere utilizzati con il comando dmap - uno di questi parametri è chiamato "shadowOpt" - che deve rappresentare il livello di ottimizzazione dell'ombra. Questo parametro imposta un enum: sembrano esserci diversi livelli di ottimizzazione dell'ombra:
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;
Ho avuto successo con l'opzione 2 - "SO_CULL_OCCLUDED". Corregge tutti gli artefatti - richiede un po 'più di tempo per essere eseguito - ma credo che molto di questo tempo sia passato a stampare grandi quantità di informazioni sulla console - queste stampe potrebbero probabilmente essere ridotte o eliminate.
Uno dei luoghi che mi ha dato alcuni indizi è stato il commento qui in 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 ) {
Ora, il problema con questa ottimizzazione dell'ombra "extra" solo durante "dmap" è che se una di queste luci viene mai spostata (il che è sempre possibile a seconda del tipo di progetto che stai facendo) - tornerà automaticamente al processo di creazione del volume dell'ombra in tempo reale "non ottimizzato" (per la luce spostata) e gli artefatti riappariranno per quella luce. Quindi l'unico modo per garantire che questi artefatti non appaiano è quello di eseguire sempre il costoso processo di ottimizzazione per queste ombre statiche dipinte dal mondo. È infatti molto costoso, quindi questa sarebbe l'ultima risorsa assoluta se non riuscissi a trovare una soluzione grafica adeguata. (se lo fai, assicurati di pubblicare la tua soluzione qui.)
Consiglierei a chiunque crei mappe di grandi dimensioni per il motore Doom 3 vaniglia - e usando la geometria di worldspawn - di creare una cvar che possano cambiare in base alle loro esigenze per la creazione in tempo reale dei volumi di ombra ottimizzati. Ho chiamato il mio cvar r_useExpensiveShadowOptimizations - che sembra essere un ossimoro. Per esempio:
// 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() ) {
Raccomando anche che, a seconda della dimensione delle mappe (e supponendo che le luci non si muovano), aumenti il livello di ottimizzazione del volume dell'ombra statica con il parametro "shadowOpt" per dmap.
Quindi praticamente tutte le cose che ti servono per avere una grande mappa e non avere artefatti ombra sono lì per te, devi solo decidere quali ti serviranno. Farlo in tempo reale è estremamente costoso e dovrebbe essere fatto come ultima risorsa se non riesci a trovare una soluzione grafica adeguata. Farlo in DMAP ha perfettamente senso in quanto risolve il problema e richiede solo qualche secondo in più per la compilazione della mappa.