OpenGL(四)之Qt窗口(QOpenGLWidget簡單例子)
上一篇QOpenGLWidget詳解中,詳細介紹了QOpenGLWidget的一些使用方法和特點,下面給出一個具體的例子。
QOpenGLWidget 簡單例子
簡介
QOpenGLWidget
是一個用來渲染OpenGL圖形的窗口組件,它繼承於QWidget
;具體使用:
- Header:
- 頭文件:
#include <QOpenGLWidget>
- qmake:
QT += widgets
- 版本: Qt 5.4之後
實例
創建一個MyOpenGLWidget
的類
MyOpenGLWidget
繼承QOpenGLWidget
以及QOpenGLFunctions_3_3_Core
;
- 繼承
QOpenGLWidget
- 繼承所有
QWidget
的功能,方便集成到應用程序中。 - 提供渲染OpenGL的圖形部件,具體爲:
initializeGL()
:設置OpenGL資源和狀態。該函數只在第一次調用resizeGL()或paintGL()前被調用一次。
resizeGL()
:設置OpenGL的視口、投影等。每次部件大小改變時都會調用該函數。
頭文件 MyOpenGLWidget.h
paintGL()
:渲染OpenGL場景。每當部件需要更新時都會調用該函數。
- 繼承
QOpenGLFunctions_3_3_Core
- 可以直接使用
QOpenGLFunctions_3_3_Core
- 根據需求替換OpenGL核心框架,或是換成兼容固定線管的框架
頭文件 MyOpenGLWidget.h
#include <QOpenGLWidget>
#include <QOpenGLFunctions_3_3_Core>
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();
}