Qt中使用GLEW进行OpenGL开发(Windows平台)

  • 为什么要使用GLEW
  • 使用VS创建Qt项目
  • 设置Widget
    • 重新实现paintEngine
  • 添加GLEW库到工程
  • 设置OpenGL上下文
    • 设置GL像素格式
    • 检测支持OpenGL的力度
    • 创建GLRC
    • 把当前窗口设置为OpenGL上下文
  • 绘制背景颜色
    • 更新视口
    • 绘制
    • 添加QtEvent
    • 调用绘制
    • Post绘制事件
  • 绘制测试
  • 源码下载
  • 开启新征程

为什么要使用GLEW

因为工作需求绘制视频,原本使用的Qt(我使用的是5.9.8的版本)自带的QOpenGL进行视频绘制,但是在稳定行测试中经常会出现界面不更新的情况。找了很久也没有好的解决方案,后来干脆使用GLEW进行OpenGL的开发。
目前Qt的OpenGL多少会存在些问题或者不完善。

使用VS创建Qt项目

1.创建一个Widget窗口即可。

#include <QtWidgets/QWidget>
#include "ui_GLEW4QT.h"class GLEW4QT : public QWidget
{Q_OBJECTpublic:GLEW4QT(QWidget *parent = Q_NULLPTR);private:Ui::GLEW4QTClass ui;
};

设置Widget

GLEW4QT::GLEW4QT(QWidget *parent): QWidget(parent, Qt::MSWindowsOwnDC)
{setAttribute(Qt::WA_PaintOnScreen);setAttribute(Qt::WA_NoSystemBackground);setAutoFillBackground(true);ui.setupUi(this);
}

1.在构造函数中设置一个Qt::MSWindowsOwnDC( 在窗口上为窗口提供自己的显示上下文)。
2.设置属性Qt::WA_PaintOnScreen,设置该属性后需要重新实现paintEngine函数。
3.设置Qt::WA_NoSystemBackground属性。
4.设置自动填充背景

重新实现paintEngine

直接返回NULL即可

virtual QPaintEngine* paintEngine() const { return NULL; }

添加GLEW库到工程

GLEW下载地址: 传送门
引入头文件

#define GLEW_STATIC
#include <GL/glew.h>
#include <GL/wglew.h>#ifdef GLEW_STATIC
//使用静态库
#pragma comment(lib, "glew32s.lib")
#else
//使用动态库
#pragma comment(lib, "glew32.lib")
#endif
#pragma comment(lib, "opengl32.lib")

注意:如果使用glew静态库则需要在#include <GL/glew.h>前定义GLEW_STATIC

设置OpenGL上下文

设置GL像素格式

创建静态函数设置

/** 设置GL像素格式*/
static bool SetupPixelFormat(HDC dc)
{//像素格式描述符,渲染的像素格式PIXELFORMATDESCRIPTOR pfd;ZeroMemory(&pfd, sizeof(PIXELFORMATDESCRIPTOR));pfd.nVersion = 1;pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);pfd.cColorBits = 32;pfd.cDepthBits = 24;pfd.cStencilBits = 8;pfd.iPixelType = PFD_TYPE_RGBA;pfd.iLayerType = PFD_MAIN_PLANE;pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;int pixelformat = 0;if ((pixelformat = ChoosePixelFormat(dc, &pfd)) == 0)return false;if (SetPixelFormat(dc, pixelformat, &pfd) == FALSE)return false;return true;
}

检测支持OpenGL的力度

这里也创建一个静态函数检测

/** 检测支持OpenGL的力度* @param major 主版本号* @param minor 次版本号* @return -1 不支持GL, -2 glinit初始化失败, 0 支持GL, 1 支持多重采样*/
static int CheckSupportGLLevel(int *major, int *minor)
{static bool checked = false;static int _major = 0;static int _minor = 0;static int support = 0;if (checked){if (major)*major = _major;if (minor)*minor = _minor;return support;}checked = true;HDC dc = nullptr;HGLRC rc = nullptr;QWidget w;HWND hwnd = (HWND)w.winId();dc = GetDC(hwnd);if (!SetupPixelFormat(dc)){support = -1;goto end;}rc = wglCreateContext(dc);wglMakeCurrent(dc, rc);if (glewInit() != GLEW_OK){support = -2;goto end;}glGetIntegerv(GL_MAJOR_VERSION, &_major);glGetIntegerv(GL_MINOR_VERSION, &_minor);if (wglChoosePixelFormatARB)support = 1;if (major)*major = _major;if (minor)*minor = _minor;
end:if (rc)wglDeleteContext(rc);if (dc)ReleaseDC(hwnd, dc);rc = nullptr;wglMakeCurrent(nullptr, nullptr);ReleaseDC(hwnd, dc);return support;
}

创建GLRC

/** 创建HGLRC* @param dc HDC* @param supportMSAA 是否支持msaa* @param msaaLevel msaa等级 // 8, 16, 32* @return NULL 为失败,否则返回HGLRC*/
static HGLRC CreateGLRC(HDC dc, bool supportMSAA, int msaaLevel)
{HGLRC rc;if (!supportMSAA){if (!SetupPixelFormat(dc))return nullptr;rc = wglCreateContext(dc);return rc;}ZeroMemory(&rc, sizeof(HGLRC));GLint attribs[]{WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB,WGL_DOUBLE_BUFFER_ARB, GL_TRUE,WGL_RED_BITS_ARB, 8,WGL_GREEN_BITS_ARB, 8,WGL_BLUE_BITS_ARB, 8,WGL_ALPHA_BITS_ARB, 8,WGL_DEPTH_BITS_ARB, 24,WGL_STENCIL_BITS_ARB, 8,WGL_SAMPLE_BUFFERS_ARB, GL_TRUE,WGL_SAMPLES_ARB, msaaLevel,//8,16,32NULL,NULL};int pixelFormat[256] = { 0 };UINT formatNum = 0;int ret = wglChoosePixelFormatARB(dc, attribs, NULL, 256, pixelFormat, &formatNum);if (formatNum > 0){PIXELFORMATDESCRIPTOR pfd;DescribePixelFormat(dc, pixelFormat[0], sizeof(PIXELFORMATDESCRIPTOR), &pfd);SetPixelFormat(dc, pixelFormat[0], &pfd);int contexAttributes[] = {WGL_CONTEXT_MAJOR_VERSION_ARB, 4,WGL_CONTEXT_MINOR_VERSION_ARB, 3,WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,0};rc = wglCreateContextAttribsARB(dc, nullptr, contexAttributes);}return rc;
}

把当前窗口设置为OpenGL上下文

在构造函数中处理

GLEW4QT::GLEW4QT(QWidget *parent): QWidget(parent, Qt::MSWindowsOwnDC)
{setAttribute(Qt::WA_PaintOnScreen);setAttribute(Qt::WA_NoSystemBackground);setAutoFillBackground(true);int major = 0, minor = 0;dc = GetDC((HWND)winId());bool supportMSAA = CheckSupportGLLevel(&major, &minor) == 1;rc = CreateGLRC(dc, supportMSAA, 16);qDebug() << "OpenGL Version:" << major << "." << minor;if (!wglMakeCurrent(dc, rc))throw;ui.setupUi(this);
}

也可以关闭垂直同步,让OpenGL火力全开

//是否开启垂直同步
wglSwapIntervalEXT(false);

在析构函数中要记得释放DC和RC

GLEW4QT::~GLEW4QT()
{wglMakeCurrent(nullptr, nullptr);if (rc)wglDeleteContext(rc);if (dc)ReleaseDC((HWND)winId(), dc);
}

绘制背景颜色

更新视口

重写resizeEvent,并更新OpenGL视口

void GLEW4QT::resizeEvent(QResizeEvent *event)
{glViewport(0, 0, event->size().width(), event->size().height());
}

绘制

void GLEW4QT::Renderer()
{glClearColor(0.0f, 0.0f, 0.0f, 1.0f);glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);SwapBuffers(dc);
}

Renderer不要直接调用,我们把他放在event中调用

添加QtEvent

class QtEvent : public QEvent
{public:enum Type{GL_Renderer = QEvent::User + 1,};QtEvent(Type type) : QEvent(QEvent::Type(type)) {};
};

调用绘制

bool GLEW4QT::event(QEvent *event)
{if (event->type() == QtEvent::GL_Renderer){Renderer();return true;}return QWidget::event(event);
}

Post绘制事件

void GLEW4QT::GLUpdate()
{QApplication::postEvent(this, new QtEvent(QtEvent::GL_Renderer));
}

这样在需要重新绘制的地方调用GLUpdate即可

void GLEW4QT::resizeEvent(QResizeEvent *event)
{glViewport(0, 0, event->size().width(), event->size().height());GLUpdate();
}

绘制测试

通过改变颜色测试OGL环境
构造函数中添加定时器改变red值

 ...QTimer *timer = new QTimer(this);connect(timer, &QTimer::timeout, [this] {red += 0.01f;if (red > 1.0f) red = 0.0f;GLUpdate();});timer->start(30);...

Renderer更新颜色值

 ...glClearColor(red, 0.0f, 0.0f, 1.0f);glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);...

测试效果

源码下载

如果您在测试的过程中某个环节出错了,请下载源码查看
源码链接: 传送门.

开启新征程

通过上面的一番操作就可以在Qt中使用原生的OpenGL了。

Qt中使用GLEW进行OpenGL开发相关推荐

  1. QT中树控件QTreeView开发实例

    转自:http://mobile.51cto.com/symbian-268700.htm 本文讲解了QT中树控件QTreeView开发实例,对于QTreeView没有过多的讲解,那么不说废话了,看代 ...

  2. QT中OpenGL开发起步

    OpenGL中环境搭建 近期由于需要做一个GUI展示的OpenGL程序,因此想到用QT来做界面,需要在QT中写OpenGL,配完环境后,在这里总计一下. QT基础 总体看来,QT的版本较为混乱,有时候 ...

  3. 基于Qt ffmpeg opengl开发跨平台安卓实时投屏软件

    [开源]基于Qt ffmpeg opengl开发跨平台安卓实时投屏软件 码云地址 https://gitee.com/Barryda/QtScrcpy github地址 https://github. ...

  4. Qt中的OpenGL

    Qt还是本人可移植GUI程序开发的首选,不过Qt开发普通的应用程序是行,但是据说效率太低,以至于像某些人说的那种刷新看得到一条条横线?这点我比较纳闷,就我使用的感觉,虽然Qt不以效率著称,但是事实上有 ...

  5. qt中opengl窗口的创建

    该笔记借鉴自 : "懂deeee珍惜"的 现代OpenGL+Qt学习笔记之二:程序框架 "爱种鱼的猫"的 QT中使用OpenGL(0)--创建一个窗口 引用引自 ...

  6. QT中使用OpenGL绘制图形

    Qt Creator中的3D绘图及动画教程(参照NeHe) 刚刚学习了Qt Creator,发现Qt提供了QtOpenGL模块,对OpenGL做了不错的封装,这使得我们可以很轻松地在Qt程序中使用Op ...

  7. Qt中使用OpenGL进行绘图

    Qt Creator中的3D绘图及动画教程(参照NeHe) 刚刚学习了Qt Creator,发现Qt提供了QtOpenGL模块,对OpenGL做了不错的封装,这使得我们可以很轻松地在Qt程序中使用Op ...

  8. qt 中 使用 opengl 上下文 (context) 相关的注意事项

    qt 中 使用 opengl 相关的注意事项 本人移植了一个glut到qt的项目,前期没有注意相关的上下文的使用,导致相关的显示混乱. 解决方案 makeCurrent();在每一个类函数中加上这一句 ...

  9. 在Qt中使用OpenGL(三)

    前言 在Qt中使用OpenGL(一) 在Qt中使用OpenGL(二) 在之前的文章中,我们首先了解了在Qt中使用OpenGL的全流程,然后我们使用了一个最简单的例子将这个流程给过了一遍. 那么,在本篇 ...

最新文章

  1. 正则表达式(javascript)
  2. AI实战:人脸识别实战项目(源码共享)
  3. 超详细的CentOS7中安装Git,yum安装和自己编译安装
  4. SAP CRM Product ACE check调试
  5. sql distinct多个字段_数据分析|记一“道”难忘的SQL面试题...
  6. 嵌入式Linux系统运行流程图
  7. [Mvp.Blazor] 集成Ids4,实现统一授权认证
  8. 如果我是博客园的产品经理【上】
  9. php环行队列实现,java数组实现队列及环形队列实现过程解析
  10. 计算机怎么取消u盘启动程序,计算机设置U盘自动启动程序| U盘自动播放设置
  11. 此项目需要迁移_AndroidX 迁移,看完它应该就够了
  12. Windows XP启用telnet服务图文教程
  13. vue 钉钉授权第三方WEB网站扫码登录功能
  14. 奇怪的问题:Windows 11 22H2任务管理器颠倒显示GPU使用率
  15. 在linux下比较好用的chm阅读器和飞信软件
  16. 学习python量化分析
  17. Mysql数据库与数据库三大范式
  18. 英文字母间隔突然增大(全角与半角转换)
  19. 2022国产PLM软件排行榜
  20. 关于时间:UTC/GMT/xST/ xDT

热门文章

  1. GLIBC源码——putchar
  2. UE4 SaveGame保存游戏注意事项
  3. javascript面向对象精要学习总结(第一章 类型)
  4. 蓝桥 质数的后代(Java)
  5. arm9 中断向量 重定位_STM32中断向量表的位置,重定向
  6. Unity3D入门——初识Unity3D
  7. python图形编程pdf_Python计算机视觉编程
  8. C语言自定义字符串复制函数
  9. 大数据系列(五)之 Flume 数据传输
  10. 关于Springboot中JSCH使用说明