Janusz Ganczarski
OpenGL
Test zasłaniania
Spis treści
Spis treści . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1
1. Testy zasłaniania . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1
Bryły ograniczające . . . . . . . . . . . . . . . . . . . . . . . . . . .
1
Obiekty analizy przesłonięć . . . . . . . . . . . . . . . . . . . . . . .
1
. . . . . . . . . . . . . . . . . . . . . . . . . . .
2
Właściwości obiektu analizy przesłonięć . . . . . . . . . . . . . . . .
2
Program przykładowy . . . . . . . . . . . . . . . . . . . . . . . . . .
3
Plik test zaslaniania.cpp . . . . . . . . . . . . . . . . . . . .
5
Literatura . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
15
1. Testy zasłaniania
W wersji 1.5 biblioteki OpenGL (rozszerzenie ARB occlusion query)
wprowadzono technikę testowania zasłaniania niewidocznych obiektów przy
użyciu brył ograniczających. Pozwala to na uniknięcie rysowania tych ele-
mentów sceny, które nie są w danym momencie widoczne. Odpowiednie uży-
cie testów zasłaniania umożliwia znaczące przyspieszenie rysowania sceny.
1.1. Bryły ograniczające
Bryła ograniczająca jest obiektem zbudowanym z prymitywów OpenGL,
która w całości zawiera wewnątrz (otacza) wybrane elementy sceny. Efektyw-
ność działania bryły ograniczającej zależy od dwóch sprzecznych wymagań.
Im mniejsza ilość wielokątów opisujących bryłę ograniczającą tym szybciej
wykonywany jest test zasłaniania. I przeciwnie, im bryła ograniczająca ma
kształt bardziej zbliżony (przylegający) do otaczanych elementów sceny, tym
dokładniej wykonywany jest test zasłaniania. W praktyce jako brył ograni-
czających używa się różnego rodzaju wielościanów.
Technika brył ograniczających wykorzystana w bibliotece OpenGL nie
jest oczywiście niczym nowym. Jest ona znana i stosowana od wielu lat
w specjalistycznych bibliotekach i programach do grafiki 3D.
1.2. Obiekty analizy przesłonięć
Przy analizie przesłonięć biblioteka OpenGL korzysta ze specjalnych
obiektów. Obiekty analizy przesłonięć posiadają unikatowe identyfikatory,
które generuje funkcja:
void glGenQueries (GLsizei n, GLuint *ids)
Parametr n określa ilość generowanych identyfikatorów obiektów analizy
przesłonięć, które umieszczane są w tablicy ids.
Usuwanie wybranych obiektów analizy przesłonięć wymaga wywołania
funkcji:
void glDeleteQueries (GLsizei n, const GLuint *ids)
której parametr n określa ilość usuwanych obiektów, a tablica ids zawiera
ich identyfikatory.
Sprawdzenie, czy dany identyfikator jest związany z obiektem analizy
przesłonięć umożliwia funkcja logiczna:
GLboolean glIsQuery (GLuint id)
1. Testy zasłaniania
2
1.3. Analiza przesłonięć
Rozpoczęcie analizy przesłonięć wymaga wywołania funkcji:
void glBeginQuery (GLenum target, GLuint id)
Parametr target określa rodzaj wykonywanego zapytania i przyjmuje
wartość GL SAMPLES PASSED. Drugi parametr id zawiera numer identyfika-
tora obiektu analizy.
Funkcja glBeginQuery tworzy nowy obiekt analizy przesłonięć. Jeżeli
z identyfikatorem id związany jest już inny obiekt analizy przesłonięć, lub
wartość tego identyfikatora wynosi zero, generowany jest błąd GL INVALID -
OPERATION.
Zakończenie analizy przesłonięć dla bieżącego obiektu analizy wymaga
wywołania funkcji:
void glEndQuery (GLenum target)
której parametr target może przyjąć jedynie wartość GL SAMPLES PASSED.
W danym czasie OpenGL może dokonywać tylko analizy przesłonięć tylko
dla jednego obiektu analizy.
Sprawdzenie stanu analiz określonego typu (aktualnie dostępne są tylko
analizy przesłonięć) umożliwia funkcja:
void glGetQueryiv (GLenum target,
GLenum pname,
GLint *params)
Parametr target może przyjąć jedynie wartość GL SAMPLES PASSED,
a sprawdzany parametr stanu analiz określa pname, który przyjmuje jedną
z dwóch wartości:
— GL CURRENT QUERY - identyfikator aktywnej analizy przesłonięć,
— GL QUERY COUNTER BITS - liczba bitów licznika służącego do obliczania
wyników analizy.
Warto zauważyć, że liczba bitów licznika analizy może wynosić 0, co
w praktyce oznacza niedostępność testu zasłaniania. Minimalna ilość bitów
licznika zależy od implementacji i wynika z maksymalnych obsługiwanych
rozmiarów okna renderingu OpenGL.
1.4. Właściwości obiektu analizy przesłonięć
Pobieranie właściwości obiektu analizy przesłonięć umożliwiają funkcje
z grupy glGetQueryObject:
void glGetQueryObjectiv (GLuint id,
GLenum pname,
1. Testy zasłaniania
3
GLint *params)
void glGetQueryObjectuiv (GLuint id,
GLenum pname,
GLuint *params)
Parametr id zawiera unikatowy identyfikator obiektu analizy przesłonięć.
Drugi parametr pname wskazuje rodzaj pobieranej właściwości obiektu, któ-
rej wartość zostanie zwrócona w parametrze params. Dostępne są następując
właściwości obiektów analizy przesłonięć:
— GL QUERY RESULT - wartość licznika analizy,
— GL QUERY RESULT AVAILABLE - informacja, czy wartość licznika analizy
jest dostępna; dostępność licznika uwarunkowana jest oczekiwaniem na
zakończenie analizy.
Wyjaśnienia wymaga jeszcze jak należy interpretować wynik analizy
przesłonięć. Jest to po prostu ilość fragmentów bryły ograniczającej, które
przeszły pomyślnie test głębokości. Wartość zero licznika analizy oznacza,
że żaden fragment bryły ograniczającej nie jest widoczny, a zatem nie jest
widoczny także właściwy obiekt.
Sprawdzanie dostępności wyników analizy jest niezbędne, ponieważ mogą
zdarzyć się sytuacje, w których wynik jednaj analizy jest zależny od wyni-
ku innych analiz. W czasie oczekiwania na wynik analizy aplikacja może
wykonywać inne operacje.
1.5. Program przykładowy
Program przykładowy prezentowany na listingu test zaslaniania.cpp
zawiera prosty test skuteczności techniki analizy przesłonięć. Program rysuje
dwie skomplikowane kule, które przedzielone są tak ułożonym prostopadło-
ścianem, aby istniała możliwość całkowitego zasłonięcia jednej z kul. Jako
bryłę ograniczającą wykorzystano sześcian, który przy tak skonstruowanej
scenie jest wystarczająco efektywny.
Kolejność postępowania przy rysowaniu sceny z testem zasłaniania jest
następująca:
1. rysujemy wszystkie elementy sceny, które nie są objęte testem zasłania-
nia,
2. wyłączamy wszystkie zbędne właściwości sceny (np. oświetlenie) pozo-
stawiając jedynie włączony bufor głębokości,
3. wyłączamy zapis do bufora głębokości i do bufora koloru,
4. wykonujemy analizę zasłonięć dla wybranych obiektów,
5. po zakończeniu analizy przesłonięć na podstawie jej wyników rysujemy
wszystkie widoczne obiekty sceny, oczywiście po wcześniejszym włącze-
niu zapisu do buforów głębokości i koloru oraz ponownej aktywacji po-
zostałych efektów wykorzystywanych w scenie.
1. Testy zasłaniania
4
Wymienione w punkcie drugim wyłącznie efektów stosowanych w sce-
nie za wyjątkiem bufora głębokości ma na celu przyspieszenie wykonywania
testu zasłaniania, w którym przykładowo parametry oświetlenia nie mają
żadnego znaczenia dla ostatecznego wyniku.
Rysunek 1. Program Test zasłaniania - scena z włączonym testem zasłania-
nia
Wyniki działania przykładowego programu pokazują, że analiza zasłania
potrafi znacząco przyspieszyć rysowanie sceny. Wystarczy porównać ilość
wyświetlanych ramek na sekundę przy włączonym (rysunek 1) i wyłączo-
nym (rysunek 2) teście zasłaniania. Jak należało się spodziewać rysowanie
szybkość sceny przy wyłączony teście zasłaniana nie jest w żaden sposób
zależna od tego, które elementy są aktualnie widoczne - patrz rysunek 3. Na
ostatnim rysunku 4 przedstawiono scenę z widocznymi krawędziami brył
ograniczających.
1. Testy zasłaniania
5
Rysunek 2. Program Test zasłaniania - scena z wyłączonym testem zasła-
niania
1.5.1. Plik test zaslaniania.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 f n d e f WIN32
#d e f i n e GLX GLXEXT LEGACY
#i n c l u d e <GL/ g l x . h>
#d e f i n e
w g l G e t P r o c A d d r e s s
glXGetProcAddressARB
#e n d i f
#i n c l u d e < s t d l i b . h>
#i n c l u d e < s t d i o . h>
#i n c l u d e <t i m e . h>
#i n c l u d e
” c o l o r s . h ”
//
w s k a ź n i k
na
f u n k c j ę
g l W i n d o w P o s 2 i
PFNGLWINDOWPOS2IPROC g l W i n d o w P o s 2 i = NULL ;
1. Testy zasłaniania
6
Rysunek 3. Program Test zasłaniania - scena z widocznymi dwiema kulami
//
w s k a ź n i k
na
f u n k c j ę
g l G e n Q u e r i e s
PFNGLGENQUERIESPROC g l G e n Q u e r i e s = NULL ;
//
w s k a ź n i k
na
f u n k c j ę
g l B e g i n Q u e r y
PFNGLBEGINQUERYPROC g l B e g i n Q u e r y = NULL ;
//
w s k a ź n i k
na
f u n k c j ę
g l E n d Q u e r y
PFNGLENDQUERYPROC glEndQuery = NULL ;
//
w s k a ź n i k
na
f u n k c j ę
g l G e t Q u e r y O b j e c t i v
PFNGLGETQUERYOBJECTIVPROC g l G e t Q u e r y O b j e c t i v = NULL ;
//
w s k a ź n i k
na
f u n k c j ę
g l D e l e t e Q u e r i e s
PFNGLDELETEQUERIESPROC g l D e l e t e Q u e r i e s = NULL ;
//
s t a ł e
do
o b s ł u g i
menu
p o d r ę c z n e g o
enum
{
OCCLUSION TEST ,
//
w ł ą c z e n i e / w y ł ą c z e n i e
t e s t u
z a s ł a n i a n i a
OCCLUSION BOX,
//
w ł ą c z e n i e / w y ł ą c z e n i e
r y s o w a n i a
b r y ł
o g r a n i c z a j ą c y c h
1. Testy zasłaniania
7
Rysunek 4. Program Test zasłaniania - scena z widocznymi krawędziami
brył ograniczających
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 ;
//
u s u n i ę c i e
d e f i n i c j i
makr
n e a r
i
f a r
#i f d e f
n e a r
#undef
n e a r
#e n d i f
#i f d e f
f a r
#undef
f a r
#e n d i f
//
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 ;
1. Testy zasłaniania
8
const GLdouble
n e a r = 3 . 0 ;
const GLdouble
f a r = 7 . 0 ;
//
k ą t y
o b r o t u
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 ;
//
w ł ą c z e n i e / w y ł ą c z e n i e
t e s t u
z a s ł a n i a n i a
bool
o c c l u s i o n t e s t = true ;
//
w ł ą c z e n i e / w y ł ą c z e n i e
r y s o w a n i a
b r y ł y
o g r a n i c z a j ą c e j
bool
o c c l u s i o n b o x = f a l s e ;
//
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 e n i a
GLuint SPHERE 0 , SPHERE 1 ,WALL, CUBE 0 , CUBE 1 ;
//
l i c z n i k
ramek
( FPS )
i n t
f r a m e s = 0 ;
//
l i c z n i k
c z a s u
long
s t a r t t i m e = 0 ;
//
t a b l i c a
z n a k ó w
z e
w a r t o ś c i ą
FPS
char
t i m e s t r i n g
[ 1 0 0 ] = ”FPS : ” ;
//
f u n k c j a
r y s u j ą c a
n a p i s w wybranym
m i e j s c u
//
( w e r s j a
k o r z y s t a j ą c a
z
f u n k c j i
g l W i n d o w P o s 2 i )
void
D r a w S t r i n g
( GLint x ,
GLint y ,
char ∗ s t r i n g )
{
//
p o ł o ż e n i e
n a p i s u
g l W i n d o w P o s 2 i
( x , y ) ;
//
w y ś w i e t l e n i e
n a p i s u
i n t
l e n = s t r l e n
( s t r i n g ) ;
f o r
( i n t
i = 0 ;
i < l e n ;
i ++)
g l u t B i t m a p C h a r a c t e r
( GLUT BITMAP 9 BY 15 , s t r i n g
[ i ] ) ;
}
//
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
( )
{
//
l i c z n i k
c z a s u
i f
( ! f r a m e s ++)
s t a r t t i m e = c l o c k
( ) ;
//
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
i
b u f o r a
g ł ę b o k o ś c i
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
( ) ;
//
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 , 0 . 0 , − ( n e a r+f a r ) / 2 ) ;
//
o b r o t y
o b i e k t u
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 ) ;
1. Testy zasłaniania
9
//
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
ź r ó d ł a
ś w i a t ł a
GL LIGHT0
g l E n a b l e
( GL LIGHT0 ) ;
//
w ł ą c z e n i e
ś l e d z e n i a
k o l o r ó w
g l E n a b l e
(GL COLOR MATERIAL ) ;
//
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 ) ;
//
n a r y s o w n a i e
e l e m e n t ó w
s c e n y
n i e
o b j ę t y c h
t e s t e m
z a s ł a n i a n i a
g l C a l l L i s t
(WALL) ;
//
t e s t
z a s ł a n i a n i a
w ł ą c z o n y
i f
( o c c l u s i o n t e s t == true )
{
//
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 y ł ą c z e n i e
ź r ó d ł a
ś w i a t ł a
GL LIGHT0
g l D i s a b l e
( GL LIGHT0 ) ;
//
w y ł ą c z e n i e
ś l e d z e n i a
k o l o r ó w
g l D i s a b l e
(GL COLOR MATERIAL ) ;
//
w y ł ą 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 D i s a b l e
(GL NORMALIZE ) ;
//
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 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 ) ;
//
g e n e r o w a n i e
i d e n t y f i k a t o r ó w
o b i e k t ó w
a n a l i z y
p r z e s ł o n i ę ć
GLuint
q u e r y i d
[ 2 ] ;
g l G e n Q u e r i e s
( 2 , q u e r y i d ) ;
//
a n a l i z a
p r z e s ł a n i a n i a
p i e r w s z e j
k u l i
g l B e g i n Q u e r y
( GL SAMPLES PASSED , q u e r y i d [ 0 ] ) ;
g l C a l l L i s t
( CUBE 0 ) ;
glEndQuery
( GL SAMPLES PASSED ) ;
//
a n a l i z a
p r z e s ł a n i a n i a
d r u g i e j
k u l i
g l B e g i n Q u e r y
( GL SAMPLES PASSED , q u e r y i d [ 1 ] ) ;
g l C a l l L i s t
( CUBE 1 ) ;
glEndQuery
( GL SAMPLES PASSED ) ;
//
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
( ) ;
//
s p r a w d z e n i e
c z y
d o s t ę p n e
s ą
w y n i k i
a n a l i z y
p r z e s ł a n i a n i a
p i e r w s z e j
k u l i
GLint
a v a i l a b l e ;
do
{
g l G e t Q u e r y O b j e c t i v
( q u e r y i d [ 0 ] , GL QUERY RESULT AVAILABLE,& a v a i l a b l e ) ;
}
while
( ! a v a i l a b l e ) ;
//
s p r a w d z e n i e
c z y
d o s t ę p n e
s ą
w y n i k i
a n a l i z y
p r z e s ł a n i a n i a
d r u g i e j
k u l i
do
{
g l G e t Q u e r y O b j e c t i v
( q u e r y i d [ 1 ] , GL QUERY RESULT AVAILABLE,& a v a i l a b l e ) ;
}
while
( ! a v a i l a b l e ) ;
//
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 ) ;
//
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 ) ;
1. Testy zasłaniania
10
//
w ł ą c z e n i e
ź r ó d ł a
ś w i a t ł a
GL LIGHT0
g l E n a b l e
( GL LIGHT0 ) ;
//
w ł ą c z e n i e
ś l e d z e n i a
k o l o r ó w
g l E n a b l e
(GL COLOR MATERIAL ) ;
//
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 ) ;
//
p o b r a n i e
w y n i k u
a n a l i z y
p r z e s ł a n i a n i a
p i e r w s z e j
k u l i
GLint
r e s u l t ;
g l G e t Q u e r y O b j e c t i v
( q u e r y i d [ 0 ] , GL QUERY RESULT,& r e s u l t ) ;
// w p r z y p a d k u
w i d o c z n o ś c i
n a r y s o w a n i e
p i e r w s z e j
k u l i
i f
( r e s u l t )
g l C a l l L i s t
( SPHERE 0 ) ;
//
p o b r a n i e
w y n i k u
a n a l i z y
p r z e s ł a n i a n i a
d r u g i e j
k u l i
g l G e t Q u e r y O b j e c t i v
( q u e r y i d [ 1 ] , GL QUERY RESULT,& r e s u l t ) ;
// w p r z y p a d k u
w i d o c z n o ś c i
n a r y s o w a n i e
d r u g i e j
k u l i
i f
( r e s u l t )
g l C a l l L i s t
( SPHERE 1 ) ;
//
u s u n i ę c i e
o b i e k t ó w
a n a l i z y
p r z e s ł o n i ę ć
g l D e l e t e Q u e r i e s
( 2 , q u e r y i d ) ;
}
//
t e s t
z a s ł a n i a n i a
w y ł ą c z o n y
e l s e
{
//
n a r y s o w a n i e
p i e r w s z e j
i
d r u g i e j
k u l i
g l C a l l L i s t
( SPHERE 0 ) ;
g l C a l l L i s t
( SPHERE 1 ) ;
}
//
r y s o w a n i e
b r y ł
o g r a n i c z a j ą c y c h
i f
( o c c l u s i o n b o x == true )
{
g l C o l o r 3 f v
( B l a c k ) ;
g l P u s h M a t r i x
( ) ;
g l T r a n s l a t e f
( 0 . 0 , 0 . 0 , 1 . 2 ) ;
g l u t W i r e C u b e
( 1 . 5 ) ;
g l T r a n s l a t e f
( 0 . 0 , 0 . 0 , − 2 . 4 ) ;
g l u t W i r e C u b e
( 1 . 5 ) ;
g l P o p M a t r i x
( ) ;
}
//
k o m u n i k a t
o
i l o ś c i
ramek
r y s o w a n y c h
na
s e k u n d ę
( FPS )
g l C o l o r 3 f v
( B l a c k ) ;
i f
( f r a m e s == 1 0 0 )
{
f r a m e s = 0 ;
s p r i n t f
( t i m e s t r i n g , ”FPS : %i ” , ( i n t ) ( 1 0 0 ∗ CLOCKS PER SEC / ( f l o a t ) ( c l o c k
() − s t a r t t i m e ) ) ) ;
}
//
n a r y s o w a n i e
n a p i s u
D r a w S t r i n g
( 1 , 1 , t i m e s t r i n g ) ;
//
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
( ) ;
1. Testy zasłaniania
11
//
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 )
{
switch
( v a l u e )
{
//
w ł ą c z e n i e / w y ł ą c z e n i e
t e s t u
z a s ł a n i a n i a
c a s e OCCLUSION TEST :
o c c l u s i o n t e s t = ! o c c l u s i o n t e s t ;
D i s p l a y S c e n e
( ) ;
break ;
//
w ł ą c z e n i e / w y ł ą c z e n i e
r y s o w a n i a
b r y ł
o g r a n i c z a j ą c y c h
c a s e OCCLUSION BOX :
o c c l u s i o n b o x = ! o c c l u s i o n b o x ;
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 ;
1. Testy zasłaniania
12
//
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
SPHERE 0 = 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 i e r w s z a
k u l a
g l N e w L i s t
( SPHERE 0 , GL COMPILE ) ;
g l C o l o r 3 f v
( B l u e ) ;
g l P u s h M a t r i x
( ) ;
g l T r a n s l a t e f
( 0 . 0 , 0 . 0 , 1 . 2 ) ;
g l u t S o l i d S p h e r e
( 0 . 7 , 2 0 0 , 2 0 0 ) ;
g l P o p M a t r i x
( ) ;
//
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 e 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
SPHERE 1 = 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 − d r u g a
k u l a
g l N e w L i s t
( SPHERE 1 , GL COMPILE ) ;
g l C o l o r 3 f v
( Lime ) ;
g l P u s h M a t r i x
( ) ;
g l T r a n s l a t e f
( 0 . 0 , 0 . 0 , − 1 . 2 ) ;
g l u t S o l i d S p h e r e
( 0 . 7 , 2 0 0 , 2 0 0 ) ;
g l P o p M a t r i x
( ) ;
//
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 e 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
t r z e c i e j
l i s t y
w y ś w i e t l a n i a
WALL = g l G e n L i s t s
( 1 ) ;
//
t r z e c i a
l i s t a
w y ś w i e t l a n i a − murek
g l N e w L i s t
(WALL, GL COMPILE ) ;
g l C o l o r 3 f v
( Red ) ;
g l P u s h M a t r i x
( ) ;
g l S c a l e f
( 1 . 0 , 1 . 0 , 0 . 1 ) ;
g l u t S o l i d C u b e
( 2 . 8 ) ;
g l P o p M a t r i x
( ) ;
//
k o n i e c
t r z e c i e j
l i s t y
w y ś w i e t l e 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
c z w a r t e j
l i s t y
w y ś w i e t l a n i a
CUBE 0 = g l G e n L i s t s
( 1 ) ;
//
c z w a r t a
l i s t a
w y ś w i e t l a n i a − s z e ś c i a n
o t a c z a j ą c y
p i e r w s z ą
k u l ę
g l N e w L i s t
( CUBE 0 , GL COMPILE ) ;
g l P u s h M a t r i x
( ) ;
g l T r a n s l a t e f
( 0 . 0 , 0 . 0 , 1 . 2 ) ;
g l u t S o l i d C u b e
( 1 . 5 ) ;
g l P o p M a t r i x
( ) ;
//
k o n i e c
c z w a r t e j
l i s t y
w y ś w i e t l e 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
p i ą t e j
l i s t y
w y ś w i e t l a n i a
CUBE 1 = g l G e n L i s t s
( 1 ) ;
//
p i ą t a
l i s t a
w y ś w i e t l a n i a − s z e ś c i a n
o t a c z a j ą c y
d r u g ą
k u l ę
g l N e w L i s t
( CUBE 1 , GL COMPILE ) ;
g l P u s h M a t r i x
( ) ;
g l T r a n s l a t e f
( 0 . 0 , 0 . 0 , − 1 . 2 ) ;
g l u t S o l i d C u b e
( 1 . 5 ) ;
g l P o p M a t r i x
( ) ;
//
k o n i e c
p i ą t e j
l i s t y
w y ś w i e t l e n i a
g l E n d L i s t
( ) ;
}
1. Testy zasłaniania
13
//
s p r a w d z e n i e
i
p r z y g o t o w a n i e
o b s ł u g i
w y b r a n y c h
r o z s z e r z e ń
void
E x t e n s i o n S e t u p
( )
{
//
p o b r a n i e
numeru
w e r s j i
b i b l i o t e k 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 ) ;
//
o d c z y t
w e r s j i
OpenGL
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
( 0 ) ;
}
//
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 . 4
i f
( m a j o r > 1
| |
m i n o r >= 4 )
{
//
p o b r a n i e
w s k a ź n i k a
w y b r a n e j
f u n k c j i
OpenGL
1 . 4
g l W i n d o w P o s 2 i = (PFNGLWINDOWPOS2IPROC) w g l G e t P r o c A d d r e s s
( ” g l W i n d o w P o s 2 i ” ) ;
}
e l s e
//
s p r a w d z e n i e
c z y
j e s t
o b s ł u g i w a n e
r o z s z e r z e n i e
A R B w i n d o w p o s
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 ARB window pos ” ) )
{
//
p o b r a n i e
w s k a ź n i k a
w y b r a n e j
f u n k c j i
r o z s z e r z e n i a
A R B w i n d o w p o s
g l W i n d o w P o s 2 i = (PFNGLWINDOWPOS2IPROC) w g l G e t P r o c A d d r e s s
( ” glWindowPos2iARB ” ) ;
}
e l s e
{
p r i n t f
( ” Brak
r o z s z e r z e n i a
ARB window pos ! \ n ” ) ;
e x i t
( 0 ) ;
}
//
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 . 5
i f
( m a j o r > 1
| |
m i n o r >= 5 )
{
//
p o b r a n i e
w s k a ź n i k a
w y b r a n y c h
f u n k c j i
OpenGL
1 . 5
g l G e n Q u e r i e s = (PFNGLGENQUERIESPROC) w g l G e t P r o c A d d r e s s
( ” g l G e n Q u e r i e s ” ) ;
g l B e g i n Q u e r y = (PFNGLBEGINQUERYPROC) w g l G e t P r o c A d d r e s s
( ” g l B e g i n Q u e r y ” ) ;
glEndQuery = (PFNGLENDQUERYPROC) w g l G e t P r o c A d d r e s s
( ” glEndQuery ” ) ;
g l G e t Q u e r y O b j e c t i v = (PFNGLGETQUERYOBJECTIVPROC)
w g l G e t P r o c A d d r e s s
( ” g l G e t Q u e r y O b j e c t i v ” ) ;
g l D e l e t e Q u e r i e s = (PFNGLDELETEQUERIESPROC)
w g l G e t P r o c A d d r e s s
( ” g l D e l e t e Q u e r i e s ” ) ;
}
e l s e
//
s p r a w d z e n i e
c z y
j e s t
o b s ł u g i w a n e
r o z s z e r z e n i e
A R B o c c l u s i o n q u e r y
i f
( g l u t E x t e n s i o n S u p p o r t e d
( ” G L A R B o c c l u s i o n q u e r y ” ) )
{
//
p o b r a n i e
w s k a ź n i k i
w y b r a n y c h
f u n k c j i
r o z s z e r z e n i a
A R B o c c l u s i o n q u e r y
g l G e n Q u e r i e s = (PFNGLGENQUERIESPROC) w g l G e t P r o c A d d r e s s
( ” glGenQueriesARB ” ) ;
g l B e g i n Q u e r y = (PFNGLBEGINQUERYPROC) w g l G e t P r o c A d d r e s s
( ” glBeginQueryARB ” ) ;
glEndQuery = (PFNGLENDQUERYPROC) w g l G e t P r o c A d d r e s s
( ” glEndQueryARB ” ) ;
g l G e t Q u e r y O b j e c t i v = (PFNGLGETQUERYOBJECTIVPROC)
w g l G e t P r o c A d d r e s s
( ” g l G e t Q u e r y O b j e c t i v A R B ” ) ;
g l D e l e t e Q u e r i e s = (PFNGLDELETEQUERIESPROC)
w g l G e t P r o c A d d r e s s
( ” g l D e l e t e Q u e r i e s A R B ” ) ;
}
e l s e
{
p r i n t f
( ” Brak
r o z s z e r z e n i a
ARB window pos ! \ n ” ) ;
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 | GLUT DEPTH ) ;
1. Testy zasłaniania
14
//
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
( ” T e s t
z a s ł a n i a n i a ” ) ;
#e l s e
g l u t C r e a t e W i n d o w
( ” T e s t
z a s l a n i a n i a ” ) ;
#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 ) ;
//
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
( ” T e s t
z a s ł a n i a n i a
w ł ą c z / w y ł ą c z ” ,OCCLUSION TEST ) ;
glutAddMenuEntry
( ” Rysowania
b r y ł
o g r a n i c z a j ą c y c h
w ł ą c z / w y ł ą c z ” ,OCCLUSION BOX ) ;
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
( ” T e s t
z a s l a n i a n i a
w l a c z / w y l a c z ” ,OCCLUSION TEST ) ;
glutAddMenuEntry
( ” Rysowania
b r y l y
o g r a n i c z a j a c y c h
w l a c z / w y l a c z ” ,OCCLUSION BOX ) ;
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 ) ;
//
s p r a w d z e n i e
i
p r z y g o t o w a n i e
o b s ł u g i
w y b r a n y c h
r o z s z e r z e ń
E x t e n s i o n S e t u p
( ) ;
//
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
( ) ;
//
f u n k c j a
b e z c z y n n o ś c i
g l u t I d l e F u n c
( D i s p l a y S c e n e ) ;
//
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
15
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
[9] Mark J. Kilgard: All About OpenGL Extensions,
resources/features/OGLextensions/
[10] Jon Leech: How to Create OpenGL Extensions,
projects/ogl-sample/registry/doc/rules.html
[11] Silicon Graphics, Inc: OpenGL
R
Extension Registry,