最近正在学习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

基于OpenGL编写一个简易的2D渲染框架-01 创建窗口的更多相关文章

  1. 基于OpenGL编写一个简易的2D渲染框架-05 渲染文本

    阅读文章前需要了解的知识:文本渲染 https://learnopengl-cn.github.io/06%20In%20Practice/02%20Text%20Rendering/ 简要步骤: 获 ...

  2. 基于OpenGL编写一个简易的2D渲染框架-06 编写一个粒子系统

    在这篇文章中,我将详细说明如何编写一个简易的粒子系统. 粒子系统可以模拟许多效果,下图便是这次的粒子系统的显示效果.为了方便演示,就弄成了一个动图. 图中,同时显示了 7 种不同粒子效果,看上去效果挺 ...

  3. 基于OpenGL编写一个简易的2D渲染框架-04 绘制图片

    阅读文章前需要了解的知识,纹理:https://learnopengl-cn.github.io/01%20Getting%20started/06%20Textures/ 过程简述:利用 FreeI ...

  4. 基于OpenGL编写一个简易的2D渲染框架-03 渲染基本几何图形

    阅读文章前需要了解的知识,你好,三角形:https://learnopengl-cn.github.io/01%20Getting%20started/04%20Hello%20Triangle/ 要 ...

  5. 基于OpenGL编写一个简易的2D渲染框架-02 搭建OpenGL环境

    由于没有使用GLFW库,接下来得费一番功夫. 阅读这篇文章前请看一下这个网页:https://learnopengl-cn.github.io/01%20Getting%20started/02%20 ...

  6. 基于OpenGL编写一个简易的2D渲染框架-08 重构渲染器-整体架构

    事实上,前面编写的渲染器 Renderer 非常简陋,虽然能够进行一些简单的渲染,但是它并不能满足我们的要求. 当渲染粒子系统时,需要开启混合模式,但渲染其他顶点时却不需要开启混合模式.所以同时渲染粒 ...

  7. 基于OpenGL编写一个简易的2D渲染框架-09 重构渲染器-Shader

    Shader 只是进行一些简单的封装,主要功能: 1.编译着色程序 2.绑定 Uniform 数据 3.根据着色程序的顶点属性传递顶点数据到 GPU 着色程序的编译 GLuint Shader::cr ...

  8. 基于OpenGL编写一个简易的2D渲染框架-11 重构渲染器-Renderer

    假如要渲染一个纯色矩形在窗口上,应该怎么做? 先确定顶点的格式,一个顶点应该包含位置信息 vec3 以及颜色信息 vec4,所以顶点的结构体定义可以这样: struct Vertex { Vec3 p ...

  9. 基于OpenGL编写一个简易的2D渲染框架-10 重构渲染器-Pass

    Pass,渲染通路,一个渲染通路指的是一次像素处理和一次顶点处理,也就是指的是一次绘制.简单来说就是顶点数据在渲染管线中走一遍最后绘制. 渲染粒子系统的粒子时,需要开启 OpenGL 的混合模式,并使 ...

随机推荐

  1. 用复制mysql/data 文件夹 下面的数据库的形式来复制数据库出现的问题

    用复制mysql/data 文件夹 下面的数据库的形式来复制数据库出现的问题 提示找不到表,我去看了一下,丢失了很多个表: 问题: 直接拷贝data下的数据库数据进行备份 , 发现部分数据表不见了. ...

  2. 【转】每天一个linux命令(51):lsof命令

    原文网址:http://www.cnblogs.com/peida/archive/2013/02/26/2932972.html lsof(list open files)是一个列出当前系统打开文件 ...

  3. Anaconda 使用(解决python包管理与环境管理)

    Anaconda完全入门指南(对python环境和原理,讲的比较透彻):https://www.jianshu.com/p/eaee1fadc1e9 用pip一个一个安装第三方库费时费力,还需要考虑兼 ...

  4. async(await)知识点

    async 函数是 Generator 函数的语法糖. async 函数对 Generator 函数的改进体现在: async 内置执行器. Generator 函数的执行必须靠执行器,需要调用 ne ...

  5. centos7 安装Zabbix3.0

    1 安装Mariadb数据库(代替MySQL)yum -y install mariadb*systemctl start mariadbsystemctl enable mariadb #自启动 2 ...

  6. bzoj 3572 [Hnoi2014]世界树——虚树

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3572 关于虚树:https://www.cnblogs.com/zzqsblog/p/556 ...

  7. jmeter测试TCP服务器/模拟发送TCP请求

    jmeter测试TCP服务器,使用TCP采样器模拟发送TCP请求. TCP采样器:打开一个到指定服务器的TCP / IP连接,然后发送指定文本并等待响应. jmeter模拟发送TCP请求的方法: 1. ...

  8. 关于WCF

    凡是被DataMember声明修饰的属性,必须要有get和set访问器,靠靠靠!!!! 给接口加 XmlSerializerFormat 强制用xml序列化.

  9. 解决EF一对一或多对一的删除

    people 类中有 zhengshu类 且是一对一,现在要删除people类中的zhengshu 网上看了N多办法,什么更新外键什么滴. 其实方法简单极了 using (KJExamEntity c ...

  10. [转载]Linux下关于system调用

    曾经的曾经,被system()函数折磨过,之所以这样,是因为对system()函数了解不够深入.只是简单的知道用这个函数执行一个系统命令,这远远不够,它的返回值.它所执行命令的返回值以及命令执行失败原 ...