Tekstury w OpenGL


W funkcji inicjuj_scene() jednorazowo uaktywniamy cały aparat teksturowania:

void TForm1:: inicjuj_scene(void)

{

glClearColor(0.8, 0.8, 0.8, 0.0); //tło szareglEnable(GL_TEXTURE_2D);

}

Na koniec wystarczy trochę zmodyfikować kod procedury rysuj_scene(), dodając proces teksturowania wykreślanego prymitywu:

glBegin(GL_QUADS);

glTexCoord2f(0,0); glVertex3f(-5, -5, -50);

glTexCoord2f(0,1); glVertex3f(-5, 5, -50);

glTexCoord2f(1,1); glVertex3f(5, 5, -50);

glTexCoord2f(1,0); glVertex3f(5, -5, -50);

glEnd();

Tekstury w OpenGL

Rysunek 2. Teksturę przypinamy do wierzchołków prymitywów (do werteksów), posługując się umownymi oznaczeniami jej rogów.

Nowością w powyższym kodzie jest funkcja glTexCoord2f(s,t). Za jej pomocą przypinamy teksturę do wszystkich rogów czworokąta, to znaczy kojarzymy cztery rogi tekstury z czterema wierzchołkami (werteksami) kwadratu. Współrzędne (s,t) w symboliczny sposób definiują rogi tekstury. Rysunek 2 przedstawia istotę tej definicji.

W środowisku Delphi należy jeszcze zadeklarować chęć użycia dwóch funkcji, wyeksportowanych z pliku DLL:

procedure glGenTextures(n: GLsizei;

var textures: GLuint); stdcall; external opengl32;

procedure glBindTexture(target: GLenum;

texture: GLuint); stdcall; external opengl32;

Dokładne informacje na ten temat dostępne są w plikach źródłowych zamieszczonych na płytach CD.

Nasz pierwszy program prezentuje obraz rozpięty na statycznym kwadracie (rys. 3). Zwróćmy uwagę, jak sprawnie biblioteka OpenGL wyświetla obraz podczas zmian jego rozmiaru, wykonując przy tym wewnętrzne algorytmy dopasowywania stałej mapy bitowej do zmiennej powierzchni obiektu.

Biblioteka tekstur

Tekstury w OpenGL

Rysunek 3. Pierwszy pokryty teksturą obiekt nie wygląda zbyt imponująco, a program jest właściwie prostą przeglądarką plików graficznych z bardzo wydajnym skalowaniem rozmiarów.

Zazwyczaj operujemy większą liczbą tekstur. W następnym przykładzie wprowadzimy do gry cały ich zestaw, nauczymy się nimi zarządzać za pomocą identyfikatorów, a także zrealizujemy dynamiczny obraz wirującej kostki, której "nieoteksturowaną" wersję znamy z poprzednich części naszego kursu.

W poprzednim przykładzie funkcja wczytaj_teksture() pobierała z dysku plik o ściśle ustalonej nazwie. Nie było to dobre rozwiązanie. Zmienimy nagłówek procedury wczytaj_teksture() tak, żeby mogła przygotowywać tekstury na podstawie pliku, którego nazwa została podana jako parametr:

procedure TForm1.wczytaj_teksture(nazwa: pchar;

id: Integer);

Algorytm ma odczytać plik o nazwie nazwa i utworzyć teksturę o numerze id. Do przechowywania uchwytów tekstur (wartości zmiennej nr_tekstury z poprzedniego przykładu) zaimplementujemy tablicę, zdefiniowaną w sekcji prywatnej klasy okienka. Rozmiar tablicy jest tożsamy z liczbą używanych tekstur. W przykładzie 2, gdzie wykorzystujemy pięć tekstur, znajduje się następująca deklaracja tablicy numerów:

var tekstura: array[0..4] of Integer;

Tekstury w OpenGL

Rysunek 4. Na obracającą się kostkę nałożono kilka różnych tekstur, które program przechowuje w swojego rodzaju bibliotece. Tekstury są identyfikowane przez swoje numery.

Taka definicja pozwala na wczytywanie pięciu plików i przechowywanie numerów tekstur w tablicy tekstura[]. Zmian w konstrukcji algorytmu wczytaj_teksture() jest niewiele i mają charakter porządkowy, jednak warto je prześledzić w plikach przykładowych. Wywołanie tej funkcji w Delphi wyglądałoby teraz następująco:

procedure TForm1.FormCreate(Sender: TObject);

begin

otworz_OpenGL;

//wczytanie kolejnych tekstur

wczytaj_teksture('tekstury/5.raw',4);

wczytaj_teksture('tekstury/4.raw',3);

wczytaj_teksture('tekstury/3.raw',2);

wczytaj_teksture('tekstury/2.raw',1);

wczytaj_teksture('tekstury/1.raw',0);

end;

Tak jak w poprzednim przykładzie, w funkcji inicjuj_scene() uaktywniamy aparat teksturowania i dodatkowo - ponieważ będziemy wykreślać trójwymiarową kostkę - w znany sposób włączamy analizator głębi OpenGL:

void TForm1:: inicjuj_scene(void)

{

glClearColor(0.8, 0.8, 0.8, 0.0); //tło szare

glEnable(GL_TEXTURE_2D);

glEnable(GL_DEPTH_TEST);

}

Procedura rysuj_scene() wykreśla sekwencję czworoboków - ścianek kostki (patrz poprzednie części kursu). Przed wykreśleniem czworoboku wybieramy z biblioteki (to znaczy z tablicy tekstura[]) właściwy numer tekstury. Wykreślając czworobok, przypisujemy do każdego wierzchołka (werteksu) odpowiedni róg płachty tekstury. Oto fragment algorytmu w C++ Builder: