Janusz Ganczarski
OpenGL
Bufor szablonowy
Spis treści
Spis treści . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1
1. Bufor szablonowy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1
Włączenie i wyłączenie bufora szablonowego
. . . . . . . . . . . . .
1
Czyszczenie bufora szablonowego . . . . . . . . . . . . . . . . . . . .
1
Sterowanie buforem szablonowym
. . . . . . . . . . . . . . . . . . .
1
. . . . . . . . . . . . . . . . . . . . . .
3
. . . . . . . . . . . . . . . . . . . . . . . . .
4
Plik odbicie.cpp . . . . . . . . . . . . . . . . . . . . . . . . .
7
Plik csg.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . .
17
Plik krawedzie.cpp . . . . . . . . . . . . . . . . . . . . . . . .
25
Plik przejscie obrazow.cpp . . . . . . . . . . . . . . . . . . .
31
Literatura . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
37
1. Bufor szablonowy
Bufor szablonowy (ang. stencil buffer) w budowie i działaniu przypomi-
na bufor głębokości. Bufor ten umożliwia utworzenie specjalnego szablonu
(matrycy) określającego obszar w buforze koloru, który będzie używany do
renderingu. Stąd właśnie porównanie funkcjonalne do bufora głębokości.
Bufor szablonowy zawiera dane w postaci liczb całkowitych. Ilość bitów
przypadających na jeden element bufora zależy od implementacji, ale nie
może być mniejsza niż 1. Wielkość tę można ustalić korzystając z funkcji
z grupy glGet z parametrem GL STENCIL BITS.
1.1. Włączenie i wyłączenie bufora szablonowego
Włączenie bufora szablonowego wymaga wywołania funkcji glEnable
z parametrem GL STENCIL TEST. Wcześniej trzeba jeszcze dodać bufor sza-
blonowy przy inicjalizacji bufora ramki. W przypadku biblioteki GLUT
sprowadza się to do dodania stałej GLUT STENCIL przy wywołaniu funkcji
glutInitDisplayMode. Wyłącznie bufora szablonowego sprowadza się do
wywołania funkcji glDisable z parametrem GL STENCIL TEST.
1.2. Czyszczenie bufora szablonowego
Zawartość bufora szablonowego, podobnie jak innych buforów wchodzą-
cych w skład bufora ramki, można wypełniać (czyścić) stałą wartością przy
pomocy znanej już funkcji glClear z parametrem GL STENCIL BUFFER BIT.
Domyślnie bufor szablonowy wypełniany jest zerami, ale wartość tę można
zmienić przy użyciu funkcji:
void glClearStencil (GLint s)
1.3. Sterowanie buforem szablonowym
Działanie bufora szablonowego reguluje kilka funkcji. Podstawową z nich
jest funkcja:
void glStencilFunc (GLenum func, GLint ref, GLuint mask)
która ustala tzw. test szablonu. Parametr func wskazuje rodzaj zastosowanej
funkcji testującej i może przyjąć jedną z poniższych wartości:
— GL NEVER - wartość testu zawsze negatywna,
— GL LESS - wartość testu pozytywna jeżeli parametr ref jest mniejszy od
wartości znajdującej się w buforze,
— GL LEQUAL wartość testu pozytywna jeżeli parametr ref jest mniejszy
lub równy wartości znajdującej się w buforze,
1. Bufor szablonowy
2
— GL GREATER - wartość testu pozytywna jeżeli parametr ref jest większy
od wartości znajdującej się w buforze,
— GL GEQUAL - wartość testu pozytywna jeżeli parametr ref jest większy
lub równy wartości znajdującej się w buforze,
— GL EQUAL - wartość testu pozytywna jeżeli parametr ref jest równy war-
tości znajdującej się w buforze,
— GL NOTEQUAL - wartość testu pozytywna jeżeli parametr ref jest różny
od wartości znajdującej się w buforze,
— GL ALWAYS - wartość testu zawsze pozytywna.
Zauważmy, że zestaw funkcji testujących bufora szablonowego jest taki sam
jak testy bufora głębokości.
Parametr ref określa tzw. wartość referencyjną używaną w teście bufora
szablonowego. Wartość ta jest zawsze obcinana do przedziału [0, 2
n
− 1],
gdzie n jest ilością bitów bufora szablonu. Przy wykonywaniu testu bufo-
ra szablonowego wykorzystywana jest maska bitowa zawarta w parametrze
mask określająca, dla których bitów wartości referencyjnej i wartości prze-
chowywanej w buforze wykonywany jest test szablonu. Operacja ta jest re-
alizowana za pomocą iloczynu logicznego testowanych wartości z wartością
maski. Domyślną wartość maski bitowej wynoszącą 1 dla każdego bitu bufora
szablonowego można zmienić przy użyciu funkcji:
void glStencilMask (uint mask)
Trzecią funkcją sterującą działaniem bufora szablonowego jest:
void glStencilOp (GLenum sfail, GLenum dpfail, GLenum dppass)
której parametry określają jaka operacja na buforze szablonowym wykony-
wana jest w przypadku:
— sfail - negatywnego wyniku testu szablonu,
— dpfali - pozytywnego wyniku testu szablonu przy negatywnym wyniku
testu bufora głębokości,
— dppass - pozytywnego wyniku testów bufora szablonowego i bufora głę-
bokości (także, gdy bufor głębokości jest wyłączony).
Każdy z parametrów sfail, dpfail i dppass może niezależnie przyjąć
jedną z poniższych wartości:
— GL KEEP - wartość bufora szablonowego nie jest zmieniana,
— GL ZERO - wartość bufora szablonowego jest zerowana,
— GL REPLACE - wartość bufora szablonowego jest zamieniana wartością
referencyjną określoną w parametrze ref funkcji glStencilFunc,
— GL INCR - wartość bufora szablonowego jest zwiększana o 1; w przypadku
wystąpienia nadmiaru rezultat przyjmuje maksymalną wartość obsługi-
waną przez bufor szablonowy,
1. Bufor szablonowy
3
— GL DECR - wartość bufora szablonowego jest zmniejszana o 1; w przypad-
ku wystąpienia niedomiaru rezultat przyjmuje wartość 0,
— GL INVERT - wartość bufora szablonowego jest negowana,
— GL DECR WRAP - wartość bufora szablonowego jest zmniejszana o 1; w przy-
padku wystąpienia niedomiaru rezultat przyjmuje maksymalną wartość
obsługiwaną przez bufor szablonowy,
— GL INCR WRAP - wartość bufora szablonowego jest zwiększana o 1; w przy-
padku wystąpienia nadmiaru rezultat przyjmuje wartość 0.
Stałe GL DECR WRAP i GL INCR WRAP zostały dodane w wersji 1.4 biblioteki
OpenGL, a wcześniej były dostępne w rozszerzeniu EXT stencil wrap.
Dla celów operacji GL INCR, GL DECR, GL DECR WRAP i GL INCR WRAP war-
tości bufora szablonowego traktowane są jak liczby całkowite bez znaku.
1.4. Rozłączny bufor szablonowy
W wersji 2.0 biblioteki OpenGL zaimplementowano zaproponowany w roz-
szerzeniach ATI separate stencil i EXT stencil two side mechanizm roz-
łącznego bufora szablonowego. Rozłączność sprowadza się do możliwości
określenia odrębnych operacji na buforze szablonowym dla przednich i tyl-
nych stron tych prymitywów graficznych, dla których OpenGL określa stro-
nę, czyli wielokątów. Natomiast przy renderingu prymitywów, dla których
nie określa się stron (m.in. punkty, linie, mapy bitowe i pikselowe) używane
są operacje określone dla przednich stron wielokątów.
Specyfikacja wprowadza trzy nowe funkcje sterujące pracą rozłącznego
bufora szablonowego:
void glStencilFuncSeparate (enum face,
enum func, int ref, uint mask)
void glStencilOpSeparate (enum face,
enum sfail, enum dpfail, enum dppass)
void glStencilMaskSeparate (enum face, uint mask)
Funkcje te różnią się od wcześniej opisanych parametrem face określającym
strony prymitywów, których dotyczą zmieniane ustawienia. Parametr ten
przyjmuje jedną z trzech znanych już wartości: GL FRONT (przedni bufor),
GL BACK (tylni bufor) i GL FRONT AND BACK (przedni i tylni bufor). Działanie
dotychczasowych funkcji glStencilFunc, glStencilOp i glStencilMask
odpowiada definiowaniem operacji dla obu stron prymitywów. Jedynie przy
czyszczeniu bufora używana jest zawsze maska określona dla przednich stron
wielokątów.
1. Bufor szablonowy
4
1.5. Programy przykładowe
Program przykładowy (plik odbicie.cpp) przedstawia sposób wykorzy-
stania mieszania kolorów i bufora szablonowego do uzyskania efektu odbicia
na płaskiej, półprzezroczystej powierzchni. Idea rozwiązania jest stosunkowo
prosta. Obiekty „świata”, które mają zostać odbite na powierzchni rysowane
są dwukrotnie. Pierwszy raz obiekty rysowane są w położeniu „lustrzanym”
w stosunku do powierzchni, w którym mają być odbite. W przypadku, gdy
płaszczyzna ta jest prostopadła do osi X wystarczy do tego odpowiednie
skalowanie macierzy modelowania:
glScalef (1.0,-1.0,1.0)
Takiemu samemu przekształceniu trzeba poddać współrzędne położenia źró-
deł światła, które są wykorzystywane do oświetlenia sceny. Pozostałe prze-
kształcenie macierzy modelowania (obroty, przesunięcia itp.) są identyczne
jak dla obiektów „rzeczywistego” świata. W przypadku, gdy program ry-
suje tylko przednie strony obiektów, przy rysowaniu świata „lustrzanego”
trzeba zmienić orientację stron wielokąta na przeciwną do stosowanej przy
rysowania świata rzeczywistego (funkcja glCullFace).
Po narysowaniu świata lustrzanego rysujemy płaszczyznę, na której re-
alizowany jest efekt odbicia. W tym celu trzeba włączyć mieszanie kolorów
oraz ustawić współczynniki mieszania kolorów na GL SRC ALPHA dla koloru
źródłowego i GL ONE MINUS SRC ALPHA dla koloru przeznaczenia. Jeżeli ko-
rzystamy z oświetlenia, tak jak ma to miejsce w przykładowym programie,
trzeba na czas rysowania płaszczyzny wyłączyć oświetlenie.
Drugi raz obiekty świata rysowane są już po narysowaniu płaszczyzny
odbicia, oczywiście po wyłączeniu mieszania kolorów oraz włączeniu oświe-
tlenia sceny.
Opisany sposób postępowania nie wymaga żadnych dodatkowych zabie-
gów w przypadku, gdy odbicie obiektów świata nigdy wykracza poza granice
płaszczyzny odbicia. W przeciwnym wypadku część sceny lustrzanej zostanie
narysowana także poza płaszczyzną odbicia, co jest oczywiście efektem nie-
pożądanym (patrz rysunek 1). Jednym ze sposobów eliminacji tego zjawiska
jest wykorzystanie opisanego wyżej bufora szablonowego.
Bufor szablonowy jest wykorzystany przy rysowaniu obiektów świata „lu-
strzanego”. Wcześniej trzeba jednak utworzyć szablon i wymaga to niestety
narysowania powierzchni, na której będzie widoczny efekt odbicia. Test bu-
fora szablonowego definiujemy tak, aby był zawsze spełniony, a poprzednie
jego wartości zastępowane (na początku rysowania ramki obrazu bufor jest
czyszczony wartością domyślną):
glStencilFunc (GL_ALWAYS,0x00000001,0xFFFFFFFF);
glStencilOp (GL_REPLACE,GL_REPLACE,GL_REPLACE);
1. Bufor szablonowy
5
Rysunek 1. Program Odbicie - bufor szablonowy wyłączony
Aby dwukrotne rysowanie powierzchni odbicia nie spowodowało niepo-
żądanego efektu w postaci zmiany jej kolorów, na czas tworzenia szablonu
trzeba wyłączyć zapis składowych RGBA w buforze koloru. Realizuje to
opisywana już funkcja glColorMask. Po narysowaniu powierzchni odbicia
i otrzymaniu szablonu test bufora szablonowego definiujemy tak, aby był
spełniony tylko przy wartości równej do znajdującej się w buforze, a sam
bufor pozostawiamy bez modyfikacji:
glStencilFunc (GL_EQUAL,0x00000001,0xFFFFFFFF);
glStencilOp (GL_KEEP,GL_KEEP,GL_KEEP);
Zauważmy, że przy tworzeniu szablonu wykorzystywaliśmy tylko jeden
bit bufora szablonowego (parametr ref funkcji glStencilFunc) co czyni
program niezależny od implementacji biblioteki OpenGL.
1. Bufor szablonowy
6
Przy tak określonym teście bufora szablonowego rysujemy tylko obiekty
świata „lustrzanego”. Następne operacje, czyli rysowanie powierzchni odbi-
cia i obiektów świata rzeczywistego, już z niego nie korzystają. Efekt dzia-
łania program z włączonym buforem szablonowym przedstawia rysunek 2.
Rysunek 2. Program Odbicie - bufor szablonowy włączony
Do uzyskania ciągłego i jednostajnego ruchu obiektu sceny, który prak-
tycznie nie będzie zależny od wydajności komputera i karty graficznej zasto-
sowano licznik czasu (ang. timer). Funkcję licznika czasu wywołuje się przy
użyciu funkcji:
void glutTimerFunc (unsigned int millis,
void (GLUTCALLBACK *func)(int value),
int value)
1. Bufor szablonowy
7
gdzie millis określa czas w milisekundach, jaki ma upłynąć do wywołania
funkcji licznika, do której wskaźnik zawiera parametr func. Ostatni para-
metr value jest przekazywany jako parametr funkcji licznika.
W przykładowym programie funkcja licznika nazywa się po prostu Timer,
która po zwiększeniu kąta obrotu obiektów sceny ponownie ustawia licznik
czasu wywołując funkcję glutTimerFunc.
1.5.1. Plik odbicie.cpp
/∗
( c )
J a n u s z
G a n c z a r s k i
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>
#i n c l u d e
” c o l o r s . h ”
//
s t a ł e
do
o b s ł u g i
menu
p o d r ę c z n e g o
enum
{
STENCIL ,
//
b u f o r
s z a b l o n o w y
w ł ą c z / w y ł ą c z
FULL WINDOW,
//
a s p e k t
o b r a z u − c a ł e
o k n o
ASPECT 1 1 ,
//
a s p e k t
o b r a z u
1 : 1
EXIT
//
w y j ś c i e
} ;
//
a s p e k t
o b r a z u
i n t
a s p e c t = FULL WINDOW ;
//
r o z m i a r y
b r y ł y
o b c i n a n i a
const GLdouble
l e f t = − 2 . 0 ;
const GLdouble
r i g h t = 2 . 0 ;
const GLdouble bottom = − 2 . 0 ;
const GLdouble
t o p = 2 . 0 ;
const GLdouble
n e a r = 3 . 0 ;
const GLdouble
f a r = 7 . 0 ;
//
k ą t y
o b r o t u
s c e n y
G L f l o a t
r o t a t e x = 3 0 . 0 ;
G L f l o a t
r o t a t e y = 0 . 0 ;
//
k ą t
o b r o t u
o b i e k t u
G L f l o a t
a n g l e = 0 . 0 ;
//
w s k a ź n i k
n a c i ś n i ę c i a
l e w e g o
p r z y c i s k u
m y s z k i
i n t
b u t t o n s t a t e = GLUT UP ;
//
p o ł o ż e n i e
k u r s o r a
m y s z k i
i n t
b u t t o n x , b u t t o n y ;
//
i d e n t y f i k a t o r y
l i s t
w y ś w i e t l a n i a
GLint GROUND LIST ;
GLint WORLD LIST ;
//
p o ł o ż e n i e
ź r ó d ł a
ś w i a t ł a
G L f l o a t
l i g h t p o s i t i o n
[ 4 ] =
{
0 . 0 , 1 0 . 0 , 1 0 . 0 , 1 . 0
} ;
//
u ż y c i e
b u f o r a
s z a b l o n o w e g o
bool
s t e n c i l
t e s t = true ;
1. Bufor szablonowy
8
//
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 S c e n e
( )
{
//
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 ,
b u f o r a
g ł ę b o k o ś c i
i
o p c j o n a l n i e
b u f o r a
s z a b l o n o w e g o
i f
( s t e n c i l
t e s t == true )
g l C l e a r
( GL COLOR BUFFER BIT | GL DEPTH BUFFER BIT |
GL STENCIL BUFFER BIT ) ;
e l s e
g l C l e a r
( GL COLOR BUFFER BIT | GL DEPTH BUFFER BIT ) ;
//
w y b ó r
m a c i e r z y
m o d e l o w a n i a
g l M a t r i x M o d e
(GL MODELVIEW ) ;
//
m a c i e r z
m o d e l o w a n i a = m a c i e r z
j e d n o s t k o w a
g l L o a d I d e n t i t y
( ) ;
//
w ł ą c z e n i e
t e s t u
b u f o r a
g ł ę b o k o ś c i
g l E n a b l e
(GL DEPTH TEST ) ;
//
w ł ą c z e n i e
o ś w i e t l e n i a
g l E n a b l e
( GL LIGHTING ) ;
//
w ł ą c z e n i e
ś w i a t ł a
GL LIGHT0
g l E n a b l e
( GL LIGHT0 ) ;
//
w ł ą c z e n i e
a u t o m a t y c z n e j
n o r m a l i z a c j i
w e k t o r ó w
n o r m a l n y c h
g l E n a b l e
(GL NORMALIZE ) ;
//
w ł ą c z e n i e
o b s ł u g i
w ł a ś c i w o ś c i
m a t e r i a ł ó w
g l E n a b l e
(GL COLOR MATERIAL ) ;
//
w ł a ś c i w o ś c i
m a t e r i a ł u
o k r e ś l o n e
p r z e z
k o l o r
w i e r z c h o ł k ó w
g l C o l o r M a t e r i a l
(GL FRONT, GL AMBIENT AND DIFFUSE ) ;
//
w ł ą c z e n i e
n i e r y s o w a n i a
t y l n e j
s t r o n y
w i e l o k ą t ó w
g l E n a b l e
( GL CULL FACE ) ;
//
p r z e s u n i ę c i e
u k ł a d u
w s p ó ł r z ę d n y c h
o b i e k t ó w
do
ś r o d k a
b r y ł y
o d c i n a n i a
g l T r a n s l a t e f
( 0 , 0 , − ( n e a r+f a r ) / 2 ) ;
//
o b r o t y
c a ł e j
s c e n y
g l R o t a t e f
( r o t a t e x , 1 . 0 , 0 . 0 , 0 . 0 ) ;
g l R o t a t e f
( r o t a t e y , 0 . 0 , 1 . 0 , 0 . 0 ) ;
//
p r z y
w ł ą c z o n y m
b u f o r z e
s z b l o n o w y m
r y s u j e m y
” p o d ł o g ę ” w
c e l u
u t w o r z e n i a
//
s z a b l o n u ,
k t ó r y
z o s t a n i e
w y k o r z y s t a n y
do
n a r y s o w a n i a
o b i e k t ó w
o d b i t y c h
i f
( s t e n c i l
t e s t == true )
{
//
w y ł ą c z e n i e
b u f o r a
g ł ę b o k o ś c i
g l D i s a b l e
(GL DEPTH TEST ) ;
//
w ł ą c z e n i e
b u f o r a
s z a b l o n o w e g o
g l E n a b l e
( GL STENCIL TEST ) ;
//
t e s t
b u f o r a
s z a b l o n o w e g o
g l S t e n c i l F u n c
(GL ALWAYS, 0 x 0 0 0 0 0 0 0 1 , 0 xFFFFFFFF ) ;
//
o k r e ś l e n i e
o p e r a c j i
na
b u f o r z e
s z a b l o n o w y m
g l S t e n c i l O p
(GL REPLACE, GL REPLACE, GL REPLACE ) ;
//
w y ł ą c z e n i e
z a p i s u
s k ł a d o w y c h RGBA do
b u f o r a
k o l o r ó w
g l C o l o r M a s k
( GL FALSE , GL FALSE , GL FALSE , GL FALSE ) ;
//
w y ś w i e t l e n i e
p ł a s z c z y z n y
o d b i c i a
g l C a l l L i s t
(GROUND LIST ) ;
//
w ł ą c z e n i e
z a p i s u
s k ł a d o w y c h RGBA do
b u f o r a
k o l o r ó w
g l C o l o r M a s k
(GL TRUE, GL TRUE, GL TRUE, GL TRUE ) ;
//
w ł ą c z e n i e
t e s t u
b u f o r a
g ł ę b o k o ś c i
g l E n a b l e
(GL DEPTH TEST ) ;
//
t e s t
b u f o r a
s z a b l o n o w e g o
g l S t e n c i l F u n c
(GL EQUAL, 0 x 0 0 0 0 0 0 0 1 , 0 xFFFFFFFF ) ;
//
o k r e ś l e n i e
o p e r a c j i
na
b u f o r z e
s z a b l o n o w y m
1. Bufor szablonowy
9
g l S t e n c i l O p
(GL KEEP , GL KEEP , GL KEEP ) ;
}
//
o d ł o ż e n i e
m a c i e r z y
m o d e l o w a n i a
na
s t o s
g l P u s h M a t r i x ( ) ;
//
s k a l o w a n i e
m a c i e r z y
m o d e l o w a n i a w
c e l u
n a r y s o w n a i a
o b i e k t ó w
ś w i a t a
” l u s t r z a n e g o ”
g l S c a l e f
( 1 . 0 , − 1 . 0 , 1 . 0 ) ;
//
p o ł o ż e n i e
” l u s t r z a n e g o ”
ź r ó d ł a
ś w i a t ł a
g l L i g h t f v
( GL LIGHT0 , GL POSITION , l i g h t p o s i t i o n ) ;
//
p r z e s u n i ę c i e
o b i e k t ó w
ś w i a t a
” l u s t r z a n e g o ”
g l T r a n s l a t e f
( 0 . 0 , 1 . 2 , 0 . 0 ) ;
//
o b r o t y
o b i e k t ó w
ś w i a t a
” l u s t r z a n e g o ”
g l R o t a t e f
( a n g l e , 1 . 0 , 0 . 0 , 0 . 0 ) ;
g l R o t a t e f
( a n g l e , 0 . 0 , 2 . 0 , 0 . 0 ) ;
g l R o t a t e f
( a n g l e , 0 . 0 , 0 . 0 , − 1 . 0 ) ;
// w
ś w i e c i e
l u s t r z a n y m
t r z e b a
z m i e n i ć
o r i e n t a c j ę
w i e r z c h o ł k ó w
p r y m i t y w ó w
g l F r o n t F a c e
(GL CW ) ;
//
w y ś w i e t l e n i e
o b i e k t ó w
ś w i a t a
” l u s t r z a n e g o ”
g l C a l l L i s t
(WORLD LIST ) ;
//
p o w r ó t
do
n o r m a l n e j
o r i e n t a c j i
w i e r z c h o ł k ó w
p r y m i t y w ó w
g l F r o n t F a c e
(GL CCW ) ;
//
z d j ę c i e
m a c i e r z y
m o d e l o w a n i a
z e
s t o s u
g l P o p M a t r i x
( ) ;
//
k o n i e c
r y s o w a n i a
o b i e k t ó w
ś w i a t a
” l u s t r z n a e g o ”
t o
t a k ż e
//
k o n i e c
k o r z y s t a n i a
z
b u f o r a
s z a b l o n o w e g o
i f
( s t e n c i l
t e s t == true )
{
//
w y ł ą c z e n i e
b u f o r a
s z a b l o n o w e g o
g l D i s a b l e
( GL STENCIL TEST ) ;
}
//
w y ł ą c z e n i e
o ś w i e t l e n i a
g l D i s a b l e
( GL LIGHTING ) ;
//
w ł ą c z e n i e
m i e s z a n i a
k o l o r ó w
g l E n a b l e
(GL BLEND ) ;
//
w s p ó ł c z y n n i k i
r ó w n a n i a
m i e s z a n i a
k o l o r ó w
g l B l e n d F u n c
( GL SRC ALPHA , GL ONE MINUS SRC ALPHA ) ;
//
w y ś w i e t l e n i e
p ł a s z c z y z n y
o d b i c i a
g l C a l l L i s t
(GROUND LIST ) ;
//
w y ł ą c z e n i e
m i e s z a n i a
k o l o r ó w
g l D i s a b l e
(GL BLEND ) ;
//
w ł ą c z e n i e
o ś w i e t l e n i a
g l E n a b l e
( GL LIGHTING ) ;
//
p o ł o ż e n i e
ź r ó d ł a
ś w i a t ł a
g l L i g h t f v ( GL LIGHT0 , GL POSITION , l i g h t p o s i t i o n ) ;
//
p r z e s u n i ę c i e
o b i e k t ó w
ś w i a t a
g l T r a n s l a t e f
( 0 . 0 , 1 . 2 , 0 . 0 ) ;
//
o b r o t y
o b i e k t ó w
ś w i a t a
g l R o t a t e f
( a n g l e , 1 . 0 , 0 . 0 , 0 . 0 ) ;
g l R o t a t e f
( a n g l e , 0 . 0 , 2 . 0 , 0 . 0 ) ;
g l R o t a t e f
( a n g l e , 0 . 0 , 0 . 0 , − 1 . 0 ) ;
//
w y ś w i e t l e n i e
o b i e k t ó w
ś w i a t a
g l C a l l L i s t
(WORLD LIST ) ;
//
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 ( ) ;
}
//
f u n k c j a
t i m e r a
1. Bufor szablonowy
10
void Timer
( i n t
v a l u e )
{
//
z w i ę k s z e n i e
k ą t a
o b r o t u
o b i e k t u
s c e n y
a n g l e ++;
//
w y ś w i e t l e n i e
s c e n y
D i s p l a y S c e n e
( ) ;
//
n a s t ę p n e
w y w o ł a n i e
f u n k c j i
t i m e r a
g l u t T i m e r F u n c
( 2 0 , Timer , 0 ) ;
}
//
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 )
{
//
o b s z a r
r e n d e r i n g u − c a ł e
o k n o
g l V i e w p o r t
( 0 , 0 , width , h e i g h t ) ;
//
w y b ó r
m a c i e r z y
r z u t o w a n i a
g l M a t r i x M o d e
(GL PROJECTION ) ;
//
m a c i e r z
r z u t o w a n i a = m a c i e r z
j e d n o s t k o w a
g l L o a d I d e n t i t y
( ) ;
//
p a r a m e t r y
b r y ł y
o b c i n a n i a
i f
( a s p e c t == ASPECT 1 1 )
{
//
w y s o k o ś ć
o k n a
w i ę k s z a
od
w y s o k o ś c i
o k n a
i f
( w i d t h < h e i g h t && w i d t h > 0 )
g l F r u s t u m
( l e f t , r i g h t , bottom ∗ h e i g h t / width , t o p ∗ h e i g h t / width , n e a r , f a r ) ;
e l s e
//
s z e r o k o ś ć
o k n a
w i ę k s z a
l u b
równa
w y s o k o ś c i
o k n a
i f
( w i d t h >= h e i g h t && h e i g h t > 0 )
g l F r u s t u m
( l e f t ∗ w i d t h / h e i g h t , r i g h t ∗ w i d t h / h e i g h t , bottom , top , n e a r , f a r ) ;
}
e l s e
g l F r u s t u m
( l e f t , r i g h t , bottom , top , n e a r , f a r ) ;
//
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 c e n e
( ) ;
}
//
o b s ł u g a
p r z y c i s k ó w
m y s z k i
void MouseButton
( i n t
b u t t o n ,
i n t
s t a t e ,
i n t x ,
i n t
y )
{
i f
( b u t t o n == GLUT LEFT BUTTON)
{
//
z a p a m i ę t a n i e
s t a n u
l e w e g o
p r z y c i s k u
m y s z k i
b u t t o n s t a t e = s t a t e ;
//
z a p a m i ę t a n i e
p o ł o ż e n i a
k u r s o r a
m y s z k i
i f
( s t a t e == GLUT DOWN)
{
b u t t o n x = x ;
b u t t o n y = y ;
}
}
}
//
o b s ł u g a
r u c h u
k u r s o r a
m y s z k i
void MouseMotion
( i n t x ,
i n t
y )
{
i f
( b u t t o n s t a t e == GLUT DOWN)
{
r o t a t e y += 30
∗ ( r i g h t − l e f t ) / g l u t G e t
(GLUT WINDOW WIDTH)
∗ ( x − b u t t o n x ) ;
b u t t o n x = x ;
r o t a t e x −= 30
∗ ( t o p − bottom ) / g l u t G e t
(GLUT WINDOW HEIGHT)
∗ ( b u t t o n y − y ) ;
b u t t o n y = y ;
g l u t P o s t R e d i s p l a y
( ) ;
}
}
//
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. Bufor szablonowy
11
{
switch
( v a l u e )
{
//
b u f o r
s z a b l o n o w y
w ł ą c z / w y ł ą c z
c a s e STENCIL :
s t e n c i l
t e s t = ! s t e n c i l
t e s t ;
D i s p l a y S c e n e
( ) ;
break ;
//
o b s z a r
r e n d e r i n g u − c a ł e
o k n o
c a s e FULL WINDOW :
a s p e c t = FULL WINDOW ;
R esha pe
( g l u t G e t
(GLUT WINDOW WIDTH) , g l u t G e t
(GLUT WINDOW HEIGHT ) ) ;
break ;
//
o b s z a r
r e n d e r i n g u − a s p e k t
1 : 1
c a s e ASPECT 1 1 :
a s p e c t = ASPECT 1 1 ;
R esha pe
( g l u t G e t
(GLUT WINDOW WIDTH) , g l u t G e t
(GLUT WINDOW HEIGHT ) ) ;
break ;
//
w y j ś c i e
c a s e EXIT :
e x i t
( 0 ) ;
}
}
//
u t w o r z e n i e
l i s t
w y ś w i e t l a n i a
void
G e n e r a t e D i s p l a y L i s t s
( )
{
//
g e n e r o w a n i e
i d e n t y f i k a t o r a
p i e r w s z e j
l i s t y
w y ś w i e t l a n i a
GROUND LIST = g l G e n L i s t s
( 1 ) ;
//
p i e r w s z a
l i s t a
w y ś w i e t l a n i a − p o d ł o g a
g l N e w L i s t
(GROUND LIST , GL COMPILE ) ;
// ” p o d ł o g a ”
r y s o w a n a
j e s t
j a k o
s z a c h o w n i c a
o
r o z m i a r a c h
// 4
x
4
j e d n o s t k i
i
z a w i e r a
s i ę
w
p ł a s z c z y ź n i e
y = 0
g l B e g i n
(GL QUADS ) ;
g l N o r m a l 3 f
( 1 . 0 , 0 . 0 , 0 . 0 ) ;
//
p r z y
k a ż d e j
i t e r a c j i
p ę t l i
r y s o w a n e
s ą
c z t e r y
p r o s t o k ą t y
s z a c h o w n i c y
f o r
( G L f l o a t
z = − 2 . 0 ;
z < 2 . 0 ;
z += 1 )
f o r
( G L f l o a t
x = − 2 . 0 ;
x < 2 . 0 ;
x += 1 )
{
g l C o l o r 4 f
( B l u e [ 0 ] , B l u e [ 1 ] , B l u e [ 2 ] , 0 . 5 ) ;
g l V e r t e x 3 f
( x + 0 . 0 , 0 . 0 , z + 0 . 0 ) ;
g l V e r t e x 3 f
( x + 0 . 0 , 0 . 0 , z + 0 . 5 ) ;
g l V e r t e x 3 f
( x + 0 . 5 , 0 . 0 , z + 0 . 5 ) ;
g l V e r t e x 3 f
( x + 0 . 5 , 0 . 0 , z + 0 . 0 ) ;
g l C o l o r 4 f
( S i l v e r [ 0 ] , S i l v e r [ 1 ] , S i l v e r [ 2 ] , 0 . 7 ) ;
g l V e r t e x 3 f
( x + 0 . 5 , 0 . 0 , z + 0 . 0 ) ;
g l V e r t e x 3 f
( x + 0 . 5 , 0 . 0 , z + 0 . 5 ) ;
g l V e r t e x 3 f
( x + 1 . 0 , 0 . 0 , z + 0 . 5 ) ;
g l V e r t e x 3 f
( x + 1 . 0 , 0 . 0 , z + 0 . 0 ) ;
g l C o l o r 4 f
( B l u e [ 0 ] , B l u e [ 1 ] , B l u e [ 2 ] , 0 . 5 ) ;
g l V e r t e x 3 f
( x + 0 . 5 , 0 . 0 , z + 0 . 5 ) ;
g l V e r t e x 3 f
( x + 0 . 5 , 0 . 0 , z + 1 . 0 ) ;
g l V e r t e x 3 f
( x + 1 . 0 , 0 . 0 , z + 1 . 0 ) ;
g l V e r t e x 3 f
( x + 1 . 0 , 0 . 0 , z + 0 . 5 ) ;
g l C o l o r 4 f
( S i l v e r [ 0 ] , S i l v e r [ 1 ] , S i l v e r [ 2 ] , 0 . 7 ) ;
g l V e r t e x 3 f
( x + 0 . 0 , 0 . 0 , z + 0 . 5 ) ;
g l V e r t e x 3 f
( x + 0 . 0 , 0 . 0 , z + 1 . 0 ) ;
g l V e r t e x 3 f
( x + 0 . 5 , 0 . 0 , z + 1 . 0 ) ;
g l V e r t e x 3 f
( x + 0 . 5 , 0 . 0 , z + 0 . 5 ) ;
}
g l E n d
( ) ;
//
k o n i e c
p i e r w s z e j
l i s t y
w y ś w i e t l a n i a
g l E n d L i s t
( ) ;
//
g e n e r o w a n i e
i d e n t y f i k a t o r a
d r u g i e j
l i s t y
w y ś w i e t l a n i a
WORLD LIST =
g l G e n L i s t s
( 1 ) ;
//
d r u g a
l i s t a
w y ś w i e t l a n i a − o b i e k t
” ś w i a t a ”
g l N e w L i s t
(WORLD LIST , GL COMPILE ) ;
//
z i e l o n y
t o r u s
g l C o l o r 4 f v
( Green ) ;
1. Bufor szablonowy
12
g l u t S o l i d T o r u s
( 0 . 3 , 0 . 7 , 5 0 , 4 0 ) ;
//
k o n i e c
d r u g i e j
l i s t y
w y ś w i e t l a n i a
g l E n d L i s t
( ) ;
}
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 | GLUT DEPTH | GLUT STENCIL ) ;
//
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
( 5 0 0 , 5 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
( ” O d b i c i e ” ) ;
//
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 S c e n e ) ;
//
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 ( R es hape ) ;
//
o b s ł u g a
p r z y c i s k ó w
m y s z k i
g l u t M o u s e F u n c
( MouseButton ) ;
//
o b s ł u g a
r u c h u
k u r s o r a
m y s z k i
g l u t M o t i o n F u n c
( MouseMotion ) ;
//
u t w o r z e n i e
podmenu − A s p e k t
o b r a z u
i n t
MenuAspect = g l u t C r e a t e M e n u
( Menu ) ;
#i f d e f WIN32
glutAddMenuEntry
( ” A s p e k t
o b r a z u − c a ł e
okno ” ,FULL WINDOW ) ;
#e l s e
glutAddMenuEntry
( ” A s p e k t
o b r a z u − c a l e
okno ” ,FULL WINDOW ) ;
#e n d i f
glutAddMenuEntry
( ” A s p e k t
o b r a z u
1 : 1 ” , ASPECT 1 1 ) ;
// menu g ł ó w n e
g l u t C r e a t e M e n u
( Menu ) ;
#i f d e f WIN32
glutAddMenuEntry
( ” B u f o r
s z a b l o n o w y
w ł ą c z / w y ł ą c z ” , STENCIL ) ;
glutAddSubMenu
( ” A s p e k t
o b r a z u ” , MenuAspect ) ;
glutAddMenuEntry
( ” W y j ś c i e ” , EXIT ) ;
#e l s e
glutAddMenuEntry
( ” B u f o r
s z a b l o n o w y
w l a c z / w y l a c z ” , STENCIL ) ;
glutAddSubMenu
( ” A s p e k t
o b r a z u ” , MenuAspect ) ;
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 g o
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 ) ;
//
u t w o r z e n i e
l i s t
w y ś w i e t l a n i a
G e n e r a t e D i s p l a y L i s t s
( ) ;
//
w y w o ł a n i e
f u n k c j i
t i m e r a
g l u t T i m e r F u n c
( 2 0 , Timer , 0 ) ;
//
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 ;
}
Drugi program przykładowy (plik csg.cpp) przedstawia techniki wy-
korzystania bufora szablonowego do konstruowania obiektów przy użyciu
operacji CSG (ang. Constructive Solid Geometry), czyli konstruktywnej geo-
metrii brył. W przestrzeni trójwymiarowej CSG polega na wykonywaniu na
1. Bufor szablonowy
13
bryłach (lub innych obiektach geometrycznych) tzw. regularyzowanych ope-
racji logicznych, czyli operacji logicznych w wyniku których zawsze powstaje
bryła. Wykonywanie operacji GSG prześledzimy na przykładzie dwóch brył:
sześcianu (rysunek 3) i kuli (rysunek 4).
Rysunek 3. Program CSG - obiekt A
Wykonanie operacji logicznej OR na dwóch obiektach jest bardzo proste i
sprowadza się do ich kolejnego wyświetlenia przy włączonym buforze głębo-
kości. Do tej operacji tej nie jest potrzebny bufor szablonowy. Efekt działania
operatora OR przedstawiono na rysunku 5. Jak już Czytelnik zauważył jest
to domyślny tryb rysowania prymitywów graficznych w bibliotece OpenGL.
Operator AND wymaga już znacznie większego nakładu pracy. Oto kolejno
wykonywane operacje:
1. Przy włączonym buforze głębokości, ale bez zapisu składowych RGBA
do bufora kolorów, rysujemy przednie strony wielokątów składających
się na obiekt A.
1. Bufor szablonowy
14
Rysunek 4. Program CSG - obiekt B
2. Przy włączonym buforze szablonowym i wyłączonym buforze głębokości
(ciągle bez zapisu danych do bufora kolorów) rysujemy przednie strony
wielokątów składających się na obiekt B. Operacje na buforze szablono-
wym są tak ustawione, że jego zawartość jest przy rysowaniu obiektu B
zwiększana o 1.
3. Następnie przy niezmienionych ustawieniach buforów głębokości i koloru
rysujemy wyłącznie tylne strony wielokątów składających się na obiekt
B. Jednocześnie zmieniamy operacje na buforze szablonowym tak, aby
podczas rysowania zmniejszać jego zawartość o 1. W efekcie bufor sza-
blonowy zawiera informacje o tych elementach obiektu A, które znajdują
się we wnętrzu B.
4. W kolejnym kroku rysujemy te elementy obiektu A, które znajdują się
we wnętrzu B. W tym celu należy odblokować zapis do bufora kolorów
oraz zmienić sposób działania bufora szablonowego, tak aby zapis składo-
1. Bufor szablonowy
15
Rysunek 5. Program CSG - A OR B
wych RGBA do bufora kolorów obejmował wyłącznie wcześniej wybrane
elementy obiektu A, które znajdują się we wnętrzu B.
5. Przed przystąpieniem do kolejnego etapu wykonywania operacji AND trze-
ba jeszcze narysować elementy obiektu B zmieniając jednak funkcję te-
stu bufora głębokości z domyślnej GL LESS na GL ALWAYS, przy czym
rysowanie odbywa się przy wyłączonym zapisie składowych RGBA do
bufora kolorów oraz wyłączonym buforze szablonowym. Po zakończeniu
rysowania przywracamy domyślną funkcję testu bufora głębokości.
6. Następnym etapem jest narysowanie tych elementów obiektu B, które
znajdują się we wnętrzu obiektu A. Wykonywane czynności odpowiadają
krokom 1-4 z oczywistą różnicą polegającą na zamianie obiektu A na
obiekt B i odwrotnie.
Końcowy wynik operacji AND przedstawiono na rysunku 6. Jak łatwo
zauważyć jest to część wspólna przenikającego się sześcianu i kuli.
1. Bufor szablonowy
16
Rysunek 6. Program CSG - A AND B
Operacja SUB (odejmowanie) jest w ogólnym przypadku nieprzemienna,
stąd różne jej efekty w zależności od kolejności odejmowania obiektów, co
wyraźnie widać na rysunkach 7 i 8. Pierwszy etap odejmowania pokrywa
się z krokami 1-5 operacji AND. Dalej także rysowane są te elementy obiektu
B, które znajdują się we wnętrzu obiektu A, przy czym w kroku 4 zmienia
się test bufora szablonowego z GL NOTEQUAL na GL EQUAL co daje właściwy
efekt „odejmowania” obiektów. Zasadniczą część programu zajmującą się
wydzielaniem wnętrza obiektów zawiera funkcja Inside.
1. Bufor szablonowy
17
Rysunek 7. Program CSG - A SUB B
1.5.2. Plik csg.cpp
/∗
( c )
J a n u s z
G a n c z a r s k i
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>
#i n c l u d e
” c o l o r s . h ”
//
s t a ł e
do
o b s ł u g i
menu
p o d r ę c z n e g o
enum
{
CSG A ,
//
t y l k o
o b i e k t A
CSG B ,
//
t y l k o
o b i e k t A
CSG A OR B ,
// A OR B
CSG A AND B ,
// A AND B
CSG A SUB B ,
// A SUB B
CSG B SUB A ,
// B SUB A
FULL WINDOW,
//
a s p e k t
o b r a z u − c a ł e
o k n o
ASPECT 1 1 ,
//
a s p e k t
o b r a z u
1 : 1
EXIT
//
w y j ś c i e
} ;
1. Bufor szablonowy
18
Rysunek 8. Program CSG - B SUB A
//
a s p e k t
o b r a z u
i n t
a s p e c t = FULL WINDOW ;
//
r o z m i a r y
b r y ł y
o b c i n a n i a
const GLdouble
l e f t = − 2 . 0 ;
const GLdouble
r i g h t = 2 . 0 ;
const GLdouble bottom = − 2 . 0 ;
const GLdouble
t o p = 2 . 0 ;
const GLdouble
n e a r = 3 . 0 ;
const GLdouble
f a r = 7 . 0 ;
//
k ą t y
o b r o t u
s c e n y
G L f l o a t
r o t a t e x = 0 . 0 ;
G L f l o a t
r o t a t e y = 0 . 0 ;
//
w s k a ź n i k
n a c i ś n i ę c i a
l e w e g o
p r z y c i s k u
m y s z k i
i n t
b u t t o n s t a t e = GLUT UP ;
//
p o ł o ż e n i e
k u r s o r a
m y s z k i
i n t
b u t t o n x , b u t t o n y ;
1. Bufor szablonowy
19
//
i d e n t y f i k a t o r y
l i s t
w y ś w i e t l a n i a
GLint A, B ;
//
r o d z a j
o p e r a c j i CSG
i n t
c s g o p = CSG A OR B ;
//
u s t a w i e n i e
b u f o r a
s z a b l o n o w e g o
t a k ,
a b y
w y d z i e l i ć
i
w y ś w i e t l i ć
//
t e
e l e m e n t y
o b i e k t u A ,
k t ó r e
z n a j d u j ą
s i ę
we
w n ę t r z u
o b i e k t u B ;
//
s t r o n ę
( p r z e d n i ą
l u b
t y l n ą )
w y s z u k i w a n y c h
e l e m e n t ó w
o b i e k t u A
//
o k r e ś l a
p a r a m e t r
c u l l
f a c e
void
I n s i d e
( GLint A,
GLint B ,
GLenum
c u l l f a c e ,
GLenum
s t e n c i l f u n c )
{
//
p o c z ą t k o w o
r y s u j e m y
o b i e k t A w
b u f o r z e
g ł ę b o k o ś c i
p r z y
//
w y ł ą c z o n y m
z a p i s i e
s k ł a d o w y c h RGBA do
b u f o r a
k o l o r ó w
//
w ł ą c z e n i e
t e s t u
b u f o r a
g ł ę b o k o ś c i
g l E n a b l e
(GL DEPTH TEST ) ;
//
w y ł ą c z e n i e
z a p i s u
s k ł a d o w y c h RGBA do
b u f o r a
k o l o r ó w
g l C o l o r M a s k
( GL FALSE , GL FALSE , GL FALSE , GL FALSE ) ;
//
r y s o w a n i e
w y b r a n e j
s t r o n y
w i e l o k ą t ó w
g l C u l l F a c e
( c u l l f a c e ) ;
//
w y ś w i e t l e n i e
o b i e k t u A
g l C a l l L i s t
(A ) ;
//
n a s t ę p n i e
p r z y
u ż y c i u
b u f o r a
s z a b l o n o w e g o
wykrywamy
t e
e l e m e n t y
//
o b i e k t u A ,
k t ó r e
z n a j d u j ą
s i ę
w e w n ą t r z
o b i e k t u B ;
w tym
c e l u
//
z a w a r t o ś ć
b u f o r a
s z a b l o n o w e g o
j e s t
z w i ę k s z a n a
o
1 ,
w s z ę d z i e
g d z i e
//
b ę d ą
p r z e d n i e
s t r o n y
w i e l o k ą t ó w
s k ł a d a j ą c y c h
s i ę
na
o b i e k t
B
//
w y ł ą c z e n i e
z a p i s u
do
b u f o r a
g ł ę b o k o ś c i
glDepthMask
( GL FALSE ) ;
//
w ł ą c z e n i e
b u f o r a
s z a b l o n o w e g o
g l E n a b l e
( GL STENCIL TEST ) ;
//
t e s t
b u f o r a
s z a b l o n o w e g o
g l S t e n c i l F u n c
(GL ALWAYS, 0 , 0 ) ;
//
o k r e ś l e n i e
o p e r a c j i
na
b u f o r z e
s z a b l o n o w y m
g l S t e n c i l O p
(GL KEEP , GL KEEP , GL INCR ) ;
//
r y s o w a n i e
t y l k o
p r z e d n i e j
s t r o n y
w i e l o k ą t ó w
g l C u l l F a c e
(GL BACK ) ;
//
w y ś w i e t l e n i e
o b i e k t u B
g l C a l l L i s t
(B ) ;
// w k o l e j n y m
e t a p i e
z m n i e j s z a m y
z a w a r t o ś ć
b u f o r a
s z a b l o n o w e g o
o 1
//
w s z ę d z i e
tam ,
g d z i e
s ą
t y l n e
s t r o n y
w i e l o k ą t ó w
o b i e k t u B
//
o k r e ś l e n i e
o p e r a c j i
na
b u f o r z e
s z a b l o n o w y m
g l S t e n c i l O p
(GL KEEP , GL KEEP , GL DECR ) ;
//
r y s o w a n i e
t y l k o
t y l n e j
s t r o n y
w i e l o k ą t ó w
g l C u l l F a c e
(GL FRONT ) ;
//
w y ś w i e t l e n i e
o b i e k t u B
g l C a l l L i s t
(B ) ;
//
d a l e j
w y ś w i e t l a m y
t e
e l e m e n t y
o b i e k t u A ,
k t ó r e
//
z n a j d u j ą
s i ę
we
w n ę t r z u
o b i e k t u B
//
w ł ą c z e n i e
z a p i s u
do
b u f o r a
g ł ę b o k o ś c i
glDepthMask
(GL TRUE ) ;
//
w ł ą c z e n i e
z a p i s u
s k ł a d o w y c h RGBA do
b u f o r a
k o l o r ó w
g l C o l o r M a s k
(GL TRUE, GL TRUE, GL TRUE, GL TRUE ) ;
//
t e s t
b u f o r a
s z a b l o n o w e g o
g l S t e n c i l F u n c
( s t e n c i l f u n c , 0 , 1 ) ;
//
w y ł ą c z e n i e
t e s t u
b u f o r a
g ł ę b o k o ś c i
g l D i s a b l e
(GL DEPTH TEST ) ;
1. Bufor szablonowy
20
//
r y s o w a n i e
w y b r a n e j
s t r o n y
w i e l o k ą t ó w
g l C u l l F a c e
( c u l l f a c e ) ;
//
w y ś w i e t l e n i e
o b i e k t u A
g l C a l l L i s t
(A ) ;
//
w y ł ą c z e n i e
b u f o r a
s z a b l o n o w e g o
g l D i s a b l e
( GL STENCIL TEST ) ;
}
//
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 S c e n e
( )
{
//
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 ,
b u f o r a
g ł ę b o k o ś c i
i
b u f o r a
s z a b l o n o w e g o
g l C l e a r
( GL COLOR BUFFER BIT | GL DEPTH BUFFER BIT |
GL STENCIL BUFFER BIT ) ;
//
w y b ó r
m a c i e r z y
m o d e l o w a n i a
g l M a t r i x M o d e
(GL MODELVIEW ) ;
//
m a c i e r z
m o d e l o w a n i a = m a c i e r z
j e d n o s t k o w a
g l L o a d I d e n t i t y
( ) ;
//
p r z e s u n i ę c i e
u k ł a d u
w s p ó ł r z ę d n y c h
o b i e k t ó w
do
ś r o d k a
b r y ł y
o d c i n a n i a
g l T r a n s l a t e f
( 0 , 0 , − ( n e a r+f a r ) / 2 ) ;
//
o b r o t y
c a ł e j
s c e n y
g l R o t a t e f
( r o t a t e x , 1 . 0 , 0 . 0 , 0 . 0 ) ;
g l R o t a t e f
( r o t a t e y , 0 . 0 , 1 . 0 , 0 . 0 ) ;
//
w ł ą c z e n i e
o ś w i e t l e n i a
g l E n a b l e
( GL LIGHTING ) ;
//
w ł ą c z e n i e
ś w i a t ł a
GL LIGHT0
g l E n a b l e
( GL LIGHT0 ) ;
//
w ł ą c z e n i e
a u t o m a t y c z n e j
n o r m a l i z a c j i
w e k t o r ó w
n o r m a l n y c h
g l E n a b l e
(GL NORMALIZE ) ;
//
w ł ą c z e n i e
o b s ł u g i
w ł a ś c i w o ś c i
m a t e r i a ł ó w
g l E n a b l e
(GL COLOR MATERIAL ) ;
//
w ł a ś c i w o ś c i
m a t e r i a ł u
o k r e ś l o n e
p r z e z
k o l o r
w i e r z c h o ł k ó w
g l C o l o r M a t e r i a l
(GL FRONT, GL AMBIENT AND DIFFUSE ) ;
//
w ł ą c z e n i e
r y s o w a n i a
w y b r a n e j
s t r o n y
w i e l o k ą t ó w
g l E n a b l e
( GL CULL FACE ) ;
//
o p e r a c j a CSG − t y l k o
o b i e k t A
i f
( c s g o p == CSG A )
{
//
w ł ą c z e n i e
t e s t u
b u f o r a
g ł ę b o k o ś c i
g l E n a b l e
(GL DEPTH TEST ) ;
//
w y ś w i e t l e n i e
o b i e k t u A
g l C a l l L i s t
(A ) ;
//
w y ł ą c z e n i e
t e s t u
b u f o r a
g ł ę b o k o ś c i
g l D i s a b l e
(GL DEPTH TEST ) ;
}
//
o p e r a c j a CSG − t y l k o
o b i e k t B
i f
( c s g o p == CSG B )
{
//
w ł ą c z e n i e
t e s t u
b u f o r a
g ł ę b o k o ś c i
g l E n a b l e
(GL DEPTH TEST ) ;
//
w y ś w i e t l e n i e
o b i e k t u B
g l C a l l L i s t
(B ) ;
//
w y ł ą c z e n i e
t e s t u
b u f o r a
g ł ę b o k o ś c i
g l D i s a b l e
(GL DEPTH TEST ) ;
}
//
o p e r a c j a CSG A l u b B
i f
( c s g o p == CSG A OR B )
1. Bufor szablonowy
21
{
//
w ł ą c z e n i e
t e s t u
b u f o r a
g ł ę b o k o ś c i
g l E n a b l e
(GL DEPTH TEST ) ;
//
w y ś w i e t l e n i e
o b i e k t u A i B
g l C a l l L i s t
(A ) ;
g l C a l l L i s t
(B ) ;
//
w y ł ą c z e n i e
t e s t u
b u f o r a
g ł ę b o k o ś c i
g l D i s a b l e
(GL DEPTH TEST ) ;
}
//
o p e r a c j a CSG A AND B
i f
( c s g o p == CSG A AND B )
{
//
e l e m e n t y
o b i e k t u A z n a j d u j ą c e
s i ę
we
w n ę t r z u B
I n s i d e
(A, B , GL BACK, GL NOTEQUAL ) ;
//
w y ł ą c z e n i e
z a p i s u
s k ł a d o w y c h RGBA do
b u f o r a
k o l o r ó w
g l C o l o r M a s k
( GL FALSE , GL FALSE , GL FALSE , GL FALSE ) ;
//
w ł ą c z e n i e
t e s t u
b u f o r a
g ł ę b o k o ś c i
g l E n a b l e
(GL DEPTH TEST ) ;
//
w y ł ą c z e n i e
b u f o r a
s z a b l o n o w e g o
g l D i s a b l e
( GL STENCIL TEST ) ;
//
w y b ó r
f u n k c j i
do
t e s t u
b u f o r a
g ł ę b o k o ś c i
g l D e p t h F u n c
(GL ALWAYS ) ;
//
w y ś w i e t l e n i e
o b i e k t u B
g l C a l l L i s t
(B ) ;
//
w y b ó r
f u n k c j i
do
t e s t u
b u f o r a
g ł ę b o k o ś c i
g l D e p t h F u n c
( GL LESS ) ;
//
e l e m e n t y
o b i e k t u B z n a j d u j ą c e
s i ę
we
w n ę t r z u A
I n s i d e
(B , A, GL BACK, GL NOTEQUAL ) ;
}
//
o p e r a c j a CSG A SUB B
i f
( c s g o p == CSG A SUB B )
{
//
e l e m e n t y
o b i e k t u A z n a j d u j ą c e
s i ę
we
w n ę t r z u B
I n s i d e
(A, B , GL FRONT, GL NOTEQUAL ) ;
//
w y ł ą c z e n i e
z a p i s u
s k ł a d o w y c h RGBA do
b u f o r a
k o l o r ó w
g l C o l o r M a s k
( GL FALSE , GL FALSE , GL FALSE , GL FALSE ) ;
//
w ł ą c z e n i e
t e s t u
b u f o r a
g ł ę b o k o ś c i
g l E n a b l e
(GL DEPTH TEST ) ;
//
w y ł ą c z e n i e
b u f o r a
s z a b l o n o w e g o
g l D i s a b l e
( GL STENCIL TEST ) ;
//
w y b ó r
f u n k c j i
do
t e s t u
b u f o r a
g ł ę b o k o ś c i
g l D e p t h F u n c
(GL ALWAYS ) ;
//
w y ś w i e t l e n i e
o b i e k t u B
g l C a l l L i s t
(B ) ;
//
w y b ó r
f u n k c j i
do
t e s t u
b u f o r a
g ł ę b o k o ś c i
g l D e p t h F u n c
( GL LESS ) ;
//
e l e m e n t y
o b i e k t u B z n a j d u j ą c e
s i ę
we
w n ę t r z u A
I n s i d e
(B , A, GL BACK, GL EQUAL ) ;
}
//
o p e r a c j a CSG B SUB A
i f
( c s g o p == CSG B SUB A )
{
//
e l e m e n t y
o b i e k t u B z n a j d u j ą c e
s i ę
we
w n ę t r z u A
I n s i d e
(B , A, GL FRONT, GL NOTEQUAL ) ;
//
w y ł ą c z e n i e
z a p i s u
s k ł a d o w y c h RGBA do
b u f o r a
k o l o r ó w
g l C o l o r M a s k
( GL FALSE , GL FALSE , GL FALSE , GL FALSE ) ;
//
w ł ą c z e n i e
t e s t u
b u f o r a
g ł ę b o k o ś c i
g l E n a b l e
(GL DEPTH TEST ) ;
1. Bufor szablonowy
22
//
w y ł ą c z e n i e
b u f o r a
s z a b l o n o w e g o
g l D i s a b l e
( GL STENCIL TEST ) ;
//
w y b ó r
f u n k c j i
do
t e s t u
b u f o r a
g ł ę b o k o ś c i
g l D e p t h F u n c
(GL ALWAYS ) ;
//
w y ś w i e t l e n i e
o b i e k t u A
g l C a l l L i s t
(A ) ;
//
w y b ó r
f u n k c j i
do
t e s t u
b u f o r a
g ł ę b o k o ś c i
g l D e p t h F u n c
( GL LESS ) ;
//
e l e m e n t y
o b i e k t u A z n a j d u j ą c e
s i ę
we
w n ę t r z u B
I n s i d e
(A, B , GL BACK, GL EQUAL ) ;
}
//
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 )
{
//
o b s z a r
r e n d e r i n g u − c a ł e
o k n o
g l V i e w p o r t
( 0 , 0 , width , h e i g h t ) ;
//
w y b ó r
m a c i e r z y
r z u t o w a n i a
g l M a t r i x M o d e
(GL PROJECTION ) ;
//
m a c i e r z
r z u t o w a n i a = m a c i e r z
j e d n o s t k o w a
g l L o a d I d e n t i t y
( ) ;
//
p a r a m e t r y
b r y ł y
o b c i n a n i a
i f
( a s p e c t == ASPECT 1 1 )
{
//
w y s o k o ś ć
o k n a
w i ę k s z a
od
w y s o k o ś c i
o k n a
i f
( w i d t h < h e i g h t && w i d t h > 0 )
g l F r u s t u m
( l e f t , r i g h t , bottom ∗ h e i g h t / width , t o p ∗ h e i g h t / width , n e a r , f a r ) ;
e l s e
//
s z e r o k o ś ć
o k n a
w i ę k s z a
l u b
równa
w y s o k o ś c i
o k n a
i f
( w i d t h >= h e i g h t && h e i g h t > 0 )
g l F r u s t u m
( l e f t ∗ w i d t h / h e i g h t , r i g h t ∗ w i d t h / h e i g h t , bottom , top , n e a r , f a r ) ;
}
e l s e
g l F r u s t u m
( l e f t , r i g h t , bottom , top , n e a r , f a r ) ;
//
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 c e n e
( ) ;
}
//
o b s ł u g a
p r z y c i s k ó w
m y s z k i
void MouseButton
( i n t
b u t t o n ,
i n t
s t a t e ,
i n t x ,
i n t
y )
{
i f
( b u t t o n == GLUT LEFT BUTTON)
{
//
z a p a m i ę t a n i e
s t a n u
l e w e g o
p r z y c i s k u
m y s z k i
b u t t o n s t a t e = s t a t e ;
//
z a p a m i ę t a n i e
p o ł o ż e n i a
k u r s o r a
m y s z k i
i f
( s t a t e == GLUT DOWN)
{
b u t t o n x = x ;
b u t t o n y = y ;
}
}
}
//
o b s ł u g a
r u c h u
k u r s o r a
m y s z k i
void MouseMotion
( i n t x ,
i n t
y )
{
i f
( b u t t o n s t a t e == GLUT DOWN)
{
r o t a t e y += 30
∗ ( r i g h t − l e f t ) / g l u t G e t
(GLUT WINDOW WIDTH)
∗ ( x − b u t t o n x ) ;
1. Bufor szablonowy
23
b u t t o n x = x ;
r o t a t e x −= 30
∗ ( t o p − bottom ) / g l u t G e t
(GLUT WINDOW HEIGHT)
∗ ( b u t t o n y − y ) ;
b u t t o n y = y ;
g l u t P o s t R e d i s p l a y
( ) ;
}
}
//
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 )
{
switch
( v a l u e )
{
//
o p e r a c j a CSG
c a s e CSG A :
c a s e CSG B :
c a s e CSG A OR B :
c a s e CSG A AND B :
c a s e CSG A SUB B :
c a s e CSG B SUB A :
c s g o p = v a l u e ;
D i s p l a y S c e n e
( ) ;
break ;
//
o b s z a r
r e n d e r i n g u − c a ł e
o k n o
c a s e FULL WINDOW :
a s p e c t = FULL WINDOW ;
R esha pe
( g l u t G e t
(GLUT WINDOW WIDTH) , g l u t G e t
(GLUT WINDOW HEIGHT ) ) ;
break ;
//
o b s z a r
r e n d e r i n g u − a s p e k t
1 : 1
c a s e ASPECT 1 1 :
a s p e c t = ASPECT 1 1 ;
R esha pe
( g l u t G e t
(GLUT WINDOW WIDTH) , g l u t G e t
(GLUT WINDOW HEIGHT ) ) ;
break ;
//
w y j ś c i e
c a s e EXIT :
e x i t
( 0 ) ;
}
}
//
u t w o r z e n i e
l i s t
w y ś w i e t l a n i a
void
G e n e r a t e D i s p l a y L i s t s
( )
{
//
g e n e r o w a n i e
i d e n t y f i k a t o r a
p i e r w s z e j
l i s t y
w y ś w i e t l a n i a
A = g l G e n L i s t s
( 1 ) ;
//
p i e r w s z a
l i s t a
w y ś w i e t l a n i a
g l N e w L i s t
(A, GL COMPILE ) ;
//
c z e r w o n y
s z e ś c i a n
g l C o l o r 4 f v
( Red ) ;
g l u t S o l i d C u b e
( 2 . 3 ) ;
//
k o n i e c
p i e r w s z e j
l i s t y
w y ś w i e t l a n i a
g l E n d L i s t
( ) ;
//
g e n e r o w a n i e
i d e n t y f i k a t o r a
d r u g i e j
l i s t y
w y ś w i e t l a n i a
B =
g l G e n L i s t s
( 1 ) ;
//
d r u g a
l i s t a
w y ś w i e t l a n i a
g l N e w L i s t
(B , GL COMPILE ) ;
//
z i e l o n a
k u l a
g l C o l o r 4 f v
( Green ) ;
g l u t S o l i d S p h e r e
( 1 . 5 , 3 0 , 3 0 ) ;
//
k o n i e c
d r u g i e j
l i s t y
w y ś w i e t l a n i a
g l E n d L i s t
( ) ;
}
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 | GLUT DEPTH | GLUT STENCIL ) ;
1. Bufor szablonowy
24
//
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
( 5 0 0 , 5 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
( ”CSG” ) ;
//
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 S c e n e ) ;
//
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 ( R es hape ) ;
//
o b s ł u g a
p r z y c i s k ó w
m y s z k i
g l u t M o u s e F u n c
( MouseButton ) ;
//
o b s ł u g a
r u c h u
k u r s o r a
m y s z k i
g l u t M o t i o n F u n c
( MouseMotion ) ;
//
u t w o r z e n i e
podmenu − O p e r a c j a CSG
i n t MenuCSGOp = g l u t C r e a t e M e n u
( Menu ) ;
glutAddMenuEntry
( ”A” , CSG A ) ;
glutAddMenuEntry
( ”B” , CSG B ) ;
glutAddMenuEntry
( ”A OR B” , CSG A OR B ) ;
glutAddMenuEntry
( ”A AND B” , CSG A AND B ) ;
glutAddMenuEntry
( ”A SUB B” , CSG A SUB B ) ;
glutAddMenuEntry
( ”B SUB A” , CSG B SUB A ) ;
//
u t w o r z e n i e
podmenu − A s p e k t
o b r a z u
i n t
MenuAspect = g l u t C r e a t e M e n u
( Menu ) ;
#i f d e f WIN32
glutAddMenuEntry
( ” A s p e k t
o b r a z u − c a ł e
okno ” ,FULL WINDOW ) ;
#e l s e
glutAddMenuEntry
( ” A s p e k t
o b r a z u − c a l e
okno ” ,FULL WINDOW ) ;
#e n d i f
glutAddMenuEntry
( ” A s p e k t
o b r a z u
1 : 1 ” , ASPECT 1 1 ) ;
// menu g ł ó w n e
g l u t C r e a t e M e n u
( Menu ) ;
glutAddSubMenu
( ” O p e r a c j a CSG” ,MenuCSGOp ) ;
#i f d e f WIN32
glutAddSubMenu
( ” A s p e k t
o b r a z u ” , MenuAspect ) ;
glutAddMenuEntry
( ” W y j ś c i e ” , EXIT ) ;
#e l s e
glutAddSubMenu
( ” A s p e k t
o b r a z u ” , MenuAspect ) ;
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 g o
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 ) ;
//
u t w o r z e n i e
l i s t
w y ś w i e t l a n i a
G e n e r a t e D i s p l a y L i s t s
( ) ;
//
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 ;
}
Trzeci program przykładowy (plik krawedzie.cpp) przestawia sposób
uzyskania przy użyciu bufora szablonowego krawędzi szkieletowych (ang.
silhouette edge) rysowanych obiektów sceny. Efekt jest bardzo łatwy do
usykania, ale niestety wymaga czterokrotnego narysowania obiektów sceny
przy czym za każdym razem obiekty muszą być przesunięte o jeden piksel
odpowiednio w lewo, w prawo, w górę i w dół. W ten sposób w buforze
szblonowym znajdą się informacje o „zarysach” obiektów. Następne - piąte
- rysowanie obiektów sceny następuje już przy ich normalnym położeniu
1. Bufor szablonowy
25
i służy do usunięcia z bufora szablonowego tej części informacji, która nie
jest związana z krawędziami obiektów. Aby narysowanć tak uzyskaną kra-
wędź wystarczy już zwykły prostokąt obejmujący całe okno renderingu i od-
powiednio ustawiony test bufora szablonowego. Całość opisywanej operacji
znajduje się w funkcji Silhouette.
Efekty działania programu przedstawiają rysunki 9 i 10.
Rysunek 9. Program Krawędzie - obiekt z krawędzią
1.5.3. Plik krawedzie.cpp
/∗
( c )
J a n u s z
G a n c z a r s k i
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>
#i n c l u d e <math . h>
#i n c l u d e
” c o l o r s . h ”
1. Bufor szablonowy
26
Rysunek 10. Program Krawędzie - zarys obiektu
//
s t a ł e
do
o b s ł u g i
menu
p o d r ę c z n e g o
enum
{
TORUS OBJ ,
//
t o r u s
CUBE OBJ ,
//
s z e ś c i a n
OBJECT,
//
r y s o w a n i e
t y l k o
o b i e k t u
SILHOUETTE,
//
r y s o w a n i e
t y l k o
k r a w ę d z i
s z k i e l e t o w y c h
SILHOUETTE OBJECT ,
//
r y s o w a n i e
o b i e k t u
i
k r a w ę d z i
s z k i e l e t o w y c h
EXIT
//
w y j ś c i e
} ;
//
r o z m i a r y
b r y ł y
o b c i n a n i a
const
GLint
l e f t = −5;
const
GLint
r i g h t = 5 ;
const
GLint bottom = −5;
const
GLint
t o p = 5 ;
const
GLint
n e a r = −5;
const
GLint
f a r = 5 ;
//
k ą t y
o b r o t u
s c e n y
G L f l o a t
r o t a t e x = 0 . 0 ;
G L f l o a t
r o t a t e y = 0 . 0 ;
1. Bufor szablonowy
27
//
w s k a ź n i k
n a c i ś n i ę c i a
l e w e g o
p r z y c i s k u
m y s z k i
i n t
b u t t o n s t a t e = GLUT UP ;
//
p o ł o ż e n i e
k u r s o r a
m y s z k i
i n t
b u t t o n x , b u t t o n y ;
//
i d e n t y f i k a t o r y
l i s t
w y ś w i e t l a n i a
GLint TORUS ID , CUBE ID ;
//
i d e n t y f i k a t o r
b i e ż ą c e j
l i s t y
w y ś w i e t l a n i a
GLint CURRENT OBJECT ;
//
t r y b
r y s o w a n i a
i n t
r e n d e r m o d e = SILHOUETTE OBJECT ;
//
r y s o w a n i e
k r a w ę d z i
s z k i e l e t o w y c h
void
S i l h o u e t t e
( )
{
//
w y ł ą c z e n i e
z a p i s u
s k ł a d o w y c h RGBA do
b u f o r a
k o l o r ó w
g l C o l o r M a s k
( GL FALSE , GL FALSE , GL FALSE , GL FALSE ) ;
//
w ł ą c z e n i e
b u f o r a
s z a b l o n o w e g o
g l E n a b l e
( GL STENCIL TEST ) ;
//
t e s t
b u f o r a
s z a b l o n o w e g o
g l S t e n c i l F u n c
(GL ALWAYS, 1 , 1 ) ;
//
o k r e ś l e n i e
o p e r a c j i
na
b u f o r z e
s z a b l o n o w y m
g l S t e n c i l O p
(GL KEEP , GL KEEP , GL REPLACE ) ;
//
w y ł ą c z e n i e
b u f o r a
g ł ę b o k o ś c i
g l D i s a b l e
(GL DEPTH TEST ) ;
//
w y ł ą c z n i e
o ś w i e t l e n i a
g l D i s a b l e
( GL LIGHTING ) ;
//
p o b r a n i e
r o z m i a r ó w
o k n a
r e n d e r i n g u
i n t
w i d t h = g l u t G e t
(GLUT WINDOW WIDTH ) ;
i n t
h e i g h t = g l u t G e t
(GLUT WINDOW HEIGHT ) ;
//
c z t e r o k r o t n e
n a r y s o w a n i e
o b i e k t u
p r z e s u n i ę t e g o
// o
j e d e n
p i k s e l
w l e w o ,
prawo , d ó ł
i
g ó r ę
g l V i e w p o r t
( − 1 , 0 , width −1 , h e i g h t ) ;
g l C a l l L i s t
(CURRENT OBJECT ) ;
g l V i e w p o r t
( 1 , 0 , w i d t h +1 , h e i g h t ) ;
g l C a l l L i s t
(CURRENT OBJECT ) ;
g l V i e w p o r t
( 0 , − 1 , width , h e i g h t − 1 ) ;
g l C a l l L i s t
(CURRENT OBJECT ) ;
g l V i e w p o r t
( 0 , 1 , width , h e i g h t + 1 ) ;
g l C a l l L i s t
(CURRENT OBJECT ) ;
//
p o w r ó t
do
p o d s t a w o w e g o
o b s z a r u
r e n d e r i n g u
g l V i e w p o r t
( 0 , 0 , width , h e i g h t ) ;
//
t e s t
b u f o r a
s z a b l o n o w e g o
g l S t e n c i l F u n c
(GL ALWAYS, 0 , 0 ) ;
//
n a r y s o w a n i e
b i e ż ą c e g o
o b i e k t u
g l C a l l L i s t
(CURRENT OBJECT ) ;
//
w ł ą c z e n i e
z a p i s u
s k ł a d o w y c h RGBA do
b u f o r a
k o l o r ó w
g l C o l o r M a s k
(GL TRUE, GL TRUE, GL TRUE, GL TRUE ) ;
//
t e s t
b u f o r a
s z a b l o n o w e g o
g l S t e n c i l F u n c
(GL EQUAL , 1 , 1 ) ;
//
o d ł o ż e n i e
m a c i e r z y
m o d e l o w a n i a
na
s t o s
g l P u s h M a t r i x
( ) ;
//
m a c i e r z
m o d e l o w a n i a = m a c i e r z
j e d n o s t k o w a
g l L o a d I d e n t i t y
( ) ;
//
k o l o r
k r a w ę d z i
s z k i e l e t o w y c h
1. Bufor szablonowy
28
g l C o l o r 3 f v
( Y e l l o w ) ;
//
n a r y s o w a n i e
p r o s t o k ą t a − f a k t y c z n i e
k r a w ę d z i
s z k i e l e t o w y c h
g l R e c t i
( l e f t , bottom , r i g h t , t o p ) ;
//
z d j ę c i e
m a c i e r z y
m o d e l o w a n i a
z e
s t o s u
g l P o p M a t r i x
( ) ;
//
w ł ą c z e n i e
b u f o r a
g ł ę b o k o ś c i
g l E n a b l e
(GL DEPTH TEST ) ;
//
w ł ą c z e n i e
o ś w i e t l e n i a
g l E n a b l e
( GL LIGHTING ) ;
//
w y ł ą c z e n i e
b u f o r a
s z a b l o n o w e g o
g l D i s a b l e
( GL STENCIL TEST ) ;
}
//
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 S c e n e
( )
{
//
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
( 0 . 0 , 0 . 0 , 1 . 0 , 1 . 0 ) ;
// w
z a l e ż n o ś c i
od
t r y b u
r y s o w a n i a
c z y s z c z e n i e
b u f o r a
k o l o r u ,
b u f o r a
//
g ł ę b o k o ś c i
i
b u f o r a
s z a b l o n o w e g o
i f
( r e n d e r m o d e == OBJECT)
g l C l e a r
( GL COLOR BUFFER BIT | GL DEPTH BUFFER BIT ) ;
e l s e
g l C l e a r
( GL COLOR BUFFER BIT | GL DEPTH BUFFER BIT |
GL STENCIL BUFFER BIT ) ;
//
w y b ó r
m a c i e r z y
m o d e l o w a n i a
g l M a t r i x M o d e
(GL MODELVIEW ) ;
//
m a c i e r z
m o d e l o w a n i a = m a c i e r z
j e d n o s t k o w a
g l L o a d I d e n t i t y
( ) ;
//
o b r o t y
c a ł e j
s c e n y
g l R o t a t e f
( r o t a t e x , 1 . 0 , 0 . 0 , 0 . 0 ) ;
g l R o t a t e f
( r o t a t e y , 0 . 0 , 1 . 0 , 0 . 0 ) ;
//
w ł ą c z e n i e
o ś w i e t l e n i a
g l E n a b l e
( GL LIGHTING ) ;
//
w ł ą c z e n i e
ś w i a t ł a
GL LIGHT0
g l E n a b l e
( GL LIGHT0 ) ;
//
w ł ą c z e n i e
a u t o m a t y c z n e j
n o r m a l i z a c j i
w e k t o r ó w
n o r m a l n y c h
g l E n a b l e
(GL NORMALIZE ) ;
//
w ł ą c z e n i e
o b s ł u g i
w ł a ś c i w o ś c i
m a t e r i a ł ó w
g l E n a b l e
(GL COLOR MATERIAL ) ;
//
w ł a ś c i w o ś c i
m a t e r i a ł u
o k r e ś l o n e
p r z e z
k o l o r
w i e r z c h o ł k ó w
g l C o l o r M a t e r i a l
(GL FRONT, GL AMBIENT AND DIFFUSE ) ;
//
w ł ą c z e n i e
b u f o r a
g ł ę b o k o ś c i
g l E n a b l e
(GL DEPTH TEST ) ;
//
n a r y s o w a n i e
w y b r a n y c h
e l e m e n t ó w
s c e n y
switch
( r e n d e r m o d e )
{
//
r y s o w a n i e
t y l k o
k r a w ę d z i
s z k i e l e t o w y c h
c a s e SILHOUETTE :
S i l h o u e t t e
( ) ;
break ;
//
r y s o w a n i e
o b i e k t u
i
k r a w ę d z i
s z k i e l e t o w y c h
c a s e SILHOUETTE OBJECT :
S i l h o u e t t e
( ) ;
g l C a l l L i s t
(CURRENT OBJECT ) ;
break ;
//
r y s o w a n i e
t y l k o
o b i e k t u
c a s e OBJECT :
g l C a l l L i s t
(CURRENT OBJECT ) ;
break ;
}
1. Bufor szablonowy
29
//
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 )
{
//
o b s z a r
r e n d e r i n g u − c a ł e
o k n o
g l V i e w p o r t
( 0 , 0 , width , h e i g h t ) ;
//
w y b ó r
m a c i e r z y
r z u t o w a n i a
g l M a t r i x M o d e
(GL PROJECTION ) ;
//
m a c i e r z
r z u t o w a n i a = m a c i e r z
j e d n o s t k o w a
g l L o a d I d e n t i t y
( ) ;
//
p a r a m e t r y
b r y ł y
o b c i n a n i a
g l O r t h o
( l e f t , r i g h t , bottom , top , n e a r , f a r ) ;
//
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 c e n e
( ) ;
}
//
o b s ł u g a
p r z y c i s k ó w
m y s z k i
void MouseButton
( i n t
b u t t o n ,
i n t
s t a t e ,
i n t x ,
i n t
y )
{
i f
( b u t t o n == GLUT LEFT BUTTON)
{
//
z a p a m i ę t a n i e
s t a n u
l e w e g o
p r z y c i s k u
m y s z k i
b u t t o n s t a t e = s t a t e ;
//
z a p a m i ę t a n i e
p o ł o ż e n i a
k u r s o r a
m y s z k i
i f
( s t a t e == GLUT DOWN)
{
b u t t o n x = x ;
b u t t o n y = y ;
}
}
}
//
o b s ł u g a
r u c h u
k u r s o r a
m y s z k i
void MouseMotion
( i n t x ,
i n t
y )
{
i f
( b u t t o n s t a t e == GLUT DOWN)
{
r o t a t e y += 50
∗ ( r i g h t − l e f t ) / ( f l o a t ) g l u t G e t
(GLUT WINDOW WIDTH)
∗ ( x − b u t t o n x ) ;
b u t t o n x = x ;
r o t a t e x −= 50
∗ ( t o p − bottom ) / ( f l o a t ) g l u t G e t
(GLUT WINDOW HEIGHT)
∗ ( b u t t o n y − y ) ;
b u t t o n y = y ;
g l u t P o s t R e d i s p l a y
( ) ;
}
}
//
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 )
{
switch
( v a l u e )
{
//
t o r u s
c a s e TORUS OBJ :
CURRENT OBJECT = TORUS ID ;
D i s p l a y S c e n e
( ) ;
break ;
//
s z e ś c i a n
c a s e CUBE OBJ :
CURRENT OBJECT = CUBE ID ;
D i s p l a y S c e n e
( ) ;
break ;
//
r y s o w a n i e
t y l k o
o b i e k t u
c a s e OBJECT :
1. Bufor szablonowy
30
//
r y s o w a n i e
t y l k o
k r a w ę d z i
s z k i e l e t o w y c h
c a s e SILHOUETTE :
//
r y s o w a n i e
o b i e k t u
i
k r a w ę d z i
s z k i e l e t o w y c h
c a s e SILHOUETTE OBJECT :
r e n d e r m o d e = v a l u e ;
D i s p l a y S c e n e
( ) ;
break ;
//
w y j ś c i e
c a s e EXIT :
e x i t
( 0 ) ;
}
}
//
u t w o r z e n i e
l i s t
w y ś w i e t l a n i a
void
G e n e r a t e D i s p l a y L i s t s
( )
{
//
g e n e r o w a n i e
i d e n t y f i k a t o r a
p i e r w s z e j
l i s t y
w y ś w i e t l a n i a
TORUS ID = g l G e n L i s t s
( 1 ) ;
//
p i e r w s z a
l i s t a
w y ś w i e t l a n i a
g l N e w L i s t
( TORUS ID , GL COMPILE ) ;
//
c z e r w o n y
t o r u s
g l C o l o r 4 f v
( Red ) ;
g l u t S o l i d T o r u s
( 1 . 0 , 2 . 0 , 2 0 , 2 0 ) ;
//
k o n i e c
p i e r w s z e j
l i s t y
w y ś w i e t l a n i a
g l E n d L i s t
( ) ;
//
g e n e r o w a n i e
i d e n t y f i k a t o r a
d r u g i e j
l i s t y
w y ś w i e t l a n i a
CUBE ID = g l G e n L i s t s
( 1 ) ;
//
d r u g a
l i s t a
w y ś w i e t l a n i a
g l N e w L i s t
( CUBE ID , GL COMPILE ) ;
//
z i e l o n y
s z e ś c i a n
g l C o l o r 4 f v
( Green ) ;
g l u t S o l i d C u b e
( 4 . 0 ) ;
//
k o n i e c
d r u g i e j
l i s t y
w y ś w i e t l a n i a
g l E n d L i s t
( ) ;
//
b i e ż ą c y
o b i e k t
CURRENT OBJECT = TORUS ID ;
}
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 | GLUT DEPTH | GLUT STENCIL ) ;
//
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
( 5 0 0 , 5 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
#i f d e f WIN32
g l u t C r e a t e W i n d o w
( ” K r a w ę d z i e ” ) ;
#e l s e
g l u t C r e a t e W i n d o w
( ” K r a w e d z i e ” ) ;
#e n d i f
//
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 S c e n e ) ;
//
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 ) ;
//
o b s ł u g a
p r z y c i s k ó w
m y s z k i
g l u t M o u s e F u n c
( MouseButton ) ;
//
o b s ł u g a
r u c h u
k u r s o r a
m y s z k i
g l u t M o t i o n F u n c
( MouseMotion ) ;
1. Bufor szablonowy
31
//
u t w o r z e n i e
podmenu − O b i e k t
i n t
MenuObject = g l u t C r e a t e M e n u
( Menu ) ;
glutAddMenuEntry
( ” T o r u s ” ,TORUS OBJ ) ;
#i f d e f WIN32
glutAddMenuEntry
( ” S z e ś c i a n ” ,CUBE OBJ ) ;
#e l s e
glutAddMenuEntry
( ” S z e s c i a n ” ,CUBE OBJ ) ;
#e n d i f
//
u t w o r z e n i e
podmenu − T r y b
r y s o w a n i a
i n t
MenuRenderMode = g l u t C r e a t e M e n u
( Menu ) ;
glutAddMenuEntry
( ” T y l k o
o b i e k t ” ,OBJECT ) ;
#i f d e f WIN32
glutAddMenuEntry
( ” T y l k o
k r a w ę d z i e
s z k i e l e t o w e ” ,SILHOUETTE ) ;
glutAddMenuEntry
( ” O b i e k t
i
k r a w ę d z i e
s z k i e l e t o w e ” ,SILHOUETTE OBJECT ) ;
#e l s e
glutAddMenuEntry
( ” T y l k o
k r a w e d z i e
s z k i e l e t o w e ” ,SILHOUETTE ) ;
glutAddMenuEntry
( ” O b i e k t
i
k r a w e d z i e
s z k i e l e t o w e ” ,SILHOUETTE OBJECT ) ;
#e n d i f
// menu g ł ó w n e
g l u t C r e a t e M e n u
( Menu ) ;
glutAddSubMenu
( ” O b i e k t ” , MenuObject ) ;
glutAddSubMenu
( ” Tryb
r y s o w a n i a ” , MenuRenderMode ) ;
#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 g o
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 ) ;
//
u t w o r z e n i e
l i s t
w y ś w i e t l a n i a
G e n e r a t e D i s p l a y L i s t s
( ) ;
//
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 ;
}
Ostatni program przykładowy (plik przejscie obrazow.cpp) przedsta-
wia sposób uzyskania przy użyciu bufora szablonowego efektu przejścia po-
między obrazami (ang. dissolving). Efekt jest bardzo prosty do uzyskania,
i daje bardzo ciekawe rezultaty. Przykładowy widok okna programu przed-
stawia rysunek 11.
1.5.4. Plik przejscie obrazow.cpp
/∗
( c )
J a n u s z
G a n c z a r s k i
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 <GL/ g l e x t . h>
#i n c l u d e < s t d l i b . h>
#i n c l u d e < s t r i n g . h>
#i n c l u d e < s t d i o . h>
#i n c l u d e
” t a r g a . h ”
//
s t a ł e
do
o b s ł u g i
menu
p o d r ę c z n e g o
enum
{
1. Bufor szablonowy
32
Rysunek 11. Program Przejście obrazów
CLEAR STENCIL ,
//
c z y s z c z e n i e
b u f o r a
s z a b l o n o w e g o
EXIT
//
w y j ś c i e
} ;
//
w s k a ź n i k
n a c i ś n i ę c i a
l e w e g o
p r z y c i s k u
m y s z k i
i n t
b u t t o n s t a t e = GLUT UP ;
//
p o ł o ż e n i e
k u r s o r a
m y s z k i
i n t
b u t t o n x , b u t t o n y ;
//
r o z m i a r y
g u m k i
const
i n t
e r a s e r w i d t h = 8 0 ;
const
i n t
e r a s e r h e i g h t = 8 0 ;
//
t a b l i c a
na
d a n e mapy
p i k s e l o w e j
z
gumką
GLubyte
e r a s e r p i x m a p
[ 4
∗
e r a s e r w i d t h
∗
e r a s e r h e i g h t ] ;
//
d a n e
o p i s u j ą c e
o b r a z
o d c z y t a n y
z
p l i k u TARGA
G L s i z e i
w i d t h ;
//
s z e r o k o ś ć
o b r a z u
G L s i z e i
h e i g h t ;
//
w y s o k o ś ć
o b r a z u
GLenum f o r m a t ;
//
f o r m a t
d a n y c h
o b r a z u
GLenum t y p e ;
//
f o r m a t
d a n y c h
p i k s e l i
o b r a z u
1. Bufor szablonowy
33
GLvoid ∗ p i x e l s ;
//
w s k a ź n i k
na
t a b l i c ę
z
d a n y m i
o b r a z u
//
w c z y t a n i e
p l i k u
g r a f i c z n e g o
w f o r m a c i e TARGA
void LoadTARGA ( i n t
a r g c ,
char ∗ a r g v [ ] )
{
//
s p r a w d z e n i e
c z y
j e s t
p a r a m e t r
i f
( a r g c < 2 )
{
p r i n t f
( ” Brak nazwy
p l i k u TARGA\n ” ) ;
e x i t
( 1 ) ;
}
//
o d c z y t
p l i k u TARGA i
e w e n t u a l n y
k o m u n i k a t
o
b ł ę d z i e
i f
( ! l o a d t a r g a
( a r g v [ 1 ] , width , h e i g h t , f o r m a t , t y p e , p i x e l s ) )
{
#i f d e f WIN32
p r i n t f
( ” Błąd
o d c z y t u
l u b
b ł ę d n y
f o r m a t
p l i k u : %s \n ” , a r g v [ 1 ] ) ;
#e l s e
p r i n t f
( ” B l ad
o d c z y t u
l u b
b l e d n y
f o r m a t
p l i k u : %s \n ” , a r g v [ 1 ] ) ;
#e n d i f
e x i t
( 1 ) ;
}
}
//
s p r a w d z e n i e
c z y
d a n y
f o r m a t
p l i k u TARGA j e s t
o b s ł u g i w a n y
void CheckImageFormat
( )
{
//
o b r a z w f o r m a c i e BGR i BGRA
i f
( f o r m a t == GL BGR
| |
f o r m a t == GL BGRA)
{
//
o d c z y t
w e r s j i
OpenGL
const char ∗ v e r s i o n = ( char ∗ ) g l G e t S t r i n g
( GL VERSION ) ;
i n t
m a j o r = 0 ,
m i n o r = 0 ;
i f
( s s c a n f
( v e r s i o n , ”%d.%d ” ,& major ,& m i n o r )
!=
2 )
{
#i f d e f WIN32
p r i n t f
( ” Błędny
f o r m a t
w e r s j i
OpenGL\n ” ) ;
#e l s e
p r i n t f
( ” B l e d n y
f o r m a t
w e r s j i
OpenGL\n ” ) ;
#e n d i f
e x i t
( 1 ) ;
}
//
s p r a w d z e n i e
c z y
j e s t
c o
n a j m n i e j
w e r s j a
1 . 2
OpenGL
i f
( m a j o r <= 1 && m i n o r < 2 )
{
//
j e ż e l i
j e s t
s t a r s z a
w e r s j a
OpenGL
s p r a w d z e n i e
//
c z y
j e s t
o b s ł u g a
r o z s z e r z e n i a
GL EXT bgra
i f
( ! g l u t E x t e n s i o n S u p p o r t e d
( ” GL EXT bgra ” ) )
{
//
k o m u n i k a t
o
b ł ę d z i e − w tym
m i e j s c u
można
w y k o n a ć
//
k o n w e r s j ę
d a n y c h
z
f o r m a t u BGR/BGRA na RGB/RGBA
p r i n t f
( ” Brak
r o z s z e r z e n i a
GL EXT bgra \n ” ) ;
e x i t
( 1 ) ;
}
}
}
}
//
w y g e n e r o w a n i e
d a n y c h
mapy
p i k s e l o w e j
z
gumką
void
G e n e r a t e E r a s e r
( )
{
//
p o k o l o r o w a n i e
c a ł e j
g u m k i
na
j a s n o
s z a r o
memset
( e r a s e r p i x m a p , 1 9 6 , 4
∗
e r a s e r w i d t h
∗
e r a s e r h e i g h t ) ;
}
//
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 ) ;
1. Bufor szablonowy
34
//
w a r t o ś ć
c z y s z c z ą c a
b u f o r
s z a b l o n o w y
g l C l e a r S t e n c i l
( ˜ 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 ) ;
//
w y b ó r
m a c i e r z y
m o d e l o w a n i a
g l M a t r i x M o d e
(GL MODELVIEW ) ;
//
m a c i e r z
m o d e l o w a n i a = m a c i e r z
j e d n o s t k o w a
g l L o a d I d e n t i t y
( ) ;
//
w ł ą c z e n i e
b u f o r a
s z a b l o n o w e g o
g l E n a b l e
( GL STENCIL TEST ) ;
//
o k r e ś l e n i e
o p e r a c j i
na
b u f o r z e
s z a b l o n o w y m
g l S t e n c i l O p
(GL KEEP , GL KEEP , GL KEEP ) ;
//
t e s t
b u f o r a
s z a b l o n o w e g o
g l S t e n c i l F u n c
(GL EQUAL, 1 , ˜ 0 ) ;
//
p o z y c j a
mapy
p i k s e l o w e j
g l R a s t e r P o s 2 i
( 0 , 0 ) ;
//
w y r ó w n y w a n i e
w i e r s z a
mapy
p i k s e l o w e j
do
p o j e d y ń c z e g o
b a j t a
g l P i x e l S t o r e i
(GL UNPACK ALIGNMENT, 1 ) ;
//
s k a l o w a n i e
mapy
p i k s e l o w e j
do
r o z m i a r ó w
o k n a
g l P i x e l Z o o m
( ( f l o a t ) g l u t G e t (GLUT WINDOW WIDTH) / ( f l o a t ) width ,
( f l o a t ) g l u t G e t (GLUT WINDOW HEIGHT) / ( f l o a t ) h e i g h t ) ;
//
w y ś w i e t l e n i e
o b r a z u
z a w a r t e g o w m a p i e
p i k s e l o w e j
g l D r a w P i x e l s
( width , h e i g h t , f o r m a t , t y p e , p i x e l s ) ;
//
n e u t r a l n e
s k a l o w a n i e
mapy
p i k s e l o w e j
g l P i x e l Z o o m
( 1 . 0 , 1 . 0 ) ;
//
r y s o w a n i e
g u m k i
i f
( b u t t o n s t a t e == GLUT DOWN)
{
//
t e s t
b u f o r a
s z a b l o n o w e g o
g l S t e n c i l F u n c
(GL ALWAYS, 1 , 0 ) ;
//
o k r e ś l e n i e
o p e r a c j i
na
b u f o r z e
s z a b l o n o w y m
g l S t e n c i l O p
(GL KEEP , GL REPLACE, GL REPLACE ) ;
//
w ł ą c z e n i e
m i e s z a n i a
k o l o r ó w
g l E n a b l e
(GL BLEND ) ;
//
f u n k c j a
m i e s z a n i a
k o l o r ó w
g l B l e n d F u n c
( GL SRC ALPHA , GL ONE MINUS SRC ALPHA ) ;
//
p o z y c j a
g u m k i
g l R a s t e r P o s 2 i
( b u t t o n x , b u t t o n y ) ;
//
p r z e s u n i ę c i e
p o z y c j i
k u r s o r a
do
ś r o d k a
g u m k i
g l B i t m a p
( 0 , 0 , 0 . 0 , 0 . 0 , − e r a s e r w i d t h / 2 . 0 , − e r a s e r h e i g h t / 2 . 0 ,NULL ) ;
//
n a r y s o w a n i e
g u m k i i
g l D r a w P i x e l s
( e r a s e r w i d t h , e r a s e r h e i g h t , GL RGBA, GL UNSIGNED BYTE , e r a s e r p i x m a p ) ;
//
w y ł ą c z e n i e
m i e s z a n i a
k o l o r ó w
g l D i s a b l e
(GL BLEND ) ;
}
//
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 )
{
//
o b s z a r
r e n d e r i n g u − c a ł e
o k n o
g l V i e w p o r t
( 0 , 0 , Width , H e i g h t ) ;
//
w y b ó r
m a c i e r z y
r z u t o w a n i a
g l M a t r i x M o d e
(GL PROJECTION ) ;
//
m a c i e r z
r z u t o w a n i a = m a c i e r z
j e d n o s t k o w a
1. Bufor szablonowy
35
g l L o a d I d e n t i t y
( ) ;
//
p a r a m e t r y
b r y ł y
o b c i n a n i a
g l u O r t h o 2 D
( 0 . 0 , Width , 0 . 0 , H e i g h t ) ;
//
c z y s z c z e n i e
b u f o r a
s z a b l o n o w e g o
g l C l e a r
( GL STENCIL BUFFER BIT ) ;
//
g e n e r o w a n i e
s c e n y
3D
D i s p l a y
( ) ;
}
//
o b s ł u g a
p r z y c i s k ó w
m y s z k i
void MouseButton
( i n t
b u t t o n ,
i n t
s t a t e ,
i n t x ,
i n t
y )
{
i f
( b u t t o n == GLUT LEFT BUTTON)
{
//
z a p a m i ę t a n i e
s t a n u
l e w e g o
p r z y c i s k u
m y s z k i
b u t t o n s t a t e = s t a t e ;
//
z a p a m i ę t a n i e
p o ł o ż e n i a
k u r s o r a
m y s z k i
i f
( s t a t e == GLUT DOWN)
{
b u t t o n x = x ;
b u t t o n y = y ;
}
}
}
//
o b s ł u g a
r u c h u
k u r s o r a
m y s z k i
void MouseMotion
( i n t x ,
i n t
y )
{
i f
( b u t t o n s t a t e == GLUT DOWN)
{
b u t t o n x = x ;
b u t t o n y = g l u t G e t
(GLUT WINDOW HEIGHT) − y ;
g l u t P o s t R e d i s p l a y
( ) ;
}
}
//
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 )
{
switch
( v a l u e )
{
//
c z y s z c z e n i e
b u f o r a
s z a b l o n o w e g o
c a s e CLEAR STENCIL :
g l C l e a r
( GL STENCIL BUFFER BIT ) ;
g l u t P o s t R e d i s p l a y ( ) ;
break ;
//
w y j ś c i e
c a s e EXIT :
e x i t
( 0 ) ;
break ;
}
}
main
( i n t
a r g c ,
char ∗ a r g v [ ] )
{
//
o d c z y t
p l i k u
g r a f i c z n e g o TARGA
LoadTARGA ( a r g c , 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 | GLUT STENCIL ) ;
//
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
( 5 0 0 , 5 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
#i f d e f WIN32
g l u t C r e a t e W i n d o w
( ” P r z e j ś c i e
o b r a z ó w ” ) ;
#e l s e
1. Bufor szablonowy
36
g l u t C r e a t e W i n d o w
( ” P r z e j s c i e
o b r a z o w ” ) ;
#e n d i f
//
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 ) ;
//
o b s ł u g a
p r z y c i s k ó w
m y s z k i
g l u t M o u s e F u n c
( MouseButton ) ;
//
o b s ł u g a
r u c h u
k u r s o r a
m y s z k i
g l u t M o t i o n F u n c
( MouseMotion ) ;
//
s p r a w d z e n i e
c z y
d a n y
f o r m a t
p l i k u TARGA j e s t
o b s ł u g i w a n y
CheckImageFormat
( ) ;
//
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 ) ;
#i f d e f WIN32
glutAddMenuEntry
( ” Wyczyść
b u f o r
s z a b l o n o w y ” , CLEAR STENCIL ) ;
glutAddMenuEntry
( ” W y j ś c i e ” , EXIT ) ;
#e l s e
glutAddMenuEntry
( ” Wyczysc
b u f o r
s z a b l o n o w y ” , CLEAR STENCIL ) ;
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 g o
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 y g e n e r o w a n i e
d a n y c h
mapy
p i k s e l o w e j
z
gumką
G e n e r a t e E r a s e r
( ) ;
//
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
37
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