From f3b45ffa6159bc8b7ecfb0578bbb5cb826de1338 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Tue, 5 Jun 2012 13:21:55 +0200 Subject: [PATCH] Added OpenGL example and documentation. Change-Id: I2d9d4e52caf0a39fef9648d8a9e83a0c1328f650 Reviewed-by: Paul Olav Tvete --- doc/src/examples/openglwindow.qdoc | 156 ++++++++++++++++++ doc/src/images/openglwindow-example.png | Bin 0 -> 19920 bytes examples/examples.pro | 1 + examples/gui/gui.pro | 2 +- examples/gui/openglwindow/main.cpp | 179 +++++++++++++++++++++ examples/gui/openglwindow/openglwindow.cpp | 169 +++++++++++++++++++ examples/gui/openglwindow/openglwindow.h | 83 ++++++++++ examples/gui/openglwindow/openglwindow.pri | 3 + examples/gui/openglwindow/openglwindow.pro | 7 + src/gui/doc/src/qtgui.qdoc | 15 +- 10 files changed, 611 insertions(+), 4 deletions(-) create mode 100644 doc/src/examples/openglwindow.qdoc create mode 100644 doc/src/images/openglwindow-example.png create mode 100644 examples/gui/openglwindow/main.cpp create mode 100644 examples/gui/openglwindow/openglwindow.cpp create mode 100644 examples/gui/openglwindow/openglwindow.h create mode 100644 examples/gui/openglwindow/openglwindow.pri create mode 100644 examples/gui/openglwindow/openglwindow.pro diff --git a/doc/src/examples/openglwindow.qdoc b/doc/src/examples/openglwindow.qdoc new file mode 100644 index 00000000000..9d93af5154e --- /dev/null +++ b/doc/src/examples/openglwindow.qdoc @@ -0,0 +1,156 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** GNU Free Documentation License +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms +** and conditions contained in a signed written agreement between you +** and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \example gui/openglwindow + \title OpenGL Window Example + + This example shows how to create a minimal QWindow based application + for the purpose of using OpenGL. + + \image openglwindow-example.png Screenshot of the OpenGLWindow example + + \section1 OpenGLWindow super class + + Our OpenGLWindow class acts as an API which is then subclassed to do the + actual rendering. It has functions to make a request for render() to be + called, either immediately with renderNow() or as soon as the event loop + has finished processing the current batch of events with renderLater(). + The OpenGLWindow subclass can either reimplement render() for OpenGL based + rendering, or render(QPainter *) for rendering with a QPainter. Use + OpenGLWindow::setAnimating(true) for render() to be called at the vertical + refresh rate, assuming vertical sync is enabled in the underlying OpenGL + drivers. + + In the class that does the OpenGL rendering you will typically want to + inherit from QOpenGLFunctions, as our OpenGLWindow does, in order to get + platform independent access to OpenGL ES 2.0 functions. By inheriting from + QOpenGLFunctions the OpenGL functions it contains will get precedence, and + you will not have to worry about resolving those functions if you want your + application to work with OpenGL as well as OpenGL ES 2.0. + + \snippet gui/openglwindow/openglwindow.h 1 + + The window's surface type must be set to QSurface::OpenGLSurface to + indicate that the window is to be used for OpenGL rendering and not for + rendering raster content with QPainter using a QBackingStore. + + \snippet gui/openglwindow/openglwindow.cpp 1 + + Any OpenGL initialization needed can be done by overriding the initialize() + function, which is called once before the first call to render(), with a + valid current QOpenGLContext. As can be seen in the following code snippet, + the default render(QPainter *) and initialize() implementations are empty, + whereas the default render() implementation initializes a + QOpenGLPaintDevice and then calls into render(QPainter *). + + \snippet gui/openglwindow/openglwindow.cpp 2 + + The renderLater() function simply puts an update request event on + the event loop, which leads to renderNow() being called once the event + gets processed. + + We also call renderNow() when we get an expose event. The exposeEvent() is + the notification to the window that its exposure, meaning visibility, on + the screen has changed. When the expose event is received you can query + QWindow::isExposed() to find out whether or not the window is currently + exposed. Do not render to or call QOpenGLContext::swapBuffers() on a window + before it has received its first expose event, as before then its final + size might be unknown, and in addition what is rendered might not even end + up on the screen. + + \snippet gui/openglwindow/openglwindow.cpp 3 + + In renderNow() we return if we are not currently exposed, in which case + rendering is delayed until we actually get an expose event. If we have not + yet done so, we create the QOpenGLContext with the same QSurfaceFormat as + was set on the OpenGLWindow, and call initialize() for the sake of the sub + class, and initializeOpenGLFunctions() in order for the QOpenGLFunctions + super class to be associated with the correct QOpenGLContext. In any case + we make the context current by calling QOpenGLContext::makeCurrent(), call + render() to do the actual rendering, and finally we schedule for the + rendered contents to be made visible by calling + QOpenGLContext::swapBuffers() with the OpenGLWindow as parameter. + + Once the rendering of a frame using an OpenGL context is initiated by + calling QOpenGLContext::makeCurrent(), giving the surface on which to + render as a parameter, OpenGL commands can be issued. The commands can be + issued either directly by including , which also includes the + system's OpenGL headers, or as by using QOpenGLFunctions, which can + either be inherited from for convenience, or accessed using + QOpenGLContext::functions(). QOpenGLFunctions gives access to all the + OpenGL ES 2.0 level OpenGL calls that are not already standard in both + OpenGL ES 2.0 and desktop OpenGL. For more information about the OpenGL and + OpenGL ES APIs, refer to the official \l{OpenGL Registry} and + \l{Khronos OpenGL ES API Registry}. + + If animation has been enabled with OpenGLWindow::setAnimating(true), we + call renderLater() to put another update request on the event loop. + + \snippet gui/openglwindow/openglwindow.cpp 4 + + Enabling animation also triggers an update request as shown in the + following code snippet. + + \snippet gui/openglwindow/openglwindow.cpp 5 + + \section1 Example OpenGL rendering sub class + + Here we sub class OpenGLWindow to show how to do OpenGL to render a + rotating triangle. By indirectly sub classing QOpenGLFunctions we gain + access to all OpenGL ES 2.0 level functionality. + + \snippet gui/openglwindow/main.cpp 1 + + In our main function we initialize QGuiApplication and instantiate our + TriangleOpenGLWindow. We give it a QSurfaceFormat specifying that we want + four samples of multisample antialiasing, as well as a default geometry. + Since we want to have animation we call the above mentioned setAnimating() + function with an argument of true. + + \snippet gui/openglwindow/main.cpp 2 + + The following code snippet shows the OpenGL shader program used in this + example. The vertex and fragment shaders are relatively simple, doing + vertex transformation and interpolated vertex coloring. + + \snippet gui/openglwindow/main.cpp 3 + + Here is the code that loads the shaders and initializes the shader program + By using QOpenGLShaderProgram instead of raw OpenGL we get the convenience + that strips out the highp, mediump, and lowp qualifiers on desktop OpenGL, + where they are not part of the standard. We store the attribute and uniform + locations in member variables to avoid having to do the location lookup + each frame. + + \snippet gui/openglwindow/main.cpp 4 + + Finally, here is our render() function, where we use OpenGL to set up the + viewport, clear the background, and render a rotating triangle. + + \snippet gui/openglwindow/main.cpp 5 +*/ diff --git a/doc/src/images/openglwindow-example.png b/doc/src/images/openglwindow-example.png new file mode 100644 index 0000000000000000000000000000000000000000..63ba4ed2f4c4790957748850e640991955e332bd GIT binary patch literal 19920 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 +#include +#include +#include + +#include + +//! [1] +class TriangleWindow : public OpenGLWindow +{ +public: + TriangleWindow(); + + void initialize(); + void render(); + +private: + GLuint loadShader(GLenum type, const char *source); + + GLuint m_posAttr; + GLuint m_colAttr; + GLuint m_matrixUniform; + + QOpenGLShaderProgram *m_program; + int m_frame; +}; + +TriangleWindow::TriangleWindow() + : m_program(0) + , m_frame(0) +{ +} +//! [1] + +//! [2] +int main(int argc, char **argv) +{ + QGuiApplication app(argc, argv); + + QSurfaceFormat format; + format.setSamples(4); + + TriangleWindow window; + window.setFormat(format); + window.resize(640, 480); + window.show(); + + window.setAnimating(true); + + return app.exec(); +} +//! [2] + + +//! [3] +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"; +//! [3] + +//! [4] +GLuint TriangleWindow::loadShader(GLenum type, const char *source) +{ + GLuint shader = glCreateShader(type); + glShaderSource(shader, 1, &source, 0); + glCompileShader(shader); + return shader; +} + +void TriangleWindow::initialize() +{ + 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"); +} +//! [4] + +//! [5] +void TriangleWindow::render() +{ + glViewport(0, 0, width(), height()); + + glClear(GL_COLOR_BUFFER_BIT); + + m_program->bind(); + + QMatrix4x4 matrix; + matrix.perspective(60, 4.0/3.0, 0.1, 100.0); + 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(); + + ++m_frame; +} +//! [5] diff --git a/examples/gui/openglwindow/openglwindow.cpp b/examples/gui/openglwindow/openglwindow.cpp new file mode 100644 index 00000000000..6a052c32e22 --- /dev/null +++ b/examples/gui/openglwindow/openglwindow.cpp @@ -0,0 +1,169 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the documentation 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 Nokia Corporation 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 "openglwindow.h" + +#include + +#include +#include +#include + +//! [1] +OpenGLWindow::OpenGLWindow(QWindow *parent) + : QWindow(parent) + , m_update_pending(false) + , m_animating(false) + , m_context(0) + , m_device(0) +{ + setSurfaceType(QWindow::OpenGLSurface); +} +//! [1] + +OpenGLWindow::~OpenGLWindow() +{ + delete m_device; +} +//! [2] +void OpenGLWindow::render(QPainter *painter) +{ + Q_UNUSED(painter); +} + +void OpenGLWindow::initialize() +{ +} + +void OpenGLWindow::render() +{ + if (!m_device) + m_device = new QOpenGLPaintDevice; + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + + m_device->setSize(size()); + + QPainter painter(m_device); + render(&painter); +} +//! [2] + +//! [3] +void OpenGLWindow::renderLater() +{ + if (!m_update_pending) { + m_update_pending = true; + QCoreApplication::postEvent(this, new QEvent(QEvent::UpdateRequest)); + } +} + +bool OpenGLWindow::event(QEvent *event) +{ + switch (event->type()) { + case QEvent::UpdateRequest: + renderNow(); + return true; + default: + return QWindow::event(event); + } +} + +void OpenGLWindow::exposeEvent(QExposeEvent *event) +{ + Q_UNUSED(event); + + if (isExposed()) + renderNow(); +} + +void OpenGLWindow::resizeEvent(QResizeEvent *event) +{ + Q_UNUSED(event); + + if (isExposed()) + renderNow(); +} +//! [3] + +//! [4] +void OpenGLWindow::renderNow() +{ + if (!isExposed()) + return; + + m_update_pending = false; + + bool needsInitialize = false; + + if (!m_context) { + m_context = new QOpenGLContext(this); + m_context->setFormat(requestedFormat()); + m_context->create(); + + needsInitialize = true; + } + + m_context->makeCurrent(this); + + if (needsInitialize) { + initializeOpenGLFunctions(); + initialize(); + } + + render(); + + m_context->swapBuffers(this); + + if (m_animating) + renderLater(); +} +//! [4] + +//! [5] +void OpenGLWindow::setAnimating(bool animating) +{ + m_animating = animating; + + if (animating) + renderLater(); +} +//! [5] + diff --git a/examples/gui/openglwindow/openglwindow.h b/examples/gui/openglwindow/openglwindow.h new file mode 100644 index 00000000000..aae797b6804 --- /dev/null +++ b/examples/gui/openglwindow/openglwindow.h @@ -0,0 +1,83 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the documentation 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 Nokia Corporation 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 +#include + +QT_BEGIN_NAMESPACE +class QPainter; +class QOpenGLContext; +class QOpenGLPaintDevice; +QT_END_NAMESPACE + +//! [1] +class OpenGLWindow : public QWindow, protected QOpenGLFunctions +{ + Q_OBJECT +public: + explicit OpenGLWindow(QWindow *parent = 0); + ~OpenGLWindow(); + + virtual void render(QPainter *painter); + virtual void render(); + + virtual void initialize(); + + void setAnimating(bool animating); + +public slots: + void renderLater(); + void renderNow(); + +protected: + bool event(QEvent *event); + + void exposeEvent(QExposeEvent *event); + void resizeEvent(QResizeEvent *event); + +private: + bool m_update_pending; + bool m_animating; + + QOpenGLContext *m_context; + QOpenGLPaintDevice *m_device; +}; +//! [1] + diff --git a/examples/gui/openglwindow/openglwindow.pri b/examples/gui/openglwindow/openglwindow.pri new file mode 100644 index 00000000000..45b0b0cd299 --- /dev/null +++ b/examples/gui/openglwindow/openglwindow.pri @@ -0,0 +1,3 @@ +INCLUDEPATH += $$PWD +SOURCES += $$PWD/openglwindow.cpp +HEADERS += $$PWD/openglwindow.h diff --git a/examples/gui/openglwindow/openglwindow.pro b/examples/gui/openglwindow/openglwindow.pro new file mode 100644 index 00000000000..c6b3f3c48a7 --- /dev/null +++ b/examples/gui/openglwindow/openglwindow.pro @@ -0,0 +1,7 @@ +include(openglwindow.pri) + +OTHER_FILES += \ + openglwindow.pri + +SOURCES += \ + main.cpp diff --git a/src/gui/doc/src/qtgui.qdoc b/src/gui/doc/src/qtgui.qdoc index 0421b172cfc..41cdfc4b3db 100644 --- a/src/gui/doc/src/qtgui.qdoc +++ b/src/gui/doc/src/qtgui.qdoc @@ -114,10 +114,19 @@ QWindow supports rendering using desktop OpenGL, OpenGL ES 1.1 and OpenGL ES 2.0, depending on what the platform supports. OpenGL rendering is enabled by setting the QWindow's surface type to - QSurface::OpenGLSurface, then creating a QOpenGLContext to manage - the native OpenGL context. + QSurface::OpenGLSurface, choosing the format attributes with + QSurfaceFormat, and then creating a QOpenGLContext to manage + the native OpenGL context. In addition, Qt has QOpenGLPaintDevice, + which enables the use of OpenGL accelerated QPainter rendering, as well as + convenience classes that simplify the writing of OpenGL code and hides the + complexities of extension handling and the differences between OpenGL ES 2 + and desktop OpenGL. The convenience classes include QOpenGLFunctions that + lets an application use all the OpenGL ES 2 functions on desktop OpenGL + without having to manually resolve the OpenGL function pointers and some + classes that wrap native OpenGL resources in a simpler Qt API: + QOpenGLBuffer, QOpenGLFramebufferObject, and QOpenGLShaderProgram. - For more information, see \l {OpenGL Enablers}. + For more information, see the \l {OpenGL Window Example}. The Qt GUI module also contains a few math classes to aid with the most common mathmatical operations related to 3D graphics. These