HATEBIN
>
//------------------ DISCLAIMERS ------------------ /* 1. This code is compiled with UNICODE flag enabled. 2. We only demonstrate the initialization of OpenGL 3.1 up to OpenGL 4.6. 3. Code attempts to use as much C styles as possible, while keeping Visual Studio happy with C++. 4. If #3 fails, keep it so we're 50-50 with C and C++. MIT Licensed */ #include "../headers.h" //Attribute names in <*attribList> for wglCreateContextAttribsARB #define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091 #define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092 #define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126 //Attribute value for WGL_CONTEXT_PROFILE_MASK_ARB in <*attribList> for //wglCreateContextAttribsARB #define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001 #define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002 //All the necessary WGL pixel format values. //Accepted as a type in the
and
parameter //arrays of wglChoosePixelFormatARB #define WGL_DRAW_TO_WINDOW_ARB 0x2001 #define WGL_ACCELERATION_ARB 0x2003 #define WGL_SUPPORT_OPENGL_ARB 0x2010 #define WGL_DOUBLE_BUFFER_ARB 0x2011 #define WGL_PIXEL_TYPE_ARB 0x2013 #define WGL_COLOR_BITS_ARB 0x2014 #define WGL_DEPTH_BITS_ARB 0x2022 #define WGL_STENCIL_BITS_ARB 0x2023 //Accepted as a value in the
and
//parameter arrays of wglChoosePixelFormatARB #define WGL_FULL_ACCELERATION_ARB 0x2027 #define WGL_TYPE_RGBA_ARB 0x202B //Diagnostic related defines #define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506 //------------------ TYPEDEFS AND GLOBAL FUNCTION POINTERS ------------------ //Need a typedef and function pointer for a function that creates an OpenGL //rendering context. /* If this function succeeds, it initializes the context to the initial state defined by the OpenGL specification, and returns a handle to it. The handle can be used (via wglMakeCurrent or wglMakeContextCurrentARB) with any HDC sharing the same pixel format as
, and created on the same device, subject to constraints imposed by the API version. */ typedef HGLRC(WINAPI* wgl_CreateContextAttributes_ARB) (HDC hDC, HGLRC hShareContext, const int *attribList); wgl_CreateContextAttributes_ARB wglCreateContextAttribsARB; //Need a typedef and function pointer for a function that selects an OpenGL //pixel format descriptor. /* wglChoosePixelFormatARB selects pixel formats to return based on the attribute values specified in
and
. Some attribute values must match the pixel format value exactly when the attribute is specified while others specify a minimum criteria, meaning that the pixel format value must meet or exceed the specified value. See the table below for details. */ typedef BOOL(WINAPI* wgl_ChoosePixelFormat_ARB) (HDC hdc, const int *piAttribIList, const float *pfAttribFList, unsigned int nMaxFormats, int *piFormats, unsigned int *nNumFormats); wgl_ChoosePixelFormat_ARB wglChoosePixelFormatARB; /* Other typedefs */ typedef unsigned char* (WINAPI* wgl_GetStringi) (unsigned int name, unsigned int index); wgl_GetStringi glGetStringi; typedef char* (WINAPI* wgl_GetExtensionsString_ARB) (HDC hdc); wgl_GetExtensionsString_ARB wglGetExtensionsStringARB; //------------------ DIAGNOSTIC CODE ------------------ //Required header for StringCchPrintf function. #include
//Usage: ErrorExit(TEXT([ Any function name that's to be expecting an error ])); void ErrorExit(LPCTSTR lpszFunction, bool isOpenGLError, int lineNumber) { if (isOpenGLError) { GLenum glError; if ((glError = glGetError()) != GL_NO_ERROR) { char buffer[128]; switch (glError) { case GL_INVALID_ENUM: snprintf(&buffer[0], sizeof(buffer), "%s", "GL_INVALID_ENUM"); break; case GL_INVALID_VALUE: snprintf(&buffer[0], sizeof(buffer), "%s", "GL_INVALID_VALUE"); break; case GL_INVALID_OPERATION: snprintf(&buffer[0], sizeof(buffer), "%s", "GL_INVALID_OPERATION"); break; case GL_STACK_OVERFLOW: snprintf(&buffer[0], sizeof(buffer), "%s", "GL_STACK_OVERFLOW"); break; case GL_STACK_UNDERFLOW: snprintf(&buffer[0], sizeof(buffer), "%s", "GL_STACK_UNDERFLOW"); break; case GL_OUT_OF_MEMORY: snprintf(&buffer[0], sizeof(buffer), "%s", "GL_OUT_OF_MEMORY"); break; case GL_INVALID_FRAMEBUFFER_OPERATION: snprintf(&buffer[0], sizeof(buffer), "%s", "GL_INVALID_FRAMEBUFFER_OPERATION"); break; } printf("Error: %s on line number: %d\n", buffer, lineNumber); } } else { LPVOID lpMsgBuf; LPVOID lpDisplayBuf; DWORD dw = GetLastError(); FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, 0, NULL); lpDisplayBuf = (LPVOID) LocalAlloc( LMEM_ZEROINIT, (lstrlen((LPCTSTR) lpMsgBuf) + lstrlen((LPCTSTR) lpszFunction) + 128) * sizeof(TCHAR)); //IntelliSense cannot handle deeply nested #define macro types. StringCchPrintfW((LPTSTR) lpDisplayBuf, LocalSize(lpDisplayBuf) / sizeof(TCHAR), TEXT("%s: Failed with error %d on line %d: %s"), lpszFunction, dw, lineNumber, lpMsgBuf); MessageBox(NULL, (LPCTSTR) lpDisplayBuf, TEXT("Error"), MB_OK); LocalFree(lpMsgBuf); LocalFree(lpDisplayBuf); ExitProcess(dw); } } //For OpenGL 4.3 and up, use this Debug Output method. /* void MessageCallback( GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLubyte* message, const void* userParam) { fprintf(stderr, "GL CALLBACK: %s type = 0x%x, severity = 0x%x, message = %s\n", (type == GL_DEBUG_TYPE_ERROR ? "** GL ERROR **" : ""), type, severity, message); } */ //------------------ MAIN CODE ------------------ static LRESULT CALLBACK OpenGLMainWindowCallback (HWND windowHandle, unsigned int message, WPARAM wParam, LPARAM lParam) { LRESULT result = 0; switch (message) { case WM_CLOSE: DestroyWindow(windowHandle); break; case WM_DESTROY: PostQuitMessage(0); break; default: result = DefWindowProc(windowHandle, message, wParam, lParam); break; } return result; } static void initializeOpenGLExtensions() { // Before we can load extensions, we need a dummy OpenGL context, created using a dummy window. // We use a dummy window because you can only set the pixel format for a window once. For the // real window, we want to use wglChoosePixelFormatARB (so we can potentially specify options // that aren't available in PIXELFORMATDESCRIPTOR), but we can't load and use that before we // have a context. //This book promised that C++20 will finally have C designated initializers for struct objects. WNDCLASS dummyWindowClass = {}; dummyWindowClass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; dummyWindowClass.lpfnWndProc = DefWindowProc; dummyWindowClass.hInstance = GetModuleHandle(nullptr); dummyWindowClass.lpszClassName = TEXT("Dummy WGL Initialization Window"); if (!RegisterClass(&dummyWindowClass)) { ErrorExit(TEXT("RegisterClass"), false, __LINE__); } HWND dummyWindowHandle = CreateWindowEx( 0, dummyWindowClass.lpszClassName, dummyWindowClass.lpszClassName, 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, nullptr, nullptr, dummyWindowClass.hInstance, nullptr ); if (!dummyWindowHandle) { ErrorExit(TEXT("CreateWindowEx"), false, __LINE__); } HDC dummyDeviceContext = GetDC(dummyWindowHandle); PIXELFORMATDESCRIPTOR pixelFormatDescriptor = {}; pixelFormatDescriptor.nSize = sizeof(pixelFormatDescriptor); pixelFormatDescriptor.nVersion = 1; pixelFormatDescriptor.iPixelType = PFD_TYPE_RGBA; pixelFormatDescriptor.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; pixelFormatDescriptor.cColorBits = 32; pixelFormatDescriptor.cAlphaBits = 8; pixelFormatDescriptor.iLayerType = PFD_MAIN_PLANE; pixelFormatDescriptor.cDepthBits = 24; pixelFormatDescriptor.cStencilBits = 8; if (!SetPixelFormat(dummyDeviceContext, ChoosePixelFormat(dummyDeviceContext, &pixelFormatDescriptor), &pixelFormatDescriptor)) { ErrorExit(TEXT("Set/Choose PixelFormat"), false, __LINE__); } //Uses the gl/GL.h header defines. HGLRC dummyOpenGLRenderingContext = wglCreateContext(dummyDeviceContext); if (!dummyOpenGLRenderingContext) { ErrorExit(TEXT("wglCreateContext"), false, __LINE__); } if (!wglMakeCurrent(dummyDeviceContext, dummyOpenGLRenderingContext)) { ErrorExit(TEXT("wglMakeCurrent"), false, __LINE__); } wglCreateContextAttribsARB = (wgl_CreateContextAttributes_ARB) wglGetProcAddress("wglCreateContextAttribsARB"); wglChoosePixelFormatARB = (wgl_ChoosePixelFormat_ARB) wglGetProcAddress("wglChoosePixelFormatARB"); wglGetExtensionsStringARB = (wgl_GetExtensionsString_ARB) wglGetProcAddress("wglGetExtensionsStringARB"); wglMakeCurrent(dummyDeviceContext, nullptr); wglDeleteContext(dummyOpenGLRenderingContext); ReleaseDC(dummyWindowHandle, dummyDeviceContext); DestroyWindow(dummyWindowHandle); } static HGLRC initializeOpenGL(HDC realDeviceContext, bool isCompatibilityMode, int majorVersion, int minorVersion, bool useOldWGLCreateContext = false) { initializeOpenGLExtensions(); // Now we can choose a pixel format the modern way, using wglChoosePixelFormatARB. //The last value should be 0, to end parsing the pixel format attributes array. int pixelFormatAttributes[] = { WGL_DRAW_TO_WINDOW_ARB, GL_TRUE, WGL_SUPPORT_OPENGL_ARB, GL_TRUE, WGL_DOUBLE_BUFFER_ARB, GL_TRUE, WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB, WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB, WGL_COLOR_BITS_ARB, 32, WGL_DEPTH_BITS_ARB, 24, WGL_STENCIL_BITS_ARB, 8, 0 }; //BOOL(WINAPI* wgl_ChoosePixelFormat_ARB) (HDC hdc, const int *piAttribIList, const float //*pfAttribFList, unsigned int nMaxFormats, int *piFormats, unsigned int *nNumFormats); int pixelFormat; unsigned int numberOfFormats; wglChoosePixelFormatARB(realDeviceContext, pixelFormatAttributes, nullptr, 1, &pixelFormat, &numberOfFormats); if (!numberOfFormats) { ErrorExit(TEXT("wglChoosePixelFormatARB"), true, __LINE__); } PIXELFORMATDESCRIPTOR realPixelFormatDescriptor = {}; DescribePixelFormat(realDeviceContext, pixelFormat, sizeof(realPixelFormatDescriptor), &realPixelFormatDescriptor); if (!SetPixelFormat(realDeviceContext, pixelFormat, &realPixelFormatDescriptor)) { ErrorExit(TEXT("SetPixelFormat"), false, __LINE__); } //Specify we want to create an OpenGL X.Y core profile context. //The last value should be 0, to end parsing the pixel format attributes array. //If the requested OpenGL version is less than 3.2, WGL_CONTEXT_PROFILE_MASK_ARB is //ignored and the functionality of the context is determined solely by the requested //version. int gl_attributes[] = { WGL_CONTEXT_MAJOR_VERSION_ARB, majorVersion, WGL_CONTEXT_MINOR_VERSION_ARB, minorVersion, WGL_CONTEXT_FLAGS_ARB, NULL, WGL_CONTEXT_PROFILE_MASK_ARB, (isCompatibilityMode ? WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB : WGL_CONTEXT_CORE_PROFILE_BIT_ARB), 0 }; HGLRC gl_renderingContext; if (useOldWGLCreateContext) { //This will always give you the most compatible OpenGL version possible with the //device context. gl_renderingContext = wglCreateContext(realDeviceContext); } else { //This will give the developers a way to control what compatible OpenGL version //specified by the major and minor version is possible with the device context. gl_renderingContext = wglCreateContextAttribsARB(realDeviceContext, nullptr, gl_attributes); } if (!gl_renderingContext) { ErrorExit(TEXT("wglCreateContextAttribsARB with gl_attributes"), true, __LINE__); } if (!wglMakeCurrent(realDeviceContext, gl_renderingContext)) { ErrorExit(TEXT("wglMakeCurrent with gl_renderingContext"), true, __LINE__); } return gl_renderingContext; } static HWND createWindow(HINSTANCE instanceHandle, long width, long height) { WNDCLASS windowClass = {}; windowClass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; windowClass.lpfnWndProc = OpenGLMainWindowCallback; windowClass.hInstance = instanceHandle; windowClass.hCursor = LoadCursor(nullptr, IDC_ARROW); windowClass.hbrBackground = nullptr; windowClass.lpszClassName = TEXT("WGL OpenGL Window"); if (!RegisterClass(&windowClass)) { ErrorExit(TEXT("RegisterClass"), false, __LINE__); } //This value is used to determine whether to take into consideration the menu toolbar //for the created window. const BOOL shouldIncludeMenuToolbarHeight = FALSE; DWORD windowStyles = WS_OVERLAPPEDWINDOW; RECT windowRect = {}; windowRect.right = width; windowRect.bottom = height; AdjustWindowRect(&windowRect, windowStyles, shouldIncludeMenuToolbarHeight); HWND window = CreateWindowEx( 0, windowClass.lpszClassName, windowClass.lpszClassName, windowStyles, CW_USEDEFAULT, CW_USEDEFAULT, windowRect.right - windowRect.left, windowRect.bottom - windowRect.top, nullptr, nullptr, instanceHandle, nullptr ); if (!window) { ErrorExit(TEXT("CreateWindowEx"), false, __LINE__); } return window; } int main() { HINSTANCE currentInstanceHandle = GetModuleHandle(nullptr); HWND glMainWindow = createWindow(currentInstanceHandle, 1024, 768); HDC glDeviceContext = GetDC(glMainWindow); //The highest it can go is OpenGL 4.6, as of March 19, 2019. //Major = 1, minor = 0 ===> Always fetches the most recent version of OpenGL supported. HGLRC glRenderingContext = initializeOpenGL(glDeviceContext, false, WANT_MAJOR_VERSION, WANT_MINOR_VERSION); //Good thing there's the SW_SHOWDEFAULT flag. Otherwise, we need to use CreateProcess //function, set up a bunch of stuffs, then have the created "STARTUPINFO" struct take //the "wShowWindow" struct member and pass it to "ShowWindow" function. ShowWindow(glMainWindow, SW_SHOWDEFAULT); UpdateWindow(glMainWindow); //Great place to run OpenGL one-time tasks here. const char* glVersionString = (const char*) glGetString(GL_VERSION); printf("OpenGL version: %s\n", glVersionString); bool isRunning = true; while (isRunning) { MSG message; while (PeekMessage(&message, nullptr, 0, 0, PM_REMOVE)) { if (message.message == WM_QUIT) { isRunning = false; } else { TranslateMessage(&message); DispatchMessage(&message); } } //XNA Framework default color: Cornflower Blue - rgb(100, 149, 237) glClearColor(100.0f / 255.0f, 149.0f / 255.0f, 237.0f / 255.0f, 1.0f); //Clearing the screen. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //DO OpenGL RENDERING HERE /* WAIT!! WHAT DO I DO HERE? PERSPECTIVE PROJECTION MATRIX */ //END OpenGL RENDERING HERE SwapBuffers(glDeviceContext); } return 0; }