Janusz Ganczarski
OpenGL
Podstawy
Spis treści
Spis treści . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1
Typy danych . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2
Układ współrzędnych . . . . . . . . . . . . . . . . . . . . . . . . . .
3
Barwy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4
Okno renderingu . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4
Maszyna stanów . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5
Obsługa błędów . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5
Literatura . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
7
1. Podstawy
Pierwsza wersja biblioteka OpenGL (ang. Open Graphics Library) po-
wstał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 zaimple-
mentowano OpenGL w wersji 1.1, stał się początkiem ogromnej popularności
biblioteki.
Obecnie OpenGL jest podstawową niskopoziomową biblioteką graficzną
3D, obsługiwaną przez wszystkie liczące się systemy operacyjne oraz więk-
szość procesorów graficznych. Niezależność od platformy sprzętowej oraz
ogólnie dostępna specyfikacji czyni z OpenGL standard powszechnie wy-
korzystywany przez producentów oprogramowania użytkowego i gier.
Rozwojem OpenGL zajmuje się organizacja ARB (ang. Architecture Re-
view 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 nie-
zależ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:
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 wielo-
kątów, powierzchni drugiego stopnia oraz krzywych i powierzchni NURBS.
1.1. Składnia
Polecenia OpenGL określane są jako funkcje lub procedury. Znaczna
część funkcji wykonuje te same operacje, ale róż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ą:
— rtype - wartość zwracana przez funkcję,
— Name - nazwa funkcji poprzedzona przedrostkiem gl lub glu dla funkcji
z biblioteki GLU,
— 1, 2, 3, 4 - ilość argumentów funkcji,
— b - argumenty typu GLbyte,
1. Podstawy
2
— s - argumenty typu GLshort,
— i - argumenty typu GLint,
— f - argumenty typu GLfloat,
— d - argumenty typu GLdouble,
— ub - argumenty typu GLubyte,
— us - argumenty typu GLushort,
— ui - argumenty typu GLuint,
— v - argument funkcji stanowi tablica wartości; w tym wypadku nie wy-
stępuje określenie ilości argumentów funkcji,
— T arg1, ..., T argN - argumenty funkcji.
Składnia ta przypomina w swoich założeniach notację węgierską, sto-
sowaną m.in. w API systemów z rodziny Windows. Może ona początkowo
sprawiać problemy, ale przy pewnej praktyce okazuje się praktyczna i wygod-
na w stosowaniu. Podobnie jak w specyfikacja biblioteki OpenGL ta i dalsza
część opisu wykorzystuje notację przyjętą w języku ANSI C.
1.2. Typy danych
Tabela 1 zawiera typy danych dostępne w bibliotece OpenGL.
typ OpenGL
minimalna
opis
ilość bitów
GLboolean
1
typ logiczny
GLbyte
8
liczba całkowita ze znakiem (U2)
GLubyte
8
liczba całkowita bez znaku
GLchar
8
ciąg znaków tekstowych
GLshort
16
liczba całkowita ze znakiem (U2)
GLushort
16
liczba całkowita bez znaku
GLint
32
liczba całkowita ze znakiem (U2)
GLuint
32
liczba całkowita bez znaku
GLsizei
32
nieujemna liczba całkowita
GLenum
32
typ wyliczeniowy całkowity
GLintptr
ptrbits
wskaźnik na liczbę całowitą ze znakiem (U2)
GLsizeiptr
ptrbits
wskaźnik na nieujemną liczbę całkowitą
GLbitfield
32
pole bitowe
GLfloat
32
liczba zmiennoprzecinkowa
GLclampf
32
liczba zmiennoprzecinkowa z przedziału [0, 1]
GLdouble
64
liczba zmiennoprzecinkowa
GLclampd
64
liczba zmiennoprzecinkowa z przedziału [0, 1]
Tabela 1: Typy danych w OpenGL
1. Podstawy
3
Specyfikacja nie określa jakiego rodzaju typy danych są użyte w konkret-
nej implementacji biblioteki OpenGL. W szczególności typy danych OpenGL
nie są typami danych występującymi w języku C (pomimo częściowej zgod-
ności nazw). Implementacja OpenGL może stosować typy danych zawierają-
ce większą niż minimalna ilość bitów. prtbits oznacza minimalną ilość bitów
niezbędną do umieszczenia wskaźnika. Stąd typy intptr i sizeiptr mu-
szą umożliwić zapamiętanie dowolnego adresu. Poza wyżej wymienionymi
typami danych biblioteka OpenGL zawiera typ pusty GLvoid.
1.3. Układ współrzędnych
Biblioteka OpenGL stosuje prawoskrętny układ współrzędnych karte-
zjańskich (patrz rysunek 1), w którym oś OZ skierowana jest prostopadle do
płaszczyzny monitora. Warto także pamiętać, że literatura informatyczna
preferuje lewoskrętne układy współrzędnych z osią OZ skierowaną w głąb
monitora.
0
X
Y
Z
Rysunek 1. Układ współrzędnych w OpenGL
1.4. 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
1. Podstawy
4
indeksowym z użyciem mapy (tablicy) barw. Obecne możliwości proceso-
rów graficznych czynią stosowanie trybu indeksowego nieopłacalnym, stąd
w przykładowych programach będziemy używać pełnego zakresu barw ofe-
rowanego 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.
1.5. 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 im-
plementacjach często jest łączony z buforem głębokości. Ostatni z wymie-
nionych 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 two-
rzenia okna renderingu.
1.6. Okno renderingu
Jedną z konsekwencji sprzętowej i systemowej niezależności biblioteki
OpenGL jest brak jakichkolwiek funkcji obsługujących komunikację z użyt-
kownikiem, 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 bi-
bliotekę GLX, Microsoft Windows bibliotekę WGL, IBM OS/2 bibliotekę
PGL, a Mac OS X aż trzy biblioteki: AGL, CGL i NSGL. Także systemy
1. Podstawy
5
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 ope-
racyjnego powoduje, że danego programu nie można skompilować i urucho-
mić 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 komuni-
katów. Pierwszą biblioteką tego typu była biblioteka AUX (ang. Auxiliary
Library), zwana także pod nazwą GLAUX. Przy jej pomocy zostały napisane
m.in. przykłady z pracy [3]. Jednak największą popularność zdobyła biblio-
teka 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 konwersję programów korzysta-
ją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
popularną i powszechnie stosowaną wieloplatformową biblioteką służąca do
uruchamiania programów w OpenGL. Stąd naturalna decyzja o wyborze tej
biblioteki przy pisaniu przykładowych programów.
1.7. Maszyna stanów
Maszyna stanów OpenGL to po prostu zbiór wszystkich zmiennych we-
wnętrznych (zmiennych stanu) i ustawień biblioteki. Wiele zmiennych stanu
jest dwustanowych, inne mają wartości całkowite lub zmiennoprzecinkowe.
Ważną cechą maszyny stanów OpenGL jest zachowywanie zmiennych
stanu do czasu, aż zostaną one zmienione przez jakąś funkcję. Pozwala to
na prostą optymalizację programów poprzez oddzielenie i jednokrotne wy-
wołanie grupy funkcji ustawiających wartości tych zmiennych stanu, które
nie ulegają dalszym zmianom.
1.8. Obsługa błędów
Ważne znaczenie w bibliotece OpenGL spełniają zmienne stanu oznacza-
jące wystąpienie błędu. Informację o kodzie bieżącego błędu zwraca funkcja:
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,
1. Podstawy
6
— 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. Wy-
ją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. Stąd w przy-
padku 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 ko-
dó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, wska-
zany w parametrze errorCode, zwraca funkcja:
const GLubyte *gluErrorString (GLenum errorCode)
Przykładowo błąd o kodzie GL INVALID VALUE spowoduje zwócenie ciągu
znaków „invalid value”.
Literatura
7
Literatura
[1] Mark Segal, Kurt Akeley: The OpenGL Graphics System. A Specification Ver-
sion 2.0
[2] Jackie Neider, Tom Davis, Mason Woo: OpenGL Programming Guide „The
Red Book”
[3] Richard S. Wright jr, Michael Sweet: OpenGL Księga eksperta, Helion 1999
[4] Richard S. Wright jr, Michael Sweet: OpenGL Księga eksperta Wydanie III,
Helion 2005
[5] The official OpenGL web page,
[6] Piotr Andrzejewski, Jakub Kurzak: Wprowadzenie do OpenGL. Programowanie
zastosowań graficznych, Kwantum 2000
[7] Kevin Hawkins, Dave Astle: OpenGL. Programowanie gier, Helion 2003
[8] Mark J. Kilgard: The OpenGL Utility Toolkit (GLUT) Programming Interface
API Version 3. Silicon Graphics, Inc. 1996