Sta su shaderi?
Shaderi su programi koji se izvrsavaju na grafickoj kartici i obradjuju vertexe (temena trouglova koji se crtaju) i pixele. Shaderi su buducnost grafike u igrama, prakticno sve AAA igre koje su sada u razvoju koriste iskljucivo shadere. Kao i uvek, nove mogucnosti povlace sa sobom i nove probleme, ali zato nude grafiku koja je mnogo bolja od postojace.
Postoji nekoliko jezika u kojem je moguce pisati shadere, ja cu ovde pisati o HLSLu (high-level shading language), koji je deo Direct3Da.
Uzmimo za pocetak vertex shadere. Da bi se neki model iscrtao, potrebno je sve njegove vertexe pretvoriti iz model spacea u view space. To se radi tako sto se svako teme pomnozi sa world matricom, pa onda sa view matricom, i na kraju sa projection matricom.
Evo kako se to radi u HLSLu:
float4x4 matWorld : WORLD;
float4x4 matView : VIEW;
float4x4 matProjection : PROJECTION;
struct VSIN
{
float4 pos : POSITION;
};
struct VSOUT
{
float4 pos : POSITION;
};
VSOUT JednostavanShader(VSIN vin)
{
VSOUT vout;
vout.pos = mul(vin.pos, matWorld);
vout.pos = mul(vout.pos, matView);
vout.pos = mul(vout.pos, matProjection);
return vout;
}
Za pocetak treba da definisemo 3 matrice koje su nam neophodne. To su World, View, i Projection matrice. HLSL uvodi pojam 'semantike' koji sluzi da dodatno opise neku promenljivu. Prva promenljiva, matWorld, je tipa float4x4 (dakle 4 x 4 matrica) i nju vezujemo za WORLD semantiku. To znaci da ce programi koji podrzavaju semantike (kao sto je EffectEdit) automatski namestiti vrednost te matrice na trenutni world transform. Isto vazi i za ostale matrice, matView i matProjection.
Nakon toga treba da definisemo dve strukture koje ce sluziti kao ulaz i izlaz iz naseg vertex shadera. Obe strukture za sad izgledaju isto, posle cemo moci da ih nadogradimo. Ulaz u vertex shader je pozicija svakog temena, a to je jedan float4 (x, y, z, w). Izlaz je takodje to, ali naravno transformisano tako da se uzme u vid pozicija objekta u svetu (world transform), pozicija kamere (view transform) i projekcija na 2D ekran (projection transform). Ove vrednosti za ulaz bi mogli da uzmemo iz bilo kog fajla koji je snimljen iz nekog od 3D programa (Maya, 3DS). Primeticete da uz pomoc POSITION semantike oznacavamo da promenljiva pos treba da sadrzi poziciju temena.
Mozda ce nekima ubosti oci to sto je ulaz float4, umesto float3. Ako su dovoljne 3 koordinate da se opise svaka tacka, cemu onda sluzi w? Kratak odgovor je nicemu, a malo duzi odgovor je da bi ovaj shader bio sto jednostavniji, radicemo samo sa homogenim koordinatama. Ili, jednostavno receno, dovoljno je da se w postavi na 1. Naravno, shaderi uglavnom ne koriste homogone koordinate za ulaz, ali o tome cemo kasnije.
I sada ide sam shader. Shaderi u HLSLu se pisu kao funkcije u Cu: imaju povratnu vrednost (u nasem slucaju VSOUT) i ulazne argumente (VSIN). Sam shader je prilicno jednostavan, samo uzima ulaz, mnozi ga sa world matricom, pa onda sa view matricom, i na kraju sa projection matricom, i onda to vraca pomocu returna.
Dobro, i kako sada to radi?
Vrlo jednostavno: iz programa se ucita ovaj shader, namesti se pomocu SetVertexShader komande, pozove se BeginPass, iscrta ceo objekat kao sto se to inace radi, i onda se pozove EndPass.
Fenomenalno, a sta se time dobija? Dobija se nesto sto izgleda isto kao i sva grafika do sada, jer je ovo u stvari minimalni shader koji moze nesto da radi. Kasnije mozemo da nadogradimo druge stvari kao sto su teksture, osveltjenje, i neke druge specijalne efekte. Ali da ovaj tekst ne bi bio ovoliko suvoparan, evo jedne slike:

Prilicno neimpresivno, zar ne? :)