Clean up the QOpenGLWindow example

1. Use includes without module prefixes, as is the custom in examples.
2. No inline functions to make it more readable.
3. Pause animation on pressing P and document our signal connection a bit more.

Change-Id: I68dc3d4c74b639cf3fec17b63b7f49626db58bdb
Reviewed-by: Gunnar Sletta <gunnar.sletta@jollamobile.com>
This commit is contained in:
Laszlo Agocs 2014-08-06 10:25:36 +02:00
parent 37023a096d
commit 78221fe762
3 changed files with 116 additions and 82 deletions

View File

@ -40,13 +40,13 @@
#include "background_renderer.h"
#include <QtCore/qmath.h>
#include <QtCore/QFileInfo>
#include <QtCore/QTime>
#include <qmath.h>
#include <QFileInfo>
#include <QTime>
#include <QtGui/QOpenGLShaderProgram>
#include <QtGui/QOpenGLContext>
#include <QtGui/QOpenGLFunctions>
#include <QOpenGLShaderProgram>
#include <QOpenGLContext>
#include <QOpenGLFunctions>
#include <math.h>

View File

@ -41,14 +41,14 @@
#ifndef FRAGMENT_TOY_H
#define FRAGMENT_TOY_H
#include <QtCore/QObject>
#include <QtCore/QFile>
#include <QtCore/QDateTime>
#include <QtCore/QFileSystemWatcher>
#include <QtGui/QOpenGLVertexArrayObject>
#include <QtGui/QOpenGLBuffer>
#include <QtGui/QOpenGLShaderProgram>
#include <QtGui/QOpenGLFunctions>
#include <QObject>
#include <QFile>
#include <QDateTime>
#include <QFileSystemWatcher>
#include <QOpenGLVertexArrayObject>
#include <QOpenGLBuffer>
#include <QOpenGLShaderProgram>
#include <QOpenGLFunctions>
class FragmentToy : public QObject, protected QOpenGLFunctions
{

View File

@ -38,12 +38,13 @@
**
****************************************************************************/
#include <QtGui/QOpenGLWindow>
#include <QtGui/QScreen>
#include <QtGui/QPainter>
#include <QtGui/QGuiApplication>
#include <QtGui/QMatrix4x4>
#include <QtGui/QStaticText>
#include <QOpenGLWindow>
#include <QScreen>
#include <QPainter>
#include <QGuiApplication>
#include <QMatrix4x4>
#include <QStaticText>
#include <QKeyEvent>
#include "background_renderer.h"
@ -65,71 +66,16 @@ class OpenGLWindow : public QOpenGLWindow
Q_OBJECT
public:
// Use NoPartialUpdate. This means that all the rendering goes directly to
// the window surface, no additional framebuffer object stands in the
// middle. This is fine since we will clear the entire framebuffer on each
// paint. Under the hood this means that the behavior is equivalent to the
// manual makeCurrent - perform OpenGL calls - swapBuffers loop that is
// typical in pure QWindow-based applications.
OpenGLWindow()
: QOpenGLWindow(QOpenGLWindow::NoPartialUpdate)
, m_fragment_toy("background.frag")
, m_text_layout("The triangle and this text is rendered with QPainter")
{
m_view.lookAt(QVector3D(3,1,1),
QVector3D(0,0,0),
QVector3D(0,1,0));
connect(this, SIGNAL(frameSwapped()), this, SLOT(update()));
QLinearGradient gradient(QPointF(-1,-1), QPointF(1,1));
gradient.setColorAt(0, Qt::red);
gradient.setColorAt(1, Qt::green);
m_brush = QBrush(gradient);
}
OpenGLWindow();
protected:
void paintGL() Q_DECL_OVERRIDE
{
m_fragment_toy.draw(size());
QPainter p(this);
p.setWorldTransform(m_window_normalised_matrix.toTransform());
QMatrix4x4 mvp = m_projection * m_view * m_model_triangle;
p.setTransform(mvp.toTransform(), true);
p.fillPath(painterPathForTriangle(), m_brush);
QTransform text_transform = (m_window_painter_matrix * m_view * m_model_text).toTransform();
p.setTransform(text_transform, false);
p.setPen(QPen(Qt::white));
m_text_layout.prepare(text_transform);
qreal x = - (m_text_layout.size().width() / 2);
qreal y = 0;
p.drawStaticText(x, y, m_text_layout);
m_model_triangle.rotate(-1, 0, 1, 0);
m_model_text.rotate(1, 0, 1, 0);
}
void resizeGL(int w, int h) Q_DECL_OVERRIDE
{
m_window_normalised_matrix.setToIdentity();
m_window_normalised_matrix.translate(w / 2.0, h / 2.0);
m_window_normalised_matrix.scale(w / 2.0, -h / 2.0);
m_window_painter_matrix.setToIdentity();
m_window_painter_matrix.translate(w / 2.0, h / 2.0);
m_text_layout.setTextWidth(std::max(w * 0.2, 80.0));
m_projection.setToIdentity();
m_projection.perspective(45.f, qreal(w) / qreal(h), 0.1f, 100.f);
}
void paintGL() Q_DECL_OVERRIDE;
void resizeGL(int w, int h) Q_DECL_OVERRIDE;
void keyPressEvent(QKeyEvent *e) Q_DECL_OVERRIDE;
private:
void setAnimating(bool enabled);
QMatrix4x4 m_window_normalised_matrix;
QMatrix4x4 m_window_painter_matrix;
QMatrix4x4 m_projection;
@ -140,9 +86,97 @@ private:
FragmentToy m_fragment_toy;
QStaticText m_text_layout;
bool m_animate;
};
int main (int argc, char **argv)
// Use NoPartialUpdate. This means that all the rendering goes directly to
// the window surface, no additional framebuffer object stands in the
// middle. This is fine since we will clear the entire framebuffer on each
// paint. Under the hood this means that the behavior is equivalent to the
// manual makeCurrent - perform OpenGL calls - swapBuffers loop that is
// typical in pure QWindow-based applications.
OpenGLWindow::OpenGLWindow()
: QOpenGLWindow(QOpenGLWindow::NoPartialUpdate)
, m_fragment_toy("background.frag")
, m_text_layout("The triangle and this text is rendered with QPainter")
, m_animate(true)
{
m_view.lookAt(QVector3D(3,1,1),
QVector3D(0,0,0),
QVector3D(0,1,0));
QLinearGradient gradient(QPointF(-1,-1), QPointF(1,1));
gradient.setColorAt(0, Qt::red);
gradient.setColorAt(1, Qt::green);
m_brush = QBrush(gradient);
setAnimating(m_animate);
}
void OpenGLWindow::paintGL()
{
m_fragment_toy.draw(size());
QPainter p(this);
p.setWorldTransform(m_window_normalised_matrix.toTransform());
QMatrix4x4 mvp = m_projection * m_view * m_model_triangle;
p.setTransform(mvp.toTransform(), true);
p.fillPath(painterPathForTriangle(), m_brush);
QTransform text_transform = (m_window_painter_matrix * m_view * m_model_text).toTransform();
p.setTransform(text_transform, false);
p.setPen(QPen(Qt::white));
m_text_layout.prepare(text_transform);
qreal x = - (m_text_layout.size().width() / 2);
qreal y = 0;
p.drawStaticText(x, y, m_text_layout);
m_model_triangle.rotate(-1, 0, 1, 0);
m_model_text.rotate(1, 0, 1, 0);
}
void OpenGLWindow::resizeGL(int w, int h)
{
m_window_normalised_matrix.setToIdentity();
m_window_normalised_matrix.translate(w / 2.0, h / 2.0);
m_window_normalised_matrix.scale(w / 2.0, -h / 2.0);
m_window_painter_matrix.setToIdentity();
m_window_painter_matrix.translate(w / 2.0, h / 2.0);
m_text_layout.setTextWidth(std::max(w * 0.2, 80.0));
m_projection.setToIdentity();
m_projection.perspective(45.f, qreal(w) / qreal(h), 0.1f, 100.f);
}
void OpenGLWindow::keyPressEvent(QKeyEvent *e)
{
if (e->key() == Qt::Key_P) { // pause
m_animate = !m_animate;
setAnimating(m_animate);
}
}
void OpenGLWindow::setAnimating(bool enabled)
{
if (enabled) {
// Animate continuously, throttled by the blocking swapBuffers() call the
// QOpenGLWindow internally executes after each paint. Once that is done
// (frameSwapped signal is emitted), we schedule a new update. This
// obviously assumes that the swap interval (see
// QSurfaceFormat::setSwapInterval()) is non-zero.
connect(this, SIGNAL(frameSwapped()), this, SLOT(update()));
update();
} else {
disconnect(this, SIGNAL(frameSwapped()), this, SLOT(update()));
}
}
int main(int argc, char **argv)
{
QGuiApplication app(argc, argv);