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:
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:
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:
W przypadku funkcji glTexImage2D parametr target przyjmuje jedną z poniższych wartości:
Także funkcja glTexImage3D posiada swój zestaw dopuszczalnych wartości parametru target:
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:
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
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
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:
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ę:
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:
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:
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:
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).
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.
Definiowanie współrzędnych s
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
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
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
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:
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:
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
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:
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:
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:
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:
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:
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:
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:
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:
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ę:
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:
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:
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:
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:
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:
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:
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):
Tabela 4: Zestawienie wartości funkcji z grupy glTexEnv
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
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 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
Tabela 8: Funkcje mieszania tekstur dla składowych alfa tekseli
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:
Dla każdej z powyższych wartości argumentu możliwe są następujące wartości parametru param/params:
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:
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:
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
Tabela 10: Argumenty funkcji mieszania GL_COMBINE_ALPHA
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:
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
Ś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
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:
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:
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:
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:
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.
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:
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:
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:
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:
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:
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:
Drugi parametr
GL_TEXTURE_COMPARE_MODE, określa tryb porównywania składowych tekstury głębi i przyjmuje jedną z wartości:
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
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:
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:
Parametry bieżącej tekstury
Pobieranie wartości parametrów bieżącej tekstury umożliwiają funkcje z grupy glGetTexParameter:
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:
Parametry automatycznego generowania współrzędnych tekstur
Pobranie parametrów automatycznego generowania współrzędnych tekstur umożliwiają funkcje z grupy glGetTexGen:
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:
Pobranie danych tekstury
Ostatnia z przedstawianych funkcja pozwala na pobranie danych tekseli (obrazu) bieżącej tekstury:
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:
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.
Plik tekstura_1d.cpp
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
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.
Plik tekstura_2d.cpp
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:
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.
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
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.
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.
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:
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:
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:
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
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.
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ą.
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
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.
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.
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 ??.
Plik drugorzedny_kolor_odbicia.cpp
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
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
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.
Plik obj.h
Uwaga! Plik obj.h do pobrania tutaj: TODO: adres |
Plik obj.cpp
Uwaga! Plik obj.cpp do pobrania tutaj: TODO: adres |
Plik obj_view.cpp
Uwaga! Plik obj_view.cpp do pobrania tutaj: TODO: adres |