Rendering efficiente con molte sorgenti luminose


10

Per eseguire il rendering di una scena con una singola sorgente luminosa utilizzando l'ombreggiatura phong, è possibile calcolare il colore finale di ciascun frammento passato nello shader di frammento in base ai componenti ambiente / diffuso / speculare sia del materiale che della sorgente luminosa.

Questo può essere facilmente esteso per adattarsi a più sorgenti luminose sommando i risultati dell'applicazione di ogni singola sorgente luminosa sul frammento in quanto tale:

final_color = (0, 0, 0, 1)
for each light:
    final_color += apply_light(material, light)
final_color = clamp(final_color, (0,0,0,1), (1,1,1,1))

Tuttavia, con un numero molto elevato di sorgenti luminose, questo processo è piuttosto lento; con le Nluci, questo approccio richiede calcoli per l'ombreggiatura del phong da eseguire Nvolte per frammento.

Esiste un approccio migliore per il rendering di scene con un numero molto elevato di sorgenti luminose (centinaia, migliaia, ecc.)?

Risposte:


15

Sì, ma hai bisogno di un cambio di paradigma.

Quello a cui sei abituato si chiama rendering in avanti. Invia la tua geometria e quindi procedi immediatamente con il passaggio di ombreggiatura. Nel rendering in avanti di base è possibile eseguire il loop all'interno dello shader per ciascuna luce o eseguire un passaggio per luce e fondere il risultato insieme (con la fusione additiva).

Ma le cose si sono evolute parecchio. Entra: Rendering differito

Ora che ci sono così tante varianti che le descrivono tutte nei dettagli ci vorrà molto più che accettabile per una risposta qui. Quindi qui sto per descrivere l'essenza dell'ombreggiatura differita, ci sono molte altre risorse che puoi facilmente trovare usando Google, speriamo che dopo aver letto questo avrai le parole chiave giuste per trovare quello che ti serve.

L'idea di base è di rimandare l'ombreggiatura a dopo la pipeline. Hai due passaggi principali:

  1. Rendering della geometria e di tutte le informazioni necessarie per l'ombreggiatura in più target di rendering. Ciò significa che in genere in un'implementazione di base si avrebbe un buffer di profondità, un buffer contenente le normali della geometria e il colore dell'albedo. Presto scoprirai che hai bisogno di altre informazioni sui materiali (ad esempio rugosità, fattore "metallico" ecc.).

Questa immagine da Wikipedia mostra tre buffer (colore, profondità e normali)

inserisci qui la descrizione dell'immagine

Ancora una volta, la quantità, il tipo e il contenuto dei buffer utilizzati varia molto tra i diversi progetti. Troverai il set di buffer con il nome di GBuffer.

  1. Dopo questo è il momento di applicare l'illuminazione effettiva. Durante il passaggio di illuminazione per ogni luce che si desidera disegnare un volume di luce che dipende dal tipo di luce:
    • Per una luce direzionale si esegue il rendering di un quad a schermo intero.
    • Per una luce puntiforme si esegue il rendering di una sfera in cui il raggio si basa sull'attenuazione della luce puntiforme.
    • Per un faretto si rende un cono le cui dimensioni dipendono nuovamente dalle caratteristiche della luce.

Nel pixel shader di questo passaggio passi i tuoi GBuffer ed esegui l'illuminazione e l'ombreggiatura usando le informazioni in essi contenute. In questo modo si elaborano solo i pixel interessati da ciascuna delle luci che hanno un sensibile aumento di velocità rispetto al rendering in avanti classico.

Presenta inoltre vari svantaggi, in particolare la gestione di oggetti trasparenti e un consumo maggiore di larghezza di banda e memoria video. Ma è anche più complicato gestire vari modelli di materiali.

Hai altri vantaggi collaterali (come avere molte informazioni pronte per la post-elaborazione) ed è anche abbastanza facile da implementare. Ma questa non è più la cosa più bella in circolazione per molte luci.

Le tecniche più recenti sono ad esempio quelle di rendering piastrellate . L'idea principale di questi è quella di suddividere la scena nello "schermo" dello spazio dello schermo e assegnare ad ogni riquadro le luci che la riguardano. Questo esiste sia in modo differito che in avanti. Queste tecniche portano ad alcuni problemi quando si hanno discontinuità di profondità diverse in una tessera, ma è generalmente più veloce del classico differito e risolve vari problemi di essa. Ad esempio, tra i vantaggi, con la piastrellatura differita leggi i GBuffer una volta per frammento acceso e i pixel nella stessa tessera elaborano coerentemente le stesse luci.

Ulteriore evoluzione da questo lato è l' ombreggiatura a grappolo che è concettualmente simile agli approcci basati su piastrelle, avendo al posto dei riquadri dello spazio schermo, i cluster con estensione 3D. Questo metodo gestisce meglio il problema delle discontinuità di profondità e generalmente si comporta meglio dei metodi piastrellati.

NOTA IMPORTANTE: ho descritto le basi dell'ombreggiatura differita. Ci sono più varianti, ottimizzazioni e miglioramenti in giro, quindi ti esorto a sperimentare una versione semplice e quindi fare alcune ricerche su altre tecniche come quella che ho menzionato sopra.


1
Ecco due risorse del codice sorgente per Tiled e Clustered
RichieSams,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.