« Tekstury, lekcja »
Rozdział 20. Tekstury jednowymiarowe, dwuwymiarowe i trójwymiarowe; tekstury zastępcze (proxy); tekstury sześcienne (kubiczne); tekstury głębi; kompresja tekstur; współrzędne, parametry i filtracja tekstur; mipmapy; obiekty i priorytety tekstur; parametry środowiska tesktur; wieloteksturowanie; automatyczne generowanie współrzędnych tekstur; dziesięć programów przykładowych, w tym mapy świetlne, mapowanie kubiczne, tekstury alfa, tekstura 3D, kompresja tekstur, drugorzędny kolor odbicia oraz wczytywanie plików OBJ. (lekcja)
Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?
Zarejestruj się!
Autor: Janusz Ganczarski
Kurs OpenGL, C++

Tekstury

[lekcja] Rozdział 20. Tekstury jednowymiarowe, dwuwymiarowe i trójwymiarowe; tekstury zastępcze (proxy); tekstury sześcienne (kubiczne); tekstury głębi; kompresja tekstur; współrzędne, parametry i filtracja tekstur; mipmapy; obiekty i priorytety tekstur; parametry środowiska tesktur; wieloteksturowanie; automatyczne generowanie współrzędnych tekstur; dziesięć programów przykładowych, w tym mapy świetlne, mapowanie kubiczne, tekstury alfa, tekstura 3D, kompresja tekstur, drugorzędny kolor odbicia oraz wczytywanie plików OBJ.
Teksturowanie to jeden z najważniejszych mechanizmów biblioteki OpenGL, który umożliwia znaczne zwiększenie realizmu generowanej grafiki. Mechanizmy związane z teksturowaniem są nie tylko bardzo obszerne, ale były także przedmiotem licznych modyfikacji. Stąd w poniższym opisie Czytelnik znajdzie częste odwołania do rozszerzeń biblioteki OpenGL. Dodajmy jeszcze, że teksturowanie jest dostępne tylko w trybie RGB(A).

Włączenie teksturowania

Włączenie i wyłącznie teksturowania wymaga wywołania funkcji glEnable/glDisable z jednym z następujących parametrów:
  • GL_TEXTURE_1D - tekstura jednowymiarowa,
  • GL_TEXTURE_2D - tekstura dwuwymiarowa,
  • GL_TEXTURE_3D - tekstura trójwymiarowa,
  • GL_TEXTURE_CUBE_MAP - tekstura sześcienna (kubiczna).
Tekstury jedno i dwuwymiarowe dostępne są w każdej wersji biblioteki OpenGL. Tekstury trójwymiarowe wprowadzono w wersji 1.2, a tekstury sześcienne w wersji 1.3. Wcześniej tekstury trójwymiarowe i tekstury sześcienne wprowadzono odpowiednio w rozszerzeniach EXT texture3D i ARB texture cube map (EXT texture cube map).
Standardowo biblioteka OpenGL w danej chwili obsługuje tylko jeden z wyżej wymienionych rodzajów tekstury. Przy jednoczesnym włączeniu więcej niż jednego rodzaju tekstury, aktywna pozostania tekstura o największej ilości wymiarów, a jeżeli jedną z włączonych tekstur jest tekstura kubiczna, to ona będzie teksturą aktywną. Pozostałe włączone tekstury nie będą dostępne. Z uwagi na czytelność programu jednoczesne włączanie więcej niż jednego rodzaju tekstury nie jest rozwiązaniem zalecanym.

Definiowanie tekstury

Zdefiniowanie jedno, dwu i trójwymiarowej tekstury umożliwiają następujące funkcje:
C/C++
void glTexImage1D( GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid * pixels )
void glTexImage2D( GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid * pixels )
void glTexImage3D( GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid * pixels )
Nieprzypadkowo funkcje te mają zbliżone zestawy parametrów. Wszystkie z nich ma bowiem takie same znaczenie, a większość identyczny zestaw wartości.

Parametr target

Parametr target określa rodzaj tworzonej tekstury i w przypadku funkcji glTexImage1D może przyjąć jedną z dwóch wartości:
  • GL_TEXTURE_1D - tekstura jednowymiarowa,
  • GL_PROXY_TEXTURE_1D - jednowymiarowa tekstura zastępcza (proxy).
W przypadku funkcji glTexImage2D parametr target przyjmuje jedną z poniższych wartości:
  • GL_TEXTURE_2D - tekstura dwuwymiarowa
  • GL_PROXY_TEXTURE_2D - dwuwymiarowa tekstura zastępcza,
  • GL_TEXTURE_CUBE_MAP_POSITIVE_X - tekstura sześcienna dla kierunku dodatnich wartości osi X,
  • GL_TEXTURE_CUBE_MAP_NEGATIVE_X - tekstura sześcienna dla kierunku ujemnych wartości osi X,
  • GL_TEXTURE_CUBE_MAP_POSITIVE_Y - tekstura sześcienna dla kierunku dodatnich wartości osi Y,
  • GL_TEXTURE_CUBE_MAP_NEGATIVE_Y - tekstura sześcienna dla kierunku ujemnych wartości osi Y,
  • GL_TEXTURE_CUBE_MAP_POSITIVE_Z - tekstura sześcienna dla kierunku dodatnich wartości osi Z,
  • GL_TEXTURE_CUBE_MAP_NEGATIVE_Z - tekstura sześcienna dla kierunku ujemnych wartości osi Z,
  • GL_PROXY_TEXTURE_CUBE_MAP - zastępcza tekstura sześcienna.
Także funkcja glTexImage3D posiada swój zestaw dopuszczalnych wartości parametru target:
  • GL_TEXTURE_3D - tekstura trójwymiarowa
  • GL_PROXY_TEXTURE_3D - trójwymiarowa tekstura zastępcza.

Parametr level

Drugi parametr level określa poziom kolejnej tworzonej mipmapy (pomniejszonej w stosunku do oryginału tekstury wykorzystywanej dla obrazu o mniejszej rozdzielczości). Wartość 0 oznacza poziom podstawowy tekstury, następne liczby całkowite określają kolejne poziomy mipmap. Mipmapy zostaną omówione w dalszej części niniejszego odcinka kursu OpenGL.

Parametr internalformat

Kolejny parametr internalformat określa wewnętrzny format danych tekstury. Parametr ten może w przypadku funkcji glTexImage1D i glTexImage2D przyjąć jedną z wartości: 1, 2, 3 i 4, które odpowiadają ilości składowych opisujących pojedynczy teksel (element tekstury).
W wersji 1.1 biblioteki OpenGL, a wcześniej w rozszerzeniu EXT texture, listę formatów danych tekstury rozszerzono o sześć formatów podstawowych opisanych następującymi stałymi:
  • GL_ALPHA - tylko składowe alfa (A),
  • GL_LUMINANCE - tylko składowe luminacji (jaskrawości); odpowiednik wartości 1,
  • GL_LUMINANCE_ALPHA - składowe luminacji i alfa; odpowiednik wartości 2,
  • GL_INTENSITY - tylko składowe natężenia (jasności),
  • GL_RGB - format RGB, odpowiednik wartości 3,
  • GL_RGBA - format RGBA, odpowiednik wartości 4.
W wersji 1.4 biblioteki OpenGL wprowadzono tzw. tekstury głębi (ang. depth texture) i jednocześnie dodano kolejny format podstawowy tekstury identyfikowany stałą: GL_DEPTH_COMPONENT. Wcześniej tekstury głębi opisywały rozszerzenia ARB depth texture i SGIX depth texture. Ten rodzaj tekstur dostępny jest wyłącznie dla tekstur jedno i dwuwymiarowych, włączając w to tekstury zastępcze o tych rozmiarach.
Tabela 1 przedstawia formaty podstawowe tekstur, używane do ich przechowywania składowe RGBA i głębi oraz określenie składowych wewnętrznych.

Tabela 1: Formaty podstawowe tekstur oraz składowe wewnętrzne

format podstawowywartości RGBA i głębiskładowe wewnętrzne
GL_ALPHAAA
GL_DEPTH_COMPONENTDepthD
GL_LUMINANCERL
GL_LUMINANCE_ALPHAR,AL A
GL_INTENSITYRI
GL_RGBR,G,BR,G,B
GL_RGBAR,G,B,AR,G,B,A
Do formatów podstawowych można także zaliczyć formaty GL_SRGB, GL_SRGB_ALPHA, GL_SLUMINANCE i GL_SLUMINANCE_ALPHA, które dotyczą tekstur sRGB, wprowadzonych w wersji 2.1 biblioteki OpenGL, a wcześniej w rozszerzeniu EXT texture sRGB. Wewnętrznie odpowiadają one odpowiednio formatom: GL_RGB, GL_RGBA, GL_LUMINANCE i GL_LUMINANCE_ALPHA.
Poza podstawowymi formatami tekstur specyfikacja biblioteki OpenGL od wersji 1.1 (a wcześniej rozszerzenie EXT texture) definiuje szereg formatów wewnętrznych, które w granicach formatu podstawowego określają ilość bitów użytych do przechowywania danych poszczególnych składowych tekseli. Zestawienie dostępnych formatów wewnętrznych zawiera tabela 2. Ich odpowiednie użycie może przyczynić się do zwiększenia szybkości działania programu, ale zazwyczaj odbędzie się to kosztem jakości renderingu.

Tabela 2: Wewnętrzne formaty tekstur oraz ilość bitów użytych do przechowywania składowych tekseli

format podstawowyRGBALID
GL_ALPHA4
GL_ALPHA8
GL_ALPHA12
GL_ALPHA16
4
8
12
16
GL_DEPTH_COMPONENT16
GL_DEPTH_COMPONENT24
GL_DEPTH_COMPONENT32
16
24
32
GL_LUMINANCE4
GL_LUMINANCE8
GL_LUMINANCE12
GL_LUMINANCE16
4
8
12
16
GL_LUMINANCE4_ALPHA4
GL_LUMINANCE6_ALPHA2
GL_LUMINANCE8_ALPHA8
GL_LUMINANCE12_ALPHA4
GL_LUMINANCE12_ALPHA12
GL_LUMINANCE16_ALPHA16
4
2
8
4
12
16
4
6
8
12
12
16
GL_INTENSITY4
GL_INTENSITY8
GL_INTENSITY12
GL_INTENSITY16
4
8
12
16
GL_R3_G3_B2
GL_RGB4
GL_RGB5
GL_RGB8
GL_RGB10
GL_RGB12
GL_RGB16
3
4
5
8
10
12
16
3
4
5
8
10
12
16
2
4
5
8
10
12
16
GL_RGBA2
GL_RGBA4
GL_RGB5_A1
GL_RGBA8
GL_RGB10_A2
GL_RGBA12
GL_RGBA16
2
4
5
8
10
12
16
2
4
5
8
10
12
16
2
4
5
8
10
12
16
2
4
1
8
2
12
16
GL_SRGB8
GL_SRGB8_ALPHA8
GL_SLUMINANCE8
GL_SLUMINANCE8_ALPHA8
8
8

8
8

8
8


8

8


8
8
Dodajmy jeszcze, że stałe związane z teksturami głębi (GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT24 i GL_DEPTH_COMPONENT32) zostały wprowadzone w wersji 1.4 biblioteki OpenGL. Natomiast ostatnie 4 stałe wymienione w tabeli 2 dotyczą tekstur sRGB, które pojawiły się w wersji 2.1 biblioteki OpenGL, a wcześniej w rozszerzeniu EXT texture sRGB.

Parametry width, height i depth

Parametry width, height i depth określają odpowiednio szerokość, wysokość i głębokość tekstury wraz z obramowaniem. Ilość dostępnych wymiarów zależy oczywiście od rodzaju tekstury.
Każdy z wymiarów tekstury wyraża się liczbą całkowitą większą od zera, która do wersji 2.0 biblioteki OpenGL musiała być potęgą liczby 2 (bez szerokości obramowania). Obsługa tekstur o wymiarach różnych od potęgi liczby 2 została wcześniej wprowadzona w rozszerzeniu ARB texture non power of - two. Każdy z wymiarów tekstury może przyjmować wielkości niezależne od pozostałych.
Określenie maksymalnych wymiarów obsługiwanych tekstur specyfikacja OpenGL pozostawia implementacji. Wartość tę dla tekstur jedno i dwuwymiarowych oraz tekstur sześciennych można sprawdzić wywołując funkcję glGetIntegerv z parametrem GL_MAX_TEXTURE_SIZE. Natomiast ustalenie maksymalnych wymiarów tekstur trójwymiarowych wymaga wywołania tej samej funkcji z parametrem GL_MAX_3D_TEXTURE_SIZE.
Minimalne obsługiwane wymiary tekstury jedno i dwuwymiarowej oraz tekstury sześciennej wynoszą 64 teksele, a tekstury trójwymiarowej tylko 16 tekseli.

Parametr border

Kolejny parametr border określa szerokość obramowania tekstury. Może on przyjąć wartość 0, która oznacza brak obramowania lub wartość 1, która oznacza, że tekstura posiada obramowanie, a każdy z wymiarów tekstury jest powiększony od dwa dodatkowe teksele. Gdy tekstura posiada obramowanie także wielkości tekstury podawane w parametrach width, height i depth muszą uwzględniać teksele obramowania.

Parametr format

Parametr format określa format danych tekstury i przyjmuje takie same wartości jak parametr format opisanej wcześniej funkcji glDrawPixels: GL_COLOR_INDEX, GL_DEPTH_COMPONENT, GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA, GL_RGB, GL_RGBA, GL_BGR, GL_BGRA, GL_LUMINANCE oraz GL_LUMINANCE_ALPHA. Nie jest jedynie dostępny format GL_STENCIL_INDEX.

Parametr type

Także kolejny parametr type, określający format tekseli tekstury, przyjmuje identyczne wartości jak analogiczny parametr funkcji glDrawPixels: GL_UNSIGNED_BYTE, GL_BITMAP, GL_BYTE, GL_UNSIGNED_SHORT, GL_SHORT, GL_UNSIGNED_INT, GL_INT, GL_FLOAT, GL_UNSIGNED_BYTE_3_3_2, GL_UNSIGNED_BYTE_2_3_3_REV, GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT_5_6_5_REV, GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_SHORT_4_4_4_4_REV, GL_UNSIGNED_SHORT_5_5_5_1, GL_UNSIGNED_SHORT_1_5_5_5_REV, GL_UNSIGNED_INT_8_8_8_8, GL_UNSIGNED_INT_8_8_8_8_REV, GL_UNSIGNED_INT_10_10_10_2 oraz GL_UNSIGNED_INT_2_10_10_10_REV.
Obowiązują takie same jak w przypadku funkcji glDrawPixels ograniczenia co do łączenia wartości parametrów format i type.

Parametr pixels

Ostatni parametr pixels zawiera wskaźnik na dane tekstury. Dane te podlegają takim samym regułom ułożenia w pamięci jak dane map pikselowych i są regulowane przy użyciu przedstawionych wcześniej funkcji z grupy glPixelStore.

Kopiowanie tekstury z bufora kolorów

Alternatywnym sposobem utworzenia tekstur jedno i dwuwymiarowych jest wprowadzona w wersji 1.1 biblioteki OpenGL, a wcześniej w rozszerzeniu EXT copy texture, możliwość utworzenia tekstury z pikseli pobranych z bufora kolorów. Realizują to dwie poniższe funkcje:
C/C++
void glCopyTexImage1D( GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border )
void glCopyTexImage2D( GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border )
Parametry target, level, internalformat, width, height i border mają takie same znaczenie jak analogiczne parametry funkcji glTexImage1D i glTexImage2D oraz niemal identyczne dopuszczalne zakresy wartości. Parametr target funkcji glCopyTexImage1D może przyjąć wyłącznie wartość GL_TEXTURE_1D, a jedyną dopuszczalną wartością tego samego parametru funkcji glCopyTexImage2D jest GL_TEXTURE_2D. Dodatkowo z listy formatów wewnętrznych tekstury (parametr internalformat) nie są obsługiwane stałe 1, 2, 3 i 4. W wersji 1.3 OpenGL dodano obsługę tekstur sześciennych przez funkcję glCopyTexImage2D.
Parametry x i y określają współrzędne punktu w buforze kolorów, od którego mają być pobierane dane do tekstury. Współrzędne te odpowiadają lewemu dolnemu końcowi danych tekstury. Wartości składowych pikseli bufora koloru, których współrzędne będą położone poza bieżącym kontekstem renderingu, pozostaną niezdefiniowane.
Podczas kopiowania danych z bufora kolorów stosowane są wszystkie ustawienia transferu pikseli określane funkcjami z grupy glPixelStore i glPixelTransfer.
Piksele kopiowane są z bufora kolorów określonego prezentowanego już funkcją glReadBuffer. Ponieważ w trybie podwójnego buforowania domyślnie dane są pobierane z tylnego bufora, przed operacją kopiowania pikseli należy wywołać funkcję:
C/C++
void glFinish()
która spowoduje zakończenie wszystkich operacji renderujących wykonywanych przez OpenGL.

Zmiana części danych tekstury

Kolejną zmianą wprowadzoną w wersji 1.1 biblioteki OpenGL (pierwotnie zdefiniowaną w rozszerzeniu EXT subtexture) jest możliwość podmiany części danych tekseli już istniejącej tekstury jedno i dwuwymiarowej. W wersji 1.2 biblioteki, a wcześniej w rozszerzeniu EXT texture3D, możliwość tę poszerzono o tekstury trójwymiarowe. Zamianę danych tekstur realizują funkcje:
C/C++
void glTexSubImage1D( GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid * pixels )
void glTexSubImage2D( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid * pixels )
void glTexSubImage3D( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid * pixels )
Parametry target, level, format, type i pixels przyjmują takie same wartości jak analogiczne parametry funkcji glTexImage1D, glTexImage2D i glTexImage3D. Wyjątkiem jest parametr target, który może przyjmować tylko wartości GL_TEXTURE_1D, GL_TEXTURE_2D i GL_TEXTURE_1D (oczywiście wartość odpowiednią do funkcji).
Parametry xoffset, yoffset i zoffset określają przesunięcie (pozycję) teksela, wyrażoną w odpowiednich kierunkach tekstury, od którego nastąpi wymiana danych bieżącej tekstury. Natomiast width, height i depth wyznaczają ilość wymienianych tekseli tekstury. Zauważmy, że obecność parametru level pozwala także na zamianę danych dowolnie wybranego poziomu mipmapy tekstury.
Analogicznie do opisywanych wcześniej funkcji glCopyTexImage1D i glCopyTexImage2D w wersji 1.1 biblioteki OpenGL oraz w rozszerzeniu EXT copy texture dodano możliwość podmiany części danych tekstury poprzez kopiowanie danych z bufora kolorów. Służą do tego funkcje:
C/C++
void glCopyTexSubImage1D( GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width )
void glCopyTexSubImage2D( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height )
Ich parametry mają dokładnie takie same znaczenie jak odpowiadające im parametry funkcji glTexSubImage1D i glTexSubImage2D. Także i w przypadku tych funkcji podczas kopiowania danych z bufora kolorów stosowane są wszystkie ustawienia transferu pikseli określane przez funkcje z grupy glPixelStore i glPixelTransfer.
W wersji 1.2 biblioteki OpenGL (wcześniej także w rozszerzeniu EXT - copy texture) dodano jeszcze funkcję pozwalającą na zamianę części danych tekstury trójwymiarowej, przy czym podmianie podlegają dane jednego z obrazów tekstury:
C/C++
void glCopyTexSubImage3D( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height )
W stosunku do dwóch pierwszych funkcji z tej grupy, funkcja glCopyTexSubImage3D posiada dodatkowy parametr zoffset wskazujący dane którego z obrazów tekstury mają zostać zmienione.

Współrzędne tekstury

Współrzędne tekstur określają w jaki sposób tekstura nakładana jest na prymityw graficzny. Ogólnie współrzędna tekstury ma cztery składowe [s, t, r, q], gdzie s określa szerokość, t wysokość, a r głębokość tekstury. Ostatnia współrzędna to współczynnik skalowania współrzędnych tekstur, co oznacza, że mają one faktycznie wartości: s , t i r . Nazwy współrzędnych q q q tekstur wybrane zostały celowo, tak aby nie kolidowały z opisem współrzędnych wierzchołków.
Rysunek 1 przedstawia oś współrzędnej s dla tekstury jednowymiarowej o szerokości 16 tekseli. Zauważmy, że opcjonalne teksele obramowania, zaznaczone na rysunku literami „B” nie są uwzględniane przy określaniu współrzędnych tekstury. Rysunki 2 i 3 przedstawiają układy współrzędnych dla tekstur dwu i trójwymiarowych. Dla zwiększenia czytelności zrezygnowano z rysowania tekseli obramowania.
Typowo wierzchołkom prymitywów przyporządkowywane są współrzędne z przedziału [0, 1], ale możliwe jest także podawanie współrzędnych spoza tego zakresu. Można w ten sposób uzyskać np. efekt wielokrotnego powielania tekstury na obiekcie.
Współrzędne tekstur definiuje się przez określeniem współrzędnych wierzchołków prymitywów, na takiej samej zasadzie jak kolory czy wektory normalne. Zatem dopóki bieżące współrzędne tekstury nie zostaną zmienione są stosowane dla każdego kolejnego wierzchołka. Początkowa i domyślna wartość współrzędnych tekstury wynosi (0, 0, 0, 1).
Rysunek 1. Współrzędna s tekstury jednowymiarowej
Rysunek 1. Współrzędna s tekstury jednowymiarowej
Rysunek 2. Współrzędne s i t tekstury dwuwymiarowej
Rysunek 2. Współrzędne s i t tekstury dwuwymiarowej
Współrzędne tekstury definiują funkcje z grupy glTexCoord. Występują one w 4 grupach różniących się ilością przekazywanych parametrów. W każdej z grup parametry mogą być określane liczbami całkowitymi lub zmiennoprzecinkowymi, a także mogą być przekazywane w postaci tablic. Parametry w postaci liczb całkowitych nie są w żaden sposób skalowane.
Ponieważ niezależnie od rodzaju stosowanej tekstury biblioteka OpenGL przechowuje zawsze wszystkie cztery współrzędne, w przypadku użycia funkcji definiującej mniejszą ich liczbę pozostałe współrzędne są uzupełniane wartościami współrzędnych domyślnych.
Do współrzędnych tekstur można używać takich samych operacji macierzowych jak w przypadku współrzędnych wierzchołków czy współrzędnych wektorów normalnych. W tym celu trzeba wybrać macierz tekstur podając stałą GL_TEXTURE jako parametr funkcji glMatrixMode. Przy operacjach na macierzach tekstur trzeba pamiętać, że minimalna głębokość stosu tych macierzy, określona w specyfikacji biblioteki OpenGL, wynosi zaledwie dwa.
Rysunek 3. Współrzędne s, t i r tekstury trójwymiarowej
Rysunek 3. Współrzędne s, t i r tekstury trójwymiarowej

Definiowanie współrzędnych s

C/C++
void glTexCoord1d( GLdouble s ) void glTexCoord1f( GLfloat s ) void glTexCoord1i( GLint s ) void glTexCoord1s( GLshort s )
void glTexCoord1dv( const GLdouble * v ) void glTexCoord1fv( const GLfloat * v ) void glTexCoord1iv( const GLint * v ) void glTexCoord1sv( const GLshort * v )

Definiowanie współrzędnych s i t

C/C++
void glTexCoord2d( GLdouble s, GLdouble t ) void glTexCoord2f( GLfloat s, GLfloat t ) void glTexCoord2i( GLint s, GLint t )
void glTexCoord2s( GLshort s, GLshort t )
void glTexCoord2dv( const GLdouble * v ) void glTexCoord2fv( const GLfloat * v ) void glTexCoord2iv( const GLint * v ) void glTexCoord2sv( const GLshort * v )

Definiowanie współrzędnych s, t i r

C/C++
void glTexCoord3d( GLdouble s, GLdouble t, GLdouble r ) void glTexCoord3f( GLfloat s, GLfloat t, GLfloat r ) void glTexCoord3i( GLint s, GLint t, GLint r )
void glTexCoord3s( GLshort s, GLshort t, GLshort r )
void glTexCoord3dv( const GLdouble * v ) void glTexCoord3fv( const GLfloat * v ) void glTexCoord3iv( const GLint * v ) void glTexCoord3sv( const GLshort * v )

Definiowanie współrzędnych s, t, r i q

C/C++
void glTexCoord4d( GLdouble s, GLdouble t, GLdouble r, GLdouble q )
void glTexCoord4f( GLfloat s, GLfloat t, GLfloat r, GLfloat q )
void glTexCoord4i( GLint s, GLint t, GLint r, GLint q )
void glTexCoord4s( GLshort s, GLshort t, GLshort r, GLshort q )
void glTexCoord4dv( const GLdouble * v ) void glTexCoord4fv( const GLfloat * v ) void glTexCoord4iv( const GLint * v ) void glTexCoord4sv( const GLshort * v )

Parametry tekstur

Parametry tekstur określają cztery funkcje z grupy glTexParameter:
C/C++
void glTexParameterf( GLenum target, GLenum pname, GLfloat param )
void glTexParameteri( GLenum target, GLenum pname, GLint param )
void glTexParameterfv( GLenum target, GLenum pname, const GLfloat * params )
void glTexParameteriv( GLenum target, GLenum pname, const GLint * params )
Parametr target oznacza rodzaj tekstury, dla której definiowane są parametry, i może przyjąć jedną ze znanych już wartości: GL_TEXTURE_1D, GL_TEXTURE_2D, GL_TEXTURE_3D lub GL_TEXTURE_CUBE_MAP.
Parametr pname określa rodzaj parametru tekstury przekazywanego bezpośrednio jako wartość param lub jak tablica wartości params. Dla wygody Czytelnika zestawienie wszystkich możliwych kombinacji wartości parametrów pname i param/params funkcji z grupy glTexParameter przedstawiono w tabeli 3. Znaczenie poszczególnych parametrów będzie omówione w dalszej części odcinka kursu.

Filtrowanie tekstur

W procesie nakładania tekstur rzadko zdarza się sytuacja, gdy pojedynczy teksel tekstury odpowiada dokładnie jednemu pikselowi okna (ekranu). W praktyce tekstura jest albo rozciągnięta albo ściśnięta w stosunku do swojej oryginalnej wielkości. Proces dopasowania tekstury do potrzebnych rozmiarów nazywamy filtrowaniem (ang. texture filtering).
Biblioteka OpenGL odrębnie ustala metodę filtrowania dla filtra powiększającego (ang. magnification filter) i filtra pomniejszającego (ang. minification filter). Odpowiada to wartościom GL_TEXTURE_MAG_FILTER i GL_TEXTURE_MIN_FILTER parametru pname funkcji z grupy glTexParameter.
Standardowo dostępne są dwie metody filtrowania tekstur. Pierwsza metoda to algorytm najbliższego sąsiada (GL_NEAREST), w którym pobierany jest najbliżej znajdujący się teksel. Metoda ta jest najszybsza, ale przy znacznym powiększeniu daje duże jednolite powierzchnie. Drugi algorytm to filtrowanie liniowe (GL_LINEAR), który oblicza wartość piksela poprzez interpolację liniową najbliższych tekseli tekstury. Efekty uzyskane przy użyciu filtrowania liniowego są zdecydowanie lepsze od algorytmu najbliższego sąsiada.
W przypadku, gdy korzystamy z mechanizmu mipmap biblioteka OpenGL udostępnia cztery dodatkowe metody filtrowania dla filtra pomniejszającego:
  • GL_NEAREST_MIPMAP_NEAREST - wybierana jest mipmapa najbardziej odpowiadająca rozmiarowi obiektu, dla której stosowany jest algorytm najbliższego sąsiada,
  • GL_NEAREST_MIPMAP_LINEAR - wykonywana jest liniowa interpolacja dwóch mipmap o rozmiarach najbardziej odpowiadających wymiarowi obiektu
    a następnie stosowany jest algorytm najbliższego sąsiada,
  • GL_LINEAR_MIPMAP_NEAREST - wybierana jest mipmapa najbardziej odpowiadająca rozmiarowi obiektu, dla której stosowany jest algorytm filtrowania liniowego,
  • GL_LINEAR_MIPMAP_LINEAR - wykonywana jest liniowa interpolacja dwóch mipmap o rozmiarach najbardziej odpowiadających wymiarowi obiektu a następnie stosowany jest algorytm filtrowania liniowego; metoda ta bywa często nazywana filtrowaniem trójliniowym.
Oczywiście przedstawione powyżej filtry mają wpływ na wydajność renderingu. Jednak dzięki szybkości obecnych akceleratorów graficznych nawet filtrowanie trójliniowe nie stanowi dużego problemu wydajnościowego.

Tabela 3: Zestawienie wartości funkcji z grupy glTexParameter

pnametypwartości param/params
GL_TEXTURE_WRAP_SGLintGL_CLAMP, GL_CLAMP_TO_EDGE, GL_REPEAT,
GL_CLAMP_TO_BORDER, GL_MIRRORED_REPEAT
GL_TEXTURE_WRAP_TGLintGL_CLAMP, GL_CLAMP_TO_EDGE, GL_REPEAT,
GL_CLAMP_TO_BORDER, GL_MIRRORED_REPEAT
GL_TEXTURE_WRAP_RGLintGL_CLAMP, GL_CLAMP_TO_EDGE, GL_REPEAT,
GL_CLAMP_TO_BORDER, GL_MIRRORED_REPEAT
GL_TEXTURE_MIN_FILTERGLintGL_NEAREST, GL_LINEAR,
GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR, GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR
GL_TEXTURE_MAG_FILTERGLintGL_NEAREST, GL_LINEAR
GL_TEXTURE_BORDER_COLOR4 × GLfloatwartości z przedziału [0, 1]
GL_TEXTURE_PRIORITYGLfloatwartość z przedziału [0, 1]
GL_TEXTURE_MIN_LODGLfloatdowolna wartość
GL_TEXTURE_MAX_LODGLfloatdowolna wartość
GL_TEXTURE_BASE_LEVELGLintdowolna liczba nieujemna
GL_TEXTURE_MAX_LEVELGLintdowolna liczba nieujemna
GL_TEXTURE_LOD_BIASGLfloatdowolna wartość
GL_DEPTH_TEXTURE_MODEGLenumGL_LUMINANCE, GL_INTENSITY, GL_ALPHA
GL_TEXTURE_COMPARE_MODEGLenumGL_NONE, GL_COMPARE_R_TO_TEXTURE
GL_TEXTURE_COMPARE_FUNCGLenumGL_LEQUAL, GL_GEQUAL, GL_LESS, GL_GREATER,
GL_EQUAL, GL_NOTEQUAL, GL_ALWAYS, GL_NEVER
GL_GENERATE_MIPMAPGLbooleanGL_TRUE lub GL_FALSE

Zawijanie tekstur

Przy opisie definiowania współrzędnych tekstur wspomnieliśmy, że ich wartości mogą przekraczać przedział [0, 1]. Sposób zawijania (bądź powielania) tekstury na obiekt określają w takich sytuacjach następujące wartości parametru pname funkcji z grupy glTexParameter:
  • GL_TEXTURE_WRAP_S - metoda zawijania tekstury w kierunku współrzędnej s,
  • GL_TEXTURE_WRAP_T - metoda zawijania tekstury w kierunku współrzędnej t,
  • GL_TEXTURE_WRAP_R - metoda zawijania tekstury w kierunku współrzędnej r.
Metody zawijania tekstury można regulować niezależnie dla każdej współrzędnej. Oczywiście ilość obsługiwanych współrzędnych zależy od wybranego rodzaju tekstury, określonego w parametrze target funkcji z grupy glTexParameter. Możliwe sposoby renderingu tekstury w takich sytuacjach definiują poniższe stałe:
  • GL_REPEAT - tekstura jest powielona na powierzchni renderowanego obiektu, przy każdym przekroczeniu wartości przedziału [0, 1] następuje powtórzenie tekstury; jest to wartość domyślna,
  • GL_CLAMP - wartości współrzędnej s są obcinane do przedziału [0, 1], a teksele brzegowe potrzebne do wyliczenia filtrowania liniowego pobierane są z obramowania tekstury lub koloru brzegu tekstury (stała GL_TEXTURE_BORDER_COLOR),
  • GL_CLAMP_TO_EDGE - wartości współrzędnej s są obcinane do przedziału [0, 1], przy obliczeniach filtrowania liniowego współrzędne wykraczające poza przedział [0, 1] (w tym także ewentualne teksele obramowania) nie są brane pod uwagę,
  • GL_CLAMP_TO_BORDER - wartości współrzędnej s są obcinane do przedziału [0, 1]; przy obliczeniach filtrowania liniowego, gdy współrzędne wykraczają poza przedział [0, 1], pod uwagę brane są tylko teksele brzegowe tekstury,
  • GL_MIRRORED_REPEAT - tekstura jest powielana na powierzchni renderowanego obiektu, ale każde przekroczenie przedziału [0, 1] powoduje powstanie efektu lustra w stosunku do poprzedniego przedziału.
Stała GL_CLAMP_TO_EDGE została wprowadzona w wersji 1.2 biblioteki OpenGL. Wcześniej stała ta była dostępna w rozszerzeniu SGIS texture - edge clamp.
Stała GL_CLAMP_TO_BORDER wprowadzona została w wersji 1.3 biblioteki OpenGL, a wcześniej w rozszerzeniach ARB texture border clamp i SGIS - texture border clamp.
Stałą GL_MIRRORED_REPEAT wprowadzono w wersji 1.4 biblioteki OpenGL, a wcześniej w rozszerzeniach ARB texture mirrored repeat i IBM texture mirrored repeat.
Odpowiednie użycie trybu GL_REPEAT pozwala na nakładanie niewielkich tzw. kafelkowych tekstur na duże obiekty. Umożliwia to redukcję ilości pamięci wymaganej przez teksturę. Zastosowanie właściwego trybu obcinającego ma szczególne znaczenie przy liniowym filtrowaniu tekstur, pozwala to bowiem na uniknięcie widocznych arfetaktów (zniekształceń) obrazu.

Kolor obramowania

Składowe RGBA koloru obramowania tekstury definiujemy, gdy wartość parametru pname wynosi GL_TEXTURE_BORDER_COLOR. Poszczególne składowe koloru obramowania przyjmują wartości z przedziału [0, 1]. Początkowo wartość składowych koloru obramowania wynosi (0, 0, 0, 0).

Mipmapy

Jak już wspomnieliśmy na początku mipmapa to tekstura pomniejszona w stosunku do oryginału, która wykorzystywana jest przy renderowaniu obiektów o mniejszej rozdzielczości. Każdy kolejny poziom mipmapy ma rozmiary dwukrotnie mniejsze od oryginału. Stąd najmniejsza możliwa mipmapa ma szerokość, wysokość i głębokość wynoszącą jeden teksel.
Mipmapy można wygenerować samodzielnie (np. korzystając z pakietu graficznego) i następnie załadować do programu korzystając z funkcji z grupy glTexImage, modyfikując odpowiednio parametr level. Pewną niedogodności jest domyślna konieczność generowania wszystkich możliwych poziomów mipmap, aż do mipmapy o szerokości jednego teksela. Można to zmienić definiując przy użyciu funkcji z grupy glTexParameter zakres ładowanych poziomów mipmap. Są to parametry:
  • GL_TEXTURE_BASE_LEVEL - podstawowy poziom ładowanej tekstury dla mechanizmu mipmapowania; wartość domyślna wynosi 0,
  • GL_TEXTURE_MAX_LEVEL - maksymalny poziom ładowanej tekstury dla mechanizmu mipmapowania; wartość domyślna wynosi 1000.
Określanie zakresu poziomów generowanych mipmap wprowadzono w wersji 1.2 biblioteki OpenGL, a wcześniej w rozszerzeniu SGIS texture lod.
Biblioteka OpenGL umożliwia także określenie poziomu szczegółowości mipmap (LOD - ang. Level Of Detail) oraz daje wpływ na działanie algorytmu doboru poziomu mipmap. Służą do tego następujące parametry funkcji z grupy glTexParameter:
  • GL_TEXTURE_MIN_LOD - minimalny poziom szczegółowości (LOD) mipmap; wartość domyślna wynosi -1000,
  • GL_TEXTURE_MAX_LOD - maksymalny poziom szczegółowości (LOD) mipmap; wartość domyślna wynosi 1000,
  • GL_TEXTURE_LOD_BIAS - przesunięcie poziomu szczegółowości (LOD) mipmap w stosunku do domyślnego algorytmu przyjętego w OpenGL; wartości ujemne tego parametru powodują przyjmowanie do renderingu wyższych poziomów mipmap (czyli tekstur o mniejszych rozmiarach) niż to wynika z rozmiarów obiektu; analogicznie wartości dodatnie powodują użycie do renderingu niższych poziomów mipmap niż wynikający z rozmiaru renderowanego obiektu; wartość domyślna wynosi 0, co oznacza standardowy algorytm doboru poziomu mipmap w bibliotece OpenGL.
Stałe GL_TEXTURE_MIN_LOD i GL_TEXTURE_MAX_LOD wprowadzono w wersji 1.2 biblioteki OpenGL, a wcześniej w wspominanym wyżej rozszerzeniu SGIS texture lod. Natomiast stała GL_TEXTURE_LOD_BIAS została przyjęta w wersji 1.4 biblioteki, przy czym wcześniej wprowadzono ją w rozszerzeniu EXT texture lod bias.
Ręczne tworzenie mipmap jest zajęciem dość uciążliwym. Stąd w bibliotece narzędziowej GLU wprowadzono kilka funkcji ułatwiających to zadanie. Pierwsza z nich umożliwia skalowanie obrazu zawartego w teksturze z wykorzystaniem prostego algorytmu interpolacji liniowej:
C/C++
GLint gluScaleImage( GLenum format, GLint widthin, GLint heightin, GLenum typein, const GLvoid * datain, GLint widthout, GLint heightout, GLenum typeout, GLvoid * dataout )
Parametr format określa format danych tekstury i przyjmuje takie same wartości jak analogiczny parametr funkcji z grupy glTexImage. Także parametry typein i typeout, określające format tekseli tekstury wejściowej i wyjściowej, przyjmują takie same wartości jak parametr type powyższych funkcji. Oczywiście obowiązują takie same jak w przypadku funkcji z grupy glTexImage ograniczenia co do łączenia wartości parametrów format i typein/typeout.
Pozostałe parametry określają rozmiary tekstury wejściowej (widthin i heightin) i tekstury wyjściowej (widthout i heightout) oraz zawierają wskaźniki na tablice z danymi obu tekstur (datain i dataout).
W przypadku pomyślnego wykonania skalowania obrazu funkcja zwraca wartość 0. W przeciwnym wypadku funkcja zwróci wartość kodu błędu.
Przypomnijmy, że do odczytu znaczenia kodów błędów biblioteki GLU stosuje się funkcję gluErrorString.
Kolejne trzy funkcje biblioteki GLU automatycznie realizują całą pracę związaną ze zdefiniowaniem tekstury i wszystkich poziomów mipmap:
C/C++
GLint gluBuild1DMipmaps( GLenum target, GLint internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid * data )
GLint gluBuild2DMipmaps( GLenum target, GLint components, GLint width, GLint height, GLenum format, GLenum type, const GLvoid * data )
GLint gluBuild3DMipmaps( GLenum target, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid * data )
Zauważmy, że lista parametrów funkcji powyższych funkcji niemal w całości odpowiada parametrom funkcji z grupy glTexImage. Brakuje jedynie parametrów level oraz border. Brak pierwszego z nich jest oczywisty, natomiast brak drugiego oznacza, że tekstura, dla której biblioteka GLU wygeneruje automatycznie mipmapy, nie może posiadać obramowania. Jeżeli rozmiary tekstury nie są potęgami liczby 2, tekstura zostanie automatycznie przeskalowana do wymiarów spełniających ten warunek.
W przypadku poprawnego wykonania funkcja zwraca wartość 0, w przeciwnym przypadku zwrócony zostanie kod błędu.
Ostatnimi funkcjami biblioteki GLU wspomagających generowanie mipmap są funkcje:
C/C++
GLint gluBuild1DMipmapLevels( GLenum target, GLint internalormat, GLsizei width, GLenum format, GLenum type, GLint level, GLint base, GLint max, const void * data )
GLint gluBuild2DMipmapLevels( GLenum target, GLint internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint level, GLint base, GLint max, const GLvoid * data )
GLint gluBuild3DMipmapLevels( GLenum target, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, GLint level, GLint base, GLint max, const GLvoid * data )
które w stosunku do funkcji gluBuild1DMipmaps, gluBuild2DMipmaps i gluBuild3DMipmaps różnią się dodaniem parametrów base i max określających początkowy i końcowy (maksymalny) poziom generowanych mipmap.
W przypadku poprawnego wykonania powyższe funkcje zwracają wartość 0, w przeciwnym przypadku zwrócony zostanie kod błędu.
Dodajmy jeszcze, że funkcje gluBuild1DMipmaps i gluBuild3DMipmapLevels zostały wprowadzone w wersji 1.3 biblioteki GLU, co oznacza, że nie są one standardowo dostępne w systemach rodziny Windows posiadających implementację wersji 1.2 tej biblioteki.
Korzystając z funkcji biblioteki GLU musimy pamiętać, że przy ich wykonywaniu wykorzystywany jest procesor komputera (CPU) a nie procesor karty graficznej (GPU). Stąd generowanie mipmap dla większych tekstur może okazać się czynnością czasochłonną.
Dopiero w wersji 1.4 biblioteki OpenGL wprowadzono, opracowany w rozszerzeniu SGIS generate mipmap, mechanizm automatycznego generowania poziomów mipmap. Włączenie techniki automatycznego generowania mipmap sprowadza się do użycia funkcji z grupy glTexParameter z parametrem pname o wartości GL_GENERATE_MIPMAP. Włączenie automatycznego generowanie mipmap wymaga podania w parametrze param/params wartość GL_TRUE. Analogicznie wyłączenie tego mechanizmu sprowadza się do przekazania GL_FALSE w powyższym parametrze.
Trzeba jeszcze dodać, że razem z mechanizmem automatycznego generowania mipmap dodano także wskazówkę renderingu GL_GENERATE_MIPMAP - HINT określającą jakość generowanych mipmap. Jej użycie wymaga wykorzystania opisywanej już funkcji glHint.

Obiekty tekstur

W wersji 1.1 biblioteki OpenGL, a wcześniej w rozszerzeniu EXT texture object, wprowadzono mechanizm obiektów tekstur. Pozwala to na zapamiętanie przez bibliotekę OpenGL kilku stanów tekstur (czyli danych tekstury wraz ze wszystkimi parametrami jej renderowania) i dowolne przełączanie się pomiędzy nimi.
Utworzenie wskazanej w parametrze n ilości unikatowych identyfikatorów
(nazw) tekstur realizuje funkcja:
C/C++
void glGenTextures( GLsizei n, GLuint * textures )
Numery identyfikatorów zwracane są w tablicy wskazywanej w parametrze textures. Oczywiście program musi zapewnić odpowiednią ilość miejsca w tablicy.
Utworzone identyfikatory tekstur trzeba dowiązać do stanu tekstury wywołując funkcję:
C/C++
void glBindTexture( GLenum target, GLuint texture )
której parametr target wskazuje rodzaj dowiązywanej tekstury (GL_TEXTURE_1D, GL_TEXTURE_2D lub GL_TEXTURE_3D), a parametr texture zawiera identyfikator dowiązywanej tekstury. Po użyciu funkcji glBindTexture wywołania funkcji związanych z ładowaniem tekstury i ustawianiem jej parametrów dotyczą aktualnie dowiązywanego obiektu tekstury. Funkcja glBindTexture służy także do przełączania się pomiędzy wybranymi teksturami.
W dowolnym czasie można sprawdzić czy dany identyfikator jest numerem tekstury. Służy do tego funkcja:
C/C++
GLboolean glIsTexture( GLuint texture )
która zwraca wartość GL_TRUE, gdy identyfikator texture jest numerem tekstury, i GL_FALSE w przeciwnym wypadku.
Niepotrzebne obiekty tekstur można usuwać celem zwolnienia wykorzystywanej przez nie pamięci. Służy do tego funkcja:
C/C++
void glDeleteTextures( GLsizei n, const GLuint * textures )
której parametr n określa ilość identyfikatorów tekstur zawartych w tablicy textures, które mają zostać usunięte. Jak nietrudno zauważyć parametry te dokładnie odpowiadają parametrom funkcji glGenTextures.

Priorytety tekstur

Jak wiadomo każda karta graficzna ma ograniczoną ilość pamięci. W momencie pisania tych słów karty typowe karty graficzne dysponowały pamięcią od 128 do 512 MB. Nie są to wielkości małe, ale jak uczy praktyka każdą ilość pamięci karty graficznej można wykorzystać. Tekstury umieszczone w pamięci karty graficznej nazywamy teksturami rezydentnymi.
Typowo implementacje biblioteki OpenGL umieszczając tekstury w pamięci karty graficznej kierują się częstotliwością ich używania określając na podstawie tego priorytet tekstury. Są to zazwyczaj algorytmy LRU (ang. Last Recently Used) lub MFU (ang. Most Frequently Used). Ponieważ nie w każdym przypadku powyższe algorytmy działają optymalnie w wersji 1.1 biblioteki OpenGL (razem z mechanizmem obiektów tekstur z rozszerzenia EXT texture object) wprowadzono mechanizmy pozwalające na ustawienia priorytetów tekstur.
Pierwsza z wprowadzonych funkcji umożliwia pobranie informacji o tym czy rezydentna jest grupa tekstur:
C/C++
GLboolean glAreTexturesResident( GLsizei n, const GLuint * textures, GLboolean * residences )
Parametr textures zwiera wskaźnik na tablicę z identyfikatorami badanej grupy tekstur, natomiast wynik zapytania zawiera tablica wskazywana w parametrze residences. Tablica ta zawiera wartości logiczne: GL_TRUE oznacza teksturę rezydentną, GL_FALSE teksturę nierezydentną. Ilość badanych tekstur, a tym samym wielkość obu powyższych tablic, określa parametr n.
Dodatkowo funkcja glAreTexturesResident zwraca wartość GL_TRUE jeżeli wszystkie badane tekstury są rezydentne. W przeciwnym wypadku funkcja zwróci wartość GL_FALSE, a sprawdzenie która tekstura nie jest rezydentna będzie wymagało przeglądu zawartości tablicy residences.
Druga funkcja pozwala na grupową zmianę wartości priorytetów tekstur, które są używane przez OpenGL:
C/C++
void glPrioritizeTextures( GLsizei n,
const GLuint * textures, const GLclampf * priorities )
Numery identyfikatorów tekstur i ich priorytety z przedziału [0, 1] zawierają odpowiednio tablice textures i priorities. Wielkość obu tablic określa parametr n.
Niski priorytet jest wskazówką dla OpenGL do usunięcia tekstury z pamięci karty graficznej. I przeciwnie, wysoki priorytet informuje bibliotekę, że dana tekstura powinna być rezydentna, nawet jeżeli nie jest często wykorzystywana.
Priorytet bieżącej tekstury można także zmienić korzystając z funkcji glTexParameter z parametrem pname równym GL_TEXTURE_PRIORITY. W tym wypadku obowiązuje oczywiście ten sam przedział wartości priorytetu, tj. [0, 1].
Sprawdzenie priorytetu bieżącej tekstury oraz pobranie informacji czy jest ona rezydentna umożliwiają funkcje z grupy glGetTexParameter z parametrem pname o wartości odpowiednio: GL_TEXTURE_PRIORITY i GL_TEXTURE_RESIDENT.

Parametry środowiska tekstur

Niezależnie od stanu parametrów tekstury, które można określać odrębnie dla każdego obiektu tekstury, wpływ na sposób renderingu danego rodzaju tekstur (jednostki teksturującej) mają parametry tzw. środowiska tekstur. Parametry te definiuje się przy użyciu poniższych funkcji:
C/C++
void glTexEnvf( GLenum target, GLenum pname, GLfloat param ) void glTexEnvi( GLenum target, GLenum pname, GLint param ) void glTexEnvfv( GLenum target, GLenum pname, const GLfloat * params )
void glTexEnviv( GLenum target, GLenum pname, const GLint * params )
Parametr target określa rodzaj modyfikowanego parametru środowiska tekstur i przyjmuje jedną z trzech wartości:
  • GL_TEXTURE_ENV - parametry mieszania kolorów obiektu (fragmentów) z tekselami tekstury,
  • GL_TEXTURE_FILTER_CONTROL - parametry filtrowania tekstur,
  • GL_POINT_SPRITE - parametry rasteryzacji sprajtów (duszków) punktowych (ang. point sprite).
Stała GL_TEXTURE_FILTER_CONTROL została wprowadzona w wersji 1.4 biblioteki OpenGL, a wcześniej w rozszerzeniu EXT texture lod bias. Natomiast stałą GL_POINT_SPRITE wprowadzono w wersji 2.0 biblioteki w oparciu o rozszerzenia ARB point sprite i NV point sprite.
Ponieważ ilość możliwych kombinacji wartości parametrów prezentowanych funkcji jest dość duża, dla wygody Czytelników wszystkie przedstawiliśmy w tabeli 4.

Środowisko GL_TEXTURE_ENV

Parametr pname określa nazwę modyfikowanego parametru środowiska tekstur. W przypadku, gdy parametr target przyjmuje wartość GL_TEXTURE_ENV, dopuszczalne są następujące wartości parametru pname: GL_TEXTURE_ENV_MODE, GL_TEXTURE_ENV_COLOR, GL_COMBINE_RGB, GL_COMBINE_ALPHA, GL_SRC0_RGB, GL_SRC1_RGB, GL_SRC2_RGB, GL_SRC0_ALPHA, GL_SRC1_ALPHA, GL_SRC2_ALPHA, GL_OPERAND0_RGB, GL_OPERAND1_RGB, GL_OPERAND2_RGB, GL_OPERAND0_ALPHA, GL_OPERAND1_ALPHA, GL_OPERAND2_ALPHA, GL_RGB_SCALE i GL_ALPHA_SCALE.
Stałe GL_SRC0_RGB, GL_SRC1_RGB, GL_SRC2_RGB, GL_SRC0_ALPHA, GL_SRC1_ALPHA i GL_SRC2_ALPHA zostały wprowadzone w wersji 1.3 biblioteki OpenGL, a wcześniej w rozszerzeniach ARB texture env combine i EXT - texture env combine. Jednak prezentowane nazwy tych stałych zostały ustalone dopiero w wersji 1.5 biblioteki. Pierwotne brzmiały one odpowiednio: GL_SOURCE0_RGB, GL_SOURCE1_RGB GL_SOURCE2_RGB, GL_SOURCE0_ALPHA, GL_SOURCE1_ALPHA i GL_SOURCE2_ALPHA.
Stałe GL_OPERAND0_RGB, GL_OPERAND1_RGB, GL_OPERAND2_RGB, GL_OPERAND0_ALPHA, GL_OPERAND1_ALPHA, GL_OPERAND2_ALPHA i GL_RGB_SCALE także zostały wprowadzone w wersji 1.3 biblioteki OpenGL, a wcześniej w rozszerzeniach ARB texture env combine i EXT texture env combine, przy czym ich nazwy nie były zmieniane.
Parametr GL_TEXTURE_ENV_MODE określa sposób mieszania składowych kolorów fragmentów ze składowymi koloru tekseli. Dopuszczalne są następujące tryby mieszania, zwane także funkcjami tekstury (ang. texture function):
  • GL_REPLACE - składowe tekseli zastępują składowe fragmentów,
  • GL_MODULATE - składowe tekseli są mnożone przy składowe fragmentów; jest to wartość domyślna,
  • GL_DECAL - składowe tekseli zastępują składowe fragmentów lub są mieszany z użyciem składowej alfa tekseli,
  • GL_BLEND - składowe koloru tekseli są mieszane z użyciem składowych koloru środowiska tekstur (parametr GL_TEXTURE_ENV_COLOR), natomiast składowe alfa tekseli są mnożone przez składowe alfa fragmentów,
  • GL_ADD - składowe koloru tekseli są dodawane do składowych koloru fragmentów, natomiast składowe alfa tekseli są mnożone przez składowe alfa fragmentów,
  • GL_COMBINE - tryb mieszania określany oddzielnie dla każdej jednostki teksturującej (opis dalej).

Tabela 4: Zestawienie wartości funkcji z grupy glTexEnv

targetpnamewartości param/params
GL_TEXTURE_ENVGL_TEXTURE_ENV_MODEGL_REPLACE, GL_MODULATE,
GL_DECAL, GL_BLEND,
GL_ADD, GL_COMBINE
GL_TEXTURE_ENV_COLORskładowe RGBA
GL_COMBINE_RGBGL_REPLACE, GL_MODULATE,
GL_ADD, GL_ADD_SIGNED,
GL_INTERPOLATE, GL_SUBTRACT,
GL_DOT3_RGB, GL_DOT3_RGBA
GL_COMBINE_ALPHAGL_REPLACE, GL_MODULATE,
GL_ADD, GL_ADD_SIGNED,
GL_INTERPOLATE, GL_SUBTRACT
GL_SRC0_RGB,
GL_SRC1_RGB,
GL_SRC2_RGB
GL_TEXTURE, GL_TEXTUREn,
GL_CONSTANT, GL_PREVIOUS,
GL_PRIMARY_COLOR
GL_SRC0_ALPHA,
GL_SRC1_ALPHA,
GL_SRC2_ALPHA
GL_TEXTURE, GL_TEXTUREn,
GL_CONSTANT, GL_PREVIOUS,
GL_PRIMARY_COLOR
GL_OPERAND0_RGB,
GL_OPERAND1_RGB,
GL_OPERAND2_RGB
GL_SRC_COLOR, GL_SRC_ALPHA
GL_ONE_MINUS_SRC_COLOR
GL_ONE_MINUS_SRC_ALPHA
GL_OPERAND0_ALPHA,
GL_OPERAND1_ALPHA,
GL_OPERAND2_ALPHA
GL_SRC_ALPHA,
GL_ONE_MINUS_SRC_ALPHA
GL_RGB_SCALEliczba zmiennoprzecinkowa
GL_ALPHA_SCALEliczba zmiennoprzecinkowa
GL_TEXTURE_FILTER_CONTROLGL_TEXTURE_LOD_BIASliczba zmiennoprzecinkowa
GL_POINT_SPRITEGL_COORD_REPLACEGL_TRUE, GL_FALSE
Tryb mieszania określony stałą GL_REPLACE został wprowadzony w wersji 1.1 biblioteki OpenGL, a wcześniej w rozszerzeniu EXT texture. Natomiast tryb mieszania reprezentowany przez stałą GL_ADD został wprowadzony w wersji 1.3 biblioteki OpenGL, a wcześniej był obsługiwany przez rozszerzenie ARB texture env add. Także w wersji 1.3 biblioteki OpenGL została wprowadzona stała GL_COMBINE, którą pierwotnie zdefiniowano w rozszerzeniach ARB texture env combine i EXT texture env combine.
Tabela 6 zawiera równania operacji wykonywanych przez wybrane funkcje tekstury. Cs i As oznaczają składowe koloru i alfa tekseli, Cp i Ap to składowe koloru i alfa fragmentów, natomiast wartości składowych koloru i alfa określone stałymi Cc i Ac, są składowymi koloru środowiska tekstur, wyznaczonymi są przy użyciu parametru GL_TEXTURE_ENV_COLOR. Początkowa wartość składowych koloru środowiska tekstur wynosi (0, 0, 0, 0).
W przypadku użycia trybu wieloteksturowania wynik operacji mieszania dla danej jednostki teksturującej jest przekazywany do następnej jednostki jako parametry Cp i Ap . Niezależnie od trybu teksturowania otrzymany wynik stanowi kolor podstawowy obiektu (fragmentu).
Interpretację składowych tekseli tekstury (Cs i As ) na składowe RGBA używane przez funkcje tekstur przedstawia tabela 5. Szczególną uwagę należy zwrócić na różnicę w traktowaniu składowej alfa w przypadku dwóch pozornie bardzo zbliżonych formatów podstawowych tj. GL_LUMINANCE i GL_INTENSITY oraz na użycie w razie potrzeby domyślnych wartości składowych RGBA.

Tabela 5: Formaty podstawowe tekstur i składowe koloru oraz alfa tekseli

format podstawowyCsAs
GL_ALPHA(0, 0, 0)A
GL_LUMINANCE(L, L, L)1
GL_LUMINANCE_ALPHA(L, L, L)A
GL_INTENSITY(I , I , I )I
GL_RGB(R, G, B)1
GL_RGBA(R, G, B)A
W przypadku wyboru mieszania odrębnie dla każdej jednostki teksturującej (tryb mieszania GL_COMBINE) do definiowania parametrów mieszania tekstur używa się także funkcji z grupy glTexEnv. Parametr GL_COMBINE_RGB określa funkcję mieszania dla składowych RGB tekseli, a parametr GL_COMBINE_ALPHA określa funkcję mieszania dla składowej alfa tekseli.

Tabela 6: Zestawienie funkcji mieszania składowych koloru obiektu ze składowymi koloru tekseli tekstury

Funkcje mieformat podstawowyGL_REPLACEGL_MODULATEGL_DECALGL_BLENDGL_ADD
GL_ALPHA
CpCp-CpCp
AsApAs-ApAsApAs
GL_LUMINANCE
(lub 1)
CsCpCs-Cp (1 − Cs ) + CcCsCp + Cs
ApAp-ApAp
GL_LUMINANCE_ALPHA
(lub 2)
CsCpCs-Cp (1 − Cs ) + CcCsCp + Cs
AsApAs-ApAsApAs
GL_INTENSITYCsCpCs-Cp (1 − Cs ) + CcCsCp + Cs
AsApAs-Ap (1 − As ) + AcAsApAs
GL_RGB
(lub 3)
CsCpCsCsCp (1 − Cs ) + CcCsCp + Cs
ApApApApAp
GL_RGBA
(lub 4)
CsCpCsCp (1 − As ) + Cs AsCp (1 − Cs ) + CcCsCp + Cs
AsApAsApApAsApAs
Funkcje mieszania dla składowych RGB i składowych alfa tekseli oraz odpowiadające im równania przedstawiają tabele 7 i 8.
W przypadku funkcji GL_DOT3_RGB i GL_DOT3_RGBA wynik równania jest skalarem i stanowi wartość odpowiednio każdej ze składowych RGB lub RGBA. Dla pozostałych funkcji mieszania obliczenia określone prezentowanymi w tabelach równaniami dokonywane są na każdej ze składowych tekseli. Dodajmy jeszcze, że dla funkcji GL_DOT3_RGB rezultat funkcji mieszania składowej alfa tekstury jest pomijany.

Tabela 7: Funkcje mieszania tekstur dla składowych RGB tekseli

GL_COMBINE_RGBrównanie mieszania
GL_REPLACEArg0
GL_MODULATEArg0 • Arg1
GL_ADDArg0 + Arg1
GL_ADD_SIGNEDArg0 + Arg1 − 0, 5
GL_INTERPOLATEArg0 • Arg2 + Arg1 • (1 − Arg2)
GL_SUBTRACTArg0 − Arg1
GL_DOT3_RGB4 • ((Arg0r − 0, 5) • (Arg1r − 0, 5) +
(Arg0g − 0, 5) • (Arg1g − 0, 5) +
(Arg0b − 0, 5) • (Arg1b − 0, 5))
GL_DOT3_RGBA4 • ((Arg0r − 0, 5) • (Arg1r − 0, 5) +
(Arg0g − 0, 5) • (Arg1g − 0, 5) +
(Arg0b − 0, 5) • (Arg1b − 0, 5))

Tabela 8: Funkcje mieszania tekstur dla składowych alfa tekseli

GL_COMBINE_ALPHArównanie mieszania
GL_REPLACEArg0
GL_MODULATEArg0 • Arg1
GL_ADDArg0 + Arg1
GL_ADD_SIGNEDArg0 + Arg1 − 0, 5
GL_INTERPOLATEArg0 • Arg2 + Arg1 • (1 − Arg2)
GL_SUBTRACTArg0 − Arg1
Wyjaśnienia wymagają jeszcze oznaczenia argumentów Arg0, Arg1 i Arg2 funkcji mieszania składowych tekseli, które także są ustalane przy użyciu funkcji z grupy glTexEnv. Argumentom tym odpowiadają odpowiednio następujące wartości parametru pname tych funkcji:
  • GL_SRC0_RGB - składowe RGB argumentu Arg0,
  • GL_SRC1_RGB - składowe RGB argumentu Arg1,
  • GL_SRC2_RGB - składowe RGB argumentu Arg2,
  • GL_SRC0_ALPHA - składowa alfa argumentu Arg0,
  • GL_SRC1_ALPHA - składowa alfa argumentu Arg1,
  • GL_SRC2_ALPHA - składowa alfa argumentu Arg2.
Dla każdej z powyższych wartości argumentu możliwe są następujące wartości parametru param/params:
  • GL_TEXTURE - składowe RGB lub alfa tekseli bieżącej jednostki teksturującej,
  • GL_TEXTUREn - składowe RGB lub alfa tekseli jednostki teksturującej o numerze n,
  • GL_CONSTANT - składowe RGB i alfa koloru środowiska tekstur (parametr GL_TEXTURE_ENV_COLOR),
  • GL_PREVIOUS - składowe RGB i alfa uzyskane w wyniku operacji w środowisku GL_TEXTURE_ENV poprzedniej jednostce teksturującej,
  • GL_PRIMARY_COLOR - składowe RGB i alfa podstawowego koloru obiektu.
Dodatkowo środowisko GL_TEXTURE_ENV umożliwia kontrolę nad przetwarzaniem wartości parametrów określanych dla poszczególnych argumentów Arg0, Arg1 i Arg2 funkcji mieszania. Po raz kolejny służą do tego funkcje z grupy glTexEnv, przy czym wartości parametru pname określają wówczas następujące stałe:
  • GL_OPERAND0_RGB - przetwarzanie wartości składowych RGB argumentu Arg0,
  • GL_OPERAND1_RGB - przetwarzanie wartości składowych RGB argumentu Arg1,
  • GL_OPERAND2_RGB - przetwarzanie wartości składowych RGB argumentu Arg2,
  • GL_OPERAND0_ALPHA - przetwarzanie wartości składowej alfa argumentu Arg0,
  • GL_OPERAND1_ALPHA - przetwarzanie wartości składowej alfa argumentu Arg1,
  • GL_OPERAND2_ALPHA - przetwarzanie wartości składowej alfa argumentu Arg2.
Sposób przetwarzania wartości parametrów określanych dla poszczególnych argumentów Arg0, Arg1 i Arg2 regulują następujące wartości parametrów param/params funkcji z grupy glTexEnv:
  • GL_SRC_COLOR - składowe RGB koloru źródła,
  • GL_ONE_MINUS_SRC_COLOR - dopełnienie do jedynki składowych RGB koloru źródła,
  • GL_SRC_ALPHA - składowa alfa,
  • GL_ONE_MINUS_SRC_ALPHA - dopełnienie do jedynki składowej alfa.
Stałych GL_SRC_COLOR i GL_ONE_MINUS_SRC_COLOR można używać tylko w połączeniu z następującymi wartościami parametru param: GL_OPERAND0 - RGB, GL_OPERAND1_RGB i GL_OPERAND2_RGB. Zestawienie kombinacji dopuszczalnych argumentów funkcji mieszania GL_COMBINE_RGB i GL_COMBINE_ALPHA przedstawiają tabele 9 i 10.
Użyte w tabelach oznaczenia określają odpowiednio: Cs i As - składowe koloru i alfa tekseli bieżącej jednostki teksturującej; C n i An - składowe koloru i alfa jednostki teksturującej o numerze n; Cc i Ac - składowe koloru środowiska tekstur (parametr GL_TEXTURE_ENV_COLOR); Cf i Af - składowe koloru i alfa podstawowego koloru obiektu; Cf i Af - składowe koloru i alfa uzyskane w wyniku operacji na poprzedniej jednostce teksturującej (dla pierwszej jednostki są to Cf i Af ).

Tabela 9: Argumenty funkcji mieszania GL_COMBINE_RGB

GL_SRCn_RGBGL_OPERANDn_RGBargument
GL_TEXTUREGL_SRC_COLORCs
GL_ONE_MINUS_SRC_COLOR1 − Cs
GL_SRC_ALPHAAs
GL_ONE_MINUS_SRC_ALPHA1 − As
GL_TEXTUREnGL_SRC_COLORCns
GL_ONE_MINUS_SRC_COLOR1 − Cns
GL_SRC_ALPHAAns
GL_ONE_MINUS_SRC_ALPHA1 − Ans
GL_CONSTANTGL_SRC_COLORCc
GL_ONE_MINUS_SRC_COLOR1 − Cc
GL_SRC_ALPHAAc
GL_ONE_MINUS_SRC_ALPHA1 − Ac
GL_PRIMARY_COLORGL_SRC_COLORCf
GL_ONE_MINUS_SRC_COLOR1 − Cf
GL_SRC_ALPHAAf
GL_ONE_MINUS_SRC_ALPHA1 − Af
GL_PREVIOUSGL_SRC_COLORCp
GL_ONE_MINUS_SRC_COLOR1 − Cp
GL_SRC_ALPHAAp
GL_ONE_MINUS_SRC_ALPHA1 − Ap

Tabela 10: Argumenty funkcji mieszania GL_COMBINE_ALPHA

GL_SRCn_ALPHAGL_OPERANDn_ALPHAargument
GL_TEXTUREGL_SRC_ALPHAAs
GL_ONE_MINUS_SRC_ALPHA1 − As
GL_TEXTUREnGL_SRC_ALPHAAns
GL_ONE_MINUS_SRC_ALPHA1 − Ans
GL_CONSTANTGL_SRC_ALPHAAc
GL_ONE_MINUS_SRC_ALPHA1 − Ac
GL_PRIMARY_COLORGL_SRC_ALPHAAf
GL_ONE_MINUS_SRC_ALPHA1 − Af
GL_PREVIOUSGL_SRC_ALPHAAp
GL_ONE_MINUS_SRC_ALPHA1 − Ap
Po wykonaniu wszystkich powyższych operacji mieszania tekstur przy wieloteksturowaniu otrzymany wynik jest jeszcze skalowany (mnożony) przez stałe określone oczywiście przy użyciu funkcji z grupy glTexEnv z następującymi wartościami parametru pname:
  • GL_RGB_SCALE - współczynnik skalowania składowych RGB; wartość domyślna 1,
  • GL_ALPHA_SCALE - współczynnik skalowania składowych alfa; wartość domyślna 1.
Na koniec opisu środowiska GL_TEXTURE_ENV podajmy jeszcze wartości domyślne dla opisanych parametrów funkcji z grupy glTexEnv określających parametry mieszania tekstur. Zestawienie to zawiera tabela 11.

Tabela 11: Zestawienie domyślnych argumentów parametrów mieszania tekstur

parametr pnameparametr param/params
GL_TEXTURE_ENV_MODEGL_MODULATE
GL_TEXTURE_ENV_COLOR(0, 0, 0, 0)
GL_COMBINE_RGBGL_MODULATE
GL_COMBINE_ALPHAGL_MODULATE
GL_SRC0_RGB
GL_SRC1_RGB
GL_SRC2_RGB
GL_TEXTURE
GL_PREVIOUS
GL_CONSTANT
GL_SRC0_ALPHA
GL_SRC1_ALPHA
GL_SRC2_ALPHA
GL_TEXTURE
GL_PREVIOUS
GL_CONSTANT
GL_OPERAND0_RGB
GL_OPERAND1_RGB
GL_OPERAND2_RGB
GL_SCR_COLOR
GL_SCR_COLOR
GL_SCR_ALPHA
GL_OPERAND0_ALPHA
GL_OPERAND1_ALPHA
GL_OPERAND2_ALPHA
GL_SCR_ALPHA
GL_SCR_ALPHA
GL_SCR_ALPHA
GL_RGB_SCALE1
GL_ALPHA_SCALE1

Środowisko GL_TEXTURE_FILTER_CONTROL

Jeżeli wartość parametru target wynosi GL_TEXTURE_FILTER_CONTROL, to parametr pname może przyjąć tylko jedną wartość określoną stałą GL_TEXTURE_LOD_BIAS, która określa przesunięcie poziomu szczegółowości (LOD) mipmap w stosunku do domyślnego algorytmu przyjętego w OpenGL. Wartość początkowa tego parametru wynosi 0.

Środowisko GL_POINT_SPRITE

Środowisko GL_POINT_SPRITE dotyczy mechanizmu duszków punktowych (ang. point sprite) i zostanie omówione w odrębnym odcinku kursu biblioteki OpenGL.

Tekstury zastępcze (proxy)

Tekstury zastępcze (proxy) są mechanizmem pozwalającym na szybką ocenę pojemności zasobów i możliwości obsługi tekstur przez daną implementację biblioteki OpenGL. Jest to przy tym sposób znacznie bardziej skuteczny od odczytu maksymalnych rozmiarów tekstury, bowiem uwzględnia wszystkie parametry tekstury decydujące o możliwości jej utworzenia. W szczególności dotyczy to wewnętrznego formatu danych tekstury i ilość bitów przeznaczonych na składowe tekseli.
Tworząc wybrany rodzaj tekstury zastępczej korzystamy z grupy standardowych funkcji glTexImage służących przede wszystkim do definiowania standardowych tekstur. Przypomnijmy tylko, że aby powstała tekstura zastępcza w parametrze target odpowiedniej funkcji z grupy glTexImage podajemy jedną ze stałych: GL_PROXY_TEXTURE_1D, GL_PROXY_TEXTURE_2D, GL_PROXY_TEXTURE_3D lub GL_PROXY_TEXTURE_CUBE_MAP. natomiast parametr pixels przyjmuje wartość NULL. Pozostałe parametry powinny mieć takie same wartości jak parametry tekstury, którą planujemy utworzyć.
Po utworzeniu tekstury zastępczej sprawdzenie, czy dana tekstura zostanie obsłużona przez bieżącą implementację OpenGL sprowadza się do ustalenia czy parametry takie jak wymiary (wysokość, szerokość i głębokość), szerokość obramowania oraz ilość bitów na każdą składową teksela odpowiadają żądaniu. Jeżeli utworzenie takiej tekstury nie będzie możliwe, to powyższe parametry tekstury zastępczej będą miały wartość 0. Do sprawdzenia wybranego parametru tekstury służą funkcje z grupy glGetTexLevelParameter, które bliżej opiszemy w dalszej części tego odcinka kursu.
Dodajmy jeszcze, że przy tworzeniu tekstury zastępczej nie jest dokonywany żaden transfer danych tekseli. Tekstur zastępczych nie można także używać w taki sam sposób jak „normalnych” tekstur, w szczególności nie obsługują one funkcji z grupy glGetTexParameter.
Tekstury zastępcze jedno i dwuwymiarowe wprowadzono w wersji 1.1 biblioteki OpenGL w oparciu o rozszerzenie EXT texture. Tekstury zastępcze trójwymiarowe i kubiczne wprowadzono jednocześnie z teksturami trójwymiarowymi i kubicznymi, tj. odpowiednio w wersjach 1.2 i 1.3 biblioteki OpenGL (rozszerzenia EXT texture3D, ARB texture cube map i EXT texture cube map).

Kompresja tekstur

Technika kompresji tekstur została wprowadzona w wersji 1.3 biblioteki OpenGL i została oparta o rozszerzenie ARB texture compression. Wykorzystanie tekstur skompresowanych może przyczynić się do wzrostu wydajności renderingu m.in. dzięki zmniejszeniu zapotrzebowania na pamięć karty graficznej.
Najprostszym sposobem kompresji tekstur jest wybór formatu skompresowanego (parametr internalformat) podczas definiowania tekstury za pomocą funkcji z grup glTexImage i glCopyTexImage. Zestawienie skompresowanych formatów tekstur zawiera tabela 12. Obok formatu skompresowanego podano odpowiadający mu format podstawowy tekstury. Cztery ostatnie formaty skompresowane dotyczą tekstur sRGB i zostały dodane w wersji 2.1 biblioteki OpenGL (rozszerzenie EXT texture sRGB).

Tabela 12: Skompresowane formaty tekstur

format skompresowanyformat podstawowy
GL_COMPRESSED_ALPHA
GL_COMPRESSED_LUMINANCE
GL_COMPRESSED_LUMINANCE_ALPHA
GL_COMPRESSED_INTENSITY
GL_COMPRESSED_RGB
GL_COMPRESSED_RGBA
GL_ALPHA
GL_LUMINANCE
GL_LUMINANCE_ALPHA
GL_INTENSITY
GL_RGB
GL_RGBA
GL_COMPRESSED_SRGB
GL_COMPRESSED_SRGB_ALPHA
GL_COMPRESSED_SLUMINANCE
GL_COMPRESSED_SLUMINANCE_ALPHA
GL_RGB
GL_RGBA
GL_LUMINANCE
GL_LUMINANCE_ALPHA
Specyfikacja biblioteki OpenGL nie określa żadnego formatu kompresji tekstur, pozostawiając to zadanie twórcom rozszerzeń. Przykładem takiego rozszerzenia jest EXT texture compression s3tc. Jednocześnie wprowadzono możliwość wpływu na jakość i zarazem poziom kompresji tekstur poprzez wskazówkę renderingu (funkcja glHint) określoną stałą GL_TEXTURE - COMPRESSION HINT.
Ilość oraz wykaz obsługiwanych formatów kompresji tekstur można ustalić korzystając ze zmiennych stanu: GL_NUM_COMPRESSED_TEXTURE_FORMATS i GL_COMPRESSED_TEXTURE_FORMATS.
Biblioteka OpenGL udostępnia także możliwość utworzenia skompresowanej tekstury na podstawie danych zapisanych w formacie specyficznym dla danego algorytmu kompresji. Służą do tego funkcje z grupy glCompressedTexImage:
C/C++
void glCompressedTexImage1D( GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid * data )
void glCompressedTexImage2D( GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid * data )
void glCompressedTexImage3D( GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid * data )
Parametry target, level, internalformat, width, height, depth i border powyższych funkcji odpowiadają analogicznym parametrom funkcji z grupy glTexImage. Jedyną różnicą jest oczywiście to, że parametr internalformat określa jeden ze skompresowanych formatów tekstury określonych w rozszerzeniu obsługiwanym przez daną implementację biblioteki OpenGL. Parametr imageSize określa rozmiar tablicy zawierającej skompresowane dane tekstury, do której adres przekazywany jest w parametrze data.
Ponadto biblioteka OpenGL zawiera odpowiedniki funkcji z grupy glTexSubImage korzystające z danych tekstury w formacie skompresowanej. Są to trzy funkcje z grupy glCompressedTexSubImage:
C/C++
void glCompressedTexSubImage1D( GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid * data )
void glCompressedTexSubImage2D( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid * data )
void glCompressedTexSubImage3D( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid * data )
Parametry target, level, xoffset, yoffset, zoffset, width, height, depth i format mają takie same znaczenie jak analogiczne parametry funkcji z grupy tt glTexSubImage. Oczywiście parametr format podlega takim samym ograniczeniom jak parametr format opisanych nieco wcześniej funkcji z grupy glCompressedTexImage. Parametry imageSize to określa rozmiar tablicy ze skompresowanym fragmentem tekstury, do którego wskaźnik zawiera parametr data.
Biblioteka OpenGL umożliwia także pobranie danych skompresowanej tekstury np. w celu jej zapisania na dysk. Pobranie danych bieżącej skompresowanej tekstury realizuje funkcja:
C/C++
void glGetCompressedTexImage( GLenum target, GLint level, GLvoid * img )
Parametr target określa rodzaj tekstury i odpowiada oczywiście analogicznemu parametrowi funkcji z grupy glCompressedTexImage. Drugi parametr level to poziom odczytywanej mipmapy, a ostatni parametr img zawiera wskaźnik do bufora w którym zostaną zapisane dane tekstury. W celu ustalenia wielkości danych skompresowanej tekstury należy użyć opisanych nieco dalej funkcji z grupy glGetTexLevelParameter z parametrem GL_TEXTURE_COMPRESSED_IMAGE_SIZE.

Wieloteksturowanie

Wieloteksturowanie, nazywane także multiteksturowaniem (ang. multitexturing), zostało wprowadzone w wersji 1.3 biblioteki OpenGL i oparte na rozszerzeniach SGIS multitexture, EXT multitexture i ARB multitexture. Idea wieloteksturowania sprowadza się do jednoczesnego nakładania więcej niż jednej tekstury na obiekt. Nowoczesne procesory graficzne zazwyczaj potrafią nakładać wiele tekstur jednocześnie, dzięki czemu wieloteksturowanie jest stosunkowo szybkie.
W implementacjach biblioteki OpenGL nie obsługujących wieloteksturowania, także jest możliwie nakładanie wielu tekstur na jeden obiekt. Jednak uzyskanie takiego efektu wymaga stosowania mieszania kolorów oraz wielokrotnego przeliczenia geometrii renderowanego obiektu. Technika ta nazywana teksturowaniem wieloprzebiegowym (ang. multipass texturing) jest oczywiście wolniejsza od wieloteksturowania.

Aktywna jednostka teksturująca

Wybór aktywnej jednostki teksturującej umożliwia funkcja:
C/C++
void glActiveTexture( GLenum texture )
której parametr texture określa numer wybranej jednostki. Plik glext.h zawiera 32 predefiniowane stałe GL_TEXTUREi z numerami jednostek teksturujących, gdzie i przyjmuje wartość od 0 do 31. Ponieważ numery jednostek mają kolejne wartości można stosować prostą arytmetykę: GL_TEXTUREi = GL_TEXTURE0 + i.
Ilość jednostek teksturujących dostępnych w implementacji biblioteki
OpenGL zawiera zmienna stanu GL_MAX_TEXTURE_UNITS.
Wyłączenie wieloteksturowania i przejście do normalnego trybu teksturowania wymaga deaktywacji wszystkich jednostek teksturujących poza pierwszą (GL_TEXUTE0).

Współrzędne tekstur

W przypadku wieloteksturowania definiowanie współrzędnych tekstur przy użyciu funkcji z grupy glTexCoord daje efekt tylko dla pierwszej jednostki teksturującej (GL_TEXTURE0). Definiowane współrzędnych tekstur dla dowolnie wybranej jednostki teksturującej umożliwiają funkcje z grupy glMultiTexCoord, które od swoich „ jednoteksturowych” odpowiedników posiadają dodatkowy parametr trarget określający numer jednostki teksturującej.
C/C++
void glMultiTexCoord1d( GLenum target, GLdouble s )
void glMultiTexCoord1dv( GLenum target, const GLdouble * v )
void glMultiTexCoord1f( GLenum target, GLfloat s )
void glMultiTexCoord1fv( GLenum target, const GLfloat * v )
void glMultiTexCoord1i( GLenum target, GLint s )
void glMultiTexCoord1iv( GLenum target, const GLint * v )
void glMultiTexCoord1s( GLenum target, GLshort s )
void glMultiTexCoord1sv( GLenum target, const GLshort * v )
void glMultiTexCoord2d( GLenum target, GLdouble s, GLdouble t )
void glMultiTexCoord2dv( GLenum target, const GLdouble * v )
void glMultiTexCoord2f( GLenum target, GLfloat s, GLfloat t )
void glMultiTexCoord2fv( GLenum target, const GLfloat * v )
void glMultiTexCoord2i( GLenum target, GLint s, GLint t )
void glMultiTexCoord2iv( GLenum target, const GLint * v )
void glMultiTexCoord2s( GLenum target, GLshort s, GLshort t )
void glMultiTexCoord2sv( GLenum target, const GLshort * v )
void glMultiTexCoord3d( GLenum target, GLdouble s, GLdouble t, GLdouble r )
void glMultiTexCoord3dv( GLenum target, const GLdouble * v )
void glMultiTexCoord3f( GLenum target, GLfloat s, GLfloat t, GLfloat r )
void glMultiTexCoord3fv( GLenum target, const GLfloat * v )
void glMultiTexCoord3i( GLenum target, GLint s, GLint t, GLint r )
void glMultiTexCoord3iv( GLenum target, const GLint * v )
void glMultiTexCoord3s( GLenum target, GLshort s, GLshort t, GLshort r )
void glMultiTexCoord3sv( GLenum target, const GLshort * v )
void glMultiTexCoord4d( GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q )
void glMultiTexCoord4dv( GLenum target, const GLdouble * v )
void glMultiTexCoord4f( GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q )
void glMultiTexCoord4fv( GLenum target, const GLfloat * v )
void glMultiTexCoord4i( GLenum target, GLint s, GLint t, GLint r, GLint q )
void glMultiTexCoord4iv( GLenum target, const GLint * v )
void glMultiTexCoord4s( GLenum target, GLshort s, GLshort t, GLshort r, GLshort q )
void glMultiTexCoord4sv( GLenum target, const GLshort * v )

Automatyczne generowanie współrzędnych tekstur

W niektórych sytuacjach biblioteka OpenGL udostępnia automatyczne generowanie współrzędnych tekstur. Mechanizm ten można włączać i wyłączać niezależnie dla każdej współrzędnej tekstury. Służą do tego dobrze znane funkcje glEnable/glDisable wywoływane z parametrami:
  • GL_TEXTURE_GEN_S - generowanie współrzędnych s tekstury,
  • GL_TEXTURE_GEN_T - generowanie współrzędnych t tekstury,
  • GL_TEXTURE_GEN_R - generowanie współrzędnych r tekstury,
  • GL_TEXTURE_GEN_Q - generowanie współrzędnych q tekstury.
Domyślnie automatyczne generowanie tekstur jest wyłączone dla wszystkich współrzędnych.
Włączenie techniki automatycznego generowania tekstur powoduje, że biblioteka OpenGL pomija wartości współrzędnych tekstur określone w tradycyjny sposób.
Sposób automatycznego generowania współrzędnych definiują funkcje z grupy glTexGen:
C/C++
void glTexGend( GLenum coord, GLenum pname, GLdouble param ) void glTexGenf( GLenum coord, GLenum pname, GLfloat param ) void glTexGeni( GLenum coord, GLenum pname, GLint param )
void glTexGendv( GLenum coord, GLenum pname, const GLdouble * params )
void glTexGenfv( GLenum coord, GLenum pname, const GLfloat * params )
void glTexGeniv( GLenum coord, GLenum pname, const GLint * params )
Pierwszy parametr coord określa która z współrzędnych ma być generowana. Dopuszczalne są cztery wartości tego parametru: GL_S, GL_T, GL_R i GL_Q. Drugi parametr pname określa rodzaj definiowanego parametru i przyjmuje jedną z trzech wartości:
  • GL_TEXTURE_GEN_MODE - określenie metody generowania współrzędnych tekstur,
  • GL_OBJECT_PLANE - współrzędne (p1, p2 , p3, p4) równania jednorodnego płaszczyzny używanego przy odwzorowaniu liniowym względem obiektu,
  • GL_EYE_PLANE - współrzędne (p1, p2 , p3, p4) równania jednorodnego płaszczyzny używanego przy odwzorowaniu liniowym względem kamery (oka).
  • Z uwagi na swoją specyfikę, dwa ostatnie parametry mogą być definiowane tylko za pomocą wersji funkcji glTexGen ze wskaźnikiem params.
  • OpenGL udostępnia kilka metod odwzorowania (mapowania) współrzędnych tekstur. Rodzaj odwzorowania określa parametr param/params (oczywiście wówczas, gdy parametr pname ma wartość GL_TEXTURE_GEN_MODE), który przyjmuje jedną z wartości:
  • GL_OBJECT_LINEAR - odwzorowanie liniowe względem obiektu (wartość domyślna),
  • GL_EYE_LINEAR - odwzorowanie liniowe względem kamery,
  • GL_SPHERE_MAP - odwzorowanie kuliste,
  • GL_REFLECTION_MAP - odwzorowanie sześcienne (kubiczne),
  • GL_NORMAL_MAP - odwzorowanie sześcienne z wykorzystaniem wektorów normalnych wierzchołków obiektów.
Stałe GL_REFLECTION_MAP i GL_NORMAL_MAP zostały wprowadzone w wersji 1.3 biblioteki OpenGL, a wcześniej w rozszerzeniach ARB texture cube - map EXT texture cube map i NV texgen reflection.

Odwzorowanie liniowe względem obiektu

W trybie odwzorowania liniowego względem obiektu (stała GL_OBJECT - LINEAR) współrzędne tekstur obliczane są na podstawie równania:
gdzie (p1, p2, p3, p4 ) są współrzędnymi równania jednorodnego płaszczyzny, względem której wykonywane jest odwzorowanie (parametr GL_OBJECT - PLANE), a (x0 , y0, z0, w0 ) są współrzędnymi wierzchołka teksturowanego obiektu.

Odwzorowanie liniowe względem kamery

W trybie odwzorowania liniowego względem kamery (stała GL_EYE_LINEAR) współrzędne tekstur obliczane są na podstawie poniższego równania:
gdzie (x0 , y0 , z0, w0 ) są współrzędnymi wierzchołka teksturowanego obiektu, a współrzędne p1', p2', p3', p4' powstają poprzez przemnożenie współrzędnych (p1, p2, p3, p4) równania jednorodnego płaszczyzny, względem której wykonywane jest odwzorowanie (parametr GL_EYE_PLANE), przemnożone przez odwrotność macierzy modelowania.

Odwzorowanie kuliste

Odwzorowanie kuliste (stała GL_SPHERE_MAP) pozwala na uzyskiwanie efektu odbicia obrazu tekstury na obiekcie. Ponieważ obliczenia związane z mapowaniem kulistym nie wymagają dodatkowych parametrów, nie ma potrzeby przedstawiania wzorów przekształceń wykonywanych przez OpenGL. Zainteresowanych odsyłam do specyfikacji biblioteki.

Odwzorowanie sześcienne

Ostatnie, dostępne od wersji 1.3 biblioteki OpenGL, odwzorowanie sześcienne (stałe GL_REFLECTION_MAP i GL_NORMAL_MAP) także pozwala na uzyskanie efektu odbicia obrazu tekstury na obiekcie. W porównaniu do odwzorowania kulistego uzyskane efekty są dużo lepsze, jednak wymagają zastosowania opisanych poniżej tekstur kubicznych.
Odwzorowanie sześcienne nie jest dostępne dla współrzędnych q tekstury.

Tekstury kubiczne

Tekstury kubiczne lub sześcienne (ang. cube map texture), wprowadzone w wersji 1.3 biblioteki OpenGL (rozszerzenia ARB texture cube map i EXT - texture cube map) nie stanowią jak inne omawiane tekstury pojedynczego zbioru tekseli, ale są zestawem sześciu tekstur, składających się na ściany sześcianu.
Wszystkie dwuwymiarowe tekstury składające się na teksturę kubiczną muszą mieć takie same wymiary, przy czym obowiązuje dodatkowy warunek aby ich długości i szerokości były równe.
Poszczególne tekstury składające się na teksturę kubiczną (rysunek 4) tworzymy przy użyciu funkcji glTexImage2D, przy czym parametr target przyjmuje jedną z poniższych wartości:
  • GL_TEXTURE_CUBE_MAP_POSITIVE_X - tekstura sześcienna dla kierunku dodatnich wartości osi X,
  • GL_TEXTURE_CUBE_MAP_NEGATIVE_X - tekstura sześcienna dla kierunku ujemnych wartości osi X,
  • GL_TEXTURE_CUBE_MAP_POSITIVE_Y - tekstura sześcienna dla kierunku dodatnich wartości osi Y,
  • GL_TEXTURE_CUBE_MAP_NEGATIVE_Y - tekstura sześcienna dla kierunku ujemnych wartości osi Y,
  • GL_TEXTURE_CUBE_MAP_POSITIVE_Z - tekstura sześcienna dla kierunku dodatnich wartości osi Z,
  • GL_TEXTURE_CUBE_MAP_NEGATIVE_Z - tekstura sześcienna dla kierunku ujemnych wartości osi Z,
Rysunek 4. Tekstura kubiczna (sześcienna)
Rysunek 4. Tekstura kubiczna (sześcienna)
Przypomnijmy, że biblioteka OpenGL umożliwia także utworzenie zastępczej tekstury kubicznej (parametr target o wartości GL_PROXY_TEXTURE_CUBE_MAP), a włączenie teksturowania kubicznego wymaga wywołania funkcji glEnable z parametrem GL_TEXTURE_CUBE_MAP.
W przypadku, gdy korzystamy z tekstury kubicznej najłatwiejszym sposobem określenia współrzędnych s, t i r tekstury jest użycie odwzorowania sześciennego, czyli techniki automatycznego generowania współrzędnych. Nieprzypadkowo wymieniamy trzy współrzędne, wprawdzie tekstura kubiczna składa się z tekstur dwuwymiarowych, to jej współrzędne są trójwymiarowe.
Wszystkie opisane wcześniej parametry tekstur mają oczywiście zastosowanie do tekstur kubicznych, przy czym ustawienia dotyczą zawsze całej tekstury, a nie poszczególnych jej składowych.

Drugorzedny kolor

Jednym z problemów jakie może powodować teksturowanie jest utrata części efektów związanych z oświetleniem obiektów. Zjawisko to dotyczy głównie efektu rozbłysków i występuje, gdy składowe fragmentów obiektów łączone są ze składowymi tekseli tekstury, a środowisko tekstur działa w trybie GL_MODULATE.
Rozwiązanie tego problemu stanowi wprowadzona w wersji 1.2 biblioteki OpenGL, a wcześniej w rozszerzeniu EXT separate specular color, technika nazywana drugorzędnym kolorem odbicia (ang. secondary specular color). Polega ona na nakładaniu na obiekt, po nałożeniu tekstury, drugorzędnego koloru, którego składowe tworzone są na podstawie właściwości światła odbitego i odpowiadającym mu właściwościom materiału.
Kontrolę nad drugorzędnym kolorem odbicia umożliwiają funkcje z grupy glLigtModel, wywoływane z parametrem pname równym GL_LIGHT_MODEL - COLOR CONTROL. Włączenie tej techniki sprowadza się do podania parametru param/params o wartości GL_SEPARATE_SPECULAR_COLOR, natomiast powrót do standardowego modelu oświetlenia wartości GL_SINGLE_COLOR.
W wersji 1.4 biblioteki OpenGL dodano możliwość zdefiniowania drugorzędnego koloru wierzchołka, którego składowe będą dodawane do składowych fragmentów, ale tylko przy wyłączonym mechanizmie oświetlenia (rozszerzenie EXT secondary color). Włączenie tej techniki wymaga wywołania funkcji glEnable z parametrem GL_COLOR_SUM, a składowe drugorzednego koloru określają funkcje z grupy glSecondaryColor3:
C/C++
void glSecondaryColor3b( GLbyte red, GLbyte green, GLbyte blue )
void glSecondaryColor3d( GLdouble red, GLdouble green, GLdouble blue )
void glSecondaryColor3f( GLfloat red, GLfloat green, GLfloat blue )
void glSecondaryColor3i( GLint red, GLint green, GLint blue )
void glSecondaryColor3s( GLshort red, GLshort green, GLshort blue )
void glSecondaryColor3ub( GLubyte red, GLubyte green, GLubyte blue )
void glSecondaryColor3ui( GLuint red, GLuint green, GLuint blue )
void glSecondaryColor3us( GLushort red, GLushort green, GLushort blue )
void glSecondaryColor3bv( const GLbyte * v )
void glSecondaryColor3dv( const GLdouble * v )
void glSecondaryColor3fv( const GLfloat * v )
void glSecondaryColor3iv( const GLint * v )
void glSecondaryColor3sv( const GLshort * v )
void glSecondaryColor3ubv( const GLubyte * v )
void glSecondaryColor3uiv( const GLuint * v )
void glSecondaryColor3usv( const GLushort * v )
Wartości składowych drugorzędnego koloru wierzchołka podlegają takim samym regułom przekształceń jak składowe koloru podstawowego, określane funkcjami z grupy glColor.
Jak widzimy biblioteka OpenGL nie udostępnia funkcji obsługujących wszystkie cztery składowe drugorzędnego koloru. Składowa alfa przyjmuje zawsze wartość równą 1, przy czym w wersji OpenGL_1.4 i 1.5, a także w rozszerzeniu EXT secondary color, domyślna wartość składowej alfa wynosi 0.

Tekstury głębi

Tekstury głębi zostały wprowadzone w wersji 1.4 biblioteki OpenGL (rozszerzenia ARB depth texture i SGIX depth texture). Tekstury te mogą być jedno i dwuwymiarowe i wyróżniają się formatem podstawowym identyfikowanym stałą GL_DEPTH_COMPONENT.
Generowanie tekstur głębi regulują trzy specjalne parametry określane przy użyciu funkcji z grupy glTexParameter. Pierwszy z nich to GL_DEPTH - TEXTURE MODE, który określa sposób odwzorowania tekstury głębi. Możliwe są następujące odwzorowania: GL_LUMINANCE, GL_INTENSITY i GL_ALPHA. Formaty te różni sposób przechowywania wartości głębi (D), który w przełożeniu na składowe RGBA tekseli wyglądają następująco:
  • GL_LUMINANCE - (D, D, D, 1),
  • GL_INTENSITY - (D, D, D, D),
  • GL_ALPHA - (0, 0, 0, D).
Drugi parametr GL_TEXTURE_COMPARE_MODE, określa tryb porównywania składowych tekstury głębi i przyjmuje jedną z wartości:
  • GL_NONE - brak porównywania,
  • GL_COMPARE_R_TO_TEXTURE - wartość współrzędnej r tekstury jest porównywana ze składową głębi (D).
Ostatni parametr GL_TEXTURE_COMPARE_FUNC określa funkcję porównującą dla tekstury głębi, czyli funkcję porównującą wartość współrzędnej r tekstury i składowej głębi (D). Zestawienie funkcji zawiera tabela 13.

Tabela 13: Funkcje porównujące tekstury głębi

funkcjaobliczanie składowej r
GL_LEQUAL
GL_GEQUAL
GL_LESS
GL_GREATER
GL_EQUAL
GL_NOTEQUAL
GL_ALWAYSr = 1
GL_NEVERr = 0
Domyślną wartością jest GL_LEQUAL. Stałe GL_LEQUAL i GL_GEQUAL wprowadzono w wersji 1.4 biblioteki OpenGL, pozostałe funkcje dodano w wersji 1.5, a wcześniej w rozszerzeniu EXT shadow funcs.

Pobieranie parametrów tekstur

Pobieranie parametrów tekstur umożliwia dość liczna grupa funkcji. Część z nich została już wspomniana we wcześniejszym tekście, a wszystkie są dokładnie opisane poniżej.

Parametry tekstury na wybranym poziomie mipmapy

Odczyt parametrów bieżącej tekstury na wybranym poziomie mipmapy umożliwiają funkcje z grupy:
C/C++
void glGetTexLevelParameterfv( GLenum target, GLint level, GLenum pname, GLfloat * params )
void glGetTexLevelParameteriv( GLenum target, GLint level, GLenum pname, GLint * params )
Parametr target określa rodzaj tekstury, której wartości będą pobierane. Dopuszczalne są poznane już stałe: GL_TEXTURE_1D, GL_TEXTURE_2D, GL_TEXTURE_3D, GL_PROXY_TEXTURE_1D, GL_PROXY_TEXTURE_2D, GL_PROXY_TEXTURE_3D, GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, GL_TEXTURE_CUBE_MAP_POSITIVE_Z i GL_TEXTURE_CUBE_MAP_NEGATIVE_Z.
Drugi parametr level określa poziom mipmapy, dla której pobierane są parametry. Kolejny parametr pname wskazuje rodzaj pobieranych danych o teksturze i może przyjąć jedną z poniższych wartości:
  • GL_TEXTURE_WIDTH - szerokość tekstury,
  • GL_TEXTURE_HEIGHT - wysokość tekstury,
  • GL_TEXTURE_DEPTH - głębokość tekstury,
  • GL_TEXTURE_INTERNAL_FORMAT - wewnętrzny format tekstury,
  • GL_TEXTURE_BORDER - składowe RGBA koloru obramowania tekstury,
  • GL_TEXTURE_RED_SIZE - ilość bitów opisujących składową R tekseli tekstury,
  • GL_TEXTURE_GREEN_SIZE - ilość bitów opisujących składową G tekseli tekstury,
  • GL_TEXTURE_BLUE_SIZE - ilość bitów opisujących składową B tekseli tekstury,
  • GL_TEXTURE_ALPHA_SIZE - ilość bitów opisujących składową alfa tekseli tekstury,
  • GL_TEXTURE_LUMINANCE_SIZE - ilość bitów opisujących składową luminacji (jaskrawości) tekseli tekstury,
  • GL_TEXTURE_INTENSITY_SIZE - ilość bitów opisujących składową natężenia (jasności) tekseli tekstury,
  • GL_TEXTURE_COMPONENTS - ilość składowych opisujących pojedynczy teksel tekstury,
  • GL_TEXTURE_COMPRESSED_IMAGE_SIZE - rozmiar danych tekstury skompresowanej.

Parametry bieżącej tekstury

Pobieranie wartości parametrów bieżącej tekstury umożliwiają funkcje z grupy glGetTexParameter:
C/C++
void glGetTexParameterfv( GLenum target, GLenum pname, GLfloat * params )
void glGetTexParameteriv( GLenum target, GLenum pname, GLint * params )
Parametr target określa rodzaj tekstury i może przyjąć jedną z wartości: GL_TEXTURE_1D, GL_TEXTURE_2D, GL_TEXTURE_3D, GL_TEXTURE_CUBE_MAP, GL_PROXY_TEXTURE_1D, GL_PROXY_TEXTURE_2D, GL_PROXY_TEXTURE_3D i GL - PROXY TEXTURE CUBE MAP.
Katalog wartości parametru pname jest taki sam jak analogicznego parametru funkcji z grupy glTexParameter (tabela 3). Przypomnijmy jeszcze raz wszystkie te wartości:
  • GL_TEXTURE_BORDER_COLOR - składowe RGBA koloru obramowania tekstury; wartość początkowa (0, 0, 0, 0),
  • GL_TEXTURE_MIN_FILTER - filtr minimalizujący; wartość początkowa GL_NEAREST_MIPMAP_LINEAR,
  • GL_TEXTURE_MAG_FILTER - filtr maksymalizujący; wartość początkowa GL_LINEAR,
  • GL_TEXTURE_WRAP_S - tryb zawijania tekstury w kierunku współrzędnej s; wartość początkowa GL_REPEAT,
  • GL_TEXTURE_WRAP_T - tryb zawijania tekstury w kierunku współrzędnej t; wartość początkowa GL_REPEAT,
  • GL_TEXTURE_WRAP_R - tryb zawijania tekstury w kierunku współrzędnej r; wartość początkowa GL_REPEAT,
  • GL_TEXTURE_PRIORITY - wartość priorytetu tekstury; wartość początkowa wynosi 1,
  • GL_TEXTURE_RESIDENT - informacja czy tekstura jest rezydentna (GL_TRUE) czy też nie jest rezydentna (GL_FALSE); wartość początkowa GL_TRUE,
  • GL_TEXTURE_MIN_LOD - minimalny poziom szczegółowości (LOD) mipmap; wartość początkowa -1000,
  • GL_TEXTURE_MAX_LOD - maksymalny poziom szczegółowości (LOD) mipmap; wartość początkowa 1000,
  • GL_TEXTURE_BASE_LEVEL - podstawowy poziom ładowanej tekstury dla mechanizmu mipmapowania; wartość domyślna wynosi 0,
  • GL_TEXTURE_MAX_LEVEL - maksymalny poziom ładowanej tekstury dla mechanizmu mipmapowania; wartość domyślna wynosi 1000,
  • GL_TEXTURE_LOD_BIAS - przesunięcie poziomu szczegółowości (LOD) mipmap w stosunku do algorytmu domyślnego; wartość początkowa 0,
  • GL_DEPTH_TEXTURE_MODE - sposób odwzorowania tekstury głębi; wartość początkowa GL_LUMINANCE,
  • GL_TEXTURE_COMPARE_MODE - tryb porównywania składowych tekstury głębi; wartość domyślna GL_NONE,
  • GL_TEXTURE_COMPARE_FUNC - funkcja porównująca dla składowych tekstury głębi; wartość domyślna GL_LEQUAL,
  • GL_GENERATE_MIPMAP - wartość GL_TRUE jeżeli włączony jest mechanizm automatycznego generowania mipmap; w przeciwnym wypadku wartość GL_FALSE.

Parametry automatycznego generowania współrzędnych tekstur

Pobranie parametrów automatycznego generowania współrzędnych tekstur umożliwiają funkcje z grupy glGetTexGen:
C/C++
void glGetTexGendv( GLenum coord, GLenum pname, GLdouble * params )
void glGetTexGenfv( GLenum coord, GLenum pname, GLfloat * params )
void glGetTexGeniv( GLenum coord, GLenum pname, GLint * params )
Parametr coord określa rodzaj współrzędnych tekstury, których dane pobieramy. Możliwa jest jedna z czterech stałych: GL_S, GL_T, GL_R lub GL_Q.
Drugi parametr pname określa rodzaj pobieranego parametru i przyjmuje jedną z poniższych wartości:
  • GL_TEXTURE_GEN_MODE - określenie metody generowania współrzędnych tekstur; wartość domyślna GL_OBJECT_LINEAR,
  • GL_OBJECT_PLANE - współrzędne równania jednorodnego płaszczyzny używanego przy odwzorowaniu liniowym względem obiektu; wartości domyślne dla współrzędnej s wynoszą (1, 0, 0, 0), dla współrzędnej t (0, 1, 0, 0), a dla współrzędnych r i q (0, 0, 0, 0),
  • GL_EYE_PLANE - współrzędne równania jednorodnego płaszczyzny używanego przy odwzorowaniu liniowym względem kamery (oka); wartości domyślne dla współrzędnej s wynoszą (1, 0, 0, 0), dla współrzędnej t(0, 1, 0, 0), a dla współrzędnych r i q (0, 0, 0, 0).

Pobranie danych tekstury

Ostatnia z przedstawianych funkcja pozwala na pobranie danych tekseli (obrazu) bieżącej tekstury:
C/C++
void glGetTexImage( GLenum target, GLint level, GLenum format, GLenum type, GLvoid * pixels )
Parametr target określa rodzaj tekstury i może przyjąć jedną z wartości: GL_TEXTURE_1D, GL_TEXTURE_2D, GL_TEXTURE_3D, GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, GL_TEXTURE_CUBE_MAP_POSITIVE_Z i GL_TEXTURE_CUBE_MAP_NEGATIVE_Z.
Drugi parametr level określa poziom mipmapy, której dane pobieramy. Kolejne dwa parametry format i type mają takie same znaczenie i wartości jak analogiczne parametry funkcji z grupy glTexImage. Ostatni parametr pixels zawiera wskaźnik do tablicy, w której zostaną umieszczone dane tekstury. Oczywiście tablica musi mieć wielkość odpowiednią do ilości pobieranych danych.

Pobieranie parametrów środowiska tesktur

Pobieranie parametrów środowiska tekstur umożliwiają funkcje z grupy glGetTexEnv:
C/C++
void glGetTexEnvfv( GLenum target, GLenum pname, GLfloat * params )
void glGetTexEnviv( GLenum target, GLenum pname, GLint * params )
Parametr target określa rodzaj pobieranego parametru środowiska tekstur i przyjmuje jedną z trzech poznanych już wartości: GL_TEXTURE_ENV, GL_TEXTURE_FILTER_CONTROL i GL_POINT_SPRITE. Zestawienie dopuszczalnych wartości parametru pname w powiązaniu z powyższymi stałymi przedstawia tabela 4. Odpowiadają one oczywiście możliwym kombinacjom analogicznych parametrów funkcji z grupy glTexEnv.

Programy przykładowe

Pierwszy program przykładowy (plik tekstura_1d.cpp) tworzy trzy tekstury jednowymiarowe. Każda z nich ma odmienny format danych ale wszystkie zawierają teksele reprezentujące odcienie szarości. Poza tym tekstury różnią się szerokością. Pierwsza ma 256 tekseli, druga 128, a trzecia 64. Dzięki temu program umożliwia porównanie jak wpływa szczegółowość tekstury na jakość generowanego obrazu i jaki praktyczny efekt dają metody filtracji tekstur.
Na rysunku 5 przedstawiono wszystkie trzy tekstury z ustawionym filtrem pomniejszającym i powiększającym typu GL_NEAREST. Na najniższej teksturze o szerokości 64 tekseli widoczne są wyraźnie różnice pomiędzy odcieniami szarości. Na drugim rysunku 6 ustawione zostały filtry typu GL_LINEAR. Różnice w jakości tekstur są praktycznie niezauważalne, pomimo odpowiednio dwu i czterokrotnego zmniejszenia ilości danych w drugiej i trzeciej teksturze.
Warto także zwrócić uwagę, że w przypadku, gdy wybranym filtrem powiększającym jest GL_LINEAR, program ustawia tryb zawijania tekstury GL_CLAMP_TO_EDGE. Stąd przy uruchamianiu programu sprawdzana jest dostępność obsługi tego trybu.
Rysunek 5. Program Tekstura 1D - filtry pomniejszający i powiększający GL_NEAREST
Rysunek 5. Program Tekstura 1D - filtry pomniejszający i powiększający GL_NEAREST

Plik tekstura_1d.cpp

Rysunek 6. Program Tekstura 1D - filtry pomniejszający i powiększający GL_LINEAR
Rysunek 6. Program Tekstura 1D - filtry pomniejszający i powiększający GL_LINEAR
Uwaga!
Plik tekstura_1d.cpp do pobrania tutaj: TODO: adres
Drugi program przykładowy (plik mipmapy_1d.cpp) przedstawia trzy różne sposoby utworzenia mipmap dla jednowymiarowej tekstury. Pierwsza technika korzysta z rysunków przygotowanych w programie graficznym o kolejnych rozmiarach: 512×1, 256×1, 128×1, 64×1, 32×1, 16×1, 8×1, 4×1, 2×1 i 1×1. Każda z tych tekstur (mipmap) jest kolejno definiowana przy użyciu funkcji glTexImage1D. Dla uproszczenia tekstury zawarto w tekście źródłowym programu w postaci tablic. Oczywiście w przypadku tekstur dwu czy trójwymiarowych takiego rozwiązania nie praktykuje się. Tekstury są najczęściej przechowywane w plikach graficznych lub plikach o formacie przygotowanym na potrzeby konkretnej aplikacji.
Przy drugiej teksturze do generowania mipmap użyto funkcji gluBuild1DMipmaps. Natomiast w trzecim przypadku wykorzystano wprowadzony w wersji 1.4 biblioteki OpenGL mechanizm automatycznego generowania mipmap (program sprawdza numer wersji biblioteki OpenGL).
Ponadto program umożliwia wybór jednego z czterech sposobów filtrowania mipmap dla filtra pomniejszającego. Efekt działania dwóch wybranych filtrów (GL_NEAREST_MIPMAP_NEAREST i GL_LINEAR_MIPMAP_LINEAR) przedstawiają rysunki 7 i 8.
Subiektywne odczucia Autora wskazują, że wszystkie trzy sposobów generowania mipmap dają identyczne rezultaty. Ale trzeba pamiętać, że użyta w programie tektura „tęcza” jest bardzo prosta i daje się z dobrymi efektami skalować nawet przy użyciu prostych algorytmów, z których korzystają biblioteki OpenGL i GLU.

Plik mipmapy_1d.cpp

Rysunek 7. Program Mipmapy 1D - filtr pomniejszający GL_NEAREST_MIPMAP_NEAREST
Rysunek 	7. Program 	Mipmapy 	1D 	-	filtr 	pomniejszający GL_NEAREST_MIPMAP_NEAREST
Rysunek 8. Program Mipmapy 1D - filtr pomniejszający GL_LINEAR_MIPMAP_LINEAR
Rysunek 	8. Program 	Mipmapy 	1D 	-	filtr 	pomniejszający GL_LINEAR_MIPMAP_LINEAR
Uwaga!
Plik mipmapy_1d.cpp do pobrania tutaj: TODO: adres
Trzeci program przykładowy (plik tekstura_2d.cpp) przedstawia jak korzystając z biblioteki GLU można narysować kwadrykę pokrytą teksturą. W tym konkretnym przypadku program rysuje kulę pokrytą jedną z trzech tekstur przedstawionych na rysunkach 9, 10 i 11. Dwie z tych tekstur powstały na podstawie zdjęć zrobionych przez sondy kosmiczne, a wszystkie trzy rysunki pochodzą z serwisu [href="http://maps.jpl.nasa.gov/"].
Wszystkie trzy tekstury wykorzystane w programie mają wymiary rozmiary 1440 × 720 tekseli, ale zastosowana funkcja gluBuild2DMipmaps dokonuje automatycznego skalowania tekstur do rozmiarów 1024 × 512, które odpowiadają najbliższym potęgom liczby 2.
Obsługa kwadryk została przedstawiona w odcinku kursu poświęconemu oświetleniu i materiałom. W programie do nałożenia dwuwymiarowej tekstury na kwadrykę wykorzystaliśmy funkcję gluQuadricTexture,, która jest szczególnie wygodna w użyciu bowiem automatycznie definiuje wszystkie współrzędne tekstur.
Rysunek 9. Wenus - zdjęcia zrobione przez sondę Magellan
Rysunek 9. Wenus - zdjęcia zrobione przez sondę Magellan

Plik tekstura_2d.cpp

Rysunek 10. Ziemia - mapa hipsometryczna
Rysunek 10. Ziemia - mapa hipsometryczna
Rysunek 11. Mars - zdjęcia zrobione przez sondy Viking
Rysunek 11. Mars - zdjęcia zrobione przez sondy Viking
Rysunek 12. Program Tekstura 2D - Wenus
Rysunek 12. Program Tekstura 2D - Wenus
Rysunek 13. Program Tekstura 2D - Ziemia
Rysunek 13. Program Tekstura 2D - Ziemia
Rysunek 14. Program Tekstura 2D - Mars
Rysunek 14. Program Tekstura 2D - Mars
Uwaga!
Plik tekstura_2d.cpp do pobrania tutaj: TODO: adres
Kolejny przykładowy program (plik mipmapy_2d.cpp) przedstawia bardzo prosty trójwymiarowy „świat”, na który składa się płaska powierzchnia „ziemi” i mały „domek”. Do budowy tego świata użyte zostały trzy tekstury przedstawione na rysunkach 15, 16 i 17. Pierwsza z nich ma rozmiary 512 × 512 tekseli, dwie pozostałe mają po 256 × 256 tekseli. Wszystkie tekstury pochodzą z kolekcji darmowych tekstur umieszczonych pod adresem http://www.crystalspace3d.org/.
Tym razem w programie współrzędne tekstur definiowane są ręcznie, przy czym w przypadku każdego obiektu tekstura powtarzana jest wielokrotnie, przy zastosowaniu domyślnego sposobu zawijania tekstur GL_REPEAT. Jak już wcześniej wspomnieliśmy, daje to efekt kafelkowania i umożliwia pokrycie dużego obiektu względnie małą teksturą. Oczywiście tekstura musi być odpowiednio przygotowana do takiego sposobu renderingu.
Do generowania mipmap zostały użyte mechanizmy wprowadzone w wersji 1.4 biblioteki OpenGL (program sprawdza numer wersji biblioteki lub obecność rozszerzenia SGIS generate mipmap). Zauważmy, że tworząc kolejne obiekty tekstur trzeba za każdym razem włączyć mechanizm automatycznego generowania mipmap. Jest to związane z zachowywaniem dla każdego stanu tekstury odrębnego zestawu parametrów tekstur.
Poza dostępną już w poprzednich programach opcją wyboru filtra minimalnego, program umożliwia także ustawienie dwóch wskazówek renderingu:
  • GL_PERSPECTIVE_CORRECTION_HINT - korekcja perspektywy przy renderingu tekstur,
  • GL_GENERATE_MIPMAP_HINT - jakość automatycznie generowanych mipmap.
W ocenie Autora na testowym komputerze żadna z powyższych opcji nie wpływała na jakość generowanego obrazu. Jednak inne implementacje biblioteki OpenGL mogą generować przy zmianie ustawień powyższych wskazówek obraz o różnej jakości.
Rysunek 15. Tekstura imitująca podłoże
Rysunek 15. Tekstura imitująca podłoże
Różnice w renderowanym obrazie są natomiast doskonale widoczne przy zmianie filtra pomniejszającego. Rysunek 18 przedstawia efekt działania filtra GL_LINEAR_MIPMAP_LINEAR, a rysunek 19 filtra GL_NEAREST_MIPMAP - NEAREST.

Plik mipmapy_2d.cpp

Rysunek 16. Tekstura, z której zbudowano ściany domku
Rysunek 16. Tekstura, z której zbudowano ściany domku
Rysunek 17. Tekstura, z której zbudowano dach domku
Rysunek 17. Tekstura, z której zbudowano dach domku
Rysunek 18. Program Mipmapy 2D - filtr pomniejszający GL_LINEAR_MIPMAP_LINEAR
Rysunek 18. Program 	Mipmapy 	2D 	-	filtr 	pomniejszający GL_LINEAR_MIPMAP_LINEAR
Rysunek 19. Program Mipmapy 2D - filtr pomniejszający GL_NEAREST_MIPMAP_NEAREST
Rysunek 19. Program 	Mipmapy 	2D 	-	filtr 	pomniejszający GL_NEAREST_MIPMAP_NEAREST
Uwaga!
Plik mipmapy_2d.cpp do pobrania tutaj: TODO: adres
Kolejny program przykładowy (plik kompresja_tekstur.cpp) testuje obsługę kompresji tekstur z implementacji biblioteki OpenGL. Program wykorzystuje jako tekstury znany już Czytelnikom obraz „Lena” oraz jego wersję w odcieniach szarości. Oba rysunki poddawane są domyślnej dla swojego formatu kompresji tj. GL_COMPRESSED_RGB i GL_COMPRESSED_LUMINANCE. Poza parametrami kompresji bieżącej tekstury (m.in. algorytm i wielkość tekstury) program wyświetla informacje o dostępnych w danej implementacji algorytmach kompresji tekstur.
Testy przeprowadzone na komputerze Autora z kartą graficzną ATI Radeon X700 wykazały, że biblioteka OpenGL obsługuje formaty kompresji rozszerzenia EXT texture compression s3tc oraz „ukrytego” rozszerzenia ATI texture compression 3dc. Słowo ukryte jest jak najbardziej na miejscu, bowiem biblioteka nie informuje o obsłudze tego rozszerzenia, a samo rozszerzenie nie jest wspierane przez plik glext.h. Oficjalnie firma ATI podaje, że rozszerzenie ATI texture compression 3dc jest obsługiwane przez karty z rodziny ATI Radeon X800 i nowsze.
Efekt kompresji pliku testowego „Lena” w formacie RGB przedstawia rysunek 20. Jak widzimy biblioteka wybrała automatycznie jeden z algorytmów kompresji opisanych w rozszerzeniu EXT texture compression s3tc, a otrzymana w wyniku kompresji tekstura ma wielkość 131.072 bajtów. Wielkość ta znajduje się pomiędzy rozmiarem tego samego obrazu w formacie PNG skompresowanego bezstratnym algorytmem deflate (476.196 bajtów, poziom 6 kompresji), a rozmiarem pliku JFIF, popularnie zwanym JPG, ze stratnym algorytmem kompresji JPEG (43.247 bajtów, poziom kompresji 0,80). Jak można się było domyśleć, biorąc pod uwagę listę obsługiwanych formatów kompresji tekstur, obraz w odcieniach szarości (rysunek 21) nie został poddany kompresji.
Rysunek 20. Program Kompresja tekstur - obraz „Lena”
Rysunek 20. Program Kompresja tekstur - obraz „Lena”
Rysunek 21. Program Kompresja tekstur - obraz „Lena” w odcieniach szarości
Rysunek 21. Program Kompresja tekstur - obraz „Lena” w odcieniach szarości

Plik kompresja_tekstur.cpp

Uwaga!
Plik kompresja_tekstur.cpp do pobrania tutaj: TODO: adres
Następny program przykładowy (plik tekstura_alfa.cpp) przedstawia sposób uzyskania efektu przezroczystości obiektów zbudowanych przy użyciu tekstur posiadających kanał alfa, czyli z tekselami w formacie RGBA. Przypomnijmy, że wartość 0 składowej alfa oznacza całkowitą przezroczystość, a wartość 1 pełną nieprzezroczystość teksela (oczywiście w przypadku, gdy wartości składowych pikseli zawierają się w przedziale [0, 1]).
W programie ponownie skorzystamy z kolekcji tekstur i obiektów umieszczonych pod adresem http://www.crystalspace3d.org/ (patrz rysunki 22 i 23). Druga tekstura jest szczególnie ważna, zawiera bowiem informacje o kanale alfa. Przy konwersji tego rodzaju plików trzeba pamiętać, że nie wszystkie programy poprawnie zachowują podczas tej czynności dane kanału alfa.
Rysunek 22. Tekstura imitująca trawę
Rysunek 22. Tekstura imitująca trawę
Rysunek 23. Tekstura imitująca drzewo
Rysunek 23. Tekstura imitująca drzewo
Efekt przezroczystości tekstury zawierającej kanał alfa można uzyskać na dwa sposoby. Pierwszy z nich jest dobrze znany i polega na użyciu techniki mieszania kolorów:
C/C++
glEnable( GL_BLEND );
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
Niestety uzyskanie poprawnego efektu wymaga sortowania przezroczystych obiektów przed rysowaniem, co omawialiśmy przy przedstawialiśmy techniki mieszania kolorów.
Drugim, znacznie łatwiejszym sposobem uzyskania przezroczystych obiektów jest testowanie wartości składowych alfa fragmentów. Test ten pozwala na odrzucenie z dalszego przetwarzania tych fragmentów, których wartości składowej alfa nie spełniają wymagań określonych za pomocą funkcji:
C/C++
void glAlphaFunc( GLenum func, GLclampf ref )
Parametr func określa funkcję testu kanału alfa i przyjmuje jedną ze znanych już z testu bufora głębokości i bufora szablonowego wartości:
  • GL_NEVER - wynik testu zawsze negatywny,
  • GL_LESS - wartość testu pozytywna jeżeli testowana wartość składowej alfa fragmentu jest mniejsza od wartości ref,
  • GL_EQUAL - wartość testu pozytywna jeżeli testowana wartość składowej alfa fragmentu jest równa wartości ref,
  • GL_LEQUAL - wartość testu pozytywna jeżeli testowana wartość składowej alfa fragmentu jest mniejsza lub równa wartości ref,
  • GL_GREATER - wartość testu pozytywna jeżeli testowana wartość składowej alfa fragmentu jest większa od wartości ref,
  • GL_NOTEQUAL - wartość testu pozytywna jeżeli testowana wartość składowej alfa fragmentu jest różna od wartości ref,
  • GL_GEQUAL - wartość testu pozytywna jeżeli testowana wartość składowej alfa fragmentu jest większa lub równa wartości ref,
  • GL_ALWAYS - wynik testu zawsze pozytywny; jest to wartość domyślna.
Wartość referencyjna podawana w parametrze ref zawiera się w przedziale [0, 1] i jest w razie potrzeby obcinana do tego przedziału. Początkowa wartość referencyjna wynosi 0.
Testowanie kanału alfa jest domyślnie wyłączone. Włączenie testu wymaga użycia funkcji glEnable z parametrem GL_ALPHA_TEST.
Popatrzmy teraz na efekty działania programu. Rysunki 24 i 25 przedstawiają efekt przezroczystości uzyskany odpowiednio przy użyciu testu kanału alfa i techniki mieszania kolorów. Rysunek 26 przedstawia efekt jaki uzyskamy, gdy przy włączonym mieszaniu kolorów nie posortujemy odpowiednio rysowanych obiektów. Ostatni rysunek nr 27 przedstawia scenę narysowaną przy wyłączonym zarówno teście kanału alfa jak i mieszaniu kolorów. Czarne pola na obiektach wskazują te części tekstury, które powinny być przezroczyste.

Plik tekstura_alfa.cpp

Rysunek 24. Program Tekstura alfa - przezroczystość z użyciem testu kanału alfa
Rysunek 24. Program Tekstura alfa - przezroczystość z użyciem testu kanału alfa
Rysunek 25. Program Tekstura alfa - przezroczystość z użyciem mieszania kolorów
Rysunek 25. Program Tekstura alfa - przezroczystość z użyciem mieszania kolorów
Rysunek 26. Program Tekstura alfa - efekt nieposortowania obiektów rysowanych z użyciem mieszania kolorów
Rysunek 26. Program Tekstura alfa - efekt nieposortowania obiektów rysowanych z użyciem mieszania kolorów
Rysunek 27. Program Tekstura alfa - brak przezroczystości
Rysunek 27. Program Tekstura alfa - brak przezroczystości
Uwaga!
Plik tekstura_alfa.cpp do pobrania tutaj: TODO: adres
Kolejny program przykładowy (plik mapa_swietlna.cpp) przedstawia jedną z bardzo popularnych technik związanych z modelowaniem oświetlenia. Mapy świetlne (ang. light map) pozwalają na ominięcie największej wady modelu oświetlenia stosowanego w bibliotece OpenGL, tj. obliczania oświetlenie tylko dla wierzchołków. Koncepcja działania map świetlnych jest niezwykle prosta i sprowadza się do odpowiedniego zmieszania danych podstawowej tekstury z teksturą zawierającą luminację (jaskrawość) poszczególnych obszarów tekstury podstawowej. Taką przykładową mapę świetlną, zastosowaną w opisywanym programie, przedstawia rysunek 28. Choć w praktyce zastosowane tej techniki ogranicza się do statycznego oświetlenia sceny, to uzyskiwane efekty znacząco podnoszą realizm grafiki 3D.
Rysunek 28. Tekstura zawierającą mapę świetlną
Rysunek 28. Tekstura zawierającą mapę świetlną
Do czasu wprowadzenie do biblioteki OpenGL wieloteksturowania mapy świetlne generowana przy użyciu tzw. teksturowania wieloprzebiegowego (ang. multipass texturing), którego główną wadą była konieczność dwukrotnego obliczania geometrii sceny. Wynika to stąd, że tekstury nakładane są dwukrotnie na ten sam obiekt. Wieloteksturowanie znacznie uprasza ten proces, a wszystkie tekstury nakładane są przy jednokrotnym obliczeniu geometrii sceny. Program przykładowy prezentuje obie techniki generowania oświetlenia z użyciem map świetlnych.
W programie wykorzystano znaną już teksturę przedstawiającą trawę (rysunek 22) oraz przedstawioną wcześniej teksturę z mapą świetlną. Przykładowy efekt nałożenia obu tekstur przedstawia rysunek 29. Dla porównania popatrzmy raz jeszcze jak wygląda podstawowa tekstura (rysunek 30) oraz mapa świetlna (rysunek 31). Na dole okna program wyświetla informację o ilości dostępnych jednostek teksturujących.
W programie wykorzystano operacje na macierzy tekstur do zmiany położenia i wielkości „plamy światła” uzyskanej w wyniku nałożenia dwóch tekstur. Aby przy zmianie współrzędnych tekstury zawierającej mapę świetlną tekstura ta była prawidłowo nakładana na cały obiekt trzeba ustawić w kierunkach współrzędnych s i t tryb zawijania GL_CLAMP oraz określić kolor brzegu tekstury (GL_TEXTURE_BORDER_COLOR). Kolor ten odpowiada oczywiście wartościom składowych koloru brzegowych tekseli tekstury z mapą świetlną.
Rysunek 29. Program Mapa świetlna - efekt nałożenia dwóch tekstur
Rysunek 29. Program Mapa świetlna - efekt nałożenia dwóch tekstur
Warto jeszcze zwrócić uwagę na sposób wyłączenia wieloteksturowania, a w szczególności na kolejność deaktywacji jednostek teksturujących. Bardzo ważne jest aby jako ostatnia została wyłączona pierwsza jednostka teksturująca (GL_TEXTURE0). Inna kolejność spowoduje, że aktywna pozostanie ostatnia wyłączana jednostka, co spowoduje niepoprawną obsługę tradycyjnych tekstur.

Plik mapa_swietlna.cpp

Rysunek 30. Program Mapa świetlna - tekstura podstawowa
Rysunek 30. Program Mapa świetlna - tekstura podstawowa
Rysunek 31. Program Mapa świetlna - tekstura z mapą świetlną
Rysunek 31. Program Mapa świetlna - tekstura z mapą świetlną
Uwaga!
Plik mapa_swietlna.cpp do pobrania tutaj: TODO: adres
Kolejny program przykładowy (plik mapowanie_kubiczne.cpp) przedstawia jeden z najczęstszych sposobów wykorzystania tekstur sześciennych i mapowanie kubicznego. Jest to efekt mapowania środowiskowego, czyli odbicia środowiska (świata) na wybranej powierzchni.
Efekt mapowania środowiskowego można otrzymać na dwa podstawowe sposoby. Pierwszy z nich polega na przygotowaniu statycznych tekstur z odbiciem środowiska (możliwość taką ma wiele programów graficznych), co jest w zupełności wystarczające dla statycznej sceny. Jeżeli jednak obiekty na scenie zmieniają się lub poruszają, to musimy generować tekstury środowiskowe przy każdej takiej zmianie. Tą drugą technikę zastosowaliśmy w przykładowym programie.
Nasza scena (rysunek 32) to znany już domek uzupełniony o trzy drzewa i wiszącą nad całością lustrzaną kulą. Obiekty sceny (poza kulą) można dowolnie obracać i skalować, a samą kulę przemieszczają klawisze kursora.
Rysunek 32. Program Mapowanie kubiczne
Rysunek 32. Program Mapowanie kubiczne
Generowaniem tekstury kubicznej zajmuje się funkcja GenerateCubeMap, która w tym celu musi sześć razy wyświetlić odpowiednio obrócone elementy sceny (oczywiście bez kuli). Do otrzymania prawidłowych danych do tekstury kubicznej nie wystarczy odpowiednie obrócenie sceny, trzeba także zmienić macierz rzutowania tak aby otrzymać 90◦ kąt widzenia. To drobne oszustwo oczywiście wprowadza pewne zniekształcenia, ale nie mają one większego praktycznego znaczenia. Po przekształceniach obraz znajdujących się buforze kolorów kopiowany jest przy użyciu funkcji glCopyTexImage2D. Warto zwrócić uwagę, że wielkość generowanej tekstury kubicznej jest uzależniona od wielkości okna programu. Ma to niekorzystny wpływ na szybkość jego działania, gdy zmiana rozmiaru okna powoduje zmianę rozmiarów generowanej tekstury sześciennej, a ewentualną optymalizację tego mechanizmu pozostawiamy Czytelnikowi.
Tak otrzymaną teksturę kubiczną dla sceny przedstawionej na rysunku 32 zawiera rysunek 33. Prezentacja tekstury kubicznej w formie siatki sześcianu jest najbardziej naturalną i chyba najlepszą z możliwych form jej przedstawiania.
Rysunek 33. Program Mapowanie kubiczne
Rysunek 33. Program Mapowanie kubiczne
W funkcji GenerateCubeMap warto jeszcze zwrócić uwagę jeden element. Funkcja ma trzy parametry x, y i z określające położenie obiektu, na który będzie znajdować się generowana tekstura kubiczna. Aby otrzymać prawidłowe odwzorowanie tekstury kubicznej trzeba oczywiście wykonać przesunięcie (translację) współrzędnych obiektów sceny ale przesunięcie to jest odwrotnością przesunięcia obiektu z teksturą kubiczną.
Pozostałe elementy programu były już opisywane wcześniej, warto tylko dodać, iż celowo zrezygnowano z tworzenia identyfikatora dla tekstury kubicznej, bowiem program używa tylko jednej takiej tekstury.

Plik mapowanie_kubiczne.cpp

Uwaga!
Plik mapowanie_kubiczne.cpp do pobrania tutaj: TODO: adres
Następny program przykładowy (plik drugi_kolor_odbicia.cpp) prezentuje opisaną wcześniej technikę drugorzędnego koloru odbicia, stosowaną w przypadku, gdy łączymy teksturę z parametrami materiałów. Efakt działania techniki znakomicie widoczny jest na rysunkach ?? i ??.
Rysunek 34. Program Drugorzędny kolor odbicia - efekt drugiego koloru włączony
Rysunek 34. Program Drugorzędny kolor odbicia - efekt drugiego koloru włączony

Plik drugorzedny_kolor_odbicia.cpp

Rysunek 35. Program Drugorzędny kolor odbicia - efekt drugiego koloru wyłączony
Rysunek 35. Program Drugorzędny kolor odbicia - efekt drugiego koloru wyłączony
Uwaga!
Plik drugorzedny_kolor_odbicia.cpp do pobrania tutaj: TODO: adres
W wersji 1.2 biblioteki OpenGL wprowadzono tekstury trójwymiarowe (rozszerzenie EXT texture3D). W kolejnym programie przykładowym (plik tekstura_3d.cpp) przedstawimy sposób wykorzystania tekstur trójwymiarowych. W programie wykorzystano dane tekstury trójwymiarowej pochdzące z kursu SIGGRAPH 1997 (rysunek 36). Oryginalne pliki w zawierające dane tekstur w formacie LA zostały przekonwertowane do pliku RAW zawierającego wyłącznie dane tekstury w formacie RGBA. Tekstura ma rozmiary 128 × 128 × 64 tekseli.
Tekstura wyświetlana jest na nieruchomym obiekcie złożonym z 512 czworokątów. Wrażenie obrotu obiektu wywoływane jest dzięki odpowiednim przekształceniom współrzędnych tekstury. Dodatkowo obiekt ograniczają dwie płaszczyzny obcinania początkowo położone równolegle do płaszczyzny XY. Ponieważ dane tekstury zawierają kanał alfa w programie wykorzystane mieszanie kolorów oraz funkcję testu kanału alfa. Przyciski „+” i „-” umożliwiają zmianę wartości referencyjnej testu kanału alfa. Efket działania programu dla różnych wartości referencyjnych przedstawiają rysunki 37 - 39.

Plik tekstura_3d.cpp

Rysunek 36. Dane tekstury trójwymiarowej z kursu SIGGRAPH 1997
Rysunek 36. Dane tekstury trójwymiarowej z kursu SIGGRAPH 1997
Rysunek 37. Program Tesktura 3D
Rysunek 37. Program Tesktura 3D
Rysunek 38. Program Tesktura 3D
Rysunek 38. Program Tesktura 3D
Rysunek 39. Program Tesktura 3D
Rysunek 39. Program Tesktura 3D
Uwaga!
Plik tekstura_3d.cpp do pobrania tutaj: TODO: adres
W dotychczasowych programach przykładowych obiekty trójwymiarowe konstruowane były z pojedynczych wielokątów, lub przy użyciu możliwości bibliotek GLU i GLUT. Jednak taki sposób budowy obiektów 3D jest bardzo kłopotliwy w przypadku bardziej skomplikowanych obiektów. W tym miejscu przydatne są pliki grafiki trójwymiarowej, które umożliwiają zapisanie praktycznie dowolnie skomplikowanych obiektów z uzyciem tesktur, a nawet z możliwością animacji. Formatów tego rodzaju plików jest bardzo dużo, ale w tym odcinku kursu bliżej zapoznamy się tylko z jednym. Jako kryterium wyboru przyjęto popularność pliku, dostępność dokumentacji oraz łatwość implementacji.
Pliki Wavefront OBJ cechują się stosunkowo prostą budową i zawierają dane wyłącznie w postaci tekstowymi, co znacznie ułatwia napisanie kodu parsującego i wyświetlającego zapisane w nich obiekty. Nie bez znaczenia jest także dostępność wyczerpującej dokumentacji opisującej budowę plików w tym formacie. Jednak najważniejszą cechą plików OBJ jest ich obsługa przez wiele programów do edycji grafiki trójwymiarowej.
Prezentowany moduł parsujący pliki OBJ (pliki obj.h i obj.cpp) ma zaimplementowane najważniejsze elementy pliku w tym obsługę tekstur dwuwymiarowych w formacie TARGA. Dodanie obsługi tekstur w innych formatach oraz pozostałych możliwości plików OBJ pozostawiamy Czytelnikowi.
Podstawowe zasady budowy plików OBJ przedstawimy na przykładzie sześcianu pokrytego tekstrurą przedstawinego na rysunku 40.
Początek pliku zawiera powołanie definicji materiałów zawartych w pliku cube.mtl:
mtllib cube.mtl
Rysunek 40. Program OBJ View - obiekt „Cube”
Rysunek 40. Program OBJ View - obiekt „Cube”
Dalej przykłądowy plik zawiera współrzędne kolejnych wierzchołków obiektu:
v -3 -3 3
v 3 -3 3
v 3 3 3
v -3 -3 -3
v -3 3 -3
v 3 3 -3
v 3 -3 -3
v -3 3 3
Następne dane w pliku to współrzędne tekstury:
vt 0 0
vt 0 1
vt 1 0
vt 1 1
Zauważmy, że w przypadku tak prostego obiektu do obsługi wszystkich ścian wystarczą cztery współrzędne. W przypadku obiektów o bardziej skomplikowanym kształcie lista współrzędnych tekstury może być zdecydowanie większa.
Ostatnimi elementami pliku OBJ są definicje kolejnych współrzędnych ścian obiektu na które składają się numer indeksu współrzędnych wierzchołka i numer indeksu współrzędnych tekstury (numeracja zaczyna się od jedynki).
usemtl cube
f 1/3 4/4 7/2
f 7/2 2/1 1/3
f 8/1 3/3 6/4
f 6/4 5/2 8/1
f 1/1 2/3 3/4
f 3/4 8/2 1/1
f 2/1 7/3 6/4
f 6/4 3/2 2/1
f 7/1 4/3 5/4
f 5/4 6/2 7/1
f 4/1 1/3 8/4
f 8/4 5/2 4/1
Początek definicji obiektu zawiera wywołanie wybranego materiału, który opisany jest we wspomnianym wcześniej pliku MTL:
newmtl cube
Ns 4
d 1
illum 2
Kd 1.000000 1.000000 1.000000
Ka 0.000000 0.000000 0.000000
Ks 0.000000 0.000000 0.000000
map_Kd wall_wood_verti_color.tga
Znaczenie poszczególnych pól definicji materiału zawiera plik obj.cpp.
Na rysunkach 41, 42 i 43 przedstawiono zdecydowanie bardziej złożone obiekty opisane w plikach OBJ. Te i inne modele dostępne są m.in. w kursach programowania OpenGL prezentowanych na konferencjach SIGGRAPH.
Rysunek 41. Program OBJ View - obiekt „F-16”
Rysunek 41. Program OBJ View - obiekt „F-16”

Plik obj.h

Uwaga!
Plik obj.h do pobrania tutaj: TODO: adres
Rysunek 42. Program OBJ View - obiekt „Porshe”
Rysunek 42. Program OBJ View - obiekt „Porshe”

Plik obj.cpp

Uwaga!
Plik obj.cpp do pobrania tutaj: TODO: adres
Rysunek 43. Program OBJ View - obiekt „Shuttle”
Rysunek 43. Program OBJ View - obiekt „Shuttle”

Plik obj_view.cpp

Uwaga!
Plik obj_view.cpp do pobrania tutaj: TODO: adres
Poprzedni dokumentNastępny dokument
AntyaliasingSelekcja obiektów