02 opengl 3 2 szablon aplikacji OpenGL

background image

OpenGL 3.2

Szablon aplikacji OpenGL

Janusz Ganczarski

www.januszg.hg.pl

background image

Wstęp

W tym odcinku kursu przygotujemy oraz omówimy szablon aplikacji OpenGL. Będą to

właściwie dwa szablony. Jeden przeznaczony dla systemów z Microsoft Windows, drugi dla systemów
posiadających X Window Serwer, czyli głównie UNIX/Linux.

Nasze przykładowe programy będą składały się z trzech zasadniczych części. Pierwszym

będzie zależny od platformy systemowej kod tworzący okno wraz z kontekstem OpenGL oraz
obsługujący interfejs użytkownika. Druga częśd obejmuje kod wykorzystujący bibliotekę OpenGL,
który napisany jest w sposób niezależny od systemu operacyjnego. Trzecią częśd stanowią biblioteki
pomocnicze najczęściej korzystające z OpenGL, które również napisane są w sposób przenośny.

Szablon aplikacji OpenGL dla Microsoft Windows

Tworzenie okna

Na początek kod źródłowy funkcji WinMain, której zadaniem jest utworzenie okna

programu. Nie opisujemy bliżej tego kodu, bowiem opis API WIN32 przekracza tematykę niniejszego
kursu, ale nie odbiega on od typowego kodu prezentowanego w dokumentacji MSDN.

#include

"resource.h"



//////////////////////////////////////////////////////////////////////
// funkcja main
//////////////////////////////////////////////////////////////////////

int

WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine,

int

nCmdShow )
{

// utworzenie i rejestracja okna

WNDCLASSEX winClass;
winClass.lpszClassName =

"MY_WINDOWS_CLASS"

;

winClass.cbSize =

sizeof

( WNDCLASSEX );

winClass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
winClass.lpfnWndProc = WindowProc;
winClass.hInstance = hInstance;
winClass.hIcon = LoadIcon( hInstance, (LPCTSTR)IDI_OPENGL_ICON );
winClass.hIconSm = LoadIcon( hInstance, (LPCTSTR)IDI_OPENGL_ICON );
winClass.hCursor = LoadCursor( NULL, IDC_ARROW );
winClass.hbrBackground = (HBRUSH)GetStockObject( WHITE_BRUSH );
winClass.lpszMenuName = NULL;
winClass.cbClsExtra = 0;
winClass.cbWndExtra = 0;

if

( !RegisterClassEx( &winClass ) )

return

FALSE;

HWND hWnd = NULL;
hWnd = CreateWindowEx( NULL,

"MY_WINDOWS_CLASS"

,

"OpenGL 3.2 - szablon OpenGL"

,

WS_OVERLAPPEDWINDOW | WS_VISIBLE, 0, 0, 500, 500, NULL, NULL, hInstance, NULL
);

if

( hWnd == NULL )

return

FALSE;


// przetwarzanie pętli komunikatów

MSG msg = { 0 };

while

( WM_QUIT != msg.message )

{

if

( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )

{
TranslateMessage( &msg );
DispatchMessage( &msg );
}

else

SendMessage( hWnd, WM_PAINT, 0, 0 );
}

// wyrejestrowania okna i zakończenie działania programu

UnregisterClass(

"MY_WINDOWS_CLASS"

, winClass.hInstance );

return

msg.wParam;

background image

}

Zasoby

Okno zawiera zasoby z ikoną z logiem biblioteki OpenGL. Plik nagłówkowy zasobów wygląda

następująco:

#ifndef

__RESOURCE_H__

#define

__RESOURCE_H__

#define

IDI_OPENGL_ICON 4001

#endif

// __RESOURCE_H__


A tak wygląda sam plik zasobów:

#include

"resource.h"

//////////////////////////////////////////////////////////////////////
// ikona OpenGL
//////////////////////////////////////////////////////////////////////

IDI_OPENGL_ICON ICON DISCARDABLE

"opengl.ico"

Funkcja przetwarzająca komunikaty

Poniżej znajduje się kod źródłowy funkcji okna w API WIN32, czyli funkcji przetwarzającej

komunikaty. Funkcja ta wykorzystuje dwie zmienne globalne hRC i hDC, deklaracje funkcji
korzystających z OpenGL oraz plik nagłówkowy „extension3.h” będący elementem biblioteki
pomocniczej extensions3, którą poznamy w dalszej części tego odcinka kursu.

#include

"extensions3.h"

//////////////////////////////////////////////////////////////////////
// deklaracje funkcji obsługujących renderning w OpenGL
//////////////////////////////////////////////////////////////////////

void

DisplayScene();

void

Reshape(

int

width,

int

height );

void

InitScene();

void

DeleteScene();

//////////////////////////////////////////////////////////////////////
// uchwyt kontekstu renderingu OpenGL
//////////////////////////////////////////////////////////////////////

HGLRC hRC3 = NULL;

//////////////////////////////////////////////////////////////////////
// uchwyt urządzenia
//////////////////////////////////////////////////////////////////////

HDC hDC = NULL;

//////////////////////////////////////////////////////////////////////
// funkcja okna
//////////////////////////////////////////////////////////////////////

LRESULT CALLBACK WindowProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{

// standardowy kontekst renderingu OpenGL

HGLRC hRC;

// przetwarzanie komunikatów

switch

(msg)

{

// utworzenie okna

case

WM_CREATE:

// utworzenie deskryptora pikseli

GLuint PixelFormat;
PIXELFORMATDESCRIPTOR pfd;
memset( &pfd, 0,

sizeof

( PIXELFORMATDESCRIPTOR ) );

pfd.nSize =

sizeof

( PIXELFORMATDESCRIPTOR );

pfd.nVersion = 1;

background image

pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 32;
pfd.cDepthBits = 24;

// utworzenie uchwytu urządzenia

hDC = GetDC( hWnd );
PixelFormat = ChoosePixelFormat( hDC, &pfd );
SetPixelFormat( hDC, PixelFormat, &pfd );

// utworzenie kontekstu renderingu OpenGL

hRC = wglCreateContext( hDC );
wglMakeCurrent( hDC, hRC );

// utworzenie kontekstu renderingu OpenGL 3.2

wglCreateContextAttribsARB =

reinterpret_cast

< PFNWGLCREATECONTEXTATTRIBSARBPROC > (

wglGetProcAddress(

"wglCreateContextAttribsARB"

) );

if

( wglCreateContextAttribsARB )

{

int

attribs[] =

{
WGL_CONTEXT_MAJOR_VERSION_ARB, 3,
WGL_CONTEXT_MINOR_VERSION_ARB, 2,
WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,
0
};
HGLRC hRC3 = wglCreateContextAttribsARB( hDC, hRC, attribs);
wglMakeCurrent( hDC, hRC3 );
wglDeleteContext( hRC );
hRC = hRC3;
}

else

{
MessageBox( NULL,

"Nie można utworzyć kontekstu OpenGL 3.2"

,

"Błąd"

, MB_OK |

MB_ICONEXCLAMATION );
PostQuitMessage( 0 );
}

// konfiguracja niezbędnych rozszerzeń

OpenGL30();

// inicjacja maszyny stanów i elementów sceny

InitScene();
InvalidateRect( hWnd, NULL, TRUE );

break

;


// usuwanie okna

case

WM_DESTROY:

wglMakeCurrent( hDC, NULL );
DeleteScene();
wglDeleteContext( hRC3 );
ReleaseDC( hWnd, hDC );
PostQuitMessage( 0 );

break

;


// zmiana rozmiaru okna

case

WM_SIZE:

Reshape( LOWORD( lParam ), HIWORD( lParam ) );
InvalidateRect( hWnd, NULL, TRUE );

break

;


// odrysowanie okna

case

WM_PAINT:

DisplayScene();
SwapBuffers( hDC );
ValidateRect( hWnd, NULL );

break

;


// automatyczne przetworzenie pozostałych komunikatów

default

:

return

DefWindowProc( hWnd, msg, wParam, lParam );

}

return

0L;

}

background image

Tworzenie okna

Strukturą opisującą zawartośd okna renderingu i bufora ramki OpenGL jest

PIXELFORMATDESCRIPTOR. Jej pełny opis znajduje się w MSDN, ale na nasze potrzeby wystarczy
wypełnienie tylko kilku jej pól. Pierwsze z nich to dwFlags zawierające rodzaj okna, a także
wskazujące na obsługę OpenGL i włączenie podwójnego buforowania:

pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;


Trzy pozostałe pola używane w naszym szablonie określają rodzaj danych przechowywanych w
buforze ramki OpenGL. Przyjęte przez nas dane wskazuą typowy dla wspólczesnych kart graficznych
format bufora ramki z 32-bitowym opisem koloru i 24-bitowym opisem głębi:

pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 32;
pfd.cDepthBits = 24;


W niektórych programach zawartośd bufora ramki będzie rozszerzana o inne informacje (np.

bufor szablonu). Operacje te będą odrębnie opisywane.

Następnymi etapami tworzenia okna jest wygenerowanie uchwyt urządzenia i kontekstu

renderingu OpenGL. Funkcje wglCreateContekst i wglMakeCurrent, jak wskazuje ich
prefiks, pochodzą z biblioteki WGL. Pierwsza funkcja tworzy kontekst, druga dokonuje jego aktywacji.

// utworzenie uchwytu urządzenia

hDC = GetDC( hWnd );
PixelFormat = ChoosePixelFormat( hDC, &pfd );
SetPixelFormat( hDC, PixelFormat, &pfd );

// utworzenie kontekstu renderingu OpenGL

hRC = wglCreateContext( hDC );
wglMakeCurrent( hDC, hRC );


Razem z wersją 3.0 biblioteki OpenGL został wprowadzony nowy rozbudowany kontekst. W

przypadku biblioteki WGL jego utworzenie wymaga użycia rozszerzenia WGL_ARB_create_context
lub WGL_ARB_create_context_profile. Specyfika budowy bibliotek dynamicznych obsługujących
OpenGL w systemach Microsoft Windows powoduje, że musimy pobierad wskaźniki funkcji obecnych
w rozszerzeniach. Dotyczy to niestety także funkcji z biblioteki OpenGL od wersji 1.2 wzwyż. Sam
wskaźnik wglCreateContextAttribsARB znajduje się w obsługującej ten mechanizm i
wspomnianej już wcześniej bibliotece extensions3.

// utworzenie kontekstu renderingu OpenGL 3.2

wglCreateContextAttribsARB =

reinterpret_cast

< PFNWGLCREATECONTEXTATTRIBSARBPROC > (

wglGetProcAddress(

"wglCreateContextAttribsARB"

) );


Po sprawdzeniu poprawności pobranego wskaźnika tworzymy nowy kontekst hRC3,

używając do tego celu „starego” kontekstu hRC. Koniecznośd tworzenia dwóch kontekstów jest
bezpośrednią konsekwencją pobierania wskaźników funkcji, która to czynnośd wymaga aktywnego
podstawowego kontekstu OpenGL. Tablica attribs opisuje parametry kontekstu i zawiera pary
liczb: parametr i jego wartośd. W naszym przypadku tworzony jest kontekst obsługujący bibliotekę
OpenGL 3.2 z wyłączoną obsługą przestarzałej funkcjonalności.

if

( wglCreateContextAttribsARB )

{

int

attribs[] =

{
WGL_CONTEXT_MAJOR_VERSION_ARB, 3,
WGL_CONTEXT_MINOR_VERSION_ARB, 2,
WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,
0
};

background image

HGLRC hRC3 = wglCreateContextAttribsARB( hDC, hRC, attribs );
wglMakeCurrent( hDC, hRC3 );
wglDeleteContext( hRC );
hRC = hRC3;
}

else

{
MessageBox( NULL,

"Nie można utworzyć kontekstu OpenGL 3.2"

,

"Błąd"

, MB_OK |

MB_ICONEXCLAMATION );
PostQuitMessage( 0 );
}


Alternatywnie od wersji 3.2 biblioteki OpenGL możemy wykorzystad profile. Interesujący nas

profil podstawowy, który nie zawiera funkcjonalności określonych jako przestarzałe, wymagałby
następującego zestawu atrybutów:

int

attribs[] =

{
WGL_CONTEXT_MAJOR_VERSION_ARB, 3,
WGL_CONTEXT_MINOR_VERSION_ARB, 2,
WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
0
};


W przypadku wyboru profilu kompatybilnego (tj. z dostępem do przestarzałej funkcjonalności

OpenGL) zamiast stałej WGL_CONTEXT_CORE_PROFILE_BIT_ARB trzeba zastosowad
WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB. Biblioteka WGL musi w takim
przypadku obsługiwad rozszerzenie WGL_ARB_create_context_profile.

Po utworzeniu kontekstu pozostaje jedynie pobranie wskaźników funkcji OpenGL 3.0 (szablon

nie używa funkcji z nowszych wersji), inicjacja naszej sceny oraz wymuszenie odrysowania okna.

// konfiguracja niezbędnych rozszerzeń

OpenGL30();

// inicjacja maszyny stanów i elementów sceny

InitScene();
InvalidateRect( hWnd, NULL, TRUE );

Usuwanie okna

Przy usuwaniu okna w pierwszej kolejności następuje usunięcie zasobów używanych przez

OpenGL, a następnie usuwamy sam kontekst OpenGL.

DeleteScene();
wglMakeCurrent( hDC, NULL );
wglDeleteContext( hRC3 );
ReleaseDC( hWnd, hDC );
PostQuitMessage( 0 );

Zmiana rozmiaru okna

Przy zmianie rozmiaru okna przekazujemy do funkcji Reshape rozmiary nowego okna, które

są dostępne jako parametry funkcji obsługującej komunikaty.

Reshape( LOWORD( lParam ), HIWORD( lParam ) );
InvalidateRect( hWnd, NULL, TRUE );

Odrysowanie okna

Odrysowanie okna sprowadza się do wywołania funkcji rysującej scenę OpenGL i zamiany

buforów koloru zawartych w buforze ramki.

background image

DisplayScene();
SwapBuffers( hDC );
ValidateRect( hWnd, NULL );

Szablon aplikacji OpenGL dla X Window Serwer

Przy tworzeniu szablonu aplikacji OpenGL dla X Window Serwer użyjemy najbardziej

podstawowej biblioteki Xlib oraz biblioteki pomocniczej Xpmlib (do obsługi ikony okna w formacie
XPM). Schemat budowy programu nie odbiega znacząco od szablonu aplikacji dla WIN32. W funkcji
main tworzymy okno, a w odrębnej funkcji okna przetwarzamy komunikaty skierowane do aplikacji
przez X Serwer.

Tworzenie okna

Tworzenie okna aplikacji podzielone jest na kilka etapów. W pierwszym tworzymy urządzenie

wyświetlające o odpowiednich parametrach (w przyszłych programach będziemy niekiedy te
parametry zmieniad). Później tworzymy kontekst renderingu OpenGL przy użyciu funkcji
glXCreateContextAttribsARB

z

rozszerzeo

GLX_ARB_create_context

i

GLX_ARB_create_context_profile, przy użyciu tablicy atrybutów attribs. Tablica attribs
opisuje parametry kontekstu i zawiera pary liczb: parametr i jego wartośd. W naszym przypadku
tworzony jest kontekst obsługujący bibliotekę OpenGL 3.2 z wyłączoną obsługą przestarzałej
funkcjonalności. Następnie tworzone jest okno i dodawana jego ikona zawarta w pliku „opengl.xpm”.
Cały kod tworzący okno z kontekstem renderingu OpenGL znajduje się poniżej.

#include

"extensions3.h"

#include

"opengl.xpm"

#include

<X11/Xlib.h>

#include

<X11/Xutil.h>

#include

<X11/keysym.h>

#include

<X11/xpm.h>

//////////////////////////////////////////////////////////////////////
// deklaracje funkcji obsługujących renderning w OpenGL
//////////////////////////////////////////////////////////////////////

void

DisplayScene();

void

Reshape(

int

width,

int

height );

void

InitScene();

void

DeleteScene();



// utworzenie urządzenia wyświetlającego

Display *display = XOpenDisplay( 0 );

int

attrList[] =

{
GLX_RGBA,
GLX_DOUBLEBUFFER,
GLX_RED_SIZE, 8,
GLX_GREEN_SIZE, 8,
GLX_BLUE_SIZE, 8,
GLX_DEPTH_SIZE, 24,
None
};
XVisualInfo *visual = glXChooseVisual( display, 0, attrList );

// utworzenie kontekstu renderingu OpenGL

int

nelements;

GLXFBConfig *fbc = glXChooseFBConfig( display, DefaultScreen( display ), 0, &nelements );

int

attribs[] =

{
GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
GLX_CONTEXT_MINOR_VERSION_ARB, 2,
GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,
0
};
GLXContext ctx = glXCreateContextAttribsARB( display, *fbc, 0,

true

, attribs );

background image

// utworzenie okna X Window

XSetWindowAttributes attr;
attr.colormap = XCreateColormap( display, RootWindow( display, visual -> screen ), visual ->
visual, AllocNone );
attr.border_pixel = 0;
attr.event_mask = ExposureMask | KeyPressMask | ButtonPressMask | ButtonReleaseMask |
PointerMotionMask | StructureNotifyMask;
Window window = XCreateWindow( display, RootWindow( display, visual -> screen ),
0, 0, 512, 512, 0, visual -> depth, InputOutput, visual -> visual, CWBorderPixel |
CWColormap | CWEventMask, &attr );
Atom wmDelete = XInternAtom( display,

"WM_DELETE_WINDOW"

,

true

);

XSetWMProtocols( display, window, &wmDelete, 1 );
XSetStandardProperties( display, window,

"OpenGL 3.2 - szablon OpenGL"

,

"OpenGL 3.2 - szablon

OpenGL"

, None, NULL, 0, NULL );

XMapRaised( display, window );
glXMakeCurrent( display, window, ctx );

// dodanie ikony okna

Pixmap icon, mask;
XpmCreatePixmapFromData( display, window, GLicon, &icon, &mask, NULL );
XWMHints winHints;
winHints.flags = IconPixmapHint;
winHints.icon_pixmap = icon;
winHints.icon_mask = mask;
XSetWMHints( display, window, &winHints );


Podobnie jak w przypadku aplikacji w systemie Windows od wersji 3.2 biblioteki OpenGL

możemy wykorzystad profile. Profil podstawowy wymagałby następującego zestawu atrybutów:

int

attribs[] =

{
GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
GLX_CONTEXT_MINOR_VERSION_ARB, 2,
GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB,
0
};


W

przypadku

wyboru

profilu

kompatybilnego,

zamiast

stałej

GLX_CONTEXT_CORE_PROFILE_BIT_ARB

trzeba

zastosowad

GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB. Biblioteka GLX musi w tym przypadku
obsługiwad rozszerzenie GLX_ARB_create_context_profile.

Po utworzeniu okna pozostaje jeszcze inicjacja maszyny stanów OpenGL. Zauważmy, że nie

musimy wcześniej pobierad wskaźników funkcji OpenGL:

// inicjacja maszyny stanów OpenGL

InitScene();

Przetwarzanie komunikatów X Serwera

Wywołanie funkcji przetwarzającej komunikaty X Serwera wykonywane jest bezpośrednio w

funkcji main programu:

// pętla przetwarzania komunikatów

WindowProc( display, window );


Popatrzmy zatem na samą funkcję okna. Zawiera ona nieskooczoną pętlę, którą przerywa

wystąpienie specjalnego komunikatu oznaczającego zamknięcie okna programu. Pozostałe elementy
wnętrza pętli są odpowiednikami przedstawionej wcześniej funkcji okna w WIN32. Jedyna zasadnicza
różnica polega na braku obsługi tworzenia i usuwania elementów sceny OpenGL, które wykonywane
są odpowiednio przed i po wywołaniem funkcji okna. W przyszłych programach poniższa funkcja
będzie w razie potrzeby rozbudowywana o kolejne elementy.

//////////////////////////////////////////////////////////////////////

background image

// funkcja okna
//////////////////////////////////////////////////////////////////////

void

WindowProc( Display *display, Window window )

{

// przetwarzanie komunikatów

bool

running =

true

;

while

( running )

{

while

( XPending( display ) > 0 )

{
XEvent

event

;

XNextEvent( display, &

event

);

switch

(

event

.type )

{

// zmiana rozmiaru okna

case

ConfigureNotify:

Reshape(

event

.xconfigure.width,

event

.xconfigure.height );

break

;


// zamknięcie okna

case

ClientMessage:

if

( *XGetAtomName( display,

event

.xclient.message_type ) ==

*

"WM_PROTOCOLS"

)

{
running =

false

;

}

break

;


// pominęcie pozostałych komunikatów

default

:

break

;

}
}

// odrysowanie okna

DisplayScene();
glXSwapBuffers( display, window );
}
}

Zakmnięcie okna i zakończenie programu

Kooczenie pracy programu wykonywane jest już po powrocie z funkcji okna i sprowadza się

do usunięcia elementów sceny OpenGL i kontekstu renderingu OpenGL. Na koocu zamykane jest
okno programu.

// zamknięcie okna

DeleteScene();
glXMakeCurrent( display, None, NULL );
glXDestroyContext( display, ctx );
XCloseDisplay( display );

// koniec programu

return

0;

Plik makefike

Przedstawimy jeszcze plik makefile służący do kompilacji szablonu programu. Zauważmy, że

wszystkie pliki bibliotek pomocniczych znajdują się w katalogu common.

PROJECT= szablon
SOURCES= szablon.cpp glx_main.cpp ../common/extensions3.cpp
OBJECTS= szablon.o glx_main.o extensions3.o
CC= g++

$(PROJECT): $(OBJECTS)

background image

$(CC) -I../common -O2 -g $(OBJECTS) -L/usr/X11R6/lib -lm -lGL -lXpm -lXxf86vm -o

$(PROJECT)

@echo Compilation Complete


$(OBJECTS): $(SOURCES)

@echo Compiling Sources

$(CC) -I../common -O2 -Wall -ansi -pedantic -g -c $(SOURCES)


clean:

@echo Deleting up $(OBJECTS) $(PROJECT)

rm -f *.o;rm $(PROJECT)

Biblioteka pomocnicza extensions3

Biblioteka pomocnicza extensions3 składa się z dwóch plików (extensions3.h i

extensions3.cpp) i przede wszystkim zawiera definicje wskaźników funkcji biblioteki OpenGL w wersji
3.0, 3.1 i 3.2. Wskaźniki te są niezbędne do działania programów w systemach Microsoft Windows. W
systemach z rodziny UNIX/Linux operacje te nie są niezbędne, ale biblioteka także jest
wykorzystywana.

Biblioteka korzysta z trzech podstawowych plików nagłówkowych: gl3.h, wglext.h i glxext.h

dostępnych na stronie domowej OpenGL pod adresem

http://www.opengl.org/registry/

.

Obsługa WGL i wskaźników funkcji w systemach Microsoft Windows

Początek pliku nagłówkowego biblioteki extensions3 w części obsługującej OpenGL i WGL w

systemach Microsoft Windows zawiera włączenie standardowych plików nagłówkowych:

#include

"gl3.h"

#include

"wglext.h"


Potem musimy ponownie włączyd plik gl3.h, ale w taki sposób aby uzyskad deklaracje tych

funkcji OpenGL z wersji 1.0 i 1.1, używanych także w wersji 3.0 - 3.2, do których nie musimy pobierad
wskaźników (o pobieraniu wskaźników funkcji wspominaliśmy już podczas opisu szablonu aplikacji
przy tworzeniu kontekstu OpenGL). Wprawdzie deklaracje te zawiera stary plik nagłówkowy
biblioteki OpenGL (gl.h) ale jego użycie nie jest zalecane, gdy nie korzystamy z przestarzałej
funkcjonalności OpenGL.

//////////////////////////////////////////////////////////////////////
// prototypy funkcji z OpenGL 1.0 i OpenGL 1.1
// (do tych funkcji nie są potrzebne wskaźniki)
//////////////////////////////////////////////////////////////////////

#ifndef

__gl_h_

#ifndef

__GL_H__

#ifdef

__cplusplus

extern

"C"

{

#endif

#undef

__gl3_h_

#define

GL3_PROTOTYPES

#undef

GL_VERSION_1_0

#undef

GL_VERSION_1_1

#include

"gl3.h"

#undef

GL3_PROTOTYPES

#ifdef

__cplusplus

}

#endif

background image

#endif
#endif


Potem następują kolejne definicje zmiennych globalnych - wskaźników funkcji pochodzących

z różnych wersji biblioteki OpenGL i jej rozszerzeo. Na początku znajduje się wskaźnik do funkcji
wglCreateContextAttribsARB którą używaliśmy przy tworzeniu kontekstu OpenGL. Z uwagi
na dużą objętośd tej części pliku prezentujemy początek definicji wskaźników i koocówkę pliku z
deklaracjami funkcji pobierającymi wskaźniki.

//////////////////////////////////////////////////////////////////////
// funkcja z rozszerzenia WGL_ARB_create_context
//////////////////////////////////////////////////////////////////////

extern

PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB;

//////////////////////////////////////////////////////////////////////
// funkcje z OpenGL 1.2
//////////////////////////////////////////////////////////////////////

extern

PFNGLBLENDCOLORPROC glBlendColor;

extern

PFNGLBLENDEQUATIONPROC glBlendEquation;

extern

PFNGLDRAWRANGEELEMENTSPROC glDrawRangeElements;

extern

PFNGLTEXIMAGE3DPROC glTexImage3D;

extern

PFNGLTEXSUBIMAGE3DPROC glTexSubImage3D;

extern

PFNGLCOPYTEXSUBIMAGE3DPROC glCopyTexSubImage3D;



//////////////////////////////////////////////////////////////////////
// pobranie wskaźników do funkcji z OpenGL 3.0
//////////////////////////////////////////////////////////////////////

bool

OpenGL30();

//////////////////////////////////////////////////////////////////////
// pobranie wskaźników do funkcji z OpenGL 3.1
//////////////////////////////////////////////////////////////////////

bool

OpenGL31();

//////////////////////////////////////////////////////////////////////
// pobranie wskaźników do funkcji z OpenGL 3.2
//////////////////////////////////////////////////////////////////////

bool

OpenGL32();


Plik źródłowy extensions3.cpp zawiera już właściwe definicje wskaźników funkcji oraz

implementacje funkcji (ponownie przedstawiamy jedynie wybrane fragmenty pliku):

//////////////////////////////////////////////////////////////////////
// wskaźnik funkcji pochodzącej z rozszerzenia WGL_ARB_create_context
//////////////////////////////////////////////////////////////////////

PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB = NULL;

//////////////////////////////////////////////////////////////////////
// wskaźniki funkcji pochodzących z OpenGL 1.2
//////////////////////////////////////////////////////////////////////

PFNGLBLENDCOLORPROC glBlendColor = NULL;
PFNGLBLENDEQUATIONPROC glBlendEquation = NULL;
PFNGLDRAWRANGEELEMENTSPROC glDrawRangeElements = NULL;
PFNGLTEXIMAGE3DPROC glTexImage3D = NULL;
PFNGLTEXSUBIMAGE3DPROC glTexSubImage3D = NULL;
PFNGLCOPYTEXSUBIMAGE3DPROC glCopyTexSubImage3D = NULL;


//////////////////////////////////////////////////////////////////////
// pobranie wskaźników do funkcji z OpenGL 3.0
//////////////////////////////////////////////////////////////////////

bool

OpenGL31()

{

// sprawdzenie numeru wersji

if

( OpenGLVersion() < 31 )

return

false

;


// pobranie wskaźników

background image

glDrawArraysInstanced =

reinterpret_cast

< PFNGLDRAWARRAYSINSTANCEDPROC > (

wglGetProcAddress(

"glDrawArraysInstanced"

) );

glDrawElementsInstanced =

reinterpret_cast

< PFNGLDRAWELEMENTSINSTANCEDPROC > (

wglGetProcAddress(

"glDrawElementsInstanced"

) );

glTexBuffer =

reinterpret_cast

< PFNGLTEXBUFFERPROC > ( wglGetProcAddress(

"glTexBuffer"

)

);
glPrimitiveRestartIndex =

reinterpret_cast

< PFNGLPRIMITIVERESTARTINDEXPROC > (

wglGetProcAddress(

"glPrimitiveRestartIndex"

) );


// pobranie wskaźników - rozszerzenie ARB_uniform_buffer_object

glGetUniformIndices =

reinterpret_cast

< PFNGLGETUNIFORMINDICESPROC > ( wglGetProcAddress(

"glGetUniformIndices"

) );

glGetActiveUniformsiv =

reinterpret_cast

< PFNGLGETACTIVEUNIFORMSIVPROC > (

wglGetProcAddress(

"glGetActiveUniformsiv"

) );

glGetActiveUniformName =

reinterpret_cast

< PFNGLGETACTIVEUNIFORMNAMEPROC > (

wglGetProcAddress(

"glGetActiveUniformName"

) );

glGetUniformBlockIndex =

reinterpret_cast

< PFNGLGETUNIFORMBLOCKINDEXPROC > (

wglGetProcAddress(

"glGetUniformBlockIndex"

) );

glGetActiveUniformBlockiv =

reinterpret_cast

< PFNGLGETACTIVEUNIFORMBLOCKIVPROC > (

wglGetProcAddress(

"glGetActiveUniformBlockiv"

) );

glGetActiveUniformBlockName =

reinterpret_cast

< PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC > (

wglGetProcAddress(

"glGetActiveUniformBlockName"

) );

glUniformBlockBinding =

reinterpret_cast

< PFNGLUNIFORMBLOCKBINDINGPROC > (

wglGetProcAddress(

"glUniformBlockBinding"

) );


// pobranie wskaźników - rozszerzenie ARB_copy_buffer

glCopyBufferSubData =

reinterpret_cast

< PFNGLCOPYBUFFERSUBDATAPROC > ( wglGetProcAddress(

"glCopyBufferSubData"

) );


// sukces

return

true

;

}


Funkcje OpenGLVersion i OpenGLExtension opisane są na koocu niniejszego punktu.

Obsługa OpenGL i GLX w systemach UNIX/Linux

Obsługa bibliotek OpenGL i GLX w systemach UNIX/Linux sprowadza się do odpowiedniego

włączenia trzech plików nagłówkowych. Standardowy plik gl3.h jest włączany z definicją
preprocesora GL3_PROTOTYPES gwarantującą bezpośredni dostęp do deklaracji funkcji OpenGL.
Później włączamy plik nagłówkowy biblioteki GLX (przyjmujemy, że znajduje się on w standardowym
miejscu). Na koniec włączamy plik glxext.h zawierających definicje rozszerzeo biblioteki GLX.
Zaprezentowane poniżej polecenia preprocesora zapewniają dostęp do deklaracji funkcji rozszerzeo,
niezależnie od tego jaka wersja tego pliku znajduje się w systemie (plik glxext.h jest włączany przez
plik glx.h).

#define

GL3_PROTOTYPES

#include

"gl3.h"

#undef

GL3_PROTOTYPES

#define

GL_GLEXT_LEGACY

#include

<GL/glx.h>

#undef

__glxext_h_

#undef

GLX_GLXEXT_VERSION

#undef

GLX_ARB_create_context

#define

GLX_GLXEXT_PROTOTYPES

#include

"glxext.h"

#undef

GLX_GLXEXT_PROTOTYPES

Pozostałe elementy biblioteki

Biblioteka extensions3 zawiera także trzy funkcje pomocnicze: pobierającą numer wersji

OpenGL i GLSL oraz sprawdzającą dostępnośd wybranego rozszerzenia. Poniżej prezentujemy ich
pełny kod źródłowy:

background image

//////////////////////////////////////////////////////////////////////
// pobranie numeru wersji biblioteki OpenGL
// numer wersji pomnożony przez 10
//////////////////////////////////////////////////////////////////////

int

OpenGLVersion()

{

int

major = 0, minor = 0;

glGetIntegerv( GL_MAJOR_VERSION, &major );
glGetIntegerv( GL_MINOR_VERSION, &minor );

return

10*major + minor;

}

//////////////////////////////////////////////////////////////////////
// sprawdzenie obsługi rozszerzenia biblioteki OpenGL
// extName - nazwa sprawdzanego rozszerzenia OpenGL
//////////////////////////////////////////////////////////////////////

bool

OpenGLExtension(

const

char

*extName )

{
GLint numExt;
glGetIntegerv( GL_NUM_EXTENSIONS, &numExt );

for

(

int

i = 0; i < numExt; i++ )

if

( std::string(

reinterpret_cast

<

const

char

* >( glGetStringi( GL_EXTENSIONS, i ) ) )

== std::string ( extName ) )

return

true

;

return

false

;

}

//////////////////////////////////////////////////////////////////////
// sprawdzenie wersji języka GLSL; numer wersji pomnożony przez 100
//////////////////////////////////////////////////////////////////////

int

GLSLVersion()

{

// pobranie numery wersji GLSL

std::stringstream version( std::stringstream::

in

| std::stringstream::

out

);

version <<

reinterpret_cast

<

const

char

* >( glGetString( GL_SHADING_LANGUAGE_VERSION ) );

if

( glGetError() != GL_NO_ERROR )

return

0;


// numer wersji pomnożony przez 100

int

major = 0, minor = 0;

char

dot

;

version >> major;

if

( version.fail() )

return

0;

version >>

dot

;

if

( version.fail() ||

dot

!=

'.'

)

return

0;

version >> minor;

if

( version.fail() )

return

0;

return

100*major + minor;

}


Teraz opiszemy krótko użyte w powyższych funkcjach elementy biblioteki OpenGL. Zmienne

stanu GL_MAJOR_VERSION i GL_MINOR_VERSION zawierają numer wersji i podwersji
implementacji OpenGL. Dwie użyte funkcje OpenGL:

const GLubyte *glGetString( GLenum name );
const GLubyte *glGetStringi( GLenum name, GLuint index );

zwracają bardziej rozbudowane informacje o bieżącej implementacji biblioteki OpenGL. Dane
zwracane przez funkcję glGetString zależą od wartości parametru name:

GL_VENDOR

- autor implementacji OpenGL,

GL_RENDERER

- nazwa urządzenia renderującego, np. karty graficznej,

GL_VERSION

- numer wersji implementacji OpenGL w formacie: <wersja>.<podwersja> lub

<wersja>.<podwersja>.<wydanie> oraz opcjonalnie po pojedynczej spacji informacja o
producencie biblioteki,

GL_SHADING_LANGUAGE_VERSION

– numer wersji GLSL - języka cieniowania OpenGL,

zwracany w formacie takim samym jak dla parametru GL_VERSION.

Zauważmy, że OpenGL zawiera dwa mechanizmy pozwalające na sprawdzenie numeru wersji i
podwersji implementacji biblioteki.

background image

Funkcja glGetStringi zwraca informację o rozszerzeniach obsługiwanych przez

implementację OpenGL. Nazwa każdego obsługiwanego rozszerzenia podawana jest odrębnie
poprzez wskazanie numeru indeksu w parametrze index, a łączną ilośd rozszerzeo zawiera zmienna
stanu GL_NUM_EXTENSIONS. Jedyną dopuszczalną wartością parametru name funkcji
glGetStringi jest stała GL_EXTENSIONS.

Obie prezentowane funkcje zwracają ciągi znaków w kodowaniu UTF-8 zakooczone znakiem

NULL (zerem).

Podstawowe elementy programu w OpenGL

Przedstawione poniżej cztery funkcje będą stałym elementem każdego programu z kursu

biblioteki OpenGL, chod oczywiście różna będzie ich zawartośd. Poznamy także funkcje biblioteki
OpenGL wykorzystane w szablonie.

Inicjacja maszyny stanu OpenGL

To pierwszy element programu korzystającego z biblioteki OpenGL. Z założenia wykonywany

jest jednokrotnie i obejmuje tylko te elementy ustawieo OpenGL, które nie będą się zmieniały (lub
będą zmieniane sporadycznie) w trakcie działania programu. W szablonie umieściliśmy wywołanie
tylko jednej funkcji OpenGL

void glClearColor( GLclampf red, GLclampf green, GLclampf blue,
GLclampf alpha );

która ustala składowe RGBA koloru czyszczącego bieżącego bufora koloru, co w programie
przedkłada się na kolor tła okna.

//////////////////////////////////////////////////////////////////////
// inicjalizacja stałych elementów maszyny stanu OpenGL
//////////////////////////////////////////////////////////////////////

void

InitScene()

{

// kolor tła - zawartość bufora koloru

glClearColor( 1.0f, 1.0f, 1.0f, 1.0f );
}

Generowanie sceny 3D

W szablonie programu OpenGL nie są generowane żadne elementy sceny. Wykonywane jest

tylko czyszczenie bieżącego bufora koloru i wymuszane jest wykonanie wszystkich wywołanych
poleceo OpenGL. Efektem będzie puste okno o kolorze tła określonym w poprzednio opisanej funkcji
szablonu.

//////////////////////////////////////////////////////////////////////
// funkcja generująca scenę 3D
//////////////////////////////////////////////////////////////////////

void

DisplayScene()

{

// czyszczenie bufora koloru

glClear( GL_COLOR_BUFFER_BIT );

// skierowanie poleceń do wykonania

glFlush();
}


Pierwsza z użytych funkcji:


void glClear( GLbitfield mask );

background image

zawiera maskę bitową z wartościami wskazującymi, które bufory są czyszczone. Wartości te wynoszą:
GL_COLOR_BUFFER_BIT, GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT i wskazują
odpowiednio aktualnie aktywne do zapisu bufory koloru, bufor głębokości i bufor szablonu. Stałe te
mogą byd łączone za pomocą operatora |.

Druga funkcja:


void glFlush( void );

określa, że wszystkie polecenia OpenGL, które zostały wcześniej wywołane muszą zostad wykonane w
skooczonym czasie. Działanie to dobrze określa słowo wymiatanie będące bezpośrednim
tłumaczeniem angielskiej nazwy funkcji. Podobną rolę wykonuje polecenie

void glFinish( void );

które wymusza wykonanie wszystkich poprzednich poleceo OpenGL. W odróżnieniu od funkcji
glFlush, glFinish nie zakooczy się dopóki wszystkie efekty wcześniej wydanych poleceo dla
zmiennych stanu klienta i serwera OpenGL oraz bufora ramki nie zostaną w pełni zrealizowane.

Zmiana wielkości okna

Typowym zdarzeniem, które występuje w programach okienkowych jest zmiana rozmiaru

okna. W przypadku biblioteki OpenGL obsługa takiego zdarzenia wymaga nie tylko odrysowania
okna. Niezbędne jest także podjęcie decyzji o modyfikacji (lub nie) wielkości obszaru renderingu, czyli
przestrzeni okna wykorzystywanej przez OpenGL.

Obszar renderingu określa zastosowana w szablonie funkcja:


void glViewport( GLint x, GLint y, GLsizei width, GLsizei height );

której parametry oznaczają:

x

, y - współrzędne lewego dolnego narożnika obszaru renderingu względem lewego dolnego

narożnika okna,

width

- szerokośd okna renderingu,

height

- wysokośd okna renderingu.

Początkowo obszar renderingu zajmuje całe okno udostępnione dla aplikacji OpenGL. W szablonie
programu glViewport określa za każdym razem obszar renderingu tak, aby obejmował on całe
okno.

//////////////////////////////////////////////////////////////////////
// zmiana wielkości okna
//////////////////////////////////////////////////////////////////////

void

Reshape(

int

width,

int

height )

{

// obszar renderingu - całe okno

glViewport( 0, 0, width, height );
}


Wspomnijmy jeszcze, że parametry funkcji Reshape określają odpowiednio nową szerokośd

i wysokośd okna i są określane na podstawie danych przekazywanych przez system okienkowy.

Usunięcie elementów sceny 3D

Ostatnia funkcja szablnu jest odpowiedzialna za usunięcie elementów sceny OpenGL, które

nie zostały wcześniej zniszczone. W szczególności mogą to byd elementy tworzone w funkcji
InitScene. Ponieważ w szabolnie nie mamy takich elementów, wnętrze funkcji pozostaje puste.

//////////////////////////////////////////////////////////////////////
// usunięcie obiektów OpenGL

background image

//////////////////////////////////////////////////////////////////////

void

DeleteScene()

{
}

Wygląd okna programu

Poniżej znajdują się zrzuty ekranu przedstawiające okna programu szablonu aplikacji OpenGL

w obu systemach operacyjnych wykorzystywanych w kursie.

Rysunek 1 Okno szablonu OpenGL (WIN32)

Rysunek 2 Okno szablonu OpenGL (Linux)


Document Outline


Wyszukiwarka

Podobne podstrony:
Smarty Szablony w aplikacjach PHP smarty
informatyka smarty szablony w aplikacjach php h hayder ebook
Smarty Szablony w aplikacjach PHP
Smarty Szablony w aplikacjach PHP smarty
Smarty Szablony w aplikacjach PHP 2
Smarty Szablony w aplikacjach PHP
Smarty Szablony w aplikacjach PHP smarty
Smarty Szablony w aplikacjach PHP smarty
Smarty Szablony w aplikacjach PHP
grafika-okno2, Studia PK, Inne - serwer Nexus, Dydaktyka, GK, OpenGL-lab1, AplikacjaWindows
opengl bufor szablonowy
Grafika komputerowa i OpenGL
Zadania z OpenGL do wykonania
opengl nurbs
opengl test zaslaniania
OpenGL Leksykon kieszonkowy opgllk
opengl ksiega eksperta wydanie iii UZFSAM5UH2NWETWCPGG2PS3RHAX75LU5XCNZJJI
OpenGL tutorial

więcej podobnych podstron