• Non ci sono risultati.

Deferred Rendering - modus operandi

6. Deferred Rendering

6.2 Deferred Rendering - modus operandi

Il paradigma deferred rendering risolve l’inconveniente del caso precedente disaccoppiando il rendering della geometia dal rendering delle luci, eseguendo quindi il calcolo delle luci in differita (da qui il nome del paradigma). Questo viene ottenuto isolando i parametri dell’equazione di shading, che vengono, nella prima fase detta GBuffer Pass, renderizzati individualmente in una serie di buffers, senza eseguire alcun calcolo. Nella seconda fase, detta

Light Pass, il GBuffer è usato come input per eseguire il calcolo vero e proprio della luminosità

Figura 6.2: pipeline deferred rendering, in cui si disaccoppia la geometria dallo shading

Il light buffer ha lo scopo di accumulare il contributo di ogni luce, e rappresenta la sommatoria della formula di phong shading. Alla fine, in un unico passaggio detto Material

Pass, il frame finale è composto modulando il colore della luce con il colore delle superfici.

Questo paradigma porta la complessità ad un livello lineare. Supponendo di avere M meshes e L luci, la complessità diventa O(M+L).

Il GBuffer (da Geometric Buffer) si chiama in questo modo proprio perchè non conteniene alcuna informazione sulla luce, ma solamente sulla geometria e sul materiale delle superfici. Il GBuffer è composto da una serie di buffer della stessa risoluzione del frame buffer, dove ogni elemento corrisponde ad un pixel del frame buffer. Essendo il GBuffer Pass eseguito con zbuffering attivo, esso conterrà le informazioni solo di ciò che è visibile nella scena finale. Dacchè il light pass prende come input il GBuffer, è evidente il vantaggio di dover calcolare l’equazione di shading (che si ricorda essere il processo più esoso in termini di prestazioni) solamente dei fragment visibili, senza sprecare alcuna risorsa nel calcolare la luminosità di oggetti o porzioni di essi non visibili nella scena finale.

É importante notare che una luce raramente interesserà l’intera area dei buffer. In altre parole, una qualsiasi luce nella scena in genere influisce solo alcuni degli oggetti visibili. Ad esempio la luce evidenziata nella figura 6.3 influenza un’area piuttosto limitata della scena visibile, ed è quindi inutile calcolare lo shading per tutti i pixel esterni all’area di influenza della luce (approssimata in figura), poichè riceverebbero un valore nullo.

Figura 6.3: generalmente una luce interessa solo una parte dei fragment della scena finale

Il problema è risolto in modo conservativo con la seguente procedura. Nel momento del caricamento della scena, per ogni luce viene calcolata una bounding mesh che racchiude il volume i cui punti interni sono sufficientemente vicini alla sorgente di luce da risentirne dell’effetto.

Le mesh sono:

- Sfere per luci point lights

- Coni per spot lights

Nel light pass, per ogni luce viene renderizzata la sua mesh. In questo modo la GPU calcolerà automaticamente (e molto velocemente) tutti i pixel potenzialmente interessati dalla luce (nel caso della figura 6.4 si tratta dei punti interni alla circonferenza tracciata). Infine, per ogni pixel, sfruttando la ricostruzione della posizione di un punto nota la sua profondità, viene risolta la formula di shading. Tuttavia, una ulteriore ottimizzazione è stata introdotta nel motore grafico.

Figura 6.4: alcuni punti inclusi nella proiezione della light mesh possono essere esterni all’influenza della luce

Com’è visibile dalla figura, la bounding sphere della luce ha una tale dimensione per cui la sua proiezione interesserà tutti i punti del viewport. Tuttavia gli oggetti A e C sono esterni alla bounding sphere. É possibile inserire un test conservativo ma molto veloce che si occupa di individuare i punti la cui proiezione è interna alla proiezione del bounding volume di una luce, che però sono troppo lontani (rispetto all’asse Z) o troppo vicini allo spettatore, per essere influenzati dalla luce. Una coppia di valori limite di profondità, chiamata range limits e rappresentata dalle due linee verticali nella figura, è ricalcolata ad ogni frame per ogni luce con una semplice formula:

Poi, nel pixel shader, è confrontata la profondità di ogni fragment. Se questa è esterna a tale intervallo, il fragment viene ignorato.

É un caso frequente quando ci si avvicina tanto ad una sorgente luminosa da rendere la mesh associata molto grande, fino ad occupare l’intero viewport. In questo caso tutti i punti della scena verranno considerati, ma fra essi quelli che rappresentano un eventuale sfondo o oggetti lontani, non verranno sicuramente raggiunti da questa sorgente di luce.

Si supponga di voler implementare un modello molto semplificato del phong shading, per ottenere il seguente modello di illuminazione:

É sufficiente considerare solamente:

- la distanza dalla sorgente di luce da ogni punto. É usata per calcolare il parametro C, ovvero l’intensità e il colore della luce ricevuta

- la componente di luce diffusa della superficie

- il colore della sorgente di luce. É usato per calcolare il parametro C

Per questo semplice modello è sufficiente un GBuffer composto da due soli buffer, contenenti (per ogni fragment):

- la posizione spaziale del punto, usata per determinare la distanza dalla sorgente di luce.

- il colore diffuso dei punti della superficie, usato per ricavare il parametro T nella formula, che modula la luce ricevuta. Usualmente questo buffer si chiama albedo

Figura 6.5: elementi corrispondenti dei buffers vengono combinati per calcolare la formula di shading

Il GBuffer è riempito nella prima fase, in cui la geometria è renderizzata ignorando le sorgenti di luce. Nella seconda fase, per ogni luce, viene calcolato Ci prendendo in considerazione la posizione e il colore della luce corrente e la posizione del fragment, ricavata dal GBuffer. In questa fase è calcolato:

Infine, per comporre la formula completa di viene eseguito il material pass che moltiplica gli elementi del light buffer con quelli dell’albedo buffer, ottenendo:

Documenti correlati