基于OpenGL编写一个简易的2D渲染框架-01 创建窗口
最近正在学习OpenGL,我认为学习的最快方法就是做一个小项目了。
如果对OpenGL感兴趣的话,这里推荐一个很好的学习网站 https://learnopengl-cn.github.io/
我用的是 vs2013,使用C++语言编写项目。这个小项目叫Simple2D,意味着简易的2D框架。最终的目的是可以渲染几何图形和图片,最后尝试加上一个2D粒子系统和Box2D物理引擎,并编译一个简单的游戏。
第一步,就是创建一个Win32项目。
接下来,生成一个窗口。编写一个RenderWindow类,用于创建窗口。头文件很简单
1 #pragma once 2 #include "Common.h" 3 #include <Windows.h> 4 #include <string> 5 6 namespace Simple2D 7 { 8 class DLL_export RenderWindow 9 { 10 public: 11 RenderWindow(int width, int height, const char* title = "Simple2D"); 12 ~RenderWindow(); 13 14 void createWindow(int width, int height, const char* title); 15 void setClientSize(int width, int height); 16 17 static LRESULT WINAPI static_window_proc(HWND wnd, UINT msg, WPARAM wParam, LPARAM lParam); 18 19 private: 20 HWND hwnd; 21 }; 22 }
下面是它的实现
1 #include "RenderWindow.h" 2 #include <exception> 3 4 #define CLASS_NAME "Simple2DApplication" 5 6 namespace Simple2D 7 { 8 RenderWindow::RenderWindow(int width, int height, const char* title) 9 { 10 this->createWindow(width, height, title); 11 } 12 13 RenderWindow::~RenderWindow() 14 { 15 16 } 17 18 void RenderWindow::createWindow(int width, int height, const char* title) 19 { 20 WNDCLASS wndclass; 21 memset(&wndclass, 0, sizeof(wndclass)); 22 23 wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS; 24 wndclass.lpfnWndProc = (WNDPROC)RenderWindow::static_window_proc; 25 wndclass.cbClsExtra = 0; 26 wndclass.cbWndExtra = 0; 27 wndclass.hInstance = ( HINSTANCE ) GetModuleHandle(0); 28 wndclass.hIcon = 0; 29 wndclass.hCursor = 0; 30 wndclass.hbrBackground = CreateSolidBrush(RGB(255, 255, 255)); 31 wndclass.lpszMenuName = 0; 32 wndclass.lpszClassName = TEXT(CLASS_NAME); 33 RegisterClass(&wndclass); 34 35 /* 创建窗口 */ 36 CreateWindowA(CLASS_NAME, title, WS_OVERLAPPEDWINDOW, 100, 100, width, height, 37 NULL, NULL, ( HINSTANCE ) GetModuleHandle(0), this); 38 39 if ( hwnd == NULL ) throw std::exception("Unable to create window"); 40 41 /* 显示窗口 */ 42 ShowWindow(hwnd, SW_SHOWNA); 43 setClientSize(width, height); 44 } 45 46 void RenderWindow::setClientSize(int width, int height) 47 { 48 /* 设置客户区大小为 width, height */ 49 RECT rectProgram, rectClient; 50 GetWindowRect(hwnd, &rectProgram); 51 GetClientRect(hwnd, &rectClient); 52 53 int borderw = rectProgram.right - rectProgram.left - (rectClient.right - rectClient.left); 54 int borderh = rectProgram.bottom - rectProgram.top - (rectClient.bottom - rectClient.top); 55 56 borderw += width; 57 borderh += height; 58 59 int showToScreenX = GetSystemMetrics(SM_CXSCREEN) / 2 - borderw / 2; 60 int showToScreenY = GetSystemMetrics(SM_CYSCREEN) / 2 - borderh / 2; 61 62 MoveWindow(hwnd, showToScreenX, showToScreenY, borderw, borderh, false); 63 } 64 65 LRESULT WINAPI RenderWindow::static_window_proc(HWND wnd, UINT msg, WPARAM wParam, LPARAM lParam) 66 { 67 RenderWindow* self = nullptr; 68 if ( msg == WM_CREATE ) { 69 LPCREATESTRUCT create_struct = ( LPCREATESTRUCT ) lParam; 70 self = ( RenderWindow* ) create_struct->lpCreateParams; 71 SetWindowLongPtr(wnd, GWLP_USERDATA, ( LONG_PTR ) self); 72 self->hwnd = wnd; 73 } 74 else { 75 self = ( RenderWindow* ) GetWindowLongPtr(wnd, GWLP_USERDATA); 76 } 77 78 switch ( msg ) { 79 case WM_CLOSE: 80 PostQuitMessage(0); 81 break; 82 case WM_DESTROY: 83 PostQuitMessage(0); 84 break; 85 case WM_PAINT: 86 RECT rect; 87 if ( GetUpdateRect(wnd, &rect, FALSE) ) { 88 ValidateRect(wnd, &rect); 89 } 90 break; 91 } 92 return DefWindowProc(wnd, msg, wParam, lParam); 93 } 94 }
主要是注册窗口类,创建窗口和显示窗口。有一点需要注意的是,我这里的窗口大小并不是真正的窗口大小,而是客户区的大小,在 函数 setClientSize 中可以看出,我重新计算了窗口的真正大小。
最后是主函数
#pragma once #include <Windows.h> #include "RenderWindow.h" using namespace Simple2D; int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { RenderWindow window(DEFAULT_WIN_W, DEFAULT_WIN_H); MSG msg = { 0 }; while ( msg.message != WM_QUIT ) { if ( PeekMessage(&msg, 0, 0, 0, PM_REMOVE) ) { TranslateMessage(&msg); DispatchMessage(&msg); } else { // TODO: } } return 0; }
只是创建了对象 RenderWindow,和消息循环。
运行后,得到下面的结果
按照我推荐的那个教程,你也可以使用 GLFW 库来创建一个窗口,这种方法更简单。有兴趣的可以尝试一下。
这里是源码地址:https://files.cnblogs.com/files/ForEmail5/Simple2D-01.rar