Janusz Ganczarski
OpenGL
Bufor akumulacyjny
Spis treści
Spis treści . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1
1. Bufor akumulacyjny . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1
Sterowanie buforem akumulacyjnym . . . . . . . . . . . . . . . . . .
1
Czyszczenie bufora akumulacyjnego . . . . . . . . . . . . . . . . . .
2
. . . . . . . . . . . . . . . . . . . . . . . . .
2
Plik rozmycie w ruchu.cpp . . . . . . . . . . . . . . . . . . .
4
Plik glebia ostrosci.cpp . . . . . . . . . . . . . . . . . . . . .
10
Plik filtracja obrazow.cpp . . . . . . . . . . . . . . . . . . . .
15
Literatura . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
28
1. Bufor akumulacyjny
Bufor akumulacyjny umożliwia łączenie kilku obrazów w celu uzyskania
określonego efektu końcowego. W swojej budowie bufor akumulacyjny przy-
pomina bufor koloru, przechowuje bowiem informacje o składowych RGBA
kolorów. Bufor akumulacyjny nie jest dostępny, gdy biblioteka OpenGL pra-
cuje w trybie indeksu kolorów.
Bufor akumulacyjny używany jest do uzyskiwania wielu efektów spe-
cjalnych. Najpopularniejsze z nich to rozmycie w ruchu (ang. motion blur),
głębia ostrości (ang. depth of field), antyaliasing pełnoekranowy (ang. FSAA
- Full Scene Anti Aliasing) oraz miękkie cienie (ang. soft shadows). Dwie
pierwsze z wymienionych technik przedstawimy w niniejszym odcinku kursu.
Pozostałe zostaną zaprezentowane wraz z innymi technikami antyaliasingu
i cieni.
Niestety użycie bufora akumulacyjnego do uzyskania efektów specjalnych
wiąże się najczęściej z bardzo dużą ilością dodatkowych obliczeń. Jednak naj-
większym problemem jest brak sprzętowej obsługi bufora akumulacyjnego
przez popularne procesory graficzne.
1.1. Sterowanie buforem akumulacyjnym
Działaniem bufora akumulacyjnego steruje funkcja:
void glAccum (GLenum op, GLfloat value)
której parametr op określa rodzaj operacji wykonywanej na buforze:
— GL ACCUM - dodawanie do bufora akumulacyjnego wartości bufora kolorów
przemnożonych (przeskalowanych) przez wartość parametru value:
R
a
= R
a
+ value · R
c
G
a
= G
a
+ value · G
c
B
a
= B
a
+ value · B
c
A
a
= A
a
+ value · A
c
— GL LOAD - zapisanie do bufora akumulacyjnego wartości bufora kolorów
przemnożonych (przeskalowanych) przez wartość parametru value:
R
a
= value · R
c
G
a
= value · G
c
B
a
= value · B
c
A
a
= value · A
c
1. Bufor akumulacyjny
2
— GL RETURN - kopiowanie wartości bufora akumulacyjnego przemnożonych
(przeskalowanych) przez wartość parametru value do bufora kolorów:
R
c
= value · R
a
G
c
= value · G
a
B
c
= value · B
a
A
c
= value · A
a
— GL MULT - mnożenie (skalowanie) wartości zawartych w buforze akumu-
lacyjnym przez wartość parametru value:
R
a
= value · R
a
G
a
= value · G
a
B
a
= value · B
a
A
a
= value · A
a
— GL ADD - dodawanie wartość parametru value do wartości zawartych
w buforze akumulacyjnym:
R
a
= R
a
+ value
G
a
= G
a
+ value
B
a
= B
a
+ value
A
a
= A
a
+ value
Jak Czytelnik zauważył, w powyższych równaniach (R
c
, G
c
, B
c
, A
c
) ozna-
czają składowe bufora kolorów, a (R
a
, G
a
, B
a
, A
a
) wartości bufora szablono-
wego
1.2. Czyszczenie bufora akumulacyjnego
W razie potrzeby bufor akumulacyjny może zostać wypełniony określo-
nymi wartościami składowych RGBA. Służy to tego dobrze znana funkcja
glClear wraz z parametrem GL ACCUM BUFFER BIT. Domyślnie bufor aku-
mulacyjny wypełniany jest wartościami (0, 0, 0, 0), ale funkcja:
void glClearAccum (GLfloat red, GLfloat green, GLfloat blue,
GLfloat alpha)
umożliwia zmianę tego stanu. Wartości parametrów red, green, blue i alpha
w razie potrzeby obcinane są do przedziału [−1, 1].
1.3. Programy przykładowe
Zgodnie z wcześniejszą zapowiedzią pierwszy program przykładowy (plik
rozmycie w ruchu.cpp) przedstawia efekt rozmycia w ruchu. Efekt uzyski-
wany jest poprzez odpowiednie operacje na buforze akumulacyjnym. Z wie-
lu możliwości uzyskania efektu rozmycia program przedstawia trzy metody.
1. Bufor akumulacyjny
3
Pierwsze dwie dają bardzo podobny efekt (patrz rysunki 1 i 2) i sprowadzają
się jedynie do wykonywania odpowiednich operacji na buforze akumulacyj-
nym, przy czym bufor ten czyszczony jest tylko przy rysowaniu pierwszej
ramki obrazu.
Trzeci zastosowany algorytm jest bardziej klasyczny i sprowadza się wie-
lokrotnego rysowania sceny za każdym razem przesuniętej o odpowiedni kąt.
Kolejne rysowane ramki są po skalowaniu sumowane w buforze akumulacyj-
nym. Efekt uzyskany przy 16 rysowanych ramkach przedstawia rysunek 3.
Metoda ta daje pełną kontrolę nad jakością uzyskanego efektu rozmycia
w ruchu, ale zwielokrotnienie rysowania sceny bezpośrednio wpływa na spa-
dek szybkości renderingu.
Aby udostępnić bufor akumulacyjny trzeba go dodać przy inicjalizacji
bufora ramki. W przypadku biblioteki GLUT sprowadza się to do dodania
stałej GLUT ACCUM przy wywołaniu funkcji glutInitDisplayMode.
Rysunek 1. Program Rozmycie w ruchu - pierwszy algorytm
1. Bufor akumulacyjny
4
Rysunek 2. Program Rozmycie w ruchu - drugi algorytm
1.3.1. Plik rozmycie w ruchu.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
{
MOTION BLUR 1 ,
//
p i e r w s z y
a l g o r y t m
r o z m y c i a w r u c h u
MOTION BLUR 2 ,
//
d r u g i
a l g o r y t m
r o z m y c i a w r u c h u
MOTION BLUR 3 ,
//
t r z e c i
a l g o r y t m
r o z m y c i a w r u c h u
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
1. Bufor akumulacyjny
5
Rysunek 3. Program Rozmycie w ruchu - trzeci algorytm
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
o b i e k t ó w
G L f l o a t
r o t a t e x = 2 0 . 0 ;
G L f l o a t
r o t a t e y = 2 0 . 0 ;
G L f l o a t
r o t a t e z = 2 0 . 0 ;
//
i d e n t y f i k a t o r
l i s t y
w y ś w i e t l a n i a
GLint WORLD LIST ;
//
w y b r a n y
a l g o r y t m
r o z m y c i a w r u c h u
i n t
m o t i o n b l u r = MOTION BLUR 1 ;
//
f u n k c j a
g e n e r u j ą c a
s c e n ę
3D
1. Bufor akumulacyjny
6
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
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
( ) ;
//
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 ) ;
//
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
o b i e k t ó w
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 ) ;
g l R o t a t e f
( r o t a t e z , 0 . 0 , 0 . 0 , − 1 . 0 ) ;
//
w y ś w i e t l e n i e
o b i e k t ó w
s c e n y
g l C a l l L i s t
(WORLD LIST ) ;
//
w y b ó r
a l g o r y t m u
r e a l i z u j ą c e g o
e f e k t
r o z m y c i a w r u c h u
switch
( m o t i o n b l u r )
{
//
p i e r w s z y
a l g o r y t m
r o z m y c i a w r u c h u
c a s e MOTION BLUR 1 :
//
p r z e s k a l o w a n i e
w a r t o ś c i
z n a j d u j ą c y c h
s i ę
w
b u f o r z e
a k u m u l a c y j n y m
glAccum
(GL MULT , 0 . 9 ) ;
//
d o d a n i e
p r z e s k a l o w a n y c h
w a r t o ś c i
z
b u f o r a
k o l o r ó w
do
b u f o r a
a k u m u l a c y n e g o
glAccum
(GL ACCUM, 0 . 1 ) ;
//
k o p i o w a n i e
w a r t o ś c i
z
b u f o r a
a k u m u l a c y j n e g o
do
b u f o r a
k o l o r ó w
glAccum
(GL RETURN , 1 . 0 ) ;
break ;
//
d r u g i
a l g o r y t m
r o z m y c i a w r u c h u
c a s e MOTION BLUR 2 :
//
d o d a n i e
p r z e s k a l o w a n y c h
w a r t o ś c i
z
b u f o r a
k o l o r ó w
do
b u f o r a
a k u m u l a c y n e g o
glAccum
(GL ACCUM, 0 . 1 ) ;
//
k o p i o w a n i e
w a r t o ś c i
z
b u f o r a
a k u m u l a c y j n e g o
do
b u f o r a
k o l o r ó w
glAccum
(GL RETURN , 1 . 0 ) ;
//
z a ł a d o w a n i e
p r z e s k a l o w a n y c h
w a r t o ś c i
z
b u f o r a
k o l o r ó w
do
b u f o r a
a k u m u l a c y j n e g o
glAccum
(GL LOAD , 0 . 9 ) ;
break ;
//
t r z e c i
a l g o r y t m
r o z m y c i a w r u c h u
c a s e MOTION BLUR 3 :
//
d o d a n i e
p r z e s k a l o w a n y c h
w a r t o ś c i
z
b u f o r a
k o l o r ó w
do
b u f o r a
a k u m u l a c y n e g o
glAccum
(GL LOAD , 0 . 5 ) ;
//
r y s o w a n i e
w y b r a n e j
i l o ś c i
p o p r z e d n i c h
ramek
a n i m a c j i
1. Bufor akumulacyjny
7
i n t
c o u n t = 1 5 ;
f o r
( i n t
i = 1 ;
i <= c o u n t ;
i ++)
{
//
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 ) ;
//
o b r o t y
o b i e k t ó w
s c e n y
g l R o t a t e f
( − 1 . 0 , 1 . 0 , 0 . 0 , 0 . 0 ) ;
g l R o t a t e f
( 1 . 0 , 0 . 0 , 1 . 0 , 0 . 0 ) ;
g l R o t a t e f
( − 1 . 0 , 0 . 0 , 0 . 0 , − 1 . 0 ) ;
//
w y ś w i e t l e n i e
o b i e k t ó w
s c e n y
g l C a l l L i s t
(WORLD LIST ) ;
//
d o d a n i e
p r z e s k a l o w a n y c h
w a r t o ś c i
z
b u f o r a
k o l o r ó w
do
b u f o r a
a k u m u l a c y n e g o
//
w s p ó ł c z y n n i k
s k a l o w a n i a
j e s t
o b l i c z a n y
na
p o d s t a w i e
i l o ś c i
r y s o w a n y c h
//
w c z e ś n i e j s z y c h
ramek
a n i m a c j i
glAccum
(GL ACCUM, 0 . 5 / ( f l o a t ) c o u n t ) ;
}
//
k o p i o w a n i e
w a r t o ś c i
z
b u f o r a
a k u m u l a c y j n e g o
do
b u f o r a
k o l o r ó w
glAccum
(GL RETURN , 1 . 0 ) ;
break ;
}
//
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 )
{
//
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
r o t a t e x ++;
r o t a t e y −−;
r o t a t e z ++;
//
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 ) ;
//
w a r t o ś ć
c z y s z c z ą c a
b u f o r
a k u m u l a c y j n y
g l C l e a r A c c u m
( 1 . 0 , 1 . 0 , 1 . 0 , 1 . 0 ) ;
1. Bufor akumulacyjny
8
//
c z y s z c z e n i e
b u f o r a
a k u m u l a c y j n e g o
g l C l e a r
(GL ACCUM 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 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 )
{
//
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 ) ;
}
}
//
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 )
{
//
p i e r w s z y
a l g o r y t m
r o z m y c i a w r u c h u
c a s e
’ 1 ’ :
g l C l e a r
(GL ACCUM BUFFER BIT ) ;
m o t i o n b l u r = MOTION BLUR 1 ;
break ;
//
d r u g i
a l g o r y t m
r o z m y c i a w r u c h u
c a s e
’ 2 ’ :
g l C l e a r
(GL ACCUM BUFFER BIT ) ;
m o t i o n b l u r = MOTION BLUR 2 ;
break ;
//
t r z e c i
a l g o r y t m
r o z m y c i a w r u c h u
c a s e
’ 3 ’ :
g l C l e a r
(GL ACCUM BUFFER BIT ) ;
m o t i o n b l u r = MOTION BLUR 3 ;
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
( ) ;
}
//
u t w o r z e n i e
l i s t y
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
( )
{
//
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
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 ) ;
//
l i s t a
w y ś w i e t l a n i a − s c e n a
g l N e w L i s t
(WORLD LIST , GL COMPILE ) ;
//
n i e b i e s k i
t o r u s
g l C o l o r 4 f v
( B l u e ) ;
g l u t S o l i d T o r u s
( 0 . 5 , 1 . 5 , 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 [ ] )
{
1. Bufor akumulacyjny
9
//
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 ACCUM ) ;
//
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
( ” Rozmycie w r u c h u ” ) ;
//
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 ) ;
//
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
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
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 y
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
( ) ;
//
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 glebia ostrosci.cpp) przedstawia
jedną z możliwych realizacji efektu głębi ostrości (ang. depth of field). Idea
pomysłu jest bardzo prosta i sprowadza się do wielokrotnego rysowania
obiektów sceny, za każdym razem nieco przesuniętych w stosunku do pod-
stawowego obrazu. Odpowiedni dobór przesunięcia powoduje, że obiekty po-
łożone bliżej (rysunek 4) są bardziej „ostre” od obiektów położonych dalej
(rysunek 4). Program umożliwia wybór jakości uzyskanego efektu, przy czym
lepsza jakość związana jest niestety z większą ilością wykonywanych obliczeń.
1. Bufor akumulacyjny
10
Rysunek 4. Program Głębia ostrości - obiekt w małej odległości
Podobna technika może zostać wykorzystania do uzyskania efektu anty-
aliasingu całej sceny, ale to przedstawimy w następnym odcinku kursu.
1.3.2. Plik glebia ostrosci.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
{
DOF 3 ,
//
g ł ę b i a
o s t r o ś c i − b u f o r
a k u m u l a c y j n y
3 x 3
DOF 5 ,
//
g ł ę b i a
o s t r o ś c i − b u f o r
a k u m u l a c y j n y
5 x 5
DOF 7 ,
//
g ł ę b i a
o s t r o ś c i − b u f o r
a k u m u l a c y j n y
7 x 7
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
1. Bufor akumulacyjny
11
Rysunek 5. Program Głębia ostrości - obiekt w dużej odległości
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 = 1 . 0 ;
const GLdouble
f a r = 1 1 ;
//
w s p ó ł r z ę d n a
z
p o ł o ż e n i a
o b i e k t u
G L f l o a t
z = 0 ;
//
r o d z a j
e f e k t u
g ł ę b i
o s t r o ś c i
i n t
d e p t h o f f i e l d = DOF 3 ;
//
j a k o ś ć
e f e k t u
g ł ę b i
o s t r o ś c i
1. Bufor akumulacyjny
12
i n t
d o f q u a l i t y = 1 ;
//
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 ) ;
//
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
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
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
r o z m i a r u
o k n a
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 ) ;
//
s c e n a
z
a n t y a l i s i n g i e m
z
u ż y c i e m
b u f o r a
a k u m u l a c y j n e g o
//
z a k r e s y
p ę t l i
r y s u j ą c y c h
k o l e j n e
p r z e s u n i ę t e
r a m k i
s c e n y
i n t
min = − d o f q u a l i t y ;
i n t max = −min + 1 ;
//
i l o ś ć
r y s o w a n y c h
ramek
s c e n y ,
w a r t o ś ć
u ż y w a n a
p r z y
//
m n o ż e n i u
d a n y c h
d o d a w a n y c h
do
b u f o r a
a k u m u l a c y j n e g o
G L f l o a t
c o u n t = ( max − min )
∗ ( max − min ) ;
//
c z y s z c z e n i e
b u f o r a
a k u m u l a c y j n e g o
g l C l e a r
(GL ACCUM BUFFER BIT ) ;
//
w y ś w i e t l e n i e
s c e n y
( max−min −1)ˆ2
r a z y
f o r ( i n t
y = min ;
y < max ;
y++)
f o r ( i n t
x = min ;
x < max ;
x++)
{
//
o b l i c z e n i e
w s p ó ł c z y n n i k ó w
p r z e s u n i ę c i a −
f l u k t u a c j i
//
( a n g .
j i t t e r )
u k ł a d u
w s p ó ł r z ę d n y c h ;
w s p ó ł c z y n n i k
//
0 . 0 2
d o b r a n y
e k s p e r y m e n t a l n i e
G L f l o a t
dx = x ∗
0 . 0 2 ;
G L f l o a t
dy = y ∗
0 . 0 2 ;
//
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 +dx , r i g h t+dx ,
bottom ∗ h e i g h t / w i d t h+dy , t o p ∗ h e i g h t / w i d t h+dy ,
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+dx ,
r i g h t ∗ w i d t h / h e i g h t+dy , bottom+dy , t o p+dy ,
n e a r , f a r ) ;
}
e l s e
g l F r u s t u m
( l e f t +dx , r i g h t+dx , bottom+dy , t o p+dy , n e a r , f a r ) ;
//
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 ) ;
1. Bufor akumulacyjny
13
//
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 u
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 ) ;
//
d r o b n e
p r z e s u n i ę c i e
o b i e k t u
p o p r a w i a j ą c e
j a k o ś ć
//
r e n d e r i n g u
o b i e k t ó w w
b l i ż s z e j
o d l e g ł o ś c i ;
//
w s p ó ł c z y n n i k
0 . 0 2
d o b r a n y
e k s p e r y m e n t a l n i e
g l T r a n s l a t e f
( x ∗ 0 . 0 2 , y ∗ 0 . 0 2 , 0 . 0 ) ;
//
k o l o r
o b i e k t u
g l C o l o r 4 f v
( Green ) ;
//
p r z e s u n i ę c i e
o b i e k t u
w z g l ę d e m
o s i OZ
g l T r a n s l a t e f
( 0 . 0 , 0 . 0 , z ) ;
//
n a r y s o w a n i e
o b i e k t u
g l u t S o l i d T o r u s
( 1 . 0 , 2 . 5 , 5 0 , 4 0 ) ;
//
d o d a n i e
d a n y c h
do
b u f o r a
a k u m u l a c y j n e g o
glAccum
(GL ACCUM, 1 . 0 / c o u n t ) ;
}
//
p r z e n i e s i e n i e
d a n y c h
z
b u f o r a
a k u m u l a c y j n e g o
do
b u f o r a
k o l o r u
glAccum
(GL RETURN , 1 . 0 ) ;
//
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 ) ;
//
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 )
{
//
p r z e s u n i ę c i e
o b i e k t u
w z g l ę d e m
o s i OZ
i f
( k e y == ’+ ’ )
z += 0 . 1 ;
e l s e
i f
( k e y == ’− ’ )
z −= 0 . 1 ;
//
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 )
{
//
g ł ę b i a
o s t r o ś c i − b u f o r
a k u m u l a c y j n y
3 x 3
c a s e DOF 3 :
d e p t h o f f i e l d = DOF 3 ;
d o f q u a l i t y = 1 ;
D i s p l a y S c e n e
( ) ;
break ;
//
g ł ę b i a
o s t r o ś c i − b u f o r
a k u m u l a c y j n y
5 x 5
c a s e DOF 5 :
d e p t h o f f i e l d = DOF 5 ;
d o f q u a l i t y = 2 ;
1. Bufor akumulacyjny
14
D i s p l a y S c e n e
( ) ;
break ;
//
g ł ę b i a
o s t r o ś c i − b u f o r
a k u m u l a c y j n y
7 x 7
c a s e DOF 7 :
d e p t h o f f i e l d = DOF 7 ;
d o f q u a l i t y = 3 ;
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 ) ;
}
}
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 ACCUM ) ;
//
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
( ” G ł ę b i a
o s t r o ś c i ” ) ;
#e l s e
g l u t C r e a t e W i n d o w
( ” G l e b i a
o s t r o s c i ” ) ;
#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
podmenu − A n t y a l i a s i n g
i n t MenuDOF = g l u t C r e a t e M e n u
( Menu ) ;
glutAddMenuEntry
( ” B u f o r
a k u m u l a c y j n y
3 x3 ” , DOF 3 ) ;
glutAddMenuEntry
( ” B u f o r
a k u m u l a c y j n y
5 x5 ” , DOF 5 ) ;
glutAddMenuEntry
( ” B u f o r
a k u m u l a c y j n y
7 x7 ” , DOF 7 ) ;
//
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
glutAddSubMenu
( ” G ł ę b i a
o s t r o ś c i ” ,MenuDOF ) ;
1. Bufor akumulacyjny
15
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
( ” G l e b i a
o s t r o s c i ” ,MenuDOF ) ;
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 ) ;
//
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 ;
}
Trzeci i ostatni program przykładowy (plik filtracja obrazow.cpp)
przedstawia sposób wykorzystania bufora akumulacyjngo do filtracji obra-
zów przy użyciu filtrów splotowych. Zbiór filtrów jest taki sam jak używa-
ny w programie prezentującym opcjonalny podzbiór przetwarzania obrazów
(plik filters.h).
Efekt działania filtra splotowego uzyskiwany jest poprzez wielokrotne
rysowanie filtrowanego obrazu przy czym za każdym razem zmieniane jest
położenie rysowanego obrazu i odpowiednio modyfikowany współczynnik
skalowania składowych RGB obrazu. Z uwagi na specyfikę działania bufora
akumulacyjnego maski filtra muszą być tak przeskalowane, aby ich war-
tość bezwzględna nie była większa o jednego. Drugim ważnym elementem,
jest kolejność nakładania poszczególnych obrazów, bowiem w przypadku
przekroczenia przez składową bufora akumulacyjnego przedziału wartości
[−1, 1], nastąpią przekłamania w końcowym wyniku filtracji. Obie powyższe
operacje wykonywane są każdorazowo przy wyborze filtra (funkcja Menu).
Efekty działania programu nie różną się w żaden sposób od działania
wspomnianego wyżej programu wykorzystującego opcjonalny podzbiór funk-
cji przetwarzania obrazów. Efekt działania wybranych filtrów przedstawiono
na rysunkach 6 - 10.
1.3.3. Plik filtracja 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 i o . 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
” t a r g a . h ”
#i n c l u d e
” f i l t e 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
{
//
f i l t r y
s p l o t o w e
1. Bufor akumulacyjny
16
Rysunek 6. Program Filtracja obrazów - filtr pionowy Laplace’a
NONE,
//
b r a k
f i l t r a c j i
AVERAGE,
//
f i l t r
u ś r e d n i a j ą c y
LP1 ,
//
f i l t r
LP1
LP2 ,
//
f i l t r
LP2
LP3 ,
//
f i l t r
LP3
GAUSS,
//
f i l t r
G a u s s a
MEAN REMOVAL,
//
f i l t r
u s u w a j ą c y
ś r e d n i ą
HP1 ,
//
f i l t r
HP1
HP2 ,
//
f i l t r
HP2
HP3 ,
//
f i l t r
HP3
HORIZONTAL,
//
f i l t r
p o z i o m y
VERTICAL,
//
f i l t r
p i o n o w y
HORIZONTAL VERTICAL,
//
f i l t r
p o z i o m y / p i o n o w y
GRADIENT EAST,
//
f i l t r
g r a d i e n t o w y
w s c h ó d
GRADIENT SOUTH EAST,
//
f i l t r
g r a d i e n t o w y
p o ł u d n i o w y
w s c h ó d
GRADIENT SOUTH,
//
f i l t r
g r a d i e n t o w y
p o ł u d n i e
GRADIENT SOUTH WEST,
//
f i l t r
g r a d i e n t o w y
p o ł u d n i o w y
z a c h ó d
GRADIENT WEST,
//
f i l t r
g r a d i e n t o w y
z a c h ó d
GRADIENT NORTH WEST,
//
f i l t r
g r a d i e n t o w y
p ó ł n o c n y
z a c h ó d
GRADIENT NORTH,
//
f i l t r
g r a d i e n t o w y
p ó ł n o c
GRADIENT NORTH EAST,
//
f i l t r
g r a d i e n t o w y
p ó ł n o c n y
w s c h ó d
EMBOSS EAST,
//
f i l t r
u w y p u k l a j ą c y
w s c h ó d
EMBOSS SOUTH EAST,
//
f i l t r
u w y p u k l a j ą c y
p o ł u d n i o w y
w s c h ó d
EMBOSS SOUTH,
//
f i l t r
u w y p u k l a j ą c y
p o ł u d n i e
EMBOSS SOUTH WEST,
//
f i l t r
u w y p u k l a j ą c y
p o ł u d n i o w y
z a c h ó d
1. Bufor akumulacyjny
17
Rysunek 7. Program Filtracja obrazów - filtr pionowy Sobela
EMBOSS WEST,
//
f i l t r
u w y p u k l a j ą c y
z a c h ó d
EMBOSS NORTH WEST,
//
f i l t r
u w y p u k l a j ą c y
p ó ł n o c n y
z a c h ó d
EMBOSS NORTH,
//
f i l t r
u w y p u k l a j ą c y
p ó ł n o c
EMBOSS NORTH EAST,
//
f i l t r
u w y p u k l a j ą c y
p ó ł n o c n y
w s c h ó d
LAPLACIAN LAPL1 ,
//
f i l t r
L a p l a c e ’ a LAPL1
LAPLACIAN LAPL2 ,
//
f i l t r
L a p l a c e ’ a LAPL2
LAPLACIAN LAPL3 ,
//
f i l t r
L a p l a c e ’ a LAPL3
LAPLACIAN DIAGONAL,
//
f i l t r
L a p l a c e ’ a
s k o ś n y
LAPLACIAN HORIZONTAL,
//
f i l t r
L a p l a c e ’ a
p o z i o m y
LAPLACIAN VERTICAL ,
//
f i l t r
L a p l a c e ’ a
p i o n o w y
SOBEL HORIZONTAL,
//
f i l t r
p o z i o m y
S o b e l a
SOBEL VERTICAL ,
//
f i l t r
p i o n o w y
S o b e l a
PREWITT HORIZONTAL,
//
f i l t r
p o z i o m y
P r e w i t t a
PREWITT VERTICAL,
//
f i l t r
p i o n o w y
P r e w i t t a
SAVE FILE ,
//
z a p i s
p l i k u TARGA
EXIT
//
w y j ś c i e
} ;
//
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 akumulacyjny
18
Rysunek 8. Program Filtracja obrazów - filtr pionowy Prewitta
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
//
n e u t r a l n a
maska
f i l t r a
s p l o t o w e g o
G L f l o a t
n e u t r a l
[ 9 ] =
{
0 , 0 , 0 ,
0 , 1 , 0 ,
0 , 0 , 0
} ;
//
t a b l i c a
z
b i e ż ą c ą
maską
f i l t r a
s p l o t o w e g o
G L f l o a t
f i l t e r
[ 9 ] =
{
0 , 0 , 0 ,
0 , 1 , 0 ,
0 , 0 , 0
} ;
//
w a r t o ś ć
s k a l u j ą c a
s k ł a d o w e
b u f o r a
a k u m u l a c y j n e g o
G L f l o a t
s c a l e = 1 . 0 ;
//
numery
k o l e j n y c h
p r z e t w a r z a n y c h
e l e m e n t ó w
m a s k i
f i l t r a
1. Bufor akumulacyjny
19
Rysunek 9. Program Filtracja obrazów - filtr HP1
i n t
d i r h
[ 9 ] =
{
2 , 0 , 0 , 2 , 1 , 0 , 1 , 2 , 1
} ;
i n t
d i r w
[ 9 ] =
{
0 , 0 , 2 , 2 , 0 , 1 , 2 , 1 , 1
} ;
//
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 ) )
{
1. Bufor akumulacyjny
20
Rysunek 10. Program Filtracja obrazów - filtr HP2
#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 ” ) ;
1. Bufor akumulacyjny
21
#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 ) ;
}
}
}
}
//
z a p i s
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 SaveTARGA ( GLenum f o r m a t )
{
//
w y r ó w n y w a n i e
w i e r s z a
mapy 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 PACK ALIGNMENT , 1 ) ;
//
w s k a ź n i k
na
b u f o r
mapy
p i k s e l o w e j
GLvoid ∗ p i x e l s ;
//
s z e r o k o ś ć
i
w y s o k o ś ć
mapy
p i k s e l o w e j
G L s i z e i
w i d t h = g l u t G e t
(GLUT WINDOW WIDTH ) ;
G L s i z e i
h e i g h t = g l u t G e t
(GLUT WINDOW HEIGHT ) ;
//
u t w o r z e n i e
b u f o r a
mapy
p i k s e l o w e j
i f
( f o r m a t == GL BGRA)
p i x e l s = new unsigned char
[ w i d t h ∗ h e i g h t ∗ 4 ] ;
e l s e
i f
( f o r m a t == GL BGR)
p i x e l s = new unsigned char
[ w i d t h ∗ h e i g h t ∗ 3 ] ;
e l s e
i f
( f o r m a t == GL LUMINANCE)
p i x e l s = new unsigned char
[ w i d t h ∗ h e i g h t ] ;
e l s e
return ;
//
t y l k o
p l i k
w o d c i e n i a c h
s z a r o ś c i
i f
( f o r m a t == GL LUMINANCE)
{
//
o k r e ś l e n i e
p r z e k s z t a ł c e n i a
s k ł a d o w y c h RGB na
o d c i e n i e
s z a r o ś c i
g l P i x e l T r a n s f e r f
( GL RED SCALE , 0 . 2 2 9 ) ;
g l P i x e l T r a n s f e r f
(GL GREEN SCALE , 0 . 5 8 7 ) ;
g l P i x e l T r a n s f e r f
( GL BLUE SCALE , 0 . 1 1 4 ) ;
}
//
s k o p i o w a n i e
z a w a r t o ś c i
b u f o r a
k o l o r u
do
b u f o r a
mapy
p i k s e l o w e j
g l R e a d P i x e l s
( 0 , 0 , width , h e i g h t , f o r m a t , GL UNSIGNED BYTE , p i x e l s ) ;
//
t y l k o
p l i k
w o d c i e n i a c h
s z a r o ś c i
i f
( f o r m a t == GL LUMINANCE)
{
//
p o w r ó t
do
n e u t r a l n e g o
p r z e k s z t a ł c e n i a
s k ł a d o w y c h
g l P i x e l T r a n s f e r f
( GL RED SCALE , 1 . 0 ) ;
g l P i x e l T r a n s f e r f
(GL GREEN SCALE , 1 . 0 ) ;
g l P i x e l T r a n s f e r f
( GL BLUE SCALE , 1 . 0 ) ;
}
//
z a p i s
mapy
p i k s e l o w e j
do
p l i k u TARGA
i f
( f o r m a t == GL BGRA)
s a v e t a r g a
( ” test BGRA . 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 ) ;
e l s e
i f
( f o r m a t == GL BGR)
s a v e t a r g a
( ” test BGR . 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 ) ;
e l s e
i f
( f o r m a t == GL LUMINANCE)
s a v e t a r g a
( ”test LUMINANCE . 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 ) ;
1. Bufor akumulacyjny
22
//
p o r z ą d k i
d e l e t e
[ ]
( unsigned char ∗ ) p i x e l s ;
}
//
w y ś w i e t l e n i e
i
s k a l o w a n i e
o b r a z u
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 ) ;
//
w a r t o ś ć
c z y s z c z ą c a
b u f o r
a k u m u l a c y j n y
g l C l e a r A c c u m
( 0 . 0 , 0 . 0 , 0 . 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
a k u m u l a c y j n e g o
g l C l e a r
( GL COLOR BUFFER BIT | GL ACCUM BUFFER BIT ) ;
//
p o b r a n i e
r o z m i a r ó w
o k n a
i n t
w i n w i d t h = g l u t G e t
(GLUT WINDOW WIDTH ) ;
i n t
w i n h e i g h t = g l u t G e t
(GLUT WINDOW HEIGHT ) ;
//
r o z m i a r y
m a s k i
f i l t r a
const
i n t whmax = 3 ;
//
f i l t r a c j a
o b r a z u
f o r
( i n t
i = 0 ;
i < whmax ∗ whmax ;
i ++)
{
//
o b s z a r
r e n d e r i n g u − o d p o w i e d n i
p r z e s u n i ę t e
o k n o
g l V i e w p o r t (− d i r w [ i ] , − d i r h [ i ] , w i n w i d t h −d i r w [ i ] , w i n h e i g h t −d i r h [ i ] ) ;
//
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 ) w i n w i d t h / ( f l o a t ) width , ( f l o a t ) w i n h e i g h t / ( 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 ) ;
//
d o d a n i e
d a n y c h
do
b u f o r a
a k u m u l a c y j n e g o
glAccum
(GL ACCUM, f i l t e r
[ d i r w [ i ] + d i r h [ i ]
∗ whmax ] ) ;
}
//
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 , w i n w i d t h , w i n h e i g h t ) ;
//
p r z e n i e s i e n i e
d a n y c h
z
b u f o r a
a k u m u l a c y j n e g o
do
b u f o r a
k o l o r u
glAccum
(GL RETURN, s c a l e ) ;
//
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 i n i 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 u O r t h o 2 D
( 0 . 0 , Width , 0 . 0 , H e i g h t ) ;
//
g e n e r o w a n i e
s c e n y
3D
D i s p l a y
( ) ;
}
1. Bufor akumulacyjny
23
//
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 )
{
//
w s k a ź n i k i
na
m a s k i
p o s z c z e g ó l n y c h
f i l t r ó w
s p l o t o w y c h
G L f l o a t
∗ f i l t e r s
[ 3 9 ] =
{
n e u t r a l ,
a v e r a g e ,
l p 1 ,
l p 2 ,
l p 3 ,
g a u s s ,
m e a n r e m o v a l ,
hp1 ,
hp2 ,
hp3 ,
h o r i z o n t a l ,
v e r t i c a l ,
h o r i z o n t a l v e r t i c a l ,
g r a d i e n t e a s t ,
g r a d i e n t s o u t h e a s t ,
g r a d i e n t s o u t h ,
g r a d i e n t s o u t h w e s t ,
g r a d i e n t w e s t ,
g r a d i e n t n o r t h w e s t ,
g r a d i e n t n o r t h ,
g r a d i e n t n o r t h e a s t ,
e m b o s s e a s t ,
e m b o s s s o u t h e a s t ,
e m b o s s s o u t h ,
e m b o s s s o u t h w e s t ,
e m b o s s w e s t ,
e m b o s s n o r t h w e s t ,
e m b o s s n o r t h ,
e m b o s s n o r t h e a s t ,
l a p l a c i a n l a p l 1 ,
l a p l a c i a n l a p l 2 ,
l a p l a c i a n l a p l 3 ,
l a p l a c i a n d i a g o n a l ,
l a p l a c i a n h o r i z o n t a l ,
l a p l a c i a n v e r t i c a l ,
s o b e l h o r i z o n t a l ,
s o b e l v e r t i c a l ,
p r e w i t t h o r i z o n t a l ,
p r e w i t t v e r t i c a l
} ;
//
s t a ł e
o k r e ś l a j ą c e
k o l e j n o ś ć
n a k ł a d a n i a
k o l e j n y c h
o b r a z ó w
enum
{
HW, HW REV, CROSS, CROSS REV
} ;
//
o z n a c z e n i a
numerów
k o l e j n y c h
e l e m e n t ó w
m a s k i
f i l t r a
//
|
00
10
20
|
//
|
10
11
21
|
//
|
20
21
22
|
//
k o l e j n o ś ć − p o z i o m e
const
i n t
hw h
[ 9 ] =
{
0 , 0 , 0 , 1 , 1 , 1 , 2 , 2 , 2
} ;
const
i n t hw w
[ 9 ] =
{
0 , 1 , 2 , 0 , 1 , 2 , 0 , 1 , 2
} ;
//
k o l e j n o ś ć − p o z i o m e
o d w r ó c o n e
const
i n t
h w r e v h
[ 9 ] =
{
2 , 2 , 2 , 1 , 1 , 1 , 0 , 0 , 0
} ;
const
i n t
h w r e v w
[ 9 ] =
{
2 , 1 , 0 , 2 , 1 , 0 , 2 , 1 , 0
} ;
//
k o l e j n o ś ć − s k r a j n e
e l e m e n t y
p r z e k ą t n e
o r a z
k r z y ż
( o d w r ó c o n e )
const
i n t
c r o s s r e v h
[ 9 ] =
{
2 , 0 , 0 , 2 , 1 , 0 , 1 , 2 , 1
} ;
const
i n t
c r o s s r e v w
[ 9 ] =
{
0 , 0 , 2 , 2 , 0 , 1 , 2 , 1 , 1
} ;
//
k o l e j n o ś ć − s k r a j n e
e l e m e n t y
p r z e k ą t n e
o r a z
k r z y ż
const
i n t
c r o s s h
[ 9 ] =
{
0 , 2 , 2 , 0 , 1 , 2 , 1 , 0 , 1
} ;
const
i n t
c r o s s w
[ 9 ] =
{
0 , 0 , 2 , 2 , 0 , 1 , 2 , 1 , 1
} ;
//
k o l e j n o ś c i
n a k ł a d a n i a
o b r a z ó w
d l a
w y b r a n y c h
f i l t r ó w
s p l o t o w y c h
i n t
d i r e c t i o n s
[ 3 9 ] =
{
CROSS, CROSS, CROSS,
//
n e u t r a l ,
a v e r a g e ,
l p 1 ,
CROSS, CROSS, CROSS,
//
l p 2 ,
l p 3 ,
g a u s s ,
CROSS, CROSS, CROSS,
//
m e a n r e m o v a l ,
hp1 ,
hp2 ,
CROSS, CROSS, CROSS,
//
hp3 ,
h o r i z o n t a l ,
v e r t i c a l ,
CROSS, CROSS, CROSS,
//
h o r i z o n t a l v e r t i c a l ,
g r a d i e n t e a s t ,
//
g r a d i e n t s o u t h e a s t ,
CROSS, CROSS, CROSS,
//
g r a d i e n t s o u t h ,
g r a d i e n t s o u t h w e s t ,
1. Bufor akumulacyjny
24
//
g r a d i e n t w e s t ,
CROSS, CROSS, CROSS,
//
g r a d i e n t n o r t h w e s t ,
g r a d i e n t n o r t h ,
//
g r a d i e n t n o r t h e a s t ,
HW, CROSS, CROSS,
//
e m b o s s e a s t ,
e m b o s s s o u t h e a s t ,
e m b o s s s o u t h ,
CROSS REV , HW REV, CROSS,
//
e m b o s s s o u t h w e s t ,
e m b o s s w e s t ,
//
e m b o s s n o r t h w e s t ,
CROSS, CROSS REV , CROSS,
//
e m b o s s n o r t h ,
e m b o s s n o r t h e a s t ,
l a p l a c i a n l a p l 1 ,
CROSS, CROSS, CROSS,
//
l a p l a c i a n l a p l 2 ,
l a p l a c i a n l a p l 3 ,
//
l a p l a c i a n d i a g o n a l ,
CROSS, CROSS, CROSS,
//
l a p l a c i a n h o r i z o n t a l ,
l a p l a c i a n v e r t i c a l ,
//
s o b e l h o r i z o n t a l ,
CROSS, CROSS, CROSS
//
s o b e l v e r t i c a l ,
p r e w i t t h o r i z o n t a l ,
//
p r e w i t t
v e r t i c a l
} ;
switch
( v a l u e )
{
//
z a p i s
p l i k u
w f o r m a c i e TARGA
c a s e SAVE FILE :
SaveTARGA ( f o r m a t ) ;
break ;
//
f i l t r y
s p l o t o w e
c a s e NONE:
c a s e AVERAGE:
c a s e LP1 :
c a s e LP2 :
c a s e LP3 :
c a s e GAUSS :
c a s e MEAN REMOVAL:
c a s e HP1 :
c a s e HP2 :
c a s e HP3 :
c a s e HORIZONTAL :
c a s e VERTICAL :
c a s e HORIZONTAL VERTICAL :
c a s e GRADIENT EAST :
c a s e GRADIENT SOUTH EAST :
c a s e GRADIENT SOUTH :
c a s e GRADIENT SOUTH WEST :
c a s e GRADIENT WEST :
c a s e GRADIENT NORTH WEST :
c a s e GRADIENT NORTH :
c a s e GRADIENT NORTH EAST :
c a s e EMBOSS EAST :
c a s e EMBOSS SOUTH EAST :
c a s e EMBOSS SOUTH :
c a s e EMBOSS SOUTH WEST :
c a s e EMBOSS WEST :
c a s e EMBOSS NORTH WEST :
c a s e EMBOSS NORTH :
c a s e EMBOSS NORTH EAST :
c a s e LAPLACIAN LAPL1 :
c a s e LAPLACIAN LAPL2 :
c a s e LAPLACIAN LAPL3 :
c a s e LAPLACIAN DIAGONAL :
c a s e LAPLACIAN HORIZONTAL :
c a s e LAPLACIAN VERTICAL :
c a s e SOBEL HORIZONTAL :
c a s e SOBEL VERTICAL :
c a s e PREWITT HORIZONTAL :
c a s e PREWITT VERTICAL :
//
k o l e j n o ś ć
n a k ł a d a n i a
o b r a z ó w
switch
( d i r e c t i o n s
[ v a l u e ] )
{
c a s e CROSS :
memcpy ( d i r h , c r o s s h , 9 ∗ s i z e o f
( i n t ) ) ;
memcpy ( d i r w , c r o s s w , 9 ∗ s i z e o f
( i n t ) ) ;
break ;
c a s e CROSS REV :
memcpy ( d i r h , c r o s s r e v h , 9 ∗ s i z e o f
( i n t ) ) ;
memcpy ( d i r w , c r o s s r e v w , 9 ∗ s i z e o f
( i n t ) ) ;
break ;
c a s e HW:
memcpy ( d i r h , hw h , 9 ∗ s i z e o f
( i n t ) ) ;
memcpy ( d i r w , hw w , 9 ∗ s i z e o f
( i n t ) ) ;
break ;
c a s e HW REV:
memcpy ( d i r h , h w r e v h , 9 ∗ s i z e o f
( i n t ) ) ;
1. Bufor akumulacyjny
25
memcpy ( d i r w , h w r e v w , 9 ∗ s i z e o f
( i n t ) ) ;
break ;
}
//
p r z y g o t o w a n i e
m a s k i
f i l t r a
memcpy ( f i l t e r , f i l t e r s
[ v a l u e ] , 9 ∗ s i z e o f
( G L f l o a t ) ) ;
//
w y s z u k a n i e
e l e m e n u
m a k s y m a l n e g o
m a s k i
s p l o t u
f i l t r a
G L f l o a t
absmax = f a b s
( f i l t e r
[ 0 ] ) ;
f o r
( i n t
i = 1 ;
i < 9 ;
i ++)
i f
( f a b s
( f i l t e r
[ i ] ) > absmax )
absmax = f a b s
( f i l t e r
[ i ] ) ;
//
m o d y f i k a c j a
m a s k i
s p l o t u
f i l t r a
i f
( absmax > 1 . 0 )
f o r
( i n t
i = 0 ;
i < 9 ;
i ++)
f i l t e r
[ i ]
/= absmax ;
//
w s p ó ł c z y n n i k
s k a l o w a n i a
s k ł a d o w y c h
b u f o r a
a k u m u l a c y j n e g o
i f
( absmax > 1 . 0 )
s c a l e = absmax ;
e l s e
s c a l e = 1 . 0 ;
//
w y ś w i e t l e n i e
s c e n y
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 ;
}
}
i n t
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 ACCUM ) ;
//
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 − r ó w n e wymiarom
//
o d c z y t a n e g o
p l i k u
g r a f i c z n e g o TARGA
g l u t I n i t W i n d o w S i z e
( width , h e i g h t ) ;
//
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 − n a zw a
o k n a
t a k a
// sama
j a k
na z w a
o d c z y t a n e g o
p l i k u
g r a f i c z n e g o TARGA
g l u t C r e a t e W i n d o w
( a r g v [ 1 ] ) ;
//
d o ł ą c z e n i e
f u n k c j i
g e n e r u j ą c e j
s c e n ę
3D − o b r a z
z a w a r t y w
p l i k u TARGA
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 ) ;
//
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
( ) ;
// podmenu ” F i l t r y ”
i n t
M e n u F i l t e r s = g l u t C r e a t e M e n u
( Menu ) ;
#i f d e f WIN32
glutAddMenuEntry
( ” F i l t r
u ś r e d n i a j ą c y ” ,AVERAGE) ;
glutAddMenuEntry
( ” F i l t r
LP1” , LP1 ) ;
glutAddMenuEntry
( ” F i l t r
LP2” , LP2 ) ;
glutAddMenuEntry
( ” F i l t r
LP3” , LP3 ) ;
glutAddMenuEntry
( ” F i l t r
Gaussa ” ,GAUSS ) ;
glutAddMenuEntry
( ” F i l t r
u s u w a j ą c y
ś r e d n i ą ” ,MEAN REMOVAL) ;
glutAddMenuEntry
( ” F i l t r
HP1” , HP1 ) ;
glutAddMenuEntry
( ” F i l t r
HP2” , HP2 ) ;
glutAddMenuEntry
( ” F i l t r
HP3” , HP3 ) ;
glutAddMenuEntry
( ” F i l t r
poziomy ” ,HORIZONTAL ) ;
glutAddMenuEntry
( ” F i l t r
pionowy ” ,VERTICAL ) ;
glutAddMenuEntry
( ” F i l t r
poziomy / pionowy ” ,HORIZONTAL VERTICAL ) ;
glutAddMenuEntry
( ” F i l t r
g r a d i e n t o w y
wschód ” ,GRADIENT EAST ) ;
1. Bufor akumulacyjny
26
glutAddMenuEntry
( ” F i l t r
g r a d i e n t o w y
p o ł u d n i o w y
wschód ” ,GRADIENT SOUTH EAST ) ;
glutAddMenuEntry
( ” F i l t r
g r a d i e n t o w y
p o ł u d n i e ” ,GRADIENT SOUTH ) ;
glutAddMenuEntry
( ” F i l t r
g r a d i e n t o w y
p o ł u d n i o w y
z a c h ó d ” ,GRADIENT SOUTH WEST ) ;
glutAddMenuEntry
( ” F i l t r
g r a d i e n t o w y
z a c h ó d ” ,GRADIENT WEST ) ;
glutAddMenuEntry
( ” F i l t r
g r a d i e n t o w y
p ó ł n o c n y
z a c h ó d ” ,GRADIENT NORTH WEST ) ;
glutAddMenuEntry
( ” F i l t r
g r a d i e n t o w y
p ó ł n o c ” ,GRADIENT NORTH ) ;
glutAddMenuEntry
( ” F i l t r
g r a d i e n t o w y
p ó ł n o c n y
wschód ” ,GRADIENT NORTH EAST ) ;
glutAddMenuEntry
( ” F i l t r
u w y p u k l a j ą c y
wschód ” ,EMBOSS EAST ) ;
glutAddMenuEntry
( ” F i l t r
u w y p u k l a j ą c y
p o ł u d n i o w y
wschód ” ,EMBOSS SOUTH EAST ) ;
glutAddMenuEntry
( ” F i l t r
u w y p u k l a j ą c y
p o ł u d n i e ” ,EMBOSS SOUTH ) ;
glutAddMenuEntry
( ” F i l t r
u w y p u k l a j ą c y
p o ł u d n i o w y
z a c h ó d ” ,EMBOSS SOUTH WEST ) ;
glutAddMenuEntry
( ” F i l t r
u w y p u k l a j ą c y
z a c h ó d ” ,EMBOSS WEST ) ;
glutAddMenuEntry
( ” F i l t r
u w y p u k l a j ą c y
p ó ł n o c n y
z a c h ó d ” ,EMBOSS NORTH WEST ) ;
glutAddMenuEntry
( ” F i l t r
u w y p u k l a j ą c y
p ó ł n o c ” ,EMBOSS NORTH ) ;
glutAddMenuEntry
( ” F i l t r
u w y p u k l a j ą c y
p ó ł n o c n y
wschód ” ,EMBOSS NORTH EAST ) ;
glutAddMenuEntry
( ” F i l t r
L a p l a c e ’ a LAPL1” , LAPLACIAN LAPL1 ) ;
glutAddMenuEntry
( ” F i l t r
L a p l a c e ’ a LAPL2” , LAPLACIAN LAPL2 ) ;
glutAddMenuEntry
( ” F i l t r
L a p l a c e ’ a LAPL3” , LAPLACIAN LAPL3 ) ;
glutAddMenuEntry
( ” F i l t r
L a p l a c e ’ a
s k o ś n y ” ,LAPLACIAN DIAGONAL ) ;
#e l s e
glutAddMenuEntry
( ” F i l t r
u ś r e d n i a j ą c y ” ,AVERAGE) ;
glutAddMenuEntry
( ” F i l t r
LP1” , LP1 ) ;
glutAddMenuEntry
( ” F i l t r
LP2” , LP2 ) ;
glutAddMenuEntry
( ” F i l t r
LP3” , LP3 ) ;
glutAddMenuEntry
( ” F i l t r
Gaussa ” ,GAUSS ) ;
glutAddMenuEntry
( ” F i l t r
u s u w a j a c y
s r e d n i a ” ,MEAN REMOVAL) ;
glutAddMenuEntry
( ” F i l t r
HP1” , HP1 ) ;
glutAddMenuEntry
( ” F i l t r
HP2” , HP2 ) ;
glutAddMenuEntry
( ” F i l t r
HP3” , HP3 ) ;
glutAddMenuEntry
( ” F i l t r
poziomy ” ,HORIZONTAL ) ;
glutAddMenuEntry
( ” F i l t r
pionowy ” ,VERTICAL ) ;
glutAddMenuEntry
( ” F i l t r
poziomy / pionowy ” ,HORIZONTAL VERTICAL ) ;
glutAddMenuEntry
( ” F i l t r
g r a d i e n t o w y
wschod ” ,GRADIENT EAST ) ;
glutAddMenuEntry
( ” F i l t r
g r a d i e n t o w y
p o l u d n i o w y
wschod ” ,GRADIENT SOUTH EAST ) ;
glutAddMenuEntry
( ” F i l t r
g r a d i e n t o w y
p o l u d n i e ” ,GRADIENT SOUTH ) ;
glutAddMenuEntry
( ” F i l t r
g r a d i e n t o w y
p o l u d n i o w y
z a c h o d ” ,GRADIENT SOUTH WEST ) ;
glutAddMenuEntry
( ” F i l t r
g r a d i e n t o w y
z a c h o d ” ,GRADIENT WEST ) ;
glutAddMenuEntry
( ” F i l t r
g r a d i e n t o w y
p o l n o c n y
z a c h o d ” ,GRADIENT NORTH WEST ) ;
glutAddMenuEntry
( ” F i l t r
g r a d i e n t o w y
p o l n o c ” ,GRADIENT NORTH ) ;
glutAddMenuEntry
( ” F i l t r
g r a d i e n t o w y
p o l n o c n y
wschod ” ,GRADIENT NORTH EAST ) ;
glutAddMenuEntry
( ” F i l t r
u w y p u k l a j a c y
wschod ” ,EMBOSS EAST ) ;
glutAddMenuEntry
( ” F i l t r
u w y p u k l a j a c y
p o l u d n i o w y
wschod ” ,EMBOSS SOUTH EAST ) ;
glutAddMenuEntry
( ” F i l t r
u w y p u k l a j a c y
p o l u d n i e ” ,EMBOSS SOUTH ) ;
glutAddMenuEntry
( ” F i l t r
u w y p u k l a j a c y
p o l u d n i o w y
z a c h o d ” ,EMBOSS SOUTH WEST ) ;
glutAddMenuEntry
( ” F i l t r
u w y p u k l a j a c y
z a c h o d ” ,EMBOSS WEST ) ;
glutAddMenuEntry
( ” F i l t r
u w y p u k l a j a c y
p o l n o c n y
z a c h o d ” ,EMBOSS NORTH WEST ) ;
glutAddMenuEntry
( ” F i l t r
u w y p u k l a j a c y
p o l n o c ” ,EMBOSS NORTH ) ;
glutAddMenuEntry
( ” F i l t r
u w y p u k l a j a c y
p o l n o c n y
wschod ” ,EMBOSS NORTH EAST ) ;
glutAddMenuEntry
( ” F i l t r
L a p l a c e ’ a LAPL1” , LAPLACIAN LAPL1 ) ;
glutAddMenuEntry
( ” F i l t r
L a p l a c e ’ a LAPL2” , LAPLACIAN LAPL2 ) ;
glutAddMenuEntry
( ” F i l t r
L a p l a c e ’ a LAPL3” , LAPLACIAN LAPL3 ) ;
glutAddMenuEntry
( ” F i l t r
L a p l a c e ’ a
s k o s n y ” ,LAPLACIAN DIAGONAL ) ;
#e n d i f
glutAddMenuEntry
( ” F i l t r
L a p l a c e ’ a poziomy ” ,LAPLACIAN HORIZONTAL ) ;
glutAddMenuEntry
( ” F i l t r
L a p l a c e ’ a pionowy ” ,LAPLACIAN VERTICAL ) ;
glutAddMenuEntry
( ” F i l t r
poziomy
S o b e l a ” ,SOBEL HORIZONTAL ) ;
glutAddMenuEntry
( ” F i l t r
pionowy
S o b e l a ” ,SOBEL VERTICAL ) ;
glutAddMenuEntry
( ” F i l t r
poziomy
P r e w i t t a ” ,PREWITT HORIZONTAL ) ;
glutAddMenuEntry
( ” F i l t r
pionowy
P r e w i t t a ” ,PREWITT VERTICAL ) ;
glutAddMenuEntry
( ” Brak ” ,NONE ) ;
//
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 ) ;
glutAddSubMenu
( ” F i l t r y ” , M e n u F i l t e r s ) ;
glutAddMenuEntry
( ” Z a p i s z ” , SAVE FILE ) ;
#i f d e f WIN32
glutAddMenuEntry
( ” W y j ś c i e ” , EXIT ) ;
#e l s e
glutAddMenuEntry
( ” W y j s c i e ” , EXIT ) ;
#e n d i f
//
o k r e ś l e n i e
p r z y c i s k u
m y s z k i
o b s ł u g u j ą c e j
menu
p o d r ę c z n e
g l u t A t t a c h M e n u
(GLUT RIGHT BUTTON ) ;
// P r e p a r e F i l t e r s
( ) ;
1. Bufor akumulacyjny
27
//
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
28
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