一. 内容简介
qt使用opengl绘制矩形,三维摄像机
二. 软件环境
2.1QT 5.14.1
QT编译器采用的是MSVC2017 64bit
2.2代码
链接:https://pan.baidu.com/s/1Fn6UpF0HLWD_mSSKe_36wA?pwd=1234 (矩形)
链接:https://pan.baidu.com/s/1PV4sYk_WgnhUiBhyyCy4iA?pwd=1234 (三维的)
三.主要流程
3.1 界面设置
qt中有直接支持opengl的窗口,但是这个没办法给他写代码,那就创建一个类,继承QOpenGLWidget类,然后再给窗口提升为创建的类,
需要重写三个虚函数,
#ifndef QQQOPENGLWIDGET_H
#define QQQOPENGLWIDGET_H
#include <QOpenGLWidget>
#include <QOpenGLFunctions_3_3_Core>
class QQQOpenGLWidget : public QOpenGLWidget,QOpenGLFunctions_3_3_Core
{
Q_OBJECT
public:
explicit QQQOpenGLWidget(QWidget *parent = nullptr);
protected:
virtual void initializeGL();
virtual void resizeGL(int w, int h);
virtual void paintGL();
};
#endif // QQQOPENGLWIDGET_H
这个构造函数需要加上: QOpenGLWidget(parent),不然没办法出图
QQQOpenGLWidget::QQQOpenGLWidget(QWidget *parent) : QOpenGLWidget(parent)
{
}
void QQQOpenGLWidget::initializeGL() {
// 这个是都要加的初始化一下,不然程序指针都是空的,调用显卡的函数
initializeOpenGLFunctions();
}
void QQQOpenGLWidget::resizeGL(int w, int h)
{
}
void QQQOpenGLWidget::paintGL()
{
glClearColor(0.2f,0.3f,0.3f,1.0f);
glClear(GL_COLOR_BUFFER_BIT);
}
然后就会出现图像了,窗口设置就好了
3.2 代码讲解
这里就分块讲解了,我只讲我学的时候里面比较难理解的点
第一步是先创建VAO,VBO,EBO。
VAO的作用就是记录缓存区里面的点怎么读,EBO会记录点的读取顺序的,VAO也会记住EBO的位置,方便后边读取,如果EBO解绑了,VAO就找不到EBO,但是VBO不会的,VBO随便解绑
VBO和EBO都是显卡中的一块显存,
GL_ARRAY_BUFFER,GL_ELEMENT_ARRAY_BUFFER是不同的缓存区,缓存区用来存放点的坐标,给缓存区绑定VBO,EBO就是,告诉相应的缓存区他们的数据应该往哪写入,
最后解绑那块,就是防止后续操作更改了已经设置好的状态,防止VAO状态改变,防止VBO,EBO中的数据被改写
// 状态设置
//创建VBO和VAO对象,并赋予ID
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glGenBuffers(1, &EBO);
//绑定VBO和VAO对象
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
//告知显卡如何解析缓冲里的属性值
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
//开启VAO管理的第一个属性值
glEnableVertexAttribArray(0);
// 这个是状态设置完成
// VAO会记录EBO的绑定状态,而不会记录VBO的,如果EBO提前解绑,就会找不到EBO
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
这块是设置着色器的代码,固定格式,里面也写了解析
// 设置着色器
unsigned int vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
// 设置片段着色器
unsigned int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
// glPolygonMode 是一个用于控制多边形的绘制模式的函数。它可以设置多边形的绘制模式,包括填充模式、线框模式和点模式。
// glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
// 删除着色器对象的主要原因是释放内存和资源。当你将着色器对象链接到程序对象后,它们的内容已经被复制到了程序对象中,并且不再需要单独的着色器对象来执行渲染。
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
绘图
void QQQOpenGLWidget::paintGL()
{
glClearColor(0.2f,0.3f,0.3f,1.0f);
glClear(GL_COLOR_BUFFER_BIT);
// 设定着色器
glUseProgram(shaderProgram);
// VAO初始化状态
glBindVertexArray(VAO);
// glDrawArrays(GL_TRIANGLES, 0, 3);
// 重复绘图也不会被覆盖的,都是在一个上面的
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
}
析构函数
// 获取当前状态
makeCurrent();
// 1是个数
glDeleteVertexArrays(1,&VAO);
glDeleteBuffers(1,&VBO);
glDeleteBuffers(1,&EBO);
glDeleteProgram(shaderProgram);
// 退出当前状态
doneCurrent();
外部调用绘图的两种方式,
第一种,
void QQQOpenGLWidget::draw()
{
// 获取当前状态
makeCurrent();
glClearColor(0.2f,0.3f,0.3f,1.0f);
glClear(GL_COLOR_BUFFER_BIT);
// 设定着色器
glUseProgram(shaderProgram);
// VAO初始化状态
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
// 退出当前状态
doneCurrent();
}
第二种是
// 会调用paintGL(),进行重绘
update();
3.3 三维三维摄像机,以后再更新
先放个图。代码在最上边,按钮有问题,凑合看吧
四.参考
https://ke.qq.com/webcourse/3999604/104150693#taid=12078191069693812&vid=3701925924839353164