直接上QOpenGLWidget类的.h和.cpp代码:
代码相对于第一节增加了析构函数,对内存合理释放。同时开放了和主界面互动的接口,想要通过按钮或者其他控件进行绘图,只需要在类中开放接口即可。程序给了详细的注释。
#ifndef MYOPENGLWIDGET_H
#define MYOPENGLWIDGET_H
#include
#include
class myopenglwidget : public QOpenGLWidget,QOpenGLFunctions_3_3_Core
{
Q_OBJECT
public:
enum Shape{None,Rect,Circle,Triangle};
explicit myopenglwidget(QWidget *parent = nullptr);
~myopenglwidget();//析构函数
void drawShape(Shape shape);//画图形接口函数
void setWirefame(bool wireframe);//有无填充接口函数
protected:
virtual void initializeGL();
virtual void resizeGL(int w, int h);
virtual void paintGL();
private:
Shape m_shape;
};
#endif // MYOPENGLWIDGET_H
#include "myopenglwidget.h"
//创建VAO和VBO对象,并赋予ID
unsigned int VBO,VAO,EBO;
float vertices[] = {
0.5f, 0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
-0.5f, -0.5f, 0.0f,
-0.5f, 0.5f, 0.0f,
};
unsigned int indices[] = {
0, 1, 3,
1, 2, 3
};
myopenglwidget::myopenglwidget(QWidget *parent) : QOpenGLWidget(parent)
{
}
myopenglwidget::~myopenglwidget()
{
makeCurrent();//调用当前状态 不用管为什么,加就好了
glDeleteBuffers(1,&VBO);
glDeleteVertexArrays(1,&VAO);
//glDeleteProgram(shaderProgram);
doneCurrent();//改变当前状态 不用管为什么,加就好了
}
void myopenglwidget::drawShape(myopenglwidget::Shape shape)
{
m_shape = shape;
update();
}
void myopenglwidget::setWirefame(bool wireframe)
{
makeCurrent();//调用当前状态
if(wireframe)
glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
else
glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
update();
doneCurrent();//改变当前状态
}
void myopenglwidget::initializeGL()
{
initializeOpenGLFunctions();
glGenVertexArrays(1,&VAO);//顶点数组用来存数据的结构
glGenBuffers(1,&VBO);//缓冲区用来存放顶点数据
//绑定VBO和VAO对象
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER,VBO);
//为当前绑定到数据的缓冲区对象开辟一个新的数据空间,如果数据不为空,则数据从内存传到显存
glBufferData(GL_ARRAY_BUFFER,sizeof(vertices),vertices,GL_STATIC_DRAW);
//告知显卡如何解析传过去的数据,该过程会被VAO偷偷记录
glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,3*sizeof(float),(void*)0);//第0个属性、三个值、浮点型、不需要标准化,步长,偏移量
//开启VAO管理的第一个属性值
glEnableVertexAttribArray(0);
//小助理可以休息了,养成好习惯,因为以后有很多的小助理
glBindBuffer(GL_ARRAY_BUFFER,0);
//绑定VEO对象
glGenBuffers(1,&EBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof(indices),indices,GL_STATIC_DRAW);
glBindVertexArray(0);
}
void myopenglwidget::resizeGL(int w, int h)
{
}
void myopenglwidget::paintGL()//所有绘制都在这里面,别的地方只是进行一个触发
{
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
//glUseProgram(shaderProgram);
glBindVertexArray(VAO);
switch(m_shape){
case Rect:
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
break;
default:
break;
}
}