基于qt5.7.1示例程序openglwindow的解读1
show()-->exposeEvent()-->run()-->postEvent()
-->event()-->run()-->postEvent()
-->event()-->run()-->postEvent()
-->event()-->run()-->postEvent()
-->event()-->run()-->postEvent()
注释: 每次窗口大小改变是都会产生exposeEvent信号,
绘画结束后通过postEvent产生一个event信号。
QT -= core
QT += gui
CONFIG += c++11
CONFIG += console
SOURCES += main.cpp \
openglwindow.cpp
HEADERS += \
openglwindowain.cpp
#include "openglwindow.h"
#include
int main(int argc, char *argv[])
{
QGuiApplication a(argc, argv);
OpenGLWindow window;
window.resize(640, 480);
window.show();
// window.run(); // 不需要run,show()自动进入
return a.exec()
}
#ifndef OPENGLWINDOW_H
#define OPENGLWINDOW_H
#include
#include
QT_BEGIN_NAMESPACE
class QPainter;
class QOpenGLContext;
class QOpenGLPaintDevice;
class QOpenGLShaderProgram;
QT_END_NAMESPACE
class OpenGLWindow : public QWindow, protected QOpenGLFunctions
{
Q_OBJECT
public:
explicit OpenGLWindow(QWindow *parent = 0);
~OpenGLWindow();
void TestFunction(); // Test绘图
void InitShader(); // 初始化着色器(画刷)
void DrawImage(); // 执行绘图动作
private:
QOpenGLContext *m_context; // 画板对象
QOpenGLShaderProgram *m_program; // 着色器(画刷)对象
GLuint m_posAttr; // 着色器参数:属性
GLuint m_colAttr; // 着色器参数:纹理
GLuint m_matrixUniform; // 着色器参数:uniform
int m_frame; // 循环变量,只要到一次
bool m_update_pending; // 绘图完成标志(窗口更新标志)
public slots:
void run(); // 动画效果实现
protected: // 消息发生器(重载而来)
bool event(QEvent *event) Q_DECL_OVERRIDE;
void exposeEvent(QExposeEvent *event) Q_DECL_OVERRIDE;
};
#endif // OPENGLWINDOW_H
#include "openglwindow.h"
#include
#include
#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";
OpenGLWindow::OpenGLWindow(QWindow *parent)
: QWindow(parent)
, m_context(0)
, m_frame(0)
, m_update_pending(false)
{
setSurfaceType(QWindow::OpenGLSurface);
}
OpenGLWindow::~OpenGLWindow()
{
if(m_context)
delete m_context;
}
void OpenGLWindow::TestFunction()
{
if(m_context)
{
m_context->makeCurrent(this);
DrawImage();
m_context->swapBuffers(this);
return;
}
m_context = new QOpenGLContext(this);
m_context->create();
m_context->makeCurrent(this);
initializeOpenGLFunctions();
InitShader();
DrawImage();
m_context->swapBuffers(this);
}
void OpenGLWindow::InitShader()
{
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");
m_colAttr = m_program->attributeLocation("colAttr");
m_matrixUniform = m_program->uniformLocation("matrix");
}
void OpenGLWindow::DrawImage()
{
const qreal retinaScale = devicePixelRatio();
glViewport(0, 0, width() * retinaScale, height() * retinaScale);
glClear(GL_COLOR_BUFFER_BIT);
m_program->bind();
QMatrix4x4 matrix;
matrix.perspective(60.0f, 4.0f/3.0f, 0.1f, 100.0f);
matrix.translate(0, 0, -2);
matrix.rotate(100.0f * m_frame++ / screen()->refreshRate(), 0, 1, 0);
m_program->setUniformValue(m_matrixUniform, matrix);
GLfloat vertices[] = {
0.0f, 0.707f,
-0.5f, -0.5f,
0.5f, -0.5f
};
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(0);
glEnableVertexAttribArray(1);
glDrawArrays(GL_TRIANGLES, 0, 3);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(0);
m_program->release();
}
bool OpenGLWindow::event(QEvent *event)
{
if(event->type() != QEvent::UpdateRequest)
return QWindow::event(event);
m_update_pending = false;
if(isExposed()) run();
return true;
}
void OpenGLWindow::exposeEvent(QExposeEvent *event)
{
Q_UNUSED(event);
if(isExposed()) run();
}
void OpenGLWindow::run()
{
TestFunction();
if (m_update_pending) return;
m_update_pending = true;
QCoreApplication::postEvent(this, new QEvent(QEvent::UpdateRequest));
}