Sto cercando di capire come impacchettare tutte le informazioni di cui ho bisogno per un renderer differito basato fisicamente in un G-Buffer senza usare un osceno quantità di target di rendering.
Quello che ho finora è 4 vettori in 3 parti:
- Albedo / Diffuse
- Normale
- Tangente
- Posizione
E 4 singoli componenti
- Metallico
- Rugosità
- Altezza
- Occlusione ambientale
Un approccio ingenuo consiste nel raggruppare uno dei singoli componenti nel canale alfa (quarto) con uno dei vettori in 3 parti, che è la mia attuale linea di indagine. Tuttavia, dato che quattro target di rendering in virgola mobile a piena precisione a 4 canali non sono piccoli, capisco che sia comune usare la metà della precisione e rappresentazioni ancora più piccole per essere più attenti alla memoria.
Quello che sto chiedendo è: su quali componenti posso ridurre la precisione senza perdere qualità e di quanto?
Risposta
Prima di tutto, non hai affatto bisogno di una posizione nel G-buffer. La posizione di un pixel può essere ricostruita dal depth buffer , conoscendo la configurazione della fotocamera e la posizione xy dello spazio sullo schermo del pixel. Così puoi sbarazzartene lintero buffer.
Inoltre, normalmente non hai bisogno di vettori tangenti nel G-buffer. Sono necessari solo per convertire le mappe normali dallo spazio tangente e per la mappatura della parallasse; questi sarebbero fatti durante il passaggio di riempimento del G-buffer (quando hai tangenti dalla mesh che stai “ri rendering), e il G-buffer lo farebbe solo memorizzare le normali nel mondo o visualizzare lo spazio.
Le proprietà dei materiali come colori, rugosità e metallo sono generalmente solo valori a 8 bit nel G-buffer, poiché “provengono da trame a 8 bit. Lo stesso per AO.
Anche laltezza non è necessaria nel G-buffer a meno che tu non stia facendo una sorta di miscelazione multi-pass che dipende da essa, ma se ne hai bisogno, 8 bit probabilmente sono abbastanza anche per questo.
Le normali possono trarre vantaggio dallessere memorizzate come valori a 16 bit invece che a 8 bit. Il mezzo float va bene, ma il punto fisso a 16 bit è ancora meglio, in quanto ti dà una precisione più uniforme su tutti gli orientamenti (il mezzo float è più preciso vicino agli assi e perde un po di precisione lontano da essi). Inoltre, puoi tagliarli da 3 componenti a 2 utilizzando la mappatura ottaedrica .
Quindi, alla fine della giornata, un minimo G-buffer potrebbe avere il seguente aspetto:
- Colore materiale + metallico: RGBA8
- Normale spazio-mondo ottaedrico + rugosità + AO: RGBA16
e questo è tutto! Solo 12 byte per pixel.
In alternativa, potresti usare un buffer RG16 per le normali e spostare rugosità + AO in un buffer a 8 bit separato. Questo ti darebbe un po di spazio per crescere se alla fine dovessi avere bisogno di più componenti G-buffer di dimensioni a 8 o 16 bit.
Commenti
- Inoltre, metalness è spesso un valore binario e, supponendo che non si utilizzino gradienti di rugosità (in modo da vedere limpatto di una precisione ridotta), è possibile memorizzare la metallicità e la rugosità in un singolo canale a 8 bit (1 bit per la metallicità e 7 per la rugosità).