Hvis du er utvikler av 3D-spill, har du sannsynligvis kommet over vilkårene fremover gjengivelse og utsatt gjengivelse i din undersøkelse av moderne grafikkmotorer. Og ofte må du velge en som skal brukes i spillet ditt. Men hva er de, hvordan varierer de, og hvilken skal du velge?
Utsatt gjengivelse for mange lys (bilde med Hannes Nevalainen)For å begynne, må vi forstå litt om moderne eller programmerbare grafikkledninger.
Tilbake på dagen var vi begrenset til hva grafikkrørledningen til skjermkortet hadde. Vi kunne ikke endre hvordan det tegnet hver piksel, bortsett fra å sende inn en annen tekstur, og vi kunne ikke krype vinkler når de var på kortet. Men tider har endret seg, og vi har nå programmerbare grafikk pipelines. Vi kan nå sende kode til skjermkortet for å endre hvordan pikslene ser ut, gi dem et humpete utseende med normale kart, og legge til refleksjon (og mye realisme).
Denne koden er i form av geometri, toppunktet, og fragment shaders, og de forandrer i hovedsak hvordan skjermkortet gjør objektene dine.
Fremadrettede gjengivelser er standard, utenom bokseringsteknikken som de fleste motorer bruker. Du leverer grafikkortet geometrien, prosjekterer det og bryter det ned i vertikaler, og deretter blir de forvandlet og splittet i fragmenter eller piksler som får den endelige gjengivelsen før de sendes på skjermen.
Det er ganske lineært, og hver geometri går ned i røret en om gangen for å produsere det endelige bildet.
Ved utsatt gjengivelse, som navnet antyder, utsettes gjengivelsen litt før alle geometriene har gått ned i røret; Det endelige bildet blir deretter produsert ved å bruke skygge på slutten.
Nå, hvorfor skulle vi gjøre det?
Belysning er hovedgrunnen til å gå en vei mot den andre. I en standard fremføringsrørledning må belysningsberegningene utføres på hvert vertex og på hvert fragment i den synlige scenen, for hvert lys i scenen.
Hvis du har en scene med 100 geometrier, og hver geometri har 1000 hjørner, så kan du ha rundt 100 000 polygoner (et veldig grovt estimat). Skjermkort kan håndtere dette ganske enkelt. Men når de polygonene blir sendt til fragmentskader, det er der de dyre belysningsberegningene skje, og den virkelige nedgangen kan oppstå.
Utviklere prøver å skyve så mange belysningsberegninger inn i Vertex shader som mulig for å redusere mengden arbeid som fragment shader skal gjøre.De dyre belysningsberegningene må utføres for hvert synlig fragment av hvert polygon på skjermen, uansett om det overlapper eller skjules av en annen polygons fragmenter. Hvis skjermen din har en oppløsning på 1024x768 (som for øvrig ikke er veldig høy res), har du nesten 800.000 piksler som må gjengis. Du kan enkelt nå en million fragment operasjoner hver ramme. Også mange av fragmentene vil aldri gjøre det til skjermen fordi de ble fjernet med dybdeprøving, og dermed var belysningsberegningen sløset på dem.
Hvis du har en million av disse fragmentene, og plutselig må du gjøre den scenen igjen for hvert lys, du har hoppet til [num lys] x 1.000.000
fragmentoperasjoner per ramme! Tenk deg om du hadde en by full av gatelys hvor hver enkelt er en punkt-lyskilde ...
Formelen for estimering av denne fremadrettede kompleksiteten kan skrives, i stor O notasjon, som O (num_geometry_fragments * num_lights)
. Du kan se her at kompleksiteten er direkte relatert til antall geometrier og antall lys.
Nå optimaliserer noen motorer dette ved å kutte ut lys som er langt borte, kombinere lys eller bruke lette kart (veldig populært, men statisk). Men hvis du vil ha dynamisk lys og mange av dem, trenger vi en bedre løsning.
Utsatt gjengivelse er en veldig interessant tilnærming som reduserer objekttellingen, og spesielt det totale fragmenttallet, og utfører belysningsberegningene på pikslene på skjermen, og bruker dermed oppløsningsstørrelsen i stedet for totalt antall fragmenttall.
Kompleksiteten til utsatt gjengivelse, i stor O notasjon, er: O (screen_resolution * num_lights)
.
Du kan se at det ikke har noen betydning hvor mange objekter du har på skjermen, som bestemmer hvor mange lys du bruker, slik at du lykkelig kan øke lysstyrken. (Dette betyr ikke at du kan ha ubegrensede objekter, de må fortsatt trekkes til bufferne for å produsere det endelige resultatene.)
La oss se hvordan det fungerer.
Hver geometri blir gjengitt, men uten lysskygging, til flere skjermrombuffere som bruker flere gjengemål. Spesielt er dybden, normaler og fargen alle skrevet til separate buffere (bilder). Disse bufferne blir deretter kombinert for å gi nok informasjon for hvert lys for å lyse pikslene.
Ved å vite hvor langt unna en piksel er, og dens normale vektor, kan vi kombinere fargen på den piksel med lyset for å produsere vår endelige gjengivelse.
Det korte svaret er at hvis du bruker mange dynamiske lys, bør du bruke utsatt gjengivelse. Det er imidlertid noen betydelige ulemper:
Hvis du ikke har mange lys eller vil være i stand til å kjøre på eldre maskinvare, bør du holde fast med fremdriftsgjenoppretting og erstatte mange lys med statisk lyskort. Resultatene kan fortsatt se fantastisk ut.
Jeg håper det har kastet litt lys på emnet. Alternativene dine er der for å løse dine gjengivelsesproblemer, men det er veldig viktig å velge riktig ved starten av spillutviklingen for å unngå vanskelige endringer senere.