Robert Sajko
Neovisno o odabranom modelu osvjetljenja, potrebno je osmisliti i implementirati odgovarajući postupak evaluacije traženog modela. Danas su u široj primjeni dva glavna pristupa: unaprijedno iscrtavanje (eng. forward rendering), te iscrtavanje s odgodom (eng. deferred rendering). Unaprijedno iscrtavanje je starija metoda, koja je tradicionalno bila izvedena sklopovljem na grafičkim karticama. Osnovni tok operacija pri iscrtavanju neke scene ovim postupkom dan je sljedećom slikom (scena je, dakako, definirana kao skup poligona):
U prvoj fazi, nad ulaznim podacima (vrhovima poligona) obavlja se transformacija, jednostavnim matričnim množenjem. Možemo razlikovati dvije glavne matrice: matricu modela (eng. world matrix, odnosno, model matrix), te matricu pogleda (eng. view matrix). Matrica modela omogućuje transformaciju vrhova objekta iz svog lokalnog koordinatnog sustava (prostor modela), u globalni koordinatni sustav scene (prostor scene, tj. "svijeta"). Matrica pogleda služi za transformaciju iz prostora scene u prostor kamere, dakle omogućava koncept virtualne kamere koju je moguće slobodno pozicionirati i orijentirati u prostoru scene. Vezano uz koncept kamere, bitna je još i projekcijska matrica. Naime, za prikaz 3D objekata na 2D zaslonu, potrebno je izvršiti odgovarajuću projekciju vrhova poligona. Vrsta i parametri projekcije su prirodno enkapsulirani unutar koncepta kamere, te ti podaci tvore projekcijsku matricu. Ova cjelokupna faza se naziva geometrijska faza, budući da se direktno vrši obrada ulazne geometrije. Tradicionalno, u ovoj se fazi izračunava osvjetljenje za pojedini vrh, upotrebom Blinn-Phong modela osvjetljenja, i time dobiva boja vrha kao četvero-komponentni vektor (crveni, zeleni, plavi i alfa kanal). Pojedinačne komponente tog vektora su širine 8 bita, što je dostatno za pohranu boja za prikaz na računalnim zaslonima. Dakako, ukoliko se definira vlastiti program za sjenčanje vrhova (eng. vertex shader), moguće je obraditi vrhove na proizvoljan način. U sljedećem koraku, vrši se odrezivanje poligona koji nisu vidljivi (eng. clipping). Naime, nakon projekcije, vrhovi poligona leže na 2D ravnini, koja je po definiciji beskonačna. No, rasterizirana slika koju želimo dobiti ima konačne dimenzije, što znači da je vrhove koji leže izvan tih granica potrebno odbaciti, i time odrezati poligone ili dijelove poligona koji nisu vidljivi. Nakon odrezivanja poligona, moguće je provesti postupak rasterizacije, odnosno generiranja skupa diskretnih slikovnih elemenata, koje ćemo nazvati fragmenti. Za svaki pojedini fragment, potrebno je odrediti konačnu boju. Jednostavan pristup je interpolacija boje izračunate po vrhu, što je funkcionalnost koju pruža grafičko sklopovlje. No, uz upotrebu vlastitih programa za sjenčanje fragmenata (eng. fragment shader) moguće je računati osvjetljenje zasebno za svaki fragment, korištenjem proizvoljnog modela osvjetljenja. Konačni rezultat za dani fragment se zapisuje u spremnik okvira (eng. framebuffer), uz mogućnost miješanja sa prethodno zapisanom vrijednosti (eng. blending). Alfa-miješanjem (miješanje boja modulirano vrijednostima alfa kanala) može se postići efekt prozirnosti ili poluprozirnosti, no moguće je koristiti miješanje i za druge efekte. Najvažnija činjenica za istaknuti jest, da kod unaprijednog iscrtavanja, cjelokupni opisani postupak se izvršava za svaki vrh ulazne geometrije zasebno, od prvog koraka do zadnjeg. Budući da se vrhovi obrađuju potpuno neovisno jedan o drugome, ovaj je postupak moguće trivijalno paralelizirati. Moderne grafičke kartice upravo imaju masivno paralelnu arhitekturu, te se sastoje od više stotina procesorskih jezgri. Međutim, ovo također znači da prilikom obrade nekog vrha ili fragmenta, nije moguć pristup podacima nekog drugog vrha ili fragmenta. Upravo ovaj problem rješava postupak iscrtavanja s odgodom. Naime, umjesto direktnog generiranja konačne slike iz ulazne geometrije, kod iscrtavanja s odgodom na temelju ulazne geometrije generira se samo skup nekih podataka (u obliku 2D slike), a koji su potrebni za računanje osvjetljenja. Dakle, svi prethodno navedeni koraci iscrtavanja se izvode nad ulaznom geometrijom, uz korištenje odgovarajućih programa za sjenčanje vrhova i fragmenata, i dobije se "slika" scene koja nije konačna, osvijetljena slika, već samo skup određenih podataka o sceni. Zatim, iscrtava se nova geometrija - pravokutnik koji prekriva cijeli zaslon - a boja pojedinih slikovnih elemenata tog pravokutnika određuje se računanjem osvjetljenja početne scene, na temelju prethodno dobivenih podataka. Dakle, za iscrtavanje s odgodom, potrebna su barem dva prolaza. Prvi prolaz služi isključivo za ekstrakciju potrebnih podataka iz ulazne geometrije scene, dok se samo osvjetljenje računa dodatnim prolazom - otuda i naziv postupka. Podaci generirani prvim prolazom se pohranjuju u teksture, koje se nazivaju G-spremnici (eng. G-buffer, skraćeno od geometry buffer), a njihova priroda ovisi o željenom modelu osvjetljenja. Primjerice, za često korišteni Blinn-Phong model, potrebni su barem difuzni i zrcalni materijal, parametar sjajnosti, te normale (pogledati poglavlje 3). Nadalje, većina stvarnih aplikacija koristi teksturirane modele, što znači da je potreban dodatan spremnik za pohranu neosvijetljene boje modela učitane iz teksture, a koja se naziva albedo. Navedene spremnike je moguće odjednom generirati u jednom prolazu, korištenjem tehnike višeodredišnog iscrtavanja (eng. multiple render targets, MRT). Sve dosad rečeno može se pregledno prikazati sljedećom slikom:
Drugi i treći prolaz je moguće sažeti u jedan prolaz, pogotovo za jednostavnije aplikacije, no ukoliko je potrebno implementirati neke dodatne algoritme opisane u kasnijim poglavljima, pogodnije je razložiti postupak na više prolaza. Obje opisane tehnike iscrtavanja imaju svoje prednosti i mane. Unaprijedno iscrtavanje je moguće obaviti u jednom prolazu, bez korištenja dodatnih spremnika, no glavni nedostatak je nemogućnost dijeljenja podataka o vrhovima odnosno fragmentima, što može biti preduvjet za implementaciju određenih naprednih algoritama. Iscrtavanje s odgodom rješava ovaj problem, ali uz cijenu dodatnih prolaza i utroška memorije. Međutim, možda i najznačajnija prednost iscrtavanja s odgodom se očituje kod korištenja većeg broja svjetala na sceni. Naime, kod tradicionalnog, unaprijednog iscrtavanja, cjelokupnu (vidljivu) geometriju scene je potrebno ponovno obraditi za svako svjetlo - od transformacije vrhova, do rasterizacije i određivanja boje fragmenata. S druge strane, kod iscrtavanja s odgodom, geometrija scene se obrađuje samo jedanput - jednom kad su G-spremnici izgrađeni, moguće ih je upotrijebiti proizvoljan broj puta, kroz proizvoljan broj prolaza. Dakle, svako dodatno svjetlo je zapravo jedan dodatan prolaz nad G-spremnicima. Budući da se osvjetljenje računa u prostoru slike, geometrijska kompleksnost više nema utjecaja na postupak osvjetljavanja, te glavni utjecaj na performanse ima rezolucija iscrtavanja. Rezultati svih prolaza osvjetljenja se akumuliraju u spremniku okvira, korištenjem aditivnog miješanja (boji fragmenta već upisanog u spremnik jednostavno se zbroji boja novo-izračunatog fragmenta). Nadalje, moguće su još poneke optimizacije kod iscrtavanja s odgodom. Naime, većina svjetala koja se javljaju u različitim scenama su lokalna, tj. svjetla ograničena u prostoru. Primjeri takvih svjetala su točkasta svjetla (eng. point light), te reflektorska svjetla (eng. spot light). Točkasti izvor svjetlosti isijava svjetlost iz neke točke prostora, jednoliko u svim smjerovima, i to na način da intenzitet osvjetljenja opada s udaljenosti od izvorišne točke; stoga, volumen kojeg obasjava točkasto svjetlo možemo zamisliti kao kuglu. Reflektorski izvor svjetlosti je sličan točkastom, no s tom razlikom da se svjetlost isijava samo u određenim smjerovima, i to tako da je opisan volumen stošca, čiji je vrh, naravno, u točki izvora svjetla. Bitno za uočiti jest činjenica da lokalna svjetla gotovo nikada ne osvjetljavaju cjelokupnu vidljivu scenu na zaslonu. Čak štoviše, u većini slučajeva, svako pojedino svjetlo na sceni će nakon iscrtavanja zauzimati možda 10% do 20% površine zaslona, odnosno slikovnih elemenata. Iz ovog opažanja slijedi da kod iscrtavanja s odgodom, nije čak niti potrebno za svako svjetlo provesti prolaz nad cjelokupnim G-spremnicima, nego samo nad onim dijelom nad kojim dano svjetlo ima utjecaja. Određivanje regije utjecaja danog svjetla moguće je obaviti korištenjem spremnika šablone (eng. stencil buffer), što je zapravo bitovna maska. Naime, budući da je volumen kojeg opisuje neko lokalno svjetlo unaprijed poznat, te odgovara nekom primitivnom geometrijskom tijelu, moguće je to geometrijsko tijelo iscrtati u spremnik šablone i tako dobiti bitovnu masku, gdje su svi elementi jednaki nuli osim onih koji odgovaraju fragmentima na koje dano svjetlo ima utjecaja. Zatim, dovoljno je jednostavno primijeniti tu bitovnu masku pri računanju prolaza osvjetljenja - grafičko sklopovlje će obraditi samo one fragmente koji su označeni maskom. Premda generiranje spremnika šablone traje određeno vrijeme, to vrijeme je gotovo zanemarivo (budući da je riječ o iscrtavanju jednostavnog geometrijskog tijela, bez teksturiranja, osvjetljavanja ili bilo kakvih drugih efekata - i to u spremnik širine jednog bita). S druge strane, primjenom šablone moguće je u većini slučajeva preskočiti relativno skupo izračunavanje osvjetljenja za 80-90% fragmenata, što je izvanredna ušteda. Za primjer, uzmimo iscrtavanje pri rezoluciji 1920x1080, što znači da je potrebno obraditi otprilike dva milijuna slikovnih elemenata. Bez upotrebe spremnika šablone, za svako pojedino svjetlo bilo bi potrebno obraditi svih dva milijuna fragmenata, dok je u protivnom za svako svjetlo u prosjeku potrebno obraditi samo dvjesto tisuća fragmenata. Uz ovu optimizaciju, iscrtavanje s odgodom omogućava upotrebu gotovo neograničenog broja lokalnih svjetala. Božićno drvce okićeno mnoštvom šarenih žaruljica, ili gradska ulica noću, osvijetljena nizom uličnih lampi i farova automobila u prolazu, samo su primjeri scena vrlo bogatih dinamičkim, lokalnim izvorima svjetla, koje bi bilo gotovo nemoguće izvesti unaprijednim iscrtavanjem. Dakako, navedena razmatranja vrijede samo za lokalna svjetla - globalni, direkcionalni izvori svjetla (kao što je Sunce), ionako obuhvaćaju cijelu scenu, pa optimizacija spremnikom šablone nije moguća - uostalom, za većinu scena, dovoljan je samo jedan direkcionalni izvor svjetla, i to najčešće Sunce. Sljedeća zanimljiva činjenica koju valja razmotriti jest, da kod unaprijednog iscrtavanja, nije unaprijed poznato da li će pojedini vrh rezultirati fragmentom koji će biti prekriven nekim drugim fragmentom ili ne, što znači da će vrlo vjerojatno doći do precrtavanja (eng. overdraw). Da bi se osiguralo pravilno iscrtavanje, potrebno je ili iscrtavati objekte pravilnim redoslijedom (od najdaljih, do najbližih), ili koristiti spremnik dubine (eng. depth buffer, odnosno z-buffer), što je vrlo često korišteno rješenje. (Kao mala digresija, kod iscrtavanja poluprozirnih objekata, spremnik dubine ne pomaže, te je ipak potrebno iscrtavati objekte od najdaljeg do najbližeg, radi pravilnog miješanja boja.) Budući da se kod unaprijednog iscrtavanja osvjetljenje odmah računa u prvom prolazu, jasno je da će neki od tih (relativno skupih) izračuna osvjetljenja biti potraćeni, budući da će dobiveni fragmenti možda biti precrtani fragmentima manje dubine. S druge strane, kod iscrtavanja s odgodom, do precrtavanja može doći jedino u prvom prolazu, kad se generiraju G-spremnici, no u toj fazi se ionako ne vrše nikakvi izračuni, već samo izvlače potrebni podaci. To znači da možemo garantirati da osvjetljenje nikada nećemo računati za fragment koji će biti odbačen, što, ovisno o sceni, može biti ili marginalna ili značajna ušteda, ali ušteda u svakom slučaju. Nažalost, to također znači da više nije moguće pravilno iscrtati poluprozirne objekte - budući da pri računanju osvjetljenja imamo informaciju samo o jednom, najbližem fragmentu, nije moguće izvesti miješanje s dubljim fragmentima (koji su bili odbačeni u prvom prolazu). Jedna mogućnost za rješavanje ovog problema jest korištenje dodatnih spremnika za pohranu dodatnih dubina fragmenata (u literaturi se ova tehnika naziva guljenje dubine, eng. depth peeling), no jasno je da time znatno povećavamo i vrijeme iscrtavanja i utrošak memorije. Druga mogućnost jest jednostavno korištenje unaprijednog iscrtavanja za ovaj poseban slučaj poluprozirnih objekata. Dodatno pitanje koje je potrebno posebno razmotriti, jest pitanje izglađivanja nazubljenih rubova poligona (eng. anti-aliasing). Naime, postojeće grafičko sklopovlje posjeduje ugrađene mehanizme za izglađivanje koji su osmišljeni za upotrebu s jednoprolaznim, unaprijednim iscrtavanjem, te nisu direktno upotrebljivi pri iscrtavanju s odgodom. Naime, navedeni mehanizmi se baziraju na ideji višestrukog uzorkovanja spremnika dubine, primjerice dvostrukog ili četverostrukog. Prilikom obrade vrhova i generiranja fragmenata, ukoliko se uzorci spremnika dubine razlikuju za dobiveni fragment (dakle, promatrani fragment se nalazi na granici poligona), odredi se boja za svaki od uzoraka i zatim obavi jednostavno miješanje, čime se rubovi poligona izglade. Međutim, problem s ovim postupkom jest taj, što kod iscrtavanja s odgodom prilikom iscrtavanja geometrije zapravo ne dobivamo konačnu boju fragmenata, već samo određene podatke za kasniju obradu. Prema tome, miješanje i "izglađivanje" tih podataka će rezultirati pogrešnim izračunom osvjetljenja (izračunati osvjetljenje nad izglađenim materijalima nije isto kao i izgladiti već osvijetljene fragmente). Ovaj ozbiljan problem je srećom riješen na modernim grafičkim karticama koje podržavaju DirectX 10 tehnologiju, koja omogućava višestruko uzorkovanje proizvoljnih spremnika i tekstura, te direktan pristup tim poduzorcima unutar programa za sjenčanje fragmenata. Na taj način, moguće je višestruko uzorkovati G-spremnike, ali odgoditi miješanje poduzoraka do završetka prolaza za osvjetljenje. Pritom program za sjenčanje fragmenata koji računa osvjetljenje mora ručno učitati poduzorke G-spremnika za dani fragment, izračunati osvjetljenje za svaki poduzorak zasebno, te kombinirati dobivene rezultate u konačnu boju. Dakako, ovaj postupak nije potrebno provoditi za baš svaki fragment, već samo za one koji se nalaze na rubovima poligona. Detekciju rubnih fragmenata je također potrebno ručno napraviti, unutar programa za sjenčanje. Primjerice, dobar način kako to izvesti jest korištenjem spremnika šablone; u pretprolazu, posebnim programom za sjenčanje fragmenata određuju se rubni fragmenti u G-spremnicima, usporedbom dubina poduzoraka. Ukoliko su zadovoljeni odgovarajući uvjeti, fragment se proglašava rubnim, te se u spremnik šablone zapisuje vrijednost jedan, a u suprotnom, zapisuje se vrijednost nula. Prema tome, izračun doprinosa pojedinog svjetla se razdvaja na dva pod-prolaza. Prvi pod-prolaz izračunava osvjetljenje koristeći samo jedan poduzorak G-spremnika (budući da su svi isti), a drugi pod-prolaz izračunava osvjetljenje onoliko puta koliko postoji poduzoraka G-spremnika (budući da se neki ili svi razlikuju), te kombinira te rezultate u konačnu boju. Uz upotrebu spremnika šablone, možemo osigurati da će grafičko sklopovlje izvesti prvi pod-prolaz samo nad ne-rubnim fragmentima, a drugi, puno skuplji pod-prolaz samo nad rubnim fragmentima, za koje je doista i potrebno izglađivanje. Dakle, premda je izglađivanje nazubljenih rubova poligona višestrukim uzorkovanjem moguće i kod iscrtavanja s odgodom, potrebna je relativno moderna grafička kartica (DirectX 10 ili novija), a čak i tada, potrebno je mnogo dodatnog posla, što nije slučaj kod unaprijednog iscrtavanja. U konačnici, najbolji rezultati se postižu kombiniranjem obje tehnike, na način da se iscrtavanje s odgodom koristi za neprozirne objekte, a unaprijedno za (polu)prozirne. Također, i direkcionalna svjetla je moguće riješiti unaprijednim iscrtavanjem, budući da bi njihovo rješavanje iscrtavanjem s odgodom samo značilo trošak dodatnog prolaza, a bez mogućnosti optimizacije kao kod lokalnih svjetala. Prednosti i nedostaci pojedinih tehnika sažeti su tablicom 1. Analizom kompleksnosti, možemo zaključiti da su oba algoritma linearne složenosti - svako dodatno svjetlo zahtjeva jednak broj dodatnih koraka. Međutim, ovo je zavaravajući rezultat, budući da ova dva postupka zapravo ne djeluju nad istim skupom podataka, te se ne mogu na tako jednostavan način direktno usporediti. Unaprijedno iscrtavanje za svako svjetlo obrađuje svaki vrh, te svaki generirani fragment. Iscrtavanje s odgodom vrhove obrađuje samo jedanput, a zatim za svako svjetlo obrađuje minimalni podskup fragmenata. Ukoliko s L označimo ukupan broj svjetala, s V ukupan broj vrhova, s F ukupan broj fragmenata, a s F' minimalni skup fragmenata (u prosjeku 10% ukupnog broja), možemo kompleksnost formulirati izrazima navedenima u tablici 1:
|