1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the documentation of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:FDL$
9 ** GNU Free Documentation License
10 ** Alternatively, this file may be used under the terms of the GNU Free
11 ** Documentation License version 1.3 as published by the Free Software
12 ** Foundation and appearing in the file included in the packaging of
16 ** Alternatively, this file may be used in accordance with the terms
17 ** and conditions contained in a signed written agreement between you
26 ****************************************************************************/
29 \example gui/openglwindow
30 \title OpenGL Window Example
32 This example shows how to create a minimal QWindow based application
33 for the purpose of using OpenGL.
35 \image openglwindow-example.png Screenshot of the OpenGLWindow example
37 \section1 OpenGLWindow super class
39 Our OpenGLWindow class acts as an API which is then subclassed to do the
40 actual rendering. It has functions to make a request for render() to be
41 called, either immediately with renderNow() or as soon as the event loop
42 has finished processing the current batch of events with renderLater().
43 The OpenGLWindow subclass can either reimplement render() for OpenGL based
44 rendering, or render(QPainter *) for rendering with a QPainter. Use
45 OpenGLWindow::setAnimating(true) for render() to be called at the vertical
46 refresh rate, assuming vertical sync is enabled in the underlying OpenGL
49 In the class that does the OpenGL rendering you will typically want to
50 inherit from QOpenGLFunctions, as our OpenGLWindow does, in order to get
51 platform independent access to OpenGL ES 2.0 functions. By inheriting from
52 QOpenGLFunctions the OpenGL functions it contains will get precedence, and
53 you will not have to worry about resolving those functions if you want your
54 application to work with OpenGL as well as OpenGL ES 2.0.
56 \snippet openglwindow/openglwindow.h 1
58 The window's surface type must be set to QSurface::OpenGLSurface to
59 indicate that the window is to be used for OpenGL rendering and not for
60 rendering raster content with QPainter using a QBackingStore.
62 \snippet openglwindow/openglwindow.cpp 1
64 Any OpenGL initialization needed can be done by overriding the initialize()
65 function, which is called once before the first call to render(), with a
66 valid current QOpenGLContext. As can be seen in the following code snippet,
67 the default render(QPainter *) and initialize() implementations are empty,
68 whereas the default render() implementation initializes a
69 QOpenGLPaintDevice and then calls into render(QPainter *).
71 \snippet openglwindow/openglwindow.cpp 2
73 The renderLater() function simply puts an update request event on
74 the event loop, which leads to renderNow() being called once the event
77 We also call renderNow() when we get an expose event. The exposeEvent() is
78 the notification to the window that its exposure, meaning visibility, on
79 the screen has changed. When the expose event is received you can query
80 QWindow::isExposed() to find out whether or not the window is currently
81 exposed. Do not render to or call QOpenGLContext::swapBuffers() on a window
82 before it has received its first expose event, as before then its final
83 size might be unknown, and in addition what is rendered might not even end
86 \snippet openglwindow/openglwindow.cpp 3
88 In renderNow() we return if we are not currently exposed, in which case
89 rendering is delayed until we actually get an expose event. If we have not
90 yet done so, we create the QOpenGLContext with the same QSurfaceFormat as
91 was set on the OpenGLWindow, and call initialize() for the sake of the sub
92 class, and initializeOpenGLFunctions() in order for the QOpenGLFunctions
93 super class to be associated with the correct QOpenGLContext. In any case
94 we make the context current by calling QOpenGLContext::makeCurrent(), call
95 render() to do the actual rendering, and finally we schedule for the
96 rendered contents to be made visible by calling
97 QOpenGLContext::swapBuffers() with the OpenGLWindow as parameter.
99 Once the rendering of a frame using an OpenGL context is initiated by
100 calling QOpenGLContext::makeCurrent(), giving the surface on which to
101 render as a parameter, OpenGL commands can be issued. The commands can be
102 issued either directly by including <qopengl.h>, which also includes the
103 system's OpenGL headers, or as by using QOpenGLFunctions, which can
104 either be inherited from for convenience, or accessed using
105 QOpenGLContext::functions(). QOpenGLFunctions gives access to all the
106 OpenGL ES 2.0 level OpenGL calls that are not already standard in both
107 OpenGL ES 2.0 and desktop OpenGL. For more information about the OpenGL and
108 OpenGL ES APIs, refer to the official \l{OpenGL Registry} and
109 \l{Khronos OpenGL ES API Registry}.
111 If animation has been enabled with OpenGLWindow::setAnimating(true), we
112 call renderLater() to put another update request on the event loop.
114 \snippet openglwindow/openglwindow.cpp 4
116 Enabling animation also triggers an update request as shown in the
117 following code snippet.
119 \snippet openglwindow/openglwindow.cpp 5
121 \section1 Example OpenGL rendering sub class
123 Here we sub class OpenGLWindow to show how to do OpenGL to render a
124 rotating triangle. By indirectly sub classing QOpenGLFunctions we gain
125 access to all OpenGL ES 2.0 level functionality.
127 \snippet openglwindow/main.cpp 1
129 In our main function we initialize QGuiApplication and instantiate our
130 TriangleOpenGLWindow. We give it a QSurfaceFormat specifying that we want
131 four samples of multisample antialiasing, as well as a default geometry.
132 Since we want to have animation we call the above mentioned setAnimating()
133 function with an argument of true.
135 \snippet openglwindow/main.cpp 2
137 The following code snippet shows the OpenGL shader program used in this
138 example. The vertex and fragment shaders are relatively simple, doing
139 vertex transformation and interpolated vertex coloring.
141 \snippet openglwindow/main.cpp 3
143 Here is the code that loads the shaders and initializes the shader program
144 By using QOpenGLShaderProgram instead of raw OpenGL we get the convenience
145 that strips out the highp, mediump, and lowp qualifiers on desktop OpenGL,
146 where they are not part of the standard. We store the attribute and uniform
147 locations in member variables to avoid having to do the location lookup
150 \snippet openglwindow/main.cpp 4
152 Finally, here is our render() function, where we use OpenGL to set up the
153 viewport, clear the background, and render a rotating triangle.
155 \snippet openglwindow/main.cpp 5