summaryrefslogtreecommitdiffstats
path: root/examples/opengl/hellogles3
diff options
context:
space:
mode:
authorLaszlo Agocs <laszlo.agocs@theqtcompany.com>2015-05-18 11:10:47 +0200
committerLaszlo Agocs <laszlo.agocs@theqtcompany.com>2015-07-23 07:59:07 +0000
commit4535c7911d47b94ecb2067793f2f6d906794e1fe (patch)
tree6f0d578e24bf0f195d6ccb1c90331c8946e33481 /examples/opengl/hellogles3
parent0cd34a0c39bf443f1ea6f6868ac6fbc0fc2c9e6d (diff)
Expose GLES 3.0 and 3.1 functions
Using the approach we already do for some GLES 3.0 functions we can provide a cross-platform, cross-GL-GLES wrapper for ES 3.0 and 3.1 functions too. Applications only have to take extra care about the version requests (context version and version directives in shader code), the rest of their code can stay the same across desktop/mobile/embedded, even when ES 3 functions are used. The new functions are placed to a new subclass which is placed between QOpenGLFunctions and the internal QOpenGLExtensions. This is necessary because, unlike with QOpenGLFunctions, there is no guarantee that these functions are always available in all configurations. When running on desktop OpenGL, we resolve as usual. If the OpenGL version contains the function in question, either in core or as an extension, it will all just work. This is handy because it does not rely on 4.x extensions like GL_ARB_ESx_compatibility, and so ES 3.0 functions will be functional on OpenGL 3.x systems too by just setting a 3.x version number in the QSurfaceFormat. We will no longer qFatal on broken systems where the driver returns a 3.0 or 3.1 context without the corresponding functions present. Instead, we show a warning and gracefully fall back to resolving as usual, via eglGetProcAddress or similar. For functions that are available in ES2 as an extension this may just work fine. Added also an example that runs identically both with OpenGL and OpenGL ES 3 and utilizes some ES 3.0 features like instanced drawing. [ChangeLog] Added QOpenGLExtraFunctions providing OpenGL ES 3.0 and 3.1 function wrappers in a cross-platform manner. Task-number: QTBUG-46161 Change-Id: I9f929eb61946c35c415b178c4d6ab2c1c958684e Reviewed-by: Paul Olav Tvete <paul.tvete@theqtcompany.com>
Diffstat (limited to 'examples/opengl/hellogles3')
-rw-r--r--examples/opengl/hellogles3/glwidget.cpp236
-rw-r--r--examples/opengl/hellogles3/glwidget.h87
-rw-r--r--examples/opengl/hellogles3/hellogles3.pro15
-rw-r--r--examples/opengl/hellogles3/hellogles3.qrc5
-rw-r--r--examples/opengl/hellogles3/main.cpp78
-rw-r--r--examples/opengl/hellogles3/mainwindow.cpp58
-rw-r--r--examples/opengl/hellogles3/mainwindow.h54
-rw-r--r--examples/opengl/hellogles3/qtlogo.pngbin0 -> 5402 bytes
8 files changed, 533 insertions, 0 deletions
diff --git a/examples/opengl/hellogles3/glwidget.cpp b/examples/opengl/hellogles3/glwidget.cpp
new file mode 100644
index 0000000000..74056d63c2
--- /dev/null
+++ b/examples/opengl/hellogles3/glwidget.cpp
@@ -0,0 +1,236 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** 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 The Qt Company Ltd 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 "glwidget.h"
+#include <QImage>
+#include <QOpenGLTexture>
+#include <QOpenGLShaderProgram>
+#include <QOpenGLBuffer>
+#include <QOpenGLContext>
+#include <QOpenGLVertexArrayObject>
+#include <QOpenGLExtraFunctions>
+#include <QPropertyAnimation>
+#include <QPauseAnimation>
+#include <QSequentialAnimationGroup>
+
+GLWidget::GLWidget()
+ : m_texture(0),
+ m_program(0),
+ m_vbo(0),
+ m_vao(0),
+ m_target(0, 0, -1),
+ m_uniformsDirty(true)
+{
+ m_world.setToIdentity();
+ m_world.translate(0, 0, -1);
+ m_world.rotate(180, 1, 0, 0);
+
+ QSequentialAnimationGroup *animGroup = new QSequentialAnimationGroup(this);
+ animGroup->setLoopCount(-1);
+ QPropertyAnimation *zAnim0 = new QPropertyAnimation(this, QByteArrayLiteral("z"));
+ zAnim0->setStartValue(0.0f);
+ zAnim0->setEndValue(1.0f);
+ zAnim0->setDuration(2000);
+ animGroup->addAnimation(zAnim0);
+ QPropertyAnimation *zAnim1 = new QPropertyAnimation(this, QByteArrayLiteral("z"));
+ zAnim1->setStartValue(0.0f);
+ zAnim1->setEndValue(70.0f);
+ zAnim1->setDuration(4000);
+ zAnim1->setEasingCurve(QEasingCurve::OutElastic);
+ animGroup->addAnimation(zAnim1);
+ QPropertyAnimation *zAnim2 = new QPropertyAnimation(this, QByteArrayLiteral("z"));
+ zAnim2->setStartValue(70.0f);
+ zAnim2->setEndValue(0.0f);
+ zAnim2->setDuration(2000);
+ animGroup->addAnimation(zAnim2);
+ animGroup->start();
+}
+
+GLWidget::~GLWidget()
+{
+ makeCurrent();
+ delete m_texture;
+ delete m_program;
+ delete m_vbo;
+ delete m_vao;
+}
+
+void GLWidget::setZ(float v)
+{
+ m_eye.setZ(v);
+ m_uniformsDirty = true;
+ update();
+}
+
+static const char *vertexShaderSource =
+ "layout(location = 0) in vec4 vertex;\n"
+ "layout(location = 1) in vec3 normal;\n"
+ "out vec3 vert;\n"
+ "out vec3 vertNormal;\n"
+ "out vec3 color;\n"
+ "uniform mat4 projMatrix;\n"
+ "uniform mat4 camMatrix;\n"
+ "uniform mat4 worldMatrix;\n"
+ "uniform sampler2D sampler;\n"
+ "void main() {\n"
+ " ivec2 pos = ivec2(gl_InstanceID % 32, gl_InstanceID / 32);\n"
+ " vec2 t = vec2(-16 + pos.x, -18 + pos.y);\n"
+ " mat4 wm = mat4(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, t.x, t.y, 0, 1) * worldMatrix;\n"
+ " color = texelFetch(sampler, pos, 0).rgb * vec3(0.4, 1.0, 0.0);\n"
+ " vert = vec3(wm * vertex);\n"
+ " vertNormal = mat3(transpose(inverse(wm))) * normal;\n"
+ " gl_Position = projMatrix * camMatrix * wm * vertex;\n"
+ "}\n";
+
+static const char *fragmentShaderSource =
+ "in highp vec3 vert;\n"
+ "in highp vec3 vertNormal;\n"
+ "in highp vec3 color;\n"
+ "out highp vec4 fragColor;\n"
+ "uniform highp vec3 lightPos;\n"
+ "void main() {\n"
+ " highp vec3 L = normalize(lightPos - vert);\n"
+ " highp float NL = max(dot(normalize(vertNormal), L), 0.0);\n"
+ " highp vec3 col = clamp(color * 0.2 + color * 0.8 * NL, 0.0, 1.0);\n"
+ " fragColor = vec4(col, 1.0);\n"
+ "}\n";
+
+QByteArray versionedShaderCode(const char *src)
+{
+ QByteArray versionedSrc;
+
+ if (QOpenGLContext::currentContext()->isOpenGLES())
+ versionedSrc.append(QByteArrayLiteral("#version 300 es\n"));
+ else
+ versionedSrc.append(QByteArrayLiteral("#version 330\n"));
+
+ versionedSrc.append(src);
+ return versionedSrc;
+}
+
+void GLWidget::initializeGL()
+{
+ QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions();
+
+ if (m_texture) {
+ delete m_texture;
+ m_texture = 0;
+ }
+ QImage img(":/qtlogo.png");
+ Q_ASSERT(!img.isNull());
+ m_texture = new QOpenGLTexture(img.scaled(32, 36).mirrored());
+
+ if (m_program) {
+ delete m_program;
+ m_program = 0;
+ }
+ m_program = new QOpenGLShaderProgram;
+ // Prepend the correct version directive to the sources. The rest is the
+ // same, thanks to the common GLSL syntax.
+ m_program->addShaderFromSourceCode(QOpenGLShader::Vertex, versionedShaderCode(vertexShaderSource));
+ m_program->addShaderFromSourceCode(QOpenGLShader::Fragment, versionedShaderCode(fragmentShaderSource));
+ m_program->link();
+
+ m_projMatrixLoc = m_program->uniformLocation("projMatrix");
+ m_camMatrixLoc = m_program->uniformLocation("camMatrix");
+ m_worldMatrixLoc = m_program->uniformLocation("worldMatrix");
+ m_lightPosLoc = m_program->uniformLocation("lightPos");
+
+ // Create a VAO. Not strictly required for ES 3, but it is for plain OpenGL.
+ if (m_vao) {
+ delete m_vao;
+ m_vao = 0;
+ }
+ m_vao = new QOpenGLVertexArrayObject;
+ if (m_vao->create())
+ m_vao->bind();
+
+ if (m_vbo) {
+ delete m_vbo;
+ m_vbo = 0;
+ }
+ m_program->bind();
+ m_vbo = new QOpenGLBuffer;
+ m_vbo->create();
+ m_vbo->bind();
+ m_vbo->allocate(m_logo.constData(), m_logo.count() * sizeof(GLfloat));
+ f->glEnableVertexAttribArray(0);
+ f->glEnableVertexAttribArray(1);
+ f->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), 0);
+ f->glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), reinterpret_cast<void *>(3 * sizeof(GLfloat)));
+ m_vbo->release();
+
+ f->glEnable(GL_DEPTH_TEST);
+ f->glEnable(GL_CULL_FACE);
+}
+
+void GLWidget::resizeGL(int w, int h)
+{
+ m_proj.setToIdentity();
+ m_proj.perspective(45.0f, GLfloat(w) / h, 0.01f, 100.0f);
+ m_uniformsDirty = true;
+}
+
+void GLWidget::paintGL()
+{
+ // Now use QOpenGLExtraFunctions instead of QOpenGLFunctions as we want to
+ // do more than what GL(ES) 2.0 offers.
+ QOpenGLExtraFunctions *f = QOpenGLContext::currentContext()->extraFunctions();
+
+ f->glClearColor(0, 0, 0, 1);
+ f->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ m_program->bind();
+ m_texture->bind();
+
+ if (m_uniformsDirty) {
+ m_uniformsDirty = false;
+ QMatrix4x4 camera;
+ camera.lookAt(m_eye, m_eye + m_target, QVector3D(0, 1, 0));
+ m_program->setUniformValue(m_projMatrixLoc, m_proj);
+ m_program->setUniformValue(m_camMatrixLoc, camera);
+ m_program->setUniformValue(m_worldMatrixLoc, m_world);
+ m_program->setUniformValue(m_lightPosLoc, QVector3D(0, 0, 70));
+ }
+
+ // Now call a function introduced in OpenGL 3.1 / OpenGL ES 3.0. We
+ // requested a 3.3 or ES 3.0 context, so we know this will work.
+ f->glDrawArraysInstanced(GL_TRIANGLES, 0, m_logo.vertexCount(), 32 * 36);
+}
diff --git a/examples/opengl/hellogles3/glwidget.h b/examples/opengl/hellogles3/glwidget.h
new file mode 100644
index 0000000000..85830c32f5
--- /dev/null
+++ b/examples/opengl/hellogles3/glwidget.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** 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 The Qt Company Ltd 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 GLWIDGET_H
+#define GLWIDGET_H
+
+#include <QOpenGLWidget>
+#include <QMatrix4x4>
+#include <QVector3D>
+#include "../hellogl2/logo.h"
+
+class QOpenGLTexture;
+class QOpenGLShaderProgram;
+class QOpenGLBuffer;
+class QOpenGLVertexArrayObject;
+
+class GLWidget : public QOpenGLWidget
+{
+ Q_OBJECT
+ Q_PROPERTY(float z READ z WRITE setZ)
+
+public:
+ GLWidget();
+ ~GLWidget();
+
+ void initializeGL();
+ void resizeGL(int w, int h);
+ void paintGL();
+
+ float z() const { return m_eye.z(); }
+ void setZ(float v);
+
+private:
+ QOpenGLTexture *m_texture;
+ QOpenGLShaderProgram *m_program;
+ QOpenGLBuffer *m_vbo;
+ QOpenGLVertexArrayObject *m_vao;
+ Logo m_logo;
+ int m_projMatrixLoc;
+ int m_camMatrixLoc;
+ int m_worldMatrixLoc;
+ int m_lightPosLoc;
+ QMatrix4x4 m_proj;
+ QMatrix4x4 m_world;
+ QVector3D m_eye;
+ QVector3D m_target;
+ bool m_uniformsDirty;
+};
+
+#endif
diff --git a/examples/opengl/hellogles3/hellogles3.pro b/examples/opengl/hellogles3/hellogles3.pro
new file mode 100644
index 0000000000..299d439fd2
--- /dev/null
+++ b/examples/opengl/hellogles3/hellogles3.pro
@@ -0,0 +1,15 @@
+HEADERS = $$PWD/glwidget.h \
+ $$PWD/mainwindow.h \
+ $$PWD/../hellogl2/logo.h
+
+SOURCES = $$PWD/glwidget.cpp \
+ $$PWD/main.cpp \
+ $$PWD/mainwindow.cpp \
+ $$PWD/../hellogl2/logo.cpp
+
+QT += widgets
+
+RESOURCES += hellogles3.qrc
+
+target.path = $$[QT_INSTALL_EXAMPLES]/opengl/hellogles3
+INSTALLS += target
diff --git a/examples/opengl/hellogles3/hellogles3.qrc b/examples/opengl/hellogles3/hellogles3.qrc
new file mode 100644
index 0000000000..f3a0978084
--- /dev/null
+++ b/examples/opengl/hellogles3/hellogles3.qrc
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource>
+ <file>qtlogo.png</file>
+ </qresource>
+</RCC>
diff --git a/examples/opengl/hellogles3/main.cpp b/examples/opengl/hellogles3/main.cpp
new file mode 100644
index 0000000000..3125623395
--- /dev/null
+++ b/examples/opengl/hellogles3/main.cpp
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** 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 The Qt Company Ltd 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 <QApplication>
+#include <QSurfaceFormat>
+#include <QOpenGLContext>
+
+#include "mainwindow.h"
+
+// This example demonstrates easy, cross-platform usage of OpenGL ES 3.0 functions via
+// QOpenGLExtraFunctions in an application that works identically on desktop platforms
+// with OpenGL 3.3 and mobile/embedded devices with OpenGL ES 3.0.
+
+// The code is always the same, with the exception of two places: (1) the OpenGL context
+// creation has to have a sufficiently high version number for the features that are in
+// use, and (2) the shader code's version directive is different.
+
+int main(int argc, char *argv[])
+{
+ QSurfaceFormat fmt;
+ fmt.setDepthBufferSize(24);
+
+ // Request OpenGL 3.3 compatibility or OpenGL ES 3.0.
+ if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGL) {
+ qDebug("Requesting 3.3 compatibility context");
+ fmt.setVersion(3, 3);
+ fmt.setProfile(QSurfaceFormat::CompatibilityProfile);
+ } else {
+ qDebug("Requesting 3.0 context");
+ fmt.setVersion(3, 0);
+ }
+
+ QSurfaceFormat::setDefaultFormat(fmt);
+
+ QApplication app(argc, argv);
+
+ MainWindow mainWindow;
+ mainWindow.showMaximized();
+
+ return app.exec();
+}
diff --git a/examples/opengl/hellogles3/mainwindow.cpp b/examples/opengl/hellogles3/mainwindow.cpp
new file mode 100644
index 0000000000..1ea72eb475
--- /dev/null
+++ b/examples/opengl/hellogles3/mainwindow.cpp
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** 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 The Qt Company Ltd 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 "mainwindow.h"
+#include "glwidget.h"
+#include <QApplication>
+#include <QMenuBar>
+#include <QMenu>
+
+MainWindow::MainWindow()
+{
+ QMenuBar *menuBar = new QMenuBar;
+ QMenu *menuWindow = menuBar->addMenu(tr("&File"));
+ QAction *exitAction = new QAction(menuWindow);
+ exitAction->setText(tr("E&xit"));
+ menuWindow->addAction(exitAction);
+ connect(exitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
+ setMenuBar(menuBar);
+
+ setCentralWidget(new GLWidget);
+}
diff --git a/examples/opengl/hellogles3/mainwindow.h b/examples/opengl/hellogles3/mainwindow.h
new file mode 100644
index 0000000000..33c2c55669
--- /dev/null
+++ b/examples/opengl/hellogles3/mainwindow.h
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** 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 The Qt Company Ltd 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 MAINWINDOW_H
+#define MAINWINDOW_H
+
+#include <QMainWindow>
+
+class MainWindow : public QMainWindow
+{
+ Q_OBJECT
+
+public:
+ MainWindow();
+};
+
+#endif
diff --git a/examples/opengl/hellogles3/qtlogo.png b/examples/opengl/hellogles3/qtlogo.png
new file mode 100644
index 0000000000..868fcea860
--- /dev/null
+++ b/examples/opengl/hellogles3/qtlogo.png
Binary files differ