diff options
Diffstat (limited to 'examples')
103 files changed, 1595 insertions, 1163 deletions
diff --git a/examples/opengl/2dpainting/2dpainting.pro b/examples/opengl/2dpainting/2dpainting.pro index 08383a4d39..b9611f5b40 100644 --- a/examples/opengl/2dpainting/2dpainting.pro +++ b/examples/opengl/2dpainting/2dpainting.pro @@ -1,4 +1,4 @@ -QT += opengl widgets +QT += widgets HEADERS = glwidget.h \ helper.h \ diff --git a/examples/opengl/2dpainting/glwidget.cpp b/examples/opengl/2dpainting/glwidget.cpp index 0443d5b5bd..5e040ae347 100644 --- a/examples/opengl/2dpainting/glwidget.cpp +++ b/examples/opengl/2dpainting/glwidget.cpp @@ -41,11 +41,12 @@ #include "glwidget.h" #include "helper.h" +#include <QPainter> #include <QTimer> //! [0] GLWidget::GLWidget(Helper *helper, QWidget *parent) - : QGLWidget(QGLFormat(QGL::SampleBuffers), parent), helper(helper) + : QOpenGLWidget(parent), helper(helper) { elapsed = 0; setFixedSize(200, 200); @@ -57,7 +58,7 @@ GLWidget::GLWidget(Helper *helper, QWidget *parent) void GLWidget::animate() { elapsed = (elapsed + qobject_cast<QTimer*>(sender())->interval()) % 1000; - repaint(); + update(); } //! [1] diff --git a/examples/opengl/2dpainting/glwidget.h b/examples/opengl/2dpainting/glwidget.h index fec1be12f7..07b279117c 100644 --- a/examples/opengl/2dpainting/glwidget.h +++ b/examples/opengl/2dpainting/glwidget.h @@ -41,12 +41,12 @@ #ifndef GLWIDGET_H #define GLWIDGET_H -#include <QGLWidget> +#include <QOpenGLWidget> //! [0] class Helper; -class GLWidget : public QGLWidget +class GLWidget : public QOpenGLWidget { Q_OBJECT diff --git a/examples/opengl/2dpainting/main.cpp b/examples/opengl/2dpainting/main.cpp index 5daff5c66f..fb3454b1cd 100644 --- a/examples/opengl/2dpainting/main.cpp +++ b/examples/opengl/2dpainting/main.cpp @@ -41,10 +41,16 @@ #include "window.h" #include <QApplication> +#include <QSurfaceFormat> int main(int argc, char *argv[]) { QApplication app(argc, argv); + + QSurfaceFormat fmt; + fmt.setSamples(4); + QSurfaceFormat::setDefaultFormat(fmt); + Window window; window.show(); return app.exec(); diff --git a/examples/opengl/2dpainting/widget.cpp b/examples/opengl/2dpainting/widget.cpp index 12b7935a94..edfff5ba79 100644 --- a/examples/opengl/2dpainting/widget.cpp +++ b/examples/opengl/2dpainting/widget.cpp @@ -57,7 +57,7 @@ Widget::Widget(Helper *helper, QWidget *parent) void Widget::animate() { elapsed = (elapsed + qobject_cast<QTimer*>(sender())->interval()) % 1000; - repaint(); + update(); } //! [1] diff --git a/examples/opengl/cube/cube.pro b/examples/opengl/cube/cube.pro index 85272bc471..b9416f1a9d 100644 --- a/examples/opengl/cube/cube.pro +++ b/examples/opengl/cube/cube.pro @@ -5,20 +5,17 @@ TEMPLATE = app SOURCES += main.cpp -qtHaveModule(opengl) { - QT += opengl +SOURCES += \ + mainwidget.cpp \ + geometryengine.cpp - SOURCES += mainwidget.cpp \ - geometryengine.cpp +HEADERS += \ + mainwidget.h \ + geometryengine.h - HEADERS += \ - mainwidget.h \ - geometryengine.h - - RESOURCES += \ - shaders.qrc \ - textures.qrc -} +RESOURCES += \ + shaders.qrc \ + textures.qrc # install target.path = $$[QT_INSTALL_EXAMPLES]/opengl/cube diff --git a/examples/opengl/cube/geometryengine.cpp b/examples/opengl/cube/geometryengine.cpp index 0a34213084..618a080c37 100644 --- a/examples/opengl/cube/geometryengine.cpp +++ b/examples/opengl/cube/geometryengine.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtCore module of the Qt Toolkit. @@ -49,29 +49,27 @@ struct VertexData QVector2D texCoord; }; +//! [0] GeometryEngine::GeometryEngine() + : indexBuf(QOpenGLBuffer::IndexBuffer) { -} - -GeometryEngine::~GeometryEngine() -{ - glDeleteBuffers(2, vboIds); -} - -void GeometryEngine::init() -{ - initializeGLFunctions(); + initializeOpenGLFunctions(); -//! [0] // Generate 2 VBOs - glGenBuffers(2, vboIds); - -//! [0] + arrayBuf.create(); + indexBuf.create(); // Initializes cube geometry and transfers it to VBOs initCubeGeometry(); } +GeometryEngine::~GeometryEngine() +{ + arrayBuf.destroy(); + indexBuf.destroy(); +} +//! [0] + void GeometryEngine::initCubeGeometry() { // For cube we would need only 8 vertices but we have to @@ -133,21 +131,21 @@ void GeometryEngine::initCubeGeometry() //! [1] // Transfer vertex data to VBO 0 - glBindBuffer(GL_ARRAY_BUFFER, vboIds[0]); - glBufferData(GL_ARRAY_BUFFER, 24 * sizeof(VertexData), vertices, GL_STATIC_DRAW); + arrayBuf.bind(); + arrayBuf.allocate(vertices, 24 * sizeof(VertexData)); // Transfer index data to VBO 1 - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboIds[1]); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, 34 * sizeof(GLushort), indices, GL_STATIC_DRAW); + indexBuf.bind(); + indexBuf.allocate(indices, 34 * sizeof(GLushort)); //! [1] } //! [2] -void GeometryEngine::drawCubeGeometry(QGLShaderProgram *program) +void GeometryEngine::drawCubeGeometry(QOpenGLShaderProgram *program) { // Tell OpenGL which VBOs to use - glBindBuffer(GL_ARRAY_BUFFER, vboIds[0]); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboIds[1]); + arrayBuf.bind(); + indexBuf.bind(); // Offset for position quintptr offset = 0; @@ -155,7 +153,7 @@ void GeometryEngine::drawCubeGeometry(QGLShaderProgram *program) // Tell OpenGL programmable pipeline how to locate vertex position data int vertexLocation = program->attributeLocation("a_position"); program->enableAttributeArray(vertexLocation); - glVertexAttribPointer(vertexLocation, 3, GL_FLOAT, GL_FALSE, sizeof(VertexData), (const void *)offset); + program->setAttributeBuffer(vertexLocation, GL_FLOAT, offset, 3, sizeof(VertexData)); // Offset for texture coordinate offset += sizeof(QVector3D); @@ -163,7 +161,7 @@ void GeometryEngine::drawCubeGeometry(QGLShaderProgram *program) // Tell OpenGL programmable pipeline how to locate vertex texture coordinate data int texcoordLocation = program->attributeLocation("a_texcoord"); program->enableAttributeArray(texcoordLocation); - glVertexAttribPointer(texcoordLocation, 2, GL_FLOAT, GL_FALSE, sizeof(VertexData), (const void *)offset); + program->setAttributeBuffer(texcoordLocation, GL_FLOAT, offset, 2, sizeof(VertexData)); // Draw cube geometry using indices from VBO 1 glDrawElements(GL_TRIANGLE_STRIP, 34, GL_UNSIGNED_SHORT, 0); diff --git a/examples/opengl/cube/geometryengine.h b/examples/opengl/cube/geometryengine.h index fe90c436c6..0b51ebf5f2 100644 --- a/examples/opengl/cube/geometryengine.h +++ b/examples/opengl/cube/geometryengine.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtCore module of the Qt Toolkit. @@ -41,22 +41,23 @@ #ifndef GEOMETRYENGINE_H #define GEOMETRYENGINE_H -#include <QGLFunctions> -#include <QGLShaderProgram> +#include <QOpenGLFunctions> +#include <QOpenGLShaderProgram> +#include <QOpenGLBuffer> -class GeometryEngine : protected QGLFunctions +class GeometryEngine : protected QOpenGLFunctions { public: GeometryEngine(); virtual ~GeometryEngine(); - void init(); - void drawCubeGeometry(QGLShaderProgram *program); + void drawCubeGeometry(QOpenGLShaderProgram *program); private: void initCubeGeometry(); - GLuint vboIds[2]; + QOpenGLBuffer arrayBuf; + QOpenGLBuffer indexBuf; }; #endif // GEOMETRYENGINE_H diff --git a/examples/opengl/cube/main.cpp b/examples/opengl/cube/main.cpp index a414fad023..73363da016 100644 --- a/examples/opengl/cube/main.cpp +++ b/examples/opengl/cube/main.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtCore module of the Qt Toolkit. @@ -40,6 +40,7 @@ #include <QApplication> #include <QLabel> +#include <QSurfaceFormat> #ifndef QT_NO_OPENGL #include "mainwidget.h" @@ -48,6 +49,11 @@ int main(int argc, char *argv[]) { QApplication app(argc, argv); + + QSurfaceFormat format; + format.setDepthBufferSize(24); + QSurfaceFormat::setDefaultFormat(format); + app.setApplicationName("cube"); app.setApplicationVersion("0.1"); #ifndef QT_NO_OPENGL diff --git a/examples/opengl/cube/mainwidget.cpp b/examples/opengl/cube/mainwidget.cpp index 5c1cd28b54..b5a7a972d1 100644 --- a/examples/opengl/cube/mainwidget.cpp +++ b/examples/opengl/cube/mainwidget.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtCore module of the Qt Toolkit. @@ -45,14 +45,21 @@ #include <math.h> MainWidget::MainWidget(QWidget *parent) : - QGLWidget(parent), + QOpenGLWidget(parent), + geometries(0), + texture(0), angularSpeed(0) { } MainWidget::~MainWidget() { - deleteTexture(texture); + // Make sure the context is current when deleting the texture + // and the buffers. + makeCurrent(); + delete texture; + delete geometries; + doneCurrent(); } //! [0] @@ -95,16 +102,18 @@ void MainWidget::timerEvent(QTimerEvent *) // Update rotation rotation = QQuaternion::fromAxisAndAngle(rotationAxis, angularSpeed) * rotation; - // Update scene - updateGL(); + // Request an update + update(); } } //! [1] void MainWidget::initializeGL() { - initializeGLFunctions(); - qglClearColor(Qt::black); + initializeOpenGLFunctions(); + + glClearColor(0, 0, 0, 1); + initShaders(); initTextures(); @@ -116,7 +125,7 @@ void MainWidget::initializeGL() glEnable(GL_CULL_FACE); //! [2] - geometries.init(); + geometries = new GeometryEngine; // Use QBasicTimer because its faster than QTimer timer.start(12, this); @@ -126,11 +135,11 @@ void MainWidget::initializeGL() void MainWidget::initShaders() { // Compile vertex shader - if (!program.addShaderFromSourceFile(QGLShader::Vertex, ":/vshader.glsl")) + if (!program.addShaderFromSourceFile(QOpenGLShader::Vertex, ":/vshader.glsl")) close(); // Compile fragment shader - if (!program.addShaderFromSourceFile(QGLShader::Fragment, ":/fshader.glsl")) + if (!program.addShaderFromSourceFile(QOpenGLShader::Fragment, ":/fshader.glsl")) close(); // Link shader pipeline @@ -147,28 +156,23 @@ void MainWidget::initShaders() void MainWidget::initTextures() { // Load cube.png image - glEnable(GL_TEXTURE_2D); - texture = bindTexture(QImage(":/cube.png")); + texture = new QOpenGLTexture(QImage(":/cube.png").mirrored()); // Set nearest filtering mode for texture minification - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + texture->setMinificationFilter(QOpenGLTexture::Nearest); // Set bilinear filtering mode for texture magnification - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + texture->setMagnificationFilter(QOpenGLTexture::Linear); // Wrap texture coordinates by repeating // f.ex. texture coordinate (1.1, 1.2) is same as (0.1, 0.2) - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + texture->setWrapMode(QOpenGLTexture::Repeat); } //! [4] //! [5] void MainWidget::resizeGL(int w, int h) { - // Set OpenGL viewport to cover whole widget - glViewport(0, 0, w, h); - // Calculate aspect ratio qreal aspect = qreal(w) / qreal(h ? h : 1); @@ -188,6 +192,8 @@ void MainWidget::paintGL() // Clear color and depth buffer glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + texture->bind(); + //! [6] // Calculate model view transformation QMatrix4x4 matrix; @@ -202,5 +208,5 @@ void MainWidget::paintGL() program.setUniformValue("texture", 0); // Draw cube geometry - geometries.drawCubeGeometry(&program); + geometries->drawCubeGeometry(&program); } diff --git a/examples/opengl/cube/mainwidget.h b/examples/opengl/cube/mainwidget.h index 92b3aabf46..8aff8f7714 100644 --- a/examples/opengl/cube/mainwidget.h +++ b/examples/opengl/cube/mainwidget.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtCore module of the Qt Toolkit. @@ -43,18 +43,18 @@ #include "geometryengine.h" -#include <QGLWidget> -#include <QGLFunctions> +#include <QOpenGLWidget> +#include <QOpenGLFunctions> #include <QMatrix4x4> #include <QQuaternion> #include <QVector2D> #include <QBasicTimer> -#include <QGLShaderProgram> - +#include <QOpenGLShaderProgram> +#include <QOpenGLTexture> class GeometryEngine; -class MainWidget : public QGLWidget, protected QGLFunctions +class MainWidget : public QOpenGLWidget, protected QOpenGLFunctions { Q_OBJECT @@ -76,10 +76,10 @@ protected: private: QBasicTimer timer; - QGLShaderProgram program; - GeometryEngine geometries; + QOpenGLShaderProgram program; + GeometryEngine *geometries; - GLuint texture; + QOpenGLTexture *texture; QMatrix4x4 projection; diff --git a/examples/opengl/doc/images/framebufferobject2-example.png b/examples/opengl/doc/images/framebufferobject2-example.png Binary files differdeleted file mode 100644 index bafb05a08b..0000000000 --- a/examples/opengl/doc/images/framebufferobject2-example.png +++ /dev/null diff --git a/examples/opengl/doc/images/grabber-example.png b/examples/opengl/doc/images/grabber-example.png Binary files differdeleted file mode 100644 index 6a05b94bec..0000000000 --- a/examples/opengl/doc/images/grabber-example.png +++ /dev/null diff --git a/examples/opengl/doc/images/hellogl-es-example.png b/examples/opengl/doc/images/hellogl-es-example.png Binary files differdeleted file mode 100644 index 7e55f09a7a..0000000000 --- a/examples/opengl/doc/images/hellogl-es-example.png +++ /dev/null diff --git a/examples/opengl/doc/images/hellogl-example.png b/examples/opengl/doc/images/hellogl-example.png Binary files differdeleted file mode 100644 index ecb3a3a7b0..0000000000 --- a/examples/opengl/doc/images/hellogl-example.png +++ /dev/null diff --git a/examples/opengl/doc/images/hellogl2-example.png b/examples/opengl/doc/images/hellogl2-example.png Binary files differnew file mode 100644 index 0000000000..5bb702e71c --- /dev/null +++ b/examples/opengl/doc/images/hellogl2-example.png diff --git a/examples/opengl/doc/images/overpainting-example.png b/examples/opengl/doc/images/overpainting-example.png Binary files differdeleted file mode 100644 index 0368dcabc8..0000000000 --- a/examples/opengl/doc/images/overpainting-example.png +++ /dev/null diff --git a/examples/opengl/doc/images/pbuffers-example.png b/examples/opengl/doc/images/pbuffers-example.png Binary files differdeleted file mode 100644 index c34a6fd02b..0000000000 --- a/examples/opengl/doc/images/pbuffers-example.png +++ /dev/null diff --git a/examples/opengl/doc/images/pbuffers2-example.png b/examples/opengl/doc/images/pbuffers2-example.png Binary files differdeleted file mode 100644 index 4a9c7175a3..0000000000 --- a/examples/opengl/doc/images/pbuffers2-example.png +++ /dev/null diff --git a/examples/opengl/doc/images/samplebuffers-example.png b/examples/opengl/doc/images/samplebuffers-example.png Binary files differdeleted file mode 100644 index b751c143b3..0000000000 --- a/examples/opengl/doc/images/samplebuffers-example.png +++ /dev/null diff --git a/examples/opengl/doc/src/cube.qdoc b/examples/opengl/doc/src/cube.qdoc index e6b2548cd1..ed1390db1a 100644 --- a/examples/opengl/doc/src/cube.qdoc +++ b/examples/opengl/doc/src/cube.qdoc @@ -117,7 +117,9 @@ aren't facing towards screen. Creating vertex buffer objects and transferring data to them is quite simple using - OpenGL provided functions. + QOpenGLBuffer. MainWidget makes sure the GeometryEngine instance is created and + destroyed with the OpenGL context current. This way we can use OpenGL resources + in the constructor and perform proper cleanup in the destructor. \snippet cube/geometryengine.cpp 0 diff --git a/examples/opengl/doc/src/framebufferobject2.qdoc b/examples/opengl/doc/src/framebufferobject2.qdoc deleted file mode 100644 index 33d641be10..0000000000 --- a/examples/opengl/doc/src/framebufferobject2.qdoc +++ /dev/null @@ -1,38 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the documentation of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:FDL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Free Documentation License Usage -** 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. Please review the following information to ensure -** the GNU Free Documentation License version 1.3 requirements -** will be met: http://www.gnu.org/copyleft/fdl.html. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -/*! - \example framebufferobject2 - \title Framebuffer Object 2 Example - - \ingroup examples-widgets-opengl - \brief The Framebuffer Object 2 example demonstrates how to use the - QGLFramebufferObject class to render into an off-screen buffer and - use the contents as a texture in a QGLWidget. - - \image framebufferobject2-example.png -*/ diff --git a/examples/opengl/doc/src/grabber.qdoc b/examples/opengl/doc/src/grabber.qdoc deleted file mode 100644 index fd2a2cf748..0000000000 --- a/examples/opengl/doc/src/grabber.qdoc +++ /dev/null @@ -1,36 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the documentation of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:FDL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Free Documentation License Usage -** 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. Please review the following information to ensure -** the GNU Free Documentation License version 1.3 requirements -** will be met: http://www.gnu.org/copyleft/fdl.html. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -/*! - \example grabber - \title Grabber Example - \ingroup examples-widgets-opengl - - \brief The Grabber examples shows how to retrieve the contents of an OpenGL framebuffer. - - \image grabber-example.png -*/ diff --git a/examples/opengl/doc/src/hellogl.qdoc b/examples/opengl/doc/src/hellogl.qdoc deleted file mode 100644 index 9740c91408..0000000000 --- a/examples/opengl/doc/src/hellogl.qdoc +++ /dev/null @@ -1,320 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the documentation of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:FDL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Free Documentation License Usage -** 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. Please review the following information to ensure -** the GNU Free Documentation License version 1.3 requirements -** will be met: http://www.gnu.org/copyleft/fdl.html. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -/*! - \example hellogl - \title Hello GL Example - \ingroup examples-widgets-opengl - - \brief The Hello GL example demonstrates the basic use of the OpenGL-related classes - provided with Qt. - - \image hellogl-example.png - - Qt provides the QGLWidget class to enable OpenGL graphics to be rendered within - a standard application user interface. By subclassing this class, and providing - reimplementations of event handler functions, 3D scenes can be displayed on - widgets that can be placed in layouts, connected to other objects using signals - and slots, and manipulated like any other widget. - - \tableofcontents - - \section1 GLWidget Class Definition - - The \c GLWidget class contains some standard public definitions for the - constructor, destructor, \l{QWidget::sizeHint()}{sizeHint()}, and - \l{QWidget::minimumSizeHint()}{minimumSizeHint()} functions: - - \snippet hellogl/glwidget.h 0 - - We use a destructor to ensure that any OpenGL-specific data structures - are deleted when the widget is no longer needed (although in this case nothing - needs cleaning up). - - \snippet hellogl/glwidget.h 1 - - The signals and slots are used to allow other objects to interact with the - 3D scene. - - \snippet hellogl/glwidget.h 2 - - OpenGL initialization, viewport resizing, and painting are handled by - reimplementing the QGLWidget::initializeGL(), QGLWidget::resizeGL(), and - QGLWidget::paintGL() handler functions. To enable the user to interact - directly with the scene using the mouse, we reimplement - QWidget::mousePressEvent() and QWidget::mouseMoveEvent(). - - \snippet hellogl/glwidget.h 3 - - The rest of the class contains utility functions and variables that are - used to construct and hold orientation information for the scene. The - \c logo variable will be used to hold a pointer to the QtLogo object which - contains all the geometry. - - \section1 GLWidget Class Implementation - - In this example, we split the class into groups of functions and describe - them separately. This helps to illustrate the differences between subclasses - of native widgets (such as QWidget and QFrame) and QGLWidget subclasses. - - \section2 Widget Construction and Sizing - - The constructor provides default rotation angles for the scene, sets - the pointer to the QtLogo object to null, and sets up some colors for - later use. - - \snippet hellogl/glwidget.cpp 0 - - We also implement a destructor to release OpenGL-related resources when the - widget is deleted: - - \snippet hellogl/glwidget.cpp 1 - - In this case nothing requires cleaning up. - - We provide size hint functions to ensure that the widget is shown at a - reasonable size: - - \snippet hellogl/glwidget.cpp 2 - \codeline - \snippet hellogl/glwidget.cpp 3 - \snippet hellogl/glwidget.cpp 4 - - The widget provides three slots that enable other components in the - example to change the orientation of the scene: - - \snippet hellogl/glwidget.cpp 5 - - In the above slot, the \c xRot variable is updated only if the new angle is - different to the old one, the \c xRotationChanged() signal is emitted to - allow other components to be updated, and an update is scheduled. - - Note that the widget's \l{QGLWidget::updateGL()}{updateGL()} function is not - called directly from here. Triggering rendering and buffer swaps directly - from the input event handlers is not desirable. Such events may, depending - on the platform, occur at a high frequency, and calling a potentially - blocking function like \l{QOpenGLContext::swapBuffers()}{swapBuffers} may - lead to unexpected results due to the main thread not being able to process - the input events at a proper rate. - - Instead, update() is used. This will eventually lead to a paint event, which - will in turn invoke paintGL(). Multiple calls to update() in a row will make - no difference while the event is still pending. This way the UI will perform - equally well with blocking swaps, that is, a a - \l{QGLFormat::swapInterval()}{swap interval} of 1, and non-vsynced - configurations. - - The \c setYRotation() and \c setZRotation() slots perform the same task for - rotations measured by the \c yRot and \c zRot variables. - - \section2 OpenGL Initialization - - The \l{QGLWidget::initializeGL()}{initializeGL()} function is used to - perform useful initialization tasks that are needed to render the 3D scene. - These often involve defining colors and materials, enabling and disabling - certain rendering flags, and setting other properties used to customize the - rendering process. - - \snippet hellogl/glwidget.cpp 6 - - In this example, we reimplement the function to set the background color, - create a QtLogo object instance which will contain all the geometry to - display, and set up the rendering process to use a particular shading model - and rendering flags. - - \section2 Resizing the Viewport - - The \l{QGLWidget::resizeGL()}{resizeGL()} function is used to ensure that - the OpenGL implementation renders the scene onto a viewport that matches the - size of the widget, using the correct transformation from 3D coordinates to - 2D viewport coordinates. - - The function is called whenever the widget's dimensions change, and is - supplied with the new width and height. Here, we define a square viewport - based on the length of the smallest side of the widget to ensure that - the scene is not distorted if the widget has sides of unequal length: - - \snippet hellogl/glwidget.cpp 8 - - A discussion of the projection transformation used is outside the scope of - this example. Please consult the OpenGL reference documentation for an - explanation of projection matrices. - - \section2 Painting the Scene - - The \l{QGLWidget::paintGL()}{paintGL()} function is used to paint the - contents of the scene onto the widget. For widgets that only need to be - decorated with pure OpenGL content, we reimplement QGLWidget::paintGL() - \e instead of reimplementing QWidget::paintEvent(): - - \snippet hellogl/glwidget.cpp 7 - - In this example, we clear the widget using the background color that - we defined in the \l{QGLWidget::initializeGL()}{initializeGL()} function, - set up the frame of reference for the geometry we want to display, and - call the draw method of the QtLogo object to render the scene. - - \section2 Mouse Handling - - Just as in subclasses of native widgets, mouse events are handled by - reimplementing functions such as QWidget::mousePressEvent() and - QWidget::mouseMoveEvent(). - - The \l{QWidget::mousePressEvent()}{mousePressEvent()} function simply - records the position of the mouse when a button is initially pressed: - - \snippet hellogl/glwidget.cpp 9 - - The \l{QWidget::mouseMoveEvent()}{mouseMoveEvent()} function uses the - previous location of the mouse cursor to determine how much the object - in the scene should be rotated, and in which direction: - - \snippet hellogl/glwidget.cpp 10 - - Since the user is expected to hold down the mouse button and drag the - cursor to rotate the object, the cursor's position is updated every time - a move event is received. - - \section1 QtLogo Class - - This class encapsulates the OpenGL geometry data which will be rendered - in the basic 3D scene. - - \snippet shared/qtlogo.h 0 - - The geometry is divided into a list of parts which may be rendered in - different ways. The data itself is contained in a Geometry structure that - includes the vertices, their lighting normals and index values which - point into the vertices, grouping them into faces. - - \snippet shared/qtlogo.cpp 0 - - The data in the Geometry class is stored in QVector<QVector3D> members - which are convenient for use with OpenGL because they expose raw - contiguous floating point values via the constData() method. Methods - are included for adding new vertex data, either with smooth normals, or - facetted normals; and for enabling the geometry ready for rendering. - - \snippet shared/qtlogo.cpp 1 - - The higher level Patch class has methods for accumulating the geometry - one face at a time, and treating collections of faces or "patches" with - transformations, applying different colors or smoothing. Although faces - may be added as triangles or quads, at the OpenGL level all data is - treated as triangles for compatibility with OpenGL/ES. - - \snippet shared/qtlogo.cpp 2 - - Drawing a Patch is simply acheived by applying any transformation, - and material effect, then drawing the data using the index range for - the patch. The model-view matrix is saved and then restored so that - any transformation does not affect other parts of the scene. - - \snippet shared/qtlogo.cpp 3 - - The geometry is built once on construction of the QtLogo, and it is - paramaterized on a number of divisions - which controls how "chunky" the - curved section of the logo looks - and on a scale, so larger and smaller - QtLogo objects can be created without having to use OpenGL scaling - (which would force normal recalculation). - - The building process is done by helper classes (read the source for full - details) which only exist during the build phase, to assemble the parts - of the scene. - - \snippet shared/qtlogo.cpp 4 - - Finally the complete QtLogo scene is simply drawn by enabling the data arrays - and then iterating over the parts, calling draw() on each one. - - \section1 Window Class Definition - - The \c Window class is used as a container for the \c GLWidget used to - display the scene: - - \snippet hellogl/window.h 0 - - In addition, it contains sliders that are used to change the orientation - of the object in the scene. - - \section1 Window Class Implementation - - The constructor constructs an instance of the \c GLWidget class and some - sliders to manipulate its contents. - - \snippet hellogl/window.cpp 0 - - We connect the \l{QAbstractSlider::valueChanged()}{valueChanged()} signal - from each of the sliders to the appropriate slots in \c{glWidget}. - This allows the user to change the orientation of the object by dragging - the sliders. - - We also connect the \c xRotationChanged(), \c yRotationChanged(), and - \c zRotationChanged() signals from \c glWidget to the - \l{QAbstractSlider::setValue()}{setValue()} slots in the - corresponding sliders. - - \snippet hellogl/window.cpp 1 - - The sliders are placed horizontally in a layout alongside the \c GLWidget, - and initialized with suitable default values. - - The \c createSlider() utility function constructs a QSlider, and ensures - that it is set up with a suitable range, step value, tick interval, and - page step value before returning it to the calling function: - - \snippet hellogl/window.cpp 2 - - \section1 Summary - - The \c GLWidget class implementation shows how to subclass QGLWidget for - the purposes of rendering a 3D scene using OpenGL calls. Since QGLWidget - is a subclass of QWidget, subclasses of QGLWidget can be placed in layouts - and provided with interactive features just like normal custom widgets. - - We ensure that the widget is able to correctly render the scene using OpenGL - by reimplementing the following functions: - - \list - \li QGLWidget::initializeGL() sets up resources needed by the OpenGL implementation - to render the scene. - \li QGLWidget::resizeGL() resizes the viewport so that the rendered scene fits onto - the widget, and sets up a projection matrix to map 3D coordinates to 2D viewport - coordinates. - \li QGLWidget::paintGL() performs painting operations using OpenGL calls. - \endlist - - Since QGLWidget is a subclass of QWidget, it can also be used - as a normal paint device, allowing 2D graphics to be drawn with QPainter. - This use of QGLWidget is discussed in the \l{2D Painting Example}{2D Painting} - example. - - More advanced users may want to paint over parts of a scene rendered using - OpenGL. QGLWidget allows pure OpenGL rendering to be mixed with QPainter - calls, but care must be taken to maintain the state of the OpenGL implementation. - See the \l{Overpainting Example}{Overpainting} example for more information. -*/ diff --git a/examples/opengl/doc/src/pbuffers.qdoc b/examples/opengl/doc/src/hellogl2.qdoc index 8e79ebb17c..adaf9d4719 100644 --- a/examples/opengl/doc/src/pbuffers.qdoc +++ b/examples/opengl/doc/src/hellogl2.qdoc @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the documentation of the Qt Toolkit. @@ -26,13 +26,18 @@ ****************************************************************************/ /*! - \example pbuffers - \title Pixel Buffers Example - + \example hellogl2 + \title Hello GL2 Example \ingroup examples-widgets-opengl - \brief The Pixel Buffers example demonstrates how to use the - QGLPixelBuffer class to render into an off-screen buffer and use - the contents as a dynamic texture in a QGLWidget. - \image pbuffers-example.png + \brief The Hello GL2 example demonstrates the basic use of the OpenGL-related classes + provided with Qt. + + \image hellogl2-example.png + + Qt provides the QOpenGLWidget class to enable OpenGL graphics to be rendered + within a standard application user interface. By subclassing this class, and + providing reimplementations of event handler functions, 3D scenes can be + displayed on widgets that can be placed in layouts, connected to other + objects using signals and slots, and manipulated like any other widget. */ diff --git a/examples/opengl/doc/src/overpainting.qdoc b/examples/opengl/doc/src/overpainting.qdoc deleted file mode 100644 index e9cbbab2c4..0000000000 --- a/examples/opengl/doc/src/overpainting.qdoc +++ /dev/null @@ -1,244 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the documentation of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:FDL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Free Documentation License Usage -** 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. Please review the following information to ensure -** the GNU Free Documentation License version 1.3 requirements -** will be met: http://www.gnu.org/copyleft/fdl.html. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -/*! - \example overpainting - \title Overpainting Example - - \ingroup examples-widgets-opengl - \brief The Overpainting example shows how QPainter can be used - to overpaint a scene rendered using OpenGL in a QGLWidget. - - \image overpainting-example.png - - QGLWidget provides a widget with integrated OpenGL graphics support - that enables 3D graphics to be displayed using normal OpenGL calls, - yet also behaves like any other standard Qt widget with support for - signals and slots, properties, and Qt's action system. - - Usually, QGLWidget is subclassed to display a pure 3D scene. The - developer reimplements \l{QGLWidget::initializeGL()}{initializeGL()} - to initialize any required resources, \l{QGLWidget::resizeGL()}{resizeGL()} - to set up the projection and viewport, and - \l{QGLWidget::paintGL()}{paintGL()} to perform the OpenGL calls needed - to render the scene. However, it is possible to subclass QGLWidget - differently to allow 2D graphics, drawn using QPainter, to be - painted over a scene rendered using OpenGL. - - In this example, we demonstrate how this is done by reusing the code - from the \l{Hello GL Example}{Hello GL} example to provide a 3D scene, - and painting over it with some translucent 2D graphics. Instead of - examining each class in detail, we only cover the parts of the - \c GLWidget class that enable overpainting, and provide more detailed - discussion in the final section of this document. - - \section1 GLWidget Class Definition - - The \c GLWidget class is a subclass of QGLWidget, based on the one used - in the \l{Hello GL Example}{Hello GL} example. Rather than describe the - class as a whole, we show the first few lines of the class and only - discuss the changes we have made to the rest of it: - - \snippet overpainting/glwidget.h 0 - \dots - \snippet overpainting/glwidget.h 1 - \dots - \snippet overpainting/glwidget.h 4 - - As usual, the widget uses \l{QGLWidget::initializeGL()}{initializeGL()} - to set up geometry for our scene and perform OpenGL initialization tasks. - The \l{QGLWidget::resizeGL()}{resizeGL()} function is used to ensure that - the 3D graphics in the scene are transformed correctly to the 2D viewport - displayed in the widget. - - Instead of implementing \l{QGLWidget::paintGL()}{paintGL()} to handle updates - to the widget, we implement a normal QWidget::paintEvent(). This - allows us to mix OpenGL calls and QPainter operations in a controlled way. - - In this example, we also implement QWidget::showEvent() to help with the - initialization of the 2D graphics used. - - The new private member functions and variables relate exclusively to the - 2D graphics and animation. The \c animate() slot is called periodically by the - \c animationTimer to update the widget; the \c createBubbles() function - initializes the \c bubbles list with instances of a helper class used to - draw the animation; the \c drawInstructions() function is responsible for - a semi-transparent message that is also overpainted onto the OpenGL scene. - - \section1 GLWidget Class Implementation - - Again, we only show the parts of the \c GLWidget implementation that are - relevant to this example. In the constructor, we initialize a QTimer to - control the animation: - - \snippet overpainting/glwidget.cpp 0 - - We turn off the widget's \l{QWidget::autoFillBackground}{autoFillBackground} property to - instruct OpenGL not to paint a background for the widget when - \l{QPainter::begin()}{QPainter::begin()} is called. - - As in the \l{Hello GL Example}{Hello GL} example, the destructor is responsible - for freeing any OpenGL-related resources: - - \snippet overpainting/glwidget.cpp 1 - - The \c initializeGL() function is fairly minimal, only setting up the QtLogo - object used in the scene. See the \l{Hello GL Example}{Hello GL} example - for details of the QtLogo class. - - \snippet overpainting/glwidget.cpp 2 - - To cooperate fully with QPainter, we defer matrix stack operations and attribute - initialization until the widget needs to be updated. - - In this example, we implement \l{QWidget::paintEvent()}{paintEvent()} rather - than \l{QGLWidget::paintGL()}{paintGL()} to render - our scene. When drawing on a QGLWidget, the paint engine used by QPainter - performs certain operations that change the states of the OpenGL - implementation's matrix and property stacks. Therefore, it is necessary to - make all the OpenGL calls to display the 3D graphics before we construct - a QPainter to draw the 2D overlay. - - We render a 3D scene by setting up model and projection transformations - and other attributes. We use an OpenGL stack operation to preserve the - original matrix state, allowing us to recover it later: - - \snippet overpainting/glwidget.cpp 4 - - We define a color to use for the widget's background, and set up various - attributes that define how the scene will be rendered. - - \snippet overpainting/glwidget.cpp 6 - - We call the \c setupViewport() private function to set up the - projection used for the scene. This is unnecessary in OpenGL - examples that implement the \l{QGLWidget::paintGL()}{paintGL()} - function because the matrix stacks are usually unmodified between - calls to \l{QGLWidget::resizeGL()}{resizeGL()} and - \l{QGLWidget::paintGL()}{paintGL()}. - - Since the widget's background is not drawn by the system or by Qt, we use - an OpenGL call to paint it before positioning the object defined earlier - in the scene: - - \snippet overpainting/glwidget.cpp 7 - - Once the QtLogo object's draw method has been executed, the GL - states we changed and the matrix stack needs to be restored to its - original state at the start of this function before we can begin - overpainting: - - \snippet overpainting/glwidget.cpp 8 - - With the 3D graphics done, we construct a QPainter for use on the widget - and simply overpaint the widget with 2D graphics; in this case, using a - helper class to draw a number of translucent bubbles onto the widget, - and calling \c drawInstructions() to overlay some instructions: - - \snippet overpainting/glwidget.cpp 10 - - When QPainter::end() is called, suitable OpenGL-specific calls are made to - write the scene, and its additional contents, onto the widget. - - With \l{QGLWidget::paintGL()}{paintGL()} the - \l{QGLWidget::swapBuffers()}{swapBuffers()} call is done for us. But an explicit - call to swapBuffers() is still not required because in the - \l{QWidget::paintEvent()}{paintEvent()} method the QPainter on the OpenGL - widget takes care of this for us. - - The implementation of the \l{QGLWidget::resizeGL()}{resizeGL()} function - sets up the dimensions of the viewport and defines a projection - transformation: - - \snippet overpainting/glwidget.cpp 11 - - Ideally, we want to arrange the 2D graphics to suit the widget's dimensions. - To achieve this, we implement the \l{QWidget::showEvent()}{showEvent()} handler, - creating new graphic elements (bubbles) if necessary at appropriate positions - in the widget. - - \snippet overpainting/glwidget.cpp 12 - - This function only has an effect if less than 20 bubbles have already been - created. - - The \c animate() slot is called every time the widget's \c animationTimer emits - the \l{QTimer::timeout()}{timeout()} signal. This keeps the bubbles moving - around. - - \snippet overpainting/glwidget.cpp 13 - - We simply iterate over the bubbles in the \c bubbles list, updating the - widget before and after each of them is moved. - - The \c setupViewport() function is called from \c paintEvent() - and \c resizeGL(). - - \snippet overpainting/glwidget.cpp 14 - - The \c drawInstructions() function is used to prepare some basic - instructions that will be painted with the other 2D graphics over - the 3D scene. - - \snippet overpainting/glwidget.cpp 15 - - \section1 Summary - - When overpainting 2D content onto 3D content, we need to use a QPainter - \e and make OpenGL calls to achieve the desired effect. Since QPainter - itself uses OpenGL calls when used on a QGLWidget subclass, we need to - preserve the state of various OpenGL stacks when we perform our own - calls, using the following approach: - - \list - \li Reimplement QGLWidget::initializeGL(), but only perform minimal - initialization. QPainter will perform its own initialization - routines, modifying the matrix and property stacks, so it is better - to defer certain initialization tasks until just before you render - the 3D scene. - \li Reimplement QGLWidget::resizeGL() as in the pure 3D case. - \li Reimplement QWidget::paintEvent() to draw both 2D and 3D graphics. - \endlist - - The \l{QWidget::paintEvent()}{paintEvent()} implementation performs the - following tasks: - - \list - \li Push the current OpenGL modelview matrix onto a stack. - \li Perform initialization tasks usually done in the - \l{QGLWidget::initializeGL()}{initializeGL()} function. - \li Perform code that would normally be located in the widget's - \l{QGLWidget::resizeGL()}{resizeGL()} function to set the correct - perspective transformation and set up the viewport. - \li Render the scene using OpenGL calls. - \li Pop the OpenGL modelview matrix off the stack. - \li Construct a QPainter object. - \li Initialize it for use on the widget with the QPainter::begin() function. - \li Draw primitives using QPainter's member functions. - \li Call QPainter::end() to finish painting. - \endlist -*/ diff --git a/examples/opengl/doc/src/pbuffers2.qdoc b/examples/opengl/doc/src/pbuffers2.qdoc deleted file mode 100644 index 249b8fa25f..0000000000 --- a/examples/opengl/doc/src/pbuffers2.qdoc +++ /dev/null @@ -1,38 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the documentation of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:FDL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Free Documentation License Usage -** 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. Please review the following information to ensure -** the GNU Free Documentation License version 1.3 requirements -** will be met: http://www.gnu.org/copyleft/fdl.html. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -/*! - \example pbuffers2 - \title Pixel Buffers 2 Example - - \ingroup examples-widgets-opengl - \brief The Pixel Buffers 2 example demonstrates how to use the - QGLPixelBuffer class to render into an off-screen buffer and use - the contents as a dynamic texture in a QGLWidget. - - \image pbuffers2-example.png -*/ diff --git a/examples/opengl/doc/src/samplebuffers.qdoc b/examples/opengl/doc/src/samplebuffers.qdoc deleted file mode 100644 index 4d4d26450e..0000000000 --- a/examples/opengl/doc/src/samplebuffers.qdoc +++ /dev/null @@ -1,37 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the documentation of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:FDL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Free Documentation License Usage -** 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. Please review the following information to ensure -** the GNU Free Documentation License version 1.3 requirements -** will be met: http://www.gnu.org/copyleft/fdl.html. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -/*! - \example samplebuffers - \title Sample Buffers Example - - \ingroup examples-widgets-opengl - \brief The Sample Buffers example demonstrates how to use and enable - sample buffers in a QGLWidget. - - \image samplebuffers-example.png -*/ diff --git a/examples/opengl/hellogl2/glwidget.cpp b/examples/opengl/hellogl2/glwidget.cpp new file mode 100644 index 0000000000..c8db3047a1 --- /dev/null +++ b/examples/opengl/hellogl2/glwidget.cpp @@ -0,0 +1,283 @@ +/**************************************************************************** +** +** 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 <QMouseEvent> +#include <QOpenGLShaderProgram> +#include <QCoreApplication> +#include <math.h> + +GLWidget::GLWidget(QWidget *parent) + : QOpenGLWidget(parent), + m_xRot(0), + m_yRot(0), + m_zRot(0), + m_program(0) +{ + m_core = QCoreApplication::arguments().contains(QStringLiteral("--coreprofile")); +} + +GLWidget::~GLWidget() +{ + cleanup(); +} + +QSize GLWidget::minimumSizeHint() const +{ + return QSize(50, 50); +} + +QSize GLWidget::sizeHint() const +{ + return QSize(400, 400); +} + +static void qNormalizeAngle(int &angle) +{ + while (angle < 0) + angle += 360 * 16; + while (angle > 360 * 16) + angle -= 360 * 16; +} + +void GLWidget::setXRotation(int angle) +{ + qNormalizeAngle(angle); + if (angle != m_xRot) { + m_xRot = angle; + emit xRotationChanged(angle); + update(); + } +} + +void GLWidget::setYRotation(int angle) +{ + qNormalizeAngle(angle); + if (angle != m_yRot) { + m_yRot = angle; + emit yRotationChanged(angle); + update(); + } +} + +void GLWidget::setZRotation(int angle) +{ + qNormalizeAngle(angle); + if (angle != m_zRot) { + m_zRot = angle; + emit zRotationChanged(angle); + update(); + } +} + +void GLWidget::cleanup() +{ + makeCurrent(); + m_logoVbo.destroy(); + delete m_program; + m_program = 0; + doneCurrent(); +} + +static const char *vertexShaderSourceCore = + "#version 150\n" + "in vec4 vertex;\n" + "in vec3 normal;\n" + "out vec3 vert;\n" + "out vec3 vertNormal;\n" + "uniform mat4 projMatrix;\n" + "uniform mat4 mvMatrix;\n" + "uniform mat3 normalMatrix;\n" + "void main() {\n" + " vert = vertex.xyz;\n" + " vertNormal = normalMatrix * normal;\n" + " gl_Position = projMatrix * mvMatrix * vertex;\n" + "}\n"; + +static const char *fragmentShaderSourceCore = + "#version 150\n" + "in highp vec3 vert;\n" + "in highp vec3 vertNormal;\n" + "out highp vec4 fragColor;\n" + "uniform highp vec3 lightPos;\n" + "void main() {\n" + " highp vec3 L = normalize(lightPos - vert);\n" + " highp float NL = max(dot(normalize(vertNormal), L), 0.0);\n" + " highp vec3 color = vec3(0.39, 1.0, 0.0);\n" + " highp vec3 col = clamp(color * 0.2 + color * 0.8 * NL, 0.0, 1.0);\n" + " fragColor = vec4(col, 1.0);\n" + "}\n"; + +static const char *vertexShaderSource = + "attribute vec4 vertex;\n" + "attribute vec3 normal;\n" + "varying vec3 vert;\n" + "varying vec3 vertNormal;\n" + "uniform mat4 projMatrix;\n" + "uniform mat4 mvMatrix;\n" + "uniform mat3 normalMatrix;\n" + "void main() {\n" + " vert = vertex.xyz;\n" + " vertNormal = normalMatrix * normal;\n" + " gl_Position = projMatrix * mvMatrix * vertex;\n" + "}\n"; + +static const char *fragmentShaderSource = + "varying highp vec3 vert;\n" + "varying highp vec3 vertNormal;\n" + "uniform highp vec3 lightPos;\n" + "void main() {\n" + " highp vec3 L = normalize(lightPos - vert);\n" + " highp float NL = max(dot(normalize(vertNormal), L), 0.0);\n" + " highp vec3 color = vec3(0.39, 1.0, 0.0);\n" + " highp vec3 col = clamp(color * 0.2 + color * 0.8 * NL, 0.0, 1.0);\n" + " gl_FragColor = vec4(col, 1.0);\n" + "}\n"; + +void GLWidget::initializeGL() +{ + // In this example the widget's corresponding top-level window can change + // several times during the widget's lifetime. Whenever this happens, the + // QOpenGLWidget's associated context is destroyed and a new one is created. + // Therefore we have to be prepared to clean up the resources on the + // aboutToBeDestroyed() signal, instead of the destructor. The emission of + // the signal will be followed by an invocation of initializeGL() where we + // can recreate all resources. + connect(context(), &QOpenGLContext::aboutToBeDestroyed, this, &GLWidget::cleanup); + + initializeOpenGLFunctions(); + + m_program = new QOpenGLShaderProgram; + m_program->addShaderFromSourceCode(QOpenGLShader::Vertex, m_core ? vertexShaderSourceCore : vertexShaderSource); + m_program->addShaderFromSourceCode(QOpenGLShader::Fragment, m_core ? fragmentShaderSourceCore : fragmentShaderSource); + m_program->bindAttributeLocation("vertex", 0); + m_program->bindAttributeLocation("normal", 1); + m_program->link(); + + m_program->bind(); + m_projMatrixLoc = m_program->uniformLocation("projMatrix"); + m_mvMatrixLoc = m_program->uniformLocation("mvMatrix"); + m_normalMatrixLoc = m_program->uniformLocation("normalMatrix"); + m_lightPosLoc = m_program->uniformLocation("lightPos"); + + // Create a vertex array object. In OpenGL ES 2.0 and OpenGL 2.x + // implementations this is optional and support may not be present + // at all. Nonetheless the below code works in all cases and makes + // sure there is a VAO when one is needed. + m_vao.create(); + QOpenGLVertexArrayObject::Binder vaoBinder(&m_vao); + + // Setup our vertex buffer object. + m_logoVbo.create(); + m_logoVbo.bind(); + m_logoVbo.allocate(m_logo.constData(), m_logo.count() * sizeof(GLfloat)); + + // Store the vertex attribute bindings for the program. + setupVertexAttribs(); + + // Our camera never changes in this example. + m_camera.setToIdentity(); + m_camera.translate(0, 0, -1); + + // Light position is fixed. + m_program->setUniformValue(m_lightPosLoc, QVector3D(0, 0, 70)); + + m_program->release(); +} + +void GLWidget::setupVertexAttribs() +{ + m_logoVbo.bind(); + QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions(); + f->glEnableVertexAttribArray(0); + f->glEnableVertexAttribArray(1); + f->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), 0); + f->glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), reinterpret_cast<void *>(3 * sizeof(GLfloat))); + m_logoVbo.release(); +} + +void GLWidget::paintGL() +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glEnable(GL_DEPTH_TEST); + glEnable(GL_CULL_FACE); + + m_world.setToIdentity(); + m_world.rotate(180.0f - (m_xRot / 16.0f), 1, 0, 0); + m_world.rotate(m_yRot / 16.0f, 0, 1, 0); + m_world.rotate(m_zRot / 16.0f, 0, 0, 1); + + QOpenGLVertexArrayObject::Binder vaoBinder(&m_vao); + m_program->bind(); + m_program->setUniformValue(m_projMatrixLoc, m_proj); + m_program->setUniformValue(m_mvMatrixLoc, m_camera * m_world); + QMatrix3x3 normalMatrix = m_world.normalMatrix(); + m_program->setUniformValue(m_normalMatrixLoc, normalMatrix); + + glDrawArrays(GL_TRIANGLES, 0, m_logo.vertexCount()); + + m_program->release(); +} + +void GLWidget::resizeGL(int w, int h) +{ + m_proj.setToIdentity(); + m_proj.perspective(45.0f, GLfloat(w) / h, 0.01f, 100.0f); +} + +void GLWidget::mousePressEvent(QMouseEvent *event) +{ + m_lastPos = event->pos(); +} + +void GLWidget::mouseMoveEvent(QMouseEvent *event) +{ + int dx = event->x() - m_lastPos.x(); + int dy = event->y() - m_lastPos.y(); + + if (event->buttons() & Qt::LeftButton) { + setXRotation(m_xRot + 8 * dy); + setYRotation(m_yRot + 8 * dx); + } else if (event->buttons() & Qt::RightButton) { + setXRotation(m_xRot + 8 * dy); + setZRotation(m_zRot + 8 * dx); + } + m_lastPos = event->pos(); +} diff --git a/examples/opengl/hellogl2/glwidget.h b/examples/opengl/hellogl2/glwidget.h new file mode 100644 index 0000000000..fcc6225999 --- /dev/null +++ b/examples/opengl/hellogl2/glwidget.h @@ -0,0 +1,103 @@ +/**************************************************************************** +** +** 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 <QOpenGLVertexArrayObject> +#include <QOpenGLBuffer> +#include <QMatrix4x4> +#include "logo.h" + +QT_FORWARD_DECLARE_CLASS(QOpenGLShaderProgram) + +class GLWidget : public QOpenGLWidget, protected QOpenGLFunctions +{ + Q_OBJECT + +public: + GLWidget(QWidget *parent = 0); + ~GLWidget(); + + QSize minimumSizeHint() const Q_DECL_OVERRIDE; + QSize sizeHint() const Q_DECL_OVERRIDE; + +public slots: + void setXRotation(int angle); + void setYRotation(int angle); + void setZRotation(int angle); + void cleanup(); + +signals: + void xRotationChanged(int angle); + void yRotationChanged(int angle); + void zRotationChanged(int angle); + +protected: + void initializeGL() Q_DECL_OVERRIDE; + void paintGL() Q_DECL_OVERRIDE; + void resizeGL(int width, int height) Q_DECL_OVERRIDE; + void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE; + void mouseMoveEvent(QMouseEvent *event) Q_DECL_OVERRIDE; + +private: + void setupVertexAttribs(); + + bool m_core; + int m_xRot; + int m_yRot; + int m_zRot; + QPoint m_lastPos; + Logo m_logo; + QOpenGLVertexArrayObject m_vao; + QOpenGLBuffer m_logoVbo; + QOpenGLShaderProgram *m_program; + int m_projMatrixLoc; + int m_mvMatrixLoc; + int m_normalMatrixLoc; + int m_lightPosLoc; + QMatrix4x4 m_proj; + QMatrix4x4 m_camera; + QMatrix4x4 m_world; +}; + +#endif diff --git a/examples/opengl/hellogl2/hellogl2.pro b/examples/opengl/hellogl2/hellogl2.pro new file mode 100644 index 0000000000..3a52e04d74 --- /dev/null +++ b/examples/opengl/hellogl2/hellogl2.pro @@ -0,0 +1,15 @@ +HEADERS = glwidget.h \ + window.h \ + mainwindow.h \ + logo.h +SOURCES = glwidget.cpp \ + main.cpp \ + window.cpp \ + mainwindow.cpp \ + logo.cpp + +QT += widgets + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/opengl/hellogl2 +INSTALLS += target diff --git a/examples/opengl/hellogl2/logo.cpp b/examples/opengl/hellogl2/logo.cpp new file mode 100644 index 0000000000..1ba47ddfb5 --- /dev/null +++ b/examples/opengl/hellogl2/logo.cpp @@ -0,0 +1,141 @@ +/**************************************************************************** +** +** 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 "logo.h" +#include <qmath.h> + +Logo::Logo() + : m_count(0) +{ + m_data.resize(2500 * 6); + + const GLfloat x1 = +0.06f; + const GLfloat y1 = -0.14f; + const GLfloat x2 = +0.14f; + const GLfloat y2 = -0.06f; + const GLfloat x3 = +0.08f; + const GLfloat y3 = +0.00f; + const GLfloat x4 = +0.30f; + const GLfloat 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 int NumSectors = 100; + + for (int i = 0; i < NumSectors; ++i) { + GLfloat angle = (i * 2 * M_PI) / NumSectors; + GLfloat angleSin = qSin(angle); + GLfloat angleCos = qCos(angle); + const GLfloat x5 = 0.30f * angleSin; + const GLfloat y5 = 0.30f * angleCos; + const GLfloat x6 = 0.20f * angleSin; + const GLfloat y6 = 0.20f * angleCos; + + angle = ((i + 1) * 2 * M_PI) / NumSectors; + angleSin = qSin(angle); + angleCos = qCos(angle); + const GLfloat x7 = 0.20f * angleSin; + const GLfloat y7 = 0.20f * angleCos; + const GLfloat x8 = 0.30f * angleSin; + const GLfloat y8 = 0.30f * angleCos; + + quad(x5, y5, x6, y6, x7, y7, x8, y8); + + extrude(x6, y6, x7, y7); + extrude(x8, y8, x5, y5); + } +} + +void Logo::add(const QVector3D &v, const QVector3D &n) +{ + GLfloat *p = m_data.data() + m_count; + *p++ = v.x(); + *p++ = v.y(); + *p++ = v.z(); + *p++ = n.x(); + *p++ = n.y(); + *p++ = n.z(); + m_count += 6; +} + +void Logo::quad(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2, GLfloat x3, GLfloat y3, GLfloat x4, GLfloat y4) +{ + QVector3D n = QVector3D::normal(QVector3D(x4 - x1, y4 - y1, 0.0f), QVector3D(x2 - x1, y2 - y1, 0.0f)); + + add(QVector3D(x1, y1, -0.05f), n); + add(QVector3D(x4, y4, -0.05f), n); + add(QVector3D(x2, y2, -0.05f), n); + + add(QVector3D(x3, y3, -0.05f), n); + add(QVector3D(x2, y2, -0.05f), n); + add(QVector3D(x4, y4, -0.05f), n); + + n = QVector3D::normal(QVector3D(x1 - x4, y1 - y4, 0.0f), QVector3D(x2 - x4, y2 - y4, 0.0f)); + + add(QVector3D(x4, y4, 0.05f), n); + add(QVector3D(x1, y1, 0.05f), n); + add(QVector3D(x2, y2, 0.05f), n); + + add(QVector3D(x2, y2, 0.05f), n); + add(QVector3D(x3, y3, 0.05f), n); + add(QVector3D(x4, y4, 0.05f), n); +} + +void Logo::extrude(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2) +{ + QVector3D n = QVector3D::normal(QVector3D(0.0f, 0.0f, -0.1f), QVector3D(x2 - x1, y2 - y1, 0.0f)); + + add(QVector3D(x1, y1, +0.05f), n); + add(QVector3D(x1, y1, -0.05f), n); + add(QVector3D(x2, y2, +0.05f), n); + + add(QVector3D(x2, y2, -0.05f), n); + add(QVector3D(x2, y2, +0.05f), n); + add(QVector3D(x1, y1, -0.05f), n); +} diff --git a/examples/opengl/hellogl2/logo.h b/examples/opengl/hellogl2/logo.h new file mode 100644 index 0000000000..29bb7fa241 --- /dev/null +++ b/examples/opengl/hellogl2/logo.h @@ -0,0 +1,65 @@ +/**************************************************************************** +** +** 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 LOGO_H +#define LOGO_H + +#include <qopengl.h> +#include <QVector> +#include <QVector3D> + +class Logo +{ +public: + Logo(); + const GLfloat *constData() const { return m_data.constData(); } + int count() const { return m_count; } + int vertexCount() const { return m_count / 6; } + +private: + void quad(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2, GLfloat x3, GLfloat y3, GLfloat x4, GLfloat y4); + void extrude(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2); + void add(const QVector3D &v, const QVector3D &n); + + QVector<GLfloat> m_data; + int m_count; +}; + +#endif // LOGO_H diff --git a/examples/opengl/hellogl2/main.cpp b/examples/opengl/hellogl2/main.cpp new file mode 100644 index 0000000000..2d439878e4 --- /dev/null +++ b/examples/opengl/hellogl2/main.cpp @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** 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 <QDesktopWidget> +#include <QSurfaceFormat> + +#include "mainwindow.h" + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + + QSurfaceFormat fmt; + fmt.setDepthBufferSize(24); + if (QCoreApplication::arguments().contains(QStringLiteral("--multisample"))) + fmt.setSamples(4); + if (QCoreApplication::arguments().contains(QStringLiteral("--coreprofile"))) { + fmt.setVersion(3, 2); + fmt.setProfile(QSurfaceFormat::CoreProfile); + } + QSurfaceFormat::setDefaultFormat(fmt); + + MainWindow mainWindow; + mainWindow.resize(mainWindow.sizeHint()); + int desktopArea = QApplication::desktop()->width() * + QApplication::desktop()->height(); + int widgetArea = mainWindow.width() * mainWindow.height(); + if (((float)widgetArea / (float)desktopArea) < 0.75f) + mainWindow.show(); + else + mainWindow.showMaximized(); + return app.exec(); +} diff --git a/examples/opengl/hellogl2/mainwindow.cpp b/examples/opengl/hellogl2/mainwindow.cpp new file mode 100644 index 0000000000..ee85cda35c --- /dev/null +++ b/examples/opengl/hellogl2/mainwindow.cpp @@ -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$ +** +****************************************************************************/ + +#include "mainwindow.h" +#include "window.h" +#include <QMenuBar> +#include <QMenu> +#include <QMessageBox> + +MainWindow::MainWindow() +{ + QMenuBar *menuBar = new QMenuBar; + QMenu *menuWindow = menuBar->addMenu(tr("&Window")); + QAction *addNew = new QAction(menuWindow); + addNew->setText(tr("Add new")); + menuWindow->addAction(addNew); + connect(addNew, SIGNAL(triggered()), this, SLOT(onAddNew())); + setMenuBar(menuBar); + + onAddNew(); +} + +void MainWindow::onAddNew() +{ + if (!centralWidget()) + setCentralWidget(new Window(this)); + else + QMessageBox::information(0, tr("Cannot add new window"), tr("Already occupied. Undock first.")); +} diff --git a/examples/opengl/hellogl2/mainwindow.h b/examples/opengl/hellogl2/mainwindow.h new file mode 100644 index 0000000000..53d4555ce8 --- /dev/null +++ b/examples/opengl/hellogl2/mainwindow.h @@ -0,0 +1,57 @@ +/**************************************************************************** +** +** 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> + +class MainWindow : public QMainWindow +{ + Q_OBJECT + +public: + MainWindow(); + +private slots: + void onAddNew(); +}; + +#endif diff --git a/examples/opengl/hellogl2/window.cpp b/examples/opengl/hellogl2/window.cpp new file mode 100644 index 0000000000..0b20870487 --- /dev/null +++ b/examples/opengl/hellogl2/window.cpp @@ -0,0 +1,133 @@ +/**************************************************************************** +** +** 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 "window.h" +#include "mainwindow.h" +#include <QSlider> +#include <QVBoxLayout> +#include <QHBoxLayout> +#include <QKeyEvent> +#include <QPushButton> +#include <QDesktopWidget> +#include <QApplication> +#include <QMessageBox> + +Window::Window(MainWindow *mw) + : mainWindow(mw) +{ + glWidget = new GLWidget; + + xSlider = createSlider(); + ySlider = createSlider(); + zSlider = createSlider(); + + connect(xSlider, SIGNAL(valueChanged(int)), glWidget, SLOT(setXRotation(int))); + connect(glWidget, SIGNAL(xRotationChanged(int)), xSlider, SLOT(setValue(int))); + connect(ySlider, SIGNAL(valueChanged(int)), glWidget, SLOT(setYRotation(int))); + connect(glWidget, SIGNAL(yRotationChanged(int)), ySlider, SLOT(setValue(int))); + connect(zSlider, SIGNAL(valueChanged(int)), glWidget, SLOT(setZRotation(int))); + connect(glWidget, SIGNAL(zRotationChanged(int)), zSlider, SLOT(setValue(int))); + + QVBoxLayout *mainLayout = new QVBoxLayout; + QHBoxLayout *container = new QHBoxLayout; + container->addWidget(glWidget); + container->addWidget(xSlider); + container->addWidget(ySlider); + container->addWidget(zSlider); + + QWidget *w = new QWidget; + w->setLayout(container); + mainLayout->addWidget(w); + dockBtn = new QPushButton(tr("Undock"), this); + connect(dockBtn, SIGNAL(clicked()), this, SLOT(dockUndock())); + mainLayout->addWidget(dockBtn); + + setLayout(mainLayout); + + xSlider->setValue(15 * 16); + ySlider->setValue(345 * 16); + zSlider->setValue(0 * 16); + + setWindowTitle(tr("Hello GL")); +} + +QSlider *Window::createSlider() +{ + QSlider *slider = new QSlider(Qt::Vertical); + slider->setRange(0, 360 * 16); + slider->setSingleStep(16); + slider->setPageStep(15 * 16); + slider->setTickInterval(15 * 16); + slider->setTickPosition(QSlider::TicksRight); + return slider; +} + +void Window::keyPressEvent(QKeyEvent *e) +{ + if (e->key() == Qt::Key_Escape) + close(); + else + QWidget::keyPressEvent(e); +} + +void Window::dockUndock() +{ + if (parent()) { + setParent(0); + setAttribute(Qt::WA_DeleteOnClose); + move(QApplication::desktop()->width() / 2 - width() / 2, + QApplication::desktop()->height() / 2 - height() / 2); + dockBtn->setText(tr("Dock")); + show(); + } else { + if (!mainWindow->centralWidget()) { + if (mainWindow->isVisible()) { + setAttribute(Qt::WA_DeleteOnClose, false); + dockBtn->setText(tr("Undock")); + mainWindow->setCentralWidget(this); + } else { + QMessageBox::information(0, tr("Cannot dock"), tr("Main window already closed")); + } + } else { + QMessageBox::information(0, tr("Cannot dock"), tr("Main window already occupied")); + } + } +} diff --git a/examples/opengl/hellogl2/window.h b/examples/opengl/hellogl2/window.h new file mode 100644 index 0000000000..a850bd6a5a --- /dev/null +++ b/examples/opengl/hellogl2/window.h @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** 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 WINDOW_H +#define WINDOW_H + +#include <QWidget> + +QT_BEGIN_NAMESPACE +class QSlider; +class QPushButton; +QT_END_NAMESPACE + +class GLWidget; +class MainWindow; + +class Window : public QWidget +{ + Q_OBJECT + +public: + Window(MainWindow *mw); + +protected: + void keyPressEvent(QKeyEvent *event) Q_DECL_OVERRIDE; + +private slots: + void dockUndock(); + +private: + QSlider *createSlider(); + + GLWidget *glWidget; + QSlider *xSlider; + QSlider *ySlider; + QSlider *zSlider; + QPushButton *dockBtn; + MainWindow *mainWindow; +}; + +#endif diff --git a/examples/opengl/hellowindow/hellowindow.cpp b/examples/opengl/hellowindow/hellowindow.cpp index b4dc4464ba..da31fee920 100644 --- a/examples/opengl/hellowindow/hellowindow.cpp +++ b/examples/opengl/hellowindow/hellowindow.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** 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. @@ -145,29 +145,18 @@ void Renderer::render() QOpenGLFunctions *f = m_context->functions(); f->glViewport(0, 0, viewSize.width() * surface->devicePixelRatio(), viewSize.height() * surface->devicePixelRatio()); - - f->glClearColor(0.1f, 0.1f, 0.2f, 1.0f); f->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - f->glFrontFace(GL_CW); - f->glCullFace(GL_FRONT); - f->glEnable(GL_CULL_FACE); - f->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.translate(0.0f, -0.2f, 0.0f); - m_program->bind(); m_program->setUniformValue(matrixUniform, modelview); m_program->setUniformValue(colorUniform, color); - paintQtLogo(); - m_program->release(); - f->glDisable(GL_DEPTH_TEST); - f->glDisable(GL_CULL_FACE); + m_context->functions()->glDrawArrays(GL_TRIANGLES, 0, vertices.size()); m_context->swapBuffers(surface); @@ -176,17 +165,6 @@ void Renderer::render() QTimer::singleShot(0, this, SLOT(render())); } -void Renderer::paintQtLogo() -{ - m_program->enableAttributeArray(normalAttr); - m_program->enableAttributeArray(vertexAttr); - m_program->setAttributeArray(vertexAttr, vertices.constData()); - m_program->setAttributeArray(normalAttr, normals.constData()); - m_context->functions()->glDrawArrays(GL_TRIANGLES, 0, vertices.size()); - m_program->disableAttributeArray(normalAttr); - m_program->disableAttributeArray(vertexAttr); -} - void Renderer::initialize() { QOpenGLShader *vshader = new QOpenGLShader(QOpenGLShader::Vertex, this); @@ -218,6 +196,7 @@ void Renderer::initialize() m_program->addShader(vshader); m_program->addShader(fshader); m_program->link(); + m_program->bind(); vertexAttr = m_program->attributeLocation("vertex"); normalAttr = m_program->attributeLocation("normal"); @@ -226,6 +205,25 @@ void Renderer::initialize() m_fAngle = 0; createGeometry(); + + m_vbo.create(); + m_vbo.bind(); + const int verticesSize = vertices.count() * 3 * sizeof(GLfloat); + m_vbo.allocate(verticesSize * 2); + m_vbo.write(0, vertices.constData(), verticesSize); + m_vbo.write(verticesSize, normals.constData(), verticesSize); + + QOpenGLFunctions *f = m_context->functions(); + f->glClearColor(0.1f, 0.1f, 0.2f, 1.0f); + f->glFrontFace(GL_CW); + f->glCullFace(GL_FRONT); + f->glEnable(GL_CULL_FACE); + f->glEnable(GL_DEPTH_TEST); + + m_program->enableAttributeArray(vertexAttr); + m_program->enableAttributeArray(normalAttr); + m_program->setAttributeBuffer(vertexAttr, GL_FLOAT, 0, 3); + m_program->setAttributeBuffer(normalAttr, GL_FLOAT, verticesSize, 3); } void Renderer::createGeometry() diff --git a/examples/opengl/hellowindow/hellowindow.h b/examples/opengl/hellowindow/hellowindow.h index 9fb7d109b9..6a6fa275e2 100644 --- a/examples/opengl/hellowindow/hellowindow.h +++ b/examples/opengl/hellowindow/hellowindow.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** 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. @@ -43,6 +43,7 @@ #include <QColor> #include <QMutex> #include <QOpenGLShaderProgram> +#include <QOpenGLBuffer> #include <QSharedPointer> #include <QTimer> @@ -65,13 +66,13 @@ private slots: private: void initialize(); - qreal m_fAngle; - bool m_showBubbles; - 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); + + qreal m_fAngle; + QVector<QVector3D> vertices; QVector<QVector3D> normals; int vertexAttr; @@ -83,6 +84,7 @@ private: QSurfaceFormat m_format; QOpenGLContext *m_context; QOpenGLShaderProgram *m_program; + QOpenGLBuffer m_vbo; QList<HelloWindow *> m_windows; int m_currentWindow; diff --git a/examples/opengl/hellowindow/main.cpp b/examples/opengl/hellowindow/main.cpp index 5b2552ee3e..62b6bfca3f 100644 --- a/examples/opengl/hellowindow/main.cpp +++ b/examples/opengl/hellowindow/main.cpp @@ -41,7 +41,6 @@ #include "hellowindow.h" #include <qpa/qplatformintegration.h> -#include <private/qguiapplication_p.h> #include <QGuiApplication> #include <QScreen> @@ -51,10 +50,7 @@ int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); - QPlatformIntegration *integ = QGuiApplicationPrivate::platformIntegration(); - const bool multipleWindows = integ->hasCapability(QPlatformIntegration::ThreadedOpenGL) - && integ->hasCapability(QPlatformIntegration::WindowManagement) - && !QGuiApplication::arguments().contains(QStringLiteral("--single")); + const bool multipleWindows = QGuiApplication::arguments().contains(QStringLiteral("--multiple")); QScreen *screen = QGuiApplication::primaryScreen(); diff --git a/examples/opengl/legacy/README b/examples/opengl/legacy/README new file mode 100644 index 0000000000..8d6cbdef2a --- /dev/null +++ b/examples/opengl/legacy/README @@ -0,0 +1,4 @@ +This directory contains legacy examples that use the fixed pipeline +and thus are not compatible with OpenGL ES 2.0+ and the core profile of +OpenGL 3.0+. They also rely on the Qt OpenGL module (e.g. QGLWidget) which +is not advisable in new application. diff --git a/examples/opengl/framebufferobject2/cubelogo.png b/examples/opengl/legacy/framebufferobject2/cubelogo.png Binary files differindex 3ae0f9ba3f..3ae0f9ba3f 100644 --- a/examples/opengl/framebufferobject2/cubelogo.png +++ b/examples/opengl/legacy/framebufferobject2/cubelogo.png diff --git a/examples/opengl/framebufferobject2/framebufferobject2.pro b/examples/opengl/legacy/framebufferobject2/framebufferobject2.pro index e0067cf27f..e0067cf27f 100644 --- a/examples/opengl/framebufferobject2/framebufferobject2.pro +++ b/examples/opengl/legacy/framebufferobject2/framebufferobject2.pro diff --git a/examples/opengl/framebufferobject2/framebufferobject2.qrc b/examples/opengl/legacy/framebufferobject2/framebufferobject2.qrc index 9fc1a56a1a..9fc1a56a1a 100644 --- a/examples/opengl/framebufferobject2/framebufferobject2.qrc +++ b/examples/opengl/legacy/framebufferobject2/framebufferobject2.qrc diff --git a/examples/opengl/framebufferobject2/glwidget.cpp b/examples/opengl/legacy/framebufferobject2/glwidget.cpp index 32b9799a4a..32b9799a4a 100644 --- a/examples/opengl/framebufferobject2/glwidget.cpp +++ b/examples/opengl/legacy/framebufferobject2/glwidget.cpp diff --git a/examples/opengl/framebufferobject2/glwidget.h b/examples/opengl/legacy/framebufferobject2/glwidget.h index 2991a4fdf2..2991a4fdf2 100644 --- a/examples/opengl/framebufferobject2/glwidget.h +++ b/examples/opengl/legacy/framebufferobject2/glwidget.h diff --git a/examples/opengl/framebufferobject2/main.cpp b/examples/opengl/legacy/framebufferobject2/main.cpp index 4c9aa9840f..4c9aa9840f 100644 --- a/examples/opengl/framebufferobject2/main.cpp +++ b/examples/opengl/legacy/framebufferobject2/main.cpp diff --git a/examples/opengl/grabber/glwidget.cpp b/examples/opengl/legacy/grabber/glwidget.cpp index abe3a8540a..abe3a8540a 100644 --- a/examples/opengl/grabber/glwidget.cpp +++ b/examples/opengl/legacy/grabber/glwidget.cpp diff --git a/examples/opengl/grabber/glwidget.h b/examples/opengl/legacy/grabber/glwidget.h index 12071be173..12071be173 100644 --- a/examples/opengl/grabber/glwidget.h +++ b/examples/opengl/legacy/grabber/glwidget.h diff --git a/examples/opengl/grabber/grabber.pro b/examples/opengl/legacy/grabber/grabber.pro index b8567580f0..b8567580f0 100644 --- a/examples/opengl/grabber/grabber.pro +++ b/examples/opengl/legacy/grabber/grabber.pro diff --git a/examples/opengl/grabber/main.cpp b/examples/opengl/legacy/grabber/main.cpp index 145e4120ef..145e4120ef 100644 --- a/examples/opengl/grabber/main.cpp +++ b/examples/opengl/legacy/grabber/main.cpp diff --git a/examples/opengl/grabber/mainwindow.cpp b/examples/opengl/legacy/grabber/mainwindow.cpp index 9f82ee10ba..9f82ee10ba 100644 --- a/examples/opengl/grabber/mainwindow.cpp +++ b/examples/opengl/legacy/grabber/mainwindow.cpp diff --git a/examples/opengl/grabber/mainwindow.h b/examples/opengl/legacy/grabber/mainwindow.h index a7895bf4c4..a7895bf4c4 100644 --- a/examples/opengl/grabber/mainwindow.h +++ b/examples/opengl/legacy/grabber/mainwindow.h diff --git a/examples/opengl/hellogl/glwidget.cpp b/examples/opengl/legacy/hellogl/glwidget.cpp index 3a9faaca5f..3a9faaca5f 100644 --- a/examples/opengl/hellogl/glwidget.cpp +++ b/examples/opengl/legacy/hellogl/glwidget.cpp diff --git a/examples/opengl/hellogl/glwidget.h b/examples/opengl/legacy/hellogl/glwidget.h index 0989be1dc6..0989be1dc6 100644 --- a/examples/opengl/hellogl/glwidget.h +++ b/examples/opengl/legacy/hellogl/glwidget.h diff --git a/examples/opengl/hellogl/hellogl.pro b/examples/opengl/legacy/hellogl/hellogl.pro index 500bd85b3c..500bd85b3c 100644 --- a/examples/opengl/hellogl/hellogl.pro +++ b/examples/opengl/legacy/hellogl/hellogl.pro diff --git a/examples/opengl/hellogl/main.cpp b/examples/opengl/legacy/hellogl/main.cpp index 2e83a11e95..2e83a11e95 100644 --- a/examples/opengl/hellogl/main.cpp +++ b/examples/opengl/legacy/hellogl/main.cpp diff --git a/examples/opengl/hellogl/window.cpp b/examples/opengl/legacy/hellogl/window.cpp index 2a85bbec57..2a85bbec57 100644 --- a/examples/opengl/hellogl/window.cpp +++ b/examples/opengl/legacy/hellogl/window.cpp diff --git a/examples/opengl/hellogl/window.h b/examples/opengl/legacy/hellogl/window.h index 900e6b13fc..900e6b13fc 100644 --- a/examples/opengl/hellogl/window.h +++ b/examples/opengl/legacy/hellogl/window.h diff --git a/examples/opengl/legacy/legacy.pro b/examples/opengl/legacy/legacy.pro new file mode 100644 index 0000000000..0a74d50f7f --- /dev/null +++ b/examples/opengl/legacy/legacy.pro @@ -0,0 +1,16 @@ +requires(qtHaveModule(opengl)) + +TEMPLATE = subdirs + +!contains(QT_CONFIG, dynamicgl): !contains(QT_CONFIG, opengles2) { + # legacy desktop-only examples, no dynamic GL support + SUBDIRS = \ + grabber \ + hellogl \ + overpainting \ + pbuffers \ + framebufferobject2 \ + samplebuffers +} + +EXAMPLE_FILES = shared diff --git a/examples/opengl/overpainting/bubble.cpp b/examples/opengl/legacy/overpainting/bubble.cpp index dbcb72bc93..dbcb72bc93 100644 --- a/examples/opengl/overpainting/bubble.cpp +++ b/examples/opengl/legacy/overpainting/bubble.cpp diff --git a/examples/opengl/overpainting/bubble.h b/examples/opengl/legacy/overpainting/bubble.h index 10d24b8af7..10d24b8af7 100644 --- a/examples/opengl/overpainting/bubble.h +++ b/examples/opengl/legacy/overpainting/bubble.h diff --git a/examples/opengl/overpainting/glwidget.cpp b/examples/opengl/legacy/overpainting/glwidget.cpp index 420ae3e881..420ae3e881 100644 --- a/examples/opengl/overpainting/glwidget.cpp +++ b/examples/opengl/legacy/overpainting/glwidget.cpp diff --git a/examples/opengl/overpainting/glwidget.h b/examples/opengl/legacy/overpainting/glwidget.h index 1d1d48458d..1d1d48458d 100644 --- a/examples/opengl/overpainting/glwidget.h +++ b/examples/opengl/legacy/overpainting/glwidget.h diff --git a/examples/opengl/overpainting/main.cpp b/examples/opengl/legacy/overpainting/main.cpp index 57c520b528..57c520b528 100644 --- a/examples/opengl/overpainting/main.cpp +++ b/examples/opengl/legacy/overpainting/main.cpp diff --git a/examples/opengl/overpainting/overpainting.pro b/examples/opengl/legacy/overpainting/overpainting.pro index c1bda7853d..c1bda7853d 100644 --- a/examples/opengl/overpainting/overpainting.pro +++ b/examples/opengl/legacy/overpainting/overpainting.pro diff --git a/examples/opengl/pbuffers/cube.cpp b/examples/opengl/legacy/pbuffers/cube.cpp index dc1bb23fea..dc1bb23fea 100644 --- a/examples/opengl/pbuffers/cube.cpp +++ b/examples/opengl/legacy/pbuffers/cube.cpp diff --git a/examples/opengl/pbuffers/cube.h b/examples/opengl/legacy/pbuffers/cube.h index 05017cb376..05017cb376 100644 --- a/examples/opengl/pbuffers/cube.h +++ b/examples/opengl/legacy/pbuffers/cube.h diff --git a/examples/opengl/pbuffers/cubelogo.png b/examples/opengl/legacy/pbuffers/cubelogo.png Binary files differindex 3ae0f9ba3f..3ae0f9ba3f 100644 --- a/examples/opengl/pbuffers/cubelogo.png +++ b/examples/opengl/legacy/pbuffers/cubelogo.png diff --git a/examples/opengl/pbuffers/glwidget.cpp b/examples/opengl/legacy/pbuffers/glwidget.cpp index b319951ccd..b319951ccd 100644 --- a/examples/opengl/pbuffers/glwidget.cpp +++ b/examples/opengl/legacy/pbuffers/glwidget.cpp diff --git a/examples/opengl/pbuffers/glwidget.h b/examples/opengl/legacy/pbuffers/glwidget.h index 1d23b7772a..1d23b7772a 100644 --- a/examples/opengl/pbuffers/glwidget.h +++ b/examples/opengl/legacy/pbuffers/glwidget.h diff --git a/examples/opengl/pbuffers/main.cpp b/examples/opengl/legacy/pbuffers/main.cpp index 8be6640e92..8be6640e92 100644 --- a/examples/opengl/pbuffers/main.cpp +++ b/examples/opengl/legacy/pbuffers/main.cpp diff --git a/examples/opengl/pbuffers/pbuffers.pro b/examples/opengl/legacy/pbuffers/pbuffers.pro index a349e39f68..a349e39f68 100644 --- a/examples/opengl/pbuffers/pbuffers.pro +++ b/examples/opengl/legacy/pbuffers/pbuffers.pro diff --git a/examples/opengl/pbuffers/pbuffers.qrc b/examples/opengl/legacy/pbuffers/pbuffers.qrc index 9fc1a56a1a..9fc1a56a1a 100644 --- a/examples/opengl/pbuffers/pbuffers.qrc +++ b/examples/opengl/legacy/pbuffers/pbuffers.qrc diff --git a/examples/opengl/pbuffers2/bubbles.svg b/examples/opengl/legacy/pbuffers2/bubbles.svg index 51730124a2..51730124a2 100644 --- a/examples/opengl/pbuffers2/bubbles.svg +++ b/examples/opengl/legacy/pbuffers2/bubbles.svg diff --git a/examples/opengl/pbuffers2/designer.png b/examples/opengl/legacy/pbuffers2/designer.png Binary files differindex 4f32d57496..4f32d57496 100644 --- a/examples/opengl/pbuffers2/designer.png +++ b/examples/opengl/legacy/pbuffers2/designer.png diff --git a/examples/opengl/pbuffers2/glwidget.cpp b/examples/opengl/legacy/pbuffers2/glwidget.cpp index de30bb8b21..de30bb8b21 100644 --- a/examples/opengl/pbuffers2/glwidget.cpp +++ b/examples/opengl/legacy/pbuffers2/glwidget.cpp diff --git a/examples/opengl/pbuffers2/glwidget.h b/examples/opengl/legacy/pbuffers2/glwidget.h index 20dd796a48..20dd796a48 100644 --- a/examples/opengl/pbuffers2/glwidget.h +++ b/examples/opengl/legacy/pbuffers2/glwidget.h diff --git a/examples/opengl/pbuffers2/main.cpp b/examples/opengl/legacy/pbuffers2/main.cpp index 79fd88a3c8..79fd88a3c8 100644 --- a/examples/opengl/pbuffers2/main.cpp +++ b/examples/opengl/legacy/pbuffers2/main.cpp diff --git a/examples/opengl/pbuffers2/pbuffers2.pro b/examples/opengl/legacy/pbuffers2/pbuffers2.pro index f9dd269eea..f9dd269eea 100644 --- a/examples/opengl/pbuffers2/pbuffers2.pro +++ b/examples/opengl/legacy/pbuffers2/pbuffers2.pro diff --git a/examples/opengl/pbuffers2/pbuffers2.qrc b/examples/opengl/legacy/pbuffers2/pbuffers2.qrc index 986f1ca385..986f1ca385 100644 --- a/examples/opengl/pbuffers2/pbuffers2.qrc +++ b/examples/opengl/legacy/pbuffers2/pbuffers2.qrc diff --git a/examples/opengl/samplebuffers/glwidget.cpp b/examples/opengl/legacy/samplebuffers/glwidget.cpp index 28abf3d6c0..28abf3d6c0 100644 --- a/examples/opengl/samplebuffers/glwidget.cpp +++ b/examples/opengl/legacy/samplebuffers/glwidget.cpp diff --git a/examples/opengl/samplebuffers/glwidget.h b/examples/opengl/legacy/samplebuffers/glwidget.h index 494c5861df..494c5861df 100644 --- a/examples/opengl/samplebuffers/glwidget.h +++ b/examples/opengl/legacy/samplebuffers/glwidget.h diff --git a/examples/opengl/samplebuffers/main.cpp b/examples/opengl/legacy/samplebuffers/main.cpp index a1272af4db..a1272af4db 100644 --- a/examples/opengl/samplebuffers/main.cpp +++ b/examples/opengl/legacy/samplebuffers/main.cpp diff --git a/examples/opengl/samplebuffers/samplebuffers.pro b/examples/opengl/legacy/samplebuffers/samplebuffers.pro index b57599aae4..b57599aae4 100644 --- a/examples/opengl/samplebuffers/samplebuffers.pro +++ b/examples/opengl/legacy/samplebuffers/samplebuffers.pro diff --git a/examples/opengl/shared/qtlogo.cpp b/examples/opengl/legacy/shared/qtlogo.cpp index 608f5b3f2b..608f5b3f2b 100644 --- a/examples/opengl/shared/qtlogo.cpp +++ b/examples/opengl/legacy/shared/qtlogo.cpp diff --git a/examples/opengl/shared/qtlogo.h b/examples/opengl/legacy/shared/qtlogo.h index 5508372b01..5508372b01 100644 --- a/examples/opengl/shared/qtlogo.h +++ b/examples/opengl/legacy/shared/qtlogo.h diff --git a/examples/opengl/opengl.pro b/examples/opengl/opengl.pro index 8d09d21d72..7c055d2a82 100644 --- a/examples/opengl/opengl.pro +++ b/examples/opengl/opengl.pro @@ -1,30 +1,16 @@ -requires(qtHaveModule(opengl)) - TEMPLATE = subdirs -contains(QT_CONFIG, dynamicgl) { - SUBDIRS = hellowindow \ - contextinfo \ - qopenglwidget \ - threadedqopenglwidget \ - qopenglwindow -} else: !contains(QT_CONFIG, opengles2) { - SUBDIRS = 2dpainting \ - grabber \ - hellogl \ - overpainting \ - pbuffers \ - framebufferobject2 \ - samplebuffers -} +SUBDIRS = hellowindow \ + paintedwindow \ + qopenglwindow -!contains(QT_CONFIG, dynamicgl): SUBDIRS += hellowindow \ - paintedwindow \ - contextinfo \ - cube \ - textures \ - qopenglwidget \ - threadedqopenglwidget \ - qopenglwindow +qtHaveModule(widgets) { + SUBDIRS += contextinfo \ + threadedqopenglwidget \ + 2dpainting \ + hellogl2 -EXAMPLE_FILES = shared + !wince*: SUBDIRS += qopenglwidget \ + cube \ + textures +} diff --git a/examples/opengl/qopenglwidget/bubble.cpp b/examples/opengl/qopenglwidget/bubble.cpp index bf04c64966..c78e26a1d4 100644 --- a/examples/opengl/qopenglwidget/bubble.cpp +++ b/examples/opengl/qopenglwidget/bubble.cpp @@ -56,15 +56,15 @@ void Bubble::updateCache() { if (cache) delete cache; - cache = new QImage(qRound(radius * 2 + 2), qRound(radius * 2 + 2), QImage::Format_ARGB32); + cache = new QImage(qRound(radius * 2 + 2), qRound(radius * 2 + 2), QImage::Format_ARGB32_Premultiplied); cache->fill(0x00000000); QPainter p(cache); - p.setRenderHint(QPainter::HighQualityAntialiasing); + p.setRenderHint(QPainter::Antialiasing); QPen pen(Qt::white); pen.setWidth(2); p.setPen(pen); p.setBrush(brush); - p.drawEllipse(0, 0, int(2*radius), int(2*radius)); + p.drawEllipse(1, 1, int(2*radius), int(2*radius)); } //! [0] diff --git a/examples/opengl/qopenglwidget/glwidget.cpp b/examples/opengl/qopenglwidget/glwidget.cpp index e95ca363fc..de581f8d47 100644 --- a/examples/opengl/qopenglwidget/glwidget.cpp +++ b/examples/opengl/qopenglwidget/glwidget.cpp @@ -1,46 +1,49 @@ /**************************************************************************** -** -** 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$ -** -****************************************************************************/ + ** + ** 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 <QOpenGLShaderProgram> +#include <QOpenGLTexture> +#include <QCoreApplication> #include <math.h> #include "mainwindow.h" @@ -50,143 +53,175 @@ const int bubbleNum = 8; GLWidget::GLWidget(MainWindow *mw, bool button, const QColor &background) : m_mainWindow(mw), + m_showBubbles(true), + m_qtLogo(true), + m_frames(0), + m_program1(0), + m_program2(0), + m_texture(0), 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() { + qDeleteAll(m_bubbles); + + // And now release all OpenGL resources. + makeCurrent(); + delete m_texture; + delete m_program1; + delete m_program2; + delete m_vshader1; + delete m_fshader1; + delete m_vshader2; + delete m_fshader2; + m_vbo1.destroy(); + m_vbo2.destroy(); + doneCurrent(); } -void GLWidget::setScaling(int scale) { - +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; + m_fScale = 1; } -void GLWidget::setLogo() { - qtLogo = true; +void GLWidget::setLogo() +{ + m_qtLogo = true; } -void GLWidget::setTexture() { - qtLogo = false; +void GLWidget::setTexture() +{ + m_qtLogo = false; } -void GLWidget::showBubbles(bool bubbles) +void GLWidget::setShowBubbles(bool bubbles) { - m_showBubbles = 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); + m_program1->enableAttributeArray(m_vertexAttr1); + m_program1->enableAttributeArray(m_normalAttr1); + + m_vbo1.bind(); + // The data in the buffer is placed like this: + // vertex1.x, vertex1.y, vertex1.z, normal1.x, normal1.y, normal1.z, vertex2.x, ... + m_program1->setAttributeBuffer(m_vertexAttr1, GL_FLOAT, 0, 3, 6 * sizeof(GLfloat)); + m_program1->setAttributeBuffer(m_normalAttr1, GL_FLOAT, 3 * sizeof(GLfloat), 3, 6 * sizeof(GLfloat)); + m_vbo1.release(); + + glDrawArrays(GL_TRIANGLES, 0, m_vertices.size()); + + m_program1->disableAttributeArray(m_normalAttr1); + m_program1->disableAttributeArray(m_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); + m_texture->bind(); + + if (!m_vbo2.isCreated()) { + static 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 + }; + + static 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 + }; + + 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 + }; + + m_vbo2.create(); + m_vbo2.bind(); + m_vbo2.allocate(36 * 8 * sizeof(GLfloat)); + m_vbo2.write(0, afVertices, sizeof(afVertices)); + m_vbo2.write(sizeof(afVertices), afTexCoord, sizeof(afTexCoord)); + m_vbo2.write(sizeof(afVertices) + sizeof(afTexCoord), afNormals, sizeof(afNormals)); + m_vbo2.release(); + } + + m_program2->setUniformValue(m_textureUniform2, 0); // use texture unit 0 + + m_program2->enableAttributeArray(m_vertexAttr2); + m_program2->enableAttributeArray(m_normalAttr2); + m_program2->enableAttributeArray(m_texCoordAttr2); + + m_vbo2.bind(); + // In the buffer we first have 36 vertices (3 floats for each), then 36 texture + // coordinates (2 floats for each), then 36 normals (3 floats for each). + m_program2->setAttributeBuffer(m_vertexAttr2, GL_FLOAT, 0, 3); + m_program2->setAttributeBuffer(m_texCoordAttr2, GL_FLOAT, 36 * 3 * sizeof(GLfloat), 2); + m_program2->setAttributeBuffer(m_normalAttr2, GL_FLOAT, 36 * 5 * sizeof(GLfloat), 3); + m_vbo2.release(); glDrawArrays(GL_TRIANGLES, 0, 36); - program2.disableAttributeArray(vertexAttr2); - program2.disableAttributeArray(normalAttr2); - program2.disableAttributeArray(texCoordAttr2); + m_program2->disableAttributeArray(m_vertexAttr2); + m_program2->disableAttributeArray(m_normalAttr2); + m_program2->disableAttributeArray(m_texCoordAttr2); } -void GLWidget::initializeGL () +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()); + m_texture = new QOpenGLTexture(QImage(":/qt.png")); - QOpenGLShader *vshader1 = new QOpenGLShader(QOpenGLShader::Vertex, this); + m_vshader1 = new QOpenGLShader(QOpenGLShader::Vertex); const char *vsrc1 = "attribute highp vec4 vertex;\n" "attribute mediump vec3 normal;\n" @@ -201,26 +236,27 @@ void GLWidget::initializeGL () " color = clamp(color, 0.0, 1.0);\n" " gl_Position = matrix * vertex;\n" "}\n"; - vshader1->compileSourceCode(vsrc1); + m_vshader1->compileSourceCode(vsrc1); - QOpenGLShader *fshader1 = new QOpenGLShader(QOpenGLShader::Fragment, this); + m_fshader1 = new QOpenGLShader(QOpenGLShader::Fragment); const char *fsrc1 = "varying mediump vec4 color;\n" "void main(void)\n" "{\n" " gl_FragColor = color;\n" "}\n"; - fshader1->compileSourceCode(fsrc1); + m_fshader1->compileSourceCode(fsrc1); - program1.addShader(vshader1); - program1.addShader(fshader1); - program1.link(); + m_program1 = new QOpenGLShaderProgram; + m_program1->addShader(m_vshader1); + m_program1->addShader(m_fshader1); + m_program1->link(); - vertexAttr1 = program1.attributeLocation("vertex"); - normalAttr1 = program1.attributeLocation("normal"); - matrixUniform1 = program1.uniformLocation("matrix"); + m_vertexAttr1 = m_program1->attributeLocation("vertex"); + m_normalAttr1 = m_program1->attributeLocation("normal"); + m_matrixUniform1 = m_program1->uniformLocation("matrix"); - QOpenGLShader *vshader2 = new QOpenGLShader(QOpenGLShader::Vertex); + m_vshader2 = new QOpenGLShader(QOpenGLShader::Vertex); const char *vsrc2 = "attribute highp vec4 vertex;\n" "attribute highp vec4 texCoord;\n" @@ -235,9 +271,9 @@ void GLWidget::initializeGL () " gl_Position = matrix * vertex;\n" " texc = texCoord;\n" "}\n"; - vshader2->compileSourceCode(vsrc2); + m_vshader2->compileSourceCode(vsrc2); - QOpenGLShader *fshader2 = new QOpenGLShader(QOpenGLShader::Fragment); + m_fshader2 = new QOpenGLShader(QOpenGLShader::Fragment); const char *fsrc2 = "varying highp vec4 texc;\n" "uniform sampler2D tex;\n" @@ -248,35 +284,59 @@ void GLWidget::initializeGL () " 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); + m_fshader2->compileSourceCode(fsrc2); - program2.addShader(vshader2); - program2.addShader(fshader2); - program2.link(); + m_program2 = new QOpenGLShaderProgram; + m_program2->addShader(m_vshader2); + m_program2->addShader(m_fshader2); + m_program2->link(); - vertexAttr2 = program2.attributeLocation("vertex"); - normalAttr2 = program2.attributeLocation("normal"); - texCoordAttr2 = program2.attributeLocation("texCoord"); - matrixUniform2 = program2.uniformLocation("matrix"); - textureUniform2 = program2.uniformLocation("tex"); + m_vertexAttr2 = m_program2->attributeLocation("vertex"); + m_normalAttr2 = m_program2->attributeLocation("normal"); + m_texCoordAttr2 = m_program2->attributeLocation("texCoord"); + m_matrixUniform2 = m_program2->uniformLocation("matrix"); + m_textureUniform2 = m_program2->uniformLocation("tex"); m_fAngle = 0; m_fScale = 1; + createGeometry(); - createBubbles(bubbleNum - bubbles.count()); + + // Use a vertex buffer object. Client-side pointers are old-school and should be avoided. + m_vbo1.create(); + m_vbo1.bind(); + // For the cube all the data belonging to the texture coordinates and + // normals is placed separately, after the vertices. Here, for the Qt logo, + // let's do something different and potentially more efficient: create a + // properly interleaved data set. + const int vertexCount = m_vertices.count(); + QVector<GLfloat> buf; + buf.resize(vertexCount * 3 * 2); + GLfloat *p = buf.data(); + for (int i = 0; i < vertexCount; ++i) { + *p++ = m_vertices[i].x(); + *p++ = m_vertices[i].y(); + *p++ = m_vertices[i].z(); + *p++ = m_normals[i].x(); + *p++ = m_normals[i].y(); + *p++ = m_normals[i].z(); + } + m_vbo1.allocate(buf.constData(), buf.count() * sizeof(GLfloat)); + m_vbo1.release(); + + createBubbles(bubbleNum - m_bubbles.count()); } void GLWidget::paintGL() { - createBubbles(bubbleNum - bubbles.count()); + createBubbles(bubbleNum - m_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); + glClearColor(m_background.redF(), m_background.greenF(), m_background.blueF(), m_transparent ? 0.0f : 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glFrontFace(GL_CW); @@ -291,16 +351,16 @@ void GLWidget::paintGL() modelview.scale(m_fScale); modelview.translate(0.0f, -0.2f, 0.0f); - if (qtLogo) { - program1.bind(); - program1.setUniformValue(matrixUniform1, modelview); + if (m_qtLogo) { + m_program1->bind(); + m_program1->setUniformValue(m_matrixUniform1, modelview); paintQtLogo(); - program1.release(); + m_program1->release(); } else { - program2.bind(); - program1.setUniformValue(matrixUniform2, modelview); + m_program2->bind(); + m_program2->setUniformValue(m_matrixUniform2, modelview); paintTexturedCube(); - program2.release(); + m_program2->release(); } glDisable(GL_DEPTH_TEST); @@ -309,50 +369,50 @@ void GLWidget::paintGL() painter.endNativePainting(); if (m_showBubbles) - foreach (Bubble *bubble, bubbles) { + foreach (Bubble *bubble, m_bubbles) { bubble->drawBubble(&painter); - } + } - if (const int elapsed = time.elapsed()) { + if (const int elapsed = m_time.elapsed()) { QString framesPerSecond; - framesPerSecond.setNum(frames /(elapsed / 1000.0), 'f', 2); + framesPerSecond.setNum(m_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); + QMutableListIterator<Bubble*> iter(m_bubbles); while (iter.hasNext()) { Bubble *bubble = iter.next(); bubble->move(rect()); } - if (!(frames % 100)) { - time.start(); - frames = 0; + if (!(m_frames % 100)) { + m_time.start(); + m_frames = 0; } m_fAngle += 1.0f; - frames ++; + ++m_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)))); + 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))); + height()*0.0175*(-0.5 + qrand()/(RAND_MAX+1.0))); - bubbles.append(new Bubble(position, radius, velocity)); + m_bubbles.append(new Bubble(position, radius, velocity)); } } void GLWidget::createGeometry() { - vertices.clear(); - normals.clear(); + m_vertices.clear(); + m_normals.clear(); qreal x1 = +0.06f; qreal y1 = -0.14f; @@ -396,71 +456,71 @@ void GLWidget::createGeometry() extrude(x8, y8, x5, y5); } - for (int i = 0;i < vertices.size();i++) - vertices[i] *= 2.0f; + for (int i = 0;i < m_vertices.size();i++) + m_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); + m_vertices << QVector3D(x1, y1, -0.05f); + m_vertices << QVector3D(x2, y2, -0.05f); + m_vertices << QVector3D(x4, y4, -0.05f); - vertices << QVector3D(x3, y3, -0.05f); - vertices << QVector3D(x4, y4, -0.05f); - vertices << QVector3D(x2, y2, -0.05f); + m_vertices << QVector3D(x3, y3, -0.05f); + m_vertices << QVector3D(x4, y4, -0.05f); + m_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; + m_normals << n; + m_normals << n; + m_normals << n; - normals << n; - normals << n; - normals << n; + m_normals << n; + m_normals << n; + m_normals << n; - vertices << QVector3D(x4, y4, 0.05f); - vertices << QVector3D(x2, y2, 0.05f); - vertices << QVector3D(x1, y1, 0.05f); + m_vertices << QVector3D(x4, y4, 0.05f); + m_vertices << QVector3D(x2, y2, 0.05f); + m_vertices << QVector3D(x1, y1, 0.05f); - vertices << QVector3D(x2, y2, 0.05f); - vertices << QVector3D(x4, y4, 0.05f); - vertices << QVector3D(x3, y3, 0.05f); + m_vertices << QVector3D(x2, y2, 0.05f); + m_vertices << QVector3D(x4, y4, 0.05f); + m_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; + m_normals << n; + m_normals << n; + m_normals << n; - normals << n; - normals << n; - normals << n; + m_normals << n; + m_normals << n; + m_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); + m_vertices << QVector3D(x1, y1, +0.05f); + m_vertices << QVector3D(x2, y2, +0.05f); + m_vertices << QVector3D(x1, y1, -0.05f); - vertices << QVector3D(x2, y2, -0.05f); - vertices << QVector3D(x1, y1, -0.05f); - vertices << QVector3D(x2, y2, +0.05f); + m_vertices << QVector3D(x2, y2, -0.05f); + m_vertices << QVector3D(x1, y1, -0.05f); + m_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; + m_normals << n; + m_normals << n; + m_normals << n; - normals << n; - normals << n; - normals << n; + m_normals << n; + m_normals << n; + m_normals << n; } void GLWidget::setTransparent(bool transparent) diff --git a/examples/opengl/qopenglwidget/glwidget.h b/examples/opengl/qopenglwidget/glwidget.h index 6c43ac1576..ba8317df4a 100644 --- a/examples/opengl/qopenglwidget/glwidget.h +++ b/examples/opengl/qopenglwidget/glwidget.h @@ -43,7 +43,7 @@ #include <QOpenGLWidget> #include <QOpenGLFunctions> -#include <QOpenGLShaderProgram> +#include <QOpenGLBuffer> #include <QVector3D> #include <QMatrix4x4> #include <QTime> @@ -53,6 +53,10 @@ class Bubble; class MainWindow; +QT_FORWARD_DECLARE_CLASS(QOpenGLTexture) +QT_FORWARD_DECLARE_CLASS(QOpenGLShader) +QT_FORWARD_DECLARE_CLASS(QOpenGLShaderProgram) + class GLWidget : public QOpenGLWidget, protected QOpenGLFunctions { Q_OBJECT @@ -64,7 +68,7 @@ public slots: void setScaling(int scale); void setLogo(); void setTexture(); - void showBubbles(bool); + void setShowBubbles(bool); void setTransparent(bool transparent); private slots: @@ -76,33 +80,40 @@ protected: 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; + + MainWindow *m_mainWindow; + qreal m_fAngle; + qreal m_fScale; + bool m_showBubbles; + QVector<QVector3D> m_vertices; + QVector<QVector3D> m_normals; + bool m_qtLogo; + QList<Bubble *> m_bubbles; + int m_frames; + QTime m_time; + QOpenGLShader *m_vshader1; + QOpenGLShader *m_fshader1; + QOpenGLShader *m_vshader2; + QOpenGLShader *m_fshader2; + QOpenGLShaderProgram *m_program1; + QOpenGLShaderProgram *m_program2; + QOpenGLTexture *m_texture; + QOpenGLBuffer m_vbo1; + QOpenGLBuffer m_vbo2; + int m_vertexAttr1; + int m_normalAttr1; + int m_matrixUniform1; + int m_vertexAttr2; + int m_normalAttr2; + int m_texCoordAttr2; + int m_matrixUniform2; + int m_textureUniform2; bool m_transparent; QPushButton *m_btn; bool m_hasButton; diff --git a/examples/opengl/qopenglwidget/main.cpp b/examples/opengl/qopenglwidget/main.cpp index 2156e60155..a545c27249 100644 --- a/examples/opengl/qopenglwidget/main.cpp +++ b/examples/opengl/qopenglwidget/main.cpp @@ -40,12 +40,21 @@ #include <QApplication> #include <QMainWindow> +#include <QSurfaceFormat> #include "mainwindow.h" int main( int argc, char ** argv ) { Q_INIT_RESOURCE(texture); QApplication a( argc, argv ); + + QSurfaceFormat format; + format.setDepthBufferSize(24); + format.setStencilBufferSize(8); + if (QCoreApplication::arguments().contains(QStringLiteral("--multisample"))) + format.setSamples(4); + QSurfaceFormat::setDefaultFormat(format); + MainWindow mw; mw.showMaximized(); return a.exec(); diff --git a/examples/opengl/qopenglwidget/mainwindow.cpp b/examples/opengl/qopenglwidget/mainwindow.cpp index f09acacaf0..152ce8601b 100644 --- a/examples/opengl/qopenglwidget/mainwindow.cpp +++ b/examples/opengl/qopenglwidget/mainwindow.cpp @@ -121,7 +121,7 @@ MainWindow::MainWindow() 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(showBubbles, SIGNAL(triggered(bool)), glwidget, SLOT(setShowBubbles(bool))); connect(slider, SIGNAL(valueChanged(int)), glwidget, SLOT(setScaling(int))); connect(transparent, &QCheckBox::toggled, glwidget, &GLWidget::setTransparent); diff --git a/examples/opengl/textures/glwidget.cpp b/examples/opengl/textures/glwidget.cpp index 305ca1aa4c..96c732f8a6 100644 --- a/examples/opengl/textures/glwidget.cpp +++ b/examples/opengl/textures/glwidget.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** 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. @@ -38,23 +38,30 @@ ** ****************************************************************************/ -#include <QtWidgets> -#include <QtOpenGL> - #include "glwidget.h" - -GLWidget::GLWidget(QWidget *parent, QGLWidget *shareWidget) - : QGLWidget(parent, shareWidget) +#include <QOpenGLShaderProgram> +#include <QOpenGLTexture> +#include <QMouseEvent> + +GLWidget::GLWidget(QWidget *parent) + : QOpenGLWidget(parent), + clearColor(Qt::black), + xRot(0), + yRot(0), + zRot(0), + program(0) { - clearColor = Qt::black; - xRot = 0; - yRot = 0; - zRot = 0; - program = 0; + memset(textures, 0, sizeof(textures)); } GLWidget::~GLWidget() { + makeCurrent(); + vbo.destroy(); + for (int i = 0; i < 6; ++i) + delete textures[i]; + delete program; + doneCurrent(); } QSize GLWidget::minimumSizeHint() const @@ -72,13 +79,13 @@ void GLWidget::rotateBy(int xAngle, int yAngle, int zAngle) xRot += xAngle; yRot += yAngle; zRot += zAngle; - updateGL(); + update(); } void GLWidget::setClearColor(const QColor &color) { clearColor = color; - updateGL(); + update(); } void GLWidget::initializeGL() @@ -89,14 +96,11 @@ void GLWidget::initializeGL() glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); -#ifdef GL_TEXTURE_2D - glEnable(GL_TEXTURE_2D); -#endif #define PROGRAM_VERTEX_ATTRIBUTE 0 #define PROGRAM_TEXCOORD_ATTRIBUTE 1 - QGLShader *vshader = new QGLShader(QGLShader::Vertex, this); + QOpenGLShader *vshader = new QOpenGLShader(QOpenGLShader::Vertex, this); const char *vsrc = "attribute highp vec4 vertex;\n" "attribute mediump vec4 texCoord;\n" @@ -109,7 +113,7 @@ void GLWidget::initializeGL() "}\n"; vshader->compileSourceCode(vsrc); - QGLShader *fshader = new QGLShader(QGLShader::Fragment, this); + QOpenGLShader *fshader = new QOpenGLShader(QOpenGLShader::Fragment, this); const char *fsrc = "uniform sampler2D texture;\n" "varying mediump vec4 texc;\n" @@ -119,7 +123,7 @@ void GLWidget::initializeGL() "}\n"; fshader->compileSourceCode(fsrc); - program = new QGLShaderProgram(this); + program = new QOpenGLShaderProgram; program->addShader(vshader); program->addShader(fshader); program->bindAttributeLocation("vertex", PROGRAM_VERTEX_ATTRIBUTE); @@ -132,7 +136,7 @@ void GLWidget::initializeGL() void GLWidget::paintGL() { - qglClearColor(clearColor); + glClearColor(clearColor.redF(), clearColor.greenF(), clearColor.blueF(), clearColor.alphaF()); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); QMatrix4x4 m; @@ -145,17 +149,14 @@ void GLWidget::paintGL() program->setUniformValue("matrix", m); program->enableAttributeArray(PROGRAM_VERTEX_ATTRIBUTE); program->enableAttributeArray(PROGRAM_TEXCOORD_ATTRIBUTE); - program->setAttributeArray - (PROGRAM_VERTEX_ATTRIBUTE, vertices.constData()); - program->setAttributeArray - (PROGRAM_TEXCOORD_ATTRIBUTE, texCoords.constData()); + program->setAttributeBuffer(PROGRAM_VERTEX_ATTRIBUTE, GL_FLOAT, 0, 3, 5 * sizeof(GLfloat)); + program->setAttributeBuffer(PROGRAM_TEXCOORD_ATTRIBUTE, GL_FLOAT, 3 * sizeof(GLfloat), 2, 5 * sizeof(GLfloat)); for (int i = 0; i < 6; ++i) { - glBindTexture(GL_TEXTURE_2D, textures[i]); + textures[i]->bind(); glDrawArrays(GL_TRIANGLE_FAN, i * 4, 4); } } - void GLWidget::resizeGL(int width, int height) { int side = qMin(width, height); @@ -196,18 +197,23 @@ void GLWidget::makeObject() { { -1, -1, +1 }, { +1, -1, +1 }, { +1, +1, +1 }, { -1, +1, +1 } } }; - for (int j=0; j < 6; ++j) { - textures[j] = bindTexture - (QPixmap(QString(":/images/side%1.png").arg(j + 1)), GL_TEXTURE_2D); - } + for (int j = 0; j < 6; ++j) + textures[j] = new QOpenGLTexture(QImage(QString(":/images/side%1.png").arg(j + 1)).mirrored()); + QVector<GLfloat> vertData; for (int i = 0; i < 6; ++i) { for (int j = 0; j < 4; ++j) { - texCoords.append - (QVector2D(j == 0 || j == 3, j == 0 || j == 1)); - vertices.append - (QVector3D(0.2 * coords[i][j][0], 0.2 * coords[i][j][1], - 0.2 * coords[i][j][2])); + // vertex position + vertData.append(0.2 * coords[i][j][0]); + vertData.append(0.2 * coords[i][j][1]); + vertData.append(0.2 * coords[i][j][2]); + // texture coordinate + vertData.append(j == 0 || j == 3); + vertData.append(j == 0 || j == 1); } } + + vbo.create(); + vbo.bind(); + vbo.allocate(vertData.constData(), vertData.count() * sizeof(GLfloat)); } diff --git a/examples/opengl/textures/glwidget.h b/examples/opengl/textures/glwidget.h index 959dfdd5e7..eb47266e64 100644 --- a/examples/opengl/textures/glwidget.h +++ b/examples/opengl/textures/glwidget.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** 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. @@ -41,18 +41,19 @@ #ifndef GLWIDGET_H #define GLWIDGET_H -#include <QtWidgets> -#include <QGLWidget> +#include <QOpenGLWidget> #include <QOpenGLFunctions> +#include <QOpenGLBuffer> -QT_FORWARD_DECLARE_CLASS(QGLShaderProgram); +QT_FORWARD_DECLARE_CLASS(QOpenGLShaderProgram); +QT_FORWARD_DECLARE_CLASS(QOpenGLTexture) -class GLWidget : public QGLWidget, protected QOpenGLFunctions +class GLWidget : public QOpenGLWidget, protected QOpenGLFunctions { Q_OBJECT public: - explicit GLWidget(QWidget *parent = 0, QGLWidget *shareWidget = 0); + explicit GLWidget(QWidget *parent = 0); ~GLWidget(); QSize minimumSizeHint() const Q_DECL_OVERRIDE; @@ -79,10 +80,9 @@ private: int xRot; int yRot; int zRot; - GLuint textures[6]; - QVector<QVector3D> vertices; - QVector<QVector2D> texCoords; - QGLShaderProgram *program; + QOpenGLTexture *textures[6]; + QOpenGLShaderProgram *program; + QOpenGLBuffer vbo; }; #endif diff --git a/examples/opengl/textures/main.cpp b/examples/opengl/textures/main.cpp index 541c2a5fcc..30b0bfa607 100644 --- a/examples/opengl/textures/main.cpp +++ b/examples/opengl/textures/main.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** 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. @@ -39,6 +39,7 @@ ****************************************************************************/ #include <QApplication> +#include <QSurfaceFormat> #include "window.h" @@ -47,6 +48,11 @@ int main(int argc, char *argv[]) Q_INIT_RESOURCE(textures); QApplication app(argc, argv); + + QSurfaceFormat format; + format.setDepthBufferSize(24); + QSurfaceFormat::setDefaultFormat(format); + Window window; window.show(); return app.exec(); diff --git a/examples/opengl/textures/textures.pro b/examples/opengl/textures/textures.pro index d83077cb6a..7a7d19bee6 100644 --- a/examples/opengl/textures/textures.pro +++ b/examples/opengl/textures/textures.pro @@ -3,8 +3,10 @@ HEADERS = glwidget.h \ SOURCES = glwidget.cpp \ main.cpp \ window.cpp + RESOURCES = textures.qrc -QT += opengl widgets + +QT += widgets # install target.path = $$[QT_INSTALL_EXAMPLES]/opengl/textures diff --git a/examples/opengl/textures/window.cpp b/examples/opengl/textures/window.cpp index 6e3497c684..8876de5602 100644 --- a/examples/opengl/textures/window.cpp +++ b/examples/opengl/textures/window.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** 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. @@ -54,7 +54,7 @@ Window::Window() / (NumRows * NumColumns - 1), 255, 63); - glWidgets[i][j] = new GLWidget(0, 0); + glWidgets[i][j] = new GLWidget; glWidgets[i][j]->setClearColor(clearColor); glWidgets[i][j]->rotateBy(+42 * 16, +42 * 16, -21 * 16); mainLayout->addWidget(glWidgets[i][j], i, j); diff --git a/examples/opengl/textures/window.h b/examples/opengl/textures/window.h index 1dd2271ff5..0b53387024 100644 --- a/examples/opengl/textures/window.h +++ b/examples/opengl/textures/window.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** 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. diff --git a/examples/opengl/threadedqopenglwidget/glwidget.cpp b/examples/opengl/threadedqopenglwidget/glwidget.cpp index 34d97bf1bf..d447f0c716 100644 --- a/examples/opengl/threadedqopenglwidget/glwidget.cpp +++ b/examples/opengl/threadedqopenglwidget/glwidget.cpp @@ -47,10 +47,6 @@ const int bubbleNum = 8; GLWidget::GLWidget(QWidget *parent) : QOpenGLWidget(parent) { - QSurfaceFormat format; - format.setDepthBufferSize(16); - setFormat(format); - setMinimumSize(300, 250); connect(this, &QOpenGLWidget::aboutToCompose, this, &GLWidget::onAboutToCompose); @@ -120,11 +116,16 @@ Renderer::Renderer(GLWidget *w) void Renderer::paintQtLogo() { - program.enableAttributeArray(normalAttr); + vbo.bind(); + program.setAttributeBuffer(vertexAttr, GL_FLOAT, 0, 3); + program.setAttributeBuffer(normalAttr, GL_FLOAT, vertices.count() * 3 * sizeof(GLfloat), 3); + vbo.release(); + program.enableAttributeArray(vertexAttr); - program.setAttributeArray(vertexAttr, vertices.constData()); - program.setAttributeArray(normalAttr, normals.constData()); + program.enableAttributeArray(normalAttr); + glDrawArrays(GL_TRIANGLES, 0, vertices.size()); + program.disableAttributeArray(normalAttr); program.disableAttributeArray(vertexAttr); } @@ -201,6 +202,13 @@ void Renderer::render() m_fScale = 1; createGeometry(); + vbo.create(); + vbo.bind(); + const int verticesSize = vertices.count() * 3 * sizeof(GLfloat); + vbo.allocate(verticesSize * 2); + vbo.write(0, vertices.constData(), verticesSize); + vbo.write(verticesSize, normals.constData(), verticesSize); + m_elapsed.start(); } diff --git a/examples/opengl/threadedqopenglwidget/glwidget.h b/examples/opengl/threadedqopenglwidget/glwidget.h index 9d746e681b..8319faf322 100644 --- a/examples/opengl/threadedqopenglwidget/glwidget.h +++ b/examples/opengl/threadedqopenglwidget/glwidget.h @@ -44,6 +44,7 @@ #include <QOpenGLWidget> #include <QOpenGLFunctions> #include <QOpenGLShaderProgram> +#include <QOpenGLBuffer> #include <QVector3D> #include <QMatrix4x4> #include <QThread> @@ -83,6 +84,7 @@ private: QVector<QVector3D> vertices; QVector<QVector3D> normals; QOpenGLShaderProgram program; + QOpenGLBuffer vbo; int vertexAttr; int normalAttr; int matrixUniform; diff --git a/examples/opengl/threadedqopenglwidget/main.cpp b/examples/opengl/threadedqopenglwidget/main.cpp index 046a24d576..75b7f5e46f 100644 --- a/examples/opengl/threadedqopenglwidget/main.cpp +++ b/examples/opengl/threadedqopenglwidget/main.cpp @@ -40,6 +40,7 @@ #include <QApplication> #include <QMainWindow> +#include <QSurfaceFormat> #include "mainwindow.h" #include "glwidget.h" @@ -47,6 +48,10 @@ int main( int argc, char ** argv ) { QApplication a( argc, argv ); + QSurfaceFormat format; + format.setDepthBufferSize(16); + QSurfaceFormat::setDefaultFormat(format); + // Two top-level windows with two QOpenGLWidget children in each. // The rendering for the four QOpenGLWidgets happens on four separate threads. MainWindow mw1; |