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.
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.
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!