上一篇博客 【OpenGL】七、桌面窗口搭建 ( 导入头文件 | 桌面程序入口函数 | 注册窗口 | 创建窗口 | 显示窗口 ) 完成了 桌面初始化的操作 , 注册桌面窗口 , 创建桌面窗口 , 显示桌面窗口 ;
本篇博客开始进行 OpenGL 渲染环境初始化 ;
导入 OpenGL 的两个头文件 : GL.h 和 GLU.h , 需要注意的是 , 注意导入头文件的顺序 , 导入这两个头文件之前 , 必须 先导入 windows.h 头文件 之后再导入 opengl 头文件 , 否则报错 ;
// 导入 OpenGL 的个头文件
// 注意 : 必须先导入 windows.h 头文件之后再导入 opengl 头文件
#include <gl/GL.h>
#include <gl/GLU.h>
链接 OpenGL 库 :
使用 #pragma comment 预处理指令 , 链接 OpenGL 库 ,
下面代码中使用 #pragma comment(lib, “opengl32.lib”) 预处理指令 , 链接了 opengl32.lib 函数库 , 相当于调用了该库 , 在后续代码中可以使用该 opengl32.lib 函数库中定义的函数 , 这里就可以调用 OpenGL 相关函数了 ;
// 链接 OpenGL 库
#pragma comment(lib, "opengl32.lib")
#pragma comment(lib, "glu32.lib")
将 Windows 桌面窗口改成 OpenGL 窗口 :
Windows 创建窗口流程是先 注册窗口 , 然后 创建窗口 , 最后 显示窗口 ;
将 Windows 桌面窗口改成 OpenGL 窗口操作是在 创建窗口完成后 进行的 ;
下面开始逐个步骤讲解 , 如何初始化 OpenGL 窗口 ;
窗口设备在初始化 OpenGL 上下文 , 和进行 OpenGL 绘制时都需要用到 , 这里设置到全局变量中 ;
// 窗口设备
// 提取到全局变量中
HDC dc = NULL;
调用 CreateWindowW 方法创建窗口后 , 返回 HWND 结构体对象 , 将其传入 GetDC 方法 , 即可获取窗口设备 ;
hInst = hInstance; // 将实例句柄存储在全局变量中
// 创建窗口的核心逻辑
HWND hWnd = CreateWindowW(
szWindowClass, // 窗口主类
szTitle, // 窗口标题名称
WS_OVERLAPPEDWINDOW, // 窗口风格
100 , // x 坐标
100 , // y 坐标
800, // 宽度
600, // 高度
nullptr, // 父窗口
nullptr, // 菜单
hInstance, // 程序实体
nullptr);
// 如果创建失败 , 直接退出
if (!hWnd)
{
return FALSE;
}
// 创建 OpenGL 的渲染上下文
// 获取窗口设备 ★
dc = GetDC(hWnd);
像素格式描述符是 PIXELFORMATDESCRIPTOR 类型的结构体 , 其字段中可以设置
绘制标志位中可以设置多个标志位 , 如下代码中的标志位含义 :
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
部分代码示例 :
// 颜色描述符, 像素格式描述符 , 选取 OpenGL 渲染的像素格式
PIXELFORMATDESCRIPTOR pfd;
// 将 PIXELFORMATDESCRIPTOR 结构体清空
memset(&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR));
// 填充结构体
// 设置版本号
pfd.nVersion = 1;
// 结构体大小
pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
// 颜色缓冲区 32 位
pfd.cColorBits = 32;
// 深度缓冲区 24 位
pfd.cDepthBits = 24;
pfd.cStencilBits = 8;
// 颜色格式
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.iLayerType = PFD_MAIN_PLANE;
// 分别设置 绘制到桌面窗口 , OpenGL 支持 , 双缓冲 标志位
// 双缓冲区可以让画面更流畅
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
// 选择像素格式 , 如果返回 -1 , 说明选择像素格式失败 , 一般情况下该选择是成功的
int pixelFormat = ChoosePixelFormat(dc, &pfd);
// 设置像素格式
SetPixelFormat(dc, pixelFormat, &pfd);
先选择像素格式 , 该操作需要调用 ChoosePixelFormat 方法 , 让系统选择像素格式 , 如果返回 -1 , 说明选择像素格式失败 , 一般情况下该选择是成功的 ;
选择完像素格式之后 , 需要调用 SetPixelFormat 方法设置像素格式 ;
// 选择像素格式 , 如果返回 -1 , 说明选择像素格式失败 , 一般情况下该选择是成功的
int pixelFormat = ChoosePixelFormat(dc, &pfd);
// 设置像素格式
SetPixelFormat(dc, pixelFormat, &pfd);
根据窗口设备创建 OpenGL 上下文对象 , 注意该操作必须在设置完像素格式后进行操作 , 然后设置该 OpenGL 上下文对象 ;
其中 dc 是 窗口设备 , HDC dc = GetDC(hWnd);
// 创建 OpenGL 上下文对象 , 注意该操作必须在设置完像素格式后进行操作
HGLRC rc = wglCreateContext(dc);
// 设置 OpenGL 上下文对象 , 将 rc 和 dc 作为当前的渲染设备
wglMakeCurrent(dc, rc);
调用 glClearColor 方法 , 设置清除缓冲区背景颜色 , 传入的四个参数 红色 , 绿色 , 蓝色 , 透明度 值 , 取值范围 0 ~ 1 ;
设置了该清除缓冲区背景颜色后 , 调用 glClear 方法 , 即可擦除当前的颜色缓冲区 , 显示当前的颜色 ;
// 设置清除缓冲区背景颜色
// glClearColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
// 对应的参数是 红色 , 绿色 , 蓝色 , 透明度
// 这里设置的是红色
glClearColor(1.0, 0.0, 0.0, 1.0);
// 创建 OpenGL 的渲染上下文
// 获取窗口设备
dc = GetDC(hWnd);
// 颜色描述符, 像素格式描述符 , 选取 OpenGL 渲染的像素格式
PIXELFORMATDESCRIPTOR pfd;
// 将 PIXELFORMATDESCRIPTOR 结构体清空
memset(&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR));
// 填充结构体
// 设置版本号
pfd.nVersion = 1;
// 结构体大小
pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
// 颜色缓冲区 32 位
pfd.cColorBits = 32;
// 深度缓冲区 24 位
pfd.cDepthBits = 24;
pfd.cStencilBits = 8;
// 颜色格式
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.iLayerType = PFD_MAIN_PLANE;
// 分别设置 绘制到桌面窗口 , OpenGL 支持 , 双缓冲 标志位
// 双缓冲区可以让画面更流畅
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
// 选择像素格式 , 如果返回 -1 , 说明选择像素格式失败 , 一般情况下该选择是成功的
int pixelFormat = ChoosePixelFormat(dc, &pfd);
// 设置像素格式
SetPixelFormat(dc, pixelFormat, &pfd);
// 创建 OpenGL 上下文对象 , 注意该操作必须在设置完像素格式后进行操作
HGLRC rc = wglCreateContext(dc);
// 设置 OpenGL 上下文对象 , 将 rc 和 dc 作为当前的渲染设备
wglMakeCurrent(dc, rc);
// 设置清除缓冲区背景颜色
// glClearColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
// 对应的参数是 红色 , 绿色 , 蓝色 , 透明度
// 这里设置的是红色
glClearColor(1.0, 0.0, 0.0, 1.0);
在显示窗口后的 消息循环 中 , 执行渲染相关操作 , 该操作调用频繁 , 基本每秒调用几十次 ;
调用 glClear(GL_COLOR_BUFFER_BIT) , 擦除颜色缓冲区 ,
调用 SwapBuffers 绘制 OpenGL 图像 ;
// 主消息循环:
while (GetMessage(&msg, nullptr, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
// 渲染场景
// 清除缓冲区 ,
// 使用之前设置的 glClearColor(1.0, 0.0, 0.0, 1.0) 擦除颜色缓冲区
// 红色背景
glClear(GL_COLOR_BUFFER_BIT);
// 将后缓冲区绘制到前台
SwapBuffers(dc);
}
展示效果 :
GitHub 地址 : https://github.com/han1202012/OpenGL
博客源码快照 : https://download.csdn.net/download/han1202012/14504132