380 likes | 512 Views
Module 01. Inicializ ácia OpenGL okna. Obsah. OpenGL knižnica Štruktúra typickej aplikácie písanej nad knižnicou OpenGL Odporúčané postupy Programovanie jednoduchej OpenGL demonštračnej aplikácie v prostredí Microsoft Visual Studio .NET. OpenGL knižnica.
E N D
Module 01 Inicializácia OpenGL okna
Obsah • OpenGL knižnica • Štruktúra typickej aplikácie písanej nad knižnicou OpenGL • Odporúčané postupy • Programovanie jednoduchej OpenGL demonštračnej aplikácie v prostredí Microsoft Visual Studio .NET.
OpenGL knižnica • OpenGL je nezávislá na použitej platforme • OpenGL je rozšíriteľnénízkoúrovňové grafické programové rozhranie • OpenGL syntax je veľmi jednoduchá
Štruktúra typického OpenGL programu main: find GL visual and create window initialize GL states (e.g. viewing, color, lighting) initialize display lists loop check for events (and process them) if window event (window moved, exposed, etc.) modify viewport, if needed redraw else if mouse or keyboard do something, e.g., change states and redraw redraw: clear screen (to background color) change state(s), if needed render some graphics change more states render some more graphics . . swap buffers
Odporúčané techniky programovania • Komentovanie zdrojových kódov • Osobitne ukladanie jednotlivých verzií projektov. • Zrozozumiteľné názvy premenných • Zarovnávané bloky kódu • Jednotný štýl písania zdrojového kódu v celom projekte (hlavne pri tímovom projekte)
Demonštračný program Postup: • Pridajte hlavičkové súbory do zdrojových kódov a prilinkujte OpenGL knižnice ku projektu • Zadeklarujteglobálne funkcie • Zadeklarujteglobálne premenné • Zadefinujte vstupný bod do aplikácie • Odchyťte všetky potrebné správy okna • Vytvorte OpenGL okno • Inicializujte OpenGL okno • Vykreslite scénu pomocou jednej hlavnej metódy • Vytvorte metódy na uvolnenie Rendering Context, Device Context a okna • Metóda na prepočítanie projekčných matíc pri zmene rozmeru okna (resize)
1)Pridanie podpory OpenGL do projektu //-------------------------------------------------------------------------------- // Header Files and Libraries //-------------------------------------------------------------------------------- #include <windows.h> // Header File For Windows #include <gl\gl.h> // Header File For The OpenGL32 Library #include <gl\glu.h> // Header File For The GLu32 Library #include <gl\glaux.h> // Header File For The GLaux Library #pragma comment( lib, "opengl32.lib" ) // OpenGL32 Library #pragma comment( lib, "glu32.lib" ) // GLu32 Library #pragma comment( lib, "glaux.lib" ) // GLaux Library
2) Deklarácia globálnych funkcií //-------------------------------------------------------------------------------- // Global Functions //-------------------------------------------------------------------------------- int WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR, int); LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); BOOL CreateGLWindow(char*, int, int, int, bool); GLvoid ReSizeGLScene(GLsizei, GLsizei); int DrawGLScene(GLvoid); int InitGL(GLvoid); GLvoid KillGLWindow(GLvoid);
3) Deklarácia globálnych premenných //-------------------------------------------------------------------------------- // Global Variables //-------------------------------------------------------------------------------- HDC hDC=NULL; // Private GDI Device Context HGLRC hRC=NULL; // Permanent Rendering Context HWND hWnd=NULL; // Holds Our Window Handle HINSTANCE hInstance; // Holds The Instance Of The Application bool keys[256]; // Array Used For The Keyboard Routine bool active=TRUE; // Window Active Flag Set To TRUE By Default bool fullscreen=TRUE; // Fullscreen Flag Set To Fullscreen Mode By Default
4) WinMain – Vstupný bod do aplikácie (1) int WINAPI WinMain( HINSTANCE hInstance, // inštancia aplikácie HINSTANCE hPrevInstance, // predchádzajúca inštancia LPSTR lpCmdLine, // parametre z príkazového riadku int nCmdShow) // Zobrazovací stav pri spustení { Postup: 1) zadefinuj lokálne premenné 2) Zisti od užívateľa aký zobrazovací mód požaduje (Window/Fullscreen) 3) Vytvor aplikačné okno 4) Spracuj prichádzajúce správy do okna 5) Ak nie sú správy na spracovanie vykresli ďalší snímok scény 6) Ošetri stlačené klávesy 7) Pri skončení uvolni všetky alokované štruktúry }// end of WinMain()
4) WinMain - Vstupný bod do aplikácie (2) int WINAPI WinMain(...) { // 1) – deklarácia lokálnych premenných MSG msg; // Windows Message Structure BOOL done=FALSE; // Bool Variable To Exit Loop // 2) – Zisti od užívateľa, ktorý zobrazovací mód požaduje if (MessageBox(NULL,"Would You Like To Run In Fullscreen Mode?", "Start FullScreen?",MB_YESNO|MB_ICONQUESTION)==IDNO) { fullscreen=FALSE; // Windowed Mode } // 3) Vytvor OpenGL okno if (!CreateGLWindow(“Module01”, 640,480,16,fullscreen)) { return 0; // Quit If Window Was Not Created } … }// end of WinMain()
4) WinMain - Vstupný bod do aplikácie (3) int WINAPI WinMain(...) { … while(!done) // Opakuj tento cyklus do skončenia aplikácie { // 4) – zisti či nečakajú nejaké správy vo fronte správ okna if (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) { if (msg.message==WM_QUIT) // Neprišla správa Quit ? { done=TRUE; // Ak áno, nastav done=TRUE } else // Ak nie, spracuj došlú správu { TranslateMessage(&msg); // Prelož správu DispatchMessage(&msg); // obslúž správu } } … } // koniec WinMain()
4) WinMain - Vstupný bod do aplikácie (4) int WINAPI WinMain(...) { … else // Ak nie su vo fronte žiadne správy na spracovanie { // 5) – Vykresli nový snímok scény if (active) // Ak je aplikácia aktívna { if (keys[VK_ESCAPE]) // 6) –Bola stlačená kláves ESC? { done=TRUE; // ESC znamená Quit } else // Update screen { DrawGLScene(); // Vygeneruj nový snímok SwapBuffers(hDC); // Swap Buffers (Double Buffering) } } … } // Koniec WinMain()
4) WinMain - Vstupný bod do aplikácie (5) int WINAPI WinMain(...) { … if (keys[VK_F1]) // 6) – Ak bola stlačená kláves F1? { keys[VK_F1]=FALSE; // neguj príznak stlačenia KillGLWindow(); // uvolni alokované štruktúry fullscreen=!fullscreen; // Prepni zobrazovací mód na opačný // pätovne vytvor okno z novým nastavením módu if (!CreateGLWindow(“Module01",640,480,16,fullscreen)) { return 0; // Ukonči program v prípade neúspechu } } } // end of else } // end of while(!done) … } // Koniec WinMain()
4) WinMain - Vstupný bod do aplikácie (6) int WINAPI WinMain(...) { … // 7) – uvolni alokované štruktúry a opusti program KillGLWindow(); // zavri okno return (msg.wParam); // opusti program } // koniec WinMain()
5) WndProc – Procedúra okna(1) LRESULT CALLBACK WndProc( HWND hWnd, // smerník na okno UINT uMsg, // ID správy WPARAM wParam, // sprievodne informácie zo správou LPARAM lParam) // sprievodne informácie zo správou { Postup: 1) Zisti čo je to za správa 2) Všetky nespracované správy odošli DefWindowProc } // Koniec WndProc()
5) WndProc – Procedúra okna(2) LRESULT CALLBACK WndProc(...) { // 1) – zisti ID správy switch (uMsg) { case WM_ACTIVATE: // Zmena aktívnosti okna { if (!HIWORD(wParam)) // Minimization State { active=TRUE; // Program je aktívny } else { active=FALSE; // Program nie je aktívny } return 0; // vráť sa a spracuj ďalšiu správu } … } // Koniec WndProc()
5) WndProc – Procedúra okna(3) LRESULT CALLBACK WndProc(...) { … case WM_SYSCOMMAND: // prišiel príkaz od OS { switch (wParam) // Over systémove volania { // Mám spustiť screensaver ? case SC_SCREENSAVE: // Mám odpojiť monitor ? case SC_MONITORPOWER: return 0; } break; // Exit } case WM_CLOSE: // Prišla správa na zatvorenie okna ? { PostQuitMessage(0); // Odošli poslednú správu na ukončenie return 0; } … } // Koniec WndProc()
5) WndProc – Procedúra okna(4) LRESULT CALLBACK WndProc(...) { … case WM_KEYDOWN: // Je stlačená kláves? { keys[wParam] = TRUE; // Ak áno tak nastav príznak na TRUE return 0; } case WM_KEYUP: Je uvolnená kláves ? { keys[wParam] = FALSE; // Ak áno tak nastav príznak na FALSE return 0; } case WM_SIZE: // Bola zmenená veľkosť okna? { // LoWord=šírka, HiWord=výška ReSizeGLScene(LOWORD(lParam),HIWORD(lParam)); return 0; } } // end of switch(uMsg) // 2) – Odošli nespracované správy so DefWindowProc return DefWindowProc(hWnd,uMsg,wParam,lParam); } // Koniec WndProc()
6) Vytvor OpenGL okno(1) BOOL CreateGLWindow(char* title, // titulok okna int width,// šírka okna int height, // výška okna int bits,// farebná hĺbka (8, 16, 24, 32) bool fullscreenflag)// fullscreen mode ak je TRUE { Postup: 1) zadeklaruj a nastav lokálne premenné 2) Zaregistruj triedu okna 3) nastav fullscreen mód 4) nastav požadovanú veľkosť okna 5) vytvor okno 6) nastav formát pixelu 7) získaj a aktivuj rendering kontext 8) inicializuj novovytvorene GL okno } // koniec CreateGLWindow()
6) Vytvor OpenGL okno(2) BOOL CreateGLWindow(...) { // 1) - deklaruj a nastav lokálne premenné Gluint PixelFormat; // Pixel formát WNDCLASS wc; // štruktúra triedy okna DWORD dwExStyle; // rozšírený štýl okna DWORD dwStyle; // štýl okna RECT WindowRect; // štruktúra obdĺžniku WindowRect.left=(long)0; // nastav ľavý okraj okna WindowRect.right=(long)width; // nastav šírku okna WindowRect.top=(long)0; // nastav hornú pozíciu okna WindowRect.bottom=(long)height; // nastav výšku okna fullscreen=fullscreenflag; // nastav príznak fullcreen módu hInstance = GetModuleHandle(NULL); // Získaj smerník na inštanciu hlavného okna … } // koniec CreateGLWindow()
6) Vytvor OpenGL okno(3) BOOL CreateGLWindow(...) { … // Redraw On Size, And Own DC For Window. wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; wc.lpfnWndProc = (WNDPROC) WndProc; // Prideľ procedúru okna wc.cbClsExtra = 0; // No Extra Window Data wc.cbWndExtra = 0; // No Extra Window Data wc.hInstance = hInstance; // Nastav inštanciu wc.hIcon = LoadIcon(NULL, IDI_WINLOGO); // Nastav ikonu wc.hCursor = LoadCursor(NULL, IDC_ARROW); // Nastav kurzor wc.hbrBackground = NULL; // Nenastavuj farbu pozadia wc.lpszMenuName = NULL; // Nepotrebujeme menu wc.lpszClassName = "OpenGL"; // prirad meno triede okna // 2) - Pokúsime sa zaregistrovať treidu takéhoto okna if (!RegisterClass(&wc)) { MessageBox(NULL,"Failed To Register The Window Class.", "ERROR",MB_OK|MB_ICONEXCLAMATION); return FALSE; // Return FALSE } … } // koniec CreateGLWindow()
6) Vytvor OpenGL okno(4) BOOL CreateGLWindow(...) { … // 3) – nastav fullscreen mód if (fullscreen) { DEVMODE dmScreenSettings; // Device Mode memset(&dmScreenSettings,0,sizeof(dmScreenSettings)); // vynuluj obsah pamäte dmScreenSettings.dmSize=sizeof(dmScreenSettings); // zisti potrebnú veľkosť dmScreenSettings.dmPelsWidth = width; // nastav šírku okna dmScreenSettings.dmPelsHeight = height; // nastav výšku okna dmScreenSettings.dmBitsPerPel = bits; // nastav farebnú hĺbku dmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT; … } // koniec CreateGLWindow()
6) Vytvor OpenGL okno(5) BOOL CreateGLWindow(...) { … // skús nastaviť vybraný rozlíšenie if (ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL) { // Ak sa nepodarí fullscreen mód, skús prepnúť do okna if (MessageBox(NULL,"The Requested Fullscreen Mode Is Not Supported By\nYour Video Card. Use Windowed Mode Instead?","NeHe GL",MB_YESNO|MB_ICONEXCLAMATION)==IDYES) { fullscreen=FALSE; // nastav okenný mód } else {// zavri aplikáciu, nepodporujeme dane rozlíšenie MessageBox(NULL,"Program Will NowClose.", "ERROR", MB_OK|MB_ICONSTOP); return FALSE; // Return FALSE } } } // end of if (fulscreen) … } // end of CreateGLWindow()
6) Vytvor OpenGL okno(6) BOOL CreateGLWindow(...) { … if (fullscreen) // Ak sme vo fullscreen móde? { dwExStyle=WS_EX_APPWINDOW; // nastav Window Extended Style dwStyle=WS_POPUP; // nastav Windows Style ShowCursor(FALSE); // skry kurzor myšky } else { // Window Extended Style dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; // Windows Style dwStyle=WS_OVERLAPPEDWINDOW; } // 4) – Nastav okno do požadovaných rozmerov AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle); … } // Koniec CreateGLWindow()
6) Vytvor OpenGL okno(7) BOOL CreateGLWindow(...) { … // 5) – Vytvor okno if (!(hWnd=CreateWindowEx( dwExStyle, // rošírený štýl pre toto okno OpenGL", // Class Name title, // titulok okna dwStyle | // Defined Window Style WS_CLIPSIBLINGS | // Required Window Style WS_CLIPCHILDREN, // Required Window Style 0, 0, // Window Position WindowRect.right-WindowRect.left,// Vypočítaj šírku okna WindowRect.bottom-WindowRect.top,// Vypočítaj výšku okna NULL, // Nemá rodičovské okno NULL, // nemá menu hInstance, // inštancia NULL))) // Neodosielaj nič do WM_CREATE { KillGLWindow(); // Resetni Displaj MessageBox(NULL,"Window Creation Error.","ERROR", MB_OK|MB_ICONEXCLAMATION); return FALSE; // Return FALSE } … } // end of CreateGLWindow()
6) Vytvor OpenGL okno(8) BOOL CreateGLWindow(...) { … // 6) – nastav pixel formát static PIXELFORMATDESCRIPTOR pfd= { sizeof(PIXELFORMATDESCRIPTOR), // veľkosť Pixel Format Descriptor 1, // verzia PFD_DRAW_TO_WINDOW | // podpora kreslenia do okna PFD_SUPPORT_OPENGL | // podpora OpenGL PFD_DOUBLEBUFFER, // podpora Double Buffering PFD_TYPE_RGBA, // požaduje RGBA Format bits, // farebná hĺbka 0, 0, 0, 0, 0, 0, // ignorované farebné bity 0, // nepoužijeme alfa kanál 0, // Shift Bit Ignored 0, // No Accumulation Buffer 0, 0, 0, 0, // Accumulation Bits Ignored 16, // 16Bit Z-Buffer (pamäť hĺbky) 0, // No Stencil Buffer 0, // No Auxiliary Buffer PFD_MAIN_PLANE, // Main Drawing Layer 0, // Reserved 0, 0, 0 // Layer Masks Ignored }; … } // end of CreateGLWindow()
6) Vytvor OpenGL okno(9) BOOL CreateGLWindow(...) { … if (!(hDC=GetDC(hWnd))) // získali sme kontext zariadenia ? { KillGLWindow(); // Reset The Display MessageBox(NULL,"Can't Create A GL Device Context.","ERROR",MB_OK|MB_ICONEXCLAMATION); return FALSE; // Return FALSE } if (!(PixelFormat=ChoosePixelFormat(hDC,&pfd))) // Je podporovaný nami vybrany PFD? { KillGLWindow(); // Reset The Display MessageBox(NULL,"Can't Find A Suitable PixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION); return FALSE; // Return FALSE } if(!SetPixelFormat(hDC,PixelFormat,&pfd)) // Vieme nastaviť vybraný PFD? { KillGLWindow(); // Reset The Display MessageBox(NULL,"Can't Set The PixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION); return FALSE; // Return FALSE } … } // end of CreateGLWindow()
6) Vytvor OpenGL okno(10) BOOL CreateGLWindow(...) { … if (!(hRC=wglCreateContext(hDC))) // 9) - získaj renderovací kontext { KillGLWindow(); // Reset The Display MessageBox(NULL,"Can't Create A GL Rendering Context.","ERROR", MB_OK|MB_ICONEXCLAMATION); return FALSE; // Return FALSE } If(!wglMakeCurrent(hDC,hRC)) // 9) – aktivuj renderovací kontext { KillGLWindow(); // Reset The Display MessageBox(NULL,"Can't Activate The GL Rendering Context.","ERROR", MB_OK|MB_ICONEXCLAMATION); return FALSE; // Return FALSE } … } // end of CreateGLWindow()
6) Vytvor OpenGL okno(11) BOOL CreateGLWindow(...) { … ShowWindow(hWnd,SW_SHOW); // zobraz The Window SetForegroundWindow(hWnd); // nastav prioritu SetFocus(hWnd); // nastav fokus z klavesnice nášmu novému oknu ReSizeGLScene(width, height); // Nastav perspektívne zobrazovanie // 10) – Inicializuj nové okno if (!InitGL()) { KillGLWindow(); // Reset The Display MessageBox(NULL,"Initialization Failed.","ERROR", MB_OK|MB_ICONEXCLAMATION); return FALSE; // Return FALSE } return TRUE; // úspešný koniec } // koniec CreateGLWindow()
7) Inicializuj OpenGL okno int InitGL(GLvoid) { glShadeModel(GL_SMOOTH); // povoľ Smooth Shading glClearColor(0.0f, 0.0f, 0.0f, 0.5f); // Nastav čierne pozadie glClearDepth(1.0f); // nastav Depth Buffer glEnable(GL_DEPTH_TEST); // povoľ testovanie hĺbky glDepthFunc(GL_LEQUAL); // nastav funkciu testovania hĺbky // Krajšie perspektívne zobrazenie glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); return TRUE; // Initialization Went OK } // koniec InitGL()
8) Vykreslenie GL scény int DrawGLScene(GLvoid) { // amž obrazovku a pamäť hĺbky glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // resetni aktuálnu modelovaciu transformačnú maticu glLoadIdentity(); return TRUE; // Everything Went OK }// koniec DrawGLScene()
9) Uvolni rendering kontext(1) GLvoid KillGLWindow(GLvoid) { Postup: 1) Zisti v akom sme móde 2) uvolni rendering kontext 3) uvolni kontext zariadenia 4) uvolni okno 5) odregistruj triedu okna } // end of KillGLWindow()
9) Uvolni kontext okna(2) GLvoid KillGLWindow(GLvoid) { if (fullscreen) // 1) – sme vo fullscreen móde ? { ChangeDisplaySettings(NULL,0); // Ak áno prepni sa naspäť do okna ShowCursor(TRUE); // zobraz kurzor myšky } if (hRC) // máme renderovací kontext? { if (!wglMakeCurrent(NULL,NULL)) // Vieme uvolniť kontexty ? { MessageBox(NULL,"Release Of DC And RC Failed.","SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION); } if (!wglDeleteContext(hRC)) // vieme zmazať RC kontext? { MessageBox(NULL,"Release Rendering Context Failed.","SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION); } hRC=NULL; // 2) – uvolni rendering kontext } … } // end of KillGLWindow()
9) Uvolni rendering kontext(3) GLvoid KillGLWindow(GLvoid) { … If (hDC && !ReleaseDC(hWnd,hDC)) // vieme uvolniť DC kontext? { MessageBox(NULL,"Release Device Context Failed.","SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION); hDC=NULL; // 3) – uvolni DC } If (hWnd && !DestroyWindow(hWnd)) // Are We Able To Destroy The Window? { MessageBox(NULL,"Could Not Release hWnd.","SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION); hWnd=NULL; // 4) – uvolni okno } if (!UnregisterClass("OpenGL",hInstance))// vieme odregistrovať aplikáciu { MessageBox(NULL,"Could Not Unregister Class.","SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION); hInstance=NULL; // 5) – odregistruj OpenGL inštanciu } } // end of KillGLWindow()
10) Zmeň veľkosťokna GLvoid ReSizeGLScene(GLsizei width, GLsizei height) { if (height==0) // zabráň deleniu nulou { height=1; // nastav min. výšku na 1 } glViewport(0,0,width,height); // Resetni aktuálny Viewport glMatrixMode(GL_PROJECTION); // nastav projekčnú maticu glLoadIdentity(); // resetni projekčnú maticu // Nastav parametre perspektívne zobrazenia v okne gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f); glMatrixMode(GL_MODELVIEW); // nastav modelovaciu maticu glLoadIdentity(); // resetni modelovaciu maticu } // end of ReSizeGLScene()
Cvičenie Otvorte: Lab01 / InitOpenGLWindow / InitOpenGLWindow.sln