I don't think this was intentional...
[qt-netbsd.git] / doc / src / examples / overpainting.qdoc
blob52bb1601b04cd052283b9cc6966f4278515aa1a0
1 /****************************************************************************
2 **
3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
7 ** This file is part of the documentation of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
14 ** this package.
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file.  Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
38 ** $QT_END_LICENSE$
40 ****************************************************************************/
42 /*!
43     \example opengl/overpainting
44     \title Overpainting Example
46     The Overpainting example shows how QPainter can be used
47     to overpaint a scene rendered using OpenGL in a QGLWidget.
49     \image overpainting-example.png
51     QGLWidget provides a widget with integrated OpenGL graphics support
52     that enables 3D graphics to be displayed using normal OpenGL calls,
53     yet also behaves like any other standard Qt widget with support for
54     signals and slots, properties, and Qt's action system.
56     Usually, QGLWidget is subclassed to display a pure 3D scene; the
57     developer reimplements \l{QGLWidget::initializeGL()}{initializeGL()}
58     to initialize any required resources, \l{QGLWidget::resizeGL()}{resizeGL()}
59     to set up the projection and viewport, and
60     \l{QGLWidget::paintGL()}{paintGL()} to perform the OpenGL calls needed
61     to render the scene. However, it is possible to subclass QGLWidget
62     differently to allow 2D graphics, drawn using QPainter, to be
63     painted over a scene rendered using OpenGL.
65     In this example, we demonstrate how this is done by reusing the code
66     from the \l{Hello GL Example}{Hello GL} example to provide a 3D scene,
67     and painting over it with some translucent 2D graphics. Instead of
68     examining each class in detail, we only cover the parts of the
69     \c GLWidget class that enable overpainting, and provide more detailed
70     discussion in the final section of this document.
72     \section1 GLWidget Class Definition
74     The \c GLWidget class is a subclass of QGLWidget, based on the one used
75     in the \l{Hello GL Example}{Hello GL} example. Rather than describe the
76     class as a whole, we show the first few lines of the class and only
77     discuss the changes we have made to the rest of it:
79     \snippet examples/opengl/overpainting/glwidget.h 0
80     \dots
81     \snippet examples/opengl/overpainting/glwidget.h 1
82     \dots
83     \snippet examples/opengl/overpainting/glwidget.h 4
85     As usual, the widget uses \l{QGLWidget::initializeGL()}{initializeGL()}
86     to set up objects for our scene and perform other OpenGL initialization tasks.
87     The \l{QGLWidget::resizeGL()}{resizeGL()} function is used to ensure that
88     the 3D graphics in the scene are transformed correctly to the 2D viewport
89     displayed in the widget.
91     Instead of implementing \l{QGLWidget::paintGL()}{paintGL()} to handle updates
92     to the widget, we implement a normal QWidget::paintEvent(). This
93     allows us to mix OpenGL calls and QPainter operations in a controlled way.
95     In this example, we also implement QWidget::showEvent() to help with the
96     initialization of the 2D graphics used.
98     The new private member functions and variables relate exclusively to the
99     2D graphics and animation. The \c animate() slot is called periodically by the
100     \c animationTimer to update the widget; the \c createBubbles() function
101     initializes the \c bubbles list with instances of a helper class used to
102     draw the animation; the \c drawInstructions() function is responsible for
103     a semi-transparent messages that is also overpainted onto the OpenGL scene.
105     \section1 GLWidget Class Implementation
107     Again, we only show the parts of the \c GLWidget implementation that are
108     relevant to this example. In the constructor, we initialize a QTimer to
109     control the animation:
111     \snippet examples/opengl/overpainting/glwidget.cpp 0
113     We turn off the widget's \l{QWidget::autoFillBackground}{autoFillBackground} property to
114     instruct OpenGL not to paint a background for the widget when
115     \l{QPainter::begin()}{QPainter::begin()} is called.
117     As in the \l{Hello GL Example}{Hello GL} example, the destructor is responsible
118     for freeing any OpenGL-related resources:
120     \snippet examples/opengl/overpainting/glwidget.cpp 1
122     The \c initializeGL() function is fairly minimal, only setting up the display
123     list used in the scene.
125     \snippet examples/opengl/overpainting/glwidget.cpp 2
127     To cooperate fully with QPainter, we defer matrix stack operations and attribute
128     initialization until the widget needs to be updated.
130     In this example, we implement \l{QWidget::paintEvent()}{paintEvent()} rather
131     than \l{QGLWidget::paintGL()}{paintGL()} to render
132     our scene. When drawing on a QGLWidget, the paint engine used by QPainter
133     performs certain operations that change the states of the OpenGL
134     implementation's matrix and property stacks. Therefore, it is necessary to
135     make all the OpenGL calls to display the 3D graphics before we construct
136     a QPainter to draw the 2D overlay.
138     We render a 3D scene by setting up model and projection transformations
139     and other attributes. We use an OpenGL stack operation to preserve the
140     original matrix state, allowing us to recover it later:
142     \snippet examples/opengl/overpainting/glwidget.cpp 4
144     We define a color to use for the widget's background, and set up various
145     attributes that define how the scene will be rendered.
147     \snippet examples/opengl/overpainting/glwidget.cpp 6
149     We call the \c setupViewport() private function to set up the
150     projection used for the scene. This is unnecessary in OpenGL
151     examples that implement the \l{QGLWidget::paintGL()}{paintGL()}
152     function because the matrix stacks are usually unmodified between
153     calls to \l{QGLWidget::resizeGL()}{resizeGL()} and
154     \l{QGLWidget::paintGL()}{paintGL()}.
156     Since the widget's background is not drawn by the system or by Qt, we use
157     an OpenGL call to paint it before positioning the object defined earlier
158     in the scene:
160     \snippet examples/opengl/overpainting/glwidget.cpp 7
162     Once the list containing the object has been executed, the GL
163     states we changed and the matrix stack needs to be restored to its
164     original state at the start of this function before we can begin
165     overpainting:
167     \snippet examples/opengl/overpainting/glwidget.cpp 8
169     With the 3D graphics done, we construct a QPainter for use on the widget
170     and simply overpaint the widget with 2D graphics; in this case, using a
171     helper class to draw a number of translucent bubbles onto the widget,
172     and calling \c drawInstructions() to overlay some instructions:
174     \snippet examples/opengl/overpainting/glwidget.cpp 10
176     When QPainter::end() is called, suitable OpenGL-specific calls are made to
177     write the scene, and its additional contents, onto the widget.
179     The implementation of the \l{QGLWidget::resizeGL()}{resizeGL()} function
180     sets up the dimensions of the viewport and defines a projection
181     transformation:
183     \snippet examples/opengl/overpainting/glwidget.cpp 11
185     Ideally, we want to arrange the 2D graphics to suit the widget's dimensions.
186     To achieve this, we implement the \l{QWidget::showEvent()}{showEvent()} handler,
187     creating new graphic elements (bubbles) if necessary at appropriate positions
188     in the widget.
190     \snippet examples/opengl/overpainting/glwidget.cpp 12
192     This function only has an effect if less than 20 bubbles have already been
193     created.
195     The \c animate() slot is called every time the widget's \c animationTimer emits
196     the \l{QTimer::timeout()}{timeout()} signal. This keeps the bubbles moving
197     around.
199     \snippet examples/opengl/overpainting/glwidget.cpp 13
201     We simply iterate over the bubbles in the \c bubbles list, updating the
202     widget before and after each of them is moved.
204     The \c setupViewport() function is called from \c paintEvent()
205     and \c resizeGL().
207     \snippet examples/opengl/overpainting/glwidget.cpp 14
209     The \c drawInstructions() function is used to prepare some basic
210     instructions that will be painted with the other 2D graphics over
211     the 3D scene.
213     \snippet examples/opengl/overpainting/glwidget.cpp 15
215     \section1 Summary
217     When overpainting 2D content onto 3D content, we need to use a QPainter
218     \e and make OpenGL calls to achieve the desired effect. Since QPainter
219     itself uses OpenGL calls when used on a QGLWidget subclass, we need to
220     preserve the state of various OpenGL stacks when we perform our own
221     calls, using the following approach:
223     \list
224     \o Reimplement QGLWidget::initializeGL(), but only perform minimal
225        initialization. QPainter will perform its own initialization
226        routines, modifying the matrix and property stacks, so it is better
227        to defer certain initialization tasks until just before you render
228        the 3D scene.
229     \o Reimplement QGLWidget::resizeGL() as in the pure 3D case.
230     \o Reimplement QWidget::paintEvent() to draw both 2D and 3D graphics.
231     \endlist
233     The \l{QWidget::paintEvent()}{paintEvent()} implementation performs the
234     following tasks:
236     \list
237     \o Push the current OpenGL modelview matrix onto a stack.
238     \o Perform initialization tasks usually done in the
239        \l{QGLWidget::initializeGL()}{initializeGL()} function.
240     \o Perform code that would normally be located in the widget's
241        \l{QGLWidget::resizeGL()}{resizeGL()} function to set the correct
242        perspective transformation and set up the viewport.
243     \o Render the scene using OpenGL calls.
244     \o Pop the OpenGL modelview matrix off the stack.
245     \o Construct a QPainter object.
246     \o Initialize it for use on the widget with the QPainter::begin() function.
247     \o Draw primitives using QPainter's member functions.
248     \o Call QPainter::end() to finish painting.
249     \endlist