Quali sono le comuni tecniche di ottimizzazione del rendering per il passaggio della geometria in un renderizzatore di ombreggiatura differito? [chiuso]


16

Ho sviluppato un motore di gioco usando OpenGL 3 e C ++ (e glfw per la gestione delle finestre). Finora ho avanzato, fatto quasi tutto, tranne entità sonore e ottimizzazioni. Il motore utilizza l'ombreggiatura differita, quindi poiché l'ombreggiatura differita è di per sé un processo stancante per una GPU media, voglio ottimizzare il processo di rendering il più possibile.

Il sistema attuale è costituito da una scena, contenente un Renderer e il mondo attuale e il mondo detiene entità ed entità di illuminazione separate std::vectors.

Quindi praticamente ogni volta che viene chiamata la scena ->render() e chiama il Renderer, passa il mondo come parametro e ottiene le entità iteratrici dal mondo, le attira all'FBO e poi passa attraverso le entità di illuminazione per il secondo passaggio. E penso che questo non sia abbastanza.

Il mio attuale algoritmo scorre attraverso tutto anche se l'entità non si trova nello spazio dello schermo. Sto pensando a un modo per ottimizzare l'attuale algoritmo di rendering in modo che chiami le funzioni API solo per gli oggetti visibili, quindi quali sono le tecniche comuni per ottimizzare tale renderer?

Risposte:


41

L'ombreggiatura differita è solo una tecnica per "rinviare" l'operazione di ombreggiatura effettiva per le fasi successive, questo può essere ottimo per ridurre il numero di passaggi necessari (ad esempio) per il rendering di 10 luci che richiedono 10 passaggi. Il mio punto è indipendentemente dalla tecnica di rendering che stai usando, ci sono alcune possibili ottimizzazioni di rendering che riducono il numero di oggetti (vertici, normali, ecc.) Che la tua pipeline di rendering deve elaborare.

Non esistono standard di fatto per l'ottimizzazione del rendering, ma piuttosto una serie di tecniche che possono essere utilizzate in modo intercambiabile o insieme per raggiungere determinate caratteristiche prestazionali. L'uso di ciascuna tecnica dipende fortemente dalla natura della scena che viene renderizzata.

Il rendering differito tenta di risolvere il problema quando aumenta il numero di spie, che nel rendering in avanti potrebbe far esplodere il numero di passaggi.

Tali tecniche non ottimizzano direttamente la parte di ombreggiatura differita, ma in base alla descrizione, la parte di ombreggiatura differita NON è un problema. Il tuo problema però è che stai sottoponendo l'intera scena alla pipeline di rendering. Quindi il tuo motore deve elaborare (ad esempio tutti i 100 milioni di vertici) nella tua scena solo per essere in grado di inviare il risultato al g-buffer, mentre la maggior parte di questi 100 milioni di vertici possono essere banalmente eliminati e non sottoposti al vertice pre-processato e frammenti passati.

Nel caso di un renderizzatore in avanti il ​​vertice N sarà elaborato dallo stadio del vertice come totale vertex count*lights counte dallo stadio del frammento come totale fragments count*number Lights, l'ombreggiatura differita riduce efficacemente questo solo vertex countper lo stadio del vertice e fragments countper il conteggio dei frammenti, prima di risolvere il ombreggiatura effettiva. Ma ancora N può essere troppo da elaborare, specialmente quando la maggior parte di essi può essere banalmente abbattuta.

Ciò rende l'abbattimento più efficace in caso di rendering in avanti / passaggi multipli. Ma tieni presente che la maggior parte dei motori utilizzerà un approccio a doppio rendering, poiché l'ombreggiatura differita da sola non può risolvere gli oggetti trasparenti, questo rende l'utilizzo di queste ottimizzazioni un must, non conosco alcun motore commerciale che non le faccia tutte.

Frustum Culling

Solo gli oggetti che sono completamente o parzialmente inclusi nel frustum della vista, devono mai essere inviati alla pipeline di rendering. Questo è il concetto di base dell'abbattimento del frustum, purtroppo controllare se una mesh è dentro / fuori dalla vista del frustum può essere un'operazione costosa, quindi, invece, i progettisti del motore usano un volume di delimitazione approssimativo come una scatola di delimitazione o sfera di delimitazione dell'asse (AABB) , anche se questo potrebbe non essere accurato come l'utilizzo della mesh effettiva, la differenza di precisione non vale la pena controllare con la mesh effettiva.

inserisci qui la descrizione dell'immagine

Anche con i volumi di delimitazione, non è necessario verificarli tutti, in alternativa è possibile costruire una gerarchia di volumi di delimitazione per eseguire una precedente eliminazione, l'utilizzo di questo dipende fortemente dalla complessità della scena.

Questa è una tecnica buona e semplice per un motore più piccolo, ed è quasi usata in ogni motore che abbia mai usato. Ti consiglio di utilizzare un "normale" volume di volume / controllo del frustum senza gerarchie se il tuo motore non richiede il rendering di scene molto complesse.

Gerarchia dei volumi limitanti

Abbattimento della faccia posteriore

Questo è un must, perché disegnare facce che non saranno comunque visibili? le API di rendering forniscono un'interfaccia per attivare / disattivare l'abbattimento della faccia posteriore. A meno che tu non abbia una forte ragione per non accenderlo, come alcune applicazioni CAD che devono tracciare backfaces in determinate circostanze, questa è una cosa da fare.

Abbattimento dell'occlusione

Utilizzando il buffer Z è possibile risolvere la determinazione della visibilità. Ma il problema è che il buffer Z non è sempre eccezionale in termini di prestazioni, poiché il buffer Z può essere risolto solo nelle fasi successive della pipeline, gli oggetti che vengono occlusi dovrebbero essere rasterizzati e potrebbero essere scritti nel buffer Z e il Buffer di colore prima di fallire il test Z.

L'abbattimento dell'occlusione risolve questo, facendo alcuni primi test per abbattere gli oggetti occlusi che si trovano nel trustum di rendering. Un'implementazione pratica dell'abbattimento dell'occlusione consiste nell'utilizzare query basate sul punto e nel verificare se determinati oggetti sono visibili da una vista punto specifica. Questo può anche essere usato per abbattere le luci che non contribuiscono all'immagine finale, questo è particolarmente utile in un renderer del motore differito.

inserisci qui la descrizione dell'immagine

Un grande esempio del mondo reale di tale tecnica è in GTA5, dove i grattacieli sono posizionati al centro della città, non sono solo decorazioni, ma funzionano anche come occludenti, occludendo efficacemente la parte restante della città e impedendole di essere rasterizzato.

LOD

Livello di dettaglio

Il livello di dettaglio è una tecnica ampiamente utilizzata, l'idea è quella di utilizzare una versione più semplice della mesh quando la mesh contribuisce meno alla scena. ci sono due implementazioni comuni; si cambia semplicemente la mesh con una più semplice quando non contribuisce più in modo significativo, la mesh viene selezionata in base a un fattore come la distanza e il numero di pixel (area sul ghiaione) che la mesh sta occupando. L'altra versione tessera dinamicamente la mesh, ampiamente utilizzata nel rendering del terreno.

inserisci qui la descrizione dell'immagine

E se tutti questi non funzionassero?

Bene, questa è una buona domanda.

La prima cosa che devi fare è profilare la tua applicazione utilizzando un profiler grafico e determinare dove si trova il collo di bottiglia. Tieni presente che il collo di bottiglia può cambiare quando il contenuto visualizzato viene modificato. Anche i colli di bottiglia potrebbero far parte del codice in esecuzione sulla CPU, quindi è necessario misurarlo anche tu.

Dopodiché devi fare alcune ottimizzazioni sul collo di bottiglia, tieni presente che non esiste una risposta giusta per questo e sarà diverso dall'hardware all'altro.

Alcuni trucchi comuni per l'ottimizzazione della GPU:

  • Evita la ramificazione negli shader.
  • Prova diverse strutture di vertici, ad esempio {VNT}interlacciate nello stesso array o {V},{N},{T}in array diversi.
  • Disegna la scena da davanti a dietro.
  • Disattiva il buffer Z in alcuni punti, ad esempio se un'immagine non ha bisogno del test Z.
  • Usa trame compresse.

Alcuni trucchi per l'ottimizzazione della CPU comuni:

  • Utilizzare le funzioni incorporate per le piccole funzioni.
  • Utilizzare SIMD (istruzione singola dati multipli) quando possibile.
  • Evita i salti di memoria ostili della cache.
  • Utilizzare i VBO con la "giusta" quantità di dati. (a seconda dell'hardware), ma in genere meno chiamate di disegno sono migliori.

E se il mio collo di bottiglia fosse nell'ombra differita?

In questo caso, poiché l'ombreggiatura differita è più preoccupata per le luci, la parte più ovvia è ottimizzare i calcoli effettivi dell'ombreggiatura. alcuni dei punti da tenere d'occhio:

  • Renderizza le luci che influenzano effettivamente l'immagine finale. In altre parole, abbatti le luci che non contribuiscono. Questo può essere efficacemente implementato usando l'abbattimento dell'occlusione di cui ho parlato prima.
  • Questa luce ha bisogno del componente speculare o di altri componenti? Forse no.
  • Questa luce getta ombra? Alcune luci non devono proiettare ombre.
  • Questo contributo leggero può essere pre-calcolato? Se non si muove, probabilmente alcuni aspetti possono essere pre-calcolati.

Siamo spiacenti, questi non hanno nulla a che fare con l'ombreggiatura differita, in realtà sono gli esatti problemi di prestazioni che la tecnica mitiga efficacemente e quindi le ottimizzazioni meno utili da fare, l'attenzione dovrebbe essere sui passaggi di illuminazione perché se il costo dell'illuminazione non è l'ombreggiatura differita dominante che richiede tempo è probabilmente la scelta sbagliata.
MickLH,

@MickLH Sfortunatamente, a quanto pare non hai letto la domanda, il suo problema era principalmente che scorre ogni volta l'intera scena e non ha menzionato alcun collo di bottiglia per quanto riguarda l'ombreggiatura sfumata. All'inizio ho detto che l'ombreggiatura sfumata risolve il problema dell'esplosione dei passaggi quando si hanno molte luci / materiali. Ma ho poi aggiunto che quelle sono ottimizzazioni indispensabili per qualsiasi motore, indipendentemente dalla tecnica di shading in avanti o in deffered. Considerando che questi sono i problemi esatti che la tecnica migita non sono assolutamente d'accordo, non posso affrontare tutti i punti qui (segue)
concept3d

è davvero stupido costruire un motore differito senza eliminare la frustum, ad esempio, quindi il motore elaborerà ad esempio (100 milioni di vertici) solo per essere in grado di inviare il risultato al g-buffer. L'ombreggiatura diversa risolve un problema diverso, che non era il suo problema, il suo problema era l'invio di tutta la geometria alla tubazione.
concept3d

anche se concordo sulla parte che dovrebbe verificarsi una certa ottimizzazione nei calcoli dell'illuminazione e se i calcoli della luce non erano dominanti, il rinvio è la strada sbagliata. ma ancora non era un suo problema.
concept3d

Ritirerò il mio downvote se chiarirai che queste ottimizzazioni sono in realtà le meno efficaci per un renderer differito, dal momento che non hai dimostrato a lui / lei + googler che il problema delle prestazioni non ha nulla a che fare con l'ombreggiatura differita.
MickLH,

6

Il tuo problema non è correlato all'ombreggiatura differita , devi implementare gli elementi base di base di un renderer prima di provare ad accelerare una parte specifica.

Quando hai finito con ciò che concept3d ha spiegato, se trovi effettivamente che devi ottimizzare shader differito stesso (al contrario dell'intero passaggio di rasterizzazione) puoi implementare l'ombreggiatura differita basata su piastrelle.

Se non si è limitato dal numero di luci dinamiche si dovrebbe prendere in considerazione perché si utilizza ombreggiatura differita a tutti, ma se siete poi si vuole provare l'ottimizzazione che ha reso possibile Battlefield 3. (Lo suggeriscono nella diapositiva 10 del loro PDF pubblico: http://dice.se/wp-content/uploads/GDC11_DX11inBF3_Public.pdf )

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.