Il rendering / l'ombreggiatura differiti è possibile con OpenGL ES 2.0?


20

L'ho chiesto su StackOverflow , ma potrebbe avere più senso qui:

Qualcuno ha implementato il rendering / shading differito in OpenGL ES 2.0? Non supporta MRT, quindi con un solo buffer di colore, non è qualcosa che può essere implementato nel modo "normale".

In particolare, sto esplorando su iPad, iPhone4 (maaaybe iPhone 3gs) e Android. Sull'app GLESView su iPad / iPhone4 / iPhone3gs è presente l'estensione GL_OES_RGB8_RGBA8 e non ho ancora guardato troppo in profondità, ma con 8 bit / canale questa idea è interessante: http://www.gamedev.net/topic/ 562.138-OpenGL-ES-20-e-rinviato-ombreggiatura /

Altre idee? Vale la pena farlo, per quanto riguarda le prestazioni?


Si è possibile.
Quazi Irfan,

7
Con quale tecnica (e)?
Jim Buck,

Risposte:


15

Sì, è possibile. Tuttavia, non è particolarmente utile.

In primo luogo, a meno che non si ha accesso al prolungamento NV_draw_buffers (come dice il nome, si tratta di NVIDIA-solo. Quindi, a meno che si sta eseguendo su Tegra, non averla), oggetti framebuffer sotto ES 2.0 può rendere solo un'immagine Al tempo. Quindi, per generare i tuoi buffer G, dovrai renderizzare la scena più volte, eliminando così uno dei vantaggi del rendering differito.

In secondo luogo, la larghezza di banda su piattaforme mobili non è la stessa che si otterrebbe anche con GPU di livello medio. E la larghezza di banda è fondamentale per rendere utile il rendering differito (per molte luci). Senza quella larghezza di banda, i passaggi di luce danneggeranno davvero, dal punto di vista delle prestazioni.

Terzo, l'hardware PowerVR non è davvero progettato per questo tipo di cose. Ottimizza il rendering con il suo hardware di rendering basato su piastrelle. Un rendering così differito in aggiunta sarebbe meno utile che in una tradizionale architettura di conversione di scansione.


6

Il problema principale è Fillrate. Sulle GPU mobili, il tasso di riempimento è basso e non è possibile eseguire l'ombreggiatura differita in tempo reale alla risoluzione nativa.

Su iPhone 4 e iPad 1, fillrate è semplicemente ridicolo. L'unico dispositivo IOS con buon fillrate è iPad 2, ma dubito che ci sia abbastanza ... Su Android, solo i dispositivi Tegra hanno i GL_NV_draw_buffers per usare MRT ma anche il fillrate è molto basso. Il Mali 400 sembra avere il miglior tasso di riempimento. Se vuoi piangere, prova a riempire un rettangolo di colore a risoluzione a schermo intero 4 volte ... Molti dispositivi non possono farlo a 60 fps.

Sulle GPU desktop, hai 10 volte (o più) fillrate come gpus mobile. Non dimenticare che le GPU mobili utilizzano la stessa memoria della CPU e non hai memoria dedicata.

Ci sono alcuni esempi in WebGL (stessa API) in modo che non sia una limitazione dell'API.


1
+1 per riempire la debolezza. Non riuscivo nemmeno a far funzionare la sfocatura gaussiana con una risoluzione di 1536x2048 a 60 fps (aumentava immediatamente la frequenza dei fotogrammi fino a 30 fps, anche con solo 4 campioni)
bobobobo

1
Penso che questo dipenda molto dalle sottigliezze della tua implementazione e dalla comprensione di ciò che influisce maggiormente sull'hardware mobile. Ad esempio, questi ragazzi hanno fatto una sfocatura DoF moderatamente performante nel 2012.
ingegnere il

1

Devi davvero considerare qual è il minimo assoluto di cui hai bisogno per un renderer differito. Se torni all'illuminazione differita, riduce la quantità di dati che devono essere memorizzati nel GBuffer, ed è davvero molto più economico che rendere metà della scena 3 volte o più per supportare una bassa quantità di luci.

Vorrei scegliere il seguente formato GBuffer:

  • Riutilizzare il buffer di profondità per il passaggio di illuminazione, non sono sicuro di quanto ampiamente sia supportato sui dispositivi mobili, ma è una trama di profondità libera.
  • Una singola trama GBuffer, al suo interno vorrei memorizzare: Normal U, Normal V, Param 0, Param 1. La codifica Lambert-Azimuthal sembra davvero piacevole per le normali e le comprime in soli due componenti, relativamente economiche per codificare e decodificare.
  • Due parametri per le variabili di illuminazione sono molti, potrebbe usarne uno come enumerazione per più funzioni di illuminazione se l'hardware funziona bene con la ramificazione dinamica.

L'illuminazione differita è simile al rendering differito, tranne per il rendering della scena due volte:

  1. Rendering profondità geometria, normali e parametri di illuminazione nel GBuffer.
  2. Rendering Si illumina nel buffer di accumulo.
  3. Rendi la geometria con shader di materiale, componi anche la tua illuminazione qui. Se sei bravo a elaborare operatori inversi di equazioni di illuminazione, puoi fare MOLTE cose davvero interessanti con questo passaggio.
  4. Fai qualsiasi post-elaborazione che ti puoi permettere, assicurati di abusare della profondità e delle normali trame a morte qui per motivi di efficienza.

Informazioni sulla memorizzazione dei risultati di illuminazione. Mi sono appassionato alla memorizzazione di colori diffusi e luminanza speculare in modo che il buffer di accumulo debba essere solo una trama di colore standard a 32 bit. È possibile stimare il colore speculare calcolando il croma del colore diffuso e combinandolo con la luminanza speculare.

La parte più importante, tuttavia, sta usando il buffer dello stencil di profondità al massimo, assicurati di non rendere nessuno dei codici di illuminazione dove non è necessario. Andrei persino al punto di aggiungere alcune dichiarazioni di scarto negli shader di frammenti a condizioni che lasceranno cadere la visibilità della luce al di sotto del campo visualizzabile del dispositivo (1e-3 è di solito un cutoff sicuro).


discardè davvero un problema per le pipeline basate su tile utilizzate da molte / la maggior parte delle GPU mobili.
Ingegnere,

1

Prendi in considerazione l'illuminazione differita. In breve, l'illuminazione differita è una tecnica che utilizza una versione ridotta dell'ombreggiatura differita per calcolare una mappa luminosa dello spazio. In un secondo passaggio, la geometria viene nuovamente renderizzata utilizzando la mappa luminosa dello spazio come informazioni di illuminazione.

Questa tecnica viene utilizzata per ridurre le dimensioni del G-Buffer, poiché sono necessari meno attributi. Ti offre anche il vantaggio che G-Buffer e la mappa luminosa dello spazio dello schermo possono avere una risoluzione inferiore rispetto allo schermo.

Avevo implementato un rigoroso renderer basato su GLES 2.0 (sebbene sperimentale) e sono riuscito a far bollire il G-Buffer fino a una trama RGBA (sì, ho usato un texture2D invece di un renderbuffer). Conteneva la normale mappa dello spazio dello schermo + il buffer di profondità nel canale alfa (che è stato compresso usando un logaritmo, per quanto mi ricordo).

Gli attributi di posizione ( qui chiamati mondo ) possono essere calcolati durante il passaggio di illuminazione usando il fatto che in una proiezione prospettica, .xy è diviso per .z , in modo che:

xyfrustum=xyworld/zworld

Ho approssimato l'attributo position xy facendo:

xyworld=xyfrustumzworld

Nota: ho dovuto effettuare ulteriori regolazioni a seconda delle impostazioni della matrice di proiezione.

Vale anche la pena notare che sono stato in grado di omettere il componente .z dei vettori normali, poiché ho potuto ricostruire .z da .xy poiché il vettore normale è normalizzato in modo che:

x2+y2+z2=1x2+y2+z2=1z2=1(x2+y2)z=1(x2+y2)

Usando questa tecnica, sono stato in grado di liberare un altro canale nel mio G-Buffer RGBA e l'ho usato per memorizzare la mappa speculare dello spazio dello schermo (o lucentezza, se vuoi).


A proposito: il mio renderer non era collegato a nessun motore di gioco. È stata semplicemente una ciao demo mondiale, che ha reso Suzanne.
Simon Schmidt,

0

Sì, è assolutamente possibile. La velocità di riempimento non è un problema perché i chip grafici mobili sono progettati per gestire schermi ad altissima risoluzione. In effetti, il rendering differito aiuta in questo perché il calcolo dell'illuminazione è indipendente dalla complessità della scena, quindi il sovraccarico non provoca un rallentamento. Ecco la mia implementazione su un iPad di quarta generazione: http://www.youtube.com/watch?v=K4X1oF6b4V8

Se vuoi prestazioni quattro volte superiori, solo metà della risoluzione della trama su cui esegui il rendering. In ogni caso, non riesco davvero a vedere nulla di diverso con la grafica 3D su uno schermo a retina.

I chip grafici mobili sono estremamente efficaci nel rendering differito a causa del modo in cui gestiscono il rendering da texture. A differenza delle schede grafiche per PC, che in genere comportano un enorme impatto sulle prestazioni quando si avvia il rendering su una trama anziché su un contesto di finestra, la grafica mobile è progettata per fare ciò senza alcun impatto sulle prestazioni. In questo modo ottieni la scalabilità di un renderer differito, senza la penalità iniziale sulle prestazioni che riscontri su una scheda grafica desktop.

Al momento della mia implementazione, OpenGLES mancava il rendering su più target, quindi ho dovuto disegnare il colore dello schermo e il normale in passaggi separati. Ciò può essere risolto nelle versioni più recenti di OpenGLES, ma non so se le soluzioni sono ancora disponibili nell'hardware mobile di consumo.


3
"I chip di grafica mobile sono estremamente efficaci nel rendering differito a causa del modo in cui gestiscono il rendering da texture. A differenza delle schede grafiche per PC, che in genere comportano un enorme impatto sulle prestazioni quando si avvia il rendering su una trama anziché su un contesto di finestra, la grafica mobile è progettato per farlo senza alcun impatto sulle prestazioni ". È un'enorme affermazione lì dentro. Hai riferimenti affidabili a sostegno di questa affermazione?
Panda Pajama,
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.