上一篇QOpenGLWidget详解中,详细介绍了QOpenGLWidget的一些使用方法和特点,下面给出一个具体的例子。
QOpenGLWidget
是一个用来渲染OpenGL图形的窗口组件,它继承于QWidget
;具体使用:
#include
QT += widgets
MyOpenGLWidget
的类MyOpenGLWidget
继承QOpenGLWidget
以及QOpenGLFunctions_3_3_Core
;
QOpenGLWidget
QWidget
的功能,方便集成到应用程序中。initializeGL()
:设置OpenGL资源和状态。该函数只在第一次调用resizeGL()或paintGL()前被调用一次。resizeGL()
:设置OpenGL的视口、投影等。每次部件大小改变时都会调用该函数。paintGL()
:渲染OpenGL场景。每当部件需要更新时都会调用该函数。QOpenGLFunctions_3_3_Core
QOpenGLFunctions_3_3_Core
头文件 MyOpenGLWidget.h
#include
#include
static const char *vertexShaderSource =
"attribute highp vec4 posAttr;\n"
"attribute lowp vec4 colAttr;\n"
"varying lowp vec4 col;\n"
"uniform highp mat4 matrix;\n"
"void main() {\n"
" col = colAttr;\n"
" gl_Position = matrix * posAttr;\n"
"}\n";
static const char *fragmentShaderSource =
"varying lowp vec4 col;\n"
"void main() {\n"
" gl_FragColor = col;\n"
"}\n";
class QOpenGLShaderProgram;
class MyOpenGLWidget : public QOpenGLWidget, protected QOpenGLFunctions_3_3_Core
{
Q_OBJECT
public:
explicit MyOpenGLWidget(QWidget *parent = 0);
~MyOpenGLWidget();
public:
void StartAnimating();
protected:
/*初始化OpenGL资源和状态*/
void initializeGL();
/*渲染OpenGL场景*/
void paintGL();
/*设置OpenGL的视口、投影等。每次部件大小改变时都会调用该函数*/
void resizeGL(int width, int height);
private:
GLint m_posAttr = 0;
GLint m_colAttr = 0;
GLint m_matrixUniform = 0;
QOpenGLShaderProgram *m_program = nullptr;
int m_frame = 0;
QTimer *m_timer;
};
源文件 MyOpenGLWidget.cpp
MyOpenGLWidget::MyOpenGLWidget(QWidget *parent)
: QOpenGLWidget(parent)
{
m_timer = new QTimer(this);
QObject::connect(m_timer, &QTimer::timeout, [this](){
this->update();
});
}
MyOpenGLWidget::~MyOpenGLWidget()
{
m_timer->deleteLater();
}
void MyOpenGLWidget::StartAnimating()
{
m_timer->start(10);
}
void MyOpenGLWidget::initializeGL()
{
// 为当前环境初始化OpenGL函数
initializeOpenGLFunctions();
//新建着色器程序处理工具
m_program = new QOpenGLShaderProgram(this);
//加载顶点着色器程序
m_program->addShaderFromSourceCode(QOpenGLShader::Vertex, vertexShaderSource);
//加载片段着色器程序
m_program->addShaderFromSourceCode(QOpenGLShader::Fragment, fragmentShaderSource);
//链接着色器程序
m_program->link();
//着色器程序位置属性
m_posAttr = m_program->attributeLocation("posAttr");
//断言是否成功
Q_ASSERT(m_posAttr != -1);
//着色器程序颜色属性
m_colAttr = m_program->attributeLocation("colAttr");
//断言是否成功
Q_ASSERT(m_colAttr != -1);
//返回统一值
m_matrixUniform = m_program->uniformLocation("matrix");
//断言是否成功
Q_ASSERT(m_matrixUniform != -1);
}
void MyOpenGLWidget::paintGL()
{
/*清空颜色缓存,深度缓存,模板缓存*/
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
//绑定着色器程序
m_program->bind();
QMatrix4x4 matrix;
//设置透视矩阵
matrix.perspective(60.0f, 4.0f / 3.0f, 0.1f, 100.0f);
//沿着Z轴负方向平移-2
matrix.translate(0, 0, -2);
//绕Y轴旋转
matrix.rotate(m_frame, 0, 1, 0);
//为着色器程序传入当前变换
m_program->setUniformValue(m_matrixUniform, matrix);
//三角形三个顶点
static const GLfloat vertices[] = {
0.0f, 0.707f,
-0.5f, -0.5f,
0.5f, -0.5f
};
//三角形每个顶点对应的颜色值
static const GLfloat colors[] = {
1.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 1.0f
};
//为着色器设置顶点属性
glVertexAttribPointer(m_posAttr, 2, GL_FLOAT, GL_FALSE, 0, vertices);
//为着色器设置颜色属性
glVertexAttribPointer(m_colAttr, 3, GL_FLOAT, GL_FALSE, 0, colors);
//启用顶点着色器属性
glEnableVertexAttribArray(m_posAttr);
//启用颜色着色器属性
glEnableVertexAttribArray(m_colAttr);
//绘制三角形
glDrawArrays(GL_TRIANGLES, 0, 3);
//关闭顶点着色器属性
glDisableVertexAttribArray(m_colAttr);
//关闭颜色着色器属性
glDisableVertexAttribArray(m_posAttr);
//解绑着色器
m_program->release();
++m_frame;
}
void MyOpenGLWidget::resizeGL(int width, int height)
{
/*获取设备像素比*/
const qreal retinaScale = devicePixelRatio();
//设置视口
glViewport(0, 0, width * retinaScale, height * retinaScale);
}
main.cpp
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QSurfaceFormat format;
//设置每个每个像素采样样本个数,用于抗锯齿
format.setSamples(16);
//实例化窗口
MyOpenGLWidget window;
window.setFormat(format);
window.resize(640, 480);
window.StartAnimating();
window.show();
return a.exec();
}
MyOpenGLWidget