Für jede OpenGL-Anwendung müssen wir zunächst einen Render- und einen Gerätekontext anlegen. Der Gerätekontext (Device Context, DC) stellt die Schnittstelle zur Grafikkarte dar und ist damit für die Verarbeitung aller OpenGL-Aufrufe verantwortlich. Eine OpenGL-Anwendung hat jedoch keinen direkten Zugriff auf den Gerätekontext, sondern ist über einen Renderkontext mit diesem verbunden. Im Zuge dessen speichert der Renderkontext alle benötigten Informationen (Bildschirmauflösung, Farbtiefe, Tiefenpuffer-Genauigkeit, usw.), damit die 3D-Szene korrekt dargestellt werden kann. Soll nun ein Renderkontext mit einem Gerätekontext verbunden werden, kommt die wglMakeCurrent()-Funktion zum Einsatz:
// Renderkontext mit Gerätekontext verbinden:
wglMakeCurrent(g_DeviceContextHandle,g_OpenGLRenderContextHandle);
wglMakeCurrent(g_DeviceContextHandle,g_OpenGLRenderContextHandle);
Hinweis:
Für eine OpenGL-Anwendung lassen sich selbstverständlich auch mehrere Renderkontexte erstellen. Müssen beispielsweise zur Laufzeit Texturen oder 3D-Modelle nachgeladen werden, dann bietet sich die Verwendung eines zweiten Renderkontexts an, der im Rahmen eines Loader-Threads zum Einsatz kommt. Wichtig ist jedoch, dass beide Kontexte die erzeugten Objekte (Texturen, Vertexbuffer, Indexbuffer, usw.) miteinander teilen. Zuständig hierfür ist die wglShareLists()-Funktion:
wglShareLists(g_OpenGLRenderContextHandle,
g_OpenGLRenderContextHandle_Loader_Thread);
g_OpenGLRenderContextHandle_Loader_Thread);
Kommen wir nun zur Deklaration von Render- und Gerätekontext. Beide Variablen werden global verwendet, genau wie die Handles der zugrunde liegenden Windows-Anwendung:
// Rendering Context (RC):
HGLRC g_OpenGLRenderContextHandle = NULL;
// Device (Geräte) Context (DC):
HDC g_DeviceContextHandle = NULL;
// Handle der Windows Anwendung:
HWND g_MainWindowHandle = NULL;
// Handle auf die Instanz der Windows Anwendung:
HINSTANCE g_ApplicationInstanceHandle = NULL;
HGLRC g_OpenGLRenderContextHandle = NULL;
// Device (Geräte) Context (DC):
HDC g_DeviceContextHandle = NULL;
// Handle der Windows Anwendung:
HWND g_MainWindowHandle = NULL;
// Handle auf die Instanz der Windows Anwendung:
HINSTANCE g_ApplicationInstanceHandle = NULL;
Hier nun eine Übersicht über die einzelnen Funktionen, die im Verlauf der Initialisierung und beim Beenden einer OpenGL-Anwendung zum Einsatz kommen:
Die InitResolutionAndRenderOptions()-Funktion öffnet eine Konfigurationsdatei (ResolutionAndRendering.txt) und liest alle renderspezifischen Informationen in das Programm ein.
Funktionsprototyp:
void InitResolutionAndRenderOptions(char* pFileName);
Betrachten wir ein Beispiel für solch eine Konfigurationsdatei:
ZBufferDepth(Bit): 24
Windows/Fullscreen(0/1): 0
Frame/TimeBased(1/2): 1
MaxFrameRate(FrameBased): 35.0
MinimalAcceptableFrameRate: 35.0
FOV_Angle(Blickfeld): 60.0
ViewDistance: 15000.0
screenwidth: 1024
screenheight: 768
colordepth(Bit): 32
. . .
Windows/Fullscreen(0/1): 0
Frame/TimeBased(1/2): 1
MaxFrameRate(FrameBased): 35.0
MinimalAcceptableFrameRate: 35.0
FOV_Angle(Blickfeld): 60.0
ViewDistance: 15000.0
screenwidth: 1024
screenheight: 768
colordepth(Bit): 32
. . .
Nachdem alle renderspezifischen Parameter eingelesen worden sind, kann die OpenGL-Anwendung mithilfe der CreateOpenGLWindow()-Funktion initialisiert werden.
Funktionsprototyp:
BOOL CreateOpenGLWindow(LPCWSTR title);
Alle OpenGL-Render-Parameter (bsp. Tiefenpuffer-Einstellungen), die im weiteren Verlauf genutzt werden sollen, werden im Zuge der Initialisierungsarbeiten innerhalb der Set_Initial_OpenGL_RenderParameter()-Funktion eingestellt.
Funktionsprototyp:
BOOL Set_Initial_OpenGL_RenderParameter(D3DXVECTOR4*
pBackgroundScreenColor);
pBackgroundScreenColor);
Die ReSizeOpenGLScene()-Funktion dient zum Einstellen der Viewport-Eigenschaften (glViewport(), Bildschirmauflösung bsp. 1024 x 768). Darüber hinaus werden die Projektionsmatrizen berechnet (g_matProj, g_matProj_ZBiased), mit deren Hilfe in den Vertex-Shader-Programmen später die Transformation der 3D-Modell-Vertices aus dem Kameraraum in den Bildraum (auf den Bildschirm) erfolgt.
Funktionsprototyp:
void ReSizeOpenGLScene(long width, long height);
Bevor eine OpenGL-Anwendung wieder beendet werden kann, müssen Render- und Gerätekontext wieder freigegeben werden. Hier kommt die KillOpenGLWindow()-Funktion ins Spiel.
Funktionsprototyp:
void KillOpenGLWindow(void);