summaryrefslogtreecommitdiffstats
path: root/examples/opengl
diff options
context:
space:
mode:
Diffstat (limited to 'examples/opengl')
-rw-r--r--examples/opengl/opengl.pro6
-rw-r--r--examples/opengl/qopenglwindow/background.frag24
-rw-r--r--examples/opengl/qopenglwindow/background_renderer.cpp201
-rw-r--r--examples/opengl/qopenglwindow/background_renderer.h78
-rw-r--r--examples/opengl/qopenglwindow/main.cpp159
-rw-r--r--examples/opengl/qopenglwindow/qopenglwindow.pro15
-rw-r--r--examples/opengl/qopenglwindow/shaders.qrc5
7 files changed, 486 insertions, 2 deletions
diff --git a/examples/opengl/opengl.pro b/examples/opengl/opengl.pro
index fb5f02c07c..8d09d21d72 100644
--- a/examples/opengl/opengl.pro
+++ b/examples/opengl/opengl.pro
@@ -6,7 +6,8 @@ contains(QT_CONFIG, dynamicgl) {
SUBDIRS = hellowindow \
contextinfo \
qopenglwidget \
- threadedqopenglwidget
+ threadedqopenglwidget \
+ qopenglwindow
} else: !contains(QT_CONFIG, opengles2) {
SUBDIRS = 2dpainting \
grabber \
@@ -23,6 +24,7 @@ contains(QT_CONFIG, dynamicgl) {
cube \
textures \
qopenglwidget \
- threadedqopenglwidget
+ threadedqopenglwidget \
+ qopenglwindow
EXAMPLE_FILES = shared
diff --git a/examples/opengl/qopenglwindow/background.frag b/examples/opengl/qopenglwindow/background.frag
new file mode 100644
index 0000000000..067c3505dc
--- /dev/null
+++ b/examples/opengl/qopenglwindow/background.frag
@@ -0,0 +1,24 @@
+uniform highp int currentTime;
+uniform highp vec2 windowSize;
+
+float noise(vec2 co)
+{
+ return 0.5 * fract(sin(dot(co.xy, vec2(12.9898,78.233))) * 43758.5453);
+}
+
+float curvSpeed()
+{
+ return mod(float(currentTime), 1000000.0) / 500.0;
+}
+
+float curv()
+{
+ return 1.0 - abs((gl_FragCoord.y / (windowSize.y / 10.0) - 5.0) - sin((gl_FragCoord.x / (windowSize.x/20.0)) - curvSpeed()));
+}
+
+void main()
+{
+ float coordNoise = noise(gl_FragCoord.xy);
+ float proximity = smoothstep(0.5, 1.0, (curv() + 1.0) * (coordNoise ));
+ gl_FragColor = vec4(coordNoise, coordNoise, coordNoise, 1.0) * proximity;
+}
diff --git a/examples/opengl/qopenglwindow/background_renderer.cpp b/examples/opengl/qopenglwindow/background_renderer.cpp
new file mode 100644
index 0000000000..6cec6666b6
--- /dev/null
+++ b/examples/opengl/qopenglwindow/background_renderer.cpp
@@ -0,0 +1,201 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
+** of its contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "background_renderer.h"
+
+#include <QtCore/qmath.h>
+#include <QtCore/QFileInfo>
+#include <QtCore/QTime>
+
+#include <QtGui/QOpenGLShaderProgram>
+#include <QtGui/QOpenGLContext>
+#include <QtGui/QOpenGLFunctions>
+
+#include <math.h>
+
+static const char vertex_shader[] =
+ "attribute highp vec3 vertexCoord;"
+ "void main() {"
+ " gl_Position = vec4(vertexCoord,1.0);"
+ "}";
+
+static const char fragment_shader[] =
+ "void main() {"
+ " gl_FragColor = vec4(0.0,1.0,0.0,1.0);"
+ "}";
+
+static const float vertices[] = { -1, -1, 0,
+ -1, 1, 0,
+ 1, -1, 0,
+ 1, 1, 0 };
+
+FragmentToy::FragmentToy(const QString &fragmentSource, QObject *parent)
+ : QObject(parent)
+ , m_recompile_shaders(true)
+{
+ if (QFile::exists(fragmentSource)) {
+ QFileInfo info(fragmentSource);
+ m_fragment_file_last_modified = info.lastModified();
+ m_fragment_file = fragmentSource;
+#ifndef QT_NO_FILESYSTEMWATCHER
+ m_watcher.addPath(info.canonicalFilePath());
+ QObject::connect(&m_watcher, &QFileSystemWatcher::fileChanged, this, &FragmentToy::fileChanged);
+#endif
+ }
+}
+
+void FragmentToy::draw(const QSize &windowSize)
+{
+ if (!m_program)
+ initializeOpenGLFunctions();
+
+ glDisable(GL_STENCIL_TEST);
+ glDisable(GL_DEPTH_TEST);
+
+ glClearColor(0,0,0,0);
+ glClear(GL_COLOR_BUFFER_BIT);
+ if (!m_vao.isCreated())
+ m_vao.create();
+
+ m_vao.bind();
+
+ if (!m_vertex_buffer.isCreated()) {
+ m_vertex_buffer.create();
+ m_vertex_buffer.bind();
+ m_vertex_buffer.allocate(vertices, sizeof(vertices));
+ m_vertex_buffer.release();
+ }
+
+ if (!m_program) {
+ m_program.reset(new QOpenGLShaderProgram);
+ m_program->create();
+ m_vertex_shader.reset(new QOpenGLShader(QOpenGLShader::Vertex));
+ if (!m_vertex_shader->compileSourceCode(vertex_shader)) {
+ qWarning() << "Failed to compile the vertex shader:" << m_vertex_shader->log();
+ }
+ if (!m_program->addShader(m_vertex_shader.data())) {
+ qWarning() << "Failed to add vertex shader to program:" << m_program->log();
+ }
+ }
+
+ if (!m_fragment_shader) {
+ QByteArray data;
+ if (m_fragment_file.size()) {
+ QFile file(m_fragment_file);
+ if (file.open(QIODevice::ReadOnly)) {
+ data = file.readAll();
+ } else {
+ qWarning() << "Failed to load input file, falling back to default";
+ data = QByteArray::fromRawData(fragment_shader, sizeof(fragment_shader));
+ }
+ } else {
+ QFile qrcFile(":/background.frag");
+ if (qrcFile.open(QIODevice::ReadOnly))
+ data = qrcFile.readAll();
+ else
+ data = QByteArray::fromRawData(fragment_shader, sizeof(fragment_shader));
+ }
+ if (data.size()) {
+ m_fragment_shader.reset(new QOpenGLShader(QOpenGLShader::Fragment));
+ if (!m_fragment_shader->compileSourceCode(data)) {
+ qWarning() << "Failed to compile fragment shader:" << m_fragment_shader->log();
+ m_fragment_shader.reset(Q_NULLPTR);
+ }
+ } else {
+ qWarning() << "Unknown error, no fragment shader";
+ }
+
+ if (m_fragment_shader) {
+ if (!m_program->addShader(m_fragment_shader.data())) {
+ qWarning() << "Failed to add fragment shader to program:" << m_program->log();
+ }
+ }
+ }
+
+ if (m_recompile_shaders) {
+ m_recompile_shaders = false;
+
+ if (m_program->link()) {
+ m_vertex_coord_pos = m_program->attributeLocation("vertexCoord");
+ } else {
+ qWarning() << "Failed to link shader program" << m_program->log();
+ }
+
+ }
+
+ m_program->bind();
+
+ m_vertex_buffer.bind();
+ m_program->setAttributeBuffer("vertexCoord", GL_FLOAT, 0, 3, 0);
+ m_program->enableAttributeArray("vertexCoord");
+ m_vertex_buffer.release();
+
+ float radiens = (QTime::currentTime().msecsSinceStartOfDay() / 60) / (2 * M_PI);
+ m_program->setUniformValue("currentTime", (uint) QDateTime::currentDateTime().toMSecsSinceEpoch());
+ m_program->setUniformValue("radiens", radiens);
+ m_program->setUniformValue("windowSize", windowSize);
+
+ QOpenGLContext::currentContext()->functions()->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+
+ m_program->release();
+ m_vao.release();
+}
+
+void FragmentToy::fileChanged(const QString &path)
+{
+ Q_UNUSED(path);
+ if (QFile::exists(m_fragment_file)) {
+ QFileInfo fragment_source(m_fragment_file);
+ if (fragment_source.lastModified() > m_fragment_file_last_modified) {
+ m_fragment_file_last_modified = fragment_source.lastModified();
+ m_recompile_shaders = true;
+ if (m_program) {
+ m_program->removeShader(m_fragment_shader.data());
+ m_fragment_shader.reset(Q_NULLPTR);
+ }
+ }
+ } else {
+ m_recompile_shaders = true;
+ if (m_program) {
+ m_program->removeShader(m_fragment_shader.data());
+ m_fragment_shader.reset(Q_NULLPTR);
+ }
+ }
+}
diff --git a/examples/opengl/qopenglwindow/background_renderer.h b/examples/opengl/qopenglwindow/background_renderer.h
new file mode 100644
index 0000000000..4f968325d5
--- /dev/null
+++ b/examples/opengl/qopenglwindow/background_renderer.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
+** of its contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#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>
+
+class FragmentToy : public QObject, protected QOpenGLFunctions
+{
+ Q_OBJECT
+public:
+ FragmentToy(const QString &fragmentSource, QObject *parent = 0);
+
+ void draw(const QSize &windowSize);
+
+private:
+ void fileChanged(const QString &path);
+ bool m_recompile_shaders;
+#ifndef QT_NO_FILESYSTEMWATCHER
+ QFileSystemWatcher m_watcher;
+#endif
+ QString m_fragment_file;
+ QDateTime m_fragment_file_last_modified;
+
+ QScopedPointer<QOpenGLShaderProgram> m_program;
+ QScopedPointer<QOpenGLShader> m_vertex_shader;
+ QScopedPointer<QOpenGLShader> m_fragment_shader;
+ QOpenGLVertexArrayObject m_vao;
+ QOpenGLBuffer m_vertex_buffer;
+ GLuint m_vertex_coord_pos;
+};
+
+#endif //FRAGMENT_TOY_H
diff --git a/examples/opengl/qopenglwindow/main.cpp b/examples/opengl/qopenglwindow/main.cpp
new file mode 100644
index 0000000000..19ac9e8a15
--- /dev/null
+++ b/examples/opengl/qopenglwindow/main.cpp
@@ -0,0 +1,159 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
+** of its contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui/QOpenGLWindow>
+#include <QtGui/QScreen>
+#include <QtGui/QPainter>
+#include <QtGui/QGuiApplication>
+#include <QtGui/QMatrix4x4>
+#include <QtGui/QStaticText>
+
+#include "background_renderer.h"
+
+static QPainterPath painterPathForTriangle()
+{
+ static const QPointF bottomLeft(-1.0, -1.0);
+ static const QPointF top(0.0, 1.0);
+ static const QPointF bottomRight(1.0, -1.0);
+
+ QPainterPath path(bottomLeft);
+ path.lineTo(top);
+ path.lineTo(bottomRight);
+ path.closeSubpath();
+ return path;
+}
+
+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);
+ }
+
+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);
+
+ }
+
+private:
+ QMatrix4x4 m_window_normalised_matrix;
+ QMatrix4x4 m_window_painter_matrix;
+ QMatrix4x4 m_projection;
+ QMatrix4x4 m_view;
+ QMatrix4x4 m_model_triangle;
+ QMatrix4x4 m_model_text;
+ QBrush m_brush;
+
+ FragmentToy m_fragment_toy;
+ QStaticText m_text_layout;
+};
+
+int main (int argc, char **argv)
+{
+ QGuiApplication app(argc, argv);
+
+ OpenGLWindow window;
+ QSurfaceFormat fmt;
+ fmt.setDepthBufferSize(24);
+ fmt.setStencilBufferSize(8);
+ window.setFormat(fmt);
+ window.show();
+
+ return app.exec();
+}
+
+#include "main.moc"
diff --git a/examples/opengl/qopenglwindow/qopenglwindow.pro b/examples/opengl/qopenglwindow/qopenglwindow.pro
new file mode 100644
index 0000000000..dad4b58158
--- /dev/null
+++ b/examples/opengl/qopenglwindow/qopenglwindow.pro
@@ -0,0 +1,15 @@
+TEMPLATE = app
+TARGET = qopenglwindow
+INCLUDEPATH += .
+
+RESOURCES += shaders.qrc
+
+SOURCES += \
+ main.cpp \
+ background_renderer.cpp
+
+HEADERS += \
+ background_renderer.h
+
+target.path = $$[QT_INSTALL_EXAMPLES]/opengl/qopenglwindow
+INSTALLS += target
diff --git a/examples/opengl/qopenglwindow/shaders.qrc b/examples/opengl/qopenglwindow/shaders.qrc
new file mode 100644
index 0000000000..64eefe2c70
--- /dev/null
+++ b/examples/opengl/qopenglwindow/shaders.qrc
@@ -0,0 +1,5 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file>background.frag</file>
+</qresource>
+</RCC>