Programi za sjenčanje geometrije

Kontakt

Autora možete kontaktirati na jmaricevic@nightirion.com

Korisni linkovi

Jezici za programiranje

U OpenGL-u od verzije 1.5 nadalje postoji jezik sličan C-u, OpenGL Shading Language ili GLSL. Za potrebe ovog seminara, svi programi za sjenčanje su isprogramirani u GLSL-u. U Microsoftovom Direct3D-u programi za sjenčanje se programiraju pomoću jezika koji se zove High Level Shading Language ili HLSL. Mogućnosti gore navedenih jezika su skoro identične, razlike postoje samo u semantici i načinu programiranja, tako da postoje alati koji služe za automatsku konverziju programa iz jednog jezika u drugi. Osim navedenih jezika, postoji još i Cg ili C for Graphics, koji je Nvidia razvila u suradnji s Microsoftom, te dijeli dosta sličnosti s HLSL-om.

GLUT

GLUT biblioteka je skup funkcija za OpenGL programe, koje većinom obavljaju ulazno izlazne operacije na razini operacijskog sustava, te time olakšavaju taj posao programeru. To uključuje definiciju prozora, kontrolu i upravljanje prozorom i očitavanje ulaza sa tipkovnice i miša. Također su dostupne funkcije za prikaz nekih primitiva poput kocke, kugle i čajnika (Utah teapot).

GLEW

GLEW je C/C++ višeplatformska biblioteka koja olakšava pozivanje i učitavanje OpenGL ekstenzija. Omogućava nam efikasno provjeravanje koje OpenGL ekstenzije su dostupne za vrijeme izvođenja programa. Sve dostupne ekstenzije su izložene u jednoj .h datoteci koja se generira pomoću službene liste ekstenzija. Sam naziv GLEW je nastao kao kratica od engleskog naziva OpenGL Extension Wrangler Library.

Korištenje programa za sjenčanje u neovisnom programu

Postoje dva osnovna načina za prevođenje i povezivanje programa za sjenčanje u glavnom programu pomoću OpenGL-a. Prvi je korištenje izvornih OpenGL 2.0 funkcija, ili u slučaju da nemamo podršku za OpenGL 2.0 korištenje ARB ekstenzija. Naziv ARB je nastao kao skraćenica od Architecture Review Board, što je neovisni konzorcij koji predlaže i odobrava promjene OpenGL specifikacija, nova izdanja i ispituje usklađenost sa standardom. Neka dodatna funkcionalnost postaje dio ARB ekstenzija (tzv. standardnih ekstenzija) tek ako nekoliko proizvođača implementira istu funkcionalnost i ako Architecture Review Board nakon detaljnog pregleda odobri navedene implementacije. Sljedeća slika prikazuje minimalne potrebne osnovne korake da prevedemo i povežemo program za sjenčanje s našim glavnim programom.


Pošto Windowsi XP nemaju izvornu podršku za OpenGL 2.0, u prvom dijelu ovog rada su korištene ARB ekstenzije za prevođenje i povezivanje programa za sjenčanje. Prvi korak je kreiranje objekta koji će služiti kao spremnik za program za sjenčanje. U ovom slučaju umjesto GLuint glCreateProgram(void) koristimo ARB ekvivalent GLhandleARB glCreateProgramObjectARB(void). Broj programa koji možemo ovako napraviti nije ograničen, a za vrijeme ostvarivanja prikaza možemo se prebacivati između programa, pa se čak i vratiti na fiksnu funkcionalnost tijekom prikaza jednog okvira. Na primjer, možemo iscrtati čajnik primjenjujući na njemu neki od programa za sjenčanje dok se istovremeno pozadina prikazuje koristeći fiksnu funkcionalnost OpenGL-a. Idući korak uključuje dodavanje programa za sjenčanje. U ovom trenutku oni ne trebaju biti prevedeni, pa čak nije ni nužno da postoje, potreban nam je samo spremnik koji smo napravili u prvom koraku. ARB funkcija koju koristimo za to je void glAttachObjectARB(GLhandleARB program, GLhandleARB shader). Prevođenje programa za sjenčanje se radi pomoću funkcija void glShaderSourceARB(GLhangleARB shader, GLuint number_strings, const GLcharARB** strings, Glint * length) i void glCompileShader(GLhandleARB shader). Zadnji korak je povezivanje i stavljanje programa u uporabu, što radimo sa funkcijama void glLinkProgramARB(GLhandleARB program) i void glUseProgramObjectARB(GLhandleARB prog). Ako za parametar prog proslijedimo 0, aktivira se fiksna funkcionalnost cjevovoda.

Naravno, prije svega navedenog potrebno je provjeriti da li uopće postoji podrška za GLSL. Primjer provjere dostupnosti ARB ekstenzija za rad sa programima za sjenčanje:

glewInit();
if (GLEW_ARB_vertex_shader && GLEW_ARB_fragment_shader)		
	printf("Graficka kartica podrzava GLSL\n");
else 
{
	printf("Nema podrske za GLSL\n");
	exit(1);
}

GLSL

GLSL sadrži sve operatore iz programskog jezika C uz iznimku pokazivača. Operatori za rad s bitovima su dodani u verziji 1.30. Slično C-u, podržava petlje i različite oblike grananja uključujući if, else, for, do-while, break i continue. Korisnički definirane funkcije su također podržane i većina često korištenih funkcija je ugrađena. Ovo dozvoljava proizvođačima grafičkih kartica da optimiziraju te funkcije na sklopovskoj razini. Primjer takvih funkcija su exp() i abs(). Također su ugrađene i neke funkcije koje su specifične za rad s računalnom grafikom poput smoothstep() i texture2D(). Varijable se dijele na tri osnovna tipa:

  • Atributne (engl. attribute) - varijable koje se zadaju na razini vrha. Ova vrsta varijabli se odnosi isključivo samo na procesor vrhova.
  • Uniformne (engl. uniform) - varijable zadane na razini primitive. Ove se varijable prenose procesoru vrhova, procesoru fragmenata ili procesoru geometrije.
  • Promjenjive (engl. varying) - varijable koje procesor vrhova prenosi procesoru fragmenata ili geometrije.

Programi za sjenčanje napravljeni pomoću GLSL-a nisu samostalni, već zahtijevaju aplikaciju koja koristi OpenGL programsko sučelje. Implementacija OpenGL sučelja je dostupna na mnogim različitim platformama, a postoje i sučelja za različite programske jezike.

Sami programi za sjenčanje su jednostavno niz tekstualnih naredbi koji se prosljeđuju upravljačkom programu uređaja da ih prevede u izvršne programe. Skup funkcija koje se koriste za prevođenje i prosljeđivanje parametara GLSL programima je specificiran u tri ekstenzije OpenGL-a, a postali su sastavni dio OpenGL-a od verzije 2.0.

Primjeri programa za sjenčanje

U sljedećih nekoliko poglavlja opisani su programi za sjenčanje koji su isprogramirani za demonstraciju mogućnosti i prednosti programa za sjenčanje nad klasičnim ostvarivanjem prikaza pomoću cjevovoda s fiksnim funkcijama. U opisu svakog programa za sjenčanje bit će navedeni samo dijelovi koda koji su bitni za njih, dok se dio koda koji se bavi općenitim ostvarivanjem prikaza i manipuliranjem scene ne smatra temom ovog rada, ali se može vidjeti na priloženom CD-u. Kao pomoć prilikom dizajniranja i programiranja samih programa za sjenčanje, korišten je AMD RenderMonkey 1.81, dok je glavni program za demonstraciju korištenja programa za sjenčanje unutar samostalnog projekta napravljen u C-u (pomoću Visual Studia 2005), te koristi GLUT i GLEW biblioteke. Također, bitno je napomenuti da za GLSL ne postoji efektivan način ispravljanja grešaka (postoje neki zaobilazni načini), tako da pronalaženje grešaka koje nisu greške kod prevođenja postaje vremenski veoma zahtjevan posao.

Tehnika prikaza Cel-shading

Jedan od najpoznatijih nefotorealističnih načina prikaza, dizajniran da se dobije dojam crtanja rukom. Najčešće se koristi u animiranim filmovima ili stripovima, ali ima i drugih primjena poput npr. povećanja čitljivosti tehničkih ilustracija. Glavna razlika između konvencionalnog ostvarivanja prikaza i cel-shadinga je u načinu računanja osvjetljenja. Prvo se izračuna normalno osvjetljenje za svaki slikovni element, te se potom tako izračunata vrijednost pretvara u neku od malog broja diskretnih vrijednosti. Svjetlija i tamnija područja tada izgledaju kao blokovi boje umjesto ravnomjernih prijelaza. Nakon toga se po volji mogu dodavati efekti poput iscrtavanja obruba. Ako se ne iscrtavaju rubovi, dovoljan je samo jedan prolaz.


Transformacije geometrije

Jedan od korisnih efekata koji se mogu postići pomoću programa za sjenčanje vrhova, bez značajnog utjecaja na performanse je mijenjanje geometrije scene na različite načine. Od najjednostavnijeg skaliranja, preko različitih izobličenja scene, pa do kompliciranijih efekata tipa pretvaranja iz jednog oblika u drugi. Također, kao argument o kojemu ovisi bilo koja od funkcija izobličenja može biti bilo što, što se može proslijediti iz glavnog programa, npr. vrijeme, pozicija miša, pozicija na sceni, slučajni broj i sl. Kombinirajući to s ostvarivanjem prikaza u teksturu moguće je postići mnogo različitih efekata (npr. efekt tkanine koja leluja na vjetru, efekt LED oglasne ploče, efekt pokvarenog televizora) koji bi inače zahtijevali puno više procesorske snage.

Izvijanje


Skaliranje

Efekt skaliranja također nije kompliciran za implementaciju pomoću programa za sjenčanje. Pošto se u osnovi skaliranje svodi na množenje matrice projekcije vektorom u kojem elementi označavaju faktor skaliranja po svakoj osi, to je jedina dodatna linija koju trebamo dodati u odnosu na ostale programe. Program za sjenčanje fragmenata se ne mijenja, pa ga ne treba dodatno ni objašnjavati.


Jednostavna prozirnost

Ponekad nam je potreban jednostavan efekt prozirnosti, u kojem možemo samo označiti koji dijelovi objekta su potpuno prozirni, a koji nisu uopće. Tako možemo dobiti izgled objekata kojima nedostaju dijelovi, npr. korodirani objekti, ili objekti sa rupama od projektila. Jedan od načina određivanja koje slikovne elemente treba ukloniti je pomoću alfa vrijednosti teksture za određeni slikovni element no broj mogućih načina je vrlo velik – od uklanjanja samo slikovnih elemenata određenih boja do potpuno slučajnog odabira.


Efekt stakla

No ako želimo vjerno prikazati materijal koji je proziran, onda to ne možemo izvesti na jednostavan način, jer ne postoje materijali koji su savršeno prozirni, već svi imaju određeni koeficijent refleksije. Sam efekt fotorealističnog prikaza prozirnog stakla je tema za sebe, tako da ćemo se ovdje usredotočiti samo na model korišten za implementiranje ovog programa za sjenčanje. U programu za sjenčanje vrhova, osim normalnog računanja pozicije vrha, računamo i vektor pogleda vViewVec koji će nam biti potreban u programu za sjenčanje fragmenata. Potom u programu za sjenčanje fragmenata računamo varijablu v kao skalarni produkt normaliziranog vektora pogleda i vektora normale, koji nam u biti određuje prozirnost trenutačnog fragmenta. Što je v veći, to znači da nam je vektor pogleda okomitiji na taj fragment, što implicira i bolju prozirnost i manju refleksiju. No osim prozirnosti, varijabla v nam također služi za dobivanje efekta disperzije svjetlosti te nju koristimo da odredimo koordinate elementa teksture duge za trenutačni fragment. Vektor refleksije vektora pogleda u odnosu na normalu ne moramo računati ručno, nego ga jednostavno možemo dobiti pomoću ugrađene funkcije reflect() koja je dio GLSL-a. Tada pozivamo funkciju textureCube() koja kao argumente uzima teksturu za uzorkovanje i trodimenzionalni vektor koji odgovara smjeru odbijanja vektora pogleda na određeni vrh. Iz tog vektora, funkcija određuje koju stranu kocke treba uzorkovati, te zatim projicira vektor na tu plohu kako bi se dobile dvodimenzionalne koordinate elementa teksture. Krajnja boju fragmenta dobivamo kao linearnu interpolaciju između dva dobivena elementa teksture uz pomoć funkcije mix().


Osvjetljenje po slikovnom elementu

Osvjetljenje po slikovnom elementu (engl. per-pixel lighting) je često korištena metoda za računanje osvjetljenja u računalnoj grafici. Dobivene slike su mnogo realističnije nego one dobivene pomoću računanja osvjetljenja vrhova (Gouradovo sjenčanje), no istovremeno i mnogo zahtjevnije što se tiče procesorske snage. Za potrebe aplikacija koje se izvode u realnom vremenu, implementacija osvjetljenja po slikovnom elementu se tipično izvodi pomoću programa za sjenčanje. Ova tehnika se često koristi u kombinaciji s preslikavanjem izbočina, zrcalnim osvjetljenjem i volumenima sjena.