最近正在学习OpenGL,我认为学习的最快方法就是做一个小项目了。
如果对OpenGL感兴趣的话,这里推荐一个很好的学习网站 https://learnopengl-cn.github.io/
我用的是 vs2013,使用C++语言编写项目。这个小项目叫Simple2D,意味着简易的2D框架。最终的目的是可以渲染几何图形和图片,最后尝试加上一个2D粒子系统和Box2D物理引擎,并编译一个简单的游戏。
第一步,就是创建一个Win32项目。
接下来,生成一个窗口。编写一个RenderWindow类,用于创建窗口。头文件很简单
#pragma once
#include "Common.h"
#include <Windows.h>
#include <string> namespace Simple2D
{
class DLL_export RenderWindow
{
public:
RenderWindow(int width, int height, const char* title = "Simple2D");
~RenderWindow(); void createWindow(int width, int height, const char* title);
void setClientSize(int width, int height); static LRESULT WINAPI static_window_proc(HWND wnd, UINT msg, WPARAM wParam, LPARAM lParam); private:
HWND hwnd;
};
}
下面是它的实现
#include "RenderWindow.h"
#include <exception> #define CLASS_NAME "Simple2DApplication" namespace Simple2D
{
RenderWindow::RenderWindow(int width, int height, const char* title)
{
this->createWindow(width, height, title);
} RenderWindow::~RenderWindow()
{ } void RenderWindow::createWindow(int width, int height, const char* title)
{
WNDCLASS wndclass;
memset(&wndclass, , sizeof(wndclass)); wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
wndclass.lpfnWndProc = (WNDPROC)RenderWindow::static_window_proc;
wndclass.cbClsExtra = ;
wndclass.cbWndExtra = ;
wndclass.hInstance = ( HINSTANCE ) GetModuleHandle();
wndclass.hIcon = ;
wndclass.hCursor = ;
wndclass.hbrBackground = CreateSolidBrush(RGB(, , ));
wndclass.lpszMenuName = ;
wndclass.lpszClassName = TEXT(CLASS_NAME);
RegisterClass(&wndclass); /* 创建窗口 */
CreateWindowA(CLASS_NAME, title, WS_OVERLAPPEDWINDOW, , , width, height,
NULL, NULL, ( HINSTANCE ) GetModuleHandle(), this); if ( hwnd == NULL ) throw std::exception("Unable to create window"); /* 显示窗口 */
ShowWindow(hwnd, SW_SHOWNA);
setClientSize(width, height);
} void RenderWindow::setClientSize(int width, int height)
{
/* 设置客户区大小为 width, height */
RECT rectProgram, rectClient;
GetWindowRect(hwnd, &rectProgram);
GetClientRect(hwnd, &rectClient); int borderw = rectProgram.right - rectProgram.left - (rectClient.right - rectClient.left);
int borderh = rectProgram.bottom - rectProgram.top - (rectClient.bottom - rectClient.top); borderw += width;
borderh += height; int showToScreenX = GetSystemMetrics(SM_CXSCREEN) / - borderw / ;
int showToScreenY = GetSystemMetrics(SM_CYSCREEN) / - borderh / ; MoveWindow(hwnd, showToScreenX, showToScreenY, borderw, borderh, false);
} LRESULT WINAPI RenderWindow::static_window_proc(HWND wnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
RenderWindow* self = nullptr;
if ( msg == WM_CREATE ) {
LPCREATESTRUCT create_struct = ( LPCREATESTRUCT ) lParam;
self = ( RenderWindow* ) create_struct->lpCreateParams;
SetWindowLongPtr(wnd, GWLP_USERDATA, ( LONG_PTR ) self);
self->hwnd = wnd;
}
else {
self = ( RenderWindow* ) GetWindowLongPtr(wnd, GWLP_USERDATA);
} switch ( msg ) {
case WM_CLOSE:
PostQuitMessage();
break;
case WM_DESTROY:
PostQuitMessage();
break;
case WM_PAINT:
RECT rect;
if ( GetUpdateRect(wnd, &rect, FALSE) ) {
ValidateRect(wnd, &rect);
}
break;
}
return DefWindowProc(wnd, msg, wParam, lParam);
}
}
主要是注册窗口类,创建窗口和显示窗口。有一点需要注意的是,我这里的窗口大小并不是真正的窗口大小,而是客户区的大小,在 函数 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 = { };
while ( msg.message != WM_QUIT ) {
if ( PeekMessage(&msg, , , , PM_REMOVE) ) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else {
// TODO:
}
} return ;
}
只是创建了对象 RenderWindow,和消息循环。
运行后,得到下面的结果
按照我推荐的那个教程,你也可以使用 GLFW 库来创建一个窗口,这种方法更简单。有兴趣的可以尝试一下。
这里是源码地址:http://files.cnblogs.com/files/ForEmail5/Simple2D-01.rar