» »

Per-Pixel Lightning

Vas zanima, kaj je to per-pixel lighting? Vas zanima, kaj bo per-pixel lighting pomenil za igre in programe, kakno je tehnično ozadje, zakaj je to e en mejnik v računalniki grafiki za osebne računalnike? No če ste vsaj na eno izmed teh vpraanj odgovorili pritrdilno, potem je ta članek za vas. V tem članku si bomo ogledali tako teoretično, kot tudi praktično plat per-pixel lightinga, povedal pa bom tudi nekaj o drugih načinih senčenja.


Let there be light:

Senčenje (lighting) je eden izmed dveh glavnih delov matematike, potrebne za 3D grafiko. Medtem, ko transformacijski (transform) del skrbi za pravilno lego objektov, senčenje poskrbi za pravilno osvetlitev scene. Skupaj tvorita ti. T&L (transformation and lighting), brez katerega 3D grafika ne bi bila mogoča. V osnovi imamo v 3D svetu opravka s tremi načini senčenja:

  • flat shading,
  • gouraud shading,
  • phong shading,

Za flat shading se osvetljenost izračuna samo za prvo ogliče vsakega trikotnika, tako je cel trikotnik enako osvetljen (teksture mu lahko pač spremenijo barvo). Ta postopek se v praksi praktično ne uporablja več, saj je zelo nenatančen.
Pri gouraud senčenju se osvetljenost izračuna za vsako oglišče trikotnika. Barva osnovnega trikotnika (brez teksture) se nato linearno preračuna čez cel trikotnik. Ta način je zaradi relativne nezahtevnosti in relativno velike natančnosti praktično edini, ki se uporablja v grafiki na osebnih računalnikih
Phong-ovo senčenje je še korak nad gouraud-ovim senčenjem. Pri tem postopku se osvetljenost izračuna za vsako točko (pixel) trikotnika posebej. To je najnatančeja metoda med osnovnimi načini in se v igrah zaradi izredne zahtevnosti sploh ne uporablja, saj je ne podpira noben grafični pospeševalec in nobena igra. Prav tako se zaradi naprednejših metod, ki nudijo še natančnejše rezultate ne uporablja v profesionalni- filmski grafiki.

Igre so tako ostale z gouradovim senčenjem, ki pa kmalu ni več zadoščalo za uresničitev želja razvijalcev iger po čim boljši grafiki v igrah. S prihodom Voodoo 2 čipa, ki je ponujal ti. multi texturing, so razvijalci dobili v roke prvo orodje za izboljšanje grafike. Današnje igre tako uporabljajo metodo imenovano light mapping. Light mapping je metoda, pri kateri se uporabi še druga tekstura (zato dandanes vse igre delujejo z multi-texturingom). Prva tekstura je običajna tekstura, ki predstavlja določeno površino, druga tekstura pa je light map. Light map je precej natančna tekstura, ki pa jih renderirajo razvijalci sami s posebnimi, za to namenjenimi orodji. Light mapping je v večini uporaben le za statične scene, kjer se luči ne premikajo in okolica ne spreminja. Uporablja se sicer tudi nekoliko prirejen princip, pri katerem nalepimo določeno light mapo na objekt glede na razdaljo in lego luči (primer: ko ustreli raketo v Quake-u se stene osvetljijo), vendar ni preveč natančen.

*
=

Alternative light mappingu:

Light mapping seveda ni odgovor na vse (če bi bil, bi bil naslov članka drugačen :)), in je dober samo do določene meje. Predvsem mu manjka "dinamičnosti". Zaradi tega sta se razvili dve naprednejši metodi senčenja (nadgradnja osnovnih treh). Razvijalci so si tako postavili pogoj: potrebujemo natančno metodo, ki bo določila osvetlitev vsake točke na zaslonu, in bo uporabna tudi za dinamične scene. Phongovo senčenje temu pogoju delno celo zadošča, vendar z njim ni mogoče simulirati valovitih površin (bump mapping). Razvili sta se dve metodi:

  • ekstremno zgoščanje trikotnikov (tessellation),
  • per-pixel lighting

Ekstremno zgoščanje trikotnikov pomeni točno to, kar bi razbrali iz izraza- ekstremno zgoščanje trikotnikov. Namesto enega trikotnika se izračunajo trije ali štirje novi, manjši trikotniki, nato pa se postopek ponovi, dokler ne pridemo do željene gostote trikotnikov. Ta postopek se uporablja samo v profesionalni- filmski grafiki, kjer potrebujejo ekstremne natančnosti. Pri studiu Pixar tako postopek ponavljajo, dokler niso vsi trikotniki veliki za 1/2 pike! Postopek je zelo, zelo zahteven (torej za resulucijo 800x600 pri hitrosti 60 slik na sekundo bi potrebovali grafično kartico, ki bi bila sposobna transformirati in senčiti veliko večkot 57.6 milijonov trikotnikov v sekundi), vendar daje rezultate, ki jih videvamo v filmih.

Začnemo z enim trikotnikom...

Po prvem prehodu nastanejo štirje...

Po drugem prehodu pa jih je že 16!

Per-pixel lighting pa je prav tako zelo dobra in predvsem mnogo hitrejša alternativa zgoraj omenjenemu postopku. Če pogledamo v današnjo računalniško grafiko ugotovimo, da že vsebuje nekaj, kar ob pravilni uporabi zasede en pixel- texel. Per-pixel lighting se tako izvaja zelo podobno kot običajni light mapping, vendar daje precej boljše rezultate, ima pa eno bistveno prednost pred light mappingom, je namreč povsem dinamičen. Per-pixel lighting tako lahko vnesemo v kakršnokoli sceno, od statičnih luči na stenah, do dinamičnih svetlobnih efektov za raketami in podobno.


Kako deluje per-pixel lightning?

Vsako senčenje se v računalniški grafiki izvaja glede na normale. V matematiki normala predstavlja vektor, ki je pravokoten na trikotnik. V 3D grafiki pa ima normala precej podoben pomen, predstavlja namreč smer (vektor) maksimalnega odboja svetlobe. Če sta torej smer luči in normala vzporedna, je osvetlitev maksimalna. Če je kot med normalo in smerjo luči velik, potem je osvetlitev majhna. Pri klasičnem gouraudovem senčenju so normale postavljene na vsako oglišče (vertex), če si torej več trikotnikov deli isto točko, moramo to upoštevati tudi pri drugačnem izračunu normale. Per-pixel lighting prav tako vsebuje normale, vendar tokrat normale niso le na ogliščih, ampak se jih nanese na teksturo. Če uporabimo ustrezne metode (mip-mapping in razne metode filtriranja tekstur) dosežemo to, da se osvetljenost lahko izračuna za vsako točko na ekranu posebej. Obenem pa lahko na to teksturo nanesemo tudi motnje, ki pri renderiranju povzročijo navidezno hrapavost povrÅ¡in.


Vektorji zapisani na teksturo?

Morda se bo komu zdelo čudno, kako to, da so lahko zapisani vektorji na teksturi, vendar je stvar zelo preprosta. Običajno imamo na današnjih 3D pospeševalcih določene formate tekstur. Ti formati povejo koliko bitov se uporabi za posamezen barvni kanal. Nekaj osnovnih tipov je recimo 565 (5 bitov za rdečo, 6 za zeleno in 5 za modro), 555 (5 bitov za rdečo, 5 za zeleno in 5 za modro), 888 (8 bitov za rdečo, 8 za zeleno in 8 za modro). Obstaja še nekaj formatov z alpha kanalom, ki pa služijo za polprosojnost barve. Vektor se v točko na teksturi spremeni zelo preprosto, namreč vsak vektor je sestavljen iz treh decimalnih števil. Ta tri števila se nato zapišejo v tri kanale teksture (iz XYZ dobimo RGB). Edini problem pri tem je to, da so decimalna števila v vektorju vedno sestavljena iz 32 bitov, na teksturo pa jih lahko spravimo le 8 (če imamo 32 bitno teksturo). Vendar to ni nič katastrofalnega, saj morajo ta števila vedno biti večja od -1 in manjša od 1. Maksimalen vektor, ki ga lahko uporabimo za normalo je tako (1,1,1). Tako nam ostane še nekako 16 bitov, to je tudi eden izmed razlogov, zakaj naj bi kmalu dočakali kar 64 bitne teksture. Primer, kako izgleda tekstura z vpisanimi vektorji odboja svetlobe. Rdeč kanal predstavlja X os, zelen Y in moder Z os. Siva obroba pa je vektor (0,0,0) in pomeni, da se od tam svetloba ne odbija.


Kako se to renderira?

Nekateri si predstavljajo per-pixel lighting kot nekaj, za kar je potrebno veliko dodatnih funkcij in podpore s strani API-ja (DirectX, OpenGL, ...). Gledano s tehničnega stališča pa gre pri per-pixel lightingu bolj za spretno programiranje, kot revolucionarne novosti. Vse, kar mora grafični čip podpirati za per-pixel lighting je funkcija dot product 3 (trenutno podprto na vseh GeForce-ih in ATI Radeon-u). Osvetljenost posamezne točke na teksturi se tako izračuna po formuli:

osvetljenost = (tekstura) dot product 3 (smer_luči)

Tekstura predstavlja trenutno točko na teksturi (tekstura vsebuje podatke o normalah), za katero poteka izračun. Smer_luči je vektor, ki predstavlja smer, v katero sveti luč. Rezultat te operacije je osvetljenost (za vsak teksel posebej), in se uporabi še za zadnji del, ki se uporabi za osvetlitev osnovne teksture (recimo slika stene).

Rezultat, do katerega pridemo z dot product 3 funkcijo. Če luč premaknemo, se spremeni tudi osvetlitev.

Dokaz, da gre za per-pixel lighting. Žični model nam pokaže, da imamo opravka s samo dvema trikotnikoma.

Vhodni podatki za zgornji slikici so le tekstura z normalami (na prejnji strani), dva trikotnika in luč. Vse ostalo naredi per-pixel lighting oziroma dot product 3 funkcija.

Še en primer uporabe per pixel lightinga. Tokrat vidimo točkovno luč (point light) v prostoru.

Takih efektov s klasičnim senčenjem ni mogoče doseči (razen z zelo gostimi poligonskimi mrežami - glej dve strani nazaj). Za določene stvari (recimo spodnja slika na tej strani) bi bil sicer dovolj light mapping, vendar pri tem ne bi mogli premikati luči. Per-pixel lighting tudi deluje povsem neodvisno od CPU-ja tako, da ne predstavlja nobenega dodatnega dela za CPU.


Zaključek:

Tako, prišli smo do konca. Kot se vam je (upam) ob branju tega članka posvetilo, je per-pixel lighting zelo zanimiv postopek. Ključ do per-pixel lighting-a pa je dot product 3 funkcija. Per-pixel lighting bo v bljižni prihodnosti igral zelo pomembno vlogo. Je namreč še en velik korak proti grafiki, kakršno videvamo v filmih, ki so izdelani s pomočjo računalnikov. Poznavalci so mnenja, da bodo grafične kartice za osebne računalnike v približno 10-ih letih dosegle tako visok nivo hitrosti in kvalitete, da bodo zmožne renderirati grafiko, kot je v risanki Toy Story v realnem času. Trenutno je grafika za osebne računalnike na zelo dobri poti, saj jim bo čez eno ali dve generaciji manjkala le še zadostna hitrost, in dovolj veliki monitorji. Toy Story je bil namreč renderiran v resuluciji kar 8000x6000. To pa je veliko več kot zmore katerikoli današnji monitor... Vprašanje je samo še če bomo v 10-ih letih imeli monitorje z resulucijo 8000x6000 in kakšna grafika bo potem v filmih?

Čudežno popotovanje skozi grafični cevovod II

Čudežno popotovanje skozi grafični cevovod II

V prvem delu smo si ogledali strukturo sodobne grafične kartice. Med drugim smo omenili shaderje, ki so zaradi svoje programabilnosti, nekakšno srce in duša sodobnih GPU-jev. Različni shaderji so odgovorni za različne strukture v grafiki (v Direct3D 10 so to oglišča, ...

Preberi cel članek »

DirectX 9.0 - Izboljšave knjižnice

DirectX 9.0 - Izboljšave knjižnice

V prejšnjem delu smo si ogledali novosti in izboljšave, ki so doletele programabilnost grafičnih kartic, torej osenčevalnike točk ter oglišč. Seveda pa novi pixel in vertex shaderji niso edina novost v DirectX 9.0. Novosti je še kar nekaj, vendar je res, da je ...

Preberi cel članek »

DirectX 9.0 - Osvetljevanje

DirectX 9.0 - Osvetljevanje

Tokrat si bomo ogledali eno izmed možnosti osvetljevanja v knjižnici DirectX 9.0. Ker tudi DirectX 9.0 še vedno pozna le osnovne osvetlitvene modele (flat in Gouraud), kljub temu da je strojna oprema že precej časa zmožna tudi česa več, si bomo pomagali s pixel ...

Preberi cel članek »

Zakaj 32bpp ni dovolj

Zakaj 32bpp ni dovolj

Verjamem, da je marsikdo precej debelo pogledal, ko je prebral naslov tega članka, pa nič zato. Še nedolgo tega smo po svetovnih forumih lahko prebirali žolčne razprave o tem, da med 16 in 32bpp sploh ni razlike. Ustvarila sta se dva tabora, ki se nista preveč lepo gledala ...

Preberi cel članek »

DirectX 8: 3D teksture, multi-sampling in point sprites

DirectX 8: 3D teksture, multi-sampling in point sprites

V prejšnjem članku smo si ogledali pixel in vertex shaderje, ki v svet grafike za osebne računalnike prinašajo programabilnost. V tem članku pa si bomo ogledali še dve veliki novosti v DirectX 8.0 - podpora za 3D teksture in multi-sampling. Če bodo vertex ...

Preberi cel članek »