diff options
Diffstat (limited to 'examples/opengl/qopenglwidget')
-rw-r--r-- | examples/opengl/qopenglwidget/bubble.cpp | 139 | ||||
-rw-r--r-- | examples/opengl/qopenglwidget/bubble.h | 76 | ||||
-rw-r--r-- | examples/opengl/qopenglwidget/glwidget.cpp | 489 | ||||
-rw-r--r-- | examples/opengl/qopenglwidget/glwidget.h | 112 | ||||
-rw-r--r-- | examples/opengl/qopenglwidget/main.cpp | 52 | ||||
-rw-r--r-- | examples/opengl/qopenglwidget/mainwindow.cpp | 152 | ||||
-rw-r--r-- | examples/opengl/qopenglwidget/mainwindow.h | 66 | ||||
-rw-r--r-- | examples/opengl/qopenglwidget/qopenglwidget.pro | 15 | ||||
-rw-r--r-- | examples/opengl/qopenglwidget/qt.png | bin | 0 -> 5174 bytes | |||
-rw-r--r-- | examples/opengl/qopenglwidget/texture.qrc | 5 |
10 files changed, 1106 insertions, 0 deletions
diff --git a/examples/opengl/qopenglwidget/bubble.cpp b/examples/opengl/qopenglwidget/bubble.cpp new file mode 100644 index 0000000000..bf04c64966 --- /dev/null +++ b/examples/opengl/qopenglwidget/bubble.cpp @@ -0,0 +1,139 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia Plc 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 <QtWidgets> + +#include "bubble.h" + +Bubble::Bubble(const QPointF &position, qreal radius, const QPointF &velocity) + : position(position), vel(velocity), radius(radius) +{ + innerColor = randomColor(); + outerColor = randomColor(); + cache = 0; + updateBrush(); +} + +//! [0] +void Bubble::updateCache() +{ + if (cache) + delete cache; + cache = new QImage(qRound(radius * 2 + 2), qRound(radius * 2 + 2), QImage::Format_ARGB32); + cache->fill(0x00000000); + QPainter p(cache); + p.setRenderHint(QPainter::HighQualityAntialiasing); + QPen pen(Qt::white); + pen.setWidth(2); + p.setPen(pen); + p.setBrush(brush); + p.drawEllipse(0, 0, int(2*radius), int(2*radius)); +} +//! [0] + +Bubble::~Bubble() +{ + if (cache) + delete cache; +} + +void Bubble::updateBrush() +{ + QRadialGradient gradient(QPointF(radius, radius), radius, + QPointF(radius*0.5, radius*0.5)); + + gradient.setColorAt(0, QColor(255, 255, 255, 255)); + gradient.setColorAt(0.25, innerColor); + gradient.setColorAt(1, outerColor); + brush = QBrush(gradient); + updateCache(); +} + +//! [1] +void Bubble::drawBubble(QPainter *painter) +{ + painter->save(); + painter->translate(position.x() - radius, position.y() - radius); + painter->setOpacity(0.8); + painter->drawImage(0, 0, *cache); + painter->restore(); +} +//! [1] + +QColor Bubble::randomColor() +{ + int red = int(185 + 70.0*qrand()/(RAND_MAX+1.0)); + int green = int(185 + 70.0*qrand()/(RAND_MAX+1.0)); + int blue = int(205 + 50.0*qrand()/(RAND_MAX+1.0)); + int alpha = int(91 + 100.0*qrand()/(RAND_MAX+1.0)); + + return QColor(red, green, blue, alpha); +} + +void Bubble::move(const QRect &bbox) +{ + position += vel; + qreal leftOverflow = position.x() - radius - bbox.left(); + qreal rightOverflow = position.x() + radius - bbox.right(); + qreal topOverflow = position.y() - radius - bbox.top(); + qreal bottomOverflow = position.y() + radius - bbox.bottom(); + + if (leftOverflow < 0.0) { + position.setX(position.x() - 2 * leftOverflow); + vel.setX(-vel.x()); + } else if (rightOverflow > 0.0) { + position.setX(position.x() - 2 * rightOverflow); + vel.setX(-vel.x()); + } + + if (topOverflow < 0.0) { + position.setY(position.y() - 2 * topOverflow); + vel.setY(-vel.y()); + } else if (bottomOverflow > 0.0) { + position.setY(position.y() - 2 * bottomOverflow); + vel.setY(-vel.y()); + } +} + +QRectF Bubble::rect() +{ + return QRectF(position.x() - radius, position.y() - radius, + 2 * radius, 2 * radius); +} diff --git a/examples/opengl/qopenglwidget/bubble.h b/examples/opengl/qopenglwidget/bubble.h new file mode 100644 index 0000000000..ea33466ef7 --- /dev/null +++ b/examples/opengl/qopenglwidget/bubble.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia Plc 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 BUBBLE_H +#define BUBBLE_H + +#include <QBrush> +#include <QColor> +#include <QPointF> +#include <QRect> +#include <QRectF> + +QT_FORWARD_DECLARE_CLASS(QPainter) + +class Bubble +{ +public: + Bubble(const QPointF &position, qreal radius, const QPointF &velocity); + ~Bubble(); + + void drawBubble(QPainter *painter); + void updateBrush(); + void move(const QRect &bbox); + void updateCache(); + QRectF rect(); + +private: + QColor randomColor(); + + QBrush brush; + QPointF position; + QPointF vel; + qreal radius; + QColor innerColor; + QColor outerColor; + QImage *cache; +}; + +#endif diff --git a/examples/opengl/qopenglwidget/glwidget.cpp b/examples/opengl/qopenglwidget/glwidget.cpp new file mode 100644 index 0000000000..e95ca363fc --- /dev/null +++ b/examples/opengl/qopenglwidget/glwidget.cpp @@ -0,0 +1,489 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia Plc 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 <QPainter> +#include <QPaintEngine> +#include <math.h> + +#include "mainwindow.h" +#include "bubble.h" + +const int bubbleNum = 8; + +GLWidget::GLWidget(MainWindow *mw, bool button, const QColor &background) + : m_mainWindow(mw), + m_transparent(false), + m_btn(0), + m_hasButton(button), + m_background(background) +{ + QSurfaceFormat format; + format.setDepthBufferSize(24); + format.setStencilBufferSize(8); + setFormat(format); + + qtLogo = true; + frames = 0; + m_showBubbles = true; + setMinimumSize(300, 250); +} + +GLWidget::~GLWidget() +{ +} + +void GLWidget::setScaling(int scale) { + + if (scale > 30) + m_fScale = 1 + qreal(scale - 30) / 30 * 0.25; + else if (scale < 30) + m_fScale = 1 - (qreal(30 - scale) / 30 * 0.25); + else + m_fScale = 1; +} + +void GLWidget::setLogo() { + qtLogo = true; +} + +void GLWidget::setTexture() { + qtLogo = false; +} + +void GLWidget::showBubbles(bool bubbles) +{ + m_showBubbles = bubbles; +} + +void GLWidget::paintQtLogo() +{ + program1.enableAttributeArray(normalAttr1); + program1.enableAttributeArray(vertexAttr1); + program1.setAttributeArray(vertexAttr1, vertices.constData()); + program1.setAttributeArray(normalAttr1, normals.constData()); + glDrawArrays(GL_TRIANGLES, 0, vertices.size()); + program1.disableAttributeArray(normalAttr1); + program1.disableAttributeArray(vertexAttr1); +} + +void GLWidget::paintTexturedCube() +{ + glBindTexture(GL_TEXTURE_2D, m_uiTexture); + GLfloat afVertices[] = { + -0.5, 0.5, 0.5, 0.5,-0.5,0.5,-0.5,-0.5,0.5, + 0.5, -0.5, 0.5, -0.5,0.5,0.5,0.5,0.5,0.5, + -0.5, -0.5, -0.5, 0.5,-0.5,-0.5,-0.5,0.5,-0.5, + 0.5, 0.5, -0.5, -0.5,0.5,-0.5,0.5,-0.5,-0.5, + + 0.5, -0.5, -0.5, 0.5,-0.5,0.5,0.5,0.5,-0.5, + 0.5, 0.5, 0.5, 0.5,0.5,-0.5,0.5,-0.5,0.5, + -0.5, 0.5, -0.5, -0.5,-0.5,0.5,-0.5,-0.5,-0.5, + -0.5, -0.5, 0.5, -0.5,0.5,-0.5,-0.5,0.5,0.5, + + 0.5, 0.5, -0.5, -0.5, 0.5, 0.5, -0.5, 0.5, -0.5, + -0.5, 0.5, 0.5, 0.5, 0.5, -0.5, 0.5, 0.5, 0.5, + -0.5, -0.5, -0.5, -0.5, -0.5, 0.5, 0.5, -0.5, -0.5, + 0.5, -0.5, 0.5, 0.5, -0.5, -0.5, -0.5, -0.5, 0.5 + }; + program2.setAttributeArray(vertexAttr2, afVertices, 3); + + GLfloat afTexCoord[] = { + 0.0f,0.0f, 1.0f,1.0f, 1.0f,0.0f, + 1.0f,1.0f, 0.0f,0.0f, 0.0f,1.0f, + 1.0f,1.0f, 1.0f,0.0f, 0.0f,1.0f, + 0.0f,0.0f, 0.0f,1.0f, 1.0f,0.0f, + + 1.0f,1.0f, 1.0f,0.0f, 0.0f,1.0f, + 0.0f,0.0f, 0.0f,1.0f, 1.0f,0.0f, + 0.0f,0.0f, 1.0f,1.0f, 1.0f,0.0f, + 1.0f,1.0f, 0.0f,0.0f, 0.0f,1.0f, + + 0.0f,1.0f, 1.0f,0.0f, 1.0f,1.0f, + 1.0f,0.0f, 0.0f,1.0f, 0.0f,0.0f, + 1.0f,0.0f, 1.0f,1.0f, 0.0f,0.0f, + 0.0f,1.0f, 0.0f,0.0f, 1.0f,1.0f + }; + program2.setAttributeArray(texCoordAttr2, afTexCoord, 2); + + GLfloat afNormals[] = { + + 0,0,-1, 0,0,-1, 0,0,-1, + 0,0,-1, 0,0,-1, 0,0,-1, + 0,0,1, 0,0,1, 0,0,1, + 0,0,1, 0,0,1, 0,0,1, + + -1,0,0, -1,0,0, -1,0,0, + -1,0,0, -1,0,0, -1,0,0, + 1,0,0, 1,0,0, 1,0,0, + 1,0,0, 1,0,0, 1,0,0, + + 0,-1,0, 0,-1,0, 0,-1,0, + 0,-1,0, 0,-1,0, 0,-1,0, + 0,1,0, 0,1,0, 0,1,0, + 0,1,0, 0,1,0, 0,1,0 + }; + program2.setAttributeArray(normalAttr2, afNormals, 3); + + program2.setUniformValue(textureUniform2, 0); // use texture unit 0 + + program2.enableAttributeArray(vertexAttr2); + program2.enableAttributeArray(normalAttr2); + program2.enableAttributeArray(texCoordAttr2); + + glDrawArrays(GL_TRIANGLES, 0, 36); + + program2.disableAttributeArray(vertexAttr2); + program2.disableAttributeArray(normalAttr2); + program2.disableAttributeArray(texCoordAttr2); +} + +void GLWidget::initializeGL () +{ + initializeOpenGLFunctions(); + + glGenTextures(1, &m_uiTexture); + QImage img = QImage(":/qt.png").convertToFormat(QImage::Format_RGBA8888); + glBindTexture(GL_TEXTURE_2D, m_uiTexture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, img.width(), img.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, img.constBits()); + + QOpenGLShader *vshader1 = new QOpenGLShader(QOpenGLShader::Vertex, this); + const char *vsrc1 = + "attribute highp vec4 vertex;\n" + "attribute mediump vec3 normal;\n" + "uniform mediump mat4 matrix;\n" + "varying mediump vec4 color;\n" + "void main(void)\n" + "{\n" + " vec3 toLight = normalize(vec3(0.0, 0.3, 1.0));\n" + " float angle = max(dot(normal, toLight), 0.0);\n" + " vec3 col = vec3(0.40, 1.0, 0.0);\n" + " color = vec4(col * 0.2 + col * 0.8 * angle, 1.0);\n" + " color = clamp(color, 0.0, 1.0);\n" + " gl_Position = matrix * vertex;\n" + "}\n"; + vshader1->compileSourceCode(vsrc1); + + QOpenGLShader *fshader1 = new QOpenGLShader(QOpenGLShader::Fragment, this); + const char *fsrc1 = + "varying mediump vec4 color;\n" + "void main(void)\n" + "{\n" + " gl_FragColor = color;\n" + "}\n"; + fshader1->compileSourceCode(fsrc1); + + program1.addShader(vshader1); + program1.addShader(fshader1); + program1.link(); + + vertexAttr1 = program1.attributeLocation("vertex"); + normalAttr1 = program1.attributeLocation("normal"); + matrixUniform1 = program1.uniformLocation("matrix"); + + QOpenGLShader *vshader2 = new QOpenGLShader(QOpenGLShader::Vertex); + const char *vsrc2 = + "attribute highp vec4 vertex;\n" + "attribute highp vec4 texCoord;\n" + "attribute mediump vec3 normal;\n" + "uniform mediump mat4 matrix;\n" + "varying highp vec4 texc;\n" + "varying mediump float angle;\n" + "void main(void)\n" + "{\n" + " vec3 toLight = normalize(vec3(0.0, 0.3, 1.0));\n" + " angle = max(dot(normal, toLight), 0.0);\n" + " gl_Position = matrix * vertex;\n" + " texc = texCoord;\n" + "}\n"; + vshader2->compileSourceCode(vsrc2); + + QOpenGLShader *fshader2 = new QOpenGLShader(QOpenGLShader::Fragment); + const char *fsrc2 = + "varying highp vec4 texc;\n" + "uniform sampler2D tex;\n" + "varying mediump float angle;\n" + "void main(void)\n" + "{\n" + " highp vec3 color = texture2D(tex, texc.st).rgb;\n" + " color = color * 0.2 + color * 0.8 * angle;\n" + " gl_FragColor = vec4(clamp(color, 0.0, 1.0), 1.0);\n" + "}\n"; + fshader2->compileSourceCode(fsrc2); + + program2.addShader(vshader2); + program2.addShader(fshader2); + program2.link(); + + vertexAttr2 = program2.attributeLocation("vertex"); + normalAttr2 = program2.attributeLocation("normal"); + texCoordAttr2 = program2.attributeLocation("texCoord"); + matrixUniform2 = program2.uniformLocation("matrix"); + textureUniform2 = program2.uniformLocation("tex"); + + m_fAngle = 0; + m_fScale = 1; + createGeometry(); + createBubbles(bubbleNum - bubbles.count()); +} + +void GLWidget::paintGL() +{ + createBubbles(bubbleNum - bubbles.count()); + + QPainter painter; + painter.begin(this); + + painter.beginNativePainting(); + + glClearColor(m_background.red() / 255.0f, m_background.green() / 255.0f, + m_background.blue() / 255.0f, m_transparent ? 0.0f : 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glFrontFace(GL_CW); + glCullFace(GL_FRONT); + glEnable(GL_CULL_FACE); + glEnable(GL_DEPTH_TEST); + + QMatrix4x4 modelview; + modelview.rotate(m_fAngle, 0.0f, 1.0f, 0.0f); + modelview.rotate(m_fAngle, 1.0f, 0.0f, 0.0f); + modelview.rotate(m_fAngle, 0.0f, 0.0f, 1.0f); + modelview.scale(m_fScale); + modelview.translate(0.0f, -0.2f, 0.0f); + + if (qtLogo) { + program1.bind(); + program1.setUniformValue(matrixUniform1, modelview); + paintQtLogo(); + program1.release(); + } else { + program2.bind(); + program1.setUniformValue(matrixUniform2, modelview); + paintTexturedCube(); + program2.release(); + } + + glDisable(GL_DEPTH_TEST); + glDisable(GL_CULL_FACE); + + painter.endNativePainting(); + + if (m_showBubbles) + foreach (Bubble *bubble, bubbles) { + bubble->drawBubble(&painter); + } + + if (const int elapsed = time.elapsed()) { + QString framesPerSecond; + framesPerSecond.setNum(frames /(elapsed / 1000.0), 'f', 2); + painter.setPen(m_transparent ? Qt::black : Qt::white); + painter.drawText(20, 40, framesPerSecond + " paintGL calls / s"); + } + + painter.end(); + + QMutableListIterator<Bubble*> iter(bubbles); + + while (iter.hasNext()) { + Bubble *bubble = iter.next(); + bubble->move(rect()); + } + if (!(frames % 100)) { + time.start(); + frames = 0; + } + m_fAngle += 1.0f; + frames ++; +} + +void GLWidget::createBubbles(int number) +{ + for (int i = 0; i < number; ++i) { + QPointF position(width()*(0.1 + (0.8*qrand()/(RAND_MAX+1.0))), + height()*(0.1 + (0.8*qrand()/(RAND_MAX+1.0)))); + qreal radius = qMin(width(), height())*(0.0175 + 0.0875*qrand()/(RAND_MAX+1.0)); + QPointF velocity(width()*0.0175*(-0.5 + qrand()/(RAND_MAX+1.0)), + height()*0.0175*(-0.5 + qrand()/(RAND_MAX+1.0))); + + bubbles.append(new Bubble(position, radius, velocity)); + } +} + +void GLWidget::createGeometry() +{ + vertices.clear(); + normals.clear(); + + qreal x1 = +0.06f; + qreal y1 = -0.14f; + qreal x2 = +0.14f; + qreal y2 = -0.06f; + qreal x3 = +0.08f; + qreal y3 = +0.00f; + qreal x4 = +0.30f; + qreal y4 = +0.22f; + + quad(x1, y1, x2, y2, y2, x2, y1, x1); + quad(x3, y3, x4, y4, y4, x4, y3, x3); + + extrude(x1, y1, x2, y2); + extrude(x2, y2, y2, x2); + extrude(y2, x2, y1, x1); + extrude(y1, x1, x1, y1); + extrude(x3, y3, x4, y4); + extrude(x4, y4, y4, x4); + extrude(y4, x4, y3, x3); + + const qreal Pi = 3.14159f; + const int NumSectors = 100; + + for (int i = 0; i < NumSectors; ++i) { + qreal angle1 = (i * 2 * Pi) / NumSectors; + qreal x5 = 0.30 * sin(angle1); + qreal y5 = 0.30 * cos(angle1); + qreal x6 = 0.20 * sin(angle1); + qreal y6 = 0.20 * cos(angle1); + + qreal angle2 = ((i + 1) * 2 * Pi) / NumSectors; + qreal x7 = 0.20 * sin(angle2); + qreal y7 = 0.20 * cos(angle2); + qreal x8 = 0.30 * sin(angle2); + qreal y8 = 0.30 * cos(angle2); + + quad(x5, y5, x6, y6, x7, y7, x8, y8); + + extrude(x6, y6, x7, y7); + extrude(x8, y8, x5, y5); + } + + for (int i = 0;i < vertices.size();i++) + vertices[i] *= 2.0f; +} + +void GLWidget::quad(qreal x1, qreal y1, qreal x2, qreal y2, qreal x3, qreal y3, qreal x4, qreal y4) +{ + vertices << QVector3D(x1, y1, -0.05f); + vertices << QVector3D(x2, y2, -0.05f); + vertices << QVector3D(x4, y4, -0.05f); + + vertices << QVector3D(x3, y3, -0.05f); + vertices << QVector3D(x4, y4, -0.05f); + vertices << QVector3D(x2, y2, -0.05f); + + QVector3D n = QVector3D::normal + (QVector3D(x2 - x1, y2 - y1, 0.0f), QVector3D(x4 - x1, y4 - y1, 0.0f)); + + normals << n; + normals << n; + normals << n; + + normals << n; + normals << n; + normals << n; + + vertices << QVector3D(x4, y4, 0.05f); + vertices << QVector3D(x2, y2, 0.05f); + vertices << QVector3D(x1, y1, 0.05f); + + vertices << QVector3D(x2, y2, 0.05f); + vertices << QVector3D(x4, y4, 0.05f); + vertices << QVector3D(x3, y3, 0.05f); + + n = QVector3D::normal + (QVector3D(x2 - x4, y2 - y4, 0.0f), QVector3D(x1 - x4, y1 - y4, 0.0f)); + + normals << n; + normals << n; + normals << n; + + normals << n; + normals << n; + normals << n; +} + +void GLWidget::extrude(qreal x1, qreal y1, qreal x2, qreal y2) +{ + vertices << QVector3D(x1, y1, +0.05f); + vertices << QVector3D(x2, y2, +0.05f); + vertices << QVector3D(x1, y1, -0.05f); + + vertices << QVector3D(x2, y2, -0.05f); + vertices << QVector3D(x1, y1, -0.05f); + vertices << QVector3D(x2, y2, +0.05f); + + QVector3D n = QVector3D::normal + (QVector3D(x2 - x1, y2 - y1, 0.0f), QVector3D(0.0f, 0.0f, -0.1f)); + + normals << n; + normals << n; + normals << n; + + normals << n; + normals << n; + normals << n; +} + +void GLWidget::setTransparent(bool transparent) +{ + setAttribute(Qt::WA_AlwaysStackOnTop, transparent); + m_transparent = transparent; + // Call update() on the top-level window after toggling AlwayStackOnTop to make sure + // the entire backingstore is updated accordingly. + window()->update(); +} + +void GLWidget::resizeGL(int w, int h) +{ + if (m_hasButton) { + if (!m_btn) { + m_btn = new QPushButton("A widget on top.\nPress me!", this); + connect(m_btn, &QPushButton::clicked, this, &GLWidget::handleButtonPress); + } + m_btn->move(w / 2, h / 2); + } +} + +void GLWidget::handleButtonPress() +{ + m_mainWindow->addNew(); +} diff --git a/examples/opengl/qopenglwidget/glwidget.h b/examples/opengl/qopenglwidget/glwidget.h new file mode 100644 index 0000000000..6c43ac1576 --- /dev/null +++ b/examples/opengl/qopenglwidget/glwidget.h @@ -0,0 +1,112 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia Plc 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 <QOpenGLWidget> +#include <QOpenGLFunctions> +#include <QOpenGLShaderProgram> +#include <QVector3D> +#include <QMatrix4x4> +#include <QTime> +#include <QVector> +#include <QPushButton> + +class Bubble; +class MainWindow; + +class GLWidget : public QOpenGLWidget, protected QOpenGLFunctions +{ + Q_OBJECT +public: + GLWidget(MainWindow *mw, bool button, const QColor &background); + ~GLWidget(); + +public slots: + void setScaling(int scale); + void setLogo(); + void setTexture(); + void showBubbles(bool); + void setTransparent(bool transparent); + +private slots: + void handleButtonPress(); + +protected: + void resizeGL(int w, int h) Q_DECL_OVERRIDE; + void paintGL() Q_DECL_OVERRIDE; + void initializeGL() Q_DECL_OVERRIDE; + +private: + MainWindow *m_mainWindow; + GLuint m_uiTexture; + qreal m_fAngle; + qreal m_fScale; + bool m_showBubbles; + void paintTexturedCube(); + void paintQtLogo(); + void createGeometry(); + void createBubbles(int number); + void quad(qreal x1, qreal y1, qreal x2, qreal y2, qreal x3, qreal y3, qreal x4, qreal y4); + void extrude(qreal x1, qreal y1, qreal x2, qreal y2); + QVector<QVector3D> vertices; + QVector<QVector3D> normals; + bool qtLogo; + QList<Bubble*> bubbles; + int frames; + QTime time; + QOpenGLShaderProgram program1; + QOpenGLShaderProgram program2; + int vertexAttr1; + int normalAttr1; + int matrixUniform1; + int vertexAttr2; + int normalAttr2; + int texCoordAttr2; + int matrixUniform2; + int textureUniform2; + bool m_transparent; + QPushButton *m_btn; + bool m_hasButton; + QColor m_background; +}; + +#endif diff --git a/examples/opengl/qopenglwidget/main.cpp b/examples/opengl/qopenglwidget/main.cpp new file mode 100644 index 0000000000..2156e60155 --- /dev/null +++ b/examples/opengl/qopenglwidget/main.cpp @@ -0,0 +1,52 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia Plc 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 <QApplication> +#include <QMainWindow> +#include "mainwindow.h" + +int main( int argc, char ** argv ) +{ + Q_INIT_RESOURCE(texture); + QApplication a( argc, argv ); + MainWindow mw; + mw.showMaximized(); + return a.exec(); +} diff --git a/examples/opengl/qopenglwidget/mainwindow.cpp b/examples/opengl/qopenglwidget/mainwindow.cpp new file mode 100644 index 0000000000..f09acacaf0 --- /dev/null +++ b/examples/opengl/qopenglwidget/mainwindow.cpp @@ -0,0 +1,152 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia Plc 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 "mainwindow.h" + +#include <QApplication> +#include <QMenuBar> +#include <QGroupBox> +#include <QSlider> +#include <QLabel> +#include <QCheckBox> +#include <QSpinBox> + +#include "glwidget.h" + +MainWindow::MainWindow() + : m_nextX(1), m_nextY(1) +{ + GLWidget *glwidget = new GLWidget(this, true, qRgb(20, 20, 50)); + QLabel *label = new QLabel(this); + m_timer = new QTimer(this); + QSlider *slider = new QSlider(this); + slider->setOrientation(Qt::Horizontal); + + QLabel *updateLabel = new QLabel("Update interval"); + QSpinBox *updateInterval = new QSpinBox(this); + updateInterval->setSuffix(" ms"); + updateInterval->setValue(10); + updateInterval->setToolTip("Interval for the timer that calls update().\n" + "Note that on most systems the swap will block to wait for vsync\n" + "and therefore an interval < 16 ms will likely lead to a 60 FPS update rate."); + QGroupBox *updateGroupBox = new QGroupBox(this); + QCheckBox *transparent = new QCheckBox("Transparent background", this); + transparent->setToolTip("Toggles Qt::WA_AlwaysStackOnTop and transparent clear color for glClear().\n" + "Note how the button on top stacks incorrectly when enabling this."); + QHBoxLayout *updateLayout = new QHBoxLayout; + updateLayout->addWidget(updateLabel); + updateLayout->addWidget(updateInterval); + updateLayout->addWidget(transparent); + updateGroupBox->setLayout(updateLayout); + + slider->setRange(0, 50); + slider->setSliderPosition(30); + m_timer->setInterval(10); + label->setText("A QOpenGLWidget"); + label->setAlignment(Qt::AlignHCenter); + + QGroupBox * groupBox = new QGroupBox(this); + setCentralWidget(groupBox); + groupBox->setTitle("QOpenGLWidget Example"); + + m_layout = new QGridLayout(groupBox); + + m_layout->addWidget(glwidget,1,0,8,1); + m_layout->addWidget(label,9,0,1,1); + m_layout->addWidget(updateGroupBox, 10, 0, 1, 1); + m_layout->addWidget(slider, 11,0,1,1); + + groupBox->setLayout(m_layout); + + QMenu *fileMenu = new QMenu("&File"); + QMenu *helpMenu = new QMenu("&Help"); + QMenu *showMenu = new QMenu("&Show"); + menuBar()->addMenu(fileMenu); + menuBar()->addMenu(showMenu); + menuBar()->addMenu(helpMenu); + QAction *exit = new QAction("E&xit", fileMenu); + QAction *aboutQt = new QAction("About Qt", helpMenu); + QAction *showLogo = new QAction("Show 3D Logo", showMenu); + QAction *showTexture = new QAction("Show 2D Texture", showMenu); + QAction *showBubbles = new QAction("Show bubbles", showMenu); + showBubbles->setCheckable(true); + showBubbles->setChecked(true); + fileMenu->addAction(exit); + helpMenu->addAction(aboutQt); + showMenu->addAction(showLogo); + showMenu->addAction(showTexture); + showMenu->addAction(showBubbles); + + connect(exit, SIGNAL(triggered(bool)), this, SLOT(close())); + connect(aboutQt, SIGNAL(triggered(bool)), qApp, SLOT(aboutQt())); + + connect(m_timer, SIGNAL(timeout()), glwidget, SLOT(update())); + + connect(showLogo, SIGNAL(triggered(bool)), glwidget, SLOT(setLogo())); + connect(showTexture, SIGNAL(triggered(bool)), glwidget, SLOT(setTexture())); + connect(showBubbles, SIGNAL(triggered(bool)), glwidget, SLOT(showBubbles(bool))); + connect(slider, SIGNAL(valueChanged(int)), glwidget, SLOT(setScaling(int))); + connect(transparent, &QCheckBox::toggled, glwidget, &GLWidget::setTransparent); + + connect(updateInterval, SIGNAL(valueChanged(int)), this, SLOT(updateIntervalChanged(int))); + + m_timer->start(); +} + +void MainWindow::updateIntervalChanged(int value) +{ + m_timer->setInterval(value); + m_timer->start(); +} + +void MainWindow::addNew() +{ + if (m_nextY == 4) + return; + GLWidget *w = new GLWidget(this, false, qRgb(qrand() % 256, qrand() % 256, qrand() % 256)); + connect(m_timer, SIGNAL(timeout()), w, SLOT(update())); + m_layout->addWidget(w, m_nextY, m_nextX, 1, 1); + if (m_nextX == 3) { + m_nextX = 1; + ++m_nextY; + } else { + ++m_nextX; + } +} diff --git a/examples/opengl/qopenglwidget/mainwindow.h b/examples/opengl/qopenglwidget/mainwindow.h new file mode 100644 index 0000000000..9db3e8cbec --- /dev/null +++ b/examples/opengl/qopenglwidget/mainwindow.h @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia Plc 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 MAINWINDOW_H +#define MAINWINDOW_H + +#include <QMainWindow> +#include <QTimer> +#include <QGridLayout> + +class MainWindow : public QMainWindow +{ + Q_OBJECT + +public: + MainWindow(); + void addNew(); + +private slots: + void updateIntervalChanged(int value); + +private: + QTimer *m_timer; + QGridLayout *m_layout; + int m_nextX; + int m_nextY; +}; + +#endif diff --git a/examples/opengl/qopenglwidget/qopenglwidget.pro b/examples/opengl/qopenglwidget/qopenglwidget.pro new file mode 100644 index 0000000000..0165285c02 --- /dev/null +++ b/examples/opengl/qopenglwidget/qopenglwidget.pro @@ -0,0 +1,15 @@ +QT += widgets + +SOURCES += main.cpp \ + glwidget.cpp \ + mainwindow.cpp \ + bubble.cpp + +HEADERS += glwidget.h \ + mainwindow.h \ + bubble.h + +RESOURCES += texture.qrc + +target.path = $$[QT_INSTALL_EXAMPLES]/opengl/qopenglwidget +INSTALLS += target diff --git a/examples/opengl/qopenglwidget/qt.png b/examples/opengl/qopenglwidget/qt.png Binary files differnew file mode 100644 index 0000000000..79e383cf50 --- /dev/null +++ b/examples/opengl/qopenglwidget/qt.png diff --git a/examples/opengl/qopenglwidget/texture.qrc b/examples/opengl/qopenglwidget/texture.qrc new file mode 100644 index 0000000000..ff1d0e535f --- /dev/null +++ b/examples/opengl/qopenglwidget/texture.qrc @@ -0,0 +1,5 @@ +<!DOCTYPE RCC><RCC version="1.0"> +<qresource> + <file>qt.png</file> +</qresource> +</RCC> |