Janusz Ganczarski
OpenGL
Obiekty buforowe
Spis treści
Spis treści . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1
1. Obiekty buforowe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1
Generowanie identyfikatorów obiektów . . . . . . . . . . . . . . . . .
1
Dowiązanie obiektów buforowych . . . . . . . . . . . . . . . . . . . .
1
Usuwanie obiektów . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2
Ładowanie danych do obiektu . . . . . . . . . . . . . . . . . . . . . .
2
Pobieranie właściwości obiektu . . . . . . . . . . . . . . . . . . . . .
5
. . . . . . . . . . . . . . . . . . . . . . .
7
Obiekty buforowe tablic wierzchołków . . . . . . . . . . . . . . . . .
7
Obiekty buforowe indeksowych tablic wierzchołków . . . . . . . . . .
7
Obiekty buforowe odczytu (rozpakowania) danych pikseli . . . . . .
8
1.10. Obiekty buforowe zapisu (spakowania) danych pikseli . . . . . . . .
8
. . . . . . . . . . . . . . . . . . . . . . . . .
8
1.11.1. Plik vbo.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . .
10
1.11.2. Plik pbo.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . .
19
Literatura . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
26
1. Obiekty buforowe
Obecne karty graficzne posiadają bardzo duże ilości pamięci. Jedynie
stosunkowo niewielka część z tej pamięci przeznaczona jest na bufor ram-
ki. Pozostałą pamięć mogą wykorzystywać tekstury (mechanizm obiektów
tekstur) lub wprowadzone w wersji 1.5 biblioteki OpenGL obiekty buforowe
wierzchołków VBO (ang. vertex buffer object), wcześniej dostępne w rozsze-
rzeniu ARB vertex buffer object. W wersji 2.1 biblioteki dodano obsługę
obiektów buforowych pikseli PBO (ang. pixel buffer object), które wcześniej
obsługiwały rozszerzenia ARB pixel buffer object i EXT pixel buffer -
object. Obiekty buforowe PBO i VBO korzystają z tego samego interfejsu,
funkcjonalnością zbliżonego do mechanizmów obiektów tekstur.
1.1. Generowanie identyfikatorów obiektów
Utworzenie wskazanej w parametrze n ilości unikatowych identyfikatorów
(nazw) obiektów buforowych realizuje funkcja:
void glGenBuffers (GLsizei n,
GLuint *buffers)
Numery identyfikatorów zwracane sa w tablicy wskazywanej w parame-
trze buffers. Oczywiście program musi zapewnić odpowiednią ilość miejsca
w tablicy. Identyfikator o wartości zero nie jest związany z żadnym obiektem
buforowym.
Sprawdzenie czy wskazany identyfikator jest identyfikatorem obiektu bu-
forowego umożliwia funkcja:
GLboolean glIsBuffer (GLuint buffer)
która zwraca stosowne wartości logiczne (GL TRUE lub GL FALSE).
1.2. Dowiązanie obiektów buforowych
Utworzony identyfikator trzeba dowiązać do obiektu buforowego wywo-
łując funkcję:
void glBindBuffer (GLenum target,
GLuint buffer)
której parametr buffer zawiera unikatowy identyfikator obiektu, a para-
metr target określa rodzaj obiektu buforowanego. Dostępne są następujące
rodzaje obiektów buforowych:
— GL ARRAY BUFFER - obiekt buforowy tablic wierzchołków,
— GL ELEMENT ARRAY BUFFER - obiekt buforowy indeksowych tablic wierz-
chołków,
1. Obiekty buforowe
2
— GL PIXEL UNPACK BUFFER - obiekt buforowy odczytu (rozpakowania) da-
nych pikseli,
— GL PIXEL PACK BUFFER - obiekt buforowy zapisu (spakowania) danych
pikseli.
Pierwsze dwa rodzaje obiektów buforowych należą do grupy obiektów
buforowych wierzchołków (VBO), dwa pozostałe to obiekty buforowe pikseli
(PBO).
Pierwsze wywołanie funkcji glBindBuffer tworzy obiekt buforowy, a na-
stępne wywołania służą do przełączania się pomiędzy wybranymi obiektami.
Opisane dalej operacje na obiektach buforowych wykonywane są zawsze na
bieżącym obiekcie, wybranym przy użyciu funkcji glBindBuffer.
1.3. Usuwanie obiektów
Usuwanie wybranej grupy obiektów buforowych realizuje funkcja:
void glDeleteBuffers (GLsizei n,
const GLuint *buffers)
Parametr n określa ilość usuwanych obiektów buforowych, których identyfi-
katowy zawiera tablica buffers.
1.4. Ładowanie danych do obiektu
Ładowanie danych do obiektu buforowego można zrealizować na dwa
sposoby. Pierwszy polega na skorzystaniu z tradycyjnego modelu aplikacji
OpenGL, tj. kopiowaniu danych do obiektu bufora z tablicy (lub innej struk-
tury danych) zawartej w pamięci operacyjnej komputera. Taki model łado-
wania danych wykorzystują obiekty tekstur. Druga metoda korzysta z tzw.
odwzorowania obiektu buforowego (ang. mapping buffer object) i pozwala na
bezpośrednie operowanie na pamięci obiektu.
Zauważmy, że pierwsza z wymienionych metod wymaga zarezerwowania
odpowiedniej ilości pamięci operacyjnej komputera, choć może to być alo-
kacja tymczasowa (dynamiczna). Drugi sposób nie wymaga przydzielania
dodatkowych zasobów systemowych.
Niezależnie od przyjętej metody ładowanie danych do obiektu buforowe-
go wymaga wywołania funkcji:
void glBufferData (GLenum target,
GLsizeiptr size,
const GLvoid *data,
GLenum usage)
1. Obiekty buforowe
3
Parametr target określa rodzaj obiektu buforowego, którego dane two-
rzymy. Możliwe są cztery opisane wcześniej wartości: GL ARRAY BUFFER, GL -
ELEMENT ARRAY BUFFER, GL PIXEL UNPACK BUFFER i GL PIXEL PACK BUFFER.
Drugi parametr size wskazuje rozmiar danych bufora obiektu buforo-
wego. Wielkość ta jest określana w BMU - podstawowe jednostkach maszy-
nowych (ang. basic machine units), czyli w bajtach. Jedynym sposobem na
zmianę wielkości bufora jest usunięcie obiektu i ponowne jego utworzenie
z żądanym rozmiarem.
Kolejny parametr data zawiera wskaźnik na dane ładowane do obiektu
buforowego. Podanie wartości różnej od NULL powoduje skopiowanie danych
z bufora zawartego w pamięci operacyjnego do bufora zawartego w pamię-
ci karty graficznej. Natomiast w przypadku podania wartości NULL pamięć
bufora obiektu buforowego jest jedynie rezerwowana, a jej zawartość jest
nieokreślona. Możliwość tę wykorzystujemy w szczególności w przypadku,
gdy zamierzamy bezpośrednio operować na pamięci obiektu buforowego.
Ostatni parametr usage zawiera wskazówkę dla biblioteki OpenGL do-
tyczącą przewidywanej metody dostępu do danych zawartych w obiekcie
buforowym. Możliwe są następujące wartości:
— GL STREAM DRAW - jednokrotne lub sporadyczne pobieranie danych i przez
większość czasu wykorzystanie ich do zapisu do obiektu OpenGL,
— GL STREAM READ - jednokrotne lub sporadyczne pobieranie danych i przez
większość czasu wykorzystanie ich do odczytu z obiektu OpenGL,
— GL STREAM COPY - jednokrotne lub sporadyczne pobieranie danych i przez
większość czasu wykorzystanie ich zarówno do odczytu z obiektu OpenGL
jak i do zapisu,
— GL STATIC DRAW - jednokrotne lub sporadyczne pobieranie danych i wie-
lokrotne ich wykorzystanie do zapisu do obiektu OpenGL,
— GL STATIC READ - jednokrotne lub sporadyczne pobieranie danych i wie-
lokrotne ich wykorzystanie do odczytu z obiektu OpenGL,
— GL STATIC COPY - jednokrotne lub sporadyczne pobieranie danych i wie-
lokrotne wykorzystanie ich zarówno do odczytu z obiektu OpenGL jak i
do zapisu,
— GL DYNAMIC DRAW - wielokrotne pobieranie danych i wielokrotne ich wy-
korzystanie do zapisu do obiektu OpenGL,
— GL DYNAMIC READ - wielokrotne pobieranie danych i wielokrotne ich wy-
korzystanie do odczytu z obiektu OpenGL,
— GL DYNAMIC COPY - wielokrotne pobieranie danych i wielokrotne wyko-
rzystanie ich zarówno do odczytu z obiektu OpenGL jak i do zapisu.
Parametr usage jest jedynie wskazówką umożliwiającą optymalizację im-
plementacji biblioteki OpenGL. Wybrana metoda dostępu do danych obiek-
tu nie ogranicza wykonywanych na nim operacji.
1. Obiekty buforowe
4
W przypadku braku możliwości przydzielenia wymaganej ilości pamięci
funkcja glBufferData generuje błąd GL OUT OF MEMORY.
Zmianę całości lub części danych zawartych w obiekcie buforowym umoż-
liwia funkcja:
void glBufferSubData (GLenum target,
GLintptr offset,
GLsizeiptr size,
const GLvoid *data)
Parametr target określa oczywiście rodzaj obiektu buforowego i przyj-
muje jedną z czterech znanych już wartości. Zakres modyfikowanych danych
określają parametry offset i size, gdzie offset jest numerem pierwszego
zmienianego elementu danych bufora obiektu (numeracja elementów zaczyna
się od zera i jest prowadzona w bajtach), a size to ilość modyfikowanych ele-
mentów bufora. Nowe dane zawarte są w tablicy wskazywanej w parametrze
data.
Wspomniana wcześniej metoda odwzorowania obiektu buforowego wy-
maga uzyskania wskaźnika do danych obiektu buforowego. Wymaga to wy-
wołania funkcji:
GLvoid *glMapBuffer (GLenum target,
GLenum access)
której parametr target określa rodzaj obiektu buforowego i przyjmuje znane
już wartości: GL ARRAY BUFFER, GL ELEMENT ARRAY BUFFER, GL PIXEL UN-
PACK BUFFER i GL PIXEL PACK BUFFER.
Drugi parametr access wskazuje do jakich operacji będzie wykorzystany
pobierany wskaźnik na dane obiektu buforowego:
— GL READ ONLY - odczyt danych,
— GL WRITE ONLY - zapis danych,
— GL READ WRITE - odczyt i zapis danych.
Wykorzystanie wskaźnika niezgodnie z planowanym przeznaczeniem nie po-
woduje wprawdzie zgłoszenia błędu przez bibliotekę OpenGL, ale efekt dzia-
łania jest nieokreślony.
Jeżeli odwzorowywany obiekt jest już w tym trybie funkcja glMapBuffer
zwraca wartość NULL oraz dodatkowo generowany jest błąd GL INVALID -
OPERATION.
Gdy obiekt buforowy znajduje się w trybie nie można na min wykony-
wać innych operacji niż związanych z pobieraniem (lub ładowaniem) danych.
W szczególności wywołanie funkcji glBufferSubData spowoduje wystąpie-
nie błędu GL INVALID OPERATION. Efekt działania innych operacji związa-
nych z obiektem buforowym jest nieokreślony. Zezwolenie na takie zachowa-
1. Obiekty buforowe
5
nie obiektów buforowych specyfikacji biblioteki OpenGL tłumaczy możliwo-
ścią uzyskania wyższej wydajności.
Po zakończeniu operacji w trybie odwzorowania trzeba zwolnić pobrany
wskaźnik do danych obiektu buforowego wywołując funkcję:
GLboolean glUnmapBuffer (GLenum target)
której parametr target określa oczywiście rodzaj obiektu buforowego.
W przypadku poprawnego wyjścia obiektu buforowego z trybu odwzoro-
wania funkcja glUnmapBuffer zwraca wartość GL TRUE. Wartość GL FALSE
zostanie zwrócona, gdy obiekt nie znajduje się w trybie odwzorowania oraz
w każdym przypadku wystąpienia zdarzenia wpływającego na zmianę sta-
nu pamięci karty graficznej. Takim zdarzeniami mogą być w szczególności:
zmiana rozdzielczości ekranu, przejście karty graficznej w tryb oszczędza-
nia energii. Wystąpienie takich sytuacji wymaga ponownego załadowania
danych do pamięci bufora obiektu.
1.5. Pobieranie właściwości obiektu
Pobranie właściwości bieżącego obiektu buforowego umożliwia funkcja:
void glGetBufferParameteriv (GLenum target,
GLenum pname,
GLint *params)
Parametr target określa rodzaj obiektu buforowego i przyjmuje jedną
z dobrze znanych wartości: GL ARRAY BUFFER, GL ELEMENT ARRAY BUFFER,
GL PIXEL UNPACK BUFFER i GL PIXEL PACK BUFFER.
Drugi parametr pname zawiera rodzaj pobieranej właściwości obiektu
buforowego, który zostaje zwrócony w parametrze params. Możliwe są na-
stępujące wartości:
— GL BUFFER SIZE - rozmiar danych obiektu (w bajtach),
— GL BUFFER USAGE - wskazówka dostępu do danych obiektu,
— GL BUFFER ACCESS - przeznaczenie wskaźnika do danych obiektu,
— GL BUFFER MAPPED- znacznik czy obiekt znajduje się w trybie odwzoro-
wania.
Jeżeli obiekt buforowy znajduje się w trybie odwzorowania możliwe jest
pobranie wskaźnika na dane obiektu. Wymaga to wywołania funkcji:
void glGetBufferPointerv (GLenum target,
GLenum pname,
GLvoid **params)
której parametr target określa rodzaj obiektu buforowego (cztery znane
wartości: GL ARRAY BUFFER, GL ELEMENT ARRAY BUFFER, GL PIXEL UNPACK -
BUFFER i GL PIXEL PACK BUFFER), a drugi parametr pname może przyjąć
1. Obiekty buforowe
6
par
am
etr
w
artość
p
o
c
zątk
o
w
a
dop
usz
czalne
w
artości
GL
BUFFE
R
SIZE
0
ni
e
u
jem
n
a
lic
zba
całk
o
wita
GL
BUFFE
R
USA
GE
GL
ST
A
TIC
DRA
W
GL
STRE
AM
DRA
W,
GL
STRE
AM
READ,
GL
STRE
AM
COPY,
G
L
ST
A
TIC
DRA
W,
GL
ST
A
TIC
READ,
G
L
ST
A
TIC
COPY,
GL
D
YNAMIC
DRA
W,
GL
D
YNAMIC
READ,
GL
D
YNAMIC
COPY
GL
BUFFE
R
A
CC
E
SS
GL
READ
WRITE
GL
READ
ONL
Y,
G
L
WRITE
ONL
Y
,
GL
READ
WRITE
GL
BUFFE
R
MAP
PE
D
GL
F
ALS
E
GL
TR
UE
,
GL
F
ALS
E
GL
BUFFE
R
MAP
PO
INT
E
R
NULL
ws
k
aźnik
T
ab
e
la
1:
Zes
ta
wie
n
ie
właśc
iw
oś
ci
obi
e
któ
w
buf
oro
wyc
h
1. Obiekty buforowe
7
jedynie wartość GL BUFFER MAP POINTER, oznaczającą właśnie pobieranie
wskaźnika na dane obiektu. Wskaźnik jest zwracany w ostatnim parametrze
params.
W przypadku, gdy wybrany obiekt buforowy nie jest w trybie odwzoro-
wania w parametrze params zostanie zwrócona wartość NULL.
Zestawienie wszystkich właściwości obiektów buforowych wraz z dopusz-
czalnymi wartościami oraz wartościami początkowymi przedstawia tabela 1.
1.6. Pobieranie danych obiektu
Biblioteka OpenGL umożliwia pobranie wybranych danych zawartych
w obiekcie buforowym przy użyciu funkcji:
void glGetBufferSubData (GLenum target,
GLintptr offset,
GLsizeiptr size,
GLvoid *data)
której parametr target określa rodzaj obiektu buforowego, a parametry
offset i size wyznaczają odpowiednio pierwszy pobierany element oraz
ilość kopiowanych elementów. Numeracja elementów obiektu buforowego za-
czyna się od zera i jest wyznaczana w bajtach. Bufor, do którego kopiowane
są wybrane elementy, wskazywany jest w parametrze data.
1.7. Obiekty buforowe tablic wierzchołków
Dane przechowywane w obiektach buforowych tablic wierzchołków są
zgodne z formatem używanym w tablicach wierzchołków. Umożliwia to bez-
pośrednie korzystanie z tablic wierzchołków przy użyciu funkcji: glArray-
Element, glDrawArrays, glMultiDrawArrays, glDrawElements, glDraw-
RangeElements i glMultiDrawElements. Jedyna różnica polega na sposo-
bie dostarczenia danych tablic wierzchołków do funkcji: glVertexPointer,
glNormalPointer, glColorPointer, glSecondaryColorPointer, glIndex-
Pointer, glEdgeFlagPointer, glFogCoordPointer i glTexCoordPointer.
Zamiast wskaźnika na dane tablicy (parametr pointer powyższych funkcji)
należy podać położenie początku danych w bieżącym obiekcie buforowym
tablicy wierzchołków. W praktyce jeden obiekt buforowy tablic wierzchołków
może zatem służyć do przechowywania danych wielu tablic wierzchołków.
1.8. Obiekty buforowe indeksowych tablic wierzchołków
Obiekty buforowe indeksowych tablic wierzchołków są bezpośrednio
przystosowane do współpracy z funkcjami: glDrawElements, glDrawRange-
Elements i glMultiDrawElements obsługującymi indeksowe tablice wierz-
1. Obiekty buforowe
8
chołków. Jedyna różnica polega na sposobie dostarczenia danych tablicy in-
deksów. Zamiast wskaźnika na dane tablicy z indeksami (parametr indices
dwóch pierwszych funkcji) podaje się położenie początku danych w bieżącym
obiekcie buforowym indeksowej tablicy wierzchołków. W przypadku funkcji
glMultiDrawElements parametr indices zawiera adresy położenia danych
kolejnych tablic indeksów w bieżącym obiekcie buforowym.
1.9. Obiekty buforowe odczytu (rozpakowania) danych pikseli
Obiekty buforowe odczytu danych pikseli można wykorzystać jako źró-
dło danych pikseli dla następujących funkcji biblioteki OpenGL: glBitmap,
glColorSubTable, glColorTable, glCompressedTexImage1D, glCompres-
sedTexImage2D, glCompressedTexImage3D, glCompressedTexSubImage1D,
glCompressedTexSubImage2D, glCompressedTexSubImage3D, glConvolu-
tionFilter1D, glConvolutionFilter2D, glDrawPixels, glPixelMapfv,
glPixelMapuiv, glPixelMapusv, glPolygonStipple, glSeparableFilter2D,
glTexImage1D, glTexImage2D, glTexImage3D, glTexSubImage1D, glTexSub-
Image2D i glTexSubImage3D.
W parametrach powyższych funkcji wskazujących źródło danych pikseli
zamiast adresu tablicy z danymi wskazujemy położenie danych w obiekcie
buforowym.
1.10. Obiekty buforowe zapisu (spakowania) danych pikseli
Obiekty buforowe zapisu danych pikseli można wykorzystać jako bufor
danych pikseli dla następujących funkcji biblioteki OpenGL: glGetCompres-
sedTexImage, glGetConvolutionFilter, glGetHistogram, glGetMinmax,
glGetPixelMapfv, glGetPixelMapuiv, glGetPixelMapusv, glGetPolygon-
Stipple, glGetSeparableFilter, glGetTexImage i glReadPixels.
W parametrach powyższych funkcji wskazujących tablicę na dane pikseli
zamiast adresu tablicy na dane wskazujemy położenie danych w obiekcie
buforowym.
1.11. Programy przykładowe
Pierwszy program przykładowy (plik vbo.cpp) jest kolejnym rozwinię-
ciem programu służącego wcześniej do testów list wyświetlania oraz ta-
blic wierzchołków. W porównaniu do poprzednika trzykrotnie zwiększono
ilość wyświetlanych prymitywów. Zastosowanie obiektów buforowych wy-
raźnie zwiększyło szybkość wyświetlania prymitywów, przy czym największy
wzrost szybkości dotyczy wyświetlania punktów (23%), nieco mniej zyskują
odcinki (8%) i trójkąty (6%). Pamiętajmy jednak, że program faktycznie
testuje jedynie szybkość renderingu, a VBO pozwala także na optymalizację
1. Obiekty buforowe
9
zarządzania pamięcią, co umożliwia jeszcze większe przyspieszenia działania
programów.
W programie zastosowano obie opisane wyżej metody ładowania danych
do obiektu buforowego, jednak nie został wyeliminowany bufor zawarty
w pamięci operacyjnej z uwagi na konieczność jego obecności do porów-
nawczego testu tablic wierzchołków. Dane tablicy ze składowymi kolorów
wierzchołków prymitywów i tablicy ze współrzędnymi tych wierzchołków
przechowywane są w dwóch odrębnych obiektach buforowych, choć możliwe
jest także wykorzystanie jednego obiektu do przechowywania danych obu
tablic.
Wyniki wszystkich testów dostępnych w programie przedstawiono na
Rysunek 1. Program VBO - punkty z obiektami buforowymi
1. Obiekty buforowe
10
Rysunek 2. Program VBO - punkty z tablicami wierzchołków
1.11.1. Plik vbo.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 r i n g . h>
#i n c l u d e < s t d i o . h>
#i n c l u d e <t 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 G e n B u f f e r s
PFNGLGENBUFFERSPROC g l G e n B u f f e r s = NULL ;
//
w s k a ź n i k
na
f u n k c j ę
g l B i n d B u f f e r
1. Obiekty buforowe
11
Rysunek 3. Program VBO - odcinki z obiektami buforowymi
PFNGLBINDBUFFERPROC g l B i n d B u f f e r = NULL ;
//
w s k a ź n i k
na
f u n k c j ę
g l B u f f e r D a t a
PFNGLBUFFERDATAPROC g l B u f f e r D a t a = NULL ;
//
w s k a ź n i k
na
f u n k c j ę
g l M a p B u f f e r
PFNGLMAPBUFFERPROC g l M a p B u f f e r = NULL ;
//
w s k a ź n i k
na
f u n k c j ę
g l U n m a p B u f f e r
PFNGLUNMAPBUFFERPROC g l U n m a p B u f f e r = NULL ;
//
s t a ł e
do
o b s ł u g i
menu
p o d r ę c z n e g o
enum
{
//
r o d z a j
t e s t u
POINTS VBO ,
//
p u n k t y
z VBO
POINTS VA ,
//
p u n k t y
z
t a b l i c a m i
w i e r z c h o ł k ó w
LINES VBO ,
//
o d c i n k i
z VBO
LINES VA ,
//
o d c i n k i
z
t a b l i c a m i
w i e r z c h o ł k ó w
TRIANGLES VBO,
//
t r ó j k ą t y
z VBO
TRIANGLES VA ,
//
t r ó j k ą t y
z
t a b l i c a m i
w i e r z c h o ł k ó w
1. Obiekty buforowe
12
Rysunek 4. Program VBO - odcinki z tablicami wierzchołków
//
o b s z a r
r e n d e r i n g 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
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. Obiekty buforowe
13
Rysunek 5. Program VBO - trójkąty z obiektami buforowymi
const GLdouble
n e a r = 3 . 0 ;
const GLdouble
f a r = 7 . 0 ;
//
r o d z a j
t e s t u − d o m y ś l n i e
p u n k t y
z
t a b l i c a m i
w i e r z c h o ł k ó w
i n t
t e s t = POINTS VA ;
//
i d e n t y f i k a t o r y
o b i e k t ó w
b u f o r o w y c h
w i e r z c h o ł k ó w
GLuint
v b o i d
[ 2 ] ;
//
i l o ś ć
g e n e r o w a n y c h
w s p ó ł r z ę d n y c h
p r y m i t y w ó w
const
i n t
s i z e = 9 0 0 0 0 ;
//
w s p ó ł r z ę d n e
p r y m i t y w ó w
G L f l o a t
v e r t e x x y z
[ 3 ∗ s i z e ] ;
//
k o l o r y
p r y m i t y w ó w
G L f l o a t
c o l o r r g b
[ 3 ∗ s i z e ] ;
//
l i c z n i k
ramek
( FPS )
i n t
f r a m e s = 0 ;
1. Obiekty buforowe
14
Rysunek 6. Program VBO - trójkąty z tablicami wierzchołków
//
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
void
D r a w S t r i n g
( G L f l o a t
x ,
G L f l o a t
y ,
char ∗ s t r i n g )
{
//
p o ł o ż e n i e
n a p i s u
g l R a s t e r P o s 2 f
( 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
( )
{
1. Obiekty buforowe
15
//
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 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 ) ;
//
w ł ą c z e n i e
t e s t u
b u f o r a
g ł ę b o k o ś c i
g l E n a b l e
(GL DEPTH TEST ) ;
//
w y k o n a n i e
w y b r a n e g o
t e s t u
switch
( t e s t )
{
//
p r y m i t y w y w VBO
c a s e POINTS VBO :
c a s e LINES VBO :
c a s e TRIANGLES VBO :
//
d o w i ą z a n i e
p i e r w s z e g o
o b i e k t u
b u f o r o w e g o
g l B i n d B u f f e r
(GL ARRAY BUFFER, v b o i d [ 0 ] ) ;
//
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 y
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 , 0 , 0 ) ;
//
d o w i ą z a n i e
d r u g i e g o
o b i e k t u
b u f o r o w e g o
g l B i n d B u f f e r
(GL ARRAY BUFFER, v b o i d [ 1 ] ) ;
//
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 y
w i e r z c h o ł k ó w
g l C o l o r P o i n t e r
( 3 , GL FLOAT , 0 , 0 ) ;
//
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 ) ;
g l E n a b l e C l i e n t S t a t e
(GL COLOR ARRAY ) ;
//
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
i f
( t e s t == POINTS VBO)
g l D r a w A r r a y s
( GL POINTS , 0 , s i z e ) ;
e l s e
i f
( t e s t == LINES VBO )
g l D r a w A r r a y s
( GL LINES , 0 , s i z e ) ;
e l s e
g l D r a w A r r a y s
( GL TRIANGLES , 0 , s i z e ) ;
//
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 COLOR ARRAY ) ;
g l D i s a b l e C l i e n t S t a t e
(GL VERTEX ARRAY ) ;
//
w y ł ą c z e n i e
d o w i ą z a n i a
o b i e k t ó w
b u f o r o w y c h
g l B i n d B u f f e r
(GL ARRAY BUFFER , 0 ) ;
break ;
//
p r y m i t y w y
z
t a b l i c a m i
w i e r z c h o ł k ó w
c a s e POINTS VA :
c a s e LINES VA :
c a s e TRIANGLES VA :
//
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, 0 , v e r t e x x y z ) ;
g l C o l o r P o i n t e r
( 3 , GL FLOAT, 0 , c o l o r r g b ) ;
//
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 ) ;
g l E n a b l e C l i e n t S t a t e
(GL COLOR ARRAY ) ;
//
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
i f
( t e s t == POINTS VA )
g l D r a w A r r a y s
( GL POINTS , 0 , s i z e ) ;
e l s e
1. Obiekty buforowe
16
i f
( t e s t == LINES VA )
g l D r a w A r r a y s
( GL LINES , 0 , s i z e ) ;
e l s e
g l D r a w A r r a y s
( GL TRIANGLES , 0 , s i z e ) ;
//
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 ) ;
g l D i s a b l e C l i e n t S t a t e
(GL COLOR ARRAY ) ;
break ;
} ;
//
t r z e b a
o d p o w i e d n i o
p r z e k s z t a ł c i ć
u k ł a d
w s p ó ł r z ę d n y c h
//
a b y
n a p i s
z n a j d o w a ł
s i ę
na
s a m e j
” g ó r z e ”
b r y ł y
o b c i n a n i a
g l L o a d I d e n t i t y
( ) ;
g l T r a n s l a t e f
( 0 , 0 , − n e a 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 )
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
( l e f t , bottom , 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
( ) ;
//
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
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 y b ó r
r o d z a j u
t e s t u
c a s e POINTS VBO :
c a s e POINTS VA :
c a s e LINES VBO :
c a s e LINES VA :
c a s e TRIANGLES VBO :
c a s e TRIANGLES VA :
t e s t = v a l u e ;
1. Obiekty buforowe
17
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
o b i e k t ó w
b u f o r o w y c h
w i e r z c h o ł k ó w
void GenerateVBO
( )
{
//
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 ) ) ;
//
g e n e r o w a n i e
p o ł o ż e n i a
p u n k t ó w
( w i e r z c h o ł k ó w )
f i g u r
o r a z
i c h
k o l o r ó w
f o r
( i n t
i = 0 ;
i < s i z e ;
i ++)
{
v e r t e x x y z
[ 3 ∗ i +0] = ( r a n d ( )
/
( f l o a t )RAND MAX)
∗ 4 − 2 ;
v e r t e x x y z
[ 3 ∗ i +1] = ( r a n d ( )
/
( f l o a t )RAND MAX)
∗ 4 − 2 ;
v e r t e x x y z
[ 3 ∗ i +2] = ( r a n d ( )
/
( f l o a t )RAND MAX)
∗ 4 − 2 ;
c o l o r r g b
[ 3 ∗ i +0] = ( r a n d ( )
/
( f l o a t )RAND MAX ) ;
c o l o r r g b
[ 3 ∗ i +1] = ( r a n d ( )
/
( f l o a t )RAND MAX ) ;
c o l o r r g b
[ 3 ∗ i +2] = ( r a n d ( )
/
( f l o a t )RAND MAX ) ;
}
//
w y g e n e r o w a n i e
d w ó c h
i d e n t y f i k a t o r ó w
o b i e k t ó w
b u f o r o w y c h
g l G e n B u f f e r s
( 2 , v b o i d ) ;
//
d o w i ą z a n i e
p i e r w s z e g o
o b i e k t u
b u f o r o w e g o
g l B i n d B u f f e r
(GL ARRAY BUFFER, v b o i d [ 0 ] ) ;
//
z a ł a d o w a n i e
d a n y c h
p i e r w s z e g o
o b i e k t u
b u f o r o w e g o
g l B u f f e r D a t a
(GL ARRAY BUFFER, s i z e o f
( G L f l o a t ) ∗ s i z e ∗ 3 , v e r t e x x y z , GL STATIC DRAW ) ;
//
d o w i ą z a n i e
d r u g i e g o
o b i e k t u
b u f o r o w e g o
g l B i n d B u f f e r
(GL ARRAY BUFFER, v b o i d [ 1 ] ) ;
//
u t w o r z e n i e
d a n y c h
d r u g i e g o
o b i e k t u
b u f o r o w e g o
g l B u f f e r D a t a
(GL ARRAY BUFFER, s i z e o f
( G L f l o a t ) ∗ s i z e ∗ 3 ,NULL, GL STATIC DRAW ) ;
//
p o b r a n i e
w s k a ź n i k a
na
d a n e
d r u g i e g o
o b i e k t u
b u f o r o w e g o
GLvoid ∗ b u f = g l M a p B u f f e r
(GL ARRAY BUFFER, GL WRITE ONLY ) ;
//
s k o p i o w a n i e
d a n y c h
do
d r u g i e g o
o b i e k t u
b u f o r o w e g o
memcpy ( b u f , c o l o r r g b , s i z e o f
( G L f l o a t ) ∗ s i z e ∗ 3 ) ;
//
z w o l n i e n i e
w s k a ź n i k a
na
d a n e
d r u g i e g o
o b i e k t u
b u f o r o w e g o
i f
( g l U n m a p B u f f e r
(GL ARRAY BUFFER) == GL FALSE )
{
p r i n t f
( ” N i e p o p r a w n e
o d w z o r o w a n i e
o b i e k t u
b u f o r o w e g o \n ” ) ;
e x i t
( 0 ) ;
}
//
w y ł ą c z e n i e
d o w i ą z a n i a
o b i e k t ó w
b u f o r o w y c h
g l B i n d B u f f e r
(GL ARRAY BUFFER , 0 ) ;
}
//
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 ;
1. Obiekty buforowe
18
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 . 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 B u f f e r s = (PFNGLGENBUFFERSPROC) w g l G e t P r o c A d d r e s s
( ” g l G e n B u f f e r s ” ) ;
g l B i n d B u f f e r = (PFNGLBINDBUFFERPROC) w g l G e t P r o c A d d r e s s
( ” g l B i n d B u f f e r ” ) ;
g l B u f f e r D a t a = (PFNGLBUFFERDATAPROC) w g l G e t P r o c A d d r e s s
( ” g l B u f f e r D a t a ” ) ;
g l M a p B u f f e r = (PFNGLMAPBUFFERPROC) w g l G e t P r o c A d d r e s s
( ” g l M a p B u f f e r ” ) ;
g l U n m a p B u f f e r = (PFNGLUNMAPBUFFERPROC) w g l G e t P r o c A d d r e s s
( ” g l U n m a p B u f f e r ” ) ;
}
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 v e r t e x b u f f e r o b j e c t
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 v e r t e x b u f f e r o b j e c t ” ) )
{
//
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
r o z s z e r z e n i a
A R B v e r t e x b u f f e r o b j e c t
g l G e n B u f f e r s = (PFNGLGENBUFFERSPROC) w g l G e t P r o c A d d r e s s
( ” g l G e n B u f f e r s A R B ” ) ;
g l B i n d B u f f e r = (PFNGLBINDBUFFERPROC) w g l G e t P r o c A d d r e s s
( ” g l B i n d B u f f e r A R B ” ) ;
g l B u f f e r D a t a = (PFNGLBUFFERDATAPROC) w g l G e t P r o c A d d r e s s
( ” g l B u f f e r D a t a A R B ” ) ;
g l M a p B u f f e r = (PFNGLMAPBUFFERPROC) w g l G e t P r o c A d d r e s s
( ” glMapBufferARB ” ) ;
g l U n m a p B u f f e r = (PFNGLUNMAPBUFFERPROC) w g l G e t P r o c A d d r e s s
( ” glUnmapBufferARB ” ) ;
}
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 v e r t e x b u f f e r o b j e c t ! \ 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
g l u t C r e a t e W i n d o w
( ”VBO” ) ;
//
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 ) ;
//
u t w o r z e n i e
podmenu − T e s t
i n t
MenuTest = g l u t C r e a t e M e n u
( Menu ) ;
#i f d e f WIN32
glutAddMenuEntry
( ” Punkty
z VBO” ,POINTS VBO ) ;
glutAddMenuEntry
( ” Punkty
z
t a b l i c a m i
w i e r z c h o ł k ó w ” , POINTS VA ) ;
glutAddMenuEntry
( ” O d c i n k i
z VBO” , LINES VBO ) ;
glutAddMenuEntry
( ” O d c i n k i
z
t a b l i c a m i
w i e r z c h o ł k ó w ” , LINES VA ) ;
glutAddMenuEntry
( ” T r ó j k ą t y
z VBO” ,TRIANGLES VBO ) ;
glutAddMenuEntry
( ” T r ó j k ą t y
z
t a b l i c a m i
w i e r z c h o ł k ó w ” ,TRIANGLES VA ) ;
#e l s e
glutAddMenuEntry
( ” Punkty
z VBO” ,POINTS VBO ) ;
glutAddMenuEntry
( ” Punkty
z
t a b l i c a m i
w i e r z c h o l k o w ” , POINTS VA ) ;
glutAddMenuEntry
( ” O d c i n k i
z VBO” , LINES VBO ) ;
glutAddMenuEntry
( ” O d c i n k i
z
t a b l i c a m i
w i e r z c h o l k o w ” , LINES VA ) ;
glutAddMenuEntry
( ” T r o j k a t y
z VBO” ,TRIANGLES VBO ) ;
glutAddMenuEntry
( ” T r o j k a t y
z
t a b l i c a m i
w i e r z c h o l k o w ” ,TRIANGLES VA ) ;
#e n d i f
1. Obiekty buforowe
19
//
u t w o r z e n i e
podmenu − A s p e k t
o b r a z u
i n t
MenuAspect = g l u t C r e a t e M e n u
( Menu ) ;
#i f d e f WIN32
glutAddMenuEntry
( ” A s p e k t
o b r a z u − c a ł e
okno ” ,FULL WINDOW ) ;
#e l s e
glutAddMenuEntry
( ” A s p e k t
o b r a z u − c a l e
okno ” ,FULL WINDOW ) ;
#e n d i f
glutAddMenuEntry
( ” A s p e k t
o b r a z u
1 : 1 ” , ASPECT 1 1 ) ;
// menu g ł ó w n e
g l u t C r e a t e M e n u
( Menu ) ;
glutAddSubMenu
( ” T e s t ” , MenuTest ) ;
glutAddSubMenu
( ” A s p e k t
o b r a z u ” , MenuAspect ) ;
#i f d e f WIN32
glutAddMenuEntry
( ” W y j ś c i e ” , EXIT ) ;
#e l s e
glutAddMenuEntry
( ” W y j s c i e ” , EXIT ) ;
#e n d i f
//
o k r e ś l e n i e
p r z y c i s k u
m y s z k i
o b s ł u g u j ą c e g o
menu
p o d r ę c z n e
g l u t A t t a c h M e n u
(GLUT RIGHT BUTTON ) ;
//
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
o b i e k t ó w
b u f o r o w y c h
w i e r z c h o ł k ó w
GenerateVBO
( ) ;
//
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 ;
}
Drugi przykładowy program (plik pbo.cpp) testuje obiekty buforowe
pikseli przy renderingu tekstur. Wyniki uzyskane na komputerze Autora nie
wskazują na przewagę szybkości w renderingu tekstur przy pomocy obiektów
buforowych, ale też nie odnotowano spadku tej szybkości. Prawdopodobnie
użycie większej ilości tekstur wykazałoby przewagę obiektów buforowych,
która ma bezpośredni związek z większą przepustowością pamięci karty gra-
ficznej w stosunku do przepustowości pamięci operacyjnej komputera.
Przykładowy efekt działania programu przedstawiono na rysunku 7.
1.11.2. Plik pbo.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 r i n g . h>
#i n c l u d e < s t d i o . h>
#i n c l u d e <t i m e . h>
#i n c l u d e
” t a r g a . h ”
#i n c l u d e
” c o l o r s . h ”
1. Obiekty buforowe
20
Rysunek 7. Program PBO - test wyświetlania tekstury „Lena”
//
w s k a ź n i k
na
f u n k c j ę
g l G e n B u f f e r s
PFNGLGENBUFFERSPROC g l G e n B u f f e r s = NULL ;
//
w s k a ź n i k
na
f u n k c j ę
g l B i n d B u f f e r
PFNGLBINDBUFFERPROC g l B i n d B u f f e r = NULL ;
//
w s k a ź n i k
na
f u n k c j ę
g l B u f f e r D a t a
PFNGLBUFFERDATAPROC g l B u f f e r D a t a = NULL ;
//
w s k a ź n i k
na
f u n k c j ę
g l G e t B u f f e r P a r a m e t e r i v
PFNGLGETBUFFERPARAMETERIVPROC g l G e t B u f f e r P a r a m e t e r i 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
{
TEST PBO ,
//
t e s t
z PBO
TEST WPBO,
//
t e s t
b e z PBO
EXIT
//
w y j ś c i e
} ;
1. Obiekty buforowe
21
//
r o d z a j
t e s t u − d o m y ś l n i e
p u n k t y
b e z PBO
i n t
t e s t = TEST WPBO ;
//
i d e n t y f i k a t o r
o b i e k t u
b u f o r o w e g o
p i k s e l i
GLuint
p b o i d ;
//
i d e n t y f i k a t o r
o b i e k t u
t e k s t u r y
GLuint
t e x t u r e i d ;
//
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
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
//
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
void
D r a w S t r i n g
( G L f l o a t
x ,
G L f l o a t
y ,
char ∗ s t r i n g )
{
//
p o ł o ż e n i e
n a p i s u
g l R a s t e r P o s 2 f
( 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
( ) ;
//
w s p ó ł r z ę d n e
p o ł o ż e n i a
p r o s t o k ą t a
z
t e k s t u r ą
f l o a t
x = g l u t G e t
(GLUT WINDOW WIDTH)
∗ r a n d
( )
/
( f l o a t )RAND MAX;
f l o a t
y = 20 + g l u t G e t
(GLUT WINDOW HEIGHT)
∗ r a n d
( )
/
( f l o a t )RAND MAX;
//
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 ) ;
//
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 NEAREST ) ;
//
f i l t r
p o w i ę k 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 MAG FILTER , GL NEAREST ) ;
//
w y ś w i e t l e n i e
t e k s t u r y
z
d a n y c h
z
p a m i ę c i
o p e r a c y j n e j
i f
( t e s t == TEST WPBO)
{
//
t e k s t u r a
2D
glTexImage2D
(GL TEXTURE 2D , 0 , GL RGB, width , h e i g h t , 0 , f o r m a t , t y p e , p i x e l s ) ;
//
c z w o r o k ą t
g l C o l o r 3 f v
( White ) ;
g l B e g i n
(GL QUADS ) ;
g l T e x C o o r d 2 f
( 0 . 0 , 0 . 0 ) ;
g l V e r t e x 2 f
( x , y ) ;
g l T e x C o o r d 2 f
( 1 . 0 , 0 . 0 ) ;
g l V e r t e x 2 f
( x +64 , y ) ;
g l T e x C o o r d 2 f
( 1 . 0 , 1 . 0 ) ;
1. Obiekty buforowe
22
g l V e r t e x 2 f
( x +64 , y + 6 4 ) ;
g l T e x C o o r d 2 f
( 0 . 0 , 1 . 0 ) ;
g l V e r t e x 2 f
( x , y + 6 4 ) ;
g l E n d
( ) ;
}
//
w y ś w i e t l e n i e
t e k s t u r y
z
d a n y c h
o b i e k t u
b u f o r o w e g o
p i k s e l i
i f
( t e s t == TEST PBO)
{
//
d o w i ą z a n i e
o b i e k t u
b u f o r o w e g o
p i k s e l i
g l B i n d B u f f e r
(GL PIXEL UNPACK BUFFER , p b o i d ) ;
//
t e k s t u r a
2D
glTexImage2D
(GL TEXTURE 2D , 0 , GL RGB, width , h e i g h t , 0 , f o r m a t , t y p e , NULL ) ;
//
c z w o r o k ą t
g l C o l o r 3 f v
( White ) ;
g l B e g i n
(GL QUADS ) ;
g l T e x C o o r d 2 f
( 0 . 0 , 0 . 0 ) ;
g l V e r t e x 2 f
( x , y ) ;
g l T e x C o o r d 2 f
( 1 . 0 , 0 . 0 ) ;
g l V e r t e x 2 f
( x +64 , y ) ;
g l T e x C o o r d 2 f
( 1 . 0 , 1 . 0 ) ;
g l V e r t e x 2 f
( x +64 , y + 6 4 ) ;
g l T e x C o o r d 2 f
( 0 . 0 , 1 . 0 ) ;
g l V e r t e x 2 f
( x , y + 6 4 ) ;
g l E n d
( ) ;
//
w y ł ą c z e n i e
o b i e k t u
b u f o r o w a n i a
p i k s e l i
p o p r z e z
//
d o w i ą z a n i e
o b i e k t u
o b i e k t u
o
i d e n t y f i k a t o r z e
0
g l B i n d B u f f e r
(GL PIXEL UNPACK BUFFER , 0 ) ;
}
//
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 ) ;
//
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 == 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 ) ) ) ;
}
//
z a m a z a n i e
p o p r z e d n i e g o
n a p i s u
g l C o l o r 3 f v
( White ) ;
g l R e c t f
( 0 . 0 , 0 . 0 , 2 0 0 . 0 , 2 0 . 0 ) ;
//
n a r y s o w a n i e
n a p i s u
g l C o l o r 3 f v
( B l a c k ) ;
D r a w S t r i n g
( 1 , 2 , 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
( ) ;
//
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 ) ;
//
k o l o r
t ł a − z a w a r t o ś ć
b u f o r a
k o l o r u
g l C l e a r C o l o r
( 1 . 0 , 1 . 0 , 1 . 0 , 1 . 0 ) ;
//
c z y s z c z e n i e
b u f o r a
k o l o r u
g l C l e a r
( GL COLOR BUFFER BIT ) ;
1. Obiekty buforowe
23
//
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 )
{
//
w y b ó r
r o d z a j u
t e s t u
c a s e TEST PBO :
c a s e TEST WPBO :
t e s t = v a l u e ;
g l C l e a r
( GL COLOR BUFFER BIT ) ;
g l u t P o s t R e d i s p l a y
( ) ;
break ;
//
w y j ś c i e
c a s e EXIT :
e x i t
( 0 ) ;
}
}
//
u t w o r z e n i e
o b i e k t ó w
b u f o r o w y c h
p i k s e l i
void GeneratePBO
( )
{
//
w y 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
o b i e k t u
b u f o r o w e g o
g l G e n B u f f e r s
( 1 , & p b o i d ) ;
//
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 ) ;
//
d o w i ą z a n i e
o b i e k t u
b u f o r o w e g o
g l B i n d B u f f e r
(GL PIXEL UNPACK BUFFER , p b o i d ) ;
//
o b l i c z e n i e
r o z m i a r u
b u f o r a
na
d a n e
GLint
s i z e = w i d t h ∗ h e i g h t ;
i f
( f o r m a t == GL BGRA)
s i z e
∗= 4 ;
e l s e
i f
( f o r m a t == GL BGR)
s i z e
∗=3;
//
z a ł a d o w a n i e
d a n y c h
o b i e k t u
b u f o r o w e g o
g l B u f f e r D a t a
(GL PIXEL UNPACK BUFFER , s i z e , p i x e l s , GL STREAM DRAW ) ;
//
p o b r a n i e
r o z m i a r u
d a n y c h
o b i e k t u
b u f o r o w e g o
GLint
b u f s i z e ;
g l G e t B u f f e r P a r a m e t e r i v
(GL PIXEL UNPACK BUFFER , GL BUFFER SIZE,& b u f s i z e ) ;
//
s p r a w d z e n i e
p o p r a w n o ś c i
r o z m i a r u
d a n y c h
o b i e k t u
b u f o r o w e g o
i f
( b u f s i z e
!=
s i z e )
{
p r i n t f
( ” Niepoprawny
z a p i s
danych do
o b i e k t u
b u f o r o w e g o \n ” ) ;
e x i t
( 0 ) ;
}
//
w y ł ą c z e n i e
d o w i ą z a n i a
o b i e k t u
b u f o r o w e g o
g l B i n d B u f f e r
(GL PIXEL UNPACK BUFFER , 0 ) ;
//
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 ) ) ;
}
//
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
1. Obiekty buforowe
24
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
2 . 1
i f
( 1 0 ∗ m a j o r + m i n o r >= 2 1 )
{
//
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
2 . 1
( a
w ł a ś c i w i e
1 . 5 )
g l G e n B u f f e r s = (PFNGLGENBUFFERSPROC) w g l G e t P r o c A d d r e s s
( ” g l G e n B u f f e r s ” ) ;
g l B i n d B u f f e r = (PFNGLBINDBUFFERPROC) w g l G e t P r o c A d d r e s s
( ” g l B i n d B u f f e r ” ) ;
g l B u f f e r D a t a = (PFNGLBUFFERDATAPROC) w g l G e t P r o c A d d r e s s
( ” g l B u f f e r D a t a ” ) ;
g l G e t B u f f e r P a r a m e t e r i v = (PFNGLGETBUFFERPARAMETERIVPROC)
w g l G e t P r o c A d d r e s s
( ” g l G e t B u f f e r P a r a m e t e r i 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 i x e l b u f f e r o b j e c t
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 i x e l b u f f e r o b j e c t ” ) )
{
//
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
r o z s z e r z e n i a
A R B p i x e l b u f f e r o b j e c t
// a
w ł a c i w i e
A R B v e r t e x b u f f e r o b j e c t
g l G e n B u f f e r s = (PFNGLGENBUFFERSPROC) w g l G e t P r o c A d d r e s s
( ” g l G e n B u f f e r s A R B ” ) ;
g l B i n d B u f f e r = (PFNGLBINDBUFFERPROC) w g l G e t P r o c A d d r e s s
( ” g l B i n d B u f f e r A R B ” ) ;
g l B u f f e r D a t a = (PFNGLBUFFERDATAPROC) w g l G e t P r o c A d d r e s s
( ” g l B u f f e r D a t a A R B ” ) ;
g l G e t B u f f e r P a r a m e t e r i v = (PFNGLGETBUFFERPARAMETERIVPROC)
w g l G e t P r o c A d d r e s s
( ” g l G e t B u f f e r P a r a m e t e r i v 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
A R B v e r t e x b u f f e r o b j e c t ! \ n ” ) ;
e x i t
( 0 ) ;
}
}
//
w c z y t a n i e
p l i k u
g r a f i c z n e g o
w f o r m a c i e TARGA
void LoadTARGA ( i n t
a r g c ,
char ∗ a r g v [ ] )
{
//
s p r a w d z e n i e
c z y
j e s t
p a r a m e t r
i f
( a r g c < 2 )
{
p r i n t f
( ” Brak nazwy
p l i k u TARGA\n ” ) ;
e x i t
( 1 ) ;
}
//
o d c z y t
p l i k u TARGA i
e w e n t u a l n y
k o m u n i k a t
o
b ł ę d z i e
i f
( ! l o a d t a r g a
( a r g v [ 1 ] , width , h e i g h t , f o r m a t , t y p e , p i x e l s ) )
{
#i f d e f WIN32
p r i n t f
( ” Błąd
o d c z y t u
l u b
b ł ę d n y
f o r m a t
p l i k u : %s \n ” , a r g v [ 1 ] ) ;
#e l s e
p r i n t f
( ” B l ad
o d c z y t u
l u b
b l e d n y
f o r m a t
p l i k u : %s \n ” , a r g v [ 1 ] ) ;
#e n d i f
e x i t
( 1 ) ;
}
}
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 ) ;
//
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
( ”PBO” ) ;
//
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 ) ;
1. Obiekty buforowe
25
//
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 ) ;
// 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 PBO” ,TEST PBO ) ;
glutAddMenuEntry
( ” T e s t
b e z PBO” ,TEST WPBO ) ;
glutAddMenuEntry
( ” W y j ś c i e ” , EXIT ) ;
#e l s e
glutAddMenuEntry
( ” W y j s c i e ” , EXIT ) ;
#e n d i f
//
o k r e ś l e n i e
p r z y c i s k u
m y s z k i
o b s ł u g u j ą c e g o
menu
p o d r ę c z n e
g l u t A t t a c h M e n u
(GLUT RIGHT BUTTON ) ;
//
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
o b i e k t ó w
b u f o r o w y c h
p i k s e l i
GeneratePBO
( ) ;
//
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
26
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,