Teksturowanie Oprogramowanie i wykorzystanie stacji roboczych Wykład 10 Dr inż. Tomasz Olas olas@icis.pcz.pl Instytut Informatyki Teoretycznej i Stosowanej Politechnika Częstochowska Teksturowanie jest to nakładanie bitmapy na obiekt, włacznie z korekta perspektywy. OpenGL już od wersji 1.0 zawiera pełny zestaw funkcji realizujacych nakładanie, filtrowanie i przekształcanie tekstur. Rodzaje tekstur: jednowymiarowe (1D), dwuwymiarowe (2D), trójwymiarowe (wolumeryczne), sześcienne (kubiczne). Tekstury 1/32 Proces nakładania tekstury Wykład 10 p Tekstura jest zbiorem pixeli (texeli), w przypadku 2D jest tablica dwuwymiarowa. W OpenGL szerokość wysokość i głębia tekstury musza być potęgami dwójki. Poszczególne piksele tekstury nazywa się texelami. 1. Utworzenie obiektu tekstury. 2. Określenie w jaki sposób tekstura ma być odwzorowana na poszczególne punkty. 3. Właczenie mapowania tekstur. 4. Renderowanie sceny uwzględniajace zarówno współrzędne obiektów, jak również odwzorowanie tekstury. 3/32 Wykład 10 p
Utworzenie obiektu tekstury Definiowanie tekstur 2D (I) Utworzenie obiektu tekstury 2D polega na: Wygenerowaniu lub wczytaniu tablicy reprezentujacej poszczególne texele tworzonej tekstury. Zdefiniowaniu tekstury w OpenGL poprzez wywołanie funkcji glteximage2d z parametrami charakteryzujacymi tworzona teksturę. W OpenGL do definiowania dwuwymiarowych tekstur służy funkcja glteximage2d: void glteximage2d(glenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels); target - GL_TEXTURE_2D. level - poziom szczegółów mipmapy. Jeśli nie sa używane mipmapy zwykle wynosi zero. internalformat - ilość komponentów koloru, od 1 do 4. width - szerokość obrazu tekstury - musi być potęga liczby 2 lub być zgodna ze wzorem 2 n + 2 border. height - wysokość obrazu tekstury - musi być potęga liczby 2 lub być zgodna ze wzorem 2 m + 2 border. border - szerokość ramki dookoła obrazu tekstury (0 lub 1). lub 2. Definiowanie tekstur 2D (II) 5/32 Definiowanie tekstur 2D - Qt (I) Wykład 10 p void glteximage2d(glenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels); format - format danych pikseli ( GL_COLOR_INDEX, GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA, GL_RGB, GL_RGBA, GL_LUMINANCE, GL_ALPHA_LUMINANCE). type - typ danych dla wartości pikseli. pixels - dane pikseli. Statyczna metoda klasy QGLWidget converttoglformat przekształca obiekt klasy QImage do postaci wymaganej przez funkcje glteximage2d z biblioteki Qt. QImage QGLWidget::convertToGLFormat (const QImage & img) [static] Zwracana mapa bitowa nie może być używana jako standardowy obiekt klasy QImage, ale moga być wykorzystywane metody width, height i bits Powyższa metoda dokonuje jedynie konwersji poszczególnych pikseli, nie jest dokonywana zmiana rozmiaru bitmapy - musi ona mieć odpowiednie rozmiary przed dokonaniem konwersji. 7/32 Wykład 10 p
Definiowanie tekstur 2D - Qt (II) Paramety obrazu tekstury (I) QImage tex1, buf; if (!buf.load("sky.bmp")) qdebug("cannot open image file"); else tex1 = QGLWidget::convertToGLFormat(buf); glteximage2d(gl_texture_2d, 0, GL_RGBA, tex1.width(), tex1.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, tex1.bits()); gltexparameter[if](glenum target, GLenum pname, GLfloat param); gltexparameter[if]v(glenum target, GLenum pname, GLfloat *param); target - musi to być GL_TEXTURE_1D lub GL_TEXTURE_2D. pname - określa parametr tekstury, który jest ustawiany: GL_TEXTURE_MIN_FILTER - określa metodę lub filtr stosowany przy zmniejszaniu tekstury. Wartościa param może być: GL_NEAREST - filtrowanie najbliższy sasiad - pobierany jest najbliższy pixel obrazu tekstury, GL_LINEAR - liniowa interpolacja - przed narysowaniem czegokolwiek na ekranie wartości kolorów obrazu tekstury powinny zostać liniowo zinterpolowane, GL_NEAREST_MIPMAP_NEAREST - filtr mipmapy najbliższy sasiad, GL_NEAREST_MIPMAP_LINEAR - liniowo interpolowana mipmapa, GL_LINEAR_MIPMAP_NEAREST - liniowo interpolacja mipmap, GL_LINEAR_MIPMAP_LINEAR - liniowa interpolacja interpolowanych mipmap. Parametry obrazu tekstury (II) 9/32 Parametry obrazu tekstury (III) gltexparameter[if](glenum target, GLenum pname, GLfloat param); gltexparameter[if]v(glenum target, GLenum pname, GLfloat *param); pname cd: GL_TEXTURE_MAG_FILTER - określa metodę lub filtr stosowany przy powiększaniu tekstury. Wartościa param może być: GL_NEAREST - filtrowanie najbliższy sasiad, GL_LINEAR - liniowa interpolacja, GL_TEXTURE_WRAP_S - określa sposób traktowania współrzędnych S tekstury poza zakresem od 0.0 do 1.0. GL_TEXTURE_WRAP_T - określa sposób traktowania współrzędnych T tekstury poza zakresem od 0.0 do 1.0. GL_CLAMP GL_REPEAT GL_BORDER_COLOR - określa kolor ramki to tekstur bez ramki. filtr GL_NEAREST filtr GL_LINEAR 11/32
Parametry obrazu tekstury (IV) Parametry teksturowania Funkcja gltexenv ustawia parametry mapowania tekstury, sterujace sposobem nakładania obrazów tekstur na wielokaty: gltexenv{fi}(glenum target, GLenum pname, TYPE param); gltexenv{fi}v(glenum target, GLenum pname, TYPE *param); target - definiowane środowisko teksturowania - musi nim być GL_TEXTURE_ENV. pname - nazwa definiowanego parametru: GL_TEXTURE_ENV_MODE - określa tryb teksturowania. Parametr param może przyjmować wartości: GL_DECAL - obraz tekstury jest bezpośrednio nakładany na wielokat, GL_VERB - przed nałożeniem na wielokat, obraz tekstury jest mieszany z określonym kolorem (GL_TEXTURE_ENV_COLOR). GL_MODULATE - przed nałożeniem na wielokat, obraz tekstury jest mnożony przez istniejacy obraz w buforze ramki. GL_TEXTURE_ENV_COLOR - określa kolor do połaczenia z tekstura. W tym przypadku parametr param jest wskaźnikiem do wartości koloru RGBA. Współrzędne tekstury 13/32 Określanie współrzędnych tekstury Do określania współrzędnych tekstury dla wielokata, na który nakładamy teksture przeznaczona jest rodzina funkcji gltexcoord: gltexcoord1{dfis}(type s); gltexcoord1{dfis}v(type *s); gltexcoord2{dfis}(type s, TYPE t); gltexcoord2{dfis}v(type st); gltexcoord3{dfis}(type s, TYPE t, TYPE r); gltexcoord3{dfis}v(type *str); gltexcoord4{dfis}(type s, TYPE t, TYPE r, TYPE q); gltexcoord4{dfis}v(type strq); s - pozioma współrzędna obrazu tekstury, t - pionowa współrzędna obrazu tekstury, r - współrzędna głębokości obrazu tekstury, q - współrzędna czasu obrazu tekstury. 15/32
łaczenie i wyłaczenie mapowania tekstur Tekstury 2D - przykład (I) Właczenie mapowania tekstur 2D: glenable(gl_texture_2d); Wyłaczenie mapowania tekstur 2D: gldisable(gl_texture_2d); Analogicznie można właczać i wyłaczać mapowanie tekstur jednowymiarowych (GL_TEXTURE_1D) i trójwymiarowych (GL_TEXTURE_3D) const GLuint Texture = 1; QImage tex1, buf; if (!buf.load( "sky.bmp" ) ) qdebug("cannot open image file"); else tex1 = QGLWidget::convertToGLFormat( buf ); glnewlist(texture, GL_COMPILE); gltexparameteri(gl_texture_2d, GL_TEXTURE_MAG_FILTER, GL_LINEAR); gltexparameteri(gl_texture_2d, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glteximage2d(gl_texture_2d, 0, 3, tex1.width(), tex1.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, tex1.bits()); glendlist(); gltexenvi(gl_texture_env, GL_TEXTURE_ENV_MODE, GL_DECAL); Definiowanie tekstur 2D (III) 17/32 Definiowanie tekstur 2D (IV) glenable(gl_texture_2d); glcalllist(texture); glbegin(gl_quads); gltexcoord2f(1.0f, 0.0f); glvertex3f(-1.0f, -1.0f, 0.0f); gltexcoord2f(0.0f, 0.0f); glvertex3f(-1.0f, 1.0f, 0.0f); gltexcoord2f(0.0f, 1.0f); glvertex3f(1.0f, 1.0f, 0.0f); gltexcoord2f(1.0f, 1.0f); glvertex3f(1.0f, -1.0f, 0.0f); glend(); 19/32
Mipmapy (I) Mipmapy (II) Mipmapy umożliwiaja dobór obrazu tekstury w zależności od odległości od obserwatora. Tekstura taka zawiera w sobie wiele obrazów. Wybierany jest obraz tekstury najbliższy rozmiarowi wielokata na ekranie. Wielkość obrazów w mipmapie nie jest dowolna. Każdy następny stanowi 1/4 (1/2 1/2) rozmiaru poprzedniego obrazka. mipmapa o rozmiarze 128x128 będzie zawierała obrazki o rozmiarach 128x128, 64x64, 32x32, 16x16, 8x8, 4x4, 2x2 i 1x1, natomiast mipmapa o rozmiarze 64x16-64x16, 32x8, 16x4, 8x2, 4x1, 2x1, 1x1. Stosowanie mipmap poprawia wyglad renderowanej sceny oraz zazwyczaj przyspiesza proces renderowania. 21/32 Mipmapy - przykład Paramety obrazu - mipmapy QImage buf; buf.load("sky0.bmp"); QImage sky0 = QGLWidget::convertToGLFormat(buf); buf.load("sky1.bmp"); QImage sky1 = QGLWidget::convertToGLFormat(buf); buf.load("sky2.bmp"); QImage sky2 = QGLWidget::convertToGLFormat(buf); glnewlist(1, GL_COMPILE); gltexparameteri(gl_texture_2d, GL_TEXTURE_MAG_FILTER, GL_LINEAR); gltexparameteri(gl_texture_2d, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glteximage2d(gl_texture_2d, 0, 3, 4, 4, 0, GL_RGB, GL_UNSIGNED_BYTE, sky0.bits()); glteximage2d(gl_texture_2d, 1, 3, 2, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, sky1.bits()); glteximage2d(gl_texture_2d, 2, 3, 1, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, sky2.bits()); glendlist(); gltexparameter[if](glenum target, GLenum pname, GLfloat param); gltexparameter[if]v(glenum target, GLenum pname, GLfloat *param); dla: GL_TEXTURE_MIN_FILTER: GL_NEAREST_MIPMAP_NEAREST - wybiera mipmapę, której teksele maja rozmiar najbardziej zbliżony do pokrywanego piksela i używa filtra GL_NEAREST do wyznaczenia barwy piksela. GL_LINEAR_MIPMAP_NEAREST - podobnie jak wyżej, ale z użyciem kryterium GL_LINEAR. GL_NEAREST_MIPMAP_LINEAR - wybiera dwie mipmapy, których teksele maja rozmiar najbardziej zbliżony do pokrywanego piksela, następnie posługuje się filtrem GL_NEAREST do wyznaczenia teksela z każdej mipmapy. Ostateczna wartość elementu tekstury jest średnia ważona dwóch poprzednich tekseli. GL_LINEAR_MIPMAP_LINEAR - tak jak wyżej, lecz z zastosowaniem opcji GL_LINEAR. Ten filtr jest też zwany trójliniowym (Trilinear Filtering). 23/32
Mipmapy - filtrowanie Definiowanie tekstur 1D (I) W OpenGL do definiowania jednowymiarowych tekstur służy funkcja glteximage1d: void glteximage1d(glenum target, GLint level, GLint components, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels); target - musi być GL_TEXTURE_1D. level - poziom szczegółów mipmapy. Jeśli nie sa używane mipmapy zwykle wynosi zero. component - ilość komponentów koloru, od 1 do 4. width - szerokość obrazu tekstury - musi być potęga liczby 2 lub być zgodna ze wzorem 2 n + 2 border. border - szerokość ramki dookoła obrazu tekstury. Musi być 0, 1 lub 2. 25/32 Definiowanie tekstur 1D (II) Mapowanie tekstur 1D - przykład (I) void glteximage1d(glenum target, GLint level, GLint components, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels); format - format danych pikseli: GL_COLOR_INDEX - wartości wszystkich pikseli sa indeksami kolorów, GL_RED - wartości pikseli sa intensywnościami czerwieni, GL_GREEN - wartości pikseli sa intensywnościami zieleni, GL_BLUE - wartości pikseli sa intensywnościami niebieskiego, GL_ALPHA - wartości pikseli sa wartościami alfa, GL_RGB - wartości pikseli sa wartościami RGB, GL_RGBA - wartości pikseli sa wartościami RGBA, GL_LUMINANCE - wartości pikseli sa kolorami w skali szarości, GL_ALPHA_LUMINANCE - wartości pikseli sa wartościami alfa i kolorami w skali szarości. type - typ danych dla wartości pikseli. pixels - dane pikseli. const GLuint RainbowTexture = 1; static unsigned char tecza[8][3] = { {0x3f, 0x00, 0x3f}, {0x7f, 0x00, 0x7f}, {0xbf, 0x00, 0xbf}, {0x00, 0x00, 0xff}, {0x00, 0xff, 0x00}, {0xff, 0xff, 0x00}, {0xff, 0x7f, 0x00}, {0xff, 0x00, 0x00} }; glnewlist(rainbowtexture, GL_COMPILE); gltexparameteri(gl_texture_1d, GL_TEXTURE_MAG_FILTER, GL_LINEAR); gltexparameteri(gl_texture_1d, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glteximage1d(gl_texture_1d, 0, 3, 8, 0, GL_RGB, GL_UNSIGNED_BYTE, tecza); glendlist(); gltexenvi(gl_texture_env, GL_TEXTURE_ENV_MODE, GL_DECAL); 27/32
Mapowanie tekstur 1D - przykład (II) Mapowanie tekstur 1D - przykład (III) glenable(gl_texture_1d); glcalllist(rainbowtexture); glbegin(gl_quad_strip); for (double th = 0.0; th <= M_PI; th += (0.03125 * M_PI)) { // dolna krawędź tęczy x = cos(th) * 50.0; y = sin(th) * 50.0; z = -50.0; gltexcoord1f(0.0); glvertex3f(x, y, z); // górna krawędź tęczy x = cos(th) * 55.0; y = sin(th) * 55.0; z = -50.0; gltexcoord1f(1.0); glvertex3f(x, y, z); } glend(); Biblioteka GLU 29/32 Mipmapy - automatyczne generowanie Biblioteka GLU dodaje do biblioteki OpenGL dodatkowe funkcje wyższego poziomu. W skład biblioteki OpenGL wchodza między innymi: transformacje ze współrzędnych obiektu na współrzędne obserwatora i odwrotnie, wsparcie dla powierzchni NURBS, funkcje do podziału wielokatów na trójkaty, skalowanie rysunków 2D oraz tworzenie mipmap, dodatkowe funkcje wspierajace rzutowanie perspektywiczne i równoległe, zmiana pozycji kamery, wybór obiektów, funkcje do renderowania dysków, cylindrów oraz sfer, W bibliotece GLU istnieja funkcje do automatycznego generowania mipmap na podstawie pojedynczej tekstury. W przypadku jednowymiarowym jest to funkcja glubuild1dmipmap natomiast dla 2D funkcja realizujac a ta operacje jest funkcja glubuild2dmipmap. 31/32