在Qt中使用OpenGL(二)

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

本文介绍在Qt中使用OpenGL的基本步骤,包括创建QOpenGLWidget、初始化OpenGL、设置深度测试、创建缓存、使用Shader等,最终绘制一个简单的三角形。

前言

在Qt中使用OpenGL(一)
在上一篇文章中,我们结合了一个实际的例子了解了在Qt中使用OpenGL的全部过程。但是肯定对于初次接触的人来说哪怕知道了整个过程,依旧是两眼一抹黑的搞不懂到底要怎么做。
本文章,就从最简的实现来把在Qt中使用OpenGL的全部过程给走一遍。

新建一个窗口类,用于显示

很显然,既然是Qt程序,那么我们首先要做的就是创建一个QWidget。
对于OpenGL,我们就要使用QOpenGLWidget这个类。
同时,对于OpenGL,我们还需要使用它提供的函数,但是OpenGL的版本比较多,每个版本提供的函数也不大一样,Qt帮助我们提供了很多类,方便我们使用。
怎么使用呢?那就是:只要即继承了这个类,那么在这个类的内部,你就可以使用OpenGL的函数。
在这里插入图片描述
看看Qt提供的这些类吧。密密麻麻不是吗?可是我们不需要关心用哪个。
为什么?
因为你现在是一个新手,不需要了解那么多的东西。你只需要知道,我们用一个类就行了:
它提供了
于是,结合之前的我们要创建一个QOpenGLWidget的需求,我们就可以创建出来一个我们自己的窗口了:
在这里插入图片描述
protected:中的三个函数继承自QOpenGLWidget,无论如何你都会用到这三个函数,所以直接重载就行了。
这是一个最简单的窗口,它本身是没有任何功能的。
如果你尝试显示这个Widget,你会看到如下画面:
在这里插入图片描述接下来让我们做一些初始化。

在initializeGL()函数中做一些基本的初始化

首先要做的,是初始化OpenGL函数。
注意,OpenGL本身的API只提供了“函数定义”,所以所有的实现实际上是操作系统或者其它库的工作。
初始化OpenGL函数的目的,就是加载这些OpenGL的实现。
这个操作可以通过以下函数来实现:

initializeOpenGLFunctions();

其次要做的,就是设置一些OpenGL的特性,例如深度测试。
深度测试是指,“近处的物体会遮挡远处的物体”这种在现实中最为基础的法则。
这个操作可以通过以下函数来实现:

glEnable(GL_DEPTH_TEST);

在最后,我们还可以设置一下刷新时的背景颜色是什么。
还记得上一节的那个黑黑的窗口吗?那个颜色就是我们要设置的。
这个操作可以通过以下函数来实现:

glClearColor(0, 0.5, 0.7, 1);

四个参数分别为R,G,B,A,的值,取值范围[0, 1]。

于是,当前的最简单的初始化就是这样:
在这里插入图片描述右侧蓝色的窗口就是我们设置了背景颜色后的结果。
注意,在OpenGL中,颜色值的范围,RGBA每个通道都是从0开始,1结束。如果希望按照[0, 255]的范围来设置,可以用(X / 255.0)进行

创建缓存

众所周知,计算机中进行的一切计算,都需要有输入。
那么,我们绘制3D图像,需要的输入是什么呢?
答案就是顶点。即:用(x,y,z)三个坐标表示的三维的点。
简单来讲,3个点,就可以确认一个三角形。OpenGL的世界中,想要绘制3D图像,你需要的,就是传进去一些顶点。
那么,怎么传入顶点呢?
答案就是将顶点中的x,y,z每个值,一个一个的放到缓存中。
OpenGL中存在两个概念:
一个叫做VAO,一个叫做VBO。
VAO指的是顶点列表对象,VBO指的是顶点缓存对象。
很显然,我们需要将顶点放到缓存,也就是VBO中,但VAO是什么呢?
简单来说,VAO可以帮助我们在绘制多个3D物品时,将各自物品的绘制状态给隔离。即:每个物品都可以有自己的顶点缓存,shader,以及其它的各种各样的状态。VAO会帮你把这些状态保存下来,下一次执行的时候,你就不需要重复的设置这些状态了。简单来说就是:一次设置,到处使用。

VAO对应的Qt中的概念是QOpenGLVertexArrayObject类,VBO对应的Qt中的概念是QOpenGLBuffer。
你一定注意到了,VBO并不是什么VertexBufferObject,而就是简简单单的OpenGLBuffer,因为对于OpenGL,顶点缓存和其它的缓存没有什么区别……它都是缓存。
那么,知道了这些之后我们要怎么操作呢?很简单,创建两个对象,然后调用它们的创建函数即可。
当然,不要忘记引用对应的头文件:
在这里插入图片描述在这里插入图片描述
我们将两个对象作为类的成员变量创建了出来,然后在初始化函数中调用了它们的create函数,这样它们就创建好了。
VAO和VBO是互相对应的,你要是希望创建第二个VBO用于绘制第二物体,那也要再创建一个VAO才行。

Shader

最新的OpenGL与之前OpenGL的最大区别,应该就是新版本的OpenGL默认就是动态渲染管线了,于是为了可以控制渲染流程,我们就需要Shader。
对于简单理解就是:
我们如果把顶点数据通过缓存给了OpenGL,那么OpenGL要如何使用这些顶点数据呢?
老版本的OpenGL的使用方法是固定的,我们也无法改变。
但是新版本的OpenGL的使用方法不是固定,并且必须由我们自己来定义。
什么意思?
你给我了三个顶点,那么我要怎么用?
是直接把三个顶点画成一个三角形?还是先来个坐标变换进行缩放,平移,旋转,然后再给每个顶点染个色,最后在画个三角形?这都是用户自己决定的。
在Qt中,提供了QOpenGLShaderProgram类帮助用户来使用shader。
在这里插入图片描述
这里,我们先不要关心shader中的各种语法,而是使用最基础的逻辑:什么都不改变。
即:如果给了我三个顶点,那么就直接用这三个顶点画一个白颜色的三角形。
那么,我们的shader就应该这么写:
在这里插入图片描述
如果要解释一下就是:
shader目前有两个类型,一个类型是vertex,一个类型是fragment
一个用于处理顶点,一个用于处理颜色。
处理顶点的时候需要定义输入的顶点。
处理颜色的时候可以什么都不用定义。

shader的语言与C语言大差不差,很容易理解。

#version 330 core
in vec3 vPos;
void main()
{
    gl_Position = vec4(vPos, 1.0);
}

其中in表示vPos这个变量是输入的变量,类型为vec3即三维向量。
gl_Position表示最终输出的位置,内置的,不需要我们定义,它是一个四维向量,即X,Y,Z,W。
于是很明显,这个shader的含义就是将输入的三维向量最后加载一个1.0的值变成四维向量,然后作为最终的输出位置,即什么都不变。
颜色那边也同样好理解:

#version 330 core
void main()
{
    gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
} 

gl_FragColor 是表示最终输出的颜色,内置的,不需要我们定义,它是一个四维向量,即R,G,B,A。
于是很明显,这个shader的含义就是最终输出的颜色为(1.0,1.0,1.0,1.0),即白色。
对于shader目前需要了解的就这点了。
最终,我们需要连接一下这个shader,即:

m_program->link();

至此,我们的最简单的shader就准备好了。

使用缓存与Shader

到目前为止,我们的所有操作都是准备。那么,当我们准备好了缓存和shader,下一步就是使用它们了。
我们都知道,OpenGL想要画出一个3D物体,就必须有顶点的输入。OpenGL通过顶点缓存这个概念让用户可以输入顶点信息。
而所谓的顶点缓存,简单点来说,就是一个很简单的,一维数组。例如:

float _vertex[] = {
	 0.0,  0.5, 0.0,
	-0.5, -0.5, 0.0,
	 0.5, -0.5, 0.0,
};

这个数组储存了9个float值,我们可以将其看作三个点,按照x,y,z,x,y,z,x,y,z这个顺序排列。
那么,我们怎么将这9个值,3个点告诉OpenGL呢?即怎么使用VBO呢?
VBO和VAO是匹配出现的,在我们定义好这个三个点后,我们就可以使用VAO和VBO的bind()函数告诉OpenGL我们要用缓存了,即:

m_vao.bind();
m_vbo.bind();

然后,我们将我们自己定义的9个值,3个点绑定到vbo上,即通过VBO的allocate()函数:

m_vbo.allocate(_vertex, 9 * sizeof(float));
// m_vbo.allocate(_vertex, sizeof(_vertex));

这里可以简单的理解一下,就好比我们需要内存保存数据一般,VBO也会创建一块和我们顶点信息相同大小的内存,既然我们的顶点信息是9个float,那这里也就需要使用9个float的大小了。当然,为了方便我们还可以尝试用注释掉的第二种方法。

至此,缓存中已经包含了我们的提供的顶点信息了。
可这就结束了吗?OpenGL就会自动的处理这些顶点信息了吗?
不,OpenGL不会。因为它完全不知道要拿这个缓存中的数据怎么办。
它甚至不知道这里面到底有几个顶点。
不要怀疑,OpenGL真的不知道,万一,你这9个数据,前6个数据代表两个点,后三个数据是垃圾数据没有任何含义怎么办?
是的,这个缓存中所谓的9个数据3个点,是我们自己在大脑中定义的,对于OpenGL来说,它从来没有制定过这么一个标准,也没人告诉它有这么一个标准。
于是,为了让OpenGL能够知道缓存中的数据到底是怎么排列的,我们就需要通过为shader绑定一些信息来告诉OpenGL。
还记得之前我们定义的Shader中,顶点类型的Shader中有一个三维向量的输入吗?它的名字vPos是我们自己定义的,所以我们此时就要使用vPos这个输入变量的名字来告诉OpenGL,我们的顶点缓存中,是按照vPos这个变量的类型,即vec3的标准来保存顶点信息的。
于是我们就可以这么写:

m_program->bind();
m_program->setAttributeBuffer("vPos", GL_FLOAT, 0, 3, 0);
m_program->enableAttributeArray("vPos");

setAttributeBuffer
一般的,当顶点缓存只有顶点信息的时候,setAttributeBuffer()这个函数我们只需要关心前4个参数即可。即shader中的输入参数的名字,顶点缓存中的数据类型,顶点缓存中从第几个点开始才是有用的数据(绝大部分第一个点就是,于是写0即可),顶点缓存中一个点需要用几个数据表示(既要和顶点缓存中的结构匹配,也要和shader中的输入变量的类型匹配,在本例子中为3)。第五个参数一般情况下取0即可。
至此,我们的所有准备工作都完成了。
然后做一个最后的清理工作,释放VAO和Shader:

m_program->release();
m_vao.release();

至此,所有的初始化工作完成。
我们的初始化代码如下图所示:
在这里插入图片描述

开始画三角形吧!

既然我们的准备工作完成了,那么接下来就是绘制三角形了吧。
那么,让我们开始吧,直接上最终的代码,因为本例子中,绘图部分非常的简单:
在这里插入图片描述对,你没看错,代码只有5行,也非常好理解。
分别是启用VAO,启用Shader,用三个点画一个三角形,释放Shader,释放VAO。

至此,一个最简单流程就走完了。
你会发现,我们只使用了void initializeGL()初始化,void paintGL()绘图,但是我们并没有使用void resizeGL(int w, int h)。难道它没用吗?

目前来说的确是没用的……因为我们用了最简单的流程啊……

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

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

相关推荐

Qt中的OpenGL

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

MasterPJ的博客 5202

Qt中使用OpenGL的三种方式

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

7360

QT中OpenGL开发起步

OpenGL中环境搭建 近期由于需要做一个GUI展示的OpenGL程序,因此想到用QT来做界面,需要在QT中写OpenGL,配完环境后,在这里总计一下。 QT基础 总体看来,QT的版本较为混乱,有时候傻傻弄不清楚,QT dialog/widget/mainwindow。又需要有界面,又要有pro文件,一圈下来,加上网上教程版本混乱,已经凌乱了。后来在同学帮助下,看了一些博客教程,综合...

新安浅滩的博客 1万+

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

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

爱看书的小沐 6070

Qt中使用GLEW进行OpenGL开发

Qt中使用GLEW进行OpenGL开发(Windows平台)为什么要使用GLEW使用VS创建Qt项目设置Widget重新实现paintEngine添加GLEW库到工程设置OpenGL上下文设置GL像素格式检测支持OpenGL的力度创建GLRC把当前窗口设置为OpenGL上下文绘制背景颜色更新视口绘制添加QtEvent调用绘制Post绘制事件绘制测试源码下载开启新征程 为什么要使用GLEW 因为工作需求绘制视频,原本使用的Qt(我使用的是5.9.8的版本)自带的QOpenGL进行视频绘制,但是在稳定行测试中经

sttplay666 4096

关于QT5.10+opengl的使用

本人最近在用qt5.10和opengl结合,看了一些博主写的文章,但是在编写程序时还是遇到了各种各样的问题,想来总结下。现在QT5之后有两种方式来结合opengl,最新的可以看看qt官方的opengl window的例子,本人暂时没有用到,还是用旧的方式。现在开始介绍吧!~~~问题总结:1.出现undefined reference to 。。。。的问题2.运行后界面全黑,不显示你所画的内容3.想...

黑手 1万+

在 Qt 中使用 OpenGL 详解

在 Qt 中使用 OpenGL 详解

m0_46566693的博客 9004

SAP ABAP实战:用GN_DELIVERY_CREATE批量创建内部交货单的完整代码与避坑指南

本文详细介绍了在SAP ABAP开发中使用GN_DELIVERY_CREATE函数批量创建内部交货单的完整实现方案。通过数据结构设计、多源数据整合、批量处理逻辑和错误处理机制等核心环节的深入解析,帮助开发者高效完成物流单据自动化处理,特别针对VL31N/VL32N等常见场景提供避坑指南。

weixin_42116058的博客 343

QT之openGL使用(二)

可以使用QT中的QOpenGLShaserProgram。用这个资源文件来进行分开加载。

m0_58233509的博客 615

谈谈SAP顾问的几个发展趋势

大家新年好,今天想聊一下对SAP顾问发展趋势的一些个人见解。过去10多年得益于我国的经济发展,外资不断加大在中国的投资和中国企业的发展,SAP顾问行业得到了很大的发展和壮大。那么未来几年SAP顾问的职业发展到底怎么样呢?

syounger的专栏 2515

三维重建之条纹投影结构光(一)

该系列为条纹投影结构光学习笔记,一共分为四篇。第一篇记录文献阅读的笔记,对重要知识点进行摘录介绍。 本篇以理论知识推导为主,主要从以下三个方面进行介绍,首先介绍条纹投影的三角测量原理;然后介绍相位主值的求解和相位展开;最后介绍相位和高度的模型,即相高模型。本篇博文不涉及具体的代码实现。 条纹投影结构光测量原理 ...

beyond951的博客 3万+

QT5.7中使用OpenGL开发记录(二)---- 绘制三角形

QT5.7中使用OpenGL开发记录(二)    前言:最近在做一个项目,需要使用QT结合OpenGL进行开发。由于原来没有怎么用过OpenGL,只知道是个开源图形库,所以先在网上查询了一些资料,发现QT5.5以上版本已经集成了OpenGL,不过和纯OpenGL的使用有些区别,而且相关资料较少。为了便于后续开发并且方便大家共同学习,这里将我的学习过程进行记录(本博客内容只记录了本人的学习过程,不保证

lonely_13的专栏 1万+

NOAA气象数据下载攻略

各方搜寻气象数据下载途径,发现网上最多的就是从NOAA下载,但是中途有尝试过很多次都没有下载到,每次都是显示不可用,今天终于下载成功了,特此记录。 首先我是从这个网址进入的:National Centers for Environmental Information (NCEI) formerly known as National Climatic Data Center (NCDC) | NCEI offers access to the most significant archives of oc

lianqian66的博客 3万+

QT5.7中的opengl使用方法

本文目的是记录一下自己搜索相关机制的结果qt5.7实现opengl机制主要包含两类一种是提供QtGui实现,这个库主要是通过QWindow结合qt封装的opengl库进行实现,官方有案例,一个旋转的三角形,使用opengl es2.0,而且这也是qml的底层实现方式。另一种是通过QWidget中的qopenglwidget类实现的,这里保留了早期的qopengl方法,即对应于opengl2.0版本的

咕噜咕噜博客 1万+

opencv去除印章痕迹

今天看到一个很有意思的程序,就是去除票据上的红色印章,觉得很有意思,就把它抄过来记录一下,同时自己也开了一下脑洞。 原来的程序来自:https://www.cnblogs.com/skyfsm/p/7638301.html 可以看到图像效果很不错,下面是源码实现: #include <iostream> #include <opencv2/imgproc/imgpro...

zeng_haoyu的博客 7959

SAP FICO 科目余额查询表开发说明书(包括测试样例、程序代码仅作参考,不保证一定可以运行)

SAP FICO 科目余额查询表开发说明书(包括开发源代码、测试样例)

我好像病了的博客 1041

【opengl】两种方法在Qt中使用OpenGL库加载stl三维模型

是一种用于渲染2D、3D矢量图形的跨语言、跨平台的应用程序接口。OpenGL的实现利用了图形加速硬件,这些实现一般由显示设备厂商提供。但真正使用时,一般采用基于gl的第三方库,用于在程序的运行期判断当前硬件是否支持相关的扩展,防止程序崩溃甚至造成硬件损坏。目前我了解到的第三方库就有gladglewglfwfreeglut等,下图反映了它们之间的关系。此外在安装Qt后,Qt本身也会对gl库进行一定的封装,即qopengl.h和s。Qt是目前做UI非常好的一款工具,再结合它给的例子,比如cube。

qq_43331089的博客 7278

ADBMS1818芯片

 可测量多达18串电池电压 3 mV最大总测量误差 内置isoSPI接口 使用单根双绞线,长达100米 290 μs内可完成系统中所有单体电池电压测量。

m0_61973119的博客 4280

网上代码《QT5.7中使用OpenGL开发记录(二)---- 绘制三角形》源代码改良

最近学习QT+OpenGL,OpenGL入门之后需要在QT上使用,貌似网上只有这个代码最全,但是编译起来各种问题,非常要命。 最终再根据QT官方文档等其他资料终于将这个代码补全,喜欢的点个赞就很感谢了。 mainwindow.h #ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QtWidgets/QMainWindow> #in...

a553455的博客 670

CryoEM - 使用 ChimeraX 工具 操作 冷冻电镜的 MRC 密度图(Density Map) 教程

由冷冻电镜 CryoSparc 软件所生成的 Volume,需要观察其内部结构,建议使用 ChimeraX 进行操作。

AGI 4962

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

Ubuntu下部署Qt5环境缺少openGL库解决方法汇总

很多人碰到这个问题,在此本人归纳了各位前辈的方法,总结如下: 参考https://blog.youkuaiyun.com/u012175418/article/details/52078291 ubuntu下缺少libGLku 网上找了一下很多人都出现了这个错误。 有两种原因,一种是没有按照libGL库,那么就安装: sudo apt-get install libgl1-mesa-dev 1 一种是装了,但是路径不对,那么就配置一下路径: $ locate libGL /usr/lib/i386-linux.

qq_30754685的博客 7712

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

实现Qt和OpenGL混合渲染

&lt;style type="text/css"&gt; &lt;!-- @page {margin:2cm} pre {font-family:"DejaVu Sans Mono",monospace} p {margin-bottom:0.21cm} --&gt; &lt;/style&gt; 实现Qt和OpenGL混合渲染 Qt自有一个混图的引擎,这个引擎的核心就...

架构设计 882

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

在Qt中使用OpenGL

在Qt5.4之前,OpenGL在Qt中的实现主要是继承QGLWidget,在5.4版本之后,则改为QOpenGLWidget和QOpenGLFunctions(QOpenGLExtraFunctions),这是qt官方的推荐写法,可以在qt自带的examples中搜索opengl找到。 除了这种写法,直接使用指定OpenGL版本的包装器也是可以的,在头文件中包含QOpenGLFunctio...

TiredWind的博客 3万+

在Qt中使用OpenGL(一)

在Qt中使用OpenGL,尽可能地使用Qt的风格

Ninsun的博客 2万+

QT中使用自带的OpenGL模块开发

原文:http://nehe.gamedev.net/ 翻译:https://www.cnblogs.com/arxive/p/6238969.html

qing666888的专栏 1万+

在Qt中使用OpenGL(三)

在Qt中使用OpenGL,绘制一个带纹理的矩形。

Ninsun的博客 1万+
上一篇: 在Qt中使用OpenGL(一)
下一篇: 在Qt中使用OpenGL(三)
Ninsun Closear
博客等级 码龄12年 321粉丝 22原创
评论 12
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值