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学习(一)相关推荐

  1. Qt|OpenGL学习笔记-绕X轴、Y轴、以及XY轴旋转的四边体

    程序运行截图如下: 源码如下: myglwidget.h #ifndef MYGLWIDGET_H #define MYGLWIDGET_H#include <QWidget> #incl ...

  2. OpenGL(十四)——Qt OpenGL纹理

    OpenGL(十四)--Qt OpenGL纹理 一.纹理 终于写到纹理的部分了: 纹理(Texture)的本质是一个2D图片(1D和3D),或者叫图形数据.只是在OpenGL中专业术语中称其为纹理. ...

  3. OpenGL学习笔记(一):环境搭建、三维空间坐标系理解以及OpenGL的基本使用

    原博主博客地址:http://blog.csdn.net/qq21497936 本文章博客地址:http://blog.csdn.net/qq21497936/article/details/7866 ...

  4. Qt OpenGL 旗帜效果(飘动的纹理)

    这次教程中,我将教大家如何创建一个飘动的旗帜.我们所要创建的旗帜,说白了就是一个以正弦波方式运动的纹理映射图像.虽然不会很难,但效果确实很不错,希望大家能喜欢.当然这次教程是基于第06课的,希望大家确 ...

  5. QT开发学习-第一章-QT简介

    QT简介 一.QT简介 1.QT简介 2.QT优点 二.QT开发工具 1.Qt Creator 2.Qt Designer 3.Qt Linguist 4.Qt Assistant 5.Qmake 6 ...

  6. Qt OpenGL 位图字体

    这次教程中,我们将创建一些基于2D图像的字体,它们可以缩放平移,但不能旋转,并且总是面向前方,但作为基本的显示来说,我想已经足够了. 或者对于这次教程,你会觉得"在屏幕上显示文字没什么难的& ...

  7. Qt OpenGL 蒙板

    这次教程中,我们教介绍OpenGL的蒙板技术.到目前为止,我们已经学会如何使用alpha混合,把一个透明物体渲染到屏幕上了,但有时使用它看起来并不是那么的复合我们的心意.使用蒙板技术,将会使图像按照我 ...

  8. Qt OpenGL 二次几何体

    这次教程中,我将介绍二次几何体.利用二次几何体,我们可以很容易创建球.圆盘.圆柱和圆锥. 我们先介绍一下二次几何体GLUquadric(NeHe教程用的是GLUquadricObj,源代码中GLUqu ...

  9. QT+OpenGL导入STL文件(二进制/ascll码格式),鼠标交互实现缩放旋转

    碎碎念 由于课设和大创涉及到了模型的旋转,因此专门去学习了模型的导入,也是废了不少心思,现在总结一下两种格式的简单导入,以及对stl模型两种格式的简单介绍.网上有很多大佬都有详细的解答,结尾附上链接: ...

  10. 【Qt OpenGL】Qt Creator中的3D绘图及动画教程

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

最新文章

  1. Cisco实战——不让坏人登陆设备
  2. .c/.cpp文件形成.exe文件的过程
  3. 海康开放平台音视频方案对比(rtsp、http-flv、hls、rtmp)
  4. 复旦大学邱锡鹏教授:词法、句法分析研究进展综述
  5. Game as a Service —— 开源云游戏搭载WebRTC
  6. mysql for update_mysql SELECT FOR UPDATE语句使用示例
  7. 如何在ashx页面获取Session值 (仅供个人参考)
  8. ajax communication failed,AJAX没有收到错误
  9. java怎么把程序写入持久化_如何将DataFrame持久化到Hive表?
  10. 蚂蚁金服 ant design 下载axure 组件库
  11. 测试@Test启动报错解决方案
  12. 从《硅谷传奇》看微软和苹果
  13. 解决在mysql官网下载慢的问题
  14. 小白C语言编程实战(16):统计4门课的优秀率和不及格率
  15. 将计算机设置成交换机主机名,交换机配置基本使用命令解析
  16. 计算机被填充背景花束纹理在那,为艺术字设置纹理填充的两种方法
  17. 商品属性的选择功能的实现
  18. Android Studio入门(安装--开发调试)
  19. 【element-plus】el-dialog距离顶部的高度
  20. 读杨绛先生的《我们仨》部分片段

热门文章

  1. 审核员必看|不符合项报告还不会写?一篇文章搞定
  2. Windows彻底停止nginx服务
  3. windows 下怎么停止 nginx 服务
  4. 协变(Covariance)、逆变(Contravariance)与不变(Invariance)in Scala
  5. Redis实例绑定CPU物理核优化Redis性能
  6. 浅谈质量方案中的预案
  7. 从计算到智算,计算产业掀起什么样的浪潮?
  8. Errors running builder 'Integrated External Tool Builder' on project 'rVoix'
  9. 三毛最伤心的100句话
  10. arcgis在线底图url地址 - 解析