summaryrefslogtreecommitdiffstats
path: root/examples/opengl/pbuffers
diff options
context:
space:
mode:
Diffstat (limited to 'examples/opengl/pbuffers')
-rw-r--r--examples/opengl/pbuffers/cube.cpp348
-rw-r--r--examples/opengl/pbuffers/cube.h149
-rw-r--r--examples/opengl/pbuffers/cubelogo.pngbin0 -> 5920 bytes
-rw-r--r--examples/opengl/pbuffers/glwidget.cpp246
-rw-r--r--examples/opengl/pbuffers/glwidget.h89
-rw-r--r--examples/opengl/pbuffers/main.cpp63
-rw-r--r--examples/opengl/pbuffers/pbuffers.pro19
-rw-r--r--examples/opengl/pbuffers/pbuffers.qrc5
8 files changed, 919 insertions, 0 deletions
diff --git a/examples/opengl/pbuffers/cube.cpp b/examples/opengl/pbuffers/cube.cpp
new file mode 100644
index 0000000000..631595a2d7
--- /dev/null
+++ b/examples/opengl/pbuffers/cube.cpp
@@ -0,0 +1,348 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 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 "cube.h"
+#include "glwidget.h"
+
+#include <QtGui/QImage>
+#include <QtCore/QPropertyAnimation>
+
+static const qreal FACE_SIZE = 0.4;
+
+static const qreal speeds[] = { 3.8f, 4.4f, 5.6f };
+static const qreal amplitudes[] = { 2.0f, 2.5f, 3.0f };
+
+static inline void qSetColor(float colorVec[], QColor c)
+{
+ colorVec[0] = c.redF();
+ colorVec[1] = c.greenF();
+ colorVec[2] = c.blueF();
+ colorVec[3] = c.alphaF();
+}
+
+int Geometry::append(const QVector3D &a, const QVector3D &n, const QVector2D &t)
+{
+ int v = vertices.count();
+ vertices.append(a);
+ normals.append(n);
+ texCoords.append(t);
+ faces.append(v);
+ colors.append(QVector4D(0.6f, 0.6f, 0.6f, 1.0f));
+ return v;
+}
+
+void Geometry::addQuad(const QVector3D &a, const QVector3D &b,
+ const QVector3D &c, const QVector3D &d,
+ const QVector<QVector2D> &tex)
+{
+ QVector3D norm = QVector3D::normal(a, b, c);
+ // append first triangle
+ int aref = append(a, norm, tex[0]);
+ append(b, norm, tex[1]);
+ int cref = append(c, norm, tex[2]);
+ // append second triangle
+ faces.append(aref);
+ faces.append(cref);
+ append(d, norm, tex[3]);
+}
+
+void Geometry::loadArrays() const
+{
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_NORMAL_ARRAY);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ glEnableClientState(GL_COLOR_ARRAY);
+ glVertexPointer(3, GL_FLOAT, 0, vertices.constData());
+ glNormalPointer(GL_FLOAT, 0, normals.constData());
+ glTexCoordPointer(2, GL_FLOAT, 0, texCoords.constData());
+ glColorPointer(4, GL_FLOAT, 0, colors.constData());
+}
+
+void Geometry::setColors(int start, GLfloat colorArray[4][4])
+{
+ int off = faces[start];
+ for (int i = 0; i < 4; ++i)
+ colors[i + off] = QVector4D(colorArray[i][0],
+ colorArray[i][1],
+ colorArray[i][2],
+ colorArray[i][3]);
+}
+
+Tile::Tile(const QVector3D &loc)
+ : location(loc)
+ , start(0)
+ , count(0)
+ , useFlatColor(false)
+ , geom(0)
+{
+ qSetColor(faceColor, QColor(Qt::darkGray));
+}
+
+void Tile::setColors(GLfloat colorArray[4][4])
+{
+ useFlatColor = true;
+ geom->setColors(start, colorArray);
+}
+
+static inline void qMultMatrix(const QMatrix4x4 &mat)
+{
+ if (sizeof(qreal) == sizeof(GLfloat))
+ glMultMatrixf((GLfloat*)mat.constData());
+#ifndef QT_OPENGL_ES
+ else if (sizeof(qreal) == sizeof(GLdouble))
+ glMultMatrixd((GLdouble*)mat.constData());
+#endif
+ else
+ {
+ GLfloat fmat[16];
+ qreal const *r = mat.constData();
+ for (int i = 0; i < 16; ++i)
+ fmat[i] = r[i];
+ glMultMatrixf(fmat);
+ }
+}
+
+void Tile::draw() const
+{
+ QMatrix4x4 mat;
+ mat.translate(location);
+ mat.rotate(orientation);
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+ qMultMatrix(mat);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, faceColor);
+ glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_SHORT, geom->indices() + start);
+ glPopMatrix();
+}
+
+TileBuilder::TileBuilder(Geometry *g, qreal depth, qreal size)
+ : verts(4)
+ , tex(4)
+ , start(g->count())
+ , count(0)
+ , geom(g)
+{
+ // front face - make a square with bottom-left at origin
+ verts[br].setX(size);
+ verts[tr].setX(size);
+ verts[tr].setY(size);
+ verts[tl].setY(size);
+
+ // these vert numbers are good for the tex-coords
+ for (int i = 0; i < 4; ++i)
+ tex[i] = verts[i].toVector2D();
+
+ // now move verts half cube width across so cube is centered on origin
+ for (int i = 0; i < 4; ++i)
+ verts[i] -= QVector3D(size / 2.0f, size / 2.0f, -depth);
+
+ // add the front face
+ g->addQuad(verts[bl], verts[br], verts[tr], verts[tl], tex);
+
+ count = g->count() - start;
+}
+
+void TileBuilder::initialize(Tile *tile) const
+{
+ tile->start = start;
+ tile->count = count;
+ tile->geom = geom;
+ qSetColor(tile->faceColor, color);
+}
+
+Tile *TileBuilder::newTile(const QVector3D &loc) const
+{
+ Tile *tile = new Tile(loc);
+ initialize(tile);
+ return tile;
+}
+
+Cube::Cube(const QVector3D &loc)
+ : Tile(loc)
+ , rot(0.0f)
+ , r(0)
+ , animGroup(0)
+{
+}
+
+Cube::~Cube()
+{
+}
+
+void Cube::setAltitude(qreal a)
+{
+ if (location.y() != a)
+ {
+ location.setY(a);
+ emit changed();
+ }
+}
+
+void Cube::setRange(qreal r)
+{
+ if (location.x() != r)
+ {
+ location.setX(r);
+ emit changed();
+ }
+}
+
+void Cube::setRotation(qreal r)
+{
+ if (r != rot)
+ {
+ orientation = QQuaternion::fromAxisAndAngle(QVector3D(1.0f, 1.0f, 1.0f), r);
+ emit changed();
+ }
+}
+
+void Cube::removeBounce()
+{
+ delete animGroup;
+ animGroup = 0;
+ delete r;
+ r = 0;
+}
+
+void Cube::startAnimation()
+{
+ if (r)
+ {
+ r->start();
+ r->setCurrentTime(startx);
+ }
+ if (animGroup)
+ animGroup->start();
+ if (rtn)
+ rtn->start();
+}
+
+void Cube::setAnimationPaused(bool paused)
+{
+ if (paused)
+ {
+ if (r)
+ r->pause();
+ if (animGroup)
+ animGroup->pause();
+ if (rtn)
+ rtn->pause();
+ }
+ else
+ {
+ if (r)
+ r->resume();
+ if (animGroup)
+ animGroup->resume();
+ if (rtn)
+ rtn->resume();
+ }
+}
+
+CubeBuilder::CubeBuilder(Geometry *g, qreal depth, qreal size)
+ : TileBuilder(g, depth)
+ , ix(0)
+{
+ for (int i = 0; i < 4; ++i)
+ verts[i].setZ(size / 2.0f);
+ // back face - "extrude" verts down
+ QVector<QVector3D> back(verts);
+ for (int i = 0; i < 4; ++i)
+ back[i].setZ(-size / 2.0f);
+
+ // add the back face
+ g->addQuad(back[br], back[bl], back[tl], back[tr], tex);
+
+ // add the sides
+ g->addQuad(back[bl], back[br], verts[br], verts[bl], tex);
+ g->addQuad(back[br], back[tr], verts[tr], verts[br], tex);
+ g->addQuad(back[tr], back[tl], verts[tl], verts[tr], tex);
+ g->addQuad(back[tl], back[bl], verts[bl], verts[tl], tex);
+
+ count = g->count() - start;
+}
+
+Cube *CubeBuilder::newCube(const QVector3D &loc) const
+{
+ Cube *c = new Cube(loc);
+ initialize(c);
+ qreal d = 4000.0f;
+ qreal d3 = d / 3.0f;
+ // Animate movement from left to right
+ c->r = new QPropertyAnimation(c, "range");
+ c->r->setStartValue(-1.3f);
+ c->r->setEndValue(1.3f);
+ c->startx = ix * d3 * 3.0f;
+ c->r->setDuration(d * 4.0f);
+ c->r->setLoopCount(-1);
+ c->r->setEasingCurve(QEasingCurve(QEasingCurve::CosineCurve));
+
+ c->animGroup = new QSequentialAnimationGroup(c);
+
+ // Animate movement from bottom to top
+ QPropertyAnimation *a_up = new QPropertyAnimation(c, "altitude", c->animGroup);
+ a_up->setEndValue(loc.y());
+ a_up->setStartValue(loc.y() + amplitudes[ix]);
+ a_up->setDuration(d / speeds[ix]);
+ a_up->setLoopCount(1);
+ a_up->setEasingCurve(QEasingCurve(QEasingCurve::InQuad));
+
+ // Animate movement from top to bottom
+ QPropertyAnimation *a_down = new QPropertyAnimation(c, "altitude", c->animGroup);
+ a_down->setEndValue(loc.y() + amplitudes[ix]);
+ a_down->setStartValue(loc.y());
+ a_down->setDuration(d / speeds[ix]);
+ a_down->setLoopCount(1);
+ a_down->setEasingCurve(QEasingCurve(QEasingCurve::OutQuad));
+
+ c->animGroup->addAnimation(a_up);
+ c->animGroup->addAnimation(a_down);
+ c->animGroup->setLoopCount(-1);
+
+ // Animate rotation
+ c->rtn = new QPropertyAnimation(c, "rotation");
+ c->rtn->setStartValue(c->rot);
+ c->rtn->setEndValue(359.0f);
+ c->rtn->setDuration(d * 2.0f);
+ c->rtn->setLoopCount(-1);
+ c->rtn->setDuration(d / 2);
+ ix = (ix + 1) % 3;
+ return c;
+}
diff --git a/examples/opengl/pbuffers/cube.h b/examples/opengl/pbuffers/cube.h
new file mode 100644
index 0000000000..5c985a3782
--- /dev/null
+++ b/examples/opengl/pbuffers/cube.h
@@ -0,0 +1,149 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 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$
+**
+****************************************************************************/
+
+#ifndef CUBE_H
+#define CUBE_H
+
+#include <QtOpenGL/qgl.h>
+#include <QtCore/qvector.h>
+#include <QtCore/qsequentialanimationgroup.h>
+#include <QtGui/qmatrix4x4.h>
+#include <QtGui/qvector3d.h>
+#include <QtGui/qvector2d.h>
+
+QT_BEGIN_NAMESPACE
+class QPropertyAnimation;
+QT_END_NAMESPACE
+
+class Geometry
+{
+public:
+ void loadArrays() const;
+ void addQuad(const QVector3D &a, const QVector3D &b,
+ const QVector3D &c, const QVector3D &d,
+ const QVector<QVector2D> &tex);
+ void setColors(int start, GLfloat colors[4][4]);
+ const GLushort *indices() const { return faces.constData(); }
+ int count() const { return faces.count(); }
+private:
+ QVector<GLushort> faces;
+ QVector<QVector3D> vertices;
+ QVector<QVector3D> normals;
+ QVector<QVector2D> texCoords;
+ QVector<QVector4D> colors;
+ int append(const QVector3D &a, const QVector3D &n, const QVector2D &t);
+ void addTri(const QVector3D &a, const QVector3D &b, const QVector3D &c, const QVector3D &n);
+ friend class Tile;
+};
+
+class Tile
+{
+public:
+ void draw() const;
+ void setColors(GLfloat[4][4]);
+protected:
+ Tile(const QVector3D &loc = QVector3D());
+ QVector3D location;
+ QQuaternion orientation;
+private:
+ int start;
+ int count;
+ bool useFlatColor;
+ GLfloat faceColor[4];
+ Geometry *geom;
+ friend class TileBuilder;
+};
+
+class TileBuilder
+{
+public:
+ enum { bl, br, tr, tl };
+ TileBuilder(Geometry *, qreal depth = 0.0f, qreal size = 1.0f);
+ Tile *newTile(const QVector3D &loc = QVector3D()) const;
+ void setColor(QColor c) { color = c; }
+protected:
+ void initialize(Tile *) const;
+ QVector<QVector3D> verts;
+ QVector<QVector2D> tex;
+ int start;
+ int count;
+ Geometry *geom;
+ QColor color;
+};
+
+class Cube : public QObject, public Tile
+{
+ Q_OBJECT
+ Q_PROPERTY(qreal range READ range WRITE setRange)
+ Q_PROPERTY(qreal altitude READ altitude WRITE setAltitude)
+ Q_PROPERTY(qreal rotation READ rotation WRITE setRotation)
+public:
+ Cube(const QVector3D &loc = QVector3D());
+ ~Cube();
+ qreal range() { return location.x(); }
+ void setRange(qreal r);
+ qreal altitude() { return location.y(); }
+ void setAltitude(qreal a);
+ qreal rotation() { return rot; }
+ void setRotation(qreal r);
+ void removeBounce();
+ void startAnimation();
+ void setAnimationPaused(bool paused);
+signals:
+ void changed();
+private:
+ qreal rot;
+ QPropertyAnimation *r;
+ QPropertyAnimation *rtn;
+ QSequentialAnimationGroup *animGroup;
+ qreal startx;
+ friend class CubeBuilder;
+};
+
+class CubeBuilder : public TileBuilder
+{
+public:
+ CubeBuilder(Geometry *, qreal depth = 0.0f, qreal size = 1.0f);
+ Cube *newCube(const QVector3D &loc = QVector3D()) const;
+private:
+ mutable int ix;
+};
+
+#endif // CUBE_H
diff --git a/examples/opengl/pbuffers/cubelogo.png b/examples/opengl/pbuffers/cubelogo.png
new file mode 100644
index 0000000000..3ae0f9ba3f
--- /dev/null
+++ b/examples/opengl/pbuffers/cubelogo.png
Binary files differ
diff --git a/examples/opengl/pbuffers/glwidget.cpp b/examples/opengl/pbuffers/glwidget.cpp
new file mode 100644
index 0000000000..f6f89e5a0e
--- /dev/null
+++ b/examples/opengl/pbuffers/glwidget.cpp
@@ -0,0 +1,246 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 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 "glwidget.h"
+#include <math.h>
+
+#include "cube.h"
+
+#include <QGLPixelBuffer>
+
+#ifndef GL_MULTISAMPLE
+#define GL_MULTISAMPLE 0x809D
+#endif
+
+static GLfloat colorArray[][4] = {
+ {0.243f, 0.423f, 0.125f, 1.0f},
+ {0.176f, 0.31f, 0.09f, 1.0f},
+ {0.4f, 0.69f, 0.212f, 1.0f},
+ {0.317f, 0.553f, 0.161f, 1.0f}
+};
+
+GLWidget::GLWidget(QWidget *parent)
+ : QGLWidget(QGLFormat(QGL::SampleBuffers), parent)
+ , geom(0)
+ , cube(0)
+{
+ // create the pbuffer
+ QGLFormat pbufferFormat = format();
+ pbufferFormat.setSampleBuffers(false);
+ pbuffer = new QGLPixelBuffer(QSize(512, 512), pbufferFormat, this);
+ setWindowTitle(tr("OpenGL pbuffers"));
+ initializeGeometry();
+}
+
+GLWidget::~GLWidget()
+{
+ pbuffer->releaseFromDynamicTexture();
+ glDeleteTextures(1, &dynamicTexture);
+ delete pbuffer;
+
+ qDeleteAll(cubes);
+ qDeleteAll(tiles);
+ delete cube;
+}
+
+void GLWidget::initializeGL()
+{
+ initCommon();
+ glShadeModel(GL_SMOOTH);
+ glEnable(GL_LIGHTING);
+ glEnable(GL_LIGHT0);
+ static GLfloat lightPosition[4] = { 0.5, 5.0, 7.0, 1.0 };
+ glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);
+ initPbuffer();
+ cube->startAnimation();
+ connect(cube, SIGNAL(changed()), this, SLOT(update()));
+ for (int i = 0; i < 3; ++i)
+ {
+ cubes[i]->startAnimation();
+ connect(cubes[i], SIGNAL(changed()), this, SLOT(update()));
+ }
+}
+
+void GLWidget::paintGL()
+{
+ pbuffer->makeCurrent();
+ drawPbuffer();
+ // On direct render platforms, drawing onto the pbuffer context above
+ // automatically updates the dynamic texture. For cases where rendering
+ // directly to a texture is not supported, explicitly copy.
+ if (!hasDynamicTextureUpdate)
+ pbuffer->updateDynamicTexture(dynamicTexture);
+ makeCurrent();
+
+ // Use the pbuffer as a texture to render the scene
+ glBindTexture(GL_TEXTURE_2D, dynamicTexture);
+
+ // set up to render the scene
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ glLoadIdentity();
+ glTranslatef(0.0f, 0.0f, -10.0f);
+
+ // draw the background
+ glPushMatrix();
+ glScalef(aspect, 1.0f, 1.0f);
+ for (int i = 0; i < tiles.count(); ++i)
+ tiles[i]->draw();
+ glPopMatrix();
+
+ // draw the bouncing cubes
+ for (int i = 0; i < cubes.count(); ++i)
+ cubes[i]->draw();
+}
+
+void GLWidget::initializeGeometry()
+{
+ geom = new Geometry();
+ CubeBuilder cBuilder(geom, 0.5);
+ cBuilder.setColor(QColor(255, 255, 255, 212));
+ // build the 3 bouncing, spinning cubes
+ for (int i = 3; i > 0; --i)
+ cubes.append(cBuilder.newCube(QVector3D((float)(i-1), -1.5f, 5 - i)));
+
+ // build the spinning cube which goes in the dynamic texture
+ cube = cBuilder.newCube();
+ cube->removeBounce();
+
+ // build the background tiles
+ TileBuilder tBuilder(geom);
+ tBuilder.setColor(QColor(Qt::white));
+ for (int c = -2; c <= +2; ++c)
+ for (int r = -2; r <= +2; ++r)
+ tiles.append(tBuilder.newTile(QVector3D(c, r, 0)));
+
+ // graded backdrop for the pbuffer scene
+ TileBuilder bBuilder(geom, 0.0f, 2.0f);
+ bBuilder.setColor(QColor(102, 176, 54, 210));
+ backdrop = bBuilder.newTile(QVector3D(0.0f, 0.0f, -1.5f));
+ backdrop->setColors(colorArray);
+}
+
+void GLWidget::initCommon()
+{
+ qglClearColor(QColor(Qt::darkGray));
+
+ glEnable(GL_DEPTH_TEST);
+ glEnable(GL_CULL_FACE);
+ glEnable(GL_MULTISAMPLE);
+
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_BLEND);
+
+ glEnable(GL_TEXTURE_2D);
+
+ geom->loadArrays();
+}
+
+void GLWidget::perspectiveProjection()
+{
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+#ifdef QT_OPENGL_ES
+ glFrustumf(-aspect, +aspect, -1.0, +1.0, 4.0, 15.0);
+#else
+ glFrustum(-aspect, +aspect, -1.0, +1.0, 4.0, 15.0);
+#endif
+ glMatrixMode(GL_MODELVIEW);
+}
+
+void GLWidget::orthographicProjection()
+{
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+#ifdef QT_OPENGL_ES
+ glOrthof(-1.0, +1.0, -1.0, +1.0, -90.0, +90.0);
+#else
+ glOrtho(-1.0, +1.0, -1.0, +1.0, -90.0, +90.0);
+#endif
+ glMatrixMode(GL_MODELVIEW);
+}
+
+void GLWidget::resizeGL(int width, int height)
+{
+ glViewport(0, 0, width, height);
+ aspect = (qreal)width / (qreal)(height ? height : 1);
+ perspectiveProjection();
+}
+
+void GLWidget::drawPbuffer()
+{
+ orthographicProjection();
+
+ glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ glDisable(GL_TEXTURE_2D);
+ backdrop->draw();
+ glEnable(GL_TEXTURE_2D);
+
+ glBindTexture(GL_TEXTURE_2D, cubeTexture);
+ glDisable(GL_CULL_FACE);
+ cube->draw();
+ glEnable(GL_CULL_FACE);
+
+ glFlush();
+}
+
+void GLWidget::initPbuffer()
+{
+ pbuffer->makeCurrent();
+
+ cubeTexture = bindTexture(QImage(":res/cubelogo.png"));
+
+ initCommon();
+
+ // generate a texture that has the same size/format as the pbuffer
+ dynamicTexture = pbuffer->generateDynamicTexture();
+
+ // bind the dynamic texture to the pbuffer - this is a no-op under X11
+ hasDynamicTextureUpdate = pbuffer->bindToDynamicTexture(dynamicTexture);
+ makeCurrent();
+}
+
+void GLWidget::setAnimationPaused(bool enable)
+{
+ cube->setAnimationPaused(enable);
+ for (int i = 0; i < 3; ++i)
+ cubes[i]->setAnimationPaused(enable);
+}
diff --git a/examples/opengl/pbuffers/glwidget.h b/examples/opengl/pbuffers/glwidget.h
new file mode 100644
index 0000000000..7a8244f4f9
--- /dev/null
+++ b/examples/opengl/pbuffers/glwidget.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 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$
+**
+****************************************************************************/
+
+#ifndef GLWIDGET_H
+#define GLWIDGET_H
+
+#include <QGLWidget>
+
+class Geometry;
+class Cube;
+class Tile;
+QT_BEGIN_NAMESPACE
+class QGLPixelBuffer;
+QT_END_NAMESPACE
+
+class GLWidget : public QGLWidget
+{
+public:
+ GLWidget(QWidget *parent = 0);
+ ~GLWidget();
+
+protected:
+ void initializeGL();
+ void paintGL();
+ void resizeGL(int width, int height);
+ void mousePressEvent(QMouseEvent *) { setAnimationPaused(true); }
+ void mouseReleaseEvent(QMouseEvent *) { setAnimationPaused(false); }
+
+private:
+ void initializeGeometry();
+ void initPbuffer();
+ void initCommon();
+ void perspectiveProjection();
+ void orthographicProjection();
+ void drawPbuffer();
+ void setAnimationPaused(bool enable);
+
+ qreal aspect;
+ GLuint dynamicTexture;
+ GLuint cubeTexture;
+ bool hasDynamicTextureUpdate;
+ QGLPixelBuffer *pbuffer;
+ Geometry *geom;
+ Cube *cube;
+ Tile *backdrop;
+ QList<Cube *> cubes;
+ QList<Tile *> tiles;
+
+};
+//! [3]
+
+#endif
diff --git a/examples/opengl/pbuffers/main.cpp b/examples/opengl/pbuffers/main.cpp
new file mode 100644
index 0000000000..b4f1512cfe
--- /dev/null
+++ b/examples/opengl/pbuffers/main.cpp
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 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 <QtGui/QApplication>
+#include <QtGui/QMessageBox>
+#include <QtOpenGL/QGLPixelBuffer>
+
+#include "glwidget.h"
+
+int main(int argc, char **argv)
+{
+ Q_INIT_RESOURCE(pbuffers);
+
+ QApplication a(argc, argv);
+ if (!QGLFormat::hasOpenGL() || !QGLPixelBuffer::hasOpenGLPbuffers()) {
+ QMessageBox::information(0, "OpenGL pbuffers",
+ "This system does not support OpenGL/pbuffers.");
+ return -1;
+ }
+
+ GLWidget widget(0);
+ widget.resize(640, 480);
+ widget.show();
+ return a.exec();
+}
+
diff --git a/examples/opengl/pbuffers/pbuffers.pro b/examples/opengl/pbuffers/pbuffers.pro
new file mode 100644
index 0000000000..48797ab142
--- /dev/null
+++ b/examples/opengl/pbuffers/pbuffers.pro
@@ -0,0 +1,19 @@
+HEADERS += glwidget.h \
+ cube.h
+SOURCES += glwidget.cpp \
+ main.cpp \
+ cube.cpp
+RESOURCES += pbuffers.qrc
+QT += opengl
+
+# install
+target.path = $$[QT_INSTALL_EXAMPLES]/qtbase/opengl/pbuffers
+sources.files = $$SOURCES \
+ $$HEADERS \
+ $$RESOURCES \
+ pbuffers.pro \
+ *.png
+sources.path = $$[QT_INSTALL_EXAMPLES]/qtbase/opengl/pbuffers
+INSTALLS += target \
+ sources
+symbian:include($$QT_SOURCE_TREE/examples/symbianpkgrules.pri)
diff --git a/examples/opengl/pbuffers/pbuffers.qrc b/examples/opengl/pbuffers/pbuffers.qrc
new file mode 100644
index 0000000000..9fc1a56a1a
--- /dev/null
+++ b/examples/opengl/pbuffers/pbuffers.qrc
@@ -0,0 +1,5 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource prefix="/res">
+ <file>cubelogo.png</file>
+</qresource>
+</RCC>