win32原生API实现OpenGL例子(无glew,glut等第三方依赖库)

2023-11-05

正文:

  话不多说,直接上代码:

#include<Windows.h>
#include<GL/GL.h>
#pragma comment(lib,"opengl32.lib")
//注册win32窗口类
BOOL win32_regist_class(const char* class_name)
{
 WNDCLASSEXA cs =
 {
  sizeof(WNDCLASSEXA),
  CS_HREDRAW | CS_VREDRAW,
  [](HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)->LRESULT
   {
    switch (msg)
    {
    case WM_NCCREATE:
    {
     SetWindowLongPtrA(hwnd, GWLP_USERDATA, (LONG_PTR)((LPCREATESTRUCTA)lparam)->lpCreateParams);
     break;
    };
    case WM_PAINT:
    {
     PAINTSTRUCT ps;
     BeginPaint(hwnd, &ps);
     EndPaint(hwnd, &ps);
     break;
    }
    case WM_ERASEBKGND://阻止窗口重绘,不然当窗口从边界移回来时会看到背景色
    {
     return TRUE;
    }
    case WM_DESTROY:
    {
     PostQuitMessage(0);
     break;
    }
    default:
     break;
    }
    return DefWindowProcA(hwnd, msg, wparam, lparam);
   },
  0,
  0,
  (HINSTANCE)GetModuleHandleA(nullptr),
  nullptr,
  LoadCursorA(nullptr,IDC_ARROW),
  (HBRUSH)COLOR_WINDOW,
  nullptr,
  class_name,
  nullptr
 };
 return RegisterClassExA(&cs);
}
//创建win32窗口
HWND win32_create(const char*class_name,const char*window_name,int x, int y, int width, int height)
{
 return CreateWindowExA(0, class_name,window_name, WS_OVERLAPPEDWINDOW | WS_VISIBLE,
  x, y, width, height,
  nullptr, nullptr, GetModuleHandle(nullptr), nullptr);
}
//获取可用于OpenGL绘制的DC
HDC win32_get_gl_dc(HWND hwnd)
{
 PIXELFORMATDESCRIPTOR pfd = {};
 pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
 pfd.nVersion = 1;
 pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
 auto hdc = GetDC(hwnd);
 auto pixelFormat = ChoosePixelFormat(hdc, &pfd);
 if (!pixelFormat)
 {
  ReleaseDC(hwnd, hdc);
  return nullptr;
 }
 if (!SetPixelFormat(hdc, pixelFormat, &pfd))
 {
  ReleaseDC(hwnd, hdc);
  return nullptr;
 }
 return hdc;
}
//处理win32消息
BOOL win32_peek_message(HWND hwnd)
{
 MSG msg;
 if (PeekMessageA(&msg, hwnd, 0, 0, PM_REMOVE))
 {
  if (msg.message == WM_QUIT)
   return FALSE;
  TranslateMessage(&msg);
  DispatchMessageA(&msg);
 }
 return TRUE;
}
//创建OpenGL API
HGLRC gl_create(HDC hdc)
{
 auto hglrc = wglCreateContext(hdc);
 if (!hglrc)
  return nullptr;
 if (!wglMakeCurrent(hdc, hglrc))
  return nullptr;
 //******获取高版本API(glew的最主要功能就是这是一步)
 /*
  在这个里获取会用到的opengl api,这些API名称可以去opengl官网查询
  因为需要的功能不复杂,不需要使用着色器,GL1.0版本的API足够用了。
  所以这里并没有获取所有高版本的API,只获取了一个glCreateShader作为例子。
 */
 auto glCreateShader=(GLuint(__stdcall*)(GLenum type))wglGetProcAddress("glCreateShader");
 //******获取高版本API结束
 return hglrc;
}
//渲染
void render(HWND hwnd, HDC hdc, HGLRC hglrc)
{
 RECT rc;
 GetClientRect(hwnd, &rc);
 wglMakeCurrent(hdc, hglrc);//关联gl的DC到窗口的hdc。如果是单DC,只需关联一次即可
 glViewport(0, 0, rc.right, rc.bottom);//设置视口
 glClearColor(0.4f, 0.5f, 0.4f, 0);//设置清屏时的颜色
 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);//清屏。这里清掉颜色缓冲区与深度缓冲区
 //******以下内容为1.0版本绘制方法,高版本的不建议这样绘制了,尽量使用glDraw*系列函数以提高性能
 //设置点
 glBegin(GL_TRIANGLE_STRIP); //以画线方式绘制,
 glColor3f(1, 0, 0); glVertex2f(0.0f, 0.0f);//中心端点,为红色
 glColor3f(0, 1, 0); glVertex2f(0.5f, 0.5f);//到左上角中点端点,为绿色
 glColor3f(0, 0, 1); glVertex2f(0.0f, 0.5f);//到上方中点端点,为蓝色
 glEnd();
 //glDrawArrays(GL_LINES, 0, 2);//经过测试,1.0版本不需要调用此函数
}
int main(int argc, const char* argv[])
{
 win32_regist_class("test");
 auto hwnd = win32_create("test", "test", 100, 100, 500, 400);
 auto hdc = win32_get_gl_dc(hwnd);
 auto hglrc = gl_create(hdc);
 while (true)
 {
  if(win32_peek_message(nullptr)==FALSE)
   break;
  render(hwnd, hdc, hglrc);
  SwapBuffers(wglGetCurrentDC());//翻转缓冲区(因为使用了双缓冲,必须要翻转才能看到绘制结果)
 }
}

  整个代码约140行,不算多。这是上次QQ群里一个人问我之后我改了之前的代码写出来的,逻辑比之前强很多,个人感觉优势在于不再需要乱七八糟的第三方库,可以作为学习用,在自己获取高版本GL的API后也可以简单取代glut。
  主要部分是win32_get_gl_dc(HWND hwnd)这个函数。这个函数执行成功了就可以继续后续的OpenGL操作,不然的话就会出现GL上下文创建失败的情况,导致后续的OpenGL操作无效。

附:gles32 API获取文件说明

  实现我已经放到我的资源里:_gles32.h,直接点击下载就行,只有一个头文件,是从GLES32官网上扒了gles32头文件下来改了实现的。
用法:

  1. 先调用上面的gl_create函数创建gl环境,不然会像gl_create代码里的注释说的一样接下来的操作失败(glew里包含有这步,所以可以直接用);
gl_load_api(wglGetProcAddress);

至于头文件包含

#include"_gles32.h"

这个不用我多说了吧。
  上面的wglGetProcAddress这个就是win32下用来获取高版本GL API的平台函数,之所以放到这里来作为参数传入而不写在_gles32.h里就是希望让_gles32.h平台独立化,所以gles32.h里是没有任何与win32相关的API的,唯一一个相关的已经被放到参数这来了。
  实现这个主要是因为原来用的glew还需要下载一个库,研究了下glew发现也没什么特别的,就去gles官网上扒了头文件下来自己改了下就完成实现了。这样下以后就可以不用再去包含一个第三方库。
  实际上我还实现了一个_gl_wrapper.h文件来对_gles32.h做包装,里面包含了着色器的操作封装及其他东西,但我觉得这不是OpenGL的核心东西,所以没放到资源里。
  完整的调用代码如下:

#include<Windows.h>
#include<GL/GL.h>
//包含头文件
#include"_gles32.h"
#pragma comment(lib,"opengl32.lib")

int main(int argc, const char* argv[])
{
 win32_regist_class("test");
 auto hwnd = win32_create("test", "test", 100, 100, 500, 400);
 auto hdc = win32_get_gl_dc(hwnd);
 //哈哈,你没看错,这就是上面那个例子的main函数,就改了这里
 auto hglrc = wglCreateContext(hdc);
 wglMakeCurrent(hdc, hglrc);
 //加载高版本GL API(就一个函数)
 gl_load_api(wglGetProcAddress);
 //加载API结束,接下来就可以正常使用高版本的GLES API了,
 //例如glCreateShader、glCreateProgram之类的。
 
 while (true)
 {
  if(win32_peek_message(nullptr)==FALSE)
   break;
  render(hwnd, hdc, hglrc);
  SwapBuffers(wglGetCurrentDC());//翻转缓冲区(因为使用了双缓冲,必须要翻转才能看到绘制结果)
 }
}

  (吐槽一下,CSDN的markdown排版有点难用啊,我用typora编辑的时候没这么蛋疼,而且typora和CSDN用的数学公式渲染器不是同一个,导致我在typora上编辑好的公式没法直接复制过来用)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

win32原生API实现OpenGL例子(无glew,glut等第三方依赖库) 的相关文章

  • 是否可以强制 XMLWriter 将元素写入单引号中?

    这是我的代码 var ptFirstName tboxFirstName Text writer WriteAttributeString first ptFirstName 请注意 即使我使用 ptFirstName 也会以双引号结束 p
  • Qt-Qlist 检查包含自定义类

    有没有办法覆盖加载自定义类的 Qt QList 的比较机制 即在 java 中你只需要重写一个比较方法 我有一个带有我的自定义类模型的 QList QList
  • 未解决的包含:“cocos2d.h” - Cocos2dx

    当我在 Eclipse 中导入 cocos2dx android 项目时 我的头文件上收到此警告 Unresolved inclusion cocos2d h 为什么是这样 它实际上困扰着我 该项目可以正确编译并运行 但我希望这种情况消失
  • 如何避免情绪低落?

    我有一个实现状态模式每个状态处理从事件队列获取的事件 根据State因此类有一个纯虚方法void handleEvent const Event 事件继承基础Event类 但每个事件都包含其可以是不同类型的数据 例如 int string
  • C++ 子字符串返回错误结果

    我有这个字符串 std string date 20121020 我正在做 std cout lt lt Date lt lt date lt lt n std cout lt lt Year lt lt date substr 0 4 l
  • 实时服务器上的 woff 字体 MIME 类型错误

    我有一个 asp net MVC 4 网站 我在其中使用 woff 字体 在 VS IIS 上运行时一切正常 然而 当我将 pate 上传到 1and1 托管 实时服务器 时 我得到以下信息 网络错误 404 未找到 http www co
  • 将布尔参数传递给 SQL Server 存储过程

    我早些时候问过这个问题 我以为我找到了问题所在 但我没有 我在将布尔参数传递给存储过程时遇到问题 这是我的 C 代码 public bool upload false protected void showDate object sende
  • WPF 中的调度程序和异步等待

    我正在尝试学习 WPF C 中的异步编程 但我陷入了异步编程和使用调度程序的困境 它们是不同的还是在相同的场景中使用 我愿意简短地回答这个问题 以免含糊不清 因为我知道我混淆了 WPF 中的概念和函数 但还不足以在功能上正确使用它 我在这里
  • 在 Visual Studio 2008 上设置预调试事件

    我想在 Visual Studio 中开始调试程序之前运行一个任务 我每次调试程序时都需要运行此任务 因此构建后事件还不够好 我查看了设置的 调试 选项卡 但没有这样的选项 有什么办法可以做到这一点吗 你唯一可以尝试的 IMO 就是尝试Co
  • C - 找到极限之间的所有友好数字

    首先是定义 一对友好的数字由两个不同的整数组成 其中 第一个整数的除数之和等于第二个整数 并且 第二个整数的除数之和等于第一个整数 完美数是等于其自身约数之和的数 我想做的是制作一个程序 询问用户一个下限和一个上限 然后向他 她提供这两个限
  • 获取没有非标准端口的原始 url (C#)

    第一个问题 环境 MVC C AppHarbor Problem 我正在调用 openid 提供商 并根据域生成绝对回调 url 在我的本地机器上 如果我点击的话 效果很好http localhost 12345 login Request
  • 如何将图像和 POST 数据上传到 Azure 移动服务 ApiController 终结点?

    我正在尝试上传图片and POST表单数据 尽管理想情况下我希望它是json 到我的端点Azure 移动服务应用 我有ApiController method HttpPost Route api upload databaseId sea
  • Qt表格小部件,删除行的按钮

    我有一个 QTableWidget 对于所有行 我将一列的 setCellWidget 设置为按钮 我想将此按钮连接到删除该行的函数 我尝试了这段代码 它不起作用 因为如果我只是单击按钮 我不会将当前行设置为按钮的行 ui gt table
  • 如何使我的表单标题栏遵循 Windows 深色主题?

    我已经下载了Windows 10更新包括黑暗主题 文件资源管理器等都是深色主题 但是当我创建自己的 C 表单应用程序时 标题栏是亮白色的 如何使我自己的桌面应用程序遵循我在 Windows 中设置的深色主题 你需要调用DwmSetWindo
  • 需要哪个版本的 Visual C++ 运行时库?

    microsoft 的最新 vcredist 2010 版 是否包含以前的版本 2008 SP1 和 2005 SP1 还是我需要安装全部 3 个版本 谢谢 你需要所有这些
  • 如何让Gtk+窗口背景透明?

    我想让 Gtk 窗口的背景透明 以便只有窗口中的小部件可见 我找到了一些教程 http mikehearn wordpress com 2006 03 26 gtk windows with alpha channels https web
  • 在 Dynamics CRM 插件中访问电子邮件发件人地址

    我正在编写一个 Dynamics CRM 2011 插件 该插件挂钩到电子邮件实体的更新后事件 阶段 40 pipeline http msdn microsoft com en us library gg327941 aspx 并且在此阶
  • C - 直接从键盘缓冲区读取

    这是C语言中的一个问题 如何直接读取键盘缓冲区中的数据 我想直接访问数据并将其存储在变量中 变量应该是什么数据类型 我需要它用于我们研究所目前正在开发的操作系统 它被称为 ICS OS 我不太清楚具体细节 它在 x86 32 位机器上运行
  • Validation.ErrorTemplate 的 Wpf 动态资源查找

    在我的 App xaml 中 我定义了一个资源Validation ErrorTemplate 这取决于动态BorderBrush资源 我打算定义独特的BorderBrush在我拥有的每个窗口以及窗口内的不同块内
  • x86 上未对齐的指针

    有人可以提供一个示例 将指针从一种类型转换为另一种类型由于未对齐而失败吗 在评论中这个答案 https stackoverflow com questions 544928 reading integer size bytes from a

随机推荐

  • MPU6500驱动调试笔记(STM32F407+SPI)

    一 问题背景 本来最开始实验室使用MPU6050芯片 采集陀螺仪原始数据做生理信号采集 但算法发现用IIC接口采样率 200hz 达不到要求 故寻找同类型支持SPI协议的芯片去替代 发现了这块MPU6500 还便宜 就用起来 在读写寄存器费
  • ST 电机控制工作台帮助文档翻译 之 STM32F3x 的 OCP 和 OVP(使用嵌入式模拟的过压保护(仅限 STM32F3x))

    ST 电机控制工作台 使用嵌入式模拟的过压保护 仅限 STM32F3x 图5显示了可以使用 STM32F30x 的内部资源实现的过压保护网络的基本实现 图5 过压保护网络 原理类似于 过流保护
  • linux-目录相关作用

    文章来自狂神老师的笔记 同时会有自己的体会 狂神老师课程的链接 https www bilibili com video BV187411y7hF from search seid 10463862828616102628 注意 linux
  • 基于SpringBoot的实习管理系统

    末尾获取源码 开发语言 Java Java开发工具 JDK1 8 后端框架 SpringBoot 前端 Vue HTML 数据库 MySQL5 7和Navicat管理工具结合 服务器 Tomcat8 5 开发软件 IDEA Eclipse
  • 一位技术主管的十年编程经验总结 .

    一位技术主管的十年编程经验总结 有天和朋友聊天 朋友是国内一家大型互联网企业的一位技术主管 朋友把他将近十年研发工作积累的心血总结成两点 这两点朋友刚一提出来我并没有马上明白 只是大约有这么一个概念 我还没达到朋友在技术领域的那种高度 不能
  • PAT乙级1041 考试座位号 (15 分)

    1041 考试座位号 15 分 一 问题描述 每个 PAT 考生在参加考试时都会被分配两个座位号 一个是试机座位 一个是考试座位 正常情况下 考生在入场时先得到试机座位号码 入座进入试机状态后 系统会显示该考生的考试座位号码 考试时考生需要
  • 机器学习:Jupyter Notebook中numpy的使用

    一 Jupyter Notebook的魔法命令 模块 方法 或者help 模块 方法 查看模块 方法的解释文档 1 run 机械学习中主要应用两个魔法命令 run timeit 魔法命令格式 命令 run 将模块引用并在Jupyter No
  • Java设计模式——备忘录模式

    文章目录 备忘录模式 备忘录模式 主要目的是保存一个对象的某个状态 以便在适当的时候恢复对象 个人觉得叫备份模式更形象些 通俗的讲下 假设有原始类A A中有各种属性 A可以决定需要备份的属性 备忘录类B是用来存储A的一些内部状态 类C呢 就
  • PyQt5 pyqtSignal: 自定义信号传入的参数方法

    PyQt5 pyqtSignal 自定义信号传入的参数方法 在PyQt5当中 用户是可以自定义信号与槽函数的 这里想讲的是如何在pyqtSignal中传入任何的参数 一般来说 我们会在pyqtSignal 中传入不同的参数 以便完成不同类之
  • 我去公司面试,人事经理面试没有过,我却把责任链模式学会了

    设计模式在开发当中是运用特别多的 设计模式就是参照我们日常生活特性 抽象出特性 从而某种实现达到具体要求 当然这当中一定是灵活转变 责任链正式拉开序幕 我去某某互联网公司去面试 好的方向的流程大致应该是 你上招聘软件投递简历 简历筛选通过
  • 查看电脑是否开启虚拟化

    第一步 win R快捷键输入cmd 第二步 输入systeminfo命令 即可查看电脑配置信息
  • 5.1 数组

    C 为基本的数据类型 整数 浮点数 字符型和布尔型 提供了内置的支持 就像在上一章我们为复数类定义了重载的运算符那样 内置的支持也称为协助函数 helper function 支持这些数据类型完成各种允许的运算 也就是说基本数据类型也可以说
  • 【华为OD机试真题2023B卷 JAVA&JS】计算最接近的数

    华为OD2023 B卷 机试题库全覆盖 刷题指南点这里 计算最接近的数 时间限制 1s 空间限制 256MB 限定语言 不限 题目描述 给定一个数组X和正整数K 请找出使表达式X i X i 1 X i K 1 结果最接近于数组中位数的下标
  • Modbus协议详解2:通信方式、地址规则、主从机通信状态

    首先我们要清楚 Modbus是一种串行链路上的主从协议 在通信线路上只能有一个主机存在 不会有多主机存在的情况 虽然主机只有一个 但是从机是可以有多个的 Modbus的通信过程都是由主机发起的 从机在接收到主机的请求后再进行响应 从机不会主
  • 30个 BeageBone 嵌入式项目

    特点 展示了如何使用 BeagleBone Black 编程和构建有趣且引人入胜的项目 学习如何将 BeagleBone Black 连接到您的计算机并对其进行编程 快速掌握 BoneScript 和其他编程工具 30 个 BeagleBo
  • 2023网站seo过时了吗?

    不完全是 虽然SEO过去的一些策略可能已经不再有效 但SEO本身并没有过时 实际上 随着搜索引擎算法的不断发展和用户对搜索结果质量的不断提高 合法 道德以及有效的SEO策略依然能够帮助网站获得搜索引擎排名并吸引大量有针对性的流量 尽管SEO
  • 接收I/O请求完成通知

    那片土在蓝天上 燃烧的翅膀 Windows via C C 学习笔记 设备I O之 接收I O请求完成通知 上一篇 讨论了如何发送I O请求 在异步的设备I O请求方式下 要考虑的问题就是当I O请求完成之后 驱动程序如何通知你的应用程序
  • Docker入门——简单记录

    Docker Docker是一个虚拟环境 某种意义上说它就是一个带有终端命令行的虚拟机 狭义上解释 Docker是一个容器 在这个容器里 Docker中的镜像不再是静态不可操作的 可以对安装的系统镜像进行软件下载 比如gcc g 之类 只不
  • 【自然语言处理

    Transformer由论文 Attention is All You Need 提出 论文地址为 https arxiv org pdf 1706 03762 pdf 文章目录 一 Transformer 整体结构 二 Transform
  • win32原生API实现OpenGL例子(无glew,glut等第三方依赖库)

    正文 话不多说 直接上代码 include