2011. február 3., csütörtök

Bevezetés a shaderek világába

Már régóta szerettem volna foglalkozni a shaderekkel. Sajnos a bevezetők írása nem az én műfajom, így most is egy nagyszerű írást hívok segítségül TheProGamer tollából. Remélem segíteni fog mindenkinek ráhangolódni a témára. Amint lesz egy kis időm a példaprogram is érkezni fog...

Bevezetés

Mik is azok a shaderek, hogy működnek és miért jelentenek fejlődést? Ezen kérdésekre próbálok ezzel a cikkel választ adni. Kezdjük is rögtön azzal hogy mik is ezek? Hogy ezt megértsük először nézzük meg hogy néz ki a Direct3D Pipeline.


Mint a képen is látható a shaderek két részre oszthatók: Pixel Shader és Vertex Shader. Ez a két shader típus két ezelőtt teljesen merev automata folyamatot vált le. A Vertex Shader-ek a T&L leváltására készültek, a Pixel Shader-ek pedig a textúra mintavételezés és a képernyőre kerülő képpontok színének előállításának merev önműködő folyamatát hivatottak rugalmasabbá tenni.

De mik is ezek a shaderek konkrétan?

Kis, önálló nyelven a programozó által írt mini programocskákról van szó, amik alapvetően arra hivatottak, hogy a idáig automata folyamatokat elvégezzék. Kérdezhetitek hogy ez akkor miért jó, hisz ugyanazt csinálja és még ezt is kódolni kell. Mert nem csak helyettesíteni lehet vele ezeket az a folyamatokat, hanem tovább fejleszteni, bonyolultabbá és összetettebbé tenni, ezáltal sokkal élethűbb képet előállítani. Mert ugye ha valamilyen új, rugalmasabb eszközt adunk a programozók kezébe egy régi helyett, akkor ők nem arra fogják ezt használni hogy csak a régit helyettesítsék vele. :) Ez idáig gondolom érthető.

De akkor most ezek konkrétan hogyan is működnek?

Kezdjük az egyszerűbbel, a Vertex Shader-rel. A Vertex Shader minden egyes vertexre lefut, nem számít hogy hol van, milyen messze, milyen irányban. Legelőször is meg kell adnunk hogy a vertexek mely adataira van szükségünk (pl.: Helyzet, Normál Vektor, Tangens Vektor, Bitangens Vektor, Vertex Szín, Textúrakoordináta stb.). Ezeken az adatokon tudunk műveleteket végezni. Viszont ha nekiállunk Vertex Shader-t használni egy modellen, akkor a T&L egység már nem fogja a beállított mátrixokat „végrehajtani”, mivel maga a T&L egység ilyenkor le is áll. Tehát nekünk kell kézbe venni a dolgokat és a mátrixokat a vertexeken végrehajtani. Ezt szerencsére meg lehet oldani Vertex Shader-el, viszont felmerül a kérdés, hogy hogyan tudjuk a Vertex Shader-ben a mátrixokat használni mikor azokat nem tudjuk a vertex adatoknál lekérni. Szerencsére erre is van megoldás, a program, ami a Vertex Shader-t használja képes arra hogy speciális függvényekkel változókat adjon át a shader-nek, így simán át lehet már passzolni a mátrixokat is a szorzásokhoz. Tehát egy alap Vertex Shader annyit csinál hogy az átadott három mártixal (Világ, Nézeti és Projekciós) megszorozza a vertex pozícióját. De ez még csak a kezdet, innen már csak a képzeletünk (és a maximális utasítás szám) szab határt annak, hogy mit csinálunk a vertexek adataival. Ha kész vagyunk a vertex adatok számolásával akkor már csak ki kell választani hogy mit akarunk tovább küldeni.
Ezzel nagyjából végig is értünk a Vertex Shader-eken. Most következzen az érdekesebb és kissé bonyolultabb rész, a Pixel Shader. A Pixel Shader minden egyes pixelre lefut és végrehajtja a megadott műveleteket (mint ahogy azt a Vertex Shader is tette a vertexekre). És akkor itt most oszlassunk el egy tévhitet, ugyanis sokan hiszik azt, hogy a Pixel Shader a textúra képpontjain halad végig. Pedig nem így van. Eleve a textúra képpontjait nem pixelnek hanem texelnek hívjuk (pixel = picture element ; texel = texture element ). Tehát a Pixel Shader a képernyőre kerülő képpontokon fut végig, azoknak a színét számolja ki a textúrából vett minta és a megadott számítások alapján.
Itt már kevesebb adattal dolgozunk, csak az adott képponthoz tartozó textúrakoordinátát és ha van akkor vertex színt kapjuk meg. Ezek alapján tudunk a texturából mintát venni és azt tovább küldeni a képernyőre. És itt jön egy újabb kérdés: Akkor hogyan tudunk megvilágítást számolni Pixel Shader-ben, hiszen ahhoz kell az adott pont Normál Vektora.
Az egész egy kis trükkel megoldható. A trükk lényege az, hogy a Vertex Shader-ben fogjuk a Normál Vektort és textúrakoordinátának „álcázva” tovább küldjük feldolgozásra. Így már tudjuk használni a Pixel Shader-ben is a Normálokat. De ennek a módszernek van még egy igen kellemes előnye, mégpedig az, hogy raszterezéskor a videokártya lineáris interpolálással minden egyes ponthoz amit a Pixel Shader később kezelésbe vesz kiszámolja az adott textúra koordinátát a környező 3 vertex textúrakoordinátájából. Magyarul a háromszög felületén végigátlagolja a textúra koordinátákat annak függvényében hogy az adott pont milyen messze van az adott vertexektől. És mivel mi a Normál Vektort is textúra koordinátaként küldtük tovább az is szépen végigátlagolódik, lényegében minden egyes ponthoz kiszámolódik az adott Normál Vektor. Innen bár semmi akadálya annak hogy hogy megvilágítást számoljunk.
Ezzel körülbelül minden a cikkben felvetett kérdésre sikerült (remélem kielégítő) választ adni, remélem hasznát veszitek. Folytatások tervben, ha van rá igény akkor meg is írom őket.

TheProGamer

0 megjegyzés :

Megjegyzés küldése