Stoppt die Vorratsdatenspeicherung! Jetzt klicken && handeln!Willst du auch bei der Aktion teilnehmen? Hier findest du alle relevanten Infos und Materialien:
 
OpenGL initialisieren
von Plapperkatze am 14.Februar 2006 um 14:24
zurück zur Kategorie "Tutorials"

Die Graphical Device Interface (GDI) von Windows stösst an ihre Grenzen, sobald man schnelle Grafik wie für Spiele oder Animationen benötigt. Dafür gibt es Engines wie DirectX oder OpenGL. Mit letzterer werde ich mich heute befassen, allerdings fürchte ich, dass viele Fragen offen bleiben werden.

Dies ist keine Einführung in OpenGL! Ich werde lediglich Skelettcode präsentieren um ein OpenGL-Fenster zu initialisieren. Diesen werde ich in späteren, hoffentlich interessanteren Tutorials verwenden.

Besonders ans Herz legen möchte ich euch die NeHe-Tutorials (Jeff Molofee):
http://nehe.gamedev.net/
Hier gibt es eine deutsche Übersetzung:
http://www.codeworx.org/opengl_tuts.php

Besser kann man es eigentlich kaum erklären und wer es dort nicht begreift, wird auch hier nichts lernen können.

Also zum Ablauf eines OpenGL-Programms:
1. Windows-Klasse registrieren
2. Fenster erzeugen (bzw. Fullscreen-Mode: ChangeDisplaySettings)
3. OpenGL initialisieren
3.1 Handle auf Device Context (hDC) des Fensters bekommen
3.2 PixelFormat festlegen mit ChoosePixelFormat und SetPixelFormat
3.3 GL Rendering Context erzeugen (hRC)
3.4 Rendering Context an Fenster binden (hRC<->hDC)
3.5 ReSizeGLScene (eine Funktion, um unseren Zeichenbereich festzulegen)
3.6 InitGL (Zeichenbereich bereit machen)
4. LOOP bis Fehler oder Ende (Windows-Messages bearbeiten, Szene zeichnen und darstellen)
5. OpenGL beenden
5.1 evtl Fullscreen-Mode beenden mit ChangeDisplaySettings
5.2 Rendering Context und Device Context freigeben (wglDeleteContext und ReleaseDC)
5.3 Fenster schliessen
5.4 Klasse freigeben

Ich habe alle OpenGL-Funktionen in eine Datei namens gl.c ausgelagert, die im Main-Code (main.c) includet wird. Hier ist diese main.c:
#include<windows.h>

#include<gl\gl.h>
#include<gl\glu.h>

HGLRC hRC = NULL;                 // Rendering Context

HDC hDC = NULL;                   // Device Context
HWND hWnd = NULL;                 // Window Handle
HINSTANCE hSavedInstance = NULL;  // Instance

LRESULT CALLBACK WndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam);

BOOL fullscreen=FALSE;
BOOL active=TRUE;

#include"gl.c"


WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
 MSG msg;
 WNDCLASS wc;
 BOOL done=FALSE;

 hSavedInstance=hInstance;


 // Windows Klasse registrieren
 wc.style=CS_HREDRAW|CS_VREDRAW|CS_OWNDC;
 wc.lpfnWndProc=(WNDPROC)WndProc;
 wc.cbClsExtra=0;
 wc.cbWndExtra=0;
 wc.hInstance=hInstance;
 wc.hIcon=LoadIcon(NULL,IDI_APPLICATION);
 wc.hCursor=LoadCursor(NULL,IDC_ARROW);
 wc.hbrBackground=NULL;
 wc.lpszMenuName=NULL;
 wc.lpszClassName="OpenGL";
 RegisterClass(&wc);
 
 // OpenGL Fenster erzeugen (breite,hoehe,bit-tiefe)
 CreateGLWindow(800,600,16);

 // Message/Zeichen-Loop
 while(!done)
 {
   if(PeekMessage(&msg,NULL,0,0,PM_REMOVE))
   {
     if(msg.message==WM_QUIT)
     {
       done=TRUE;
     }
     else
     {
       TranslateMessage(&msg);
       DispatchMessage(&msg);
     }
   }
   else
   {
     if(active&&!DrawGLScene())
     {
       done=TRUE;
     }
     else
     {
       SwapBuffers(hDC);
     }
   }
 }
 // Aufraeumen
 KillGLWindow();

 DestroyWindow(hWnd);
 UnregisterClass("OpenGL",hInstance);
 return(msg.wParam);
}

LRESULT CALLBACK WndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
 switch(uMsg)
 {
   case WM_ACTIVATE:
   {
     if(!HIWORD(wParam))
     {
       active=TRUE;
     }
     else
     {
       active=FALSE;
     }
     return 0;
   }
   case WM_SYSCOMMAND:
   {
     switch(wParam)
     {
       case SC_SCREENSAVE:
        case SC_MONITORPOWER:
        return 0;

     }
     break;
   }
   case WM_CLOSE:
   {
     PostQuitMessage(0);
     return 0;
   }
   case WM_SIZE:
   {
     ReSizeGLScene(LOWORD(lParam),HIWORD(lParam));
     return 0;
   }
 }
 return DefWindowProc(hWnd,uMsg,wParam,lParam);
}

Nun, es werden hier also folgende Funktionen aus gl.c verwendet:

CreateGLWindow(width,height,colorbits)
DrawGLScene()
KillGLWindow()
ReSizeGLScene(width,height)

Sehen wir uns das einmal an.
Hier ist CreateGLWindow:
BOOL CreateGLWindow(int width,int height,int bits)
{
 GLuint PixelFormat;
 PIXELFORMATDESCRIPTOR pfd;

 RECT WindowRect;

 DWORD dwExStyle;
 DWORD dwStyle;

 pfd.nSize=sizeof(PIXELFORMATDESCRIPTOR);
 pfd.nVersion=1;
 pfd.dwFlags=PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL|PFD_DOUBLEBUFFER;
 pfd.iPixelType=PFD_TYPE_RGBA;
 pfd.cColorBits=bits;
 pfd.cRedBits=0;
 pfd.cRedShift=0;  
 pfd.cGreenBits=0;  
 pfd.cGreenShift=0;  
 pfd.cBlueBits=0;  
 pfd.cBlueShift=0;  
 pfd.cAlphaBits=0;  
 pfd.cAlphaShift=0;  
 pfd.cAccumBits=0;  
 pfd.cAccumRedBits=0;
 pfd.cAccumGreenBits=0;
 pfd.cAccumBlueBits=0;
 pfd.cAccumAlphaBits=0;  
 pfd.cDepthBits=bits;
 pfd.cStencilBits=0;
 pfd.cAuxBuffers=0;  
 pfd.iLayerType=PFD_MAIN_PLANE;
 pfd.bReserved=0;
 pfd.dwLayerMask=0;
 pfd.dwVisibleMask=0;
 pfd.dwDamageMask=0;

 if(fullscreen)
 {
   dwExStyle=WS_EX_APPWINDOW;
   dwStyle=WS_POPUP;
   ShowCursor(FALSE);
 }
 else
 {
   dwExStyle=WS_EX_APPWINDOW|WS_EX_WINDOWEDGE;
   dwStyle=WS_OVERLAPPEDWINDOW;
 }

 WindowRect.left=(long)0;
 WindowRect.right=(long)width;
 WindowRect.top=(long)0;
 WindowRect.bottom=(long)height;

 AdjustWindowRectEx(&WindowRect,dwStyle,FALSE,dwExStyle);
 
 hWnd=CreateWindowEx(dwExStyle,"OpenGL","OpenGL mit der plapperkatze",
      dwStyle|WS_CLIPSIBLINGS|WS_CLIPCHILDREN,0,0,
      WindowRect.right-WindowRect.left,WindowRect.bottom-WindowRect.top,
      NULL,NULL,hSavedInstance,NULL);

 if(fullscreen)
 {
   DEVMODE dmScreenSettings;
   memset(&dmScreenSettings,0,sizeof(dmScreenSettings));
   dmScreenSettings.dmSize=sizeof(dmScreenSettings);
   dmScreenSettings.dmPelsWidth=WindowRect.right-WindowRect.left;
   dmScreenSettings.dmPelsHeight=WindowRect.bottom-WindowRect.top;
   dmScreenSettings.dmBitsPerPel=16;
   dmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;
   if(ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL)
   {
     if(MessageBox(NULL,"The requested fullscreen mode is not supported by\nyour video card. Use windowed mode instead?","OpenGL",MB_YESNO|MB_ICONEXCLAMATION)==IDYES)
     {
       fullscreen=FALSE;
     }
     else
     {
       error("Program will now close.");
       return FALSE;
     }
   }
 }

 if(!(hDC=GetDC(hWnd)))
 {
   KillGLWindow();
   error("Can't create a GL device context.");
   return FALSE;
 }
 if(!(PixelFormat=ChoosePixelFormat(hDC,&pfd)))
 {
   KillGLWindow();
   error("Can't find a suitable pixelformat.");
   return FALSE;
 }
 if(!SetPixelFormat(hDC,PixelFormat,&pfd))
 {
   KillGLWindow();
   error("Can't set the pixelformat.");
   return FALSE;
 }
 if(!(hRC=wglCreateContext(hDC)))
 {
   KillGLWindow();
   error("Can't create a GL rendering context.");
   return FALSE;
 }
 if(!wglMakeCurrent(hDC,hRC))
 {
   KillGLWindow();
   error("Can't activate the GL rendering context.");
   return FALSE;
 }
 ShowWindow(hWnd,SW_SHOW);
 SetForegroundWindow(hWnd);
 //UpdateWindow(hWnd);
 ReSizeGLScene(width,height);
 if(!InitGL())
 {
   KillGLWindow();
   error("Initialization failed.");
   return FALSE;
 }
 return TRUE;
}

CreateGLWindow erzeugt ein Fenster/Vollbild, reserviert DC und RC und ruft zuerst ReSizeGLScene auf:
GLvoid ReSizeGLScene(GLsizei width,GLsizei height)
{
 if(height==0)
 {
   height=1;
 }
 glViewport(0,0,width,height);
 glMatrixMode(GL_PROJECTION);
 glLoadIdentity();
 gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f);
 glMatrixMode(GL_MODELVIEW);
 glLoadIdentity();
}

und dann InitGL():
int InitGL(GLvoid)
{
 glEnable(GL_TEXTURE_2D);
 glBlendFunc(GL_SRC_ALPHA,GL_ONE);
 glClearColor(0.0f,0.0f,0.0f,0.0f);
 glClearDepth(1.0);
 glDepthFunc(GL_LESS);
 glEnable(GL_DEPTH_TEST);
 glShadeModel(GL_SMOOTH);
 glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST);
 return TRUE;
}

Damit ist das GL-Fenster erzeugt, und der Loop mit DrawGLScene() beginnt. Da wir nichts zeichnen in diesem Tutorial, ist diese Funktion bisher kurz:
int DrawGLScene(GLvoid)         // drawing
{
 //glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear
 //glLoadIdentity();       // Reset the current modelview matrix
 return TRUE;
}

Am Ende alles aufräumen mit KillGLWindow:
GLvoid KillGLWindow(GLvoid)
{
 if(fullscreen)
 {
   ChangeDisplaySettings(NULL,0);
   ShowCursor(TRUE);
 }

 if(hRC)
 {
   if(!wglMakeCurrent(NULL,NULL))error("Release of DC and RC failed.");
   if(!wglDeleteContext(hRC))error("Release rendering context failed.");
   hRC=NULL;
 }

 if(hDC&&!ReleaseDC(hWnd,hDC))error("Release device context failed.");  
 hDC=NULL;
}

Das sollte es gewesen sein. Bei mir ist ilink32 sogar klug genug, die GL-Libraries gleich einzubinden. Sorry dass mal wieder kaum etwas kommentiert ist, ich hole das bald nach.

Hier der Download (Quelltext + Executable als .rar, 26kB):
http://katze.dead-men.de/upload/18_opengl-tut.rar

gruesse, die plapperkatze

zurück zur Kategorie "Tutorials"
[0 Kommentare]

Name


Kommentar




Bitte abtippen


 
(C) 2006-20012 Plapperkatze - 220706 Besucher seit dem 23.01.2012 Login