#if !defined WIN32_CREATE_CONTEXT_OGL31 #define WIN32_CREATE_CONTEXT_OGL31 #include #include #pragma comment(lib, "opengl32.lib") #pragma comment(lib, "glew32.lib") #pragma comment(lib, "glew32s.lib") #include #include #include #define GL3_PROTOTYPES 1; #include #include #endif //---------------------------------------------------------------------- // Constantes. //---------------------------------------------------------------------- #define APP_TITLE "OpenGL 3.0" //---------------------------------------------------------------------- // Globales. //---------------------------------------------------------------------- HWND g_hWnd; // Handle de la fenêtre. HINSTANCE g_hInstance; // L'instance en cours. HDC g_hDC; // Le contexte de dessin. HGLRC g_hRC; // Le contexte OpenGL int g_windowWidth; // La largeur de la fenêtre. int g_windowHeight; // La hauteur de la fenêtre. bool g_isFullScreen; // Plein écran ou fenêtré. bool g_hasFocus; // Vrai si la fenêtre à le focus. //---------------------------------------------------------------------- // Prototypes de fonctions. //---------------------------------------------------------------------- HWND CreateAppWindow(const WNDCLASSEX &wcl, const char *pszTitle); LRESULT CALLBACK WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); void ToggleFullScreen(); void Cleanup(); bool Init(); bool InitGL(); void RenderFrame(); //---------------------------------------------------------------------- // Fonctions. //---------------------------------------------------------------------- char* filetobuf(char *file) { FILE *fptr; long length; char *buf; fptr = fopen(file, "r"); /* Open file for reading */ if (!fptr) /* Return NULL on failure */ return 0; fseek(fptr, 0, SEEK_END); /* Seek to the end of the file */ length = ftell(fptr); /* Find out how many bytes into the file we are */ buf = (char*)malloc(length+1); /* Allocate a buffer for the entire length of the file and a null terminator */ fseek(fptr, 0, SEEK_SET); /* Go back to the beginning of the file */ fread(buf, length, 1, fptr); /* Read the contents of the file in to the buffer */ fclose(fptr); /* Close the file */ buf[length] = 0; /* Null terminator */ if(strlen(buf) > 1) return buf; /* Return the buffer */ else exit(0); } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) { #if defined _DEBUG _CrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF | _CRTDBG_ALLOC_MEM_DF); _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE); _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR); #endif MSG msg = {0}; WNDCLASSEX wcl = {0}; wcl.cbSize = sizeof(wcl); wcl.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW; wcl.lpfnWndProc = WindowProc; wcl.cbClsExtra = 0; wcl.cbWndExtra = 0; wcl.hInstance = g_hInstance = hInstance; wcl.hIcon = LoadIcon(0, IDI_APPLICATION); wcl.hCursor = LoadCursor(0, IDC_ARROW); wcl.hbrBackground = 0; wcl.lpszMenuName = 0; wcl.lpszClassName = (LPCWSTR) "GL3WindowClass"; wcl.hIconSm = 0; if (!RegisterClassEx(&wcl)) return 0; g_hWnd = CreateAppWindow(wcl, APP_TITLE); if (g_hWnd) { if (Init()) { ShowWindow(g_hWnd, nShowCmd); UpdateWindow(g_hWnd); while (true) { while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) { if (msg.message == WM_QUIT) break; TranslateMessage(&msg); DispatchMessage(&msg); } if (msg.message == WM_QUIT) break; if (g_hasFocus) { RenderFrame(); SwapBuffers(g_hDC); } else { WaitMessage(); } } } Cleanup(); UnregisterClass(wcl.lpszClassName, hInstance); } return static_cast(msg.wParam); } LRESULT CALLBACK WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_ACTIVATE: switch (wParam) { default: break; case WA_ACTIVE: case WA_CLICKACTIVE: g_hasFocus = true; break; case WA_INACTIVE: if (g_isFullScreen) ShowWindow(hWnd, SW_MINIMIZE); g_hasFocus = false; break; } break; case WM_CHAR: switch (static_cast(wParam)) { case VK_ESCAPE: PostMessage(hWnd, WM_CLOSE, 0, 0); break; default: break; } break; case WM_DESTROY: PostQuitMessage(0); return 0; case WM_SIZE: g_windowWidth = static_cast(LOWORD(lParam)); g_windowHeight = static_cast(HIWORD(lParam)); break; case WM_SYSKEYDOWN: if (wParam == VK_RETURN) ToggleFullScreen(); break; default: break; } return DefWindowProc(hWnd, msg, wParam, lParam); } void Cleanup() { if (g_hDC) { if (g_hRC) { wglMakeCurrent(g_hDC, 0); wglDeleteContext(g_hRC); g_hRC = 0; } ReleaseDC(g_hWnd, g_hDC); g_hDC = 0; } } HWND CreateAppWindow(const WNDCLASSEX &wcl, const char *pszTitle) { // Création d'une fenêtre centrée. DWORD wndExStyle = WS_EX_OVERLAPPEDWINDOW; DWORD wndStyle = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_CLIPCHILDREN | WS_CLIPSIBLINGS; HWND hWnd = CreateWindowEx(wndExStyle, wcl.lpszClassName, (LPCWSTR)pszTitle, wndStyle, 0, 0, 0, 0, 0, 0, wcl.hInstance, 0); if (hWnd) { int screenWidth = GetSystemMetrics(SM_CXSCREEN); int screenHeight = GetSystemMetrics(SM_CYSCREEN); int halfScreenWidth = screenWidth / 2; int halfScreenHeight = screenHeight / 2; int left = (screenWidth - halfScreenWidth) / 2; int top = (screenHeight - halfScreenHeight) / 2; RECT rc = {0}; SetRect(&rc, left, top, left + halfScreenWidth, top + halfScreenHeight); AdjustWindowRectEx(&rc, wndStyle, FALSE, wndExStyle); MoveWindow(hWnd, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, TRUE); GetClientRect(hWnd, &rc); g_windowWidth = rc.right - rc.left; g_windowHeight = rc.bottom - rc.top; } return hWnd; } bool Init() { try { InitGL(); return true; } catch (const std::exception &e) { std::ostringstream msg; msg << "Erreur lors de l'initialisation de l'application!" << std::endl << std::endl; msg << e.what(); MessageBox(g_hWnd,(LPCWSTR) msg.str().c_str(), (LPCWSTR)"Error", MB_ICONERROR); return false; } } bool InitGL() { if (!(g_hDC = GetDC(g_hWnd))) throw std::runtime_error("GetDC() failed."); int pixelFormat = 0; PIXELFORMATDESCRIPTOR pfd; // Création et définition d'un format de pixel pour la fenêtre memset(&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR)); 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 = 32; pfd.cDepthBits = 32; pfd.iLayerType = PFD_MAIN_PLANE; pixelFormat = ChoosePixelFormat(g_hDC, &pfd); if(pixelFormat == 0) throw std::runtime_error("ChoosePixelFormat() failed."); if (!SetPixelFormat(g_hDC, pixelFormat, &pfd)) throw std::runtime_error("SetPixelFormat() failed."); // Création du contexte temporaire. HGLRC tempContext = wglCreateContext(g_hDC); wglMakeCurrent(g_hDC, tempContext); PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB = NULL; wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC) wglGetProcAddress("wglCreateContextAttribsARB"); GLenum err = glewInit(); if (GLEW_OK != err) { throw std::runtime_error("initialisation de GLEW"); } if(wglCreateContextAttribsARB != NULL) { int attribList[] = { WGL_CONTEXT_MAJOR_VERSION_ARB, 3, WGL_CONTEXT_MINOR_VERSION_ARB, 1, WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB, 0, 0 }; if(wglewIsSupported("WGL_ARB_create_context") == 1) { g_hRC = wglCreateContextAttribsARB(g_hDC,0, attribList); wglMakeCurrent(NULL,NULL); wglDeleteContext(tempContext); } else { // Impossible de créer un contexte OpenGL 3.1, on utilise l'ancien contexte (OpenGL 2.x ou 1.x). g_hRC = tempContext; } } if (!wglMakeCurrent(g_hDC, g_hRC)) throw std::runtime_error("wglMakeCurrent() failed for OpenGL 3 context."); // Vérification de la version d'OpenGL int OpenGLVersion[2]; glGetIntegerv(GL_MAJOR_VERSION, &OpenGLVersion[0]); glGetIntegerv(GL_MINOR_VERSION, &OpenGLVersion[1]); if(OpenGLVersion[0] != 3 || OpenGLVersion[1] != 1) return false; if (!g_hRC) return false; return true; } void RenderFrame() { GLuint vao; GLuint vbo[2]; const GLfloat triangle[9] = {-0.5,0.0,0.0,0.5,0.0,0,0.0,0.5,0.0}; const GLfloat triangleColors[9] = {1.0,0,0,0,1.0,0,0,0,1.0}; glGenVertexArrays(1, &vao); glBindVertexArray(vao); glGenBuffers(2, vbo); glBindBuffer(GL_ARRAY_BUFFER, vbo[0]); glBufferData(GL_ARRAY_BUFFER, 9 * sizeof(GLfloat), triangle, GL_STATIC_DRAW); glVertexAttribPointer((GLuint)0, 3, GL_FLOAT, GL_FALSE, 0, 0); glEnableVertexAttribArray(0); glBindBuffer(GL_ARRAY_BUFFER, vbo[1]); glBufferData(GL_ARRAY_BUFFER, 9 * sizeof(GLfloat), triangle, GL_STATIC_DRAW); glVertexAttribPointer((GLuint)1, 3, GL_FLOAT, GL_FALSE, 0, 0); glEnableVertexAttribArray(1); // Shaders unsigned int vertexID, fragmentID, programID; programID = glCreateProgram(); // Création des shaders vertexID = glCreateShader (GL_VERTEX_SHADER); fragmentID = glCreateShader (GL_FRAGMENT_SHADER); // Chargement du code source des shaders const char * vertexSource = filetobuf("shader.vert"); const char * fragmentSource = filetobuf("shader.frag"); // Envoi du code source glShaderSource (vertexID, 1, &vertexSource, NULL); glShaderSource (fragmentID, 1, &fragmentSource, NULL); // Compilation des shaders glCompileShader (vertexID); glCompileShader (fragmentID); // Attache des shaders au programme (on peut les détacher avec la fonction glDetachShader) glAttachShader (programID, vertexID); glAttachShader (programID, fragmentID); glBindAttribLocation(programID, 0, "in_Position"); glBindAttribLocation(programID, 1, "in_Color"); // Linkage du programme glLinkProgram (programID) ; glViewport(0, 0, g_windowWidth, g_windowHeight); glClearColor(0.3f, 0.5f, 0.9f, 0.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glUseProgram (programID) ; glBindVertexArray(vao); // select first VAO glDrawArrays(GL_TRIANGLES, 0, 3); // draw first object SwapBuffers(g_hDC); } void ToggleFullScreen() { static DWORD savedExStyle; static DWORD savedStyle; static RECT rcSaved; g_isFullScreen = !g_isFullScreen; if (g_isFullScreen) { // Passage en mode plein écran. savedExStyle = GetWindowLong(g_hWnd, GWL_EXSTYLE); savedStyle = GetWindowLong(g_hWnd, GWL_STYLE); GetWindowRect(g_hWnd, &rcSaved); SetWindowLong(g_hWnd, GWL_EXSTYLE, 0); SetWindowLong(g_hWnd, GWL_STYLE, WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS); SetWindowPos(g_hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED | SWP_SHOWWINDOW); g_windowWidth = GetSystemMetrics(SM_CXSCREEN); g_windowHeight = GetSystemMetrics(SM_CYSCREEN); SetWindowPos(g_hWnd, HWND_TOPMOST, 0, 0, g_windowWidth, g_windowHeight, SWP_SHOWWINDOW); } else { // Passage en mode fenêtré. SetWindowLong(g_hWnd, GWL_EXSTYLE, savedExStyle); SetWindowLong(g_hWnd, GWL_STYLE, savedStyle); SetWindowPos(g_hWnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED | SWP_SHOWWINDOW); g_windowWidth = rcSaved.right - rcSaved.left; g_windowHeight = rcSaved.bottom - rcSaved.top; SetWindowPos(g_hWnd, HWND_NOTOPMOST, rcSaved.left, rcSaved.top, g_windowWidth, g_windowHeight, SWP_SHOWWINDOW); } }