Hirdetés

Alkalmazásfejlesztés badára: Textúrázás

Bevezető

Az előző néhány bejegyzésben láttuk, hogy hogyan építhetünk fel objektumokat és azokhoz hogyan rendelhetünk különféle anyagtulajdonságokat. Azonban ha realizmusra törekszünk, egy komplex jelenet felépítése óriási munkát jelentene, gondoljunk csak egy csempézett falra vagy egy hajópadlóra. Itt jön képbe a textúrázás.

Tex-tor-túra

Kezdetben a textúra nem volt más, mint egy kétdimenziós tömb, melynek minden pontja az adott pontbeli szín koordinátáit tartalmazta (körülbelül mint egy bitmap formátumú kép (.bmp), a neve is hasonló: bittérképes textúra). Később megjelentek összetettebb textúrázási módszerek is, például a procedurális textúrázás, illetve a 3D textúrák. Bár az OpenGL-ben a bittérképes módszer található meg, pár szót ejtenék a másik kettőről is. Előbbi lényege, hogy a textúránkat olyan módszerekkel generáljuk, melyek különféle zajokat adnak a kapott bittérképhez, például fraktál- vagy turbulencia-alapú zajokat. Ezek hasonlítanak a természetben előforduló “zajokra”, így egy igen realisztikus képet kapunk, amely minden újra-generáláskor egy kicsit változik. Ezzel a módszerrel például fa, szikla, gránit és márvány anyagokat szokás generálni. A másik módszer, a háromdimenziós textúrázás esetén n darab (ahol n kettő hatványa) kétdimenziós textúránk van, és mindig a mélységtől függ, melyiket használjuk.

De térjünk is vissza a bittérképes textúrázáshoz! Mint írtam, egy kétdimenziós bittérképpel ábrázolható, egy kitétel van: az oldalak hosszának kettő hatványának kell lennie. Az algoritmusunk lényege, hogy a Res folderben elhelyezett .bmp kiterjesztésű képből generálunk textúrát.

Hárd kód

Mint minden OpenGL funkció használatához, a textúrázáshoz is be kell billentenünk egy engedélyező bitet az inicializáló kódban a glEnable(GL_TEXTURE_2D) segítségével. Következő lépés a textúra beolvasása. Ezt érdemes külön függvényben megtenni, és csak egyszer meghívni az init() résznél, hiszen maga a kép változatlan marad, nincs szükség arra, hogy  minden egyes újrarajzolásnál újrageneráljuk. Először be kell olvasnunk a képünket egy bitmapbe egy Osp::Media::Image objektum segítségével, majd ki kell szednünk az egyes pixelek színét. Ez egy kicsit trükkösen működik: először kirakjuk a bitmapet egy ByteBuffer objektumba a EncodeToBufferN függvénnyel (itt meg kell adnunk az elérési utat, valamint a képkódolási algoritmust), majd az első 54 byte-ot kihagyva (egy bitmapnek ekkora a header része, ezt nem kell beolvasnunk) átmásoljuk egy byte tömbbe.

Ezzel még nem vagyunk készen, a bmp egyik kódolási tulajdonsága miatt (BGR színsorrend) fel kell cserélnünk a vörös és kék koordinátákat. Készen vagyunk a szín-tömbbel, rendeljük hát hozzá egy textúrához!

Először tudassuk az OpenGL-lel ezen szándékunkat a glGenTextures segítségével, majd kössük hozzá a generálandó textúrát a változónkhoz (glBindTexture). Jöhet maga a generálás, ehhez a glTexImage2D függvényt fogjuk használni, amelynek 9 bemenő paramétert kell megadnunk: textúra típusa (GL_TEXTURE_2D), részletességi szint (jelen esetben 0, mipmap készítéskor kell hozzányúlni), belső formátum (jelen esetben GL_RGB), szélesség és hosszúság (ezt a változót lekérhetjük a bitmaptől is, de ügyeljünk a kettő hatványokra, érdemes a képet átméretezni), keret szélessége (0 vagy 1 lehet), pixelformátum (GL_RGB), a színeket tartalmazó tömb típusa (GL_UNSIGNED_BYTE) valamint a tömb neve. Ha ezzel megvagyunk, a glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN/MAG_FILTER, GL_LINEAR) segítségével állítsunk be linear filteringet, majd a glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S/T, GL_REPEAT) segítségével az ismétlést (azaz ha nagyobb az objektumunk a kép méreténél, ne nyújtsa a képet, hanem ismételje).

Ez után már csak engedélyezni kell a textúrarajzolást (glEnableClientState(GL_TEXTURE_COORD_ARRAY)) és a környezeti paramétereket a glTexEnvi segítségével. Utóbbi azt mondja meg, hogy hogyan viselkedjen a textúránk, ha nem négyzet alakú poligonra húzzuk rá. Valamint hozzá kell rendelni egy, a textúrakoordinátákat tartalmazó tömböt. Ennek a lényege, hogy a képünk négy pontját megfeleltessük a paralelogrammánk négy pontjával, így rendeli hozzá a textúrát az objektumhoz az OpenGL. Készen vagyunk, rajzoljunk is egyet!

Alternatív módszer: amennyiben nem akarjuk képből beolvasni a textúráinkat, megadhatjuk az egyes pontok színét kézzel is, a közeljövőben erről is lesz egy bejegyzés. Bizonyos képszerkesztő programok, például a Gimp is képes a megadott képből kiírni pontról pontra a színeket egy fileba, ezt utána bemásolva egy GLuint tömbbe meg is kapjuk a textúránkat.

A sample_code.cpp tartalmazza azt a snippetet, amellyel a több textúrát tartalmazó kép kirajzolható. A kód, illetve a képek természetesen ismét letölthetők az előbbi linkre kattintva.

holdmester

Azóta történt

Előzmények