Tak
jak już obiecałam postaram się rozszerzyć wiedzę na temat
biblioteki OpenGL. Post ten będzie skupiał się na teorii ogólnie
związanej z tą biblioteką, a mianowicie umieszczę informację o
układzie współrzędnych, o barwach, buforze ramki, a także o
oknie renderingu.
Układ współrzędnych
Biblioteka OpenGL stosuje prawoskrętny
układ współrzędnych kartezjańskich (pokazane na rysunku), w
którym os OZ skierowana jest prostopadle do płaszczyzny monitora.
Warto także pamiętać, ze literatura informatyczna preferuje
lewoskrętne układy współrzędnych z osia OZ skierowana w głąb
monitora.
Układ współrzędnych w OpenGL
Barwy
Biblioteka OpenGL wykorzystuje model barw RGB, opierający się na
trzech podstawowych barwach: czerwonej, zielonej i niebieskiej. Barwa
może być opisywana bezpośrednio przez wartości składowych RGB,
bądź w trybie indeksowym z użyciem mapy (tablicy) barw. Obecne
możliwości procesorów graficznych czynią stosowanie trybu
indeksowego nieopłacalnym, stad w przykładowych programach będziemy
używać pełnego zakresu barw oferowanego przez model RGB, w razie
potrzeby uzupełniając składowe RGB o kanał alfa (
RGBA).
Wybór trybu w jakim będzie generowany obraz dokonywany jest podczas
tworzenia okna renderingu.
Bufor ramki
W OpenGL w skład bufora ramki (pamięci obrazu) wchodzą
następujące elementy:
bufor koloru (ang. color
buffer),
bufor głębokości, nazywany
także buforem głębi (ang. depth buffer),
bufor szablonowy, nazywany także
buforem szablonu (ang. stencil buffer),
- bufor akumulacyjny (ang. accumulation buffer).
Specyfikacja wymaga istnienie co najmniej jednego bufora koloru,
ale implementacje biblioteki OpenGL zawierają najczęściej dwa
bufory koloru: przedni i tylni. Zamiana buforów umożliwia płynne
wyświetlenie animacji - jeden bufor jest aktualnie prezentowany na
ekranie monitora, a drugi służy do generowania nowej sceny 3D.
Ponadto implementacja OpenGL może zawierać lewe i prawe bufory
koloru, które umożliwiają tworzenie obrazów stereoskopowych.
Bufor głębokości używany jest podczas działania algorytmu
Z-bufor, którego zadaniem jest ukrywanie niewidocznych powierzchni.
Bufor szablonu służy do ograniczenia obszaru renderingu do wybranej
części okna i w implementacjach często jest łączony z buforem
głębokości Ostatni z wymienionych elementów ramki - bufor
akumulacyjny, umożliwia łączenie kilku obrazów w celu uzyskania
określonego efektu końcowego Wybór, które bufory wchodzą w skład
ramki dokonuje się podczas tworzenia okna renderingu.
Okno renderingu
Jedna z konsekwencji sprzętowej i systemowej niezależności
biblioteki OpenGL jest brak jakichkolwiek funkcji obsługujących
komunikacje z użytkownikiem, w tym obsługi okien, klawiatury i
myszki. Większość graficznych systemów operacyjnych posiada
jednak specjalizowane funkcje pozwalające na obsługę okna
renderingu OpenGL. Przykładowo X Windows zawiera bibliotekę GLX,
Microsoft Windows bibliotekę WGL, IBM OS/2 bibliotekę PGL, a Mac OS
X aż trzy biblioteki: AGL, CGL i NSGL. Także systemy wbudowane,
korzystające ze znacznie skromniejszej biblioteki OpenGL ES (ang.
OpenGL Embedded Systems), zawierają bibliotekę narzędziową EGL.
Oczywiście stosowanie rozwiązań specyficznych dla danego systemu
operacyjnego powoduje, ze danego programu nie można skompilować i
uruchomić w innym systemie operacyjnym bez dokonania szeregu zmian w
tekście źródłowym Rozwiązanie tego problemu stanowią biblioteki
oferujące jeden, niezależny od systemu operacyjnego, interfejs do
obsługi okien i komunikatów.
Pierwsza biblioteka tego typu
była biblioteka AUX (ang.
Auxiliary Library), zwana także
pod nazwa GLAUX. Jednak największą popularność zdobyła
biblioteka GLUT (ang.
OpenGL Utility Toolkit), opracowana i
rozwijana w latach 1994-1998 przez Marka J. Kilgarda. Jej autor
rozwinął idee zapoczątkowane przez twórców biblioteki AUX, co
ułatwia konwersje programów korzystających z tej biblioteki (patrz
skrypt aux2glut.sed). Bibliotek GLUT, choć od kilku lat nie
rozwijana (ostatnia wersja to 3.6), jest ciągle najbardziej
popularna i powszechnie stosowana wieloplatformowa biblioteka służąca
do uruchamiania programów w OpenGL. Stad naturalna decyzja o wyborze
tej biblioteki przy pisaniu przykładowych programów.
Maszyna stanów
Maszyna stanów OpenGL to po prostu zbiór wszystkich zmiennych
wewnętrznych (zmiennych stanu) i ustawień biblioteki. Wiele
zmiennych stanu jest dwustanowych, inne maja wartości całkowite lub
zmiennoprzecinkowe. Ważna cecha maszyny stanów OpenGL jest
zachowywanie zmiennych stanu do czasu, aż zostaną one zmienione
przez jakąś funkcje. Pozwala to na prosta optymalizacje programów
poprzez oddzielenie i jednokrotne wywołanie grupy funkcji
ustawiających wartości tych zmiennych stanu, które nie ulegają
dalszym zmianom.
Obsługa błędów
Ważne znaczenie w bibliotece OpenGL
spełniają zmienne stanu oznaczające wystąpienie błędu
Informacje o kodzie bieżącego błędu zwraca funkcja:
C/C++
GLenum glGetError( void )
Oto znaczenie poszczególnych kodów
błędów:
GL_NO_ERROR
- brak błędu,
GL_INVALID_ENUM
- argument typu
wyliczeniowego poza dopuszczalnym zakresem,
GL_INVALID_VALUE
- argument liczbowy
poza dopuszczalnym zakresem,
GL_INVALID_OPERATION
- operacja niewykonalna w obecnym stanie,
GL_STACK_OVERFLOW
- operacja
spowodowałaby przepełnienie stosu,
GL_STACK_UNDERFLOW
- operacja
spowodowałaby niedomiar stosu,
GL_OUT_OF_MEMORY
- brakuje pamięci do wykonania operacji,
GL_TABLE_TOO_LARGE
- wskazana tablica jest za duża.
Wystąpienie błędu nie powoduje
przerwania wykonywania programu - nie jest wykonywana jedynie funkcja
odpowiedzialna za jego powstanie. Wyjątek stanowi wystąpienie błędu
o kodzie GL_OUT_OF_MEMORY, który powoduje powstanie stanu
nieokreślonego Uwagę należy zwrócić na mechanizm przechowywania
kodów błędów Każdy rodzaj błędu jest oddzielnie zapamiętywany,
a każdorazowe wywołanie funkcji glGetError zwraca kod tylko jednego
błędu Stad w przypadku sprawdzania wystąpienia błędu niezbędne
jest wywoływanie funkcji glGetError tak długo, aż zwrócona
zostanie wartość GL_NO_ERROR. Biblioteka GLU ma odrębne
kody błędów będące odpowiednikami kodów błędów OpenGL:
GLU_INVALID_OPERATION, GLU_INVALID_ENUM,
GLU_INVALID_VALUE i GLU_OUT_OF_MEMORY. Ciąg znaków
opisujący kod błędu biblioteki OpenGL oraz GLU, wskazany w
parametrze errorCode, zwraca funkcja:
C/C++
const
GLubyte * gluErrorString( GLenum errorCode )
Przykładowo błąd o kodzie
GL_INVALID_VALUE spowoduje zwrócenie ciągu znaków
"invalid value".