在Qt中使用OpenGL(一)

Qt中的OpenGL 也叫可编程管线,提供了更多的灵活性,更高的效率,更重要的是可以更深入的理解图形编程。其中,顶点着色器和片段着色器需要自己去编写,几何着色器可选择性编写,有这三个可以编辑的部分,即为可编程管线(管线可以理解为一个处理流程)。Ps:状态机是一种理论模型,用于描述一个系统在不同时间点的行为和状态转移规律。OpenGL自身是一个巨大的状态机上下文(Context)通常把OpenGL上下文比作一个大的结构体,包含很多子集:当前状态只有一份。 阅读详情
AI摘要

本文介绍了如何在Qt中使用OpenGL渲染动态点云数据。包括初始化OpenGL、设置shader程序、配置顶点缓存及绘制过程等关键步骤。

前言

之前一段时间在研究Kinect的深度摄像头,发现了深度摄像头存在一个“点云”模式。
也就是可以将摄像头识别到的深度信息在3D空间以一个一个点的形式给表现出来。
于是想要自己试着渲染一个点云出来。
既然是在3D空间,那么显然需要使用3D相关的技术了。
在Qt中……那就用Qt提供的OpenGL吧。
恰好之前(挺早之前了)我也算是接触过OpenGL的,然而当我查找了一下相关的文档才发现……新的OpenGL已经和我之前了解的OpenGL是两个东西了……
详见LearnOpenGL CN:https://learnopengl-cn.github.io/
新的OpenGL竟然在最简单的例子中要求写shader?
好家伙,直接给我整不会了。
不过没办法,既然需要写shader那就写吧……
于是最终的成品就是如下所示:
在这里插入图片描述距离摄像机越近,点的颜色越红,越远越蓝,适中就是绿色。

Qt中的OpenGL

要怎么说呢,Qt中对OpenGL的使用是进行了很多层的包装的,我尽可能的挑选了Qt原生的对OpenGL的使用方法,也就是继承QOpenGLWidget和QOpenGLExtraFunctions的方案:
在这里插入图片描述在这里插入图片描述
大致上,你的用于显示OpenGL渲染结果的窗口,应该是这么一个类,即拥有以下特性:

  • 继承QOpenGLWidget和QOpenGLExtraFunctions
  • 重载void initializeGL(),void paintGL()还有void resizeGL(int w, int h)三个函数
  • 提供一些函数,用于设置你的摄像机的位置与旋转
  • 提供一些函数,用于设置你需要显示的内容具体数据(在本例子中,就是提供点云的具体数据。在其他例子中,可能就是提供模型数据了。比如加载模型,卸载模型等)
  • 提供一些函数,用于设置你要显示内容的缩放,旋转与位移(在本例子中,就是点云。在其它例子中,可能就是设置加载的模型的缩放,位置,旋转了)

注意:当你需要显示复杂的内容时,就需要额外的编写逻辑,例如模型管理,贴图管理等等。本例子中因为只显示一个点云数据,所以并没有什么复杂的资源管理逻辑,只需要一个顶点缓存用来保存点云数据,然后在有一些矩阵数据保存各种变化矩阵即可。

initializeGL

在void initializeGL()函数中,我们需要对OpenGL进行一定的初始化。
具体来说,就是:

  1. 初始化函数指针以便可以使用OpenGL的各种函数。
    Qt帮我们提供了这么一个函数:initializeOpenGLFunctions()只要调用就可以了。如果不调用这个函数,则我们将无法使用OpenGL提供的函数。
  2. 启用一些flag
    例如glEnable(GL_DEPTH_TEST)启用深度测试等。深度测试可以让我们在绘制3D图形的时候,总是看到“近处的物体可以挡住远处的物体”这个效果。
  3. 进行一些缓存的创建。
    OpenGL使用的时候需要一些缓存对象,顶点队列对象(VAO),顶点缓存对象(VBO)之类的,都可以在初始化的时候进行创建。
    至于什么是VAO,VBO我们之后再说。目前只需要知道OpenGL在3D绘制的时候,其数据的来源,就是来自于这些缓存之中。
  4. 初始化shader程序并链接:
    Qt提供了一个类QOpenGLShaderProgram,我们用它就可以了。
    new出来这个类,然后用addShaderFromSourceCode或addShaderFromSourceFile加载你的shader,最后用link函数连接即可。
    至于shader是干什么用的我们之后再说。目前只需要知道shader可以让OpenGL在3D绘制的时候,对数据来源进行一定程度的修改。例如你感受到的3D空间的位置的变化或旋转实际上都是通过shader对要绘制的模型的顶点进行了额外处理模拟出来的,并不是真的存在一个摄像机,而是模拟出来了一个摄像机。
  5. 根据需要,如果你要显示的内容是静态的(例如一个静态的模型),那么就可以在初始化的时候加载,否则就需要实时的加载了。我们的点云数据是动态变化的,所以不能初始化加载,而是动态加载。

paintGL

在void paintGL()函数中,我们就可以进行主要的3D绘制逻辑了。
我们主要需要进行以下行为:

  1. 清除之前绘制的内容,包含颜色与深度信息
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    
  2. 启用shader,调用bind函数
    m_program->bind();
    
  3. 设置shader中的全局数据,例如摄像机矩阵,投影矩阵,每个模型自身的变换矩阵等
	// 设置视图矩阵
	m_view.setToIdentity();
	QVector3D _lookDir{ 0, 0, 1 };
	QVector3D _up{ 0, -1, 0 };
	_lookDir = _lookDir * m_cameraRotate;
	_up = _up * m_cameraRotate;
	m_view.lookAt(m_cameraPos, m_cameraPos + _lookDir, _up);
	m_program->setUniformValue("view", m_view);
	// 设置投影矩阵
	m_program->setUniformValue("projection", m_projection);
	// 针对本模型, 设置模型矩阵
	m_model.setToIdentity();
	m_model *= m_scale;
	m_model *= m_rotate;
	m_model *= m_translate;
	m_program->setUniformValue("model", m_model);
  1. 启用顶点队列对象(VAO)
	m_vao.bind();
  1. 启用并设置顶点缓存(VBO),即告诉OpenGL当前要绘制的顶点信息和其它信息
	// 绑定本模型需要的顶点缓冲
	m_vbo.bind();
	m_vbo.setUsagePattern(QOpenGLBuffer::StaticDraw);
	m_vbo.allocate(m_vertices, m_vertecesCount * 3 * sizeof(float));
  1. 将shader与顶点缓存进行对应,即告知OpenGL要如何使用将顶点缓存中的数据转化为shader中的顶点数据
		// 针对本模型, 设置如何渲染
		m_program->setAttributeBuffer(0, GL_FLOAT, 0, 3, 0);
		m_program->enableAttributeArray(0);
  1. 调用OpenGL的绘制函数,绘制顶点缓存中的内容
		// 绘制模型
		glDrawArrays(GL_POINTS, 0, m_vertecesCount);
  1. 释放顶点队列对象(VAO)
	m_vao.release();
  1. 释放shader
	m_program->release();

其中,第5步和第6步就是动态加载数据的步骤。如果你要显示的内容是静态的(例如一个静态模型),你实际上应该在初始化的时候进行这个操作。注意,初始化的时候也要先启用shader和VAO后在操作,并在最后释放VAO和shader。

总结

说了这么多,实际上我们只是对整个OpenGL的使用流程做了一个最初步的介绍,如果你是第一次接触肯定会依旧感到莫名其妙。
但是不要紧,因为我们现在其实并不需要真的理解,面对复杂的内容,我个人的习惯是首先了解整个流程,然后再找到一个最小样的例来体验这个流程。
目前我们已经了解了整个流程,即初始化然后绘制。
简单来说,就是:

初始阶段:

  1. 初始化OpenGL函数
  2. 初始化各种flag
  3. 创建各种缓存对象
  4. 创建并链接shader
  5. 启用shader
  6. 启用缓存
  7. 绑定缓存(加载不变的数据)
  8. 绑定shader的缓存数据(告诉OpenGL如何从缓存中读取数据到shader中)
  9. 释放缓存
  10. 释放shader

绘制阶段:

  1. 清屏
  2. 启用shader
  3. 绑定shader的全局数据(例如摄像机变换矩阵,投影矩阵等)
  4. 启用缓存
  5. 绑定缓存(加载变化的数据)
  6. 绑定shader的缓存数据(告诉OpenGL如何从缓存中读取数据到shader中)
  7. 绘制(使用shader读取缓存中的内容,转换为顶点,然后按照命令基于顶点绘制3D数据)
  8. 释放缓存
  9. 释放shader

根据我们的需求(数据变化与否),我们会在初始化阶段绑定缓存(数据不会变化)或者在绘制阶段绑定缓存(数据会变化)。

注意:可以存在多个缓存。每个缓存可以保存不同的内容(例如不同的模型),根据需要,我们可以在绘制阶段重复4,5,6,7,8步骤以达到绘制不同模型的目的。

下一篇:
在Qt中使用OpenGL(二)

Qt+OpenGL基础教程 基于Qt与OpenGL的UR3机械臂仿真与控制程序的先行文,介绍了如何画出一个可以变换视角的坐标系。 阅读详情

相关推荐

【QT】——OpenGL学习(一)

OpenGL简介 OpenGL(英语:Open Graphics Library,译名:开放图形库或者“开放式图形库”)是用于渲染2D、3D矢量图形的跨语言、跨平台的应用程序编程接口(API)。 这个接口由近350个不同的函数调用组成,用来绘制从简单的图形比特到复杂的三维景象。而另一种程序接口系统是仅用于Microsoft Windows上的Direct3D。OpenGL常用于CAD、虚拟现实、科学可视化程序和电子游戏开发。 OpenGL的高效实现(利用了图形加速硬件)存在于Windows,部分UNIX平台

vhcjgc的博客 8339

【小沐学QT】QT学习之OpenGL开发笔记

Qt提供了与OpenGL实现集成的支持,使开发人员有机会在更传统的用户界面的同时显示硬件加速的3D图形。Qt有两种主要的UI开发方法:QtQuick和QtWidgets。它们的存在是为了支持不同类型的用户界面,并建立在针对每种类型进行了优化的独立图形引擎上。可以将在OpenGL图形API中编写的代码与Qt中的这两种用户界面类型结合起来。当应用程序有自己的OpenGL相关代码时,或者当它与基于OpenGL的第三方渲染器集成时,这可能很有用。Qt OpenGL模块包含方便类,使这种类型的集成更容易、更快。

爱看书的小沐 6070

采用QT进行OpenGL开发(一)绘制平面图形

在QT中进行OpenGL开发的实现方式有很多种,最简单直接的方式就是通过子类化QOpenGLWindow实现OpenGL的绘制和渲染。QOpenGLWindow是用来显示OpenGL的窗口和QT中的其它的标准窗口没有什么区别,我们可以将它和其它的QT控件组合到一起使用。 QT通过QOpenGLContext类来保存OpenGL的上下文状态从而对OpenGL的渲染和绘制过程进行控制。我们的所有绘制和渲染操作都是针对当前的上下文的,可以通过切换上下文实现不同状态之间的切换。在进行渲染绘制的时候一定要把对应的上下

yang1fei2的博客 4945

Qt中使用OpenGL的三种方式

3. 继承QOpenGLWidget 与QOpenGLExtraFunctions。2. 继承QOpenGLFunctions类可直接使用OPENGL函数。通过使用QOpenGLContext来操作OPENGL函数。1.继承QOpenGLWidget并重写基类如下函数。在OPENGL中使用Shader。直接使用OPENGL函数。

7360

Qt OpenGL(四十一)——Qt OpenGL 核心模式-GLSL(一)

这意味着色器可以做一些常规程序做不到的事情。 在管线的不同阶段运行的着色器也不同。我们主要关注的就是顶点着色器和片段着色器。 而着色器则使用被称为“着色器语言”的编程语言编写,着色器语言有很多,OpenGL图形库的着色器语言叫做OpenGL Shading Language,即GLSL。这个语言很像C语言,语法也很相似,我们下一篇继续。 但是,你一定要记住一点:着色器就是在GUP显卡上执行的程序。

ifeng12358的博客 731

在win10上使用QT Creater开发OpenGL工程的流程一

在win10上使用QT Creater开发OpenGL工程的流程 QT Creater的下载自带OpenGL的开发库; QT Creater可以直接使用制作OpenGL工程; 一.在win10上使用QT Creater开发OpenGL工程的流程 (1)使用QT Creater创建QWidget工程,并测试运行成功; (2)修改对应的工程文件openGLProTest35.pro (3)修改对应的文件myglwidget.h与 修改对应的文件myglwidget.cpp文件,使用OpenGL库函

shengGod的博客 459

在 Qt 中使用 OpenGL 详解

在 Qt 中使用 OpenGL 详解

m0_46566693的博客 9004

【UV打印机】PrintExp打印软件教程(六)-高级模式(马达)

输入高级模式密码进入高级模式高级模式界面有操作栏、控制栏、参数栏及参数界面操作栏名称功能说明文件加载数据从板卡加载参数保存将参数保存到主板退出退出高级模式固件导入固件导入配套版本下的固件配置*xpcfx导出固件导出当前使用的固件配置*xpcfx导入波形文件导入对应的波形文件*waf操作初始化系统继续初始化动作复位X轴复位回原点控制栏可进行小车运动、闪喷操作(此闪喷为点击进行闪喷,不受平台位置限制),无清洗功能。

Print World的专栏 3112

QT绘图高级编程 openGL篇

OpenGL简介OpenGL简介OpenGL(Open Graphics Library)是一个跨语言、跨平台的应用程序编程接口(API),主要用于开发2D及3D图形应用程序。它被广泛应用于计算机游戏、科学可视化、虚拟现实等领域。OpenGL是一个开放标准,由Khronos Group负责维护。OpenGL的历史OpenGL的历史可以追溯到1992年,当时是由SGI(Silicon Graphics Inc.)公司开发的。

QT性能优化QT原理源码QT界面美化 4499

ComfyUI+minimaxh3本地部署:漫剧分镜批量生成工作流全实操

视频生成模型正从云端API向本地化部署迁移,背后的技术逻辑是将扩散模型的文本编码、潜空间采样、VAE解码等阶段拆分为可编排的独立环节。ComfyUI作为节点化管线工具,恰好能以可视化连线方式管理这些阶段,让生成过程可控、可复用、可批量执行。minimaxh3模型支持本地推理,配合LoRA微调与参数优化,能够在保证角色一致性的前提下,从分镜脚本批量产出连续剧情片段,规避云端排队、成本高、素材不可控等工程问题。这套工作流广泛应用于漫剧、短剧和动态条漫的工业化生产,尤其适合需要高频迭代分镜草稿的内容团队。文本以零

weixin_29057065的博客 366

逆向分析第一步:如何从HEX文件‘还原’出单片机的原始程序与数据?

本文详细解析了如何从HEX文件逆向分析出单片机的原始程序与数据,涵盖了固件逆向的底层逻辑与实践。通过介绍HEX文件的结构、内存映像重建技术以及专业工具链的使用,帮助读者掌握从十六进制数据到可执行代码的完整流程,适用于嵌入式系统开发和逆向工程领域。

weixin_29745609的博客 317

QT之openGL使用(一)

OpenGL(Open Graphics Library)是一种跨语言、跨平台的图形编程接口,主要用于渲染二维和三维矢量图形。它由一个庞大的函数库组成(只有头文件声明,由各家厂家自己实现内容),允许开发者通过编程方式与图形硬件进行交互,从而实现高效、复杂的图形渲染。以下是OpenGL的一些关键特点和用途:1.OpenGL可以在多种操作系统上运行,如Windows、macOS、Linux、Android和iOS等。它支持多种编程语言,包括C、C++、Python、Java等。2.

m0_58233509的博客 2465

ConvLSTM时空预测实战代码详解

ConvLSTM代码复现

JaysonWong的博客 1万+

基于Qt的OpenGL(一):OpenGL理论及QOpenGLWidget

框架:OpenGL3.3、Qt 5.12.3MinGW(3.2以前是传统模式(固定管线模式-已被丢弃),3.3是现在模式(可编程管线)) 优势:安装简单,Qt已经封装好了,如GLFW和GLAD。自己有支持OpenGL的窗口。 介绍:OpenGL是Open Graphics Library的缩写,它是由Khronos组织制定并维护的一个规范。OpenGL的核心库是用C语言编写,但同时也支持多种语言的派生。 核心模式:3.3以后版本新推出的模式,也叫现在模式或可编程模式。 GPU渲染是一个流水线:比如输入一大

认真努力,做一只会飞的毛毛虫。 9465

一文读懂,WMS仓库管理系统模块功能

对于仓库管理人员来说,仓储管理是一件需要十分负责、又精细化的工作。

深蓝易网的博客 5219

DIY必备:如何用N-MOS管搭建低成本DC有刷电机驱动电路(附原理图+避坑指南)

本文详细介绍了如何使用N-MOS管搭建低成本、高可靠性的DC有刷电机驱动电路。针对DIY爱好者,从核心原理、电路设计、元件选型到焊接调试,提供了完整的实战指南,并重点解析了续流二极管选型、栅极驱动设计等关键避坑要点,帮助读者成功驱动电机并确保电路稳定运行。

delta的博客 776

Qt实现OpenGL的经典教程①——创建窗口

本帖将参考LearnOpenGL这一经典教程,使用Qt的原生环境完成教程中所提的所有流程,并尽量和原教程保持一直,如有错误,欢迎评论!Qt版本:6.7操作系统:Windows10。

qq_45233572的博客 3574

AgentScope 实战训练营-A2UI的完整实现:从概念到部署全流程

本文详细介绍了如何在AgentScope框架中实现Google的A2UI(Agent-to-Agent UI)协议,构建一个能生成可交互UI的智能体应用。文章涵盖了从环境准备、架构设计、核心代码实现到测试部署的完整流程,包括A2UI协议解析、技能系统、客户端实现、通信机制等核心技术点,适合AI Agent和前端开发人员学习参考。

program哲学 202

QT5 OPenGL(一)

概要 QT5 需要加的模块 实例运行效果图 实例代码 部分函数接口的解释 glLoadIdentity glBegin glVertex3f x y z glViewport 0 0 GLintwidth GLintheight glMatrixMode glLoadIdentity gluPerspectiveGLdouble fovyGLdouble aspectGLdouble z

li235456789的专栏 1万+

Python 爬虫教程:企业官网基本信息抓取

本文介绍了使用Python爬虫技术抓取企业官网信息的方法,包括公司名称、简介、联系方式、地址、产品及新闻等数据。通过Requests和BeautifulSoup库实现网页请求与解析,并利用Pandas存储数据为CSV文件。同时提供了应对反爬虫机制(如设置User-Agent、代理IP池、延迟请求等)的解决方案,帮助高效获取企业公开数据。

专注于Python爬虫开发,分享爬虫技巧、项目实战与反爬经验,使用Scrapy、BeautifulSoup等工具,解决数据抓取难题。 1861

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

OpenGL: OpenGL+Qt实现介绍 (一)

OpenGL: OpenGL+Qt实现介绍 (一)

青春有梦,且行且学习! 353

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

Qt+OpenGl入门教程(一)——认识OpenGL

一般它被认为是一个API(Application Programming Interface,应用程序编程接口),包含了一系列可以操作图形、图像的函数。然而,OpenGL本身并不是一个API,它仅仅是一个由制定并维护的规范(Specification)。

bmseven的博客 2067

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

QT QOpenGLWidget使用说明(一)OpenGL 类的添加

QT QOpenGLWidget使用说明(一)OpenGL 类的添加

qq_30150579的博客 5139

Qt5和OpenGL一概述

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_34041003的博客 645

vs-qt开发openGL使用教程(一)

本文详细介绍了在Visual Studio 2022中结合Qt框架开发OpenGL应用程序的完整环境配置流程。涵盖软件下载、路径规划、工程搭建以及关键库的集成步骤。

qq_48932009的博客 1116

QT OpenGL(一 VAO、VBO、EBO使用)

OpenGraphicsLibrary,它是一个由Khronos组织制定并维护的规范OpenGL核心是一个C库,同时也支持多种语言的派生核心模式也叫可编程管线,提供了更多的灵活性,更高的效率,更重要的是可以更深入的理解图像编程,蓝色部分是编程的,通过这一条流水线,最后形成一个OpenGL程序我们通过改变一些上下文变量来改变OpenGL状态,从而告诉OpenGL如何绘图。.........

weixin_45715405的博客 1667
上一篇: Debian11中,QtCreator无法调试,提示不支持python脚本
下一篇: 在Qt中使用OpenGL(二)
Ninsun Closear
博客等级 码龄12年 321粉丝 22原创
评论 8
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值