Janusz Ganczarski
OpenGL
Systemy cząstek
Spis treści
Spis treści . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1
1. Systemy cząstek . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1
Rozszerzona geometria punktów . . . . . . . . . . . . . . . . . . . .
1
. . . . . . . . . . . . . . . . . . . . . . . . . . . .
2
Program przykładowy . . . . . . . . . . . . . . . . . . . . . . . . . .
3
Plik snieg.cpp . . . . . . . . . . . . . . . . . . . . . . . . . .
5
Literatura . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
16
1. Systemy cząstek
Systemy cząstek (ang. particle systems) wykorzystywane są głównie do
uzyskiwania różnorodnych efektów atmosferycznych, takich jak deszcz, śnieg
lub mgła. Pomijając kwestie fizyczne, systemy cząstek można zbudować
w oparciu o punkty, odcinki lub czworokąty pokryte teksturą. Możliwości
biblioteki OpenGL w tym zakresie rozszerzano dwukrotnie. W wersji 1.4
dodano obsługę rozszerzonej geometrii punktów, a w wersji 2.0 wprowadzo-
no sprajty punktowe (ang. point sprite).
1.1. Rozszerzona geometria punktów
Punkty opisywaliśmy już dwukrotnie. Jednak z punktu widzenia sys-
temu cząstek punkty w bibliotece OpenGL mają jedną zasadniczą wadę.
Ich wielkość nie jest w żaden sposób uzależniona od położenia w prze-
strzeni 3D, a w szczególności od odległości punktu od obserwatora. Tę wa-
dę usunięto w wersji 1.4 biblioteki OpenGL, a wcześniej w rozszerzeniach
ARB point parameters, EXT point parameters i SGIS point parameters.
Kontrolę nad rozszerzoną geometrią punktów umożliwiają funkcje z gru-
py glPointParameter:
void glPointParameterf (GLenum pname, GLfloat param)
void glPointParameterx (GLenum pname, GLfixed param)
void glPointParameterfv (GLenum pname, const GLfloat *params)
void glPointParameterxv (GLenum pname, const GLfixed *params)
gdzie pname określa rodzaj definiowanego parametru i może przyjąć jedną
z poniższych wartości:
— GL POINT SIZE MIN - minimalna wielkość punktu po przekształceniach
geometrycznych; wartość początkowa 0,
— GL POINT SIZE MAX - maksymalna wielkość punktu po przekształceniach
geometrycznych; wartość początkowa jest maksymalną wielkością punk-
tu z aliasingiem i antyaliasingiem obsługiwaną przez daną implementację
OpenGL,
— GL POINT FADE THRESHOLD SIZE - wartość progowa używana przy włą-
czonym wielopróbkowaniu do zmiany wielkości punktu oraz zmiany skła-
dowej alfa koloru punktu; wartość początkowa 1,
— GL POINT DISTANCE ATTENUATION - współczynniki a, b i c równania okre-
ślającego rozmiar punktu po przekształceniach geometrycznych.
Wielkość punktu po przekształceniach geometrycznych określa równanie:
derived size = clamp
size ·
s
1
a + b · d + c · d
2
1. Systemy cząstek
2
gdzie size jest wielkością punktu określoną przy użyciu funkcji glPointSize,
d odległością punktu od obserwatora, a clamp wynikiem obcięcia wielkości
punktu do przedziału określonego stałymi GL POINT SIZE MIN i GL POINT -
SIZE MAX. Przy wartościach domyślnych współczynników równania wyno-
szących a = 1, b = 0 i c = 0, wielkość punktu jest równa wielkości określonej
funkcją glPointSize.
Jak już napisaliśmy przy włączonym wielopróbkowaniu stała GL POINT -
FADE THRESHOLD SIZE jest używana do zmiany wielkości punktu oraz zmia-
ny składowej alfa koloru punktu. Wielkość punktu określa funkcja width,
a współczynnik mnożenia składowej alfa określa funkcja fade:
width =
(
derived size
derived size ≥ threshold
threshold
derived size < threshold
f ade =
1
derived size ≥ threshold
derived size
threshold
2
derived size < threshold
1.2. Sprajty punktowe
Sprajty lub duszki punktowe (ang. point sprite) zostały wprowadzone
w wersji 2.0 biblioteki OpenGL w oparciu o rozszerzenia ARB point sprite
i NV point sprite. W uproszczeniu technika ta sprowadza się do obsługi
tekstury dwuwymiarowej opartej na pojedynczym wierzchołku - punkcie.
Pozwala to na znaczne przyspieszenie generowania grafiki, bowiem karta
graficzna przetwarza jeden zamiast typowo czterech wierzchołków.
Sprajty punktowe są domyślnie wyłączone. Ich aktywacja wymaga wywo-
łania funkcji glEnable z parametrem GL POINT SPRITE. Włączenie sprajtów
punktowych powoduje jednocześnie deaktywację antyaliasingu punktów.
Wraz z techniką sprajtów punktowych wprowadzono środowisko tekstur
GL POINT SPRITE, o którym już wspominaliśmy opisując tekstury. Środo-
wisko to dopuszcza jeden parametr pname funkcji z grupy glTexEnv, który
oznaczony jest stałą GL COORD REPLACE. Parametr ten określa czy współ-
rzędne tekstur mają być zastępowane współrzędnymi sprajtów punktowych
(wartość GL TRUE). Domyślnie jest to, podobnie jak i sprajty punktowe, wy-
łączone (wartość GL FALSE).
Ponadto rozszerzono dopuszczalne wartości parametru pname funkcji
z grupy glPointParameter o stałą GL POINT SPRITE COORD ORIGIN, któ-
ra określa czy lewy górny róg duszka ma pokrywać się z lewym górnym
rogiem tekstury (wartość GL UPPER LEFT) czy też z prawym dolnym rogiem
tekstury (wartość GL LOWER LEFT). Domyślnie OpenGL przyjmuje wartość
GL UPPER LEFT.
1. Systemy cząstek
3
1.3. Program przykładowy
Typowy system cząstek zawiera informacje o ilości cząstek, ich położeniu
i innych aspektach fizycznych. W naszym przykładowym programie system
cząstek jest maksymalnie uproszczony i całkowicie oddzielony od graficz-
nej reprezentacji cząstek. Pojedynczą cząstkę - płatek śniegu - reprezentuje
struktura SnowFlake, która zwiera informację o położeniu cząstki (pola x, y
i z) oraz pole logiczne active o jej aktywności. Płatki śniegu generowane są
losowo a szybkość ich opadania także jest losowo zmieniana. Cała ta warstwa
fizyczna systemu cząstek zaimplementowana jest w funkcji timera. Oczywi-
ście funkcja ta zapewnia także stałą szybkość opadania śniegu, ograniczoną
jedynie wydajnością karty graficznej.
Rysunek 1. Program Śnieg - klasyczne punkty
Program wyświetla śnieg korzystając z czterech metod. Pierwsza stosuje
punkty z antyaliasingiem, przy czym wielkość punktu jest prostą (liniową)
1. Systemy cząstek
4
funkcją wartości jego współrzędnej z. Komputer Autora pozwala na ren-
dering 20.000 punktów z szybkością około 10 ramek na sekundę (patrz ry-
sunek 1). Druga z zastosowanych metod korzysta z rozszerzonej geometrii
punktów i wizualnie praktycznie nie różni się od efektów uzyskanych pierw-
szą metodą (rysunek 1). Kilkukrotny jest za to przyrost prędkości renderingu
(około 65 ramek na sekundę), który dodatkowo ogranicza tempo wywołań
funkcji timera.
Druga metoda ma jeszcze jedną zaletę - umożliwia wykorzystanie tablic
wierzchołków. Nie było to możliwe przy rysowaniu klasycznych punktów,
bowiem jak pamiętamy wielkość punktu może być zmieniana tylko przed
wywołaniem funkcji glBegin z parametrem GL POINTS.
Rysunek 2. Program Śnieg - punkty z rozszerzoną geometrią
Dwie ostatnie metody stosują teksturę z rysunkiem płatka śniegu (ry-
sunek 3). Rysunek ten, a właściwie zdjęcie, pochodzi ze wspaniałej kolekcji
autorstwa Wilsona Bentley’a której niewielki fragment jest dostępny pod ad-
1. Systemy cząstek
5
resem
. Rysowane 20.000 płatków śniegu
utworzonych z pokrytych teksturą czworokątów na komputerze Autora od-
bywał się z szybkością około 46 ramek na sekundę (rysunek 4). Analogiczny
test z użyciem sprajtów punktowych pozwala na zauważalne przyspieszenie.
Scena rysowana jest z szybkością około 65 FPS (rysunek 5) i ponownie jest
to szybkość ograniczona wywołaniami funkcji timera.
Rysunek 3. Zdjęcie przykładowego płatka śniegu
Przy sprajtach punktowych program ponownie korzysta z tablic wierz-
chołków, co oczywiście jest możliwe także w przypadku tradycyjnych tek-
stur, ale wymagałoby radykalnego zwiększenia ilości informacji przechowy-
wanych przez system cząstek.
1.3.1. Plik snieg.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 i o . h>
#i n c l u d e < s t d l i b . 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 ”
#i n c l u d e
” t a r g a . 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 ;
//
w s k a ź n i k
na
f u n k c j e
g l P o i n t P a r a m e t e r f
i
g l P o i n t P a r a m e t e r f v
PFNGLPOINTPARAMETERFPROC g l P o i n t P a r a m e t e r f = NULL ;
1. Systemy cząstek
6
Rysunek 4. Program Śnieg - tekstury oparte na czworkątach
PFNGLPOINTPARAMETERFVPROC g l P o i n t P a r a m e t e r f v = NULL ;
//
s t a ł e
do
o b s ł u g i
menu
p o d r ę c z n e g o
enum
{
STD POINTS ,
//
ś n i e g − p u n k t y
GEOMETRIC POINTS,
//
ś n i e g − p u n k t y
z
r o z s z e r z o n ą
g e o m e t r i ą
TEXTURE,
//
ś n i e g − t e k s t u r a
POINT SPRITE ,
//
ś n i e g − s p r a j t y
p u n k t o w e
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 ´
r 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
1. Systemy cząstek
7
Rysunek 5. Program Śnieg - sprajty punktowe
#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 ;
const GLdouble
n e a r = 3 . 0 ;
const GLdouble
f a r = 7 . 0 ;
//
i l o ś ć
a n i m o w a n y c h
p ł a t k ó w
s n i e g u
i n t
f l a k e c o u n t = 1 0 0 0 ;
//
m a k s y m a l n a
i l o ś ć
a n i m o w a n y c h
p ł a t k ó w
ś n i e g u
const
i n t MAX FLAKE COUNT = 2 0 0 0 0 ;
//
s t r u k t u r a
z
i n f o r m a c j a m i
o
p ł a t k u
ś n i e g u
s t r u c t
SnowFlake
{
G L f l o a t x , y , z ;
bool
a c t i v e ;
} ;
1. Systemy cząstek
8
//
t a b l i c a
z e
w s z y s t k i m
p ł a t k a m i
ś n i e g u
SnowFlake
S n o w F l a k e s
[ MAX FLAKE COUNT ] ;
//
r o d z a j
g e n e r o w a n e g o
ś n i e g u
i n t
snow mode = STD POINTS ;
//
d o m y ś l n e
w s p ó ł c z y n n i k i
r ó w n a n i a
p r z e k s z t a ł c e n i a
w i e l k o ś c i
p u n k t ó w
G L f l o a t
s t d a t t e n a t i o n
[ 3 ] =
{
1 . 0 ,
0 . 0 ,
0 . 0
} ;
//
w s p ó ł c z y n n i k i
r ó w n a n i a
p r z e k s z t a ł c e n i a
w i e l k o ś c i
p u n k t ó w
G L f l o a t
q u a d a t t e n a t i o n
[ 3 ] =
{
0 . 0 ,
0 . 0 ,
0 . 2
} ;
//
i d e n t y f i k a t o r
t e k s t u r y
GLuint SNOW FLAKE ;
//
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
( Dark Blue [ 0 ] , DarkBlue [ 1 ] , DarkBlue [ 2 ] , 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
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 ) ;
//
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 ) ;
//
ś n i e g − p u n k t y
1. Systemy cząstek
9
i f
( snow mode == STD POINTS )
{
//
w ł ą c z e n i e
a n t y a l i a s i n g u
p u n k t ó w
g l E n a b l e
(GL POINT SMOOTH ) ;
//
k o l o r
p u n k t ó w
g l C o l o r 4 f v
( Snow ) ;
//
n a r y s o w a n i e
w s z y s t i c h
p ł a t k ó w
ś n i e g u
f o r
( i n t
i = 0 ;
i < f l a k e c o u n t ;
i ++)
{
//
r o z m i a r
p u n k t ó w
u z a l e ż n i o n y
w
l i n i o w y
s p o s ó b
//
od
w i e l k o ś c i
w s p ó ł r z e d n e j
z
g l P o i n t S i z e
(3+ S n o w F l a k e s
[ i ] . z ) ;
g l B e g i n
( GL POINTS ) ;
g l V e r t e x 3 f
( S n o w F l a k e s
[ i ] . x , S n o w F l a k e s
[ i ] . y , S n o w F l a k e s
[ i ] . z ) ;
g l E n d
( ) ;
}
//
w y ł ą c z e n i e
a n t y a l i a s i n g u
p u n k t ó w
g l D i s a b l e
(GL POINT SMOOTH ) ;
}
//
ś n i e g − p u n k t y
z
r o z s z e r z o n ą
g e o m e t r i ą
i f
( snow mode == GEOMETRIC POINTS)
{
//
m i n i m a l n a
w i e l k o ś ć
p u n k t u
po
p r z e k s z t a ł c e n i a c h
g e o m e t r y c z n y c h
g l P o i n t P a r a m e t e r f
( GL POINT SIZE MIN , 1 . 0 ) ;
//
m a k s y m a l n a
w i e l k o ś ć
p u n k t u
po
p r z e k s z t a ł c e n i a c h
g e o m e t r y c z n y c h
g l P o i n t P a r a m e t e r f
( GL POINT SIZE MAX , 1 0 . 0 ) ;
//
w s p ó ł c z y n n i k i
r ó w n a n i a
p r z e k s z t a ł c e n i a
w i e l k o ś c i
p u n k t ó w
g l P o i n t P a r a m e t e r f v
(GL POINT DISTANCE ATTENUATION , q u a d a t t e n a t i o n ) ;
//
b a z o w a
w i e l k o ś ć
p u n k t u
g l P o i n t S i z e
( 1 0 . 0 ) ;
//
k o l o r
p u n k t ó w
g l C o l o r 4 f v
( Snow ) ;
//
w ł ą c z e n i e
a n t y a l i a s i n g u
p u n k t ó w
g l E n a b l e
(GL POINT SMOOTH ) ;
//
w ł ą c z e n i e
t a b l i c
w i e r z c h o ł k ó w
g l E n a b l e C l i e n t S t a t e
(GL VERTEX ARRAY ) ;
//
z d e f i n i o w a n i e
d a n y c h
t a b l i c
w i e r z c h o ł k ó w
g l V e r t e x P o i n t e r
( 3 , GL FLOAT , s i z e o f
( SnowFlake ) , S n o w F l a k e s ) ;
//
n a r y s o w a n i e
d a n y c h
z a w a r t y c h w
t a b l i c a c h
g l D r a w A r r a y s
( GL POINTS , 0 , f l a k e c o u n t ) ;
//
w y ł ą c z e n i e
t a b l i c
w i e r z c h o ł k ó w
g l D i s a b l e C l i e n t S t a t e
(GL VERTEX ARRAY ) ;
//
d o m y ś l n e
w s p ó ł c z y n n i k i
r ó w n a n i a
p r z e k s z t a ł c e n i a
w i e l k o ś c i
p u n k t ó w
g l P o i n t P a r a m e t e r f v
(GL POINT DISTANCE ATTENUATION , s t d a t t e n a t i o n ) ;
//
w y ł ą c z e n i e
a n t y a l i a s i n g u
p u n k t ó w
g l D i s a b l e
(GL POINT SMOOTH ) ;
}
//
ś n i e g − t e k s t u r a
i f
( snow mode == TEXTURE)
{
//
w ł ą c z e n i e
t e k s t u r
2D
g l E n a b l e
(GL TEXTURE 2D ) ;
//
d o w i ą z a n i e
s t a n u
t e k s t u r y
g l B i n d T e x t u r e
(GL TEXTURE 2D , SNOW FLAKE ) ;
//
w ł ą c z e n i e
t e s t o w a n i a
k a n a ł u
a l f a
g l E n a b l e
(GL ALPHA TEST ) ;
g l A l p h a F u n c
(GL GREATER, 0 . 2 ) ;
//
u s t a w i e n i e
p a r a m e t ó w
ś r o d o w i s k a
t e k s t u r
g l T e x E n v f
(GL TEXTURE ENV, GL TEXTURE ENV MODE, GL REPLACE ) ;
//
c z w o r o k ą t y
1. Systemy cząstek
10
g l B e g i n
(GL QUADS ) ;
//
n a r y s o w a n i e
w s z y s t i c h
p ł a t k ó w
ś n i e g u
f o r
( i n t
i = 0 ;
i < f l a k e c o u n t ;
i ++)
{
g l T e x C o o r d 2 f
( 1 . 0 , 1 . 0 ) ;
g l V e r t e x 3 f
( S n o w F l a k e s
[ i ] . x + 0 . 0 4 , S n o w F l a k e s
[ i ] . y + 0 . 0 4 , S n o w F l a k e s
[ i ] . z ) ;
g l T e x C o o r d 2 f
( 0 . 0 , 1 . 0 ) ;
g l V e r t e x 3 f
( S n o w F l a k e s
[ i ] . x − 0 . 0 4 , S n o w F l a k e s
[ i ] . y + 0 . 0 4 , S n o w F l a k e s
[ i ] . z ) ;
g l T e x C o o r d 2 f
( 0 . 0 , 0 . 0 ) ;
g l V e r t e x 3 f
( S n o w F l a k e s
[ i ] . x − 0 . 0 4 , S n o w F l a k e s
[ i ] . y − 0 . 0 4 , S n o w F l a k e s
[ i ] . z ) ;
g l T e x C o o r d 2 f
( 1 . 0 , 0 . 0 ) ;
g l V e r t e x 3 f
( S n o w F l a k e s
[ i ] . x + 0 . 0 4 , S n o w F l a k e s
[ i ] . y − 0 . 0 4 , S n o w F l a k e s
[ i ] . z ) ;
}
g l E n d
( ) ;
//
w y ł ą c z e n i e
t e s t o w a n i a
k a n a ł u
a l f a
g l D i s a b l e
(GL ALPHA TEST ) ;
//
w y ł ą c z e n i e
t e k s t u r
2D
g l D i s a b l e
(GL TEXTURE 2D ) ;
}
//
ś n i e g − s p r a j t y
p u n k t o w e
i f
( snow mode == POINT SPRITE )
{
//
m i n i m a l n a
w i e l k o ś ć
p u n k t u
po
p r z e k s z t a ł c e n i a c h
g e o m e t r y c z n y c h
g l P o i n t P a r a m e t e r f
( GL POINT SIZE MIN , 1 . 0 ) ;
//
m a k s y m a l n a
w i e l k o ś ć
p u n k t u
po
p r z e k s z t a ł c e n i a c h
g e o m e t r y c z n y c h
g l P o i n t P a r a m e t e r f
( GL POINT SIZE MAX , 1 0 . 0 ) ;
//
w s p ó ł c z y n n i k i
r ó w n a n i a
p r z e k s z t a ł c e n i a
w i e l k o ś c i
p u n k t ó w
g l P o i n t P a r a m e t e r f v
(GL POINT DISTANCE ATTENUATION , q u a d a t t e n a t i o n ) ;
//
b a z o w a
w i e l k o ś ć
p u n k t u
g l P o i n t S i z e
( 1 5 . 0 ) ;
//
w ł ą c z e n i e
t e k s t u r o w a n i a
2D
g l E n a b l e
(GL TEXTURE 2D ) ;
//
d o w i ą z a n i e
s t a n u
t e k s t u r y
g l B i n d T e x t u r e
(GL TEXTURE 2D , SNOW FLAKE ) ;
//
w ł ą c z e n i e
t e s t o w a n i a
k a n a ł u
a l f a
g l E n a b l e
(GL ALPHA TEST ) ;
g l A l p h a F u n c
(GL GREATER, 0 . 2 ) ;
//
u s t a w i e n i e
p a r a m e t ó w
ś r o d o w i s k a
t e k s t u r
g l T e x E n v f
(GL TEXTURE ENV, GL TEXTURE ENV MODE, GL REPLACE ) ;
//
u s t a w i e n i e
p a r a m e t r ó w
ś r o d o w s k a
s p r a j t ó w
p u n k t o w y c h
g l T e x E n v f
( GL POINT SPRITE , GL COORD REPLACE, GL TRUE ) ;
//
w ł ą c z e n i e
s p r a j t ó w
p u n k t o w y c h
g l E n a b l e
( GL POINT SPRITE ) ;
//
w ł ą c z e n i e
t a b l i c
w i e r z c h o ł k ó w
g l E n a b l e C l i e n t S t a t e
(GL VERTEX ARRAY ) ;
//
z d e f i n i o w a n i e
d a n y c h
t a b l i c
w i e r z c h o ł k ó w
g l V e r t e x P o i n t e r
( 3 , GL FLOAT , s i z e o f
( SnowFlake ) , S n o w F l a k e s ) ;
//
n a r y s o w a n i e
d a n y c h
z a w a r t y c h w
t a b l i c a c h
g l D r a w A r r a y s
( GL POINTS , 0 , f l a k e c o u n t ) ;
//
w y ł ą c z e n i e
t a b l i c
w i e r z c h o ł k ó w
g l D i s a b l e C l i e n t S t a t e
(GL VERTEX ARRAY ) ;
//
d o m y ś l n e
w s p ó ł c z y n n i k i
r ó w n a n i a
p r z e k s z t a ł c e n i a
w i e l k o ś c i
p u n k t ó w
g l P o i n t P a r a m e t e r f v
(GL POINT DISTANCE ATTENUATION , s t d a t t e n a t i o n ) ;
//
w y ł ą c z e n i e
s p r a j t ó w
p u n k t o w y c h
g l D i s a b l e
( GL POINT SPRITE ) ;
//
w y ł ą c z e n i e
t e s t o w a n i a
k a n a ł u
a l f a
g l D i s a b l e
(GL ALPHA TEST ) ;
//
w y ł ą c z e n i e
t e k s t u r o w a n i a
2D
g l D i s a b l e
(GL TEXTURE 2D ) ;
1. Systemy cząstek
11
}
//
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 ) ;
//
i l o ś ć
w y ś w i e t l a n y c h
p ł a t k ó w
ś n i e g u
g l C o l o r 3 f v
( Y e l l o w ) ;
char
s t r
[ 1 0 0 ] ;
s p r i n t f
( s t r , ”PARTICLES COUNT = %i ” , f l a k e c o u n t ) ;
D r a w S t r i n g
( 2 , 2 , s t r ) ;
//
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 )
i f
( f r a m e s == 5 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 ) ( 5 0 ∗ CLOCKS PER SEC / ( f l o a t ) ( c l o c k
() − s t a r t t i m e ) ) ) ;
}
D r a w S t r i n g
( 2 , 1 6 , 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 ( ) ;
}
//
f u n k c j a
t i m e r a
void Timer
( i n t
v a l u e )
{
//
o k r e ś l e n i e
z a r o d k a
d l a
c i ą g u
l i c z b
p s e u d o l o s o w y c h
s r a n d
( t i m e
(NULL ) ) ;
//
a k t u a l i z a c j a
p a r a m e t r ó w
p ł a t k ó w
ś n i e g u
f o r
( i n t
i = 0 ;
i < f l a k e c o u n t ;
i ++)
//
g e n e r o w a n i e
n o w y c h
p ł a t k ó w
ś n i e g u
i f
( S n o w F l a k e s
[ i ] . a c t i v e == f a l s e )
{
S n o w F l a k e s
[ i ] . x = 2 ∗ ( r a n d ( )
/
( f l o a t )RAND MAX)
∗ ( r i g h t − l e f t ) − 2∗ r i g h t ;
S n o w F l a k e s
[ i ] . y = ( r a n d ( )
/
( f l o a t )RAND MAX)
∗ ( t o p − bottom ) + t o p ;
S n o w F l a k e s
[ i ] . z = ( r a n d ( )
/
( f l o a t )RAND MAX)
∗ ( f a r − n e a r ) ;
S n o w F l a k e s
[ i ] . a c t i v e = true ;
}
//
r e a l i z a c j a
o p a d a n i a
p ł a t k ó w
ś n i e g u
i
i c h
u s u w a n i a
e l s e
{
S n o w F l a k e s
[ i ] . y −= 0 . 0 0 5 + r a n d ( )
/
( f l o a t )RAND MAX/ 2 0 0 ;
S n o w F l a k e s
[ i ] . x += 0 . 0 0 1 − r a n d ( )
/
( f l o a t )RAND MAX/ 2 0 0 ;
S n o w F l a k e s
[ i ] . z += 0 . 0 0 1 − r a n d ( )
/
( f l o a t )RAND MAX/ 2 0 0 ;
i f
( S n o w F l a k e s
[ i ] . y < bottom )
S n o w F l a k e s
[ i ] . a c t i v e = f a l s 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
( 1 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 )
1. Systemy cząstek
12
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
k l a w i a t u r y
void Keyboard
( unsigned char key ,
i n t x ,
i n t
y )
{
switch
( k e y )
{
//
k l a w i s z +
c a s e
’+ ’ :
i f
( f l a k e c o u n t < MAX FLAKE COUNT)
f l a k e c o u n t += 1 0 0 0 ;
break ;
//
k l a w i s z −
c a s e
’− ’ :
i f
( f l a k e c o u n t > 1 0 0 0 )
f l a k e c o u n t −= 1 0 0 0 ;
//
d e a k t y w a c j a
u s u n i ę t y c h
p ł a t k ó w
f o r
( i n t
i = f l a k e c o u n t ;
i < 1 0 0 0 ;
i ++)
S n o w F l a k e s
[ i ] . a c t i v e = f a l s e ;
break ;
}
//
n a r y s o w a n i e
s c e n y
D i s p l a y S c e n e
( ) ;
}
//
o b s ł u g a
menu
p o d r ę c z n e g o
void Menu ( i n t
v a l u e )
{
switch
( v a l u e )
{
//
r o d z a j
ś n i e g u
c a s e STD POINTS :
c a s e GEOMETRIC POINTS :
c a s e TEXTURE:
c a s e POINT SPRITE :
snow mode = 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 T e x t u r e s
( )
{
//
z m i e n n e
u ż y t e
p r z y
o b s ł u d z e
p l i k ó w TARGA
G L s i z e i
width ,
h e i g h t ;
1. Systemy cząstek
13
GLenum f o r m a t ,
t y p e ;
GLvoid ∗ p i x e l s ;
//
t r y b
u p a k o w a n i a
b a j t ó w
d a n y c h
t e k s t u r y
g l P i x e l S t o r e i
(GL UNPACK ALIGNMENT, 1 ) ;
//
w c z y t a n i e
t e k s t u r y
z
p ł a t k i e m
ś n i e g u
//
ź r ó d ł o :
h t t p : / / s n o w f l a k e b e n t l e y . com /
GLboolean
e r r o r = l o a d t a r g a
( ” s n o w f l a k e s . t g a ” , width , h e i g h t , f o r m a t , t y p e , p i x e l s ) ;
//
b ł ą d
o d c z y t u
p l i k u
i f
( e r r o r == GL FALSE )
{
p r i n t f
( ” Niepoprawny
o d c z y t
p l i k u
s n o w f l a k e s . t g a ” ) ;
e x i t
( 0 ) ;
}
//
u t w o r z e n i e
b u f o r a
p o m o c n i c z e g o
na
o b r a z w f o r m a c i e RGBA
unsigned char ∗ r g b a p i x e l s = new unsigned char
[ w i d t h ∗
h e i g h t
∗
4 ] ;
unsigned char ∗ r g b p i x e l s = ( unsigned char ∗ ) p i x e l s ;
//
u t w o r z e n i e
o b r a z u w f o r m a c i e RGBA
f o r
( i n t
i = 0 ;
i < w i d t h ∗
h e i g h t ;
i ++)
{
r g b a p i x e l s
[ 4 ∗ i + 0 ] = r g b p i x e l s
[ 3 ∗ i + 0 ] ;
r g b a p i x e l s
[ 4 ∗ i + 1 ] = r g b p i x e l s
[ 3 ∗ i + 1 ] ;
r g b a p i x e l s
[ 4 ∗ i + 2 ] = r g b p i x e l s
[ 3 ∗ i + 2 ] ;
//
w a r t o ś ć
s k ł ą d o w e j
a l f a
u z a l e z n i o n a
od
j a s n o ś c i
p i k s e l a
i f
( r g b p i x e l s
[ 3 ∗ i +0] + r g b p i x e l s
[ 3 ∗ i +1] + r g b p i x e l s
[ 3 ∗ i +2] < 1 0 )
r g b a p i x e l s
[ 4 ∗ i + 3 ] = 0 ;
e l s e
r g b a p i x e l s
[ 4 ∗ i + 3 ] = 2 5 5 ;
}
//
u t w o r z e n i e
i d e n t y f i k a t o r a
t e k s t u r y
g l G e n T e x t u r e s
( 1 , &SNOW FLAKE ) ;
//
d o w i ą z a n i e
s t a n u
t e k s t u r y
g l B i n d T e x t u r e
(GL TEXTURE 2D , SNOW FLAKE ) ;
//
f i l t r
p o m n i e j s z a j ą c y
g l T e x P a r a m e t e r i
(GL TEXTURE 2D , GL TEXTURE MIN FILTER , GL LINEAR MIPMAP LINEAR ) ;
//
u t w o r z e n i e
t e k s t u r y
w r a z
z
mipmapami
gluBuild2DMipmaps
(GL TEXTURE 2D , GL RGBA, width , h e i g h t , GL BGRA, t y p e , r g b a p i x e l s ) ;
//
p o r z ą d k i
d e l e t e
[ ]
( unsigned char ∗ ) p i x e l s ;
d e l e t e
[ ]
r g b a p i x e l s ;
}
//
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
1. Systemy cząstek
14
//
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 . 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 ó w
w y b r a n y c h
f u n k c j i
OpenGL
1 . 4
g l P o i n t P a r a m e t e r f =
(PFNGLPOINTPARAMETERFPROC) w g l G e t P r o c A d d r e s s
( ” g l P o i n t P a r a m e t e r f ” ) ;
g l P o i n t P a r a m e t e r f v =
(PFNGLPOINTPARAMETERFVPROC)
w g l G e t P r o c A d d r e s s
( ” g l P o i n t P a r a m e t e r f v ” ) ;
}
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 p o i n t p a r a m e t e r 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
( ” G L A R B p o i n t p a r a m e t e r s ” ) )
{
//
p o b r a n i e
w s k a ź n i k ó w
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 p o i n t p a r a m e t e r s
g l P o i n t P a r a m e t e r f =
(PFNGLPOINTPARAMETERFPROC) w g l G e t P r o c A d d r e s s
( ” g l P o i n t P a r a m e t e r f ” ) ;
g l P o i n t P a r a m e t e r f v =
(PFNGLPOINTPARAMETERFVPROC)
w g l G e t P r o c A d d r e s s
( ” g l P o i n t P a r a m e t e r f v ” ) ;
}
e l s e
{
p r i n t f
( ” Brak
r o z s z e r z e n i a
A R B p o i n t p a r a m e t e r s ! \ 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
2 . 0
OpenGL
l u b
//
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 p o i n t s p r i t e
i f
( ! ( m a j o r >= 2 ) && ! 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 p o i n t s p r i t e ” ) )
{
p r i n t f
( ” Brak
r o z s z e r z e n i a
G L A R B p o i n t s p r i t e ! \ 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 ) ;
//
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
( ” Ś n i e g ” ) ;
#e l s e
g l u t C r e a t e W i n d o w
( ” S n i e g ” ) ;
#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 ) ;
//
d o ł ą c z e n i e
f u n k c j i
o b s ł u g i
k l a w i a t u r y
g l u t K e y b o a r d F u n c
( Keyboard ) ;
//
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 ) ;
//
u t w o r z e n i e
podmenu − a s p e k t
o b r a z u
1. Systemy cząstek
15
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 ) ;
//
u t w o r z e n i e
podmenu − R o d z a j
ś n i e g u
i n t MenuSnowMode = g l u t C r e a t e M e n u
( Menu ) ;
glutAddMenuEntry
( ” Punkty ” , STD POINTS ) ;
#i f d e f WIN32
glutAddMenuEntry
( ” Punkty
z
r o z s z e r z o n ą
g e o m e t r i ą ” ,GEOMETRIC POINTS ) ;
#e l s e
glutAddMenuEntry
( ” Punkty
z
r o z s z e r z o n a
g e o m e t r i a ” ,GEOMETRIC POINTS ) ;
#e n d i f
glutAddMenuEntry
( ” T e k s t u r a ” ,TEXTURE ) ;
glutAddMenuEntry
( ” S p r a j t y
punktowe ” , POINT SPRITE ) ;
// 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
glutAddSubMenu
( ” R o d z a j
ś n i e g u ” , MenuSnowMode ) ;
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
( ” R o d z a j
s n i e g u ” , MenuSnowMode ) ;
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 j
menu
p o d r ę c z n e
g l u t A t t a c h M e n u
(GLUT RIGHT BUTTON ) ;
//
u t w o r z e n i e
t e k s t u r
G e n e r a t e T e x t u r e s
( ) ;
//
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
( ) ;
//
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
( 1 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 ;
}
Literatura
16
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,
http://www.opengl.org/registry/
[12] Gunter Born: Przeglądarka do plików TARGA w Borland Delphi. Software
Nr 3/1996, str. 36-38
[13] Truevision: TGA File Format Specification Version 2.0
[14] Krzysztof Łabanowski: Format graficzny TARGA. PCkurier Nr 23/1993, str.
135-138,