Podstawy
Pierwsza wersja biblioteka OpenGL (ang. Open Graphics Library) powstała w 1992 roku na bazie języka GL opracowanego przez firmę Silicon Graphics Inc. (w skrócie SGI) na potrzeby stacji graficznych IRIS. Dopiero jednak sukces systemów z rodziny Microsoft Windows, w których zaimplementowano OpenGL w wersji 1.1, stał się początkiem ogromnej popularności biblioteki. Obecnie OpenGL jest podstawowa niskopoziomowa biblioteka graficzna 3D, obsługiwana przez wszystkie liczące się systemy operacyjne oraz większość procesorów graficznych.
Niezależność od platformy sprzętowej oraz ogólnie dostępna specyfikacji czyni z OpenGL standard powszechnie wykorzystywany przez producentów oprogramowania użytkowego i gier. Rozwojem OpenGL zajmuje się organizacja ARB (ang. Architecture Review Board), w skład której wchodzą przedstawiciele firm 3DLabs, Apple, ATI, Dell, IBM, Intel, NVIDIA, SGI i Sun (stan na koniec 2004 roku). Taki sposób wprowadzania zmian w bibliotece zapewnia zachowanie niezależności OpenGL od jednej platformy sprzętowej lub programowej przy jednoczesnym uwzględnieniu do najnowszych osiągnięć w dziedzinie grafiki komputerowej. Materiały ze spotkań członków ARB, specyfikacje i szeregu innych materiałów na temat OpenGL dostępne są na oficjalnej stronie ARB:
http://www.opengl.org/. Ważnym uzupełnieniem OpenGL jest biblioteka GLU (ang. OpenGL Graphics System Utility Library). GLU zawiera szereg dodatkowych narzędzi, w tym do obsługi macierzy, odwzorowania tekstur, kafelkowania wielokątów, powierzchni drugiego stopnia oraz krzywych i powierzchni NURBS.
Składnia
Polecenia OpenGL określane są jako funkcje lub procedury. Znaczna część funkcji wykonuje te same operacje, ale rożni się zbiorem argumentów. Przyjęta konwencja nazewnictwa określa ilość i rodzaj parametrów funkcji według poniższego schematu:
rtype Name {1|2|3|4} {b|s|i|f|d|ub|us|ui} {v}
([args,] T arg1, ..., T argN [,args])
gdzie poszczególne elementy oznaczają:
Składnia ta przypomina w swoich założeniach notacje węgierska, stosowana m.in. w API systemów z rodziny Windows. Może ona początkowo sprawiać problemy, ale przy pewnej praktyce okazuje się praktyczna i wygodna w stosowaniu. Podobnie jak w specyfikacja biblioteki OpenGL ta i dalsza
część opisu wykorzystuje notacje przyjęta w języku ANSI C.
Typy danych
Poniższa tabela zawiera typy danych dostępne w bibliotece OpenGL.
Tabela 1: Typy danych w OpenGL
Specyfikacja nie określa jakiego rodzaju typy danych są użyte w konkretnej implementacji biblioteki OpenGL. W szczególnosci typy danych OpenGL nie są typami danych występującymi w języku C (pomimo częściowej zgodności nazw). Implementacja OpenGL może stosować typy danych zawierające większą niż minimalna ilość bitów. prtbits oznacza minimalna ilość bitów niezbędna do umieszczenia wskaźnika Stad typy intptr i sizeiptr muszą umożliwić zapamiętanie dowolnego adresu. Poza wyżej wymienionymi typami danych biblioteka OpenGL zawiera typ pusty GLvoid.
Układ współrzędnych
Biblioteka OpenGL stosuje prawoskrętny układ współrzędnych kartezjańskich (patrz rysunek 1), 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.
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:
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. Przy jej pomocy zostały napisane m.in. przykłady z pracy [3]. 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:
GLenum glGetError( void )
Oto znaczenie poszczególnych kodów błędów:
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 zapamietywany, 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:
const GLubyte * gluErrorString( GLenum errorCode )
Przykładowo błąd o kodzie
GL_INVALID_VALUE spowoduje zwrócenie ciągu znaków "invalid value".