写在前面:
QT中使用OpenGL有两种方法,其实也不叫方法,只是窗体表现形式
1、使用设计栏的OpenGL Widget并提升为一个自定义的widget类
2、直接定义一个OpenGL widget类
方法一
1、在设计界面添加一个OpenGL Widget组件
2、工程文件.pro中引入OpenGL Widget模块
QT += core gui openglwidgets
3、创建一个自定义的widget类,继承于QOpenGLWidget , QOpenGLFunctions_3_3_Core,并重写三个opengl绘图函数
.h文件:
#ifndef MYWIDGET_H
#define MYWIDGET_H
#include <QObject>
#include <QtOpenGLWidgets/QOpenGLWidget>
#include <QOpenGLFunctions_3_3_Core>
class MyWidget : public QOpenGLWidget , QOpenGLFunctions_3_3_Core
{
Q_OBJECT
public:
explicit MyWidget(QWidget *parent = nullptr);
protected:
virtual void initializeGL();
virtual void resizeGL(int w, int h);
virtual void paintGL();
signals:
};
#endif // MYWIDGET_H
.cpp文件
#include "mywidget.h"
MyWidget::MyWidget(QWidget *parent)
: QOpenGLWidget{parent}
{
}
void MyWidget::initializeGL()
{
initializeOpenGLFunctions();
}
void MyWidget::resizeGL(int w, int h)
{
// qDebug()<<"test";
}
void MyWidget::paintGL()
{
glClear(GL_COLOR_BUFFER_BIT);
glClearColor(0.2f, 0.4f, 0.1f, 1.0f);
}
4、设计界面里将原始OpengGL Widget组件提升为自定义的类
5、运行结果
方法二
1、创建一个QT设计界面类,我这里选的是widget
2、与方法一一致,改变继承关系、重写绘制函数
#ifndef MYWINDOW_H
#define MYWINDOW_H
#include <QWidget>
#include <QtOpenGLWidgets/QOpenGLWidget>
#include <QOpenGLFunctions_3_3_Core>
namespace Ui {
class MyWindow;
}
class MyWindow : public QOpenGLWidget,QOpenGLFunctions_3_3_Core
{
Q_OBJECT
public:
explicit MyWindow(QOpenGLWidget *parent = nullptr);
~MyWindow();
protected:
virtual void initializeGL();
virtual void resizeGL(int w, int h);
virtual void paintGL();
private:
Ui::MyWindow *ui;
};
#endif // MYWINDOW_H
#include "mywindow.h"
#include "ui_mywindow.h"
MyWindow::MyWindow(QOpenGLWidget *parent)
: QOpenGLWidget(parent)
, ui(new Ui::MyWindow)
{
ui->setupUi(this);
}
MyWindow::~MyWindow()
{
delete ui;
}
void MyWindow::initializeGL()
{
initializeOpenGLFunctions();
}
void MyWindow::resizeGL(int w, int h)
{
}
void MyWindow::paintGL()
{
glClear(GL_COLOR_BUFFER_BIT);
glClearColor(0.2f, 0.4f, 0.1f, 1.0f);
}
3、实例化widget类对象,并显示
MyWindow w;
w.show();
4、结果
方法一进行三角形绘制案例
自定义widget类的声明:
#ifndef MYWIDGET_H
#define MYWIDGET_H
#include <QObject>
#include <QtOpenGLWidgets/QOpenGLWidget>
#include <QOpenGLFunctions_3_3_Core>
#include <QOpenGLShader>
#include <QOpenGLShaderProgram>
#include <QOpenGLVertexArrayObject>
class MyWidget : public QOpenGLWidget , QOpenGLFunctions_3_3_Core
{
Q_OBJECT
public:
explicit MyWidget(QWidget *parent = nullptr);
protected:
virtual void initializeGL();
virtual void resizeGL(int w, int h);
virtual void paintGL();
private:
GLuint VBO; //顶点缓冲对象
GLuint VAO; //顶点数组对象
QOpenGLShaderProgram shaderProgram; // 着色器程序
signals:
};
#endif // MYWIDGET_H
自定义widget类的实现,附上超详细注释
#include "mywidget.h"
MyWidget::MyWidget(QWidget *parent)
: QOpenGLWidget{parent}
{
}
void MyWidget::initializeGL()
{
initializeOpenGLFunctions();
//声明三角形顶点数据
GLfloat vertices[]=
{ -0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.0f, 0.5f, 0.0f
};
// 生成并绑定顶点数组对象
glGenVertexArrays(1, &VAO);//1表示对象个数
glBindVertexArray(VAO);
// 生成顶点缓冲对象
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO); //将标识符为 VBO 的缓冲对象绑定到 GL_ARRAY_BUFFER 目标上
// 将顶点数据存储到VBO中
glBufferData(GL_ARRAY_BUFFER,sizeof(vertices),vertices,GL_STATIC_DRAW);
// 指定顶点数组中每个顶点属性的数据格式
//0 表示顶点属性数组中的第一个属性;3 表示每个顶点属性有三个浮点数;GL_FLOAT 表示每个组件是一个单精度浮点数
//GL_FALSE 表示不进行归一化 ;3 * sizeof(GLfloat) 表示每个顶点属性之间相隔3个浮点数,即12个字节;(void*)0 表示从数组的开头开始
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (void*)0);
//启用指定索引的顶点属性数组.0 是顶点属性数组的索引
glEnableVertexAttribArray(0);
// 解绑VBO和VAO,将原先绑定在VAO、VBO的数据绑定到 0 上
// 确保在后续的渲染或设置状态之前,没有任何缓冲或顶点数组对象处于活动状态
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
QOpenGLShader vertexShader(QOpenGLShader::Vertex);
vertexShader.compileSourceFile(":/res/demo.vert");
QOpenGLShader fragShader(QOpenGLShader::Fragment);
fragShader.compileSourceFile(":/res/demo.frag");
shaderProgram.addShader(&vertexShader);
shaderProgram.addShader(&fragShader);
//链接着色器程序
shaderProgram.link();
}
void MyWidget::resizeGL(int w, int h)
{
// qDebug()<<"test";
}
void MyWidget::paintGL()
{
// 使用指定的清除颜色清除颜色缓冲区
glClearColor(0.2f, 0.4f, 0.1f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
// 激活着色器程序,准备进行绘制
shaderProgram.bind();
// 绑定之前创建的顶点数组对象
glBindVertexArray(VAO);
// 使用OpenGL函数绘制一个三角形,0 是指从顶点数组的第一个顶点开始绘制。3 是指绘制的顶点数量,这里是一个三角形
glDrawArrays(GL_TRIANGLES,0,3);
update();
}
这里我把顶点着色器和片段着色器程序放在资源文件里
片段着色器,用于处理片段(像素)的颜色
#version 330 core
out vec4 FragColor;
void main()
{
FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);
}
顶点着色器,用于处理顶点数据
#version 330 core
layout (location = 0) in vec3 aPos;
void main()
{
gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);
}
运行结果