Textúrázás
1. Kezdjünk új OpenGL projektet, de üres main.cpp helyett ezzel a file-lal!
2. Először saját, memóriában létrehozott textúrával próbáljuk ki a textúrázást! Ehhez adjuk meg a következő függvényt és globális változót:
GLuint checker; void loadGenTexture() { unsigned char tex[256][256][3]; for (int i=0; i<256; ++i) for (int j=0; j<256; ++j) { if ( i == 0 ) { // elso sor tex[i][j][0] = 0; tex[i][j][1] = 255; tex[i][j][2] = 0; } else if ( j == 0 ) { // elso oszlpo tex[i][j][0] = 0; tex[i][j][1] = 0; tex[i][j][2] = 255; } else tex[i][j][0] = tex[i][j][1] = tex[i][j][2] = ((i/16%2) ^ (j/16%2)) * 255; } glGenTextures(1, &checker); glBindTexture(GL_TEXTURE_2D, checker); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 256, 256, 0, GL_RGB, GL_UNSIGNED_BYTE, tex); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); }
A tex változóban hozunk létre egy 256x256-os képet, minden képponthoz három byte-nyi RGB adat tartozik. A kép egy 16x16-os sakktábla lesz, bal oldalán egy kék, tetején egy zöld csíkkal. A bal felső sarkot egy piros pont jelzi.
Ahhoz, hogy ezt a képet textúraként tudjuk használni, először egy új textúra nevet kell az OpenGL-től kérnünk (ami gyakorlatilag csak egy szám), amivel a továbbiakban erre a textúrára tudunk hivatkozni. Ezt fogjuk a checker változóban tárolni, és a glGenTextures függvény segítségével generáltatjuk. Ezzel egyszerre akár több textúra nevet is lehet generáltatni, amiket a paraméterként kapott címre menti.
Az aktuálisan használt textúrát a glBindTexture függvénnyel adhatjuk meg. Ennek első paramétere, hogy milyen cél textúráról van szó, mi csak a GL_TEXTURE_2D típust fogjuk használni. Második paramétere a használni kívánt textúra neve.
A képadatok betöltését a glTexImage2D függvény végzi. Itt a negyedik és az ötödik paraméter adja meg a kép szélességét és magasságát, amik régi OpenGL verziókban csak kettő-hatvány értékűek lehetnek.
A glTexParameter az első paramétereként megadott cél textúra viselkedése állítható. A lehetséges paraméterek listája a függvény leírásánál megtalálható, a fontosabbak:
- GL_TEXTURE_MIN_FILTER, ami arra az esetre adja meg a szűrés módját, ha egyetlen képpont mérete nagyobb, mint egy textúra pont. Ennek lehetséges értékei: GL_NEAREST, GL_LINEAR, GL_NEAREST_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR, GL_LINEAR_MIPMAP_LINEAR. A MIPMAP-es filterek mipmap-et tartalmazó textúrát várnak, ami esetünkben nincs meg.
- GL_TEXTURE_MAG_FILTER, ami az előzőnek fordítottja: szűrés módja abban az esetbe, ha egy képpont egy textúra pontot, vagy egy textúra pontnak csak egy részlét fedi le. Ennek lehetséges értékei: GL_NEAREST, GL_LINEAR.
- GL_TEXTURE_WRAP_S, GL_TEXTURE_WRAP_T és GL_TEXTURE_WRAP_R: megadja az egyes textúra dimenziók
mentén a [0,1] intervallumon kívüleső textúra-koordináták
kezelését. Lehetséges értekei, a DirectX hasonló beállításához
hasonlóan: GL_CLAMP,
GL_CLAMP_TO_BORDER, GL_CLAMP_TO_EDGE, GL_MIRRORED_REPEAT vagy
GL_REPEAT.
- GL_TEXTURE_BORDER_COLOR, ami egy RGBA négyessel adja meg a textúra keretének a színét.
3. Ezt a függvényt hívjuk meg main-ben, és engedélyezzük a textúrák használatát:
//... glutMouseFunc(mouseClick); glutMotionFunc(mouseMove); loadGenTexture(); glEnable(GL_TEXTURE_2D); glutMainLoop(); return 0; }
4. Ahhoz, hogy ez meg is jelenjen a modellen, a csúcspontokhoz textúra-koordinátákat kell megadnunk:
void display(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); cam.setView(); glBegin(GL_QUADS); glTexCoord2f(0, 1); glVertex3f(-1,-1, 0); glTexCoord2f(0, 0); glVertex3f(-1, 1, 0); glTexCoord2f(1, 0); glVertex3f( 1, 1, 0); glTexCoord2f(1, 1); glVertex3f( 1,-1, 0); glEnd(); glutSwapBuffers(); }
Feladatok:
a) Próbáld ki a GL_TEXTURE_MIN_FILTER és a GL_TEXTURE_MAG_FILTER más beállításait is!
b) Különböző, 0-nál kisebb és 1-nél nagyobb textúra koordináták mellett próbáld ki a GL_TEXTURE_WRAP_S és GL_TEXTURE_WRAP_T változtatásának a hatását!
Képek betöltése file-ból
1. Se az OpenGL se a GLUT nem támogatja képfile-ok betöltését, ezért ehhez külön könyvtárra van szükségünk.
Az órán a FreeImage nevű könyvtárt fogjuk használni. Az ehhez szükséges file-ok letölthetők innen. Ezeket a projekt könyvtárába kell másolni. A projekt beállításoknál meg kell adni a következőt:
- Project\____ Properties...
- Linker\Input
- Additional Dependencies: FreeImage.lib
A programunkban pedig include-olni kell a FreeImage.h header-t.
2. A következő függvénnyel tölthetünk be egy képet textúrába, és a textúra nevét kapjuk meg visszatérési értékként:
GLuint textureFromFile(const char* filename) { FREE_IMAGE_FORMAT fileFormat = FIF_UNKNOWN; FIBITMAP *image(0); BYTE* bits(0); unsigned int width(0), height(0); fileFormat = FreeImage_GetFileType(filename, 0); image = FreeImage_Load(fileFormat, filename); if(!image) return 0; FreeImage_FlipVertical(image); bits = FreeImage_GetBits(image); width = FreeImage_GetWidth(image); height = FreeImage_GetHeight(image); GLuint tex; glGenTextures(1, &tex); glBindTexture(GL_TEXTURE_2D, tex); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, bits); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); FreeImage_Unload(image); return tex; }
Feladat:
a) A függvény segítségével tölts be egy képet file-ból!
b) Hozz létre újabb objektumokat vagy a meglévőt rajzold ki többször, és jelenítsd meg őket különböző textúrákkal!