OpenGL.Hu - IX. Rész

Textúrázás - 3.5 avagy könnyítsünk életünkön...

Ennek a cikknek elméletileg az lett volna a célja, hogy az előzőekben tanultakra építve most írunk egy multitexturing extension-t használó programot. Nos.... ez így is lesz, de kell egy kis kitérőt tennünk. Az eddigi levélhegyek alapján, amiket kaptam, úgy tűnik, azokat, akiket az OpenGL érdekel, nem feltétlenül tudja lekötni a Windows és a DLL-ek meg hasonlók mélyebb ismerete, ráadásul bőven vannak olyanok is, akik még eddig library fájlokkal sem dolgoztak soha életükben. Nos az Ő érdekükben fogunk most tenni egy kis kitérőt, mielőtt továbblépnénk.

OpenGL Extension... Muszáj így csinálni?

Az utóbbi hetekben azzal töltöttem el az időmet, hogy a levelekre reagálva megpróbáljam leegyszerűsíteni az OpenGL Extension-ök használatát. Nos, a megoldátst végül némi „hackelés” és egy freeware library jelentette. Az Interneten futottam össze az OglExt nevű ingyenes library-val, melynek pontosan ez a célja. A használata semmivel sem bonyolultabb, mint a GLUT-é vagy akármelyik dll+lib+header kobinációé. Adott tehát egy header file (OglExt.h), amit beillesztünk a programunkba az #include utasítás segítségével. Ezután adott egy DLL, amit a már megszokott módon elhelyezünk a Windows\System (vagy System32, XP/2000 esetén) könyvtárba. És végül a library tárgykód fájlja, amit a fordító .\lib könyvtárába kell tennünk. És hogy mit nyertünk ezzel? Az OpenGL 1.4-ig (ez a legújabb verzió) elérhető összes extension úgy használható, hogy meghívjuk a megfelelő függvényt, amelyet már az OglExt fog a videokártya driveréből kibányászni helyettünk.

Vegyünk egy példát! A multitextúrázáshoz eddig el kellett végeznünk az alábbi függvényhívásokat:

PFNGLMULTITEXCOORD1FARBPROC glMultiTexCoord1fARB = NULL;

PFNGLMULTITEXCOORD2FARBPROC glMultiTexCoord2fARB = NULL;

PFNGLACTIVETEXTUREARBPROC   glActiveTextureARB   = NULL;

glMultiTexCoord1fARB = (PFNGLMULTITEXCOORD1FARBPROC) wglGetProcAddress("glMultiTexCoord1fARB");

glMultiTexCoord2fARB = (PFNGLMULTITEXCOORD2FARBPROC) wglGetProcAddress("glMultiTexCoord2fARB");

glActiveTextureARB   = (PFNGLACTIVETEXTUREARBPROC)   wglGetProcAddress(  "glActiveTextureARB");

Nos, ezek az utasítások egy az egyben eltűntek és csak az alábbi egy sor kell helyettük, természetesen a programunk elejére:

#include "glext.h"

 

Az OglExt letölthető az alkotójának oldaláról, melynek címe:

http://www.julius.caesar.de/oglext/

Viszont, gondot jelenthet, hogy a program eredeti csomagjához nem tartozik .a fájl (ami ugye a .lib helyét foglalja el a DevC++ fordítónál. Összeállítottam tehát egy csomagot, amely a http://3dnation.uw.hu címen elérhető. Ez tartalmaz minden szükséges fájlt és egy néhány soros útmutatót a használatba vételhez.

És végül 4. Lássuk a példát!

Nos, gondolom sokan vágynak már erre a pillanatra. Vágjunk tehát bele. A multitextúrázás nem sokkal bonyolultabb az átlagos textúrázásnál (így már nem... J ), szóval a legutóbbi példánkat fogjuk most módosítani.

Első lépésként módosítsuk a LoadTextures függvényt, hogy ne csak azt az egy textúrát töltse be, amit eddig használtunk, hanem általában megadhassunk neki egy fájlnevet és egy texture ID-t, amit a fájlból létrehoz. Nos, eddig ugye statikusan a 0 volt ez az ID, hiszen egyetlen textúránk volt csupán. Most ezt a programon belül mindenhol texno-ra cseréljük, az eddig közvetlenül átadott fájlnevet pedig texname-re. Az új függvény-fejléc tehát így néz ki:

void LoadTexture(int texno, char * texname)

Ezzel a textúrák betöltését megoldottuk. A főprogramban az eddigi

LoadTextures();

sort a következő kettőre cseréltük:

LoadTexture(0,"textures\\metal.bmp");

LoadTexture(1,"textures\\light.bmp"); 

Hogyan használjuk ezeket a textúrákat? Először is: a RenderScene() függvényünkben volt egy sor, amely kijelölte, hogy az utána definiált poligonokra a 0 ID-jű textúrát „húzzuk rá”. Ez a sor a

glBindTexture(GL_TEXTURE_2D, texture[0]);

volt. Ezt most ki kell cserélnünk a következő sorokra:

glActiveTextureARB(GL_TEXTURE0_ARB);

            glEnable(GL_TEXTURE_2D);

            glBindTexture(GL_TEXTURE_2D,  texture[0]);

            glActiveTextureARB(GL_TEXTURE1_ARB);

            glEnable(GL_TEXTURE_2D);

            glBindTexture(GL_TEXTURE_2D,  texture[1]);

 

Elsőre feltűnhet, hogy ez gyakorlatilag három utasítás, amit mind a két textúrára el kell végezni, hiszen ugyanúgy rá fogjuk húzni őket ugyanarra a poligonra. Az első utasítás azt csinálja, hogy kijelöli, hogy az engedélyezett multitextúra-rétegek közül a 0. az, amit aktuálissá akarunk most tenni. A második sorban engedélyezzük a textúrázást ennek felhasználásával. A harmadik pedig már ismerős. Hozzáteszem, hogy ha csak egyetlen textúra-réteget használunk, akkor az első két sor feleslegessé válik, hiszen a 0. lesz az alapértelmezett réteg, a textúrázást pedig engedélyeztük valahol a program inicializációs részében. Tehát mondhatjuk, hogy a multitextúrázás a normál texture-mapping általánosítása.

a ez megvan, már csak az van, hogy megnézzük, hogyan jelölünk ki textúra-koordinátákat multitexturing esetén. Nem muszáj ugyanis, hogy a két (vagy több) textúra ugyanúgy helyezkedjen el a poligonunk felületén. Mi most az egyszerűség kedvéért mégis ezt tesszük. A következő sorral adtuk meg eddig a textúra-koorinátákat:

            glTexCoord2f( x, y );

Most ezt a következőre kell lecserélnünk:

glMultiTexCoord2fARB(GL_TEXTURE0_ARB,x, y);           

            glMultiTexCoord2fARB(GL_TEXTURE1_ARB,x, y);

Az előbbi új utasítások logikáját használva ez a kettő is ugyanazt csinálja, csak külön-külön az egyes textúrákra. Annyiban különbözik a glTexCoord2f() utasítástól, hogy megadhatjuk, melyik textúra-rétegnek jelöljük ki a koordinátáit.

észen is lennénk! A dolognak működnie kell, feltéve, hogy a videokártya támogatja a multitexturing használatát. Erről könnyen meggyőződhetünk az alábbi (szintén az OglExt-re épülő) sorral:

if (glexExtensionsSupported("GL_ARB_multitexture") == GL_FALSE) return;

Ezzel az alkalommal már egy kicsit közelebb kerültünk a 3D játékokban használt technikákhoz, a következő részben pedig egy még látványosabb dolgot próbálunk ki. Hogy mit? Legyen meglepetés! J

Továbbra is várok mindenféle kommentárt, kérdést, melyekre szivesen válaszolok is!

 Merczel László - laszlo.merczel@mailbox.hu