【QT】——OpenGL学习(一)
OpenGL简介
OpenGL(英语:Open Graphics Library,译名:开放图形库或者“开放式图形库”)是用于渲染2D、3D矢量图形的跨语言、跨平台的应用程序编程接口(API)。
这个接口由近350个不同的函数调用组成,用来绘制从简单的图形比特到复杂的三维景象。而另一种程序接口系统是仅用于Microsoft Windows上的Direct3D。OpenGL常用于CAD、虚拟现实、科学可视化程序和电子游戏开发。
OpenGL的高效实现(利用了图形加速硬件)存在于Windows,部分UNIX平台和Mac OS。这些实现一般由显示设备厂商提供,而且非常依赖于该厂商提供的硬件。开放源代码库Mesa是一个纯基于软件的图形API,它的代码兼容于OpenGL。但是,由于许可证的原因,它只声称是一个“非常相似”的API。
Qt中的OpenGL
通过继承QOpenGLWidget和QOpenGLExtraFunctions,重载void initializeGL(),void paintGL()还有void resizeGL(int w, int h)三个函数进行绘图
创建一个QWidget
继承QOpenGLWidget和QOpenGLExtraFunctions
#include <QOpenGLWidget>
#include <QOpenGLExtraFunctions>class OpenGLWidget : public QOpenGLWidget, public QOpenGLExtraFunctions
重载initializeGL(),paintGL()和resizeGL(int w, int h)
protected:virtual void initializeGL() override;virtual void resizeGL(int x, int y) override;virtual void paintGL() override;
在initializeGL()函数中做一些基本的初始化
OpenGL本身的API只提供了“函数定义”,所以所有的实现实际上是操作系统或者其它库的工作。
初始化OpenGL函数的目的,就是加载这些OpenGL的实现。
initializeOpenGLFunctions();
设置一些OpenGL的特性,例如深度测试。
深度测试是指,“近处的物体会遮挡远处的物体”这种在现实中最为基础的法则。
glEnable(GL_DEPTH_TEST);
设置一下刷新时的背景颜色,四个参数分别为R,G,B,A,的值,取值范围[0, 1]。
glClearColor(0, 0.5, 0.7, 1);
创建缓存
OpenGL的世界中,想要绘制3D图像,3个点,就可以确认一个三角形。将顶点中的x,y,z每个值,一个一个的放到缓存中。
OpenGL中存在两个概念:
VAO指的是顶点列表对象,VBO指的是顶点缓存对象。
VAO可以帮助我们在绘制多个3D物品时,将各自物品的绘制状态给隔离。即:每个物品都可以有自己的顶点缓存,shader,以及其它的各种各样的状态。VAO会帮你把这些状态保存下来,下一次执行的时候,你就不需要重复的设置这些状态了。简单来说就是:一次设置,到处使用。
#include <QOpenGLVertexArrayObject>
#include <QOpenGLBuffer>QOpenGLVertexArrayObject m_vao;
QOpenGLBuffer m_vbo;m_vao.create();
m_vbo.create();
Shader
需要使用Shader控制渲染流程。在Qt中,提供了QOpenGLShaderProgram类帮助用户来使用shader。
in 用在函数的参数中,表示这个参数是输入的,在函数中改变这个值,并不会影响对调用的函数产生副作用。(相当于C语言的传值),这个是函数参数默认的修饰符
out 用在函数的参数中,表示该参数是输出参数,值是会改变的。
图形处理之Shader语言(一)GLSL语法篇
#include <QOpenGLShaderProgram>QOpenGLShaderProgram *m_program;m_program = new QOpenGLShaderProgram();///gl_Position vec4 输出属性-变换后的顶点的位置,用于后面的固定的裁剪等操作。/// 所有的顶点着色器都必须写这个值。/// 顶点着色器(Vertex Shader)m_program->addShaderFromSourceCode(QOpenGLShader::Vertex, u8R"(#version 330 core
in vec3 vPos;
in vec2 vTexture;
out vec2 oTexture;
void main()
{gl_Position = vec4(vPos, 1.0);oTexture = vTexture;
})");///sampler2D 二维纹理句柄/// uniform 一致变量。这个值在编译时期是未知的是由着色器外部初始化的。///只能在全局范围进行声明。///gl_FragColor vec4 输出的颜色用于随后的像素操作/// Fragment Shader(片段着色器)m_program->addShaderFromSourceCode(QOpenGLShader::Fragment, u8R"(#version 330 core
in vec2 oTexture;
uniform sampler2D uTexture;
void main()
{gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);//gl_FragColor = texture(uTexture, oTexture);
}
)");
顶点缓存
一个一维数组,存储了顶点信息
float _vertex[] = {-0.5, -0.5, 0.0,-0.5, 0.5, 0.0,0.5, 0.5, 0.0,0.5, -0.5, 0.0,
};
可以将其看作四个点,按照x,y,z,x,y,z,x,y,z这个顺序排列。
使用vPos这个输入变量的名字来告诉OpenGL,我们的顶点缓存中,是按照vPos这个变量的类型,即vec3的标准来保存顶点信息的。
m_program->bind();
// 绑定顶点坐标信息, 从0 * sizeof(float)字节开始读取3个float, 因为一个顶点有3个float数据, 所以下一个数据需要偏移3 * sizeof(float)个字节
m_program->setAttributeBuffer("vPos", GL_FLOAT, 0, 3, 3 * sizeof(float));
m_program->enableAttributeArray("vPos");
释放VAO和Shader
m_program->release();
m_vao.release();
完整的初始化代码
void OpenGLWidget::initializeGL()
{initializeOpenGLFunctions();glEnable(GL_DEPTH_TEST);glClearColor(0, 0.5, 0.7, 1);m_vao.create();m_vbo.create();m_program = new QOpenGLShaderProgram();///gl_Position vec4 输出属性-变换后的顶点的位置,用于后面的固定的裁剪等操作。/// 所有的顶点着色器都必须写这个值。/// 顶点着色器(Vertex Shader)m_program->addShaderFromSourceCode(QOpenGLShader::Vertex, u8R"(#version 330 core
in vec3 vPos;
in vec2 vTexture;
out vec2 oTexture;
void main()
{gl_Position = vec4(vPos, 1.0);oTexture = vTexture;
})");///sampler2D 二维纹理句柄/// uniform 一致变量。这个值在编译时期是未知的是由着色器外部初始化的。///只能在全局范围进行声明。///gl_FragColor vec4 输出的颜色用于随后的像素操作/// Fragment Shader(片段着色器)m_program->addShaderFromSourceCode(QOpenGLShader::Fragment, u8R"(#version 330 core
in vec2 oTexture;
uniform sampler2D uTexture;
void main()
{gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);//gl_FragColor = texture(uTexture, oTexture);
}
)");m_program->link();float _vertex1[] = {-0.5, -0.5, 0.0,-0.5, 0.5, 0.0,0.5, 0.5, 0.0,0.5, -0.5, 0.0,};// 顶点缓存中前三个是顶点坐标, 后两个是纹理坐标, 一个顶点由5个float值组成float _vertex0[] = {// 顶点 纹理-1, 1, 0, 0, 1, // 左上-1, -1, 0, 0, 0, // 左下1, -1, 0, 1, 0, // 右下1, 1, 0, 1, 1, // 右上};m_vao.bind();m_vbo.bind();//m_vbo.allocate(_vertex, 9 * sizeof(float));m_vbo.allocate(_vertex1, sizeof(_vertex1));m_program->bind();// 绑定顶点坐标信息, 从0 * sizeof(float)字节开始读取3个float, 因为一个顶点有5个float数据, 所以下一个数据需要偏移3 * sizeof(float)个字节m_program->setAttributeBuffer("vPos", GL_FLOAT, 0, 3, 3 * sizeof(float));m_program->enableAttributeArray("vPos");m_program->release();m_vao.release();}
绘制图形
void OpenGLWidget::paintGL()
{m_vao.bind();m_program->bind();glDrawArrays(GL_TRIANGLE_FAN, 0, 4);//GL_TRIANGLE_FAN绘制各三角形形成一个扇形序列,以v0为起始点,(v0,v1,v2)、(v0,v2,v3)、(v0,v3,v4)。m_program->release();m_vao.release();
}
一般情况下有三种绘制一系列三角形的方式,分别是
- GL_TRIANGLES
- GL_TRIANGLE_STRIP
- GL_TRIANGLE_FAN
GL_TRIANGLES是以每三个顶点绘制一个三角形。第一个三角形使用顶点v0,v1,v2,第二个使用v3,v4,v5,以此类推。如果顶点的个数n不是3的倍数,那么最后的1个或者2个顶点会被忽略。
GL_TRIANGLE_STRIP则稍微有点复杂。
其规律是:
构建当前三角形的顶点的连接顺序依赖于要和前面已经出现过的2个顶点组成三角形的当前顶点的序号的奇偶性(如果从0开始):
- 如果当前顶点是奇数: 组成三角形的顶点排列顺序:T = [n-1、n-2、n].
- 如果当前顶点是偶数: 组成三角形的顶点排列顺序:T = [n-2、n-1、n].
以上图为例,第一个三角形,顶点v2序号是2,是偶数,则顶点排列顺序是v0,v1,v2。第二个三角形,顶点v3序号是3,是奇数,则顶点排列顺序是v2,v1,v3,第三个三角形,顶点v4序号是4,是偶数,则顶点排列顺序是v2,v3,v4,以此类推。
注意:顶点个数n至少要大于3,否则不能绘制任何三角形。
GL_TRIANGLE_FAN绘制各三角形形成一个扇形序列,以v0为起始点,(v0,v1,v2)、(v0,v2,v3)、(v0,v3,v4)。
运行结果
参考学习
在Qt中使用OpenGL(一)
在Qt中使用OpenGL(二)
理解GL_TRIANGLES、GL_TRIANGLE_STRIP、GL_TRIANGLE_FAN绘制三角形序列的三种方式
【QT】——OpenGL学习(一)相关推荐
- Qt|OpenGL学习笔记-绕X轴、Y轴、以及XY轴旋转的四边体
程序运行截图如下: 源码如下: myglwidget.h #ifndef MYGLWIDGET_H #define MYGLWIDGET_H#include <QWidget> #incl ...
- OpenGL(十四)——Qt OpenGL纹理
OpenGL(十四)--Qt OpenGL纹理 一.纹理 终于写到纹理的部分了: 纹理(Texture)的本质是一个2D图片(1D和3D),或者叫图形数据.只是在OpenGL中专业术语中称其为纹理. ...
- OpenGL学习笔记(一):环境搭建、三维空间坐标系理解以及OpenGL的基本使用
原博主博客地址:http://blog.csdn.net/qq21497936 本文章博客地址:http://blog.csdn.net/qq21497936/article/details/7866 ...
- Qt OpenGL 旗帜效果(飘动的纹理)
这次教程中,我将教大家如何创建一个飘动的旗帜.我们所要创建的旗帜,说白了就是一个以正弦波方式运动的纹理映射图像.虽然不会很难,但效果确实很不错,希望大家能喜欢.当然这次教程是基于第06课的,希望大家确 ...
- QT开发学习-第一章-QT简介
QT简介 一.QT简介 1.QT简介 2.QT优点 二.QT开发工具 1.Qt Creator 2.Qt Designer 3.Qt Linguist 4.Qt Assistant 5.Qmake 6 ...
- Qt OpenGL 位图字体
这次教程中,我们将创建一些基于2D图像的字体,它们可以缩放平移,但不能旋转,并且总是面向前方,但作为基本的显示来说,我想已经足够了. 或者对于这次教程,你会觉得"在屏幕上显示文字没什么难的& ...
- Qt OpenGL 蒙板
这次教程中,我们教介绍OpenGL的蒙板技术.到目前为止,我们已经学会如何使用alpha混合,把一个透明物体渲染到屏幕上了,但有时使用它看起来并不是那么的复合我们的心意.使用蒙板技术,将会使图像按照我 ...
- Qt OpenGL 二次几何体
这次教程中,我将介绍二次几何体.利用二次几何体,我们可以很容易创建球.圆盘.圆柱和圆锥. 我们先介绍一下二次几何体GLUquadric(NeHe教程用的是GLUquadricObj,源代码中GLUqu ...
- QT+OpenGL导入STL文件(二进制/ascll码格式),鼠标交互实现缩放旋转
碎碎念 由于课设和大创涉及到了模型的旋转,因此专门去学习了模型的导入,也是废了不少心思,现在总结一下两种格式的简单导入,以及对stl模型两种格式的简单介绍.网上有很多大佬都有详细的解答,结尾附上链接: ...
- 【Qt OpenGL】Qt Creator中的3D绘图及动画教程
Qt Creator中的3D绘图及动画教程(参照NeHe) 刚刚学习了Qt Creator,发现Qt提供了QtOpenGL模块,对OpenGL做了不错的封装,这使得我们可以很轻松地在Qt程序中使用Op ...
最新文章
- Cisco实战——不让坏人登陆设备
- .c/.cpp文件形成.exe文件的过程
- 海康开放平台音视频方案对比(rtsp、http-flv、hls、rtmp)
- 复旦大学邱锡鹏教授:词法、句法分析研究进展综述
- Game as a Service —— 开源云游戏搭载WebRTC
- mysql for update_mysql SELECT FOR UPDATE语句使用示例
- 如何在ashx页面获取Session值 (仅供个人参考)
- ajax communication failed,AJAX没有收到错误
- java怎么把程序写入持久化_如何将DataFrame持久化到Hive表?
- 蚂蚁金服 ant design 下载axure 组件库
- 测试@Test启动报错解决方案
- 从《硅谷传奇》看微软和苹果
- 解决在mysql官网下载慢的问题
- 小白C语言编程实战(16):统计4门课的优秀率和不及格率
- 将计算机设置成交换机主机名,交换机配置基本使用命令解析
- 计算机被填充背景花束纹理在那,为艺术字设置纹理填充的两种方法
- 商品属性的选择功能的实现
- Android Studio入门(安装--开发调试)
- 【element-plus】el-dialog距离顶部的高度
- 读杨绛先生的《我们仨》部分片段