Janusz Ganczarski
OpenGL
Pierwszy program
Spis treści
Spis treści . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1
1. Pierwszy program . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1
Rysowanie sceny 3D . . . . . . . . . . . . . . . . . . . . . . . . . . .
1
Kolor tła . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1
. . . . . . . . . . . . . . . . . . .
1
Kolor obiektu . . . . . . . . . . . . . . . . . . . . . . . . . .
1
Definiowanie obiektu . . . . . . . . . . . . . . . . . . . . . .
2
Wykonanie poleceń OpenGL i zamiana buforów koloru . . .
2
Tworzenie okna renderingu . . . . . . . . . . . . . . . . . . . . . . .
3
Obsługa menu podręcznego . . . . . . . . . . . . . . . . . . . . . . .
3
Plik kwadrat1.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4
Literatura . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
7
1. Pierwszy program
Pierwszy program korzystający z biblioteki OpenGL jest oczywiście bar-
dzo prosty. Wyświetlimy w oknie o rozmiarach 400 × 400 pikseli kwadrat
o bokach jednostkowych. Program składa się z trzech zasadniczych elemen-
tów. Pierwszy to funkcja rysująca scenę 3D, drugim jest inicjacja okna ren-
deringu a trzecim obsługa menu podręcznego.
1.1. Rysowanie sceny 3D
Rysowanie, czy też jak przyjęło się to nazywać, renderowanie sceny 3D,
składa się z kilku kroków. Z uwagi na prostotę programu etapy występujące
w pierwszym programie nie przedstawiają kompletnego schematu tworzenia
sceny 3D.
1.1.1. Kolor tła
Pierwszym etapem tworzenia sceny 3D, który realizuje funkcja Display,
jest określenie koloru tła, czyli wartości jakimi zostanie wypełniony bufor
koloru. Realizuje to funkcja:
void glClearColor (GLclampf red, GLclampf green, GLclampf blue,
GLclampf alpha)
której parametry red, green, blue określają wartości składowych koloru,
a parametr alpha wartość składowej kanału alfa (stopień przezroczystości
piksela). Wartości wszystkich parametrów funkcji glClearColor powinny
zawierać się w przedziale [0, 1]. Parametry przekraczające powyższy zakres
zostaną odpowiednio przycięte: mniejsze od 0 przyjmą wartość 0, większe od
1 wartość 1. Domyślne podczas czyszczenia bufora koloru używa się koloru
(0, 0, 0, 0).
1.1.2. Czyszczenie bufora koloru
Po określeniu koloru tła przystępujemy do wyczyszczenia tła, czyli wy-
pełnienia zawartości bufora koloru. Wykonuje to funkcja:
void glClear (GLbitfield mask)
której na razie jedynym parametrem jest stała GL COLOR BUFFER BIT okre-
ślająca jaki element bufora ramki ma zostać wypełniony.
1.1.3. Kolor obiektu
Kolejnym etapem tworzenia naszej sceny 3D jest określenie koloru obiek-
tu. Wykorzystamy do tego celu jedną z funkcji z rodziny glColor:
void glColor3f (GLfloat red, GLfloat green, GLfloat blue)
1. Pierwszy program
2
której parametry red, green, blue określają wartości składowych koloru.
Zakres tych wartości powinny zawierać się w przedziale [0, 1]. Wartości znaj-
dujące się poza tym przedziałem zostaną odpowiednio przycięte.
Uważny Czytelnik zapyta zapewne dlaczego dla koloru obiektu nie okre-
ślamy wartości składowej alfa. Jest to oczywiście możliwe - rodzina funk-
cji glColor zawiera także funkcje określające kolor na podstawie czterech
składowych. Jeżeli jednak zdecydujemy się na określanie tylko składowych
RGB, składowa alfa przyjmuje domyślną wartość 1,0 (całkowita nieprzezro-
czystość).
1.1.4. Definiowanie obiektu
Definiowanie obiektów w OpenGL rozpoczyna wywołanie funkcji:
void glBegin (GLenum mode)
która określa rodzaj generowanego prymitywu lub prymitywów. W pierw-
szym programie traktujemy kwadrat jako szczególny przypadek wielokąta,
stąd stała GL POLYGON. Kolejne wierzchołki kwadratu określamy przy pomo-
cy funkcji:
void glVertex3f (GLfloat x, GLfloat y, GLfloat z)
która należy do rodziny obszernej funkcji glVertex. Jeżeli uważnie popa-
trzymy na współrzędne wierzchołków rysowanego kwadratu, to zauważymy,
że zawiera się on w płaszczyźnie o równaniu Z = 0. W takim przypadku
do definiowania współrzędnych wierzchołków obiektów można także zasto-
sować funkcję glVertex2, która pozwala określić dwie pierwsze współrzędne
wierzchołków, trzeciej nadając wartość 0.
Definiowane współrzędnych wierzchołków obiektu obowiązkowo kończy
wywołanie funkcji:
void glEnd (void)
Specyfikacja biblioteki nie pozwala na uruchamianie wszystkich poleceń
OpenGL pomiędzy parą wywołań funkcji glBegin i glEnd. Co do zasady
mogą się tam znaleźć polecenia generujące obiekty sceny. Wywołanie nie-
dozwolonej funkcji powoduje zgłoszenie błędu, ale nie przerywa działania
programu.
1.1.5. Wykonanie poleceń OpenGL i zamiana buforów koloru
To w jaki sposób biblioteka utworzy scenę 3D, po wywołaniu wszystkich
funkcji tworzących jej elementy, zależy oczywiście od konkretnej implemen-
tacji. Jednak wywołując funkcję:
void glFlush (void)
1. Pierwszy program
3
możemy wymusić wykonanie wszystkich dotychczasowych poleceń. Ma to
szczególne znaczenie, gdy dana implementacja stosuje bufory poleceń, a za-
leży nam na wykonaniu części zadań.
Końcowym elementem tworzenia sceny 3D jest zamiana buforów koloru,
co w przypadku stosowania biblioteki GLUT realizuje funkcja:
void glutSwapBuffers (void)
1.2. Tworzenie okna renderingu
Okno renderingu tworzone jest funkcji main programu. Inicjalizację bu-
fora ramki wykonuje funkcja:
void glutInitDisplayMode (unsigned int mode)
W przykładowym programie wartość parametru mode decyduje, że bufor
ramki zawiera dwa bufory koloru (stała GLUT DOUBLE), które pracują w try-
bie RGB (stała GLUT RGB).
Rozmiar okna renderingu, w którym będzie rysowana scena 3D określa
funkcja:
void glutInitWindowSize (int width, int height)
której parametry width i height oznaczają odpowiednio szerokość i wyso-
kość obszaru dostępnego do renderingu. Warto zauważyć, że wielkość okna
jakie zostanie utworzone po wywołaniu funkcji:
int glutCreateWindow (char *name)
jest zależna od systemu operacyjnego i jest tak dobrane aby obszar dostępny
do renderingu miał wcześniej określone rozmiary. W przykładowym progra-
mie obszar renderingu jest stały - zmiana rozmiaru okna (funkcja Reshape)
nie modyfikuje jego rozmiarów. Zmiana rozmiaru okna nie powoduje zmiany
wielkości ani przemieszczenia rysowanego kwadratu.
Ostatnim etapem tworzenia okna renderingu jest dołączenie funkcji ge-
nerującej scenę 3D (Display) oraz funkcji wywoływanej przy zmianie roz-
miarów okna (Reshape). Realizują to funkcje:
void glutDisplayFunc (void (*func)(void))
void glutReshapeFunc (void (*func)(int width, int height))
1.3. Obsługa menu podręcznego
Menu podręczne tworzy funkcja:
int glutCreateMenu (void (*func)(int value))
1. Pierwszy program
4
której parametrem jest wskaźnik do funkcji obsługi komunikatów menu
(w programie funkcja Menu) a zwracana wartość to unikatowy numer menu.
Dodanie kolejnych pozycji do menu podręcznego umożliwia funkcja:
void glutAddMenuEntry (char *name, int value)
której parametry to nazwa pozycji menu i numer (unikatowy) przekazywany
w przypadku wybrania tej pozycji do funkcji obsługującej komunikaty menu.
W tym i dalszych programach unikatowość numerów menu zapewnia zasto-
sowanie typu wyliczeniowego. W pierwszym programie menu ma minimalną
zawartość - umożliwia jedynie wyjście z programu. Z uwagi na różnice w ko-
dowaniu polskich znaków w różnych systemach operacyjnych wywołanie tej
funkcji ujęte zostało w bloku instrukcji warunkowych preprocesora:
#ifdef WIN32
#else
#endif
Ostatnią operacją przy tworzeniu menu podręcznego jest wywołanie funk-
cji określającej, który przycisk myszki aktywuje menu:
void glutAttachMenu (int button)
Możliwe są następujące wartości parametru button:
— GLUT LEFT BUTTON - lewy przycisk myszki,
— GLUT MIDDLE BUTTON - środkowy przycisk myszki,
— GLUT RIGHT BUTTON - prawy przycisk myszki.
1.4. Plik kwadrat1.cpp
Początkowe okno programu kwadrat1.cpp, którego tekst źródłowy znaj-
duje się poniżej, przedstawia rysunek 1.
/∗
( c )
J a n u s z
G a n c z a r s k i
( Power )
h t t p : / / www . j a n u s z g . h g . p l
J a n u s z G @ e n t e r . n e t . p l
∗/
#i n c l u d e <GL/ g l u t . h>
#i n c l u d e < s t d l i b . h>
//
f u n k c j a
g e n e r u j ą c a
s c e n ę
3D
void
D i s p l a y
( )
{
//
k o l o r
t ł a − z a w a r t o ś ć
b u f o r a
k o l o r u
g l C l e a r C o l o r
( 1 . 0 , 1 . 0 , 1 . 0 , 1 . 0 ) ;
//
c z y s z c z e n i e
b u f o r a
k o l o r u
g l C l e a r
( GL COLOR BUFFER BIT ) ;
//
k o l o r
k w a d r a t u
g l C o l o r 3 f
( 1 . 0 , 0 . 0 , 0 . 0 ) ;
//
p o c z ą t e k
d e f i n i c j i
w i e l o k ą t a
g l B e g i n
(GL POLYGON ) ;
1. Pierwszy program
5
Rysunek 1. Okno początkowe programu Kwadrat 1
//
k o l e j n e
w i e r z c h o ł k i
w i e l o k ą t a
g l V e r t e x 3 f
( 0 . 0 ,
0 . 0 ,
0 . 0 ) ;
g l V e r t e x 3 f
( 0 . 0 ,
1 . 0 ,
0 . 0 ) ;
g l V e r t e x 3 f
( 1 . 0 ,
1 . 0 ,
0 . 0 ) ;
g l V e r t e x 3 f
( 1 . 0 ,
0 . 0 ,
0 . 0 ) ;
//
k o n i e c
d e f i n i c j i
p r y m i t y w u
g l E n d
( ) ;
//
s k i e r o w a n i e
p o l e c e ń
do
w y k o n a n i a
g l F l u s h
( ) ;
//
z a m i a n a
b u f o r ó w
k o l o r u
g l u t S w a p B u f f e r s ( ) ;
}
//
z m i a n a
w i e l k o ś c i
o k n a
void
R esh ape
( i n t
width ,
i n t
h e i g h t )
{
//
g e n e r o w a n i e
s c e n y
3D
D i s p l a y
( ) ;
}
//
s t a ł e
do
o b s ł u g i
menu
p o d r ę c z n e g o
enum
{
EXIT //
w y j ś c i e
} ;
//
o b s ł u g a
menu
p o d r ę c z n e g o
void Menu ( i n t
v a l u e )
{
1. Pierwszy program
6
switch
( v a l u e )
{
//
w y j ś c i e
c a s e EXIT :
e x i t
( 0 ) ;
}
}
i n t
main
( i n t
a r g c ,
char ∗ a r g v [ ] )
{
//
i n i c j a l i z a c j a
b i b l i o t e k i
GLUT
g l u t I n i t
(& a r g c , a r g v ) ;
//
i n i c j a l i z a c j a
b u f o r a
r a m k i
g l u t I n i t D i s p l a y M o d e
(GLUT DOUBLE | GLUT RGB ) ;
//
r o z m i a r y
g ł ó w n e g o
o k n a
p r o g r a m u
g l u t I n i t W i n d o w S i z e
( 4 0 0 , 4 0 0 ) ;
//
u t w o r z e n i e
g ł ó w n e g o
o k n a
p r o g r a m u
g l u t C r e a t e W i n d o w
( ” Kwadrat 1 ” ) ;
//
d o ł ą c z e n i e
f u n k c j i
g e n e r u j ą c e j
s c e n ę
3D
g l u t D i s p l a y F u n c
( D i s p l a y ) ;
//
d o ł ą c z e n i e
f u n k c j i
w y w o ł y w a n e j
p r z y
z m i a n i e
r o z m i a r u
o k n a
g l u t R e s h a p e F u n c
( Re sha pe ) ;
//
u t w o r z e n i e
menu
p o d r ę c z n e g o
g l u t C r e a t e M e n u
( Menu ) ;
//
d o d a d n i e
p o z y c j i
do menu
p o d r ę c z n e g o
#i f d e f WIN32
glutAddMenuEntry
( ” W y j ś c i e ” , EXIT ) ;
#e l s e
glutAddMenuEntry
( ” W y j s c i e ” , EXIT ) ;
#e n d i f
//
o k r e ś l e n i e
p r z y c i s k u
m y s z k i
o b s ł u g u j ą c e j
menu
p o d r ę c z n e
g l u t A t t a c h M e n u
(GLUT RIGHT BUTTON ) ;
//
w p r o w a d z e n i e
p r o g r a m u
do
o b s ł u g i
p ę t l i
k o m u n i k a t ó w
g l u t M a i n L o o p
( ) ;
return
0 ;
}
Literatura
7
Literatura
[1] Mark Segal, Kurt Akeley: The OpenGL Graphics System. A Specification
Version 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. Programowa-
nie 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