文章中引用的内容均来自这本书中的原文:【Qt Creator快速入门_霍亚飞编著】,本文的示例也是在书中代码的基础上进行编写的(其中部分代码使用原文编译不过,进行了修正),这里对相关知识进行了学习总结,想要了解更加详细的内容可见原文。
OpenGL是一个跨平台的、用来渲染3D图形的标准API,Qt对OpenGL提供了强大的支持。Qt4时代的QtOpenGL模块在Qt5中已经不再建议使用,OpenGL相关的类被移到了QtGUI模块。QtWidgets模块中的QOpenGLWidget类提供了一个可以渲染OpenGL图形的部件,通过该部件可以轻松地将OpenGL图形整合到Qt应用程序中。
提示:以下是本篇文章正文内容,下面案例可供参考
QOpenGLWidget类是一个用来渲染OpenGL图形的部件,它提供了在Qt应用程序中显示 OpenGL图形的功能。这个类使用起来很简单,只需要继承该类,然后像使用其他QWidget 部件一样来使用它即可。QGLWidget 提供了3个方便的虚函数,可以在子类中重新实现它们来执行典型的 OpenGL任务:
initializeGL():设置 OpenGL资源和状态,该函数只在第一次调用resizeGL()或paintGL()前被调用一次;
resizeGL():设置OpenGL的视口投影等,每次部件改变大小时都会调用该函数;
paintGL():渲染OpenGL 场景,每当部件需要更新时都会调用该函数。
这里介绍下Qt下一些类的使用和OpenGL中重要的概念或名称,详情可见参考文章:
QOpenGLShader:用来创建和编译着色器。着色器是使用 OpenGL着色语言(OpenGL Shading Language,GLSL)编写的一个小型函数。绘图时需要至少指定两个着色器;顶点着色器(vertexshader)和片段着色器(fragmentshader,也称为片元着色器)
QOpenGLShaderProgram:用来创建并设置着色器程序,可以链接多个着色器,并在OpenGL当前环境(current context,也称为当前上下文)中绑定着色器程序
QAbstractOpenGLFunctions:是一个类族的基类,类族中的类涉及了所有 OpenGL 版本,并为相应版本 OpenGL 的所有函数提供了访问接口
QOpenGLBuffer:用来创建并管理OpenGL缓存对象
QOpenGLTexture:封装了一个OpenGL纹理对象,可以使用该类来设置纹理
1.MyOpenGL.pro
QT += widgets
HEADERS += \
myopenglwidget.h
SOURCES += \
main.cpp \
myopenglwidget.cpp
2.myopenglwidget.h
#ifndef MYOPENGLWIDGET_H
#define MYOPENGLWIDGET_H
#include
#include
#include
#include
#include
#include
class QOpenGLTexture;
class QOpenGLShaderProgram;
class MyOpenGLWidget : public QOpenGLWidget, protected QOpenGLFunctions
{
Q_OBJECT
public:
explicit MyOpenGLWidget(QWidget *parent = 0);
protected:
void initializeGL();
void paintGL();
void resizeGL(int width,int height);
void keyPressEvent(QKeyEvent *event);
private:
QOpenGLShaderProgram *program;
QOpenGLBuffer vbo;
QOpenGLTexture *textures[2];
GLfloat translate,xRot,yRot,zRot;
};
#endif // MYOPENGLWIDGET_H
3.myopenglwidget.cpp
#include "myopenglwidget.h"
MyOpenGLWidget::MyOpenGLWidget(QWidget *parent)
: QOpenGLWidget(parent)
{
//初始化变量
translate = -6.0;
xRot = zRot = 0.0;
yRot = -30.0;
}
void MyOpenGLWidget::initializeGL()
{
//初始化纹理变量
for(int i=0;i<2;i++)
{
textures[i] = new QOpenGLTexture(QImage(QString("../MyOpenGL/side%1.jpg").arg(i+1)).mirrored());
}
//为当前环境初始化OpenGL环境
initializeOpenGLFunctions();
//开启深度测试
glEnable(GL_DEPTH_TEST);
//下列着色器使用书中代码运行报错,进行了修正
//创建顶点着色器
QOpenGLShader *vshader = new QOpenGLShader(QOpenGLShader::Vertex,this);
const char *vsrc = "#version 330\n"
"in vec4 vPosition;\n"
"in vec2 vTexCoord;\n"
"out vec2 texCoord;\n"
"uniform mat4 matrix;\n"
"void main()\n"
"{\n"
" texCoord = vTexCoord;\n"
" gl_Position = matrix * vPosition;\n"
"}\n";
vshader->compileSourceCode(vsrc);
//创建片段着色器
QOpenGLShader *fshader = new QOpenGLShader(QOpenGLShader::Fragment,this);
const char *fsrc = "#version 330\n"
"uniform sampler2D tex;\n"
"in vec2 texCoord;\n"
"out vec4 fColor;\n"
"void main()\n"
"{\n"
" fColor = texture(tex,texCoord);\n"
"}\n";
fshader->compileSourceCode(fsrc);
//创建着色器程序
program = new QOpenGLShaderProgram;
program->addShader(vshader);
program->addShader(fshader);
program->link();
program->bind();
}
void MyOpenGLWidget::paintGL()
{
//设置视口为正方形
int w = width();
int h = height();
int side = qMin(w,h);
glViewport((w-side)/2,(h-side)/2,side,side);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//顶点位置
GLfloat vertices[2][4][3] =
{
{{-0.8f,0.8f,0.8f},{-0.8f,-0.8f,0.8f},{0.8f,-0.8f,0.8f},{0.8f,0.8f,0.8f}},
{{0.8f,0.8f,0.8f},{0.8f,-0.8f,0.8f},{0.8f,-0.8f,-0.8f},{0.8f,0.8f,-0.8f}}
};
//添加缓存
vbo.create();
vbo.bind();
vbo.allocate(vertices,48*sizeof(GLfloat));
GLuint vPosition = program->attributeLocation("vPosition");
//glVertexAttribPointer(vPosition,2,GL_FLOAT,GL_FALSE,0,vertices);
program->setAttributeBuffer(vPosition,GL_FLOAT,0,3,0);
glEnableVertexAttribArray(vPosition);
//顶点着色
GLfloat coords[2][4][2] =
{
{{0.0f,1.0f},{0.0f,0.0f},{1.0f,0.0f},{1.0f,1.0f}},
{{0.0f,1.0f},{0.0f,0.0f},{1.0f,0.0f},{1.0f,1.0f}}
};
vbo.write(24*sizeof(GLfloat),coords,16*sizeof(GLfloat));
GLuint vTexCoord = program->attributeLocation("vTexCoord");
program->setAttributeBuffer(vTexCoord,GL_FLOAT,24*sizeof(GLfloat),2,0);
glEnableVertexAttribArray(vTexCoord);
program->setUniformValue("tex",0);
//顶点变换
QMatrix4x4 matrix;
matrix.perspective(45.0f,(GLfloat)w/(GLfloat)h,0.1f,100.0f);
matrix.translate(0,0,translate);
matrix.rotate(xRot,1.0,0.0,0.0);
matrix.rotate(yRot,0.0,1.0,0.0);
matrix.rotate(zRot,0.0,0.0,1.0);
program->setUniformValue("matrix",matrix);
//绘制函数
for(int i=0;i<2;i++)
{
textures[i]->bind();
glDrawArrays(GL_TRIANGLE_FAN,i*4,4);
}
}
void MyOpenGLWidget::resizeGL(int,int)
{
}
//按键事件
void MyOpenGLWidget::keyPressEvent(QKeyEvent *event)
{
switch(event->key())
{
case Qt::Key_Up:
xRot -= 10;
break;
case Qt::Key_Down:
xRot += 10;
break;
case Qt::Key_Left:
yRot -= 10;
break;
case Qt::Key_Right:
yRot += 10;
break;
case Qt::Key_PageUp:
zRot -= 10;
break;
case Qt::Key_PageDown:
zRot += 10;
break;
case Qt::Key_Space:
translate += 1;
break;
case Qt::Key_Alt:
translate -= 1;
break;
default:
break;
}
update();
QOpenGLWidget::keyPressEvent(event);
}
4.main.cpp
#include
#include "myopenglwidget.h"
int main(int argc,char *argv[])
{
QApplication app(argc,argv);
MyOpenGLWidget w;
w.resize(400,300);
w.show();
return app.exec();
}
通过对书上的3D绘图这一章节学习,我也对在Qt下使用OpenGL进行了初步的了解,本文仅仅将示例展示给大家,没有进行很详细的解释,详见学习书籍:【Qt Creator快速入门_霍亚飞编著】
这里也推荐一个关于OpenGL的学习网站:LearnOpenGL CN(https://learnopengl-cn.github.io/)
hello:
共同学习,共同进步,如果还有相关问题,可在评论区留言进行讨论。
学习书籍:【Qt Creator快速入门_霍亚飞编著】
参考文章:
OpenGL 基本概念
在Qt中使用OpenGL(一)