Jeg er i ferd med å finne ut hvordan jeg skal pakke all informasjon jeg trenger for en fysisk basert utsatt renderer i en G-buffer uten å bruke en uanstendig mengden gjengivelsesmål.
Det jeg har så langt er 4 tredelte vektorer:
- Albedo / Diffuse
- Normal
- Tangent
- Position
Og 4 enkeltkomponenter
- Metallic
- Roughness
- Høyde
- Omgivende okklusjon
En naiv tilnærming er å pakke en av enkeltkomponentene i alfa (fjerde) kanal med en av de tre delte vektorene, som er min nåværende undersøkelseslinje. Men med tanke på at fire 4-kanals gjengivelsesmål for flytende punkt med full presisjon ikke er lite, forstår jeg at det er vanlig å bruke halv presisjon og enda mindre representasjoner for å være mer minnebevisst.
Det jeg spør om er: hvilke komponenter kan jeg trygt redusere presisjonen uten å miste kvaliteten, og med hvor mye?
Svar
Først og fremst trenger du ikke posisjon i G-bufferen i det hele tatt. Pikselens posisjon kan rekonstrueres fra dybdebufferen , med kunnskap om kameraoppsettet og pikselens skjermplass xy-posisjon. Så du kan bli kvitt hele bufferen.
Du trenger heller ikke tangentvektorer i G-bufferen. De er bare nødvendige for å konvertere normale kart fra tangentområdet, og for parallaks kartlegging; disse vil bli gjort under G-buffer fyllpasset (når du har tangenter fra nettet du gjengir), og G-bufferen ville bare lagre normaler i verden eller se rom.
Materielle egenskaper som farger, ruhet og metall er vanligvis bare 8-biters verdier i G-bufferen, siden de kommer fra 8-biters teksturer. Samme for AO.
Det er heller ikke behov for høyde i G-bufferen, med mindre du skal gjøre en slags multi-pass-blanding som avhenger av det, men hvis du trenger det, er sannsynligvis 8 bits nok til det også.
Normaler kan ha nytte av å bli lagret som 16-biters verdier i stedet for 8-bit. Half-float er greit, men 16-biters fixed-point er enda bedre, da det gir deg mer jevn presisjon på tvers av alle retninger (halv-float er mer presis nær aksene og mister litt presisjon vekk fra dem). Videre kan du kutte dem fra 3 komponenter ned til 2 ved hjelp av oktaedrisk kartlegging .
Så på slutten av dagen, et minimum G-buffer kan se ut som:
- Materiellfarge + metallisk: RGBA8
- Oktahedrisk verdensrom normal + ruhet + AO: RGBA16
og det er alt! Bare 12 byte per piksel.
Alternativt kan du bruke en RG16-buffer til det normale, og flytte ruhet + AO til en separat 8-bits buffer. Det vil gi deg noe rom for å vokse hvis du til slutt trenger flere G-bufferkomponenter i enten 8-biters eller 16-bitersstørrelser.
Kommentarer
- Også metallitet er ofte en binær verdi, og forutsatt at du ikke vil bruke ruhetsgradienter (for å se effekten av redusert presisjon), kan du lagre metallhet og ruhet i en enkelt 8-bits kanal (1 bit for metallitet og 7 for ruhet).