diff options
author | Sean Harmer <sean.harmer@kdab.com> | 2016-08-14 09:23:05 +0100 |
---|---|---|
committer | Sean Harmer <sean.harmer@kdab.com> | 2016-08-14 09:41:21 +0100 |
commit | 9a18925b63d47a20d7b74cfd508d7ae71f2d4d7c (patch) | |
tree | 4d0d0538b9475a9104d56ee3d07f4bab7b0e00b4 | |
parent | 9a1c0c96246126d2377bd56ed702f47214e3ee0a (diff) | |
parent | 71eee85093ba807f5bc2add472b359841faa062d (diff) |
Merge branch '5.7' into dev
Change-Id: Id62e225062a030f4864fb7af2ed6f60d6be87460
108 files changed, 2471 insertions, 589 deletions
diff --git a/examples/qt3d/basicshapes-cpp/main.cpp b/examples/qt3d/basicshapes-cpp/main.cpp index 301aabb66..b4b01ff30 100644 --- a/examples/qt3d/basicshapes-cpp/main.cpp +++ b/examples/qt3d/basicshapes-cpp/main.cpp @@ -87,7 +87,7 @@ int main(int argc, char **argv) { QApplication app(argc, argv); Qt3DExtras::Qt3DWindow *view = new Qt3DExtras::Qt3DWindow(); - view->defaultFramegraph()->setClearColor(QColor(QRgb(0x4d4d4f))); + view->defaultFrameGraph()->setClearColor(QColor(QRgb(0x4d4d4f))); QWidget *container = QWidget::createWindowContainer(view); QSize screenSize = view->screen()->size(); container->setMinimumSize(QSize(200, 100)); diff --git a/examples/qt3d/exampleresources/assets/cubemaps/miramar/miramar_negx.webp b/examples/qt3d/exampleresources/assets/cubemaps/miramar/miramar_negx.webp Binary files differindex 1ea719fb3..d6c230e1d 100644 --- a/examples/qt3d/exampleresources/assets/cubemaps/miramar/miramar_negx.webp +++ b/examples/qt3d/exampleresources/assets/cubemaps/miramar/miramar_negx.webp diff --git a/examples/qt3d/exampleresources/assets/cubemaps/miramar/miramar_negy.webp b/examples/qt3d/exampleresources/assets/cubemaps/miramar/miramar_negy.webp Binary files differindex 5329f6ac9..101c0db05 100644 --- a/examples/qt3d/exampleresources/assets/cubemaps/miramar/miramar_negy.webp +++ b/examples/qt3d/exampleresources/assets/cubemaps/miramar/miramar_negy.webp diff --git a/examples/qt3d/exampleresources/assets/cubemaps/miramar/miramar_negz.webp b/examples/qt3d/exampleresources/assets/cubemaps/miramar/miramar_negz.webp Binary files differindex 2bae54690..164298faa 100644 --- a/examples/qt3d/exampleresources/assets/cubemaps/miramar/miramar_negz.webp +++ b/examples/qt3d/exampleresources/assets/cubemaps/miramar/miramar_negz.webp diff --git a/examples/qt3d/exampleresources/assets/cubemaps/miramar/miramar_posx.webp b/examples/qt3d/exampleresources/assets/cubemaps/miramar/miramar_posx.webp Binary files differindex ec33d1eb7..1cf2f4936 100644 --- a/examples/qt3d/exampleresources/assets/cubemaps/miramar/miramar_posx.webp +++ b/examples/qt3d/exampleresources/assets/cubemaps/miramar/miramar_posx.webp diff --git a/examples/qt3d/exampleresources/assets/cubemaps/miramar/miramar_posy.webp b/examples/qt3d/exampleresources/assets/cubemaps/miramar/miramar_posy.webp Binary files differindex 6d36fcba5..16316a77c 100644 --- a/examples/qt3d/exampleresources/assets/cubemaps/miramar/miramar_posy.webp +++ b/examples/qt3d/exampleresources/assets/cubemaps/miramar/miramar_posy.webp diff --git a/examples/qt3d/exampleresources/assets/cubemaps/miramar/miramar_posz.webp b/examples/qt3d/exampleresources/assets/cubemaps/miramar/miramar_posz.webp Binary files differindex 327041c71..3b178422e 100644 --- a/examples/qt3d/exampleresources/assets/cubemaps/miramar/miramar_posz.webp +++ b/examples/qt3d/exampleresources/assets/cubemaps/miramar/miramar_posz.webp diff --git a/examples/qt3d/exampleresources/assets/cubemaps/night/night_negx.webp b/examples/qt3d/exampleresources/assets/cubemaps/night/night_negx.webp Binary files differindex 1c595caf3..05700db5a 100644 --- a/examples/qt3d/exampleresources/assets/cubemaps/night/night_negx.webp +++ b/examples/qt3d/exampleresources/assets/cubemaps/night/night_negx.webp diff --git a/examples/qt3d/exampleresources/assets/cubemaps/night/night_negy.webp b/examples/qt3d/exampleresources/assets/cubemaps/night/night_negy.webp Binary files differindex 9a597d998..c189703c2 100644 --- a/examples/qt3d/exampleresources/assets/cubemaps/night/night_negy.webp +++ b/examples/qt3d/exampleresources/assets/cubemaps/night/night_negy.webp diff --git a/examples/qt3d/exampleresources/assets/cubemaps/night/night_negz.webp b/examples/qt3d/exampleresources/assets/cubemaps/night/night_negz.webp Binary files differindex a05772c23..07fae984f 100644 --- a/examples/qt3d/exampleresources/assets/cubemaps/night/night_negz.webp +++ b/examples/qt3d/exampleresources/assets/cubemaps/night/night_negz.webp diff --git a/examples/qt3d/exampleresources/assets/cubemaps/night/night_posx.webp b/examples/qt3d/exampleresources/assets/cubemaps/night/night_posx.webp Binary files differindex 0b15aa6eb..599f07287 100644 --- a/examples/qt3d/exampleresources/assets/cubemaps/night/night_posx.webp +++ b/examples/qt3d/exampleresources/assets/cubemaps/night/night_posx.webp diff --git a/examples/qt3d/exampleresources/assets/cubemaps/night/night_posy.webp b/examples/qt3d/exampleresources/assets/cubemaps/night/night_posy.webp Binary files differindex 23cd803a9..b3c7a2bfb 100644 --- a/examples/qt3d/exampleresources/assets/cubemaps/night/night_posy.webp +++ b/examples/qt3d/exampleresources/assets/cubemaps/night/night_posy.webp diff --git a/examples/qt3d/exampleresources/assets/cubemaps/night/night_posz.webp b/examples/qt3d/exampleresources/assets/cubemaps/night/night_posz.webp Binary files differindex 4899aa98e..8ff3fc500 100644 --- a/examples/qt3d/exampleresources/assets/cubemaps/night/night_posz.webp +++ b/examples/qt3d/exampleresources/assets/cubemaps/night/night_posz.webp diff --git a/src/3rdparty/assimp/assimp.pri b/src/3rdparty/assimp/assimp.pri index f0a7bf757..ad72816d8 100644 --- a/src/3rdparty/assimp/assimp.pri +++ b/src/3rdparty/assimp/assimp.pri @@ -34,6 +34,19 @@ intel_icc: { # Stop compiler complaining about ignored qualifiers on return types QMAKE_CFLAGS_WARN_ON += -Wno-ignored-qualifiers -Wno-unused-parameter -Wno-unused-variable -Wno-deprecated-declarations -Wno-unused-function -Wno-reorder QMAKE_CXXFLAGS_WARN_ON = $$QMAKE_CFLAGS_WARN_ON +} else:msvc { + # Disabled Warnings: + # 4100: 'identifier' : unreferenced formal parameter + # 4189: 'identifier' : local variable is initialized but not referenced + # 4267: coversion from 'size_t' to 'int', possible loss of data + # 4996: Function call with parameters that may be unsafe + QMAKE_CFLAGS_WARN_ON += -wd"4100" -wd"4189" -wd"4267" -wd"4996" + QMAKE_CXXFLAGS_WARN_ON = $$QMAKE_CFLAGS_WARN_ON +} + +clang: { + QMAKE_CFLAGS_WARN_ON += -Wno-unused-private-field + QMAKE_CXXFLAGS_WARN_ON = $$QMAKE_CFLAGS_WARN_ON } CONFIG += warn_on diff --git a/src/core/aspects/qaspectengine.cpp b/src/core/aspects/qaspectengine.cpp index 0af068c6e..81ee707bd 100644 --- a/src/core/aspects/qaspectengine.cpp +++ b/src/core/aspects/qaspectengine.cpp @@ -126,7 +126,41 @@ void QAspectEnginePrivate::generateCreationChanges(QNode *root) * \class Qt3DCore::QAspectEngine * \inherits QObject * \inmodule Qt3DCore - * \brief Responsible for handling all the QAbstractAspect subclasses that have been registered with the scene. + * + * \brief Responsible for handling all the QAbstractAspect subclasses that have + * been registered with the scene. + * + * The Qt3D run loop is controlled by the Qt3DRender::QAspectEngine. + * + * Qt3DCore::QAbstractAspect subclasses can be registered by calling + * Qt3DCore::QAspectEngine::registerAspect() which will take care of registering + * the aspect and in turn that will call Qt3DCore::QAbstractAspect::onRegistered(); + * + * The simulation loop is launched as soon as a root Qt3DCore::QEntity + * is set on the Qt3DCore::QAspectEngine. This is followed by a call to + * onEngineStartup() on each aspect so that they can start their simulation + * work. + * + * The simulation loop is stopped when the root entity is set to + * Qt3DCore::QEntityPtr(). This calls onEngineShutdown() on each aspect so + * that they can stop performing their simulation work. + * + * Setting a new valid root entity would restart the simulation loop again. + */ + +/*! + * \internal + * This loop is executed in a separate thread called the AspectThread in + * Qt3DCore::QAspectThread. This thread is started when the + * Qt3DCore::QAspectEngine is created and provides the + * Qt3DCore::QAspectManager which lives in this thread for as long as it's + * running. + * + * Once the AspectThread is running, it starts the run loop and waits for + * aspects to be registered. + * + * Destroying the Qt3DCore::QAspectEngine instance stops the AspectThread and + * properly terminates the run loop. */ /*! @@ -163,6 +197,8 @@ QAspectEngine::~QAspectEngine() Q_D(QAspectEngine); // Shutdown the simulation loop by setting an empty scene + // Note: this sets an atomic which allows the AspectThread to break out of + // the inner simulation loop in the AspectThread::exec function setRootEntity(QEntityPtr()); // Unregister all aspects and exit the main loop @@ -170,6 +206,7 @@ QAspectEngine::~QAspectEngine() for (auto aspect : aspects) unregisterAspect(aspect); + // Wait for thread to have completed it's final loop of execution d->m_aspectThread->aspectManager()->quit(); d->m_aspectThread->wait(); diff --git a/src/core/changes/qpropertynoderemovedchange.cpp b/src/core/changes/qpropertynoderemovedchange.cpp index ac1c4b313..af08635e4 100644 --- a/src/core/changes/qpropertynoderemovedchange.cpp +++ b/src/core/changes/qpropertynoderemovedchange.cpp @@ -47,6 +47,7 @@ namespace Qt3DCore { QPropertyNodeRemovedChangePrivate::QPropertyNodeRemovedChangePrivate() : QStaticPropertyValueRemovedChangeBasePrivate() + , m_propertyName(nullptr) , m_removedNodeIdTypePair() { } diff --git a/src/core/changes/qstaticpropertyupdatedchangebase.cpp b/src/core/changes/qstaticpropertyupdatedchangebase.cpp index 8beae634b..887e9d799 100644 --- a/src/core/changes/qstaticpropertyupdatedchangebase.cpp +++ b/src/core/changes/qstaticpropertyupdatedchangebase.cpp @@ -45,7 +45,8 @@ QT_BEGIN_NAMESPACE namespace Qt3DCore { QStaticPropertyUpdatedChangeBasePrivate::QStaticPropertyUpdatedChangeBasePrivate() - : QPropertyUpdatedChangeBasePrivate() + : QPropertyUpdatedChangeBasePrivate(), + m_propertyName(nullptr) { } diff --git a/src/core/changes/qstaticpropertyvalueaddedchangebase.cpp b/src/core/changes/qstaticpropertyvalueaddedchangebase.cpp index 20d2af032..f79372040 100644 --- a/src/core/changes/qstaticpropertyvalueaddedchangebase.cpp +++ b/src/core/changes/qstaticpropertyvalueaddedchangebase.cpp @@ -45,7 +45,8 @@ QT_BEGIN_NAMESPACE namespace Qt3DCore { QStaticPropertyValueAddedChangeBasePrivate::QStaticPropertyValueAddedChangeBasePrivate() - : QPropertyValueAddedChangeBasePrivate() + : QPropertyValueAddedChangeBasePrivate(), + m_propertyName(nullptr) { } diff --git a/src/core/changes/qstaticpropertyvalueremovedchangebase.cpp b/src/core/changes/qstaticpropertyvalueremovedchangebase.cpp index 0891abba8..44fa89a36 100644 --- a/src/core/changes/qstaticpropertyvalueremovedchangebase.cpp +++ b/src/core/changes/qstaticpropertyvalueremovedchangebase.cpp @@ -45,7 +45,8 @@ QT_BEGIN_NAMESPACE namespace Qt3DCore { QStaticPropertyValueRemovedChangeBasePrivate::QStaticPropertyValueRemovedChangeBasePrivate() - : QPropertyValueRemovedChangeBasePrivate() + : QPropertyValueRemovedChangeBasePrivate(), + m_propertyName(nullptr) { } diff --git a/src/core/nodes/qnode_p.h b/src/core/nodes/qnode_p.h index 8f48dd728..56a54a8ae 100644 --- a/src/core/nodes/qnode_p.h +++ b/src/core/nodes/qnode_p.h @@ -111,7 +111,8 @@ public: void registerDestructionHelper(NodeType *node, DestructionFunction<Caller, NodeType> func, NodeType *&) { // If the node is destoyed, we make sure not to keep a dangling pointer to it - auto f = std::bind(func, static_cast<Caller *>(q_func()), nullptr); + Q_Q(QNode); + auto f = [q, func]() { (static_cast<Caller *>(q)->*func)(nullptr); }; m_destructionConnections.insert(node, QObject::connect(node, &QNode::nodeDestroyed, f)); } @@ -119,7 +120,8 @@ public: void registerDestructionHelper(NodeType *node, DestructionFunction<Caller, NodeType> func, QVector<NodeType*> &) { // If the node is destoyed, we make sure not to keep a dangling pointer to it - auto f = std::bind(func, static_cast<Caller *>(q_func()), node); + Q_Q(QNode); + auto f = [q, func, node]() { (static_cast<Caller *>(q)->*func)(node); }; m_destructionConnections.insert(node, QObject::connect(node, &QNode::nodeDestroyed, f)); } diff --git a/src/core/resources/qhandlemanager_p.h b/src/core/resources/qhandlemanager_p.h index 53439e13c..b41fc75b1 100644 --- a/src/core/resources/qhandlemanager_p.h +++ b/src/core/resources/qhandlemanager_p.h @@ -153,6 +153,9 @@ QHandle<T, INDEXBITS> QHandleManager<T, INDEXBITS>::acquire(T *d) m_firstFreeEntry = m_entries[newIndex].m_nextFreeIndex; m_entries[newIndex].m_nextFreeIndex = 0; ++m_entries[newIndex].m_counter; + // Check if the counter is about to overflow and reset if necessary + if (m_entries[newIndex].m_counter == qHandle::MaxCounter) + m_entries[newIndex].m_counter = 0; if (m_entries[newIndex].m_counter == 0) m_entries[newIndex].m_counter = 1; m_entries[newIndex].m_active = true; diff --git a/src/core/resources/qresourcemanager_p.h b/src/core/resources/qresourcemanager_p.h index 30605a2d9..1b79434fd 100644 --- a/src/core/resources/qresourcemanager_p.h +++ b/src/core/resources/qresourcemanager_p.h @@ -60,6 +60,14 @@ #include "qhandle_p.h" #include "qhandlemanager_p.h" +// Silence complaints about unreferenced local variables in +// ArrayAllocatingPolicy::deallocateBuckets() when the compiler +// inlines the call to the dtor and it is empty. Default warning +// setting re-enabled at bottom of this file +#if defined(Q_CC_MSVC) +#pragma warning(disable : 4189) +#endif + QT_BEGIN_NAMESPACE namespace Qt3DCore { @@ -542,4 +550,8 @@ QDebug operator<<(QDebug dbg, const QResourceManager<ValueType, KeyType, INDEXBI QT_END_NAMESPACE +#if defined(Q_CC_MSVC) +#pragma warning(default : 4189) +#endif + #endif // QT3DCORE_QABSTRACTRESOURCESMANAGER_H diff --git a/src/core/transforms/qtransform.cpp b/src/core/transforms/qtransform.cpp index 22e48b266..85fe7f9f1 100644 --- a/src/core/transforms/qtransform.cpp +++ b/src/core/transforms/qtransform.cpp @@ -55,6 +55,7 @@ QTransformPrivate::QTransformPrivate() , m_eulerRotationAngles() , m_matrixDirty(false) { + m_shareable = false; } QTransformPrivate::~QTransformPrivate() @@ -68,6 +69,8 @@ QTransformPrivate::~QTransformPrivate() * \instantiates Qt3DCore::QComponent * \since 5.6 * \brief Used to perform transforms on meshes + * + * The Transform component is not shareable between multiple Entity's. */ /*! @@ -170,6 +173,8 @@ QTransformPrivate::~QTransformPrivate() * \inherits Qt3DCore::QComponent * \since 5.6 * \brief Used to perform transforms on meshes + * + * The QTransform component is not shareable between multiple QEntity's. */ /*! diff --git a/src/doc/doc.pro b/src/doc/doc.pro index a0ef6f976..34ef2f2b4 100644 --- a/src/doc/doc.pro +++ b/src/doc/doc.pro @@ -1,3 +1,5 @@ TEMPLATE = aux QMAKE_DOCS = $$PWD/qt3d.qdocconf + +OTHER_FILES += $$PWD/src/*.qdoc diff --git a/src/doc/qt3d.qdocconf b/src/doc/qt3d.qdocconf index f97535628..623a2c5d5 100644 --- a/src/doc/qt3d.qdocconf +++ b/src/doc/qt3d.qdocconf @@ -46,7 +46,8 @@ headerdirs += . \ ../logic \ ../plugins \ ../quick3d/quick3d \ - ../input + ../input \ + ../extras # Exclude private header files from the documentation build excludefiles += "*_p.h" @@ -57,7 +58,8 @@ sourcedirs += . \ ../logic \ ../plugins \ ../quick3d/quick3d \ - ../input + ../input \ + ../extras exampledirs += ../../examples/qt3d \ snippets @@ -80,7 +82,8 @@ Cpp.ignoretokens += QT3DINPUTSHARED_EXPORT \ QT3DLOGICSHARED_EXPORT \ QT3DRENDERSHARED_EXPORT \ QT3DRENDERSHARED_PRIVATE_EXPORT \ - QT3DQUICKSHARED_PRIVATE_EXPORT + QT3DQUICKSHARED_PRIVATE_EXPORT \ + QT3DEXTRASSHARED_EXPORT Cpp.ignoredirectives += Q_DECLARE_LOGGING_CATEGORY diff --git a/src/doc/src/qt3d-index.qdoc b/src/doc/src/qt3d-index.qdoc index 3c2630c22..693864414 100644 --- a/src/doc/src/qt3d-index.qdoc +++ b/src/doc/src/qt3d-index.qdoc @@ -61,7 +61,7 @@ \l qmake \c .pro file: \badcode - QT += 3dcore 3drender 3dinput 3dlogic + QT += 3dcore 3drender 3dinput 3dlogic 3dextras \endcode To include the definitions of the modules' classes, use the following @@ -72,6 +72,7 @@ #include <Qt3DRender> #include <Qt3DInput> #include <Qt3DLogic> + #include <Qt3DExtras> \endcode A Qt Quick application requires also additional dependencies: @@ -96,15 +97,15 @@ \section1 Qt 3D Platform Support - In this Technology Preview Qt 3D has the following support for platforms: + Qt 3D has the following support for platforms: \list \li Microsoft Windows (win32) - Supported \li Linux X11 - Supported - \li OS X - Supported although there may be some retina scaling issues + \li \macos - Supported although there may be some retina scaling issues \li Android - Supported \li Embedded Linux - Supported - \li iOS - Not supported yet (coming in Qt 5.6) + \li iOS - Supported since (Qt 5.7) \li WinRT - Not supported yet \li Windows CE - Compiles but not tested \endlist diff --git a/src/doc/src/qt3d-module.qdoc b/src/doc/src/qt3d-module.qdoc index f6dc6934d..c82c528f1 100644 --- a/src/doc/src/qt3d-module.qdoc +++ b/src/doc/src/qt3d-module.qdoc @@ -74,6 +74,9 @@ \section2 Qt 3D Render Module \generatelist {classesbymodule Qt3DRender} + + \section2 Qt 3D Extras Module + \generatelist {classesbymodule Qt3DExtras} */ /*! @@ -107,6 +110,7 @@ import Qt3D.Render 2.0 import Qt3D.Input 2.0 import Qt3D.Logic 2.0 + import Qt3D.Extras 2.0 \endcode \section1 QML Types @@ -123,4 +127,8 @@ \section2 Qt 3D Render Module \generatelist {qmltypesbymodule Qt3D.Render} \noautolist + + \section2 Qt 3D Extras Module + \generatelist {qmltypesbymodule Qt3D.Extras} + \noautolist */ diff --git a/src/doc/src/qt3d-overview.qdoc b/src/doc/src/qt3d-overview.qdoc index 7e9c7b4c3..9bbd7f988 100644 --- a/src/doc/src/qt3d-overview.qdoc +++ b/src/doc/src/qt3d-overview.qdoc @@ -62,7 +62,7 @@ \list \li 2D and 3D rendering for C++ and Qt Quick applications - \li Meshes + \li Meshes and \l {Qt 3D Render Geometry}{Geometry} \li \l {Materials} \li \l {Shaders} \li \l {Shadow Mapping}{Shadow mapping} diff --git a/src/doc/src/qt3dextras-module.qdoc b/src/doc/src/qt3dextras-module.qdoc new file mode 100644 index 000000000..087018139 --- /dev/null +++ b/src/doc/src/qt3dextras-module.qdoc @@ -0,0 +1,154 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \module Qt3DExtras + \title Qt 3D Extras C++ Classes + + \brief The Qt 3D Extras modules provides a set of prebuilt elements to help + you get started with Qt 3D. + + This module is still in tech preview. This means it is unstable, likely to + change and provided as a convenience only. + + \ingroup modules + \ingroup qt3d-modules + \qtvariable 3dextras + + \code + #include <Qt3DExtras> + \endcode + + To link against the corresponding C++ library, add the following to your qmake project file: + + \badcode + QT += 3dextras + \endcode + + Classes, types, and functions are declared under the \l [Qt3DExtras]{Qt3DExtras} namespace. + + \section1 Overview + + \section2 Materials + + \list + \li Qt3DExtras::QDiffuseMapMaterial + \li Qt3DExtras::QDiffuseSpecularMapMaterial + \li Qt3DExtras::QGoochMaterial + \li Qt3DExtras::QNormalDiffuseMapMaterial + \li Qt3DExtras::QNormalDiffuseMapAlphaMaterial + \li Qt3DExtras::QNormalDiffuseSpecularMapMaterial + \li Qt3DExtras::QPerVertexColorMaterial + \li Qt3DExtras::QPhongMaterial + \li Qt3DExtras::QPhongAlphaMaterial + \endlist + + \section2 Meshes and Geometries + + \list + \li Qt3DExtras::QConeGeometry + \li Qt3DExtras::QConeMesh + \li Qt3DExtras::QCuboidGeometry + \li Qt3DExtras::QCuboidMesh + \li Qt3DExtras::QCylinderGeometry + \li Qt3DExtras::QCylinderMesh + \li Qt3DExtras::QPlaneGeometry + \li Qt3DExtras::QPlaneMesh + \li Qt3DExtras::QSphereGeometry + \li Qt3DExtras::QSphereMesh + \li Qt3DExtras::QTorusGeometry + \li Qt3DExtras::QTorusMesh + \endlist + + \section2 Camera Controllers + + \list + \li Qt3DExtras::QFirstPersonCameraController + \li Qt3DExtras::QOrbitCameraController + \endlist + + \section2 Entities + + \list + \li Qt3DExtras::QSkyboxEntity + \endlist + + \section2 FrameGraphs + + \list + \li Qt3DExtras::QForwardRenderer + \endlist + + \section2 Window + + \list + \li Qt3DExtras::Qt3DWindow + \endlist + + \note The Quick3DExtras module also specifies a Qt3DExtras::Quick::Qt3DQuickWindow. + + \section1 Reference + \list + \li \l {Qt 3D Extras C++ Classes} + \li \l {Qt 3D Examples} + \endlist + */ + +/*! + \namespace Qt3DExtras + \inmodule Qt3DExtras + \ingroup qt3d-namespaces + + \brief Contains classes from the Qt3DExtras module. +*/ + +/*! + \qmlmodule Qt3D.Extras 2.0 + \title Qt 3D Extras QML Types + \ingroup qmlmodules + \ingroup qt3d-qmlmodules + + \brief Provides Qt 3D QML types for the extras module. + + To import and use the module's QML types, use the following statement: + + \badcode + import Qt3D.Extras 2.0 + \endcode +*/ diff --git a/src/doc/src/qt3drender-framegraph.qdoc b/src/doc/src/qt3drender-framegraph.qdoc index d585c833b..44b1cbe89 100644 --- a/src/doc/src/qt3drender-framegraph.qdoc +++ b/src/doc/src/qt3drender-framegraph.qdoc @@ -122,17 +122,17 @@ \section2 Setting the Framegraph The FrameGraph tree should be assigned to the activeFrameGraph property of - a QFrameGraph component, itself being a component of the root entity in the - Qt 3D scene. This is what makes it the active framegraph for the renderer. - Of course, since this is a QML property binding, the active framegraph (or - parts of it) can be changed on the fly at runtime. For example, if you want - to use different rendering approaches for indoor and outdoor scenes or to - enable or disable some special effect. + a QRenderSettings component, itself being a component of the root entity in + the Qt 3D scene. This is what makes it the active framegraph for the + renderer. Of course, since this is a QML property binding, the active + framegraph (or parts of it) can be changed on the fly at runtime. For + example, if you want to use different rendering approaches for indoor and + outdoor scenes or to enable or disable some special effect. \badcode Entity { id: sceneRoot - components: FrameGraph { + components: RenderSettings { activeFrameGraph: ... // FrameGraph tree } } @@ -144,7 +144,7 @@ \badcode Entity { id: sceneRoot - components: FrameGraph { + components: RenderSettings { ... // FrameGraph tree } } diff --git a/src/doc/src/qt3drender-geometry.qdoc b/src/doc/src/qt3drender-geometry.qdoc new file mode 100644 index 000000000..03e84b1d7 --- /dev/null +++ b/src/doc/src/qt3drender-geometry.qdoc @@ -0,0 +1,154 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \page qt3drender-geometry.html + \title Qt 3D Render Geometry + + \brief Presents the classes provided by the Qt 3D Render aspect to specify + data to the renderer, typically containing geometry. + + Qt 3D Render provides a generic way of storing geometry data and specifying + how it should be read by the renderer. + + \list + \li \l {Buffer} + \li \l {Attribute} + \li \l {Geometry} + \li \l {GeometryRenderer} + \endlist + + \section2 Buffer + + The Qt3DRender::QBuffer class stores the raw data. This acts purely as an + array of memory. In most cases a Qt3DRender::QBuffer will be used + indirectly by being referenced by one or more Qt3DRender::QAttributes. + However there are times when a QBuffer may be used directly as the value + property of a QParameter when dealing with Uniform Buffer Objects (UBO) or + Shader Storage Buffer Objects (SSBO). + + \code + Buffer { + id: vertexBuffer + type: Buffer.VertexBuffer + data: buildVertexBufferData() + } + \endcode + + \section2 Attribute + + Qt3DRender::QAttribute specifies how data contained in the referenced + buffer should be extracted and passed to an input of a vertex shader. It + references a Qt3DRender::QBuffer and can specify the layout of the + attributes by definining the vertex size, the data type, the stride between + two vertices and a starting offset. The type of the attribute will also + define whether it is to be used as a vertex buffer or as an index buffer. + This allows you complete flexibility of how you structure your data in + buffers. It is possible to use separate buffers for each vertex attribute, + an interleaved buffer containing data for all attributes or a combination + of separate and interleaved buffers. + + \code + Attribute { + attributeType: Attribute.VertexAttribute + vertexBaseType: Attribute.Float + vertexSize: 3 + byteOffset: 0 + byteStride: 9 * 4 + count: 4 + name: defaultPositionAttributeName() + buffer: vertexBuffer + } + \endcode + + \section2 Geometry + + A Qt3DRender::QGeometry aggregates various attributes to form a piece of + geometry. Usually a proper geometry will provide an attribute for vertex + positions, an attribute for vertex normals and an attribute for texture + coordinates. If you want your geometry to also work with normal mapped + materials it will need to provide a consistent set of vertex tangent + vectors too. + + \code + Geometry { + Attribute { + attributeType: Attribute.VertexAttribute + vertexBaseType: Attribute.Float + vertexSize: 3 + byteOffset: 0 + byteStride: 9 * 4 + count: 4 + name: defaultPositionAttributeName() + buffer: vertexBuffer + } + + Attribute { + attributeType: Attribute.VertexAttribute + vertexBaseType: Attribute.Float + vertexSize: 3 + byteOffset: 3 * 4 + byteStride: 9 * 4 + count: 4 + name: defaultNormalAttributeName() + buffer: vertexBuffer + } + \endcode + + \section2 GeometryRenderer + + Qt3DRender::QGeometryRenderer is a QComponent which when aggregated by a + QEntity allows to draw the Qt3DRender::QGeometry it references. It provides + properties to control the draw call such as the number of instances to be + drawn, the starting instance, the type of + Qt3DRender::QGeometryRenderer::PrimitiveType to be used, etc. A + Qt3DRender::QGeometryRenderer is translated into a draw call to the + underlying graphics API. + + \code + GeometryRenderer { + instanceCount: 1 + indexOffset: 0 + firstInstance: 0 + primitiveType: GeometryRenderer.Triangles + geometry: Geometry { ... } + } + \endcode + + */ diff --git a/src/extras/defaults/qt3dwindow.cpp b/src/extras/defaults/qt3dwindow.cpp index 782be9037..ab0b0e400 100644 --- a/src/extras/defaults/qt3dwindow.cpp +++ b/src/extras/defaults/qt3dwindow.cpp @@ -144,7 +144,7 @@ Qt3DRender::QFrameGraphNode *Qt3DWindow::activeFrameGraph() const return m_renderSettings->activeFrameGraph(); } -Qt3DExtras::QForwardRenderer *Qt3DWindow::defaultFramegraph() const +Qt3DExtras::QForwardRenderer *Qt3DWindow::defaultFrameGraph() const { return m_forwardRenderer; } diff --git a/src/extras/defaults/qt3dwindow.h b/src/extras/defaults/qt3dwindow.h index 1d73966de..109e1be75 100644 --- a/src/extras/defaults/qt3dwindow.h +++ b/src/extras/defaults/qt3dwindow.h @@ -98,7 +98,7 @@ public: void setActiveFrameGraph(Qt3DRender::QFrameGraphNode *activeFrameGraph); Qt3DRender::QFrameGraphNode *activeFrameGraph() const; - Qt3DExtras::QForwardRenderer *defaultFramegraph() const; + Qt3DExtras::QForwardRenderer *defaultFrameGraph() const; Qt3DRender::QCamera *camera() const; diff --git a/src/extras/geometries/qcuboidgeometry.cpp b/src/extras/geometries/qcuboidgeometry.cpp index 9ef40c192..a632111f6 100644 --- a/src/extras/geometries/qcuboidgeometry.cpp +++ b/src/extras/geometries/qcuboidgeometry.cpp @@ -70,35 +70,66 @@ void createPlaneVertexData(float w, float h, const QSize &resolution, const float b0 = -h / 2.0f; const float da = w / (resolution.width() - 1); const float db = h / (resolution.height() - 1); - const float du = 1.0 / (resolution.width() - 1); - const float dv = 1.0 / (resolution.height() - 1); - float n = 1.0f; + const float du = 1.0f / (resolution.width() - 1); + const float dv = 1.0f / (resolution.height() - 1); switch (normal) { case NegativeX: - n = -1.0f; // fall through + // Iterate over z + for (int j = resolution.width() - 1; j >= 0; --j) { + const float a = a0 + static_cast<float>(j) * da; + const float u = static_cast<float>(j) * du; + + // Iterate over y + for (int i = 0; i < resolution.height(); ++i) { + const float b = b0 + static_cast<float>(i) * db; + const float v = static_cast<float>(i) * dv; + + // position + *vertices++ = planeDistance; + *vertices++ = b; + *vertices++ = a; + + // texture coordinates + *vertices++ = 1.0f - u; + *vertices++ = v; + + // normal + *vertices++ = -1.0f; + *vertices++ = 0.0f; + *vertices++ = 0.0f; + + // tangent + *vertices++ = 0.0f; + *vertices++ = 0.0f; + *vertices++ = -1.0f; + *vertices++ = -1.0f; + } + } + break; + case PositiveX: { // Iterate over z for (int j = 0; j < resolution.height(); ++j) { - const float b = b0 + static_cast<float>(j) * db; - const float v = static_cast<float>(j) * dv; + const float a = a0 + static_cast<float>(j) * da; + const float u = static_cast<float>(j) * du; // Iterate over y for (int i = 0; i < resolution.width(); ++i) { - const float a = a0 + static_cast<float>(i) * da; - const float u = static_cast<float>(i) * du; + const float b = b0 + static_cast<float>(i) * db; + const float v = static_cast<float>(i) * dv; // position *vertices++ = planeDistance; - *vertices++ = a; *vertices++ = b; + *vertices++ = a; // texture coordinates *vertices++ = u; *vertices++ = v; // normal - *vertices++ = n; + *vertices++ = 1.0f; *vertices++ = 0.0f; *vertices++ = 0.0f; @@ -106,15 +137,13 @@ void createPlaneVertexData(float w, float h, const QSize &resolution, *vertices++ = 0.0f; *vertices++ = 0.0f; *vertices++ = 1.0f; - *vertices++ = 1.0f; + *vertices++ = -1.0f; } } break; } case NegativeY: - n = -1.0f; - case PositiveY: { // Iterate over z for (int j = 0; j < resolution.height(); ++j) { const float b = b0 + static_cast<float>(j) * db; @@ -123,7 +152,7 @@ void createPlaneVertexData(float w, float h, const QSize &resolution, // Iterate over x // This iterates in the opposite sense to the other directions // so that the winding order is correct - for (int i = resolution.width() - 1; i >= 0; --i) { + for (int i = 0; i < resolution.width(); ++i) { const float a = a0 + static_cast<float>(i) * da; const float u = static_cast<float>(i) * du; @@ -138,7 +167,43 @@ void createPlaneVertexData(float w, float h, const QSize &resolution, // normal *vertices++ = 0.0f; - *vertices++ = n; + *vertices++ = -1.0f; + *vertices++ = 0.0f; + + // tangent + *vertices++ = 1.0f; + *vertices++ = 0.0f; + *vertices++ = 0.0f; + *vertices++ = 1.0f; + } + } + break; + + case PositiveY: { + // Iterate over z + for (int j = resolution.height() - 1; j >= 0; --j) { + const float b = b0 + static_cast<float>(j) * db; + const float v = static_cast<float>(j) * dv; + + // Iterate over x + // This iterates in the opposite sense to the other directions + // so that the winding order is correct + for (int i = 0; i < resolution.width(); ++i) { + const float a = a0 + static_cast<float>(i) * da; + const float u = static_cast<float>(i) * du; + + // position + *vertices++ = a; + *vertices++ = planeDistance; + *vertices++ = b; + + // texture coordinates + *vertices++ = u; + *vertices++ = 1.0f - v; + + // normal + *vertices++ = 0.0f; + *vertices++ = 1.0f; *vertices++ = 0.0f; // tangent @@ -152,7 +217,39 @@ void createPlaneVertexData(float w, float h, const QSize &resolution, } case NegativeZ: - n = -1.0f; + // Iterate over y + for (int j = 0; j < resolution.height(); ++j) { + const float b = b0 + static_cast<float>(j) * db; + const float v = static_cast<float>(j) * dv; + + // Iterate over x + for (int i = resolution.width() - 1; i >= 0; --i) { + const float a = a0 + static_cast<float>(i) * da; + const float u = static_cast<float>(i) * du; + + // position + *vertices++ = a; + *vertices++ = b; + *vertices++ = planeDistance; + + // texture coordinates + *vertices++ = 1.0f - u; + *vertices++ = v; + + // normal + *vertices++ = 0.0f; + *vertices++ = 0.0f; + *vertices++ = -1.0f; + + // tangent + *vertices++ = -1.0f; + *vertices++ = 0.0f; + *vertices++ = 0.0f; + *vertices++ = 1.0f; + } + } + break; + case PositiveZ: { // Iterate over y for (int j = 0; j < resolution.height(); ++j) { @@ -176,7 +273,7 @@ void createPlaneVertexData(float w, float h, const QSize &resolution, // normal *vertices++ = 0.0f; *vertices++ = 0.0f; - *vertices++ = n; + *vertices++ = 1.0f; // tangent *vertices++ = 1.0f; @@ -190,54 +287,24 @@ void createPlaneVertexData(float w, float h, const QSize &resolution, } // switch (normal) } -void createPlaneIndexData(PlaneNormal normal, const QSize &resolution, quint16 *indices, quint16 &baseVertex) +void createPlaneIndexData(const QSize &resolution, quint16 *indices, quint16 &baseVertex) { - float n = 1.0f; - - switch (normal) { - case NegativeX: - case NegativeY: - case NegativeZ: - n = -1.0f; - break; - default: - break; - } - // Populate indices taking care to get correct CCW winding on all faces - if (n > 0.0f) { - for (int j = 0; j < resolution.height() - 1; ++j) { - const int rowStartIndex = j * resolution.width() + baseVertex; - const int nextRowStartIndex = (j + 1) * resolution.width() + baseVertex; - - // Iterate over x - for (int i = 0; i < resolution.width() - 1; ++i) { - // Split quad into two triangles - *indices++ = rowStartIndex + i; - *indices++ = rowStartIndex + i + 1; - *indices++ = nextRowStartIndex + i; - - *indices++ = nextRowStartIndex + i; - *indices++ = rowStartIndex + i + 1; - *indices++ = nextRowStartIndex + i + 1; - } - } - } else { - for (int j = 0; j < resolution.height() - 1; ++j) { - const int rowStartIndex = j * resolution.width() + baseVertex; - const int nextRowStartIndex = (j + 1) * resolution.width() + baseVertex; - - // Iterate over x - for (int i = 0; i < resolution.width() - 1; ++i) { - // Split quad into two triangles - *indices++ = rowStartIndex + i; - *indices++ = nextRowStartIndex + i; - *indices++ = rowStartIndex + i + 1; - - *indices++ = nextRowStartIndex + i; - *indices++ = nextRowStartIndex + i + 1; - *indices++ = rowStartIndex + i + 1; - } + // Iterate over v direction (rows) + for (int j = 0; j < resolution.height() - 1; ++j) { + const int rowStartIndex = j * resolution.width() + baseVertex; + const int nextRowStartIndex = (j + 1) * resolution.width() + baseVertex; + + // Iterate over u direction (columns) + for (int i = 0; i < resolution.width() - 1; ++i) { + // Split quad into two triangles + *indices++ = rowStartIndex + i; + *indices++ = rowStartIndex + i + 1; + *indices++ = nextRowStartIndex + i; + + *indices++ = nextRowStartIndex + i; + *indices++ = rowStartIndex + i + 1; + *indices++ = nextRowStartIndex + i + 1; } } baseVertex += resolution.width() * resolution.height(); @@ -299,17 +366,17 @@ QByteArray createCuboidIndexData(const QSize &yzResolution, quint16 *indices = reinterpret_cast<quint16 *>(indexData.data()); quint16 baseIndex = 0; - createPlaneIndexData(PositiveX, yzResolution, indices, baseIndex); + createPlaneIndexData(yzResolution, indices, baseIndex); indices += yzIndices; - createPlaneIndexData(NegativeX, yzResolution, indices, baseIndex); + createPlaneIndexData(yzResolution, indices, baseIndex); indices += yzIndices; - createPlaneIndexData(PositiveY, xzResolution, indices, baseIndex); + createPlaneIndexData(xzResolution, indices, baseIndex); indices += xzIndices; - createPlaneIndexData(NegativeY, xzResolution, indices, baseIndex); + createPlaneIndexData(xzResolution, indices, baseIndex); indices += xzIndices; - createPlaneIndexData(PositiveZ, xyResolution, indices, baseIndex); + createPlaneIndexData(xyResolution, indices, baseIndex); indices += xyIndices; - createPlaneIndexData(NegativeZ, xyResolution, indices, baseIndex); + createPlaneIndexData(xyResolution, indices, baseIndex); return indexData; } diff --git a/src/quick3d/imports/render/qt3dquick3drenderplugin.cpp b/src/quick3d/imports/render/qt3dquick3drenderplugin.cpp index a7897a4ba..463491ab3 100644 --- a/src/quick3d/imports/render/qt3dquick3drenderplugin.cpp +++ b/src/quick3d/imports/render/qt3dquick3drenderplugin.cpp @@ -100,7 +100,6 @@ #include <Qt3DRender/qcamera.h> #include <Qt3DRender/qrendersettings.h> #include <Qt3DRender/qpickingsettings.h> -#include <Qt3DRender/private/qboundingvolumedebug_p.h> #include <Qt3DQuickRender/private/quick3dlayerfilter_p.h> #include <Qt3DQuickRender/private/quick3dtechnique_p.h> #include <Qt3DQuickRender/private/quick3dmaterial_p.h> @@ -192,9 +191,6 @@ void Qt3DQuick3DRenderPlugin::registerTypes(const char *uri) Qt3DRender::Quick::registerExtendedType<Qt3DRender::QGeometry, Qt3DRender::Render::Quick::Quick3DGeometry>("QGeometry", "Qt3D.Render/Geometry", uri, 2, 0, "Geometry"); qmlRegisterType<Qt3DRender::QGeometryRenderer>(uri, 2, 0, "GeometryRenderer"); - // Debug components -// qmlRegisterType<Qt3DRender::QBoundingVolumeDebug>(uri, 2, 0, "BoundingVolumeDebug"); - // Mesh qmlRegisterType<Qt3DRender::QMesh>(uri, 2, 0, "Mesh"); diff --git a/src/quick3d/imports/scene3d/scene3ditem.cpp b/src/quick3d/imports/scene3d/scene3ditem.cpp index 750be8fa7..c03e77018 100644 --- a/src/quick3d/imports/scene3d/scene3ditem.cpp +++ b/src/quick3d/imports/scene3d/scene3ditem.cpp @@ -48,7 +48,7 @@ #include <Qt3DRender/qcamera.h> #include <Qt3DRender/QRenderAspect> #include <Qt3DRender/qrendersurfaceselector.h> -#include <Qt3DRender/qrendersettings.h> +#include <Qt3DRender/private/qrendersurfaceselector_p.h> #include <Qt3DInput/QInputAspect> #include <Qt3DInput/qinputsettings.h> #include <Qt3DLogic/qlogicaspect.h> @@ -198,57 +198,19 @@ void Scene3DItem::applyRootEntityChange() void Scene3DItem::setWindowSurface(QObject *rootObject) { - // Find surface selector in framegraph and set ourselves up as the - // render surface there - Qt3DRender::QRenderSettings *renderSettings - = rootObject->findChild<Qt3DRender::QRenderSettings *>(); - if (!renderSettings) { - qWarning() << "No renderer settings component found"; - return; - } - - Qt3DCore::QNode *frameGraphRoot = renderSettings->activeFrameGraph(); - if (!frameGraphRoot) { - qWarning() << "No active frame graph found"; - return; - } - - Qt3DRender::QRenderSurfaceSelector *surfaceSelector - = frameGraphRoot->findChild<Qt3DRender::QRenderSurfaceSelector *>(); - if (!surfaceSelector) { - qWarning() << "No render surface selector found in frame graph"; - return; - } + Qt3DRender::QRenderSurfaceSelector *surfaceSelector = Qt3DRender::QRenderSurfaceSelectorPrivate::find(rootObject); // Set the item's window surface if it appears // the surface wasn't set on the surfaceSelector - if (!surfaceSelector->surface()) + if (surfaceSelector && !surfaceSelector->surface()) surfaceSelector->setSurface(this->window()); } void Scene3DItem::setItemArea(const QSize &area) { - // Find surface selector in framegraph and set the area - Qt3DRender::QRenderSettings *renderSettings - = m_entity->findChild<Qt3DRender::QRenderSettings *>(); - if (!renderSettings) { - qWarning() << "No renderer settings component found"; - return; - } - - Qt3DCore::QNode *frameGraphRoot = renderSettings->activeFrameGraph(); - if (!frameGraphRoot) { - qWarning() << "No active frame graph found"; - return; - } - - Qt3DRender::QRenderSurfaceSelector *surfaceSelector - = frameGraphRoot->findChild<Qt3DRender::QRenderSurfaceSelector *>(); - if (!surfaceSelector) { - qWarning() << "No render surface selector found in frame graph"; - return; - } - surfaceSelector->setExternalRenderTargetSize(area); + Qt3DRender::QRenderSurfaceSelector *surfaceSelector = Qt3DRender::QRenderSurfaceSelectorPrivate::find(m_entity); + if (surfaceSelector) + surfaceSelector->setExternalRenderTargetSize(area); } bool Scene3DItem::isHoverEnabled() const diff --git a/src/quick3d/quick3dextras/qt3dquickwindow.cpp b/src/quick3d/quick3dextras/qt3dquickwindow.cpp index 10c932e98..8a7921d8e 100644 --- a/src/quick3d/quick3dextras/qt3dquickwindow.cpp +++ b/src/quick3d/quick3dextras/qt3dquickwindow.cpp @@ -52,8 +52,8 @@ #include <Qt3DQuick/QQmlAspectEngine> #include <Qt3DRender/qcamera.h> #include <Qt3DRender/qrenderaspect.h> -#include <Qt3DRender/qrendersettings.h> #include <Qt3DRender/qrendersurfaceselector.h> +#include <Qt3DRender/private/qrendersurfaceselector_p.h> #include <Qt3DInput/qinputaspect.h> #include <Qt3DInput/qinputsettings.h> #include <Qt3DLogic/qlogicaspect.h> @@ -230,30 +230,9 @@ void Qt3DQuickWindow::onSceneCreated(QObject *rootObject) void Qt3DQuickWindow::setWindowSurface(QObject *rootObject) { - // Find surface selector in framegraph and set ourselves up as the - // render surface there - Qt3DRender::QRenderSettings *rendererSettings - = rootObject->findChild<Qt3DRender::QRenderSettings *>(); - if (!rendererSettings) { - qWarning() << "No renderer settings component found"; - return; - } - - Qt3DCore::QNode *frameGraphRoot = rendererSettings->activeFrameGraph(); - if (!frameGraphRoot) { - qWarning() << "No active frame graph found"; - return; - } - - Qt3DRender::QRenderSurfaceSelector *surfaceSelector = qobject_cast<Qt3DRender::QRenderSurfaceSelector *>(frameGraphRoot); - if (!surfaceSelector) - surfaceSelector = frameGraphRoot->findChild<Qt3DRender::QRenderSurfaceSelector *>(); - if (!surfaceSelector) { - qWarning() << "No render surface selector found in frame graph"; - return; - } - - surfaceSelector->setSurface(this); + Qt3DRender::QRenderSurfaceSelector *surfaceSelector = Qt3DRender::QRenderSurfaceSelectorPrivate::find(rootObject); + if (surfaceSelector) + surfaceSelector->setSurface(this); } void Qt3DQuickWindow::setCameraAspectModeHelper() diff --git a/src/quick3d/quick3dextras/quick3dextras.pro b/src/quick3d/quick3dextras/quick3dextras.pro index 7af47424e..489200a0c 100644 --- a/src/quick3d/quick3dextras/quick3dextras.pro +++ b/src/quick3d/quick3dextras/quick3dextras.pro @@ -1,7 +1,7 @@ TARGET = Qt3DQuickExtras MODULE = 3dquickextras -QT += core core-private qml qml-private 3dcore 3dinput 3dquick 3drender 3dlogic +QT += core core-private qml qml-private 3dcore 3dinput 3dquick 3drender 3drender-private 3dlogic CONFIG -= precompile_header # Qt3D is free of Q_FOREACH - make sure it stays that way: diff --git a/src/render/backend/entity.cpp b/src/render/backend/entity.cpp index 7091d493f..095a5a62d 100644 --- a/src/render/backend/entity.cpp +++ b/src/render/backend/entity.cpp @@ -50,7 +50,6 @@ #include <Qt3DRender/qgeometryrenderer.h> #include <Qt3DRender/qobjectpicker.h> #include <Qt3DRender/qcomputecommand.h> -#include <Qt3DRender/private/qboundingvolumedebug_p.h> #include <Qt3DRender/private/geometryrenderermanager_p.h> #include <Qt3DRender/qcameralens.h> diff --git a/src/render/backend/handle_types_p.h b/src/render/backend/handle_types_p.h index d22ef1d90..e68f0f1c5 100644 --- a/src/render/backend/handle_types_p.h +++ b/src/render/backend/handle_types_p.h @@ -114,7 +114,7 @@ typedef Qt3DCore::QHandle<Parameter, 16> HParameter; typedef Qt3DCore::QHandle<ShaderData, 16> HShaderData; typedef Qt3DCore::QHandle<TextureImage, 16> HTextureImage; typedef Qt3DCore::QHandle<Buffer, 16> HBuffer; -typedef Qt3DCore::QHandle<Attribute, 16> HAttribute; +typedef Qt3DCore::QHandle<Attribute, 20> HAttribute; typedef Qt3DCore::QHandle<Geometry, 16> HGeometry; typedef Qt3DCore::QHandle<GeometryRenderer, 16> HGeometryRenderer; typedef Qt3DCore::QHandle<ObjectPicker, 16> HObjectPicker; diff --git a/src/render/backend/managers_p.h b/src/render/backend/managers_p.h index f2c26fd00..8d922c0d1 100644 --- a/src/render/backend/managers_p.h +++ b/src/render/backend/managers_p.h @@ -310,7 +310,7 @@ class TextureImageManager : public Qt3DCore::QResourceManager< class AttributeManager : public Qt3DCore::QResourceManager< Attribute, Qt3DCore::QNodeId, - 16, + 20, Qt3DCore::ArrayAllocatingPolicy, Qt3DCore::ObjectLevelLockingPolicy> { diff --git a/src/render/backend/renderer.cpp b/src/render/backend/renderer.cpp index 58cc4c483..c91eff86e 100644 --- a/src/render/backend/renderer.cpp +++ b/src/render/backend/renderer.cpp @@ -290,6 +290,12 @@ void Renderer::shutdown() { qCDebug(Backend) << Q_FUNC_INFO << "Requesting renderer shutdown"; m_running.store(0); + + // We delete any renderqueue that we may not have had time to render + // before the surface was destroyed + qDeleteAll(m_renderQueue->nextFrameQueue()); + m_renderQueue->reset(); + if (!m_renderThread) { releaseGraphicsResources(); } else { @@ -760,12 +766,19 @@ void Renderer::updateGLResources() } } - const QVector<HShader> activeShaderHandles = m_nodesManager->shaderManager()->activeHandles(); - for (HShader handle: activeShaderHandles) { - Shader *shader = m_nodesManager->shaderManager()->data(handle); - if (!shader->isLoaded()) { - // Compile shader - m_graphicsContext->loadShader(shader); + const QVector<HTechnique> activeTechniques = m_nodesManager->techniqueManager()->activeHandles(); + for (HTechnique techniqueHandle : activeTechniques) { + Technique *technique = m_nodesManager->techniqueManager()->data(techniqueHandle); + // If api of the renderer matches the one from the technique + if (*contextInfo() == *technique->graphicsApiFilter()) { + const auto passIds = technique->renderPasses(); + for (const QNodeId passId : passIds) { + RenderPass *renderPass = m_nodesManager->renderPassManager()->lookupResource(passId); + HShader shaderHandle = m_nodesManager->shaderManager()->lookupHandle(renderPass->shaderProgram()); + Shader *shader = m_nodesManager->shaderManager()->data(shaderHandle); + if (shader != nullptr && !shader->isLoaded()) + m_graphicsContext->loadShader(shader); + } } } @@ -798,6 +811,7 @@ Renderer::ViewSubmissionResultData Renderer::submitRenderViews(const QVector<Ren QSurface *surface = nullptr; QSurface *previousSurface = renderViews.first()->surface(); QSurface *lastUsedSurface = nullptr; + for (int i = 0; i < renderViewsCount; ++i) { // Initialize GraphicsContext for drawing // If the RenderView has a RenderStateSet defined @@ -842,13 +856,14 @@ Renderer::ViewSubmissionResultData Renderer::submitRenderViews(const QVector<Ren lastBoundFBOId = m_graphicsContext->boundFrameBufferObject(); } - // Set RenderView render state // Note: the RenderStateSet is allocated once per RV if needed // and it contains a list of StateVariant value types RenderStateSet *renderViewStateSet = renderView->stateSet(); - if (renderViewStateSet) + + // Set the RV state if not null, + if (renderViewStateSet != nullptr) m_graphicsContext->setCurrentStateSet(renderViewStateSet); - else if (surfaceHasChanged || i == 0) // Reset state to the default state on initial render view or on surface change + else m_graphicsContext->setCurrentStateSet(m_defaultRenderStateSet); // Set RenderTarget ... diff --git a/src/render/backend/renderer_p.h b/src/render/backend/renderer_p.h index ddbc4cffc..3e6ef6ffc 100644 --- a/src/render/backend/renderer_p.h +++ b/src/render/backend/renderer_p.h @@ -82,7 +82,6 @@ #include <QAtomicInt> #include <QScopedPointer> #include <QSemaphore> -#include <QThreadStorage> QT_BEGIN_NAMESPACE diff --git a/src/render/backend/renderview.cpp b/src/render/backend/renderview.cpp index 8d40f2882..9226f8fac 100644 --- a/src/render/backend/renderview.cpp +++ b/src/render/backend/renderview.cpp @@ -114,12 +114,14 @@ RenderView::StandardUniformsPFuncsHash RenderView::initializeStandardUniformSett setters.insert(StringToInt::lookupId(QLatin1String("viewMatrix")), &RenderView::viewMatrix); setters.insert(StringToInt::lookupId(QLatin1String("projectionMatrix")), &RenderView::projectionMatrix); setters.insert(StringToInt::lookupId(QLatin1String("modelView")), &RenderView::modelViewMatrix); + setters.insert(StringToInt::lookupId(QLatin1String("viewProjectionMatrix")), &RenderView::viewProjectionMatrix); setters.insert(StringToInt::lookupId(QLatin1String("modelViewProjection")), &RenderView::modelViewProjectionMatrix); setters.insert(StringToInt::lookupId(QLatin1String("mvp")), &RenderView::modelViewProjectionMatrix); setters.insert(StringToInt::lookupId(QLatin1String("inverseModelMatrix")), &RenderView::inverseModelMatrix); setters.insert(StringToInt::lookupId(QLatin1String("inverseViewMatrix")), &RenderView::inverseViewMatrix); setters.insert(StringToInt::lookupId(QLatin1String("inverseProjectionMatrix")), &RenderView::inverseProjectionMatrix); setters.insert(StringToInt::lookupId(QLatin1String("inverseModelView")), &RenderView::inverseModelViewMatrix); + setters.insert(StringToInt::lookupId(QLatin1String("inverseViewProjectionMatrix")), &RenderView::inverseViewProjectionMatrix); setters.insert(StringToInt::lookupId(QLatin1String("inverseModelViewProjection")), &RenderView::inverseModelViewProjectionMatrix); setters.insert(StringToInt::lookupId(QLatin1String("modelNormalMatrix")), &RenderView::modelNormalMatrix); setters.insert(StringToInt::lookupId(QLatin1String("modelViewNormal")), &RenderView::modelViewNormalMatrix); @@ -151,6 +153,12 @@ QUniformValue RenderView::modelViewMatrix(const QMatrix4x4 &model) const return QUniformValue(QVariant::fromValue(m_data.m_viewMatrix * model)); } +QUniformValue RenderView::viewProjectionMatrix(const QMatrix4x4 &model) const +{ + Q_UNUSED(model); + return QUniformValue(QVariant::fromValue(m_data.m_renderCameraLens->projection() * m_data.m_viewMatrix)); +} + QUniformValue RenderView::modelViewProjectionMatrix(const QMatrix4x4 &model) const { return QUniformValue(QVariant::fromValue(m_data.m_viewProjectionMatrix * model)); @@ -179,6 +187,13 @@ QUniformValue RenderView::inverseModelViewMatrix(const QMatrix4x4 &model) const return QUniformValue(QVariant::fromValue((m_data.m_viewMatrix * model).inverted())); } +QUniformValue RenderView::inverseViewProjectionMatrix(const QMatrix4x4 &model) const +{ + Q_UNUSED(model); + const auto viewProjectionMatrix = m_data.m_renderCameraLens->projection() * m_data.m_viewMatrix; + return QUniformValue(QVariant::fromValue(viewProjectionMatrix.inverted())); +} + QUniformValue RenderView::inverseModelViewProjectionMatrix(const QMatrix4x4 &model) const { return QUniformValue(QVariant::fromValue((m_data.m_viewProjectionMatrix * model).inverted(0))); @@ -383,6 +398,13 @@ void RenderView::addClearBuffers(const ClearBuffers *cb) { // If we are there, we know that entity had a GeometryRenderer + Material QVector<RenderCommand *> RenderView::buildDrawRenderCommands(const QVector<Entity *> &entities) const { + // Note: since many threads can be building render commands + // we need to ensure that the UniformBlockValueBuilder they are using + // is only accessed from the same thread + UniformBlockValueBuilder *builder = new UniformBlockValueBuilder(); + builder->shaderDataManager = m_manager->shaderDataManager(); + m_localData.setLocalData(builder); + QVector<RenderCommand *> commands; commands.reserve(entities.size()); @@ -429,6 +451,8 @@ QVector<RenderCommand *> RenderView::buildDrawRenderCommands(const QVector<Entit std::sort(lightSources.begin(), lightSources.end(), LightSourceCompare(node)); ParameterInfoList globalParameters = passData.parameterInfo; + // setShaderAndUniforms can initialize a localData + // make sure this is cleared before we leave this function setShaderAndUniforms(command, pass, globalParameters, *(node->worldTransform()), lightSources.mid(0, std::max(lightSources.size(), MAX_LIGHTS))); buildSortingKey(command); @@ -436,11 +460,22 @@ QVector<RenderCommand *> RenderView::buildDrawRenderCommands(const QVector<Entit } } } + + // We reset the local data once we are done with it + m_localData.setLocalData(nullptr); + return commands; } QVector<RenderCommand *> RenderView::buildComputeRenderCommands(const QVector<Entity *> &entities) const { + // Note: since many threads can be building render commands + // we need to ensure that the UniformBlockValueBuilder they are using + // is only accessed from the same thread + UniformBlockValueBuilder *builder = new UniformBlockValueBuilder(); + builder->shaderDataManager = m_manager->shaderDataManager(); + m_localData.setLocalData(builder); + // If the RenderView contains only a ComputeDispatch then it cares about // A ComputeDispatch is also implicitely a NoDraw operation // enabled flag @@ -477,6 +512,10 @@ QVector<RenderCommand *> RenderView::buildComputeRenderCommands(const QVector<En } } } + + // We reset the local data once we are done with it + m_localData.setLocalData(nullptr); + return commands; } @@ -612,28 +651,22 @@ void RenderView::setShaderStorageValue(ShaderParameterPack &uniformPack, void RenderView::setDefaultUniformBlockShaderDataValue(ShaderParameterPack &uniformPack, Shader *shader, ShaderData *shaderData, const QString &structName) const { - // Note: since many threads can be building render commands - // we need to ensure that the UniformBlockValueBuilder they are using - // is only accessed from the same thread - if (!m_localData.hasLocalData()) { - m_localData.setLocalData(UniformBlockValueBuilder()); - m_localData.localData().shaderDataManager = m_manager->shaderDataManager(); - } - - UniformBlockValueBuilder &builder = m_localData.localData(); - builder.activeUniformNamesToValue.clear(); + UniformBlockValueBuilder *builder = m_localData.localData(); + builder->activeUniformNamesToValue.clear(); // updates transformed properties; + // Fix me: this will lead to races when having multiple cameras shaderData->updateViewTransform(m_data.m_viewMatrix); + // Force to update the whole block - builder.updatedPropertiesOnly = false; + builder->updatedPropertiesOnly = false; // Retrieve names and description of each active uniforms in the uniform block - builder.uniforms = shader->activeUniformsForUniformBlock(-1); + builder->uniforms = shader->activeUniformsForUniformBlock(-1); // Build name-value map for the block - builder.buildActiveUniformNameValueMapStructHelper(shaderData, structName); + builder->buildActiveUniformNameValueMapStructHelper(shaderData, structName); // Set uniform values for each entrie of the block name-value map - QHash<int, QVariant>::const_iterator activeValuesIt = builder.activeUniformNamesToValue.constBegin(); - const QHash<int, QVariant>::const_iterator activeValuesEnd = builder.activeUniformNamesToValue.constEnd(); + QHash<int, QVariant>::const_iterator activeValuesIt = builder->activeUniformNamesToValue.constBegin(); + const QHash<int, QVariant>::const_iterator activeValuesEnd = builder->activeUniformNamesToValue.constEnd(); while (activeValuesIt != activeValuesEnd) { setUniformValue(uniformPack, activeValuesIt.key(), activeValuesIt.value()); diff --git a/src/render/backend/renderview_p.h b/src/render/backend/renderview_p.h index 0b01744e9..7be9903f6 100644 --- a/src/render/backend/renderview_p.h +++ b/src/render/backend/renderview_p.h @@ -242,7 +242,7 @@ private: void setShaderAndUniforms(RenderCommand *command, RenderPass *pass, ParameterInfoList ¶meters, const QMatrix4x4 &worldTransform, const QVector<LightSource> &activeLightSources) const; - mutable QThreadStorage<UniformBlockValueBuilder> m_localData; + mutable QThreadStorage<UniformBlockValueBuilder*> m_localData; Renderer *m_renderer; NodeManagers *m_manager; @@ -282,11 +282,13 @@ private: QUniformValue viewMatrix(const QMatrix4x4&) const; QUniformValue projectionMatrix(const QMatrix4x4 &) const; QUniformValue modelViewMatrix(const QMatrix4x4 &model) const; + QUniformValue viewProjectionMatrix(const QMatrix4x4 &model) const; QUniformValue modelViewProjectionMatrix(const QMatrix4x4 &model) const; QUniformValue inverseModelMatrix(const QMatrix4x4 &model) const; QUniformValue inverseViewMatrix(const QMatrix4x4 &) const; QUniformValue inverseProjectionMatrix(const QMatrix4x4 &) const; QUniformValue inverseModelViewMatrix(const QMatrix4x4 &model) const; + QUniformValue inverseViewProjectionMatrix(const QMatrix4x4 &model) const; QUniformValue inverseModelViewProjectionMatrix(const QMatrix4x4 &model) const; QUniformValue modelNormalMatrix(const QMatrix4x4 &model) const; QUniformValue modelViewNormalMatrix(const QMatrix4x4 &model) const; diff --git a/src/render/framegraph/qrendersurfaceselector.cpp b/src/render/framegraph/qrendersurfaceselector.cpp index 349ceb827..e76963e72 100644 --- a/src/render/framegraph/qrendersurfaceselector.cpp +++ b/src/render/framegraph/qrendersurfaceselector.cpp @@ -43,7 +43,9 @@ #include <QtGui/QWindow> #include <QtGui/QScreen> #include <QtGui/QOffscreenSurface> +#include <Qt3DCore/qentity.h> #include <Qt3DCore/qpropertyupdatedchange.h> +#include <Qt3DRender/qrendersettings.h> QT_BEGIN_NAMESPACE @@ -104,6 +106,30 @@ QRenderSurfaceSelectorPrivate::~QRenderSurfaceSelectorPrivate() QObject::disconnect(m_screenConn); } +QRenderSurfaceSelector *QRenderSurfaceSelectorPrivate::find(QObject *rootObject) +{ + auto rendererSettings = rootObject->findChild<Qt3DRender::QRenderSettings *>(); + if (!rendererSettings) { + qWarning() << "No renderer settings component found"; + return nullptr; + } + + auto frameGraphRoot = rendererSettings->activeFrameGraph(); + if (!frameGraphRoot) { + qWarning() << "No active frame graph found"; + return nullptr; + } + + auto surfaceSelector = qobject_cast<Qt3DRender::QRenderSurfaceSelector *>(frameGraphRoot); + if (!surfaceSelector) + surfaceSelector = frameGraphRoot->findChild<Qt3DRender::QRenderSurfaceSelector *>(); + + if (!surfaceSelector) + qWarning() << "No render surface selector found in frame graph"; + + return surfaceSelector; +} + void QRenderSurfaceSelectorPrivate::setExternalRenderTargetSize(const QSize &size) { m_externalRenderTargetSize = size; diff --git a/src/render/framegraph/qrendersurfaceselector_p.h b/src/render/framegraph/qrendersurfaceselector_p.h index d21bf744c..899387b98 100644 --- a/src/render/framegraph/qrendersurfaceselector_p.h +++ b/src/render/framegraph/qrendersurfaceselector_p.h @@ -53,6 +53,7 @@ #include <Qt3DRender/private/qframegraphnode_p.h> #include <Qt3DRender/private/platformsurfacefilter_p.h> +#include <Qt3DRender/private/qt3drender_global_p.h> #include <QtGui/qsurface.h> #include <QtGui/qwindow.h> #include <QtCore/qpointer.h> @@ -61,12 +62,17 @@ QT_BEGIN_NAMESPACE namespace Qt3DRender { -class QRenderSurfaceSelectorPrivate : public Qt3DRender::QFrameGraphNodePrivate +class QRenderSurfaceSelector; + +class QT3DRENDERSHARED_PRIVATE_EXPORT QRenderSurfaceSelectorPrivate : public Qt3DRender::QFrameGraphNodePrivate { public: QRenderSurfaceSelectorPrivate(); ~QRenderSurfaceSelectorPrivate(); + // TODO: Qt 5.8, make it public + static QRenderSurfaceSelector *find(QObject *rootObject); + void setExternalRenderTargetSize(const QSize &size); QSize externalRenderTargetSize() const { return m_externalRenderTargetSize; } diff --git a/src/render/framegraph/sortpolicy.cpp b/src/render/framegraph/sortpolicy.cpp index 628fa75e4..9631ebeab 100644 --- a/src/render/framegraph/sortpolicy.cpp +++ b/src/render/framegraph/sortpolicy.cpp @@ -74,6 +74,7 @@ QVector<QSortPolicy::SortType> SortPolicy::sortTypes() const void SortPolicy::initializeFromPeer(const QNodeCreatedChangeBasePtr &change) { + FrameGraphNode::initializeFromPeer(change); const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QSortPolicyData>>(change); const QSortPolicyData &data = typedChange->data; m_sortTypes = data.sortTypes; diff --git a/src/render/framegraph/sortpolicy_p.h b/src/render/framegraph/sortpolicy_p.h index 32d2888c3..868c1430d 100644 --- a/src/render/framegraph/sortpolicy_p.h +++ b/src/render/framegraph/sortpolicy_p.h @@ -60,7 +60,7 @@ namespace Qt3DRender { namespace Render { -class SortPolicy : public FrameGraphNode +class Q_AUTOTEST_EXPORT SortPolicy : public FrameGraphNode { public: SortPolicy(); diff --git a/src/render/frontend/qboundingvolumedebug.cpp b/src/render/frontend/qboundingvolumedebug.cpp deleted file mode 100644 index 4ee6816d6..000000000 --- a/src/render/frontend/qboundingvolumedebug.cpp +++ /dev/null @@ -1,182 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB). -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt3D module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#if 0 - -#include "qboundingvolumedebug_p.h" -#include <Qt3DCore/qentity.h> -#include <Qt3DCore/private/qcomponent_p.h> -#include <Qt3DCore/qpropertyupdatedchange.h> -#include <Qt3DRender/qspheremesh.h> -#include <Qt3DCore/qtransform.h> -#include <Qt3DRender/qphongalphamaterial.h> -#include <Qt3DRender/qlayer.h> -#include <QThread> - -QT_BEGIN_NAMESPACE - -namespace Qt3DRender { - -class QBoundingVolumeDebugPrivate : public Qt3DCore::QComponentPrivate -{ -public: - QBoundingVolumeDebugPrivate() - : QComponentPrivate() - , m_recursive(false) - , m_debugSubtree(nullptr) - , m_sphereMesh(nullptr) - , m_transform(nullptr) - , m_material(nullptr) - , m_layer(nullptr) - , m_bvRadius(0.0f) - { - m_shareable = false; - } - - Q_DECLARE_PUBLIC(QBoundingVolumeDebug) - - bool m_recursive; - Qt3DCore::QEntity *m_debugSubtree; - Qt3DRender::QSphereMesh *m_sphereMesh; - Qt3DCore::QTransform *m_transform; - Qt3DRender::QMaterial *m_material; - Qt3DRender::QLayer *m_layer; - - float m_bvRadius; - QVector3D m_bvCenter; - - Qt3DCore::QEntity *findRootEntity(Qt3DCore::QEntity *e); - void updateSubtree(); -}; - -QBoundingVolumeDebug::QBoundingVolumeDebug(Qt3DCore::QNode *parent) - : QComponent(*new QBoundingVolumeDebugPrivate(), parent) -{ -} - -QBoundingVolumeDebug::~QBoundingVolumeDebug() -{ - QComponent::cleanup(); -} - -void QBoundingVolumeDebug::setRecursive(bool recursive) -{ - Q_D(QBoundingVolumeDebug); - if (d->m_recursive != recursive) { - d->m_recursive = recursive; - emit recursiveChanged(recursive); - } -} - -bool QBoundingVolumeDebug::recursive() const -{ - Q_D(const QBoundingVolumeDebug); - return d->m_recursive; -} - -void QBoundingVolumeDebug::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) -{ - Q_D(QBoundingVolumeDebug); - Qt3DCore::QPropertyUpdatedChangePtr e = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(change); - if (e->type() == Qt3DCore::PropertyUpdated) { - if (e->propertyName() == QByteArrayLiteral("center")) { - d->m_bvCenter = e->value().value<QVector3D>(); - d->updateSubtree(); - } else if (e->propertyName() == QByteArrayLiteral("radius")) { - d->m_bvRadius = e->value().toFloat(); - d->updateSubtree(); - } - } -} - -// Executed in the frontend thread -Qt3DCore::QEntity *QBoundingVolumeDebugPrivate::findRootEntity(Qt3DCore::QEntity *e) -{ - Qt3DCore::QEntity *tmp = nullptr; - Qt3DCore::QEntity *parentEntity = nullptr; - while (e && (tmp = e->parentEntity()) != nullptr) { - parentEntity = tmp; - e = parentEntity; - } - return parentEntity; -} - -void QBoundingVolumeDebugPrivate::updateSubtree() -{ - Q_Q(QBoundingVolumeDebug); - if (m_debugSubtree == nullptr) { - m_debugSubtree = new Qt3DCore::QEntity(); - m_sphereMesh = new Qt3DRender::QSphereMesh(); - m_transform = new Qt3DCore::QTransform(); - m_material = new Qt3DRender::QPhongAlphaMaterial(); - m_layer = new Qt3DRender::QLayer(); - - static_cast<QPhongAlphaMaterial *>(m_material)->setAlpha(0.3f); - static_cast<QPhongAlphaMaterial *>(m_material)->setDiffuse(QColor::fromRgb(255, 153, 0)); - - m_layer->setNames(QStringList() << QStringLiteral("debug")); - - m_debugSubtree->addComponent(m_sphereMesh); - m_debugSubtree->addComponent(m_transform); - m_debugSubtree->addComponent(m_material); - m_debugSubtree->addComponent(m_layer); - - m_transform->setTranslation(m_bvCenter); - m_transform->setScale(m_bvRadius * 2.0f); - m_sphereMesh->setRadius(0.5f); - m_sphereMesh->setRings(100); - m_sphereMesh->setSlices(100); - - // Insert into scene - if (q->entities().size() > 0) { - Qt3DCore::QEntity *rootEntity = findRootEntity(q->entities().constFirst()); - m_debugSubtree->setParent(rootEntity ? rootEntity : q->entities().constFirst()); - } - } else { - // Just update the mesh - m_transform->setTranslation(m_bvCenter); - m_transform->setScale(m_bvRadius * 2.0f); - } -} - -} // Qt3DRender - -QT_END_NAMESPACE - -#endif diff --git a/src/render/frontend/qlayer.cpp b/src/render/frontend/qlayer.cpp index e9f23a015..cd7d92caf 100644 --- a/src/render/frontend/qlayer.cpp +++ b/src/render/frontend/qlayer.cpp @@ -53,7 +53,38 @@ QLayerPrivate::QLayerPrivate() \class Qt3DRender::QLayer \inmodule Qt3DRender \since 5.5 - \brief The QLayer class provides ... + \brief The QLayer class provides a way of filtering which entities will be rendered. + + Qt3DRender::QLayer works in conjunction with the Qt3DRender::QLayerFilter in the FrameGraph. + \sa Qt3DRender::QLayerFilter + + Qt3DRender::QLayer doesn't define any new properties but is supposed to only be referenced. + + \code + #include <Qt3DCore/QEntity> + #include <Qt3DRender/QGeometryRenderer> + #include <Qt3DRender/QLayer> + #include <Qt3DRender/QLayerFilter> + #include <Qt3DRender/QViewport> + + // Scene + Qt3DCore::QEntity *rootEntity = new Qt3DCore::Qt3DCore::QEntity; + + Qt3DCore::QEntity *renderableEntity = new Qt3DCore::Qt3DCore::QEntity(rootEntity); + Qt3DRender::QGeometryRenderer *geometryRenderer = new Qt3DCore::QGeometryRenderer(renderableEntity); + Qt3DRender::QLayer *layer1 = new Qt3DCore::QLayer(renderableEntity); + renderableEntity->addComponent(geometryRenderer); + renderableEntity->addComponent(layer1); + + ... + + // FrameGraph + Qt3DRender::QViewport *viewport = new Qt3DRender::QViewport; + Qt3DRender::QLayerFilter *layerFilter = new Qt3DRender::QLayerFilter(viewport); + layerFilter->addLayer(layer1); + + ... + \endcode */ /*! @@ -62,7 +93,48 @@ QLayerPrivate::QLayerPrivate() \inherits Component3D \inqmlmodule Qt3D.Render \since 5.5 - \brief For ... + \sa LayerFilter + \brief Layer provides a way of filtering which entities will be rendered. + + Layer works in conjunction with the LayerFilter in the FrameGraph. + + Layer doesn't define any new properties but is supposed to only be referenced. + + \code + import Qt3D.Core 2.0 + import Qt3D.Render 2.0 + + Entity { + id: root + + components: RenderSettings { + // FrameGraph + Viewport { + ClearBuffers { + buffers: ClearBuffers.ColorDepthBuffer + CameraSelector { + camera: mainCamera + LayerFilter { + layers: [layer1] + } + } + } + } + } + + // Scene + Camera { id: mainCamera } + + Layer { id: layer1 } + + GeometryRenderer { id: mesh } + + Entity { + id: renderableEntity + components: [ mesh, layer1 ] + } + } + \endcode */ /*! \fn Qt3DRender::QLayer::QLayer(Qt3DCore::QNode *parent) diff --git a/src/render/frontend/qrenderaspect.cpp b/src/render/frontend/qrenderaspect.cpp index 03a939a13..5a8195b64 100644 --- a/src/render/frontend/qrenderaspect.cpp +++ b/src/render/frontend/qrenderaspect.cpp @@ -77,7 +77,6 @@ #include <Qt3DRender/qrendersurfaceselector.h> #include <Qt3DRender/qrendersettings.h> -#include <Qt3DRender/private/qboundingvolumedebug_p.h> #include <Qt3DRender/private/cameraselectornode_p.h> #include <Qt3DRender/private/layerfilternode_p.h> #include <Qt3DRender/private/filterkey_p.h> @@ -173,6 +172,9 @@ void QRenderAspectPrivate::registerBackendTypes() { Q_Q(QRenderAspect); + qRegisterMetaType<Qt3DRender::QBuffer*>(); + qRegisterMetaType<Qt3DRender::QEffect*>(); + q->registerBackendType<Qt3DCore::QEntity>(QSharedPointer<Render::RenderEntityFunctor>::create(m_renderer, m_nodeManagers)); q->registerBackendType<Qt3DCore::QTransform>(QSharedPointer<Render::NodeFunctor<Render::Transform, Render::TransformManager> >::create(m_renderer, m_nodeManagers->transformManager())); @@ -222,7 +224,6 @@ void QRenderAspectPrivate::registerBackendTypes() q->registerBackendType<QViewport>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::ViewportNode, QViewport> >::create(m_renderer, m_nodeManagers->frameGraphManager())); // Picking - // q->registerBackendType<QBoundingVolumeDebug>(QSharedPointer<Render::NodeFunctor<Render::BoundingVolumeDebug, Render::BoundingVolumeDebugManager> >::create(m_renderer, m_nodeManagers->boundingVolumeDebugManager())); q->registerBackendType<QObjectPicker>(QSharedPointer<Render::NodeFunctor<Render::ObjectPicker, Render::ObjectPickerManager> >::create(m_renderer, m_nodeManagers->objectPickerManager())); } @@ -278,7 +279,6 @@ void QRenderAspectPrivate::unregisterBackendTypes() unregisterBackendType<QViewport>(); // Picking - // unregisterBackendType<QBoundingVolumeDebug>(); unregisterBackendType<QObjectPicker>(); } diff --git a/src/render/frontend/render-frontend.pri b/src/render/frontend/render-frontend.pri index 5f5246518..829e3d756 100644 --- a/src/render/frontend/render-frontend.pri +++ b/src/render/frontend/render-frontend.pri @@ -10,7 +10,6 @@ HEADERS += \ $$PWD/qrendertarget.h \ $$PWD/qrendertarget_p.h \ $$PWD/sphere_p.h \ - $$PWD/qboundingvolumedebug_p.h \ $$PWD/qcamera_p.h \ $$PWD/qcamera.h \ $$PWD/qcameralens.h \ @@ -31,7 +30,6 @@ SOURCES += \ $$PWD/sphere.cpp \ $$PWD/qlayer.cpp \ $$PWD/qrendertarget.cpp \ - $$PWD/qboundingvolumedebug.cpp \ $$PWD/qcamera.cpp \ $$PWD/qcameralens.cpp \ $$PWD/qrendersettings.cpp \ diff --git a/src/render/geometry/qattribute.cpp b/src/render/geometry/qattribute.cpp index 3067b0527..ef439f2b4 100644 --- a/src/render/geometry/qattribute.cpp +++ b/src/render/geometry/qattribute.cpp @@ -65,7 +65,12 @@ QAttributePrivate::QAttributePrivate() * \qmltype Attribute * \instantiates Qt3DRender::QAttribute * \inqmlmodule Qt3D.Render - * \brief Uncreatable + * \brief Defines an attribute and how data should be read from a Buffer. + * + * When providing your own attributes, it may make sense to name your attribute + * using helpers such as QAttribute::defaultPositionAttributeName() as that + * will ensure your geometry will be compatible with picking and the various + * materials provided in the Qt3DExtras module. */ /*! @@ -74,6 +79,14 @@ QAttributePrivate::QAttributePrivate() * * \inherits Qt3DCore::QNode * + * \brief Defines an attribute and how data should be read from a QBuffer. + * + * When providing your own attributes, it may make sense to name your attribute + * using helpers such as QAttribute::defaultPositionAttributeName() as that + * will ensure your geometry will be compatible with picking and the various + * materials provided in the Qt3DExtras module. + * + * \sa QBuffer. */ /*! @@ -119,7 +132,7 @@ QAttribute::QAttribute(QNode *parent) * and \a stride with \a parent. */ QAttribute::QAttribute(QBuffer *buf, VertexBaseType type, uint dataSize, uint count, uint offset, uint stride, QNode *parent) - : QNode(*new QAttributePrivate(), parent) + : QAttribute(parent) { Q_D(QAttribute); setBuffer(buf); @@ -136,7 +149,7 @@ QAttribute::QAttribute(QBuffer *buf, VertexBaseType type, uint dataSize, uint co * dataSize, \a count, \a offset, and \a stride with \a parent. */ QAttribute::QAttribute(QBuffer *buf, const QString &name, VertexBaseType type, uint dataSize, uint count, uint offset, uint stride, QNode *parent) - : QNode(*new QAttributePrivate(), parent) + : QAttribute(parent) { Q_D(QAttribute); setBuffer(buf); diff --git a/src/render/geometry/qbuffer.cpp b/src/render/geometry/qbuffer.cpp index 779f808f7..e63798027 100644 --- a/src/render/geometry/qbuffer.cpp +++ b/src/render/geometry/qbuffer.cpp @@ -59,6 +59,9 @@ QBufferPrivate::QBufferPrivate() * \qmltype Buffer * \instantiates Qt3DRender::QBuffer * \inqmlmodule Qt3D.Render + * + * \brief Provides a data store for raw data to later be used as vertices or + * uniforms. */ /*! @@ -89,6 +92,16 @@ QBufferPrivate::QBufferPrivate() * \inmodule Qt3DRender * * \inherits Qt3DCore::QNode + * + * \brief Provides a data store for raw data to later be used as vertices or + * uniforms. + * + * Data can either be provided directly using QBuffer::setData() or by + * specifying a generator with QBuffer::setDataGenerator() and providing a + * Qt3DRender::QBufferDataGeneratorPtr. + * + * When using a generator the data will be loaded asynchronously in a job. The + * loaded data can be read back if the QBuffer::syncData flag is set to true. */ /*! diff --git a/src/render/graphicshelpers/graphicscontext.cpp b/src/render/graphicshelpers/graphicscontext.cpp index 5169c8fb4..acec8edf6 100644 --- a/src/render/graphicshelpers/graphicscontext.cpp +++ b/src/render/graphicshelpers/graphicscontext.cpp @@ -71,6 +71,7 @@ #include <Qt3DRender/private/graphicshelpergl4_p.h> #endif #include <Qt3DRender/private/graphicshelperes2_p.h> +#include <Qt3DRender/private/graphicshelperes3_p.h> #include <QSurface> #include <QWindow> @@ -285,7 +286,6 @@ void GraphicsContext::endDrawing(bool swapBuffers) m_gl->swapBuffers(m_surface); if (m_ownCurrent) m_gl->doneCurrent(); - m_stateSet = nullptr; decayTextureScores(); } @@ -557,7 +557,7 @@ void GraphicsContext::bindFrameBufferAttachmentHelper(GLuint fboId, const Attach if (fboSize.isEmpty()) fboSize = QSize(glTex->width(), glTex->height()); else - fboSize = QSize(qMin(fboSize.width(), glTex->width()), qMin(fboSize.width(), glTex->width())); + fboSize = QSize(qMin(fboSize.width(), glTex->width()), qMin(fboSize.height(), glTex->height())); m_glHelper->bindFrameBufferAttachment(glTex, attachment); } } @@ -647,7 +647,10 @@ GraphicsHelperInterface *GraphicsContext::resolveHighestOpenGLFunctions() GraphicsHelperInterface *glHelper = nullptr; if (m_gl->isOpenGLES()) { - glHelper = new GraphicsHelperES2(); + if (m_gl->format().majorVersion() >= 3) + glHelper = new GraphicsHelperES3(); + else + glHelper = new GraphicsHelperES2(); glHelper->initializeHelper(m_gl, nullptr); qCDebug(Backend) << Q_FUNC_INFO << " Building OpenGL 2/ES2 Helper"; } diff --git a/src/render/graphicshelpers/graphicshelperes2.cpp b/src/render/graphicshelpers/graphicshelperes2.cpp index 6bf287cee..b09e33291 100644 --- a/src/render/graphicshelpers/graphicshelperes2.cpp +++ b/src/render/graphicshelpers/graphicshelperes2.cpp @@ -80,9 +80,6 @@ void GraphicsHelperES2::initializeHelper(QOpenGLContext *context, Q_ASSERT(context); m_funcs = context->functions(); Q_ASSERT(m_funcs); - m_isES3 = context->format().majorVersion() >= 3; - if (m_isES3) - m_extraFuncs = QOpenGLContext::currentContext()->extraFunctions(); } void GraphicsHelperES2::drawElementsInstancedBaseVertexBaseInstance(GLenum primitiveType, @@ -99,19 +96,11 @@ void GraphicsHelperES2::drawElementsInstancedBaseVertexBaseInstance(GLenum primi if (baseVertex != 0) qWarning() << "glDrawElementsInstancedBaseVertex is not supported with OpenGL ES 2"; - if (m_isES3 && m_extraFuncs) { - m_extraFuncs->glDrawElementsInstanced(primitiveType, - primitiveCount, - indexType, - indices, - instances); - } else { - for (GLint i = 0; i < instances; i++) - drawElements(primitiveType, - primitiveCount, - indexType, - indices); - } + for (GLint i = 0; i < instances; i++) + drawElements(primitiveType, + primitiveCount, + indexType, + indices); } void GraphicsHelperES2::drawArraysInstanced(GLenum primitiveType, @@ -241,8 +230,8 @@ QVector<ShaderStorageBlock> GraphicsHelperES2::programShaderStorageBlocks(GLuint void GraphicsHelperES2::vertexAttribDivisor(GLuint index, GLuint divisor) { - if (m_isES3 && m_extraFuncs) - m_extraFuncs->glVertexAttribDivisor(index, divisor); + Q_UNUSED(index); + Q_UNUSED(divisor); } void GraphicsHelperES2::blendEquation(GLenum mode) @@ -365,7 +354,7 @@ bool GraphicsHelperES2::supportsFeature(GraphicsHelperInterface::Feature feature return false; } } -void GraphicsHelperES2::drawBuffers(GLsizei , const int *) +void GraphicsHelperES2::drawBuffers(GLsizei, const int *) { qWarning() << "drawBuffers is not supported by ES 2.0"; } @@ -462,13 +451,8 @@ void GraphicsHelperES2::bindUniform(const QVariant &v, const ShaderUniform &desc case GL_SAMPLER_CUBE_SHADOW: case GL_SAMPLER_2D_ARRAY: case GL_SAMPLER_2D_ARRAY_SHADOW: - if (m_isES3) { - Q_ASSERT(description.m_size == 1); - m_funcs->glUniform1i(description.m_location, v.toInt()); - } else { - qWarning() << Q_FUNC_INFO << "ES 3.0 uniform type" << description.m_type << "for" - << description.m_name << "is not supported in ES 2.0"; - } + qWarning() << Q_FUNC_INFO << "ES 3.0 uniform type" << description.m_type << "for" + << description.m_name << "is not supported in ES 2.0"; break; default: diff --git a/src/render/graphicshelpers/graphicshelperes2_p.h b/src/render/graphicshelpers/graphicshelperes2_p.h index 5f4413e09..df8f148a9 100644 --- a/src/render/graphicshelpers/graphicshelperes2_p.h +++ b/src/render/graphicshelpers/graphicshelperes2_p.h @@ -118,10 +118,8 @@ public: uint uniformByteSize(const ShaderUniform &description) Q_DECL_OVERRIDE; void useProgram(GLuint programId) Q_DECL_OVERRIDE; void vertexAttribDivisor(GLuint index, GLuint divisor) Q_DECL_OVERRIDE; -private: +protected: QOpenGLFunctions *m_funcs; - QOpenGLExtraFunctions *m_extraFuncs = nullptr; - bool m_isES3; }; } // namespace Render diff --git a/src/render/graphicshelpers/graphicshelperes3.cpp b/src/render/graphicshelpers/graphicshelperes3.cpp new file mode 100644 index 000000000..fe39d9d3f --- /dev/null +++ b/src/render/graphicshelpers/graphicshelperes3.cpp @@ -0,0 +1,173 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB). +** Copyright (C) 2016 Svenn-Arne Dragly. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "graphicshelperes3_p.h" +#include <private/attachmentpack_p.h> +#include <QOpenGLExtraFunctions> + +QT_BEGIN_NAMESPACE + +// ES 3.0+ +#ifndef GL_SAMPLER_3D +#define GL_SAMPLER_3D 0x8B5F +#endif +#ifndef GL_SAMPLER_2D_SHADOW +#define GL_SAMPLER_2D_SHADOW 0x8B62 +#endif +#ifndef GL_SAMPLER_CUBE_SHADOW +#define GL_SAMPLER_CUBE_SHADOW 0x8DC5 +#endif +#ifndef GL_SAMPLER_2D_ARRAY +#define GL_SAMPLER_2D_ARRAY 0x8DC1 +#endif +#ifndef GL_SAMPLER_2D_ARRAY_SHADOW +#define GL_SAMPLER_2D_ARRAY_SHADOW 0x8DC4 +#endif + +namespace Qt3DRender { +namespace Render { + +GraphicsHelperES3::GraphicsHelperES3() +{ +} + +GraphicsHelperES3::~GraphicsHelperES3() +{ +} + +void GraphicsHelperES3::initializeHelper(QOpenGLContext *context, + QAbstractOpenGLFunctions *functions) +{ + GraphicsHelperES2::initializeHelper(context, functions); + m_extraFuncs = context->extraFunctions(); + Q_ASSERT(m_extraFuncs); +} + +void GraphicsHelperES3::drawElementsInstancedBaseVertexBaseInstance(GLenum primitiveType, + GLsizei primitiveCount, + GLint indexType, + void *indices, + GLsizei instances, + GLint baseVertex, + GLint baseInstance) +{ + if (baseInstance != 0) + qWarning() << "glDrawElementsInstancedBaseVertexBaseInstance is not supported with OpenGL ES 3"; + + if (baseVertex != 0) + qWarning() << "glDrawElementsInstancedBaseVertex is not supported with OpenGL ES 3"; + + m_extraFuncs->glDrawElementsInstanced(primitiveType, + primitiveCount, + indexType, + indices, + instances); +} + +void GraphicsHelperES3::vertexAttribDivisor(GLuint index, GLuint divisor) +{ + m_extraFuncs->glVertexAttribDivisor(index, divisor); +} + +void GraphicsHelperES3::bindFrameBufferAttachment(QOpenGLTexture *texture, const Attachment &attachment) +{ + GLenum attr = GL_COLOR_ATTACHMENT0; + + if (attachment.m_point <= QRenderTargetOutput::Color15) + attr = GL_COLOR_ATTACHMENT0 + attachment.m_point; + else if (attachment.m_point == QRenderTargetOutput::Depth) + attr = GL_DEPTH_ATTACHMENT; + else if (attachment.m_point == QRenderTargetOutput::Stencil) + attr = GL_STENCIL_ATTACHMENT; + else + qCritical() << "Unsupported FBO attachment OpenGL ES 3.0"; + + texture->bind(); + QOpenGLTexture::Target target = texture->target(); + if (target == QOpenGLTexture::Target2D) + m_funcs->glFramebufferTexture2D(GL_FRAMEBUFFER, attr, target, texture->textureId(), attachment.m_mipLevel); + else if (target == QOpenGLTexture::TargetCubeMap) + m_funcs->glFramebufferTexture2D(GL_FRAMEBUFFER, attr, attachment.m_face, texture->textureId(), attachment.m_mipLevel); + else + qCritical() << "Unsupported Texture FBO attachment format"; + texture->release(); +} + +bool GraphicsHelperES3::supportsFeature(GraphicsHelperInterface::Feature feature) const +{ + switch (feature) { + case RenderBufferDimensionRetrieval: + case MRT: + return true; + default: + return false; + } +} + +void GraphicsHelperES3::drawBuffers(GLsizei n, const int *bufs) +{ + QVarLengthArray<GLenum, 16> drawBufs(n); + + for (int i = 0; i < n; i++) + drawBufs[i] = GL_COLOR_ATTACHMENT0 + bufs[i]; + m_extraFuncs->glDrawBuffers(n, drawBufs.constData()); +} + +void GraphicsHelperES3::bindUniform(const QVariant &v, const ShaderUniform &description) +{ + switch (description.m_type) { + case GL_SAMPLER_3D: + case GL_SAMPLER_2D_SHADOW: + case GL_SAMPLER_CUBE_SHADOW: + case GL_SAMPLER_2D_ARRAY: + case GL_SAMPLER_2D_ARRAY_SHADOW: + Q_ASSERT(description.m_size == 1); + m_funcs->glUniform1i(description.m_location, v.toInt()); + break; + default: + GraphicsHelperES2::bindUniform(v, description); + break; + } +} + +} // namespace Render +} // namespace Qt3DRender + +QT_END_NAMESPACE diff --git a/src/render/frontend/qboundingvolumedebug_p.h b/src/render/graphicshelpers/graphicshelperes3_p.h index 8ffe556b5..e5bb51c53 100644 --- a/src/render/frontend/qboundingvolumedebug_p.h +++ b/src/render/graphicshelpers/graphicshelperes3_p.h @@ -1,6 +1,7 @@ /**************************************************************************** ** -** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB). +** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB). +** Copyright (C) 2016 Svenn-Arne Dragly. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt3D module of the Qt Toolkit. @@ -37,10 +38,8 @@ ** ****************************************************************************/ -#if 0 - -#ifndef QT3DRENDER_QBOUNDINGVOLUMEDEBUG_P_H -#define QT3DRENDER_QBOUNDINGVOLUMEDEBUG_P_H +#ifndef QT3DRENDER_RENDER_GRAPHICSHELPERES3_H +#define QT3DRENDER_RENDER_GRAPHICSHELPERES3_H // // W A R N I N G @@ -53,46 +52,34 @@ // We mean it. // -#include <Qt3DCore/qcomponent.h> -#include <Qt3DRender/qt3drender_global.h> +#include <Qt3DRender/private/graphicshelperes2_p.h> QT_BEGIN_NAMESPACE namespace Qt3DRender { +namespace Render { -class QGeometry; -class QBoundingVolumeDebugPrivate; - -class QT3DRENDERSHARED_EXPORT QBoundingVolumeDebug : public Qt3DCore::QComponent +class GraphicsHelperES3 : public GraphicsHelperES2 { - Q_OBJECT - Q_PROPERTY(bool recursive READ recursive WRITE setRecursive NOTIFY recursiveChanged) - public: - explicit QBoundingVolumeDebug(Qt3DCore::QNode *parent = nullptr); - ~QBoundingVolumeDebug(); - - bool recursive() const; - -public Q_SLOTS: - void setRecursive(bool recursive); - -Q_SIGNALS: - void recursiveChanged(bool recursive); - + GraphicsHelperES3(); + virtual ~GraphicsHelperES3(); + + // QGraphicHelperInterface interface + virtual void bindFrameBufferAttachment(QOpenGLTexture *texture, const Attachment &attachment) Q_DECL_OVERRIDE; + virtual void bindUniform(const QVariant &v, const ShaderUniform &description) Q_DECL_OVERRIDE; + virtual void drawBuffers(GLsizei n, const int *bufs) Q_DECL_OVERRIDE; + virtual void drawElementsInstancedBaseVertexBaseInstance(GLenum primitiveType, GLsizei primitiveCount, GLint indexType, void *indices, GLsizei instances, GLint baseVertex = 0, GLint baseInstance = 0) Q_DECL_OVERRIDE; + virtual void initializeHelper(QOpenGLContext *context, QAbstractOpenGLFunctions *functions) Q_DECL_OVERRIDE; + virtual bool supportsFeature(Feature feature) const Q_DECL_OVERRIDE; + virtual void vertexAttribDivisor(GLuint index, GLuint divisor) Q_DECL_OVERRIDE; protected: - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) Q_DECL_OVERRIDE; - -private: - Q_DECLARE_PRIVATE(QBoundingVolumeDebug) - - // TODO: Handle creation changes + QOpenGLExtraFunctions *m_extraFuncs = Q_NULLPTR; }; -} // Qt3DRender +} // namespace Render +} // namespace Qt3DRender QT_END_NAMESPACE -#endif // QT3DRENDER_QBOUNDINGVOLUMEDEBUG_P_H - -#endif +#endif // QT3DRENDER_RENDER_GRAPHICSHELPERES3_H diff --git a/src/render/graphicshelpers/graphicshelpers.pri b/src/render/graphicshelpers/graphicshelpers.pri index a5dcbe808..ecf2e6b54 100644 --- a/src/render/graphicshelpers/graphicshelpers.pri +++ b/src/render/graphicshelpers/graphicshelpers.pri @@ -6,6 +6,7 @@ HEADERS += \ $$PWD/graphicscontext_p.h \ $$PWD/graphicshelperinterface_p.h \ $$PWD/graphicshelperes2_p.h \ + $$PWD/graphicshelperes3_p.h \ $$PWD/graphicshelpergl2_p.h \ $$PWD/graphicshelpergl3_p.h \ $$PWD/graphicshelpergl3_3_p.h \ @@ -14,6 +15,7 @@ HEADERS += \ SOURCES += \ $$PWD/graphicscontext.cpp \ $$PWD/graphicshelperes2.cpp \ + $$PWD/graphicshelperes3.cpp \ $$PWD/graphicshelpergl2.cpp \ $$PWD/graphicshelpergl3.cpp \ $$PWD/graphicshelpergl3_3.cpp \ diff --git a/src/render/io/qsceneloader.cpp b/src/render/io/qsceneloader.cpp index 215f8edd0..2d0c3311c 100644 --- a/src/render/io/qsceneloader.cpp +++ b/src/render/io/qsceneloader.cpp @@ -67,6 +67,28 @@ QSceneLoaderPrivate::QSceneLoaderPrivate() \brief Provides the facility to load an existing Scene + Given a 3D source file, the Qt3DRender::QSceneLoader will try to parse it and + build a tree of Qt3DCore::QEntity with proper Qt3DRender::QGeometryRenderer + Qt3DCore::QTransform and QtRender::QMaterial components. + + The loader will try to determine the best material to be used based on the properties + of the model file. If you wish to use a custom material, you will have to traverse + the tree and replace the default associated materials with yours. + + As the name implies, Qt3DRender::QSceneLoader loads a complete scene subtree. + If you wish to load a single piece of geometry, you should rather be using + the Qt3DRender::QMesh instead. + + Qt3DRender::QSceneLoader internally relies on the use of plugins to support a + wide variety of 3D file formats. \l + {http://www.assimp.org/main_features_formats.html}{Here} is a list of formats + that are supported by Qt3D. + + \note this component shouldn't be shared among several Qt3DCore::QEntity instances. + Undefined behavior will result. + + \sa Qt3DRender::QMesh + \sa Qt3DRender::QGeometryRenderer */ /*! @@ -76,16 +98,40 @@ QSceneLoaderPrivate::QSceneLoaderPrivate() \inherits Component \since 5.7 \qmlabstract Provides the facility to load an existing Scene + + Given a 3D source file, the SceneLoader will try to parse it and build a + tree of Entity with proper GeometryRenderer, Transform and Material + components. + + The loader will try to determine the best material to be used based on the + properties of the model file. If you wish to use a custom material, you + will have to traverse the tree and replace the default associated materials + with yours. + + As the name implies, SceneLoader loads a complete scene subtree. If you + wish to load a single piece of geometry, you should rather be using the + Mesh instead. + + SceneLoader internally relies on the use of plugins to support a wide + variety of 3D file formats. \l + {http://www.assimp.org/main_features_formats.html}{Here} is a list of + formats that are supported by Qt3D. + + \note this component shouldn't be shared among several Entity instances. + Undefined behavior will result. + + \sa Mesh + \sa GeometryRenderer */ /*! \enum QSceneLoader::Status This enum identifies the state of loading - \value None - \value Loading - \value Ready - \value Error + \value None The Qt3DRender::QSceneLoader hasn't been used yet. + \value Loading The Qt3DRender::QSceneLoader is currently loading the scene file. + \value Ready The Qt3DRender::QSceneLoader successfully loaded the scene file. + \value Error The Qt3DRender::QSceneLoader encountered an error while loading the scene file. */ /*! diff --git a/src/render/jobs/filterlayerentityjob.cpp b/src/render/jobs/filterlayerentityjob.cpp index 5e3536cf2..d22b61337 100644 --- a/src/render/jobs/filterlayerentityjob.cpp +++ b/src/render/jobs/filterlayerentityjob.cpp @@ -93,6 +93,10 @@ void FilterLayerEntityJob::filterLayerAndEntity() for (const HEntity handle : handles) { Entity *entity = entityManager->data(handle); + + if (!entity->isEnabled()) + continue; + const Qt3DCore::QNodeIdVector entityLayers = entity->componentsUuid<Layer>(); // An Entity is positively filtered if it contains at least one Layer component with the same id as the @@ -114,8 +118,11 @@ void FilterLayerEntityJob::selectAllEntities() const QVector<HEntity> handles = entityManager->activeHandles(); m_filteredEntities.reserve(handles.size()); - for (const HEntity handle : handles) - m_filteredEntities.push_back(entityManager->data(handle)); + for (const HEntity handle : handles) { + Entity *e = entityManager->data(handle); + if (e->isEnabled()) + m_filteredEntities.push_back(e); + } } } // Render diff --git a/src/render/jobs/frustumcullingjob_p.h b/src/render/jobs/frustumcullingjob_p.h index 087b7687c..cb4b38b2b 100644 --- a/src/render/jobs/frustumcullingjob_p.h +++ b/src/render/jobs/frustumcullingjob_p.h @@ -62,7 +62,7 @@ namespace Render { class Entity; class EntityManager; -class Plane; +struct Plane; class FrustumCullingJob : public Qt3DCore::QAspectJob { diff --git a/src/render/jobs/loadscenejob.cpp b/src/render/jobs/loadscenejob.cpp index d0d8be9ef..758e0b135 100644 --- a/src/render/jobs/loadscenejob.cpp +++ b/src/render/jobs/loadscenejob.cpp @@ -63,23 +63,29 @@ void LoadSceneJob::run() { // Iterate scene IO handlers until we find one that can handle this file type Qt3DCore::QEntity *sceneSubTree = nullptr; - for (QSceneIOHandler *sceneIOHandler : qAsConst(m_sceneIOHandlers)) { - if (!sceneIOHandler->isFileTypeSupported(m_source)) - continue; - // File type is supported, try to load it - sceneIOHandler->setSource(m_source); - Qt3DCore::QEntity *sub = sceneIOHandler->scene(); - if (sub) { - sceneSubTree = sub; - break; + // Perform the loading only if the source wasn't explicitly set to empty + if (!m_source.isEmpty()) { + for (QSceneIOHandler *sceneIOHandler : qAsConst(m_sceneIOHandlers)) { + if (!sceneIOHandler->isFileTypeSupported(m_source)) + continue; + + // File type is supported, try to load it + sceneIOHandler->setSource(m_source); + Qt3DCore::QEntity *sub = sceneIOHandler->scene(); + if (sub) { + sceneSubTree = sub; + break; + } } } - // Set clone of sceneTree in sceneComponent. This will move the sceneSubTree // to the QCoreApplication thread which is where the frontend object tree lives. Scene *scene = m_managers->sceneManager()->lookupResource(m_sceneComponent); - if (scene && sceneSubTree) + + // If the sceneSubTree is null it will trigger the frontend to unload + // any subtree it may hold + if (scene) scene->setSceneSubtree(sceneSubTree); } diff --git a/src/render/jobs/pickboundingvolumejob.cpp b/src/render/jobs/pickboundingvolumejob.cpp index 5c713e1a7..11faf5138 100644 --- a/src/render/jobs/pickboundingvolumejob.cpp +++ b/src/render/jobs/pickboundingvolumejob.cpp @@ -118,6 +118,15 @@ private: return vca; } + bool isUnique(const QVector<ViewportCameraAreaTriplet> &vcaTriplets, const ViewportCameraAreaTriplet &vca) const + { + for (const ViewportCameraAreaTriplet &triplet : vcaTriplets) { + if (vca.cameraId == triplet.cameraId && vca.viewport == triplet.viewport && vca.area == triplet.area) + return false; + } + return true; + } + public: QVector<ViewportCameraAreaTriplet> gather(FrameGraphNode *root) { @@ -129,7 +138,7 @@ public: // Find all viewport/camera pairs by traversing from leaf to root for (Render::FrameGraphNode *leaf : qAsConst(m_leaves)) { ViewportCameraAreaTriplet vcaTriplet = gatherUpViewportCameraAreas(leaf); - if (!vcaTriplet.cameraId.isNull()) + if (!vcaTriplet.cameraId.isNull() && isUnique(vcaTriplets, vcaTriplet)) vcaTriplets.push_back(vcaTriplet); } return vcaTriplets; @@ -519,11 +528,12 @@ void PickBoundingVolumeJob::run() } case QEvent::MouseButtonRelease: { - // Send release event to m_currentPicker - if (lastCurrentPicker != nullptr) { + if (lastCurrentPicker != nullptr && m_currentPicker == objectPickerHandle) m_currentPicker = HObjectPicker(); - lastCurrentPicker->onClicked(pickEvent); - lastCurrentPicker->onReleased(pickEvent); + // Only send the release event if it was pressed + if (objectPicker->isPressed()) { + objectPicker->onClicked(pickEvent); + objectPicker->onReleased(pickEvent); } break; } diff --git a/src/render/jobs/renderviewinitializerjob_p.h b/src/render/jobs/renderviewinitializerjob_p.h index 35620bc65..dbc80c162 100644 --- a/src/render/jobs/renderviewinitializerjob_p.h +++ b/src/render/jobs/renderviewinitializerjob_p.h @@ -54,7 +54,6 @@ #include <Qt3DCore/qaspectjob.h> #include <Qt3DCore/private/qframeallocator_p.h> -#include <QThreadStorage> #include <QSize> QT_BEGIN_NAMESPACE diff --git a/src/render/materialsystem/qgraphicsapifilter.cpp b/src/render/materialsystem/qgraphicsapifilter.cpp index 5a52ff0fd..119a294ac 100644 --- a/src/render/materialsystem/qgraphicsapifilter.cpp +++ b/src/render/materialsystem/qgraphicsapifilter.cpp @@ -55,20 +55,36 @@ GraphicsApiFilterData::GraphicsApiFilterData() bool GraphicsApiFilterData::operator ==(const GraphicsApiFilterData &other) const { - if (other.m_api == m_api - && other.m_profile <= m_profile - && (other.m_major < m_major - || (other.m_major == m_major && other.m_minor <= m_minor))) { - for (const QString &neededExt : other.m_extensions) - if (!m_extensions.contains(neededExt)) - return false; - // If a vendor name was specified in sample, we perform comparison, - // otherwise we assume the vendor name doesn't matter - if (!other.m_vendor.isEmpty()) - return (other.m_vendor == m_vendor); - return true; + // Check API + if (other.m_api != m_api) + return false; + + // Check versions + const bool versionsCompatible = other.m_major < m_major + || (other.m_major == m_major && other.m_minor <= m_minor); + if (!versionsCompatible) + return false; + + // Check profiles if requiring OpenGL (profiles not relevant for OpenGL ES) + if (other.m_api == QGraphicsApiFilter::OpenGL) { + const bool profilesCompatible = m_profile != QGraphicsApiFilter::CoreProfile + || other.m_profile == m_profile; + if (!profilesCompatible) + return false; } - return false; + + // Check extensions + for (const QString &neededExt : other.m_extensions) { + if (!m_extensions.contains(neededExt)) + return false; + } + + // Check vendor + if (!other.m_vendor.isEmpty()) + return (other.m_vendor == m_vendor); + + // If we get here everything looks good :) + return true; } bool GraphicsApiFilterData::operator <(const GraphicsApiFilterData &other) const diff --git a/src/render/materialsystem/qgraphicsapifilter.h b/src/render/materialsystem/qgraphicsapifilter.h index d09c2f753..c618358dd 100644 --- a/src/render/materialsystem/qgraphicsapifilter.h +++ b/src/render/materialsystem/qgraphicsapifilter.h @@ -95,8 +95,8 @@ public Q_SLOTS: void setVendor(const QString &vendor); Q_SIGNALS: - void apiChanged(Api api); - void profileChanged(OpenGLProfile profile); + void apiChanged(Qt3DRender::QGraphicsApiFilter::Api api); + void profileChanged(Qt3DRender::QGraphicsApiFilter::OpenGLProfile profile); void minorVersionChanged(int minorVersion); void majorVersionChanged(int majorVersion); void extensionsChanged(const QStringList &extensions); @@ -107,8 +107,8 @@ private: Q_DECLARE_PRIVATE(QGraphicsApiFilter) }; -bool operator ==(const QGraphicsApiFilter &reference, const QGraphicsApiFilter &sample); -bool operator !=(const QGraphicsApiFilter &reference, const QGraphicsApiFilter &sample); +Q_AUTOTEST_EXPORT bool operator ==(const QGraphicsApiFilter &reference, const QGraphicsApiFilter &sample); +Q_AUTOTEST_EXPORT bool operator !=(const QGraphicsApiFilter &reference, const QGraphicsApiFilter &sample); } // namespace Qt3DRender diff --git a/src/render/picking/qobjectpicker.cpp b/src/render/picking/qobjectpicker.cpp index 29912fa79..1842b7fee 100644 --- a/src/render/picking/qobjectpicker.cpp +++ b/src/render/picking/qobjectpicker.cpp @@ -313,7 +313,7 @@ void QObjectPickerPrivate::propagateEvent(QPickEvent *event, EventType type) if (!m_entities.isEmpty()) { Qt3DCore::QEntity *entity = m_entities.first(); Qt3DCore::QEntity *parentEntity = nullptr; - while (entity != nullptr && entity->parent() != nullptr && !event->isAccepted()) { + while (entity != nullptr && entity->parentEntity() != nullptr && !event->isAccepted()) { parentEntity = entity->parentEntity(); const auto components = parentEntity->components(); for (Qt3DCore::QComponent *c : components) { diff --git a/src/render/renderstates/renderstatenode.cpp b/src/render/renderstates/renderstatenode.cpp index 47e82a9bd..d1698e4b6 100644 --- a/src/render/renderstates/renderstatenode.cpp +++ b/src/render/renderstates/renderstatenode.cpp @@ -63,7 +63,7 @@ void RenderStateNode::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBaseP { cleanup(); const auto renderStateChange = qSharedPointerCast<Qt3DRender::QRenderStateCreatedChangeBase>(change); - m_impl = std::move(RenderStateSet::initializeStateFromPeer(renderStateChange)); + m_impl = RenderStateSet::initializeStateFromPeer(renderStateChange); } void RenderStateNode::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) diff --git a/src/render/renderstates/renderstateset.cpp b/src/render/renderstates/renderstateset.cpp index ffe7f6ee8..992d649e8 100644 --- a/src/render/renderstates/renderstateset.cpp +++ b/src/render/renderstates/renderstateset.cpp @@ -94,7 +94,6 @@ namespace Render { RenderStateSet::RenderStateSet() : m_stateMask(0) - , m_cachedPrevious(0) { } @@ -153,24 +152,15 @@ void RenderStateSet::apply(GraphicsContext *gc) } qCDebug(RenderStates) << " current states " << QString::number(stateMask(), 2) << "inverse " << QString::number(invOurState, 2) << " -> states to change: " << QString::number(stateToReset, 2); + // Reset states that aren't active in the current state set resetMasked(stateToReset, gc); - if (m_cachedPrevious && previousStates == m_cachedPrevious) { - // state-change cache hit - for (const StateVariant &ds : qAsConst(m_cachedDeltaStates)) - ds.apply(gc); - } else { - // compute deltas and cache for next frame - m_cachedDeltaStates.clear(); - m_cachedPrevious = previousStates; - - for (const StateVariant &ds : qAsConst(m_states)) { - if (previousStates && previousStates->contains(ds)) - continue; - - m_cachedDeltaStates.push_back(ds); - ds.apply(gc); - } + // Apply states that weren't in the previous state or that have + // different values + for (const StateVariant &ds : qAsConst(m_states)) { + if (previousStates && previousStates->contains(ds)) + continue; + ds.apply(gc); } } diff --git a/src/render/renderstates/renderstateset_p.h b/src/render/renderstates/renderstateset_p.h index 96af97f84..307e0ff1d 100644 --- a/src/render/renderstates/renderstateset_p.h +++ b/src/render/renderstates/renderstateset_p.h @@ -114,9 +114,7 @@ private: bool contains(const StateVariant &ds) const; StateMaskSet m_stateMask; - RenderStateSet* m_cachedPrevious; QVector<StateVariant> m_states; - QVector<StateVariant> m_cachedDeltaStates; }; template<> diff --git a/src/render/renderstates/statevariant.cpp b/src/render/renderstates/statevariant.cpp index 7a47d429e..f472d9920 100644 --- a/src/render/renderstates/statevariant.cpp +++ b/src/render/renderstates/statevariant.cpp @@ -79,7 +79,7 @@ void StateVariant::apply(GraphicsContext *gc) const data.scissorTest.apply(gc); return; case StencilTestStateMask: - data.scissorTest.apply(gc); + data.stencilTest.apply(gc); return; case AlphaCoverageStateMask: data.alphaCoverage.apply(gc); diff --git a/src/render/texture/qtexture.cpp b/src/render/texture/qtexture.cpp index 09ace37d0..13e6a04ab 100644 --- a/src/render/texture/qtexture.cpp +++ b/src/render/texture/qtexture.cpp @@ -954,6 +954,7 @@ bool QTextureFromSourceGenerator::operator ==(const QTextureGenerator &other) co QTextureFromSourceGenerator::QTextureFromSourceGenerator(const QUrl &url) : QTextureGenerator() , m_url(url) + , m_status(QAbstractTexture::None) { } diff --git a/src/render/texture/qtextureimage.cpp b/src/render/texture/qtextureimage.cpp index cc8d7acfe..dab92082a 100644 --- a/src/render/texture/qtextureimage.cpp +++ b/src/render/texture/qtextureimage.cpp @@ -170,6 +170,7 @@ void QTextureImage::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) QImageTextureDataFunctor::QImageTextureDataFunctor(const QUrl &url) : QTextureImageDataGenerator() , m_url(url) + , m_status(QTextureImage::None) { if (url.isLocalFile()) { QFileInfo info(url.toLocalFile()); diff --git a/src/src.pro b/src/src.pro index 9d51e6b14..61ceeb5f9 100644 --- a/src/src.pro +++ b/src/src.pro @@ -59,7 +59,7 @@ src_quick3d_imports_logic.depends = src_logic src_quick3d_imports_extras.file = $$PWD/quick3d/imports/extras/importsextras.pro src_quick3d_imports_extras.target = sub-quick3d-imports-extras -src_quick3d_imports_extras.depends = src_extras +src_quick3d_imports_extras.depends = src_extras src_quick3d_extras # Qt3D Scene Parser plugins src_plugins_sceneparsers.file = $$PWD/plugins/sceneparsers/sceneparsers.pro diff --git a/tests/auto/core/handlemanager/tst_handlemanager.cpp b/tests/auto/core/handlemanager/tst_handlemanager.cpp index a60d3cc57..3198b54a9 100644 --- a/tests/auto/core/handlemanager/tst_handlemanager.cpp +++ b/tests/auto/core/handlemanager/tst_handlemanager.cpp @@ -47,6 +47,7 @@ private slots: void updateChangesValue(); void resetRemovesAllEntries(); void maximumEntries(); + void checkNoCounterOverflow(); }; class SimpleResource @@ -63,61 +64,83 @@ typedef Qt3DCore::QHandle<SimpleResource> Handle; void tst_HandleManager::construction() { + // GIVEN Qt3DCore::QHandleManager<SimpleResource> manager; + + // THEN QVERIFY(manager.activeEntries() == 0); } void tst_HandleManager::correctPointer() { + // GIVEN Qt3DCore::QHandleManager<SimpleResource> manager; SimpleResource *p1 = (SimpleResource *)0xdeadbeef; + + // WHEN const Handle h = manager.acquire(p1); bool ok = false; SimpleResource *p2 = manager.data(h, &ok); + + // THEN QVERIFY(ok == true); QVERIFY(p1 == p2); } void tst_HandleManager::correctPointers() { + // GIVEN Qt3DCore::QHandleManager<SimpleResource> manager; SimpleResource *p[3]; p[0] = (SimpleResource *)0xdeadbeef; p[1] = (SimpleResource *)0x11111111; p[2] = (SimpleResource *)0x22222222; + // WHEN for (int i = 0; i < 3; ++i) { + // WHEN const Handle h = manager.acquire(p[i]); bool ok = false; SimpleResource *q = manager.data(h, &ok); + + // THEN QVERIFY(ok == true); QVERIFY(p[i] == q); } + // THEN QVERIFY(manager.activeEntries() == 3); } void tst_HandleManager::correctConstPointer() { + // GIVEN Qt3DCore::QHandleManager<SimpleResource> manager; QSharedPointer<SimpleResource> p1(new SimpleResource); const Handle h = manager.acquire(p1.data()); + // WHEN bool ok = false; const SimpleResource *p2 = manager.constData(h, &ok); + + // THEN QVERIFY(ok == true); QVERIFY(p1.data() == p2); } void tst_HandleManager::nullForRemovedEntry() { + // GIVEN Qt3DCore::QHandleManager<SimpleResource> manager; QSharedPointer<SimpleResource> p1(new SimpleResource); const Handle h = manager.acquire(p1.data()); + + // WHEN manager.release(h); + // THEN bool ok = false; SimpleResource *p2 = manager.data(h, &ok); QVERIFY(ok == false); @@ -126,44 +149,67 @@ void tst_HandleManager::nullForRemovedEntry() void tst_HandleManager::validHandleForReplacementEntry() { + // GIVEN Qt3DCore::QHandleManager<SimpleResource> manager; QSharedPointer<SimpleResource> p1(new SimpleResource); const Handle h = manager.acquire(p1.data()); + + // THEN QVERIFY(manager.activeEntries() == 1); + + // WHEN manager.release(h); + + // THEN QVERIFY(manager.activeEntries() == 0); + // WHEN QSharedPointer<SimpleResource> p2(new SimpleResource); const Handle h2 = manager.acquire(p2.data()); + + // THEN QVERIFY(h2.isNull() == false); QVERIFY(h2.counter() == 2); QVERIFY(manager.activeEntries() == 1); + // WHEN bool ok = false; SimpleResource *p3 = manager.data(h2, &ok); + + // THEN QVERIFY(ok == true); QVERIFY(p3 == p2); } void tst_HandleManager::updateChangesValue() { + // GIVEN Qt3DCore::QHandleManager<SimpleResource> manager; QSharedPointer<SimpleResource> p1(new SimpleResource); const Handle h = manager.acquire(p1.data()); + // WHEN QSharedPointer<SimpleResource> p2(new SimpleResource); manager.update(h, p2.data()); + + // THEN QVERIFY(manager.activeEntries() == 1); + // WHEN bool ok = false; SimpleResource *p3 = manager.data(h, &ok); + + // THEN QVERIFY(ok == true); QVERIFY(p3 == p2); } void tst_HandleManager::resetRemovesAllEntries() { + // GIVEN Qt3DCore::QHandleManager<SimpleResource> manager; + + // WHEN for (int i = 0; i < 100; ++i) { SimpleResource *p = (SimpleResource *) 0xdead0000 + i; const Handle h = manager.acquire(p); @@ -174,18 +220,25 @@ void tst_HandleManager::resetRemovesAllEntries() QVERIFY(p == q); } + // THEN QVERIFY(manager.activeEntries() == 100); + // WHEN manager.reset(); + + // THEN QVERIFY(manager.activeEntries() == 0); } void tst_HandleManager::maximumEntries() { + // GIVEN Qt3DCore::QHandleManager<SimpleResource> manager; + // THEN QCOMPARE(Handle::maxIndex(), (uint)((1 << 16) - 1)); + // WHEN for (int i = 0; i < (int)Handle::maxIndex(); ++i) { SimpleResource *p = (SimpleResource *) 0xdead0000 + i; const Handle h = manager.acquire(p); @@ -196,11 +249,58 @@ void tst_HandleManager::maximumEntries() QVERIFY(p == q); } - QVERIFY(manager.activeEntries() == Handle::maxIndex()); + // THEN + QVERIFY(manager.activeEntries() == Handle::maxIndex());\ + + // WHEN manager.reset(); + + // THEN QVERIFY(manager.activeEntries() == 0); } +void tst_HandleManager::checkNoCounterOverflow() +{ + // GIVEN + const int indexBits = 16; + Qt3DCore::QHandleManager<SimpleResource, indexBits> manager; + SimpleResource *p = (SimpleResource *) 0xdead0000; + Qt3DCore::QHandle<SimpleResource, indexBits> h = manager.acquire(p); + + // THEN + QCOMPARE(h.maxCounter(), (quint32)((1 << (32 - indexBits - 2)) - 1)); + QCOMPARE(h.counter(), (quint32)1); + + // WHEN + const quint32 maxIterations = h.maxCounter() - 2; + const quint32 handleIndex = h.index(); + + qDebug() << maxIterations << handleIndex; + + // Acquire and release maxIteration time to increase counter + for (quint32 i = 0; i < maxIterations; ++i) { + // WHEN + manager.release(h); + h = manager.acquire(p); + + // THEN + QCOMPARE(h.index(), handleIndex); + QCOMPARE(h.counter(), i + 2); + } + + // THEN + QCOMPARE(h.counter(), h.maxCounter() - 1); + + // WHEN + manager.release(h); + h = manager.acquire(p); + + // THEN + QCOMPARE(h.counter(), (quint32)1); +} + + + QTEST_APPLESS_MAIN(tst_HandleManager) #include "tst_handlemanager.moc" diff --git a/tests/auto/core/qtransform/tst_qtransform.cpp b/tests/auto/core/qtransform/tst_qtransform.cpp index 0713ec775..ee63255b8 100644 --- a/tests/auto/core/qtransform/tst_qtransform.cpp +++ b/tests/auto/core/qtransform/tst_qtransform.cpp @@ -41,6 +41,23 @@ class tst_QTransform : public QObject Q_OBJECT private Q_SLOTS: + void defaultConstruction() + { + // GIVEN + Qt3DCore::QTransform transform; + + // THEN + QCOMPARE(transform.isShareable(), false); + QCOMPARE(transform.matrix(), QMatrix4x4()); + QCOMPARE(transform.scale(), 1.0f); + QCOMPARE(transform.scale3D(), QVector3D(1.0f, 1.0f, 1.0f)); + QCOMPARE(transform.rotation(), QQuaternion()); + QCOMPARE(transform.rotationX(), 0.0f); + QCOMPARE(transform.rotationY(), 0.0f); + QCOMPARE(transform.rotationZ(), 0.0f); + QCOMPARE(transform.translation(), QVector3D(0.0f, 0.0f, 0.0f)); + } + void checkCloning_data() { QTest::addColumn<Qt3DCore::QTransform *>("transform"); diff --git a/tests/auto/render/layerfiltering/tst_layerfiltering.cpp b/tests/auto/render/layerfiltering/tst_layerfiltering.cpp index cf7a507a1..244906c90 100644 --- a/tests/auto/render/layerfiltering/tst_layerfiltering.cpp +++ b/tests/auto/render/layerfiltering/tst_layerfiltering.cpp @@ -164,9 +164,9 @@ private Q_SLOTS: childEntity3->addComponent(layer); QTest::newRow("LayerWithLayerFilterWithFilter-ShouldSelectAllButRoot") << rootEntity - << (Qt3DCore::QNodeIdVector() << layer->id()) - << true - << (Qt3DCore::QNodeIdVector() << childEntity1->id() << childEntity2->id() << childEntity3->id()); + << (Qt3DCore::QNodeIdVector() << layer->id()) + << true + << (Qt3DCore::QNodeIdVector() << childEntity1->id() << childEntity2->id() << childEntity3->id()); } { @@ -202,9 +202,28 @@ private Q_SLOTS: childEntity3->addComponent(layer); QTest::newRow("LayerWithLayerFilterWithFilter-ShouldSelectNone") << rootEntity - << (Qt3DCore::QNodeIdVector() << layer2->id()) + << (Qt3DCore::QNodeIdVector() << layer2->id()) + << true + << Qt3DCore::QNodeIdVector(); + } + + { + Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity(); + Qt3DCore::QEntity *childEntity1 = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity2 = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity3 = new Qt3DCore::QEntity(rootEntity); + + childEntity1->setEnabled(false); + + Qt3DRender::QLayer *layer = new Qt3DRender::QLayer(rootEntity); + childEntity1->addComponent(layer); + childEntity2->addComponent(layer); + childEntity3->addComponent(layer); + + QTest::newRow("LayerWithEntityDisabled-ShouldSelectOnlyEntityEnabled") << rootEntity + << (Qt3DCore::QNodeIdVector() << layer->id()) << true - << Qt3DCore::QNodeIdVector(); + << (Qt3DCore::QNodeIdVector() << childEntity2->id() << childEntity3->id()); } } diff --git a/tests/auto/render/qcuboidgeometry/qcuboidgeometry.pro b/tests/auto/render/qcuboidgeometry/qcuboidgeometry.pro new file mode 100644 index 000000000..2599b5fe6 --- /dev/null +++ b/tests/auto/render/qcuboidgeometry/qcuboidgeometry.pro @@ -0,0 +1,13 @@ +TEMPLATE = app + +TARGET = tst_qcuboidgeometry + +QT += 3dextras testlib + +CONFIG += testcase + +SOURCES += \ + tst_qcuboidgeometry.cpp + +include(../../core/common/common.pri) +include(../commons/commons.pri) diff --git a/tests/auto/render/qcuboidgeometry/tst_qcuboidgeometry.cpp b/tests/auto/render/qcuboidgeometry/tst_qcuboidgeometry.cpp new file mode 100644 index 000000000..ddd9eed22 --- /dev/null +++ b/tests/auto/render/qcuboidgeometry/tst_qcuboidgeometry.cpp @@ -0,0 +1,505 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtTest/QTest> +#include <QObject> +#include <Qt3DExtras/qcuboidgeometry.h> +#include <Qt3DRender/qattribute.h> +#include <Qt3DRender/qbuffer.h> +#include <Qt3DRender/qbufferdatagenerator.h> +#include <QtGui/qopenglcontext.h> +#include <QtGui/qvector2d.h> +#include <QtGui/qvector3d.h> +#include <QtGui/qvector4d.h> +#include <QtCore/qdebug.h> +#include <QtCore/qsharedpointer.h> +#include <QSignalSpy> + +namespace { + +void generateGeometry(Qt3DRender::QGeometry &geometry) +{ + // Get all attributes + const QVector<Qt3DRender::QAttribute *> attributes = geometry.attributes(); + + // Get all unique data generators from the buffers referenced by the attributes + QHash<Qt3DRender::QBufferDataGeneratorPtr, Qt3DRender::QBuffer *> dataGenerators; + for (const auto attribute : attributes) { + const auto dataGenerator = attribute->buffer()->dataGenerator(); + if (!dataGenerators.contains(dataGenerator)) + dataGenerators.insert(dataGenerator, attribute->buffer()); + } + + // Generate data for each buffer + const auto end = dataGenerators.end(); + for (auto it = dataGenerators.begin(); it != end; ++it) { + Qt3DRender::QBufferDataGeneratorPtr dataGenerator = it.key(); + const QByteArray data = (*dataGenerator)(); + + Qt3DRender::QBuffer *buffer = it.value(); + buffer->setData(data); + } +} + +template<typename IndexType> +IndexType extractIndexData(Qt3DRender::QAttribute *attribute, int index) +{ + // Get the raw data + const IndexType *typedData = reinterpret_cast<const IndexType *>(attribute->buffer()->data().constData()); + + // Offset into the data taking stride and offset into account + const IndexType indexValue = *(typedData + index); + return indexValue; +} + +template<typename VertexType, typename IndexType> +VertexType extractVertexData(Qt3DRender::QAttribute *attribute, IndexType index) +{ + // Get the raw data + const char *rawData = attribute->buffer()->data().constData(); + + // Offset into the data taking stride and offset into account + const char *vertexData = rawData + (index * attribute->byteStride() + attribute->byteOffset()); + + // Construct vertex from the typed data + VertexType vertex; + const Qt3DRender::QAttribute::VertexBaseType type = attribute->vertexBaseType(); + switch (type) + { + case Qt3DRender::QAttribute::Float: { + const float *typedVertexData = reinterpret_cast<const float *>(vertexData); + const int components = attribute->vertexSize(); + for (int i = 0; i < components; ++i) + vertex[i] = typedVertexData[i]; + break; + + // TODO: Handle other types as needed + } + + default: + qWarning() << "Unhandled type"; + Q_UNREACHABLE(); + break; + } + + return vertex; +} + +} + +class tst_QCuboidGeometry : public QObject +{ + Q_OBJECT +private Q_SLOTS: + void defaultConstruction() + { + // WHEN + Qt3DExtras::QCuboidGeometry geometry; + + // THEN + QCOMPARE(geometry.xExtent(), 1.0f); + QCOMPARE(geometry.yExtent(), 1.0f); + QCOMPARE(geometry.zExtent(), 1.0f); + QCOMPARE(geometry.xyMeshResolution(), QSize(2, 2)); + QCOMPARE(geometry.yzMeshResolution(), QSize(2, 2)); + QCOMPARE(geometry.xzMeshResolution(), QSize(2, 2)); + QVERIFY(geometry.positionAttribute() != nullptr); + QCOMPARE(geometry.positionAttribute()->name(), Qt3DRender::QAttribute::defaultPositionAttributeName()); + QVERIFY(geometry.normalAttribute() != nullptr); + QCOMPARE(geometry.normalAttribute()->name(), Qt3DRender::QAttribute::defaultNormalAttributeName()); + QVERIFY(geometry.texCoordAttribute() != nullptr); + QCOMPARE(geometry.texCoordAttribute()->name(), Qt3DRender::QAttribute::defaultTextureCoordinateAttributeName()); + QVERIFY(geometry.tangentAttribute() != nullptr); + QCOMPARE(geometry.tangentAttribute()->name(), Qt3DRender::QAttribute::defaultTangentAttributeName()); + QVERIFY(geometry.indexAttribute() != nullptr); + } + + void properties() + { + // GIVEN + Qt3DExtras::QCuboidGeometry geometry; + + { + // WHEN + QSignalSpy spy(&geometry, SIGNAL(xExtentChanged(float))); + const float newValue = 2.0f; + geometry.setXExtent(newValue); + + // THEN + QCOMPARE(geometry.xExtent(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + geometry.setXExtent(newValue); + + // THEN + QCOMPARE(geometry.xExtent(), newValue); + QCOMPARE(spy.count(), 0); + } + + { + // WHEN + QSignalSpy spy(&geometry, SIGNAL(yExtentChanged(float))); + const float newValue = 2.0f; + geometry.setYExtent(newValue); + + // THEN + QCOMPARE(geometry.yExtent(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + geometry.setYExtent(newValue); + + // THEN + QCOMPARE(geometry.yExtent(), newValue); + QCOMPARE(spy.count(), 0); + } + + { + // WHEN + QSignalSpy spy(&geometry, SIGNAL(zExtentChanged(float))); + const float newValue = 2.0f; + geometry.setZExtent(newValue); + + // THEN + QCOMPARE(geometry.zExtent(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + geometry.setZExtent(newValue); + + // THEN + QCOMPARE(geometry.zExtent(), newValue); + QCOMPARE(spy.count(), 0); + } + + { + // WHEN + QSignalSpy spy(&geometry, SIGNAL(xyMeshResolutionChanged(QSize))); + const auto newValue = QSize(4, 8); + geometry.setXYMeshResolution(newValue); + + // THEN + QCOMPARE(geometry.xyMeshResolution(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + geometry.setXYMeshResolution(newValue); + + // THEN + QCOMPARE(geometry.xyMeshResolution(), newValue); + QCOMPARE(spy.count(), 0); + } + + { + // WHEN + QSignalSpy spy(&geometry, SIGNAL(yzMeshResolutionChanged(QSize))); + const auto newValue = QSize(4, 8); + geometry.setYZMeshResolution(newValue); + + // THEN + QCOMPARE(geometry.yzMeshResolution(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + geometry.setYZMeshResolution(newValue); + + // THEN + QCOMPARE(geometry.yzMeshResolution(), newValue); + QCOMPARE(spy.count(), 0); + } + + { + // WHEN + QSignalSpy spy(&geometry, SIGNAL(xzMeshResolutionChanged(QSize))); + const auto newValue = QSize(4, 8); + geometry.setXZMeshResolution(newValue); + + // THEN + QCOMPARE(geometry.xzMeshResolution(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + geometry.setXZMeshResolution(newValue); + + // THEN + QCOMPARE(geometry.xzMeshResolution(), newValue); + QCOMPARE(spy.count(), 0); + } + } + + void generatedGeometryShouldBeConsistent_data() + { + QTest::addColumn<float>("xExtent"); + QTest::addColumn<float>("yExtent"); + QTest::addColumn<float>("zExtent"); + QTest::addColumn<QSize>("xyMeshResolution"); + QTest::addColumn<QSize>("yzMeshResolution"); + QTest::addColumn<QSize>("xzMeshResolution"); + QTest::addColumn<int>("triangleIndex"); + QTest::addColumn<QVector<quint16>>("indices"); + QTest::addColumn<QVector<QVector3D>>("positions"); + QTest::addColumn<QVector<QVector3D>>("normals"); + QTest::addColumn<QVector<QVector2D>>("texCoords"); + QTest::addColumn<QVector<QVector4D>>("tangents"); + + { + const int triangleIndex = 0; + const auto indices = (QVector<quint16>() << 0 << 1 << 2); + const auto positions = (QVector<QVector3D>() + << QVector3D(0.5f, -0.5f, -0.5f) + << QVector3D(0.5f, 0.5f, -0.5f) + << QVector3D(0.5f, -0.5f, 0.5f)); + const auto normals = (QVector<QVector3D>() + << QVector3D(1.0f, 0.0f, 0.0f) + << QVector3D(1.0f, 0.0f, 0.0f) + << QVector3D(1.0f, 0.0f, 0.0f)); + const auto texCoords = (QVector<QVector2D>() + << QVector2D(0.0f, 0.0f) + << QVector2D(0.0f, 1.0f) + << QVector2D(1.0f, 0.0f)); + const auto tangents = (QVector<QVector4D>() + << QVector4D(0.0f, 0.0f, 1.0f, -1.0f) + << QVector4D(0.0f, 0.0f, 1.0f, -1.0f) + << QVector4D(0.0f, 0.0f, 1.0f, -1.0f)); + QTest::newRow("default_positiveX_firstTriangle") + << 1.0f << 1.0f << 1.0f + << QSize(2,2) << QSize(2,2) << QSize(2,2) + << triangleIndex + << indices << positions << normals << texCoords << tangents; + } + + { + const int triangleIndex = 3; + const auto indices = (QVector<quint16>() << 6 << 5 << 7); + const auto positions = (QVector<QVector3D>() + << QVector3D(-0.5f, -0.5f, -0.5f) + << QVector3D(-0.5f, 0.5f, 0.5f) + << QVector3D(-0.5f, 0.5f, -0.5f)); + const auto normals = (QVector<QVector3D>() + << QVector3D(-1.0f, 0.0f, 0.0f) + << QVector3D(-1.0f, 0.0f, 0.0f) + << QVector3D(-1.0f, 0.0f, 0.0f)); + const auto texCoords = (QVector<QVector2D>() + << QVector2D(1.0f, 0.0f) + << QVector2D(0.0f, 1.0f) + << QVector2D(1.0f, 1.0f)); + const auto tangents = (QVector<QVector4D>() + << QVector4D(0.0f, 0.0f, -1.0f, -1.0f) + << QVector4D(0.0f, 0.0f, -1.0f, -1.0f) + << QVector4D(0.0f, 0.0f, -1.0f, -1.0f)); + QTest::newRow("default_negativeX_lastTriangle") + << 1.0f << 1.0f << 1.0f + << QSize(2,2) << QSize(2,2) << QSize(2,2) + << triangleIndex + << indices << positions << normals << texCoords << tangents; + } + + { + const int triangleIndex = 4; + const auto indices = (QVector<quint16>() << 8 << 9 << 10); + const auto positions = (QVector<QVector3D>() + << QVector3D(-0.5f, 0.5f, 0.5f) + << QVector3D(0.5f, 0.5f, 0.5f) + << QVector3D(-0.5f, 0.5f, -0.5f)); + const auto normals = (QVector<QVector3D>() + << QVector3D(0.0f, 1.0f, 0.0f) + << QVector3D(0.0f, 1.0f, 0.0f) + << QVector3D(0.0f, 1.0f, 0.0f)); + const auto texCoords = (QVector<QVector2D>() + << QVector2D(0.0f, 0.0f) + << QVector2D(1.0f, 0.0f) + << QVector2D(0.0f, 1.0f)); + const auto tangents = (QVector<QVector4D>() + << QVector4D(1.0f, 0.0f, 0.0f, 1.0f) + << QVector4D(1.0f, 0.0f, 0.0f, 1.0f) + << QVector4D(1.0f, 0.0f, 0.0f, 1.0f)); + QTest::newRow("default_positiveY_firstTriangle") + << 1.0f << 1.0f << 1.0f + << QSize(2,2) << QSize(2,2) << QSize(2,2) + << triangleIndex + << indices << positions << normals << texCoords << tangents; + } + + { + const int triangleIndex = 7; + const auto indices = (QVector<quint16>() << 14 << 13 << 15); + const auto positions = (QVector<QVector3D>() + << QVector3D(-0.5f, -0.5f, 0.5f) + << QVector3D(0.5f, -0.5f, -0.5f) + << QVector3D(0.5f, -0.5f, 0.5f)); + const auto normals = (QVector<QVector3D>() + << QVector3D(0.0f, -1.0f, 0.0f) + << QVector3D(0.0f, -1.0f, 0.0f) + << QVector3D(0.0f, -1.0f, 0.0f)); + const auto texCoords = (QVector<QVector2D>() + << QVector2D(0.0f, 1.0f) + << QVector2D(1.0f, 0.0f) + << QVector2D(1.0f, 1.0f)); + const auto tangents = (QVector<QVector4D>() + << QVector4D(1.0f, 0.0f, 0.0f, 1.0f) + << QVector4D(1.0f, 0.0f, 0.0f, 1.0f) + << QVector4D(1.0f, 0.0f, 0.0f, 1.0f)); + QTest::newRow("default_negativeY_lastTriangle") + << 1.0f << 1.0f << 1.0f + << QSize(2,2) << QSize(2,2) << QSize(2,2) + << triangleIndex + << indices << positions << normals << texCoords << tangents; + } + + { + const int triangleIndex = 8; + const auto indices = (QVector<quint16>() << 16 << 17 << 18); + const auto positions = (QVector<QVector3D>() + << QVector3D(-0.5f, -0.5f, 0.5f) + << QVector3D(0.5f, -0.5f, 0.5f) + << QVector3D(-0.5f, 0.5f, 0.5f)); + const auto normals = (QVector<QVector3D>() + << QVector3D(0.0f, 0.0f, 1.0f) + << QVector3D(0.0f, 0.0f, 1.0f) + << QVector3D(0.0f, 0.0f, 1.0f)); + const auto texCoords = (QVector<QVector2D>() + << QVector2D(0.0f, 0.0f) + << QVector2D(1.0f, 0.0f) + << QVector2D(0.0f, 1.0f)); + const auto tangents = (QVector<QVector4D>() + << QVector4D(1.0f, 0.0f, 0.0f, 1.0f) + << QVector4D(1.0f, 0.0f, 0.0f, 1.0f) + << QVector4D(1.0f, 0.0f, 0.0f, 1.0f)); + QTest::newRow("default_positiveZ_firstTriangle") + << 1.0f << 1.0f << 1.0f + << QSize(2,2) << QSize(2,2) << QSize(2,2) + << triangleIndex + << indices << positions << normals << texCoords << tangents; + } + + { + const int triangleIndex = 11; + const auto indices = (QVector<quint16>() << 22 << 21 << 23); + const auto positions = (QVector<QVector3D>() + << QVector3D(0.5f, 0.5f, -0.5f) + << QVector3D(-0.5f, -0.5f, -0.5f) + << QVector3D(-0.5f, 0.5f, -0.5f)); + const auto normals = (QVector<QVector3D>() + << QVector3D(0.0f, 0.0f, -1.0f) + << QVector3D(0.0f, 0.0f, -1.0f) + << QVector3D(0.0f, 0.0f, -1.0f)); + const auto texCoords = (QVector<QVector2D>() + << QVector2D(0.0f, 1.0f) + << QVector2D(1.0f, 0.0f) + << QVector2D(1.0f, 1.0f)); + const auto tangents = (QVector<QVector4D>() + << QVector4D(-1.0f, 0.0f, 0.0f, 1.0f) + << QVector4D(-1.0f, 0.0f, 0.0f, 1.0f) + << QVector4D(-1.0f, 0.0f, 0.0f, 1.0f)); + QTest::newRow("default_negativeZ_lastTriangle") + << 1.0f << 1.0f << 1.0f + << QSize(2,2) << QSize(2,2) << QSize(2,2) + << triangleIndex + << indices << positions << normals << texCoords << tangents; + } + } + + void generatedGeometryShouldBeConsistent() + { + // GIVEN + Qt3DExtras::QCuboidGeometry geometry; + const QVector<Qt3DRender::QAttribute *> attributes = geometry.attributes(); + Qt3DRender::QAttribute *positionAttribute = geometry.positionAttribute(); + Qt3DRender::QAttribute *normalAttribute = geometry.normalAttribute(); + Qt3DRender::QAttribute *texCoordAttribute = geometry.texCoordAttribute(); + Qt3DRender::QAttribute *tangentAttribute = geometry.tangentAttribute(); + Qt3DRender::QAttribute *indexAttribute = geometry.indexAttribute(); + + // WHEN + QFETCH(float, xExtent); + QFETCH(float, yExtent); + QFETCH(float, zExtent); + QFETCH(QSize, xyMeshResolution); + QFETCH(QSize, yzMeshResolution); + QFETCH(QSize, xzMeshResolution); + geometry.setXExtent(xExtent); + geometry.setYExtent(yExtent); + geometry.setZExtent(zExtent); + geometry.setXYMeshResolution(xyMeshResolution); + geometry.setYZMeshResolution(yzMeshResolution); + geometry.setXZMeshResolution(xzMeshResolution); + + generateGeometry(geometry); + + // THEN + + // Check buffer of each attribute is valid and actually has some data + for (const auto &attribute : attributes) { + Qt3DRender::QBuffer *buffer = attribute->buffer(); + QVERIFY(buffer != nullptr); + QVERIFY(buffer->data().size() != 0); + } + + // Check some data in the buffers + + // Check specific indices and vertex attributes of triangle under test + QFETCH(int, triangleIndex); + QFETCH(QVector<quint16>, indices); + QFETCH(QVector<QVector3D>, positions); + QFETCH(QVector<QVector3D>, normals); + QFETCH(QVector<QVector2D>, texCoords); + QFETCH(QVector<QVector4D>, tangents); + + int i = 0; + for (auto index : indices) { + const auto testIndex = extractIndexData<quint16>(indexAttribute, 3 * triangleIndex + i); + QCOMPARE(testIndex, indices.at(i)); + + const auto position = extractVertexData<QVector3D, quint32>(positionAttribute, index); + QCOMPARE(position, positions.at(i)); + + const auto normal = extractVertexData<QVector3D, quint32>(normalAttribute, index); + QCOMPARE(normal, normals.at(i)); + + const auto texCoord = extractVertexData<QVector2D, quint32>(texCoordAttribute, index); + QCOMPARE(texCoord, texCoords.at(i)); + + const auto tangent = extractVertexData<QVector4D, quint32>(tangentAttribute, index); + QCOMPARE(tangent, tangents.at(i)); + + ++i; + } + } +}; + + +QTEST_APPLESS_MAIN(tst_QCuboidGeometry) + +#include "tst_qcuboidgeometry.moc" diff --git a/tests/auto/render/qgraphicsapifilter/qgraphicsapifilter.pro b/tests/auto/render/qgraphicsapifilter/qgraphicsapifilter.pro new file mode 100644 index 000000000..ce2d9ac12 --- /dev/null +++ b/tests/auto/render/qgraphicsapifilter/qgraphicsapifilter.pro @@ -0,0 +1,13 @@ +TEMPLATE = app + +TARGET = tst_qgraphicsapifilter + +QT += 3dcore 3dcore-private 3drender 3drender-private testlib + +CONFIG += testcase + +SOURCES += \ + tst_qgraphicsapifilter.cpp + +include(../../core/common/common.pri) +include(../commons/commons.pri) diff --git a/tests/auto/render/qgraphicsapifilter/tst_qgraphicsapifilter.cpp b/tests/auto/render/qgraphicsapifilter/tst_qgraphicsapifilter.cpp new file mode 100644 index 000000000..7d4a3bfc9 --- /dev/null +++ b/tests/auto/render/qgraphicsapifilter/tst_qgraphicsapifilter.cpp @@ -0,0 +1,246 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtTest/QTest> +#include <QObject> +#include <Qt3DRender/qgraphicsapifilter.h> +#include <QtGui/qopenglcontext.h> +#include <QtCore/qsharedpointer.h> +#include <QSignalSpy> + +class tst_QGraphicsApiFilter : public QObject +{ + Q_OBJECT +private Q_SLOTS: + void defaultConstruction() + { + // WHEN + Qt3DRender::QGraphicsApiFilter apiFilter; + + // THEN + const auto api = (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGL) + ? Qt3DRender::QGraphicsApiFilter::OpenGL + : Qt3DRender::QGraphicsApiFilter::OpenGLES; + QCOMPARE(apiFilter.api(), api); + QCOMPARE(apiFilter.profile(), Qt3DRender::QGraphicsApiFilter::NoProfile); + QCOMPARE(apiFilter.majorVersion(), 0); + QCOMPARE(apiFilter.minorVersion(), 0); + QCOMPARE(apiFilter.extensions(), QStringList()); + QCOMPARE(apiFilter.vendor(), QString()); + } + + void properties() + { + // GIVEN + Qt3DRender::QGraphicsApiFilter apiFilter; + + { + // WHEN + QSignalSpy spy(&apiFilter, SIGNAL(apiChanged(Qt3DRender::QGraphicsApiFilter::Api))); + apiFilter.setApi(Qt3DRender::QGraphicsApiFilter::OpenGL); + + // THEN + QCOMPARE(apiFilter.api(), Qt3DRender::QGraphicsApiFilter::OpenGL); + bool shouldEmitSignal = (QOpenGLContext::openGLModuleType() != QOpenGLContext::LibGL); + QCOMPARE(spy.isEmpty(), !shouldEmitSignal); + } + + { + // WHEN + QSignalSpy spy(&apiFilter, SIGNAL(profileChanged(Qt3DRender::QGraphicsApiFilter::OpenGLProfile))); + apiFilter.setProfile(Qt3DRender::QGraphicsApiFilter::CoreProfile); + + // THEN + QCOMPARE(apiFilter.profile(), Qt3DRender::QGraphicsApiFilter::CoreProfile); + QCOMPARE(spy.count(), 1); + } + + { + // WHEN + QSignalSpy spy(&apiFilter, SIGNAL(majorVersionChanged(int))); + apiFilter.setMajorVersion(4); + + // THEN + QCOMPARE(apiFilter.majorVersion(), 4); + QCOMPARE(spy.count(), 1); + } + + { + // WHEN + QSignalSpy spy(&apiFilter, SIGNAL(minorVersionChanged(int))); + apiFilter.setMinorVersion(5); + + // THEN + QCOMPARE(apiFilter.minorVersion(), 5); + QCOMPARE(spy.count(), 1); + } + + { + // WHEN + QSignalSpy spy(&apiFilter, SIGNAL(extensionsChanged(QStringList))); + const auto extensions = (QStringList() << QLatin1String("extension1") << QLatin1String("extension2")); + apiFilter.setExtensions(extensions); + + // THEN + QCOMPARE(apiFilter.extensions(), extensions); + QCOMPARE(spy.count(), 1); + } + + { + // WHEN + QSignalSpy spy(&apiFilter, SIGNAL(vendorChanged(QString))); + const QLatin1String vendor("Triangles McTriangleFace"); + apiFilter.setVendor(vendor); + + // THEN + QCOMPARE(apiFilter.vendor(), vendor); + QCOMPARE(spy.count(), 1); + } + } + + void shouldDetermineCompatibility_data() + { + QTest::addColumn<QSharedPointer<Qt3DRender::QGraphicsApiFilter>>("required"); + QTest::addColumn<QSharedPointer<Qt3DRender::QGraphicsApiFilter>>("actual"); + QTest::addColumn<bool>("expected"); + + auto required = QSharedPointer<Qt3DRender::QGraphicsApiFilter>::create(); + required->setApi(Qt3DRender::QGraphicsApiFilter::OpenGL); + required->setProfile(Qt3DRender::QGraphicsApiFilter::CoreProfile); + required->setMajorVersion(4); + required->setMinorVersion(5); + auto actual = QSharedPointer<Qt3DRender::QGraphicsApiFilter>::create(); + actual->setApi(Qt3DRender::QGraphicsApiFilter::OpenGL); + actual->setProfile(Qt3DRender::QGraphicsApiFilter::CoreProfile); + actual->setMajorVersion(4); + actual->setMinorVersion(5); + bool expected = true; + QTest::newRow("exact_match") << required << actual << expected; + + required = QSharedPointer<Qt3DRender::QGraphicsApiFilter>::create(); + required->setApi(Qt3DRender::QGraphicsApiFilter::OpenGL); + required->setProfile(Qt3DRender::QGraphicsApiFilter::CoreProfile); + required->setMajorVersion(3); + required->setMinorVersion(2); + actual = QSharedPointer<Qt3DRender::QGraphicsApiFilter>::create(); + actual->setApi(Qt3DRender::QGraphicsApiFilter::OpenGL); + actual->setProfile(Qt3DRender::QGraphicsApiFilter::CoreProfile); + actual->setMajorVersion(4); + actual->setMinorVersion(5); + expected = true; + QTest::newRow("actual_is_higher_version") << required << actual << expected; + + required = QSharedPointer<Qt3DRender::QGraphicsApiFilter>::create(); + required->setApi(Qt3DRender::QGraphicsApiFilter::OpenGL); + required->setProfile(Qt3DRender::QGraphicsApiFilter::CoreProfile); + required->setMajorVersion(4); + required->setMinorVersion(5); + actual = QSharedPointer<Qt3DRender::QGraphicsApiFilter>::create(); + actual->setApi(Qt3DRender::QGraphicsApiFilter::OpenGL); + actual->setProfile(Qt3DRender::QGraphicsApiFilter::CoreProfile); + actual->setMajorVersion(3); + actual->setMinorVersion(2); + expected = false; + QTest::newRow("actual_is_lower_version") << required << actual << expected; + + required = QSharedPointer<Qt3DRender::QGraphicsApiFilter>::create(); + required->setApi(Qt3DRender::QGraphicsApiFilter::OpenGL); + required->setProfile(Qt3DRender::QGraphicsApiFilter::CompatibilityProfile); + required->setMajorVersion(4); + required->setMinorVersion(5); + actual = QSharedPointer<Qt3DRender::QGraphicsApiFilter>::create(); + actual->setApi(Qt3DRender::QGraphicsApiFilter::OpenGL); + actual->setProfile(Qt3DRender::QGraphicsApiFilter::CoreProfile); + actual->setMajorVersion(4); + actual->setMinorVersion(5); + expected = false; + QTest::newRow("wrong_profile") << required << actual << expected; + + required = QSharedPointer<Qt3DRender::QGraphicsApiFilter>::create(); + required->setApi(Qt3DRender::QGraphicsApiFilter::OpenGL); + required->setProfile(Qt3DRender::QGraphicsApiFilter::CoreProfile); + required->setMajorVersion(3); + required->setMinorVersion(2); + actual = QSharedPointer<Qt3DRender::QGraphicsApiFilter>::create(); + actual->setApi(Qt3DRender::QGraphicsApiFilter::OpenGLES); + actual->setProfile(Qt3DRender::QGraphicsApiFilter::NoProfile); + actual->setMajorVersion(3); + actual->setMinorVersion(2); + expected = false; + QTest::newRow("wrong_api") << required << actual << expected; + + required = QSharedPointer<Qt3DRender::QGraphicsApiFilter>::create(); + required->setApi(Qt3DRender::QGraphicsApiFilter::OpenGL); + required->setProfile(Qt3DRender::QGraphicsApiFilter::NoProfile); + required->setMajorVersion(2); + required->setMinorVersion(0); + actual = QSharedPointer<Qt3DRender::QGraphicsApiFilter>::create(); + actual->setApi(Qt3DRender::QGraphicsApiFilter::OpenGL); + actual->setProfile(Qt3DRender::QGraphicsApiFilter::CompatibilityProfile); + actual->setMajorVersion(3); + actual->setMinorVersion(2); + expected = true; + QTest::newRow("gl_3_2_compatibility_can_use_gl_2_0") << required << actual << expected; + + required = QSharedPointer<Qt3DRender::QGraphicsApiFilter>::create(); + required->setApi(Qt3DRender::QGraphicsApiFilter::OpenGL); + required->setProfile(Qt3DRender::QGraphicsApiFilter::NoProfile); + required->setMajorVersion(2); + required->setMinorVersion(0); + actual = QSharedPointer<Qt3DRender::QGraphicsApiFilter>::create(); + actual->setApi(Qt3DRender::QGraphicsApiFilter::OpenGL); + actual->setProfile(Qt3DRender::QGraphicsApiFilter::CoreProfile); + actual->setMajorVersion(3); + actual->setMinorVersion(2); + expected = false; + QTest::newRow("gl_3_2_core_cant_use_gl_2_0") << required << actual << expected; + } + + void shouldDetermineCompatibility() + { + // GIVEN + QFETCH(QSharedPointer<Qt3DRender::QGraphicsApiFilter>, required); + QFETCH(QSharedPointer<Qt3DRender::QGraphicsApiFilter>, actual); + QFETCH(bool, expected); + + // WHEN + const auto isCompatible = (*actual == *required); + + // THEN + QCOMPARE(isCompatible, expected); + } + + // TODO: Add equality test in 5.8 when we can add new api to + // test for compatibility and properly use operator == to really + // test for equality. +}; + + +QTEST_APPLESS_MAIN(tst_QGraphicsApiFilter) + +#include "tst_qgraphicsapifilter.moc" diff --git a/tests/auto/render/qrendersurfaceselector/qrendersurfaceselector.pro b/tests/auto/render/qrendersurfaceselector/qrendersurfaceselector.pro new file mode 100644 index 000000000..57626b9ef --- /dev/null +++ b/tests/auto/render/qrendersurfaceselector/qrendersurfaceselector.pro @@ -0,0 +1,10 @@ +TEMPLATE = app + +TARGET = tst_qrendersurfaceselector +QT += core-private 3dcore 3dcore-private 3drender 3drender-private testlib + +CONFIG += testcase + +SOURCES += tst_qrendersurfaceselector.cpp + +include(../commons/commons.pri) diff --git a/tests/auto/render/qrendersurfaceselector/tst_qrendersurfaceselector.cpp b/tests/auto/render/qrendersurfaceselector/tst_qrendersurfaceselector.cpp new file mode 100644 index 000000000..17c7cf40d --- /dev/null +++ b/tests/auto/render/qrendersurfaceselector/tst_qrendersurfaceselector.cpp @@ -0,0 +1,107 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtTest/QTest> +#include <Qt3DCore/qentity.h> + +#include <Qt3DRender/qrendersettings.h> +#include <Qt3DRender/qrendersurfaceselector.h> +#include <Qt3DRender/private/qrendersurfaceselector_p.h> + +class tst_QRenderSurfaceSelector: public QObject +{ + Q_OBJECT + +private Q_SLOTS: + void shouldFindInstanceInEntityTree_data() + { + QTest::addColumn<QSharedPointer<Qt3DCore::QEntity>>("root"); + QTest::addColumn<Qt3DRender::QRenderSurfaceSelector*>("expected"); + + auto root = QSharedPointer<Qt3DCore::QEntity>::create(); + auto settings = new Qt3DRender::QRenderSettings; + root->addComponent(settings); + auto selector = new Qt3DRender::QRenderSurfaceSelector; + settings->setActiveFrameGraph(selector); + QTest::newRow("simplest_tree") << root << selector; + + root = QSharedPointer<Qt3DCore::QEntity>::create(); + settings = new Qt3DRender::QRenderSettings; + root->addComponent(settings); + settings->setActiveFrameGraph(new Qt3DRender::QFrameGraphNode); + selector = nullptr; + QTest::newRow("no_selector") << root << selector; + + root = QSharedPointer<Qt3DCore::QEntity>::create(); + settings = new Qt3DRender::QRenderSettings; + root->addComponent(settings); + selector = nullptr; + QTest::newRow("no_framegraph") << root << selector; + + root = QSharedPointer<Qt3DCore::QEntity>::create(); + selector = nullptr; + QTest::newRow("no_rendersettings") << root << selector; + + root = QSharedPointer<Qt3DCore::QEntity>::create(); + auto entity = new Qt3DCore::QEntity(root.data()); + entity = new Qt3DCore::QEntity(entity); + settings = new Qt3DRender::QRenderSettings; + entity->addComponent(settings); + selector = new Qt3DRender::QRenderSurfaceSelector; + settings->setActiveFrameGraph(selector); + QTest::newRow("in_subentity") << root << selector; + + root = QSharedPointer<Qt3DCore::QEntity>::create(); + entity = new Qt3DCore::QEntity(root.data()); + entity = new Qt3DCore::QEntity(entity); + settings = new Qt3DRender::QRenderSettings; + entity->addComponent(settings); + auto node = new Qt3DRender::QFrameGraphNode; + settings->setActiveFrameGraph(node); + node = new Qt3DRender::QFrameGraphNode(node); + selector = new Qt3DRender::QRenderSurfaceSelector(node); + QTest::newRow("in_deeper_framegraph") << root << selector; + } + + void shouldFindInstanceInEntityTree() + { + // GIVEN + QFETCH(QSharedPointer<Qt3DCore::QEntity>, root); + + // WHEN + auto selector = Qt3DRender::QRenderSurfaceSelectorPrivate::find(root.data()); + + // THEN + QFETCH(Qt3DRender::QRenderSurfaceSelector*, expected); + QCOMPARE(selector, expected); + } +}; + +QTEST_MAIN(tst_QRenderSurfaceSelector) + +#include "tst_qrendersurfaceselector.moc" diff --git a/tests/auto/render/render.pro b/tests/auto/render/render.pro index 3c9f4d462..d64a5e4e9 100644 --- a/tests/auto/render/render.pro +++ b/tests/auto/render/render.pro @@ -49,5 +49,9 @@ contains(QT_CONFIG, private_tests) { shadercache \ layerfiltering \ filterentitybycomponent \ - genericlambdajob + genericlambdajob \ + qgraphicsapifilter \ + qrendersurfaceselector \ + sortpolicy \ + qcuboidgeometry } diff --git a/tests/auto/render/renderviewutils/tst_renderviewutils.cpp b/tests/auto/render/renderviewutils/tst_renderviewutils.cpp index 1bda16cba..df68a61d4 100644 --- a/tests/auto/render/renderviewutils/tst_renderviewutils.cpp +++ b/tests/auto/render/renderviewutils/tst_renderviewutils.cpp @@ -290,35 +290,45 @@ private: void tst_RenderViewUtils::topLevelScalarValueNoUniforms() { + // GIVEN QScopedPointer<ScalarShaderData> shaderData(new ScalarShaderData()); QScopedPointer<Qt3DRender::Render::ShaderDataManager> manager(new Qt3DRender::Render::ShaderDataManager()); + // WHEN shaderData->setScalar(883.0f); initBackendShaderData(shaderData.data(), manager.data()); + // THEN Qt3DRender::Render::ShaderData *backendShaderData = manager->lookupResource(shaderData->id()); QVERIFY(backendShaderData != nullptr); + // WHEB Qt3DRender::Render::UniformBlockValueBuilder blockBuilder; blockBuilder.shaderDataManager = manager.data(); blockBuilder.updatedPropertiesOnly = false; // build name-value map blockBuilder.buildActiveUniformNameValueMapStructHelper(backendShaderData, QStringLiteral("")); + + // THEN // activeUniformNamesToValue should be empty as blockBuilder.uniforms is QVERIFY(blockBuilder.activeUniformNamesToValue.isEmpty()); } void tst_RenderViewUtils::topLevelScalarValue() { + // GIVEN QScopedPointer<ScalarShaderData> shaderData(new ScalarShaderData()); QScopedPointer<Qt3DRender::Render::ShaderDataManager> manager(new Qt3DRender::Render::ShaderDataManager()); + // WHEN shaderData->setScalar(883.0f); initBackendShaderData(shaderData.data(), manager.data()); + // THEN Qt3DRender::Render::ShaderData *backendShaderData = manager->lookupResource(shaderData->id()); QVERIFY(backendShaderData != nullptr); + // WHEN Qt3DRender::Render::UniformBlockValueBuilder blockBuilder; blockBuilder.shaderDataManager = manager.data(); blockBuilder.updatedPropertiesOnly = false; @@ -326,13 +336,16 @@ void tst_RenderViewUtils::topLevelScalarValue() // build name-value map blockBuilder.buildActiveUniformNameValueMapStructHelper(backendShaderData, QStringLiteral("MyBlock")); + // THEN QVERIFY(blockBuilder.uniforms.count() == 1); QCOMPARE(blockBuilder.activeUniformNamesToValue.count(), 1); + // WHEN Qt3DRender::Render::UniformBlockValueBuilderHash::const_iterator it = blockBuilder.activeUniformNamesToValue.begin(); const Qt3DRender::Render::UniformBlockValueBuilderHash::const_iterator end = blockBuilder.activeUniformNamesToValue.end(); while (it != end) { + // THEN QVERIFY(blockBuilder.uniforms.contains(Qt3DRender::Render::StringToInt::lookupString(it.key()))); QCOMPARE(it.value(), QVariant(shaderData->scalar())); ++it; @@ -341,16 +354,20 @@ void tst_RenderViewUtils::topLevelScalarValue() void tst_RenderViewUtils::topLevelArrayValue() { + // GIVEN QScopedPointer<ArrayShaderData> shaderData(new ArrayShaderData()); QScopedPointer<Qt3DRender::Render::ShaderDataManager> manager(new Qt3DRender::Render::ShaderDataManager()); + // WHEN QVariantList arrayValues = QVariantList() << 454 << 350 << 383 << 427 << 552; shaderData->setArray(arrayValues); initBackendShaderData(shaderData.data(), manager.data()); + // THEN Qt3DRender::Render::ShaderData *backendShaderData = manager->lookupResource(shaderData->id()); QVERIFY(backendShaderData != nullptr); + // WHEN Qt3DRender::Render::UniformBlockValueBuilder blockBuilder; blockBuilder.shaderDataManager = manager.data(); blockBuilder.updatedPropertiesOnly = false; @@ -358,13 +375,16 @@ void tst_RenderViewUtils::topLevelArrayValue() // build name-value map blockBuilder.buildActiveUniformNameValueMapStructHelper(backendShaderData, QStringLiteral("MyBlock")); + // THEN QVERIFY(blockBuilder.uniforms.count() == 1); QCOMPARE(blockBuilder.activeUniformNamesToValue.count(), 1); + // WHEN Qt3DRender::Render::UniformBlockValueBuilderHash::const_iterator it = blockBuilder.activeUniformNamesToValue.begin(); const Qt3DRender::Render::UniformBlockValueBuilderHash::const_iterator end = blockBuilder.activeUniformNamesToValue.end(); while (it != end) { + // THEN QVERIFY(blockBuilder.uniforms.contains(Qt3DRender::Render::StringToInt::lookupString(it.key()))); QCOMPARE(it.value(), QVariant(arrayValues)); ++it; @@ -405,15 +425,19 @@ void tst_RenderViewUtils::topLevelStructValue_data() void tst_RenderViewUtils::topLevelStructValue() { + // GIVEN QFETCH(StructShaderData *, shaderData); QFETCH(QString, blockName); QScopedPointer<Qt3DRender::Render::ShaderDataManager> manager(new Qt3DRender::Render::ShaderDataManager()); + // WHEN initBackendShaderData(shaderData, manager.data()); + // THEN Qt3DRender::Render::ShaderData *backendShaderData = manager->lookupResource(shaderData->id()); QVERIFY(backendShaderData != nullptr); + // WHEN Qt3DRender::Render::UniformBlockValueBuilder blockBuilder; blockBuilder.shaderDataManager = manager.data(); blockBuilder.updatedPropertiesOnly = false; @@ -422,12 +446,15 @@ void tst_RenderViewUtils::topLevelStructValue() // build name-value map blockBuilder.buildActiveUniformNameValueMapStructHelper(backendShaderData, blockName); + // THEN QCOMPARE(blockBuilder.activeUniformNamesToValue.count(), blockBuilder.uniforms.count()); + // WHEN Qt3DRender::Render::UniformBlockValueBuilderHash::const_iterator it = blockBuilder.activeUniformNamesToValue.begin(); const Qt3DRender::Render::UniformBlockValueBuilderHash::const_iterator end = blockBuilder.activeUniformNamesToValue.end(); while (it != end) { + // THEN QVERIFY(blockBuilder.uniforms.contains(Qt3DRender::Render::StringToInt::lookupString(it.key()))); QVERIFY(expectedValues.contains(Qt3DRender::Render::StringToInt::lookupString(it.key()))); QCOMPARE(it.value(), expectedValues.value(Qt3DRender::Render::StringToInt::lookupString(it.key()))); @@ -437,16 +464,20 @@ void tst_RenderViewUtils::topLevelStructValue() void tst_RenderViewUtils::topLevelDynamicProperties() { + // GIVEN QScopedPointer<Qt3DRender::QShaderData> shaderData(new Qt3DRender::QShaderData()); QScopedPointer<Qt3DRender::Render::ShaderDataManager> manager(new Qt3DRender::Render::ShaderDataManager()); + // WHEN shaderData->setProperty("scalar", 883.0f); shaderData->setProperty("array", QVariantList() << 454 << 350 << 383 << 427 << 552); initBackendShaderData(shaderData.data(), manager.data()); + // THEN Qt3DRender::Render::ShaderData *backendShaderData = manager->lookupResource(shaderData->id()); QVERIFY(backendShaderData != nullptr); + // WHEN Qt3DRender::Render::UniformBlockValueBuilder blockBuilder; blockBuilder.shaderDataManager = manager.data(); blockBuilder.updatedPropertiesOnly = false; @@ -455,6 +486,7 @@ void tst_RenderViewUtils::topLevelDynamicProperties() // build name-value map blockBuilder.buildActiveUniformNameValueMapStructHelper(backendShaderData, QStringLiteral("MyBlock")); + // THEN QVERIFY(blockBuilder.uniforms.count() == 2); QCOMPARE(blockBuilder.activeUniformNamesToValue.count(), 2); diff --git a/tests/auto/render/sortpolicy/sortpolicy.pro b/tests/auto/render/sortpolicy/sortpolicy.pro new file mode 100644 index 000000000..18b28cff7 --- /dev/null +++ b/tests/auto/render/sortpolicy/sortpolicy.pro @@ -0,0 +1,13 @@ +TEMPLATE = app + +TARGET = tst_sortpolicy + +QT += 3dcore 3dcore-private 3drender 3drender-private testlib + +CONFIG += testcase + +SOURCES += \ + tst_sortpolicy.cpp + +include(../../core/common/common.pri) +include(../commons/commons.pri) diff --git a/tests/auto/render/sortpolicy/tst_sortpolicy.cpp b/tests/auto/render/sortpolicy/tst_sortpolicy.cpp new file mode 100644 index 000000000..8cab1a9c4 --- /dev/null +++ b/tests/auto/render/sortpolicy/tst_sortpolicy.cpp @@ -0,0 +1,105 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtTest/QTest> +#include <qbackendnodetester.h> +#include <Qt3DRender/private/sortpolicy_p.h> +#include <Qt3DCore/qpropertyupdatedchange.h> +#include "testrenderer.h" + +class tst_SortPolicy : public Qt3DCore::QBackendNodeTester +{ + Q_OBJECT +private Q_SLOTS: + void checkInitialState() + { + // GIVEN + TestRenderer renderer; + Qt3DRender::Render::SortPolicy backendNode; + backendNode.setRenderer(&renderer); + + // THEN + QVERIFY(backendNode.peerId().isNull()); + QVERIFY(backendNode.parentId().isNull()); + QVERIFY(backendNode.sortTypes().isEmpty()); + } + + void checkPeerPropertyMirroring() + { + // GIVEN + Qt3DRender::QFrameGraphNode parent; + auto parentBackend = new Qt3DRender::Render::FrameGraphNode; + simulateInitialization(&parent, parentBackend); + + Qt3DRender::Render::FrameGraphManager manager; + manager.appendNode(parent.id(), parentBackend); + + const auto sortTypes = QVector<Qt3DRender::QSortPolicy::SortType>() << Qt3DRender::QSortPolicy::BackToFront + << Qt3DRender::QSortPolicy::Material; + Qt3DRender::Render::SortPolicy backendNode; + backendNode.setFrameGraphManager(&manager); + Qt3DRender::QSortPolicy sortPolicy(&parent); + sortPolicy.setSortTypes(sortTypes); + + // WHEN + simulateInitialization(&sortPolicy, &backendNode); + + // THEN + QCOMPARE(backendNode.peerId(), sortPolicy.id()); + QCOMPARE(backendNode.parentId(), parent.id()); + QCOMPARE(backendNode.sortTypes(), sortTypes); + } + + void checkPropertyChanges() + { + // GIVEN + const auto sortTypes = QVector<Qt3DRender::QSortPolicy::SortType>() << Qt3DRender::QSortPolicy::BackToFront + << Qt3DRender::QSortPolicy::Material; + TestRenderer renderer; + Qt3DRender::Render::SortPolicy backendNode; + backendNode.setRenderer(&renderer); + + // WHEN + auto sortTypeInts = QVector<int>(); + std::transform(sortTypes.constBegin(), sortTypes.constEnd(), + std::back_inserter(sortTypeInts), + [] (Qt3DRender::QSortPolicy::SortType type) -> int { return type; }); + Qt3DCore::QPropertyUpdatedChangePtr updateChange(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId())); + updateChange->setValue(QVariant::fromValue(sortTypeInts)); + updateChange->setPropertyName("sortTypes"); + backendNode.sceneChangeEvent(updateChange); + + // THEN + QCOMPARE(backendNode.sortTypes(), sortTypes); + } +}; + + +QTEST_APPLESS_MAIN(tst_SortPolicy) + +#include "tst_sortpolicy.moc" diff --git a/tests/manual/assimp-cpp/main.cpp b/tests/manual/assimp-cpp/main.cpp index 9701cb66a..06e0907be 100644 --- a/tests/manual/assimp-cpp/main.cpp +++ b/tests/manual/assimp-cpp/main.cpp @@ -118,7 +118,7 @@ int main(int ac, char **av) { QApplication app(ac, av); Qt3DExtras::Qt3DWindow view; - view.defaultFramegraph()->setClearColor(Qt::black); + view.defaultFrameGraph()->setClearColor(Qt::black); // Root entity Qt3DCore::QEntity *sceneRoot = new Qt3DCore::QEntity(); diff --git a/tests/manual/bigscene-cpp/main.cpp b/tests/manual/bigscene-cpp/main.cpp index 95b198f58..ebbd499f3 100644 --- a/tests/manual/bigscene-cpp/main.cpp +++ b/tests/manual/bigscene-cpp/main.cpp @@ -77,7 +77,7 @@ int main(int ac, char **av) { QGuiApplication app(ac, av); Qt3DExtras::Qt3DWindow view; - view.defaultFramegraph()->setClearColor(Qt::black); + view.defaultFrameGraph()->setClearColor(Qt::black); QEntity *root = new QEntity(); diff --git a/tests/manual/clip-planes-qml/CappingMaterialEffect.qml b/tests/manual/clip-planes-qml/CappingMaterialEffect.qml index 512e9f920..e503b15e3 100644 --- a/tests/manual/clip-planes-qml/CappingMaterialEffect.qml +++ b/tests/manual/clip-planes-qml/CappingMaterialEffect.qml @@ -70,7 +70,7 @@ Effect { graphicsApiFilter { api: GraphicsApiFilter.OpenGL - profile: GraphicsApiFilter.NoProfile + profile: GraphicsApiFilter.CoreProfile majorVersion: 3 minorVersion: 2 } diff --git a/tests/manual/clip-planes-qml/ClipMaterialEffect.qml b/tests/manual/clip-planes-qml/ClipMaterialEffect.qml index 7132831ed..f6761403f 100644 --- a/tests/manual/clip-planes-qml/ClipMaterialEffect.qml +++ b/tests/manual/clip-planes-qml/ClipMaterialEffect.qml @@ -69,7 +69,7 @@ Effect { graphicsApiFilter { api: GraphicsApiFilter.OpenGL - profile: GraphicsApiFilter.NoProfile + profile: GraphicsApiFilter.CoreProfile majorVersion: 3 minorVersion: 2 } diff --git a/tests/manual/clip-planes-qml/main.qml b/tests/manual/clip-planes-qml/main.qml index 4ab043285..7f449e291 100644 --- a/tests/manual/clip-planes-qml/main.qml +++ b/tests/manual/clip-planes-qml/main.qml @@ -91,7 +91,7 @@ Entity { ClippingPlanes { id: clippingPlanes visualizationLayer: frameGraph.visualizationLayer - capsLayer: frameGraph.contentLayer + capsLayer: frameGraph.capsLayer } // Entity being clipped diff --git a/tests/manual/custom-mesh-cpp/main.cpp b/tests/manual/custom-mesh-cpp/main.cpp index 26fc236be..e51321e65 100644 --- a/tests/manual/custom-mesh-cpp/main.cpp +++ b/tests/manual/custom-mesh-cpp/main.cpp @@ -76,7 +76,7 @@ int main(int argc, char* argv[]) { QGuiApplication app(argc, argv); Qt3DExtras::Qt3DWindow view; - view.defaultFramegraph()->setClearColor(QColor::fromRgbF(0.0, 0.5, 1.0, 1.0)); + view.defaultFrameGraph()->setClearColor(QColor::fromRgbF(0.0, 0.5, 1.0, 1.0)); // Root entity Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity(); diff --git a/tests/manual/custom-mesh-update-data-cpp/main.cpp b/tests/manual/custom-mesh-update-data-cpp/main.cpp index 94c4d6982..7485dbec5 100644 --- a/tests/manual/custom-mesh-update-data-cpp/main.cpp +++ b/tests/manual/custom-mesh-update-data-cpp/main.cpp @@ -95,7 +95,7 @@ int main(int argc, char* argv[]) { QGuiApplication app(argc, argv); Qt3DExtras::Qt3DWindow view; - view.defaultFramegraph()->setClearColor(QColor::fromRgbF(0.0, 0.5, 1.0, 1.0)); + view.defaultFrameGraph()->setClearColor(QColor::fromRgbF(0.0, 0.5, 1.0, 1.0)); // Root entity Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity(); diff --git a/tests/manual/deferred-renderer-cpp/deferredrenderer.cpp b/tests/manual/deferred-renderer-cpp/deferredrenderer.cpp index 5d613fef8..48f8ad3fe 100644 --- a/tests/manual/deferred-renderer-cpp/deferredrenderer.cpp +++ b/tests/manual/deferred-renderer-cpp/deferredrenderer.cpp @@ -64,7 +64,9 @@ DeferredRenderer::DeferredRenderer(Qt3DCore::QNode *parent) , m_geometryPassFilter(new Qt3DRender::QRenderPassFilter(m_clearGBuffer)) , m_finalPassFilter(new Qt3DRender::QRenderPassFilter(m_clearScreenQuad)) , m_sceneCameraSelector(new Qt3DRender::QCameraSelector(m_geometryPassFilter)) + , m_winSize(new Qt3DRender::QParameter(QStringLiteral("winSize"), QSizeF(1024.0f, 768.0f))) , m_gBuffer(new GBuffer(this)) + , m_window(nullptr) { m_clearGBuffer->setBuffers(Qt3DRender::QClearBuffers::ColorDepthBuffer); m_clearScreenQuad->setBuffers(Qt3DRender::QClearBuffers::ColorDepthBuffer); @@ -73,13 +75,7 @@ DeferredRenderer::DeferredRenderer(Qt3DCore::QNode *parent) m_finalPassFilter->addParameter(new Qt3DRender::QParameter(QStringLiteral("position"), m_gBuffer->positionTexture())); m_finalPassFilter->addParameter(new Qt3DRender::QParameter(QStringLiteral("normal"), m_gBuffer->normalTexture())); m_finalPassFilter->addParameter(new Qt3DRender::QParameter(QStringLiteral("color"), m_gBuffer->colorTexture())); - - Qt3DRender::QParameter *winSize = new Qt3DRender::QParameter(QStringLiteral("winSize"), QSize(1024, 768)); - QObject::connect(m_surfaceSelector, &Qt3DRender::QRenderSurfaceSelector::externalRenderTargetSizeChanged, - [=] (const QSize &viewSize) { - winSize->setValue(viewSize); - }); - m_finalPassFilter->addParameter(winSize); + m_finalPassFilter->addParameter(m_winSize); } void DeferredRenderer::setSceneCamera(Qt3DCore::QEntity *camera) @@ -111,5 +107,27 @@ void DeferredRenderer::setScreenQuadLayer(Qt3DRender::QLayer *layer) void DeferredRenderer::setSurface(QWindow *surface) { - m_surfaceSelector->setSurface(surface); + if (surface != m_window) { + + // Disconnect old window's signals + if (m_window != nullptr) { + QObject::disconnect(m_widthChangedConnection); + QObject::disconnect(m_heightChangedConnection); + } + + m_window = surface; + m_surfaceSelector->setSurface(surface); + + if (m_window != nullptr) { + // Store connections + m_widthChangedConnection = QObject::connect(surface, &QWindow::widthChanged, + [this] (int width) { + m_winSize->setValue(QSizeF(float(width), m_winSize->value().toSizeF().height())); + }); + m_heightChangedConnection = QObject::connect(surface, &QWindow::heightChanged, + [this] (int height) { + m_winSize->setValue(QSizeF(m_winSize->value().toSizeF().width(), float(height))); + }); + } + } } diff --git a/tests/manual/deferred-renderer-cpp/deferredrenderer.h b/tests/manual/deferred-renderer-cpp/deferredrenderer.h index 4483afb07..0d22c1e81 100644 --- a/tests/manual/deferred-renderer-cpp/deferredrenderer.h +++ b/tests/manual/deferred-renderer-cpp/deferredrenderer.h @@ -85,7 +85,12 @@ private: Qt3DRender::QRenderPassFilter *m_geometryPassFilter; Qt3DRender::QRenderPassFilter *m_finalPassFilter; Qt3DRender::QCameraSelector *m_sceneCameraSelector; + Qt3DRender::QParameter *m_winSize; GBuffer *m_gBuffer; + QWindow *m_window; + + QMetaObject::Connection m_widthChangedConnection; + QMetaObject::Connection m_heightChangedConnection; }; #endif // DEFERREDRENDERER_H diff --git a/tests/manual/deferred-renderer-cpp/sceneeffect.cpp b/tests/manual/deferred-renderer-cpp/sceneeffect.cpp index 8e0b597ca..570df66c7 100644 --- a/tests/manual/deferred-renderer-cpp/sceneeffect.cpp +++ b/tests/manual/deferred-renderer-cpp/sceneeffect.cpp @@ -65,10 +65,10 @@ SceneEffect::SceneEffect(Qt3DCore::QNode *parent) , m_passCriterion(new Qt3DRender::QFilterKey(this)) { - m_gl3Technique->graphicsApiFilter()->setProfile(Qt3DRender::QGraphicsApiFilter::NoProfile); + m_gl3Technique->graphicsApiFilter()->setProfile(Qt3DRender::QGraphicsApiFilter::CoreProfile); m_gl3Technique->graphicsApiFilter()->setApi(Qt3DRender::QGraphicsApiFilter::OpenGL); m_gl3Technique->graphicsApiFilter()->setMajorVersion(3); - m_gl3Technique->graphicsApiFilter()->setMinorVersion(3); + m_gl3Technique->graphicsApiFilter()->setMinorVersion(1); m_gl2Technique->graphicsApiFilter()->setApi(Qt3DRender::QGraphicsApiFilter::OpenGL); m_gl2Technique->graphicsApiFilter()->setMajorVersion(2); diff --git a/tests/manual/deferred-renderer-qml/DeferredRenderer.qml b/tests/manual/deferred-renderer-qml/DeferredRenderer.qml index 9ee2c2345..8e10005a5 100644 --- a/tests/manual/deferred-renderer-qml/DeferredRenderer.qml +++ b/tests/manual/deferred-renderer-qml/DeferredRenderer.qml @@ -61,7 +61,12 @@ Viewport { property alias screenQuadLayer: screenQuadLayerFilter.layers property alias debugLayer: debugLayerFilter.layers + readonly property real windowWidth: surfaceSelector.surface !== null ? surfaceSelector.surface.width: 0 + readonly property real windowHeight: surfaceSelector.surface !== null ? surfaceSelector.surface.height: 0 + RenderSurfaceSelector { + id: surfaceSelector + CameraSelector { id : sceneCameraSelector @@ -104,7 +109,7 @@ Viewport { buffers: ClearBuffers.ColorDepthBuffer RenderPassFilter { matchAny : FilterKey { name : "pass"; value : "final" } - parameters: Parameter { name: "winSize"; value : Qt.size(1024, 768) } + parameters: Parameter { name: "winSize"; value : Qt.size(windowWidth, windowHeight) } } } @@ -116,7 +121,7 @@ Viewport { normalizedRect : Qt.rect(0.5, 0.5, 0.5, 0.5) RenderPassFilter { matchAny : FilterKey { name : "pass"; value : "final" } - parameters: Parameter { name: "winSize"; value : Qt.size(1024 * 0.5, 768 * 0.5) } + parameters: Parameter { name: "winSize"; value : Qt.size(windowWidth * 0.5, windowHeight * 0.5) } } } } diff --git a/tests/manual/deferred-renderer-qml/GBufferDebugger.qml b/tests/manual/deferred-renderer-qml/GBufferDebugger.qml index f7c730cb1..7f148099e 100644 --- a/tests/manual/deferred-renderer-qml/GBufferDebugger.qml +++ b/tests/manual/deferred-renderer-qml/GBufferDebugger.qml @@ -65,46 +65,18 @@ Entity { renderPasses: RenderPass { filterKeys: FilterKey { name: "pass"; value: "final" } shaderProgram: ShaderProgram { - vertexShaderCode: - "#version 110 - - attribute vec4 vertexPosition; - uniform mat4 modelMatrix; - - void main() - { - gl_Position = modelMatrix * vertexPosition; - }" - - fragmentShaderCode: - "#version 110 - - uniform sampler2D color; - uniform sampler2D position; - uniform sampler2D normal; - uniform sampler2D depth; - uniform vec2 winSize; - - void main() - { - vec2 texCoord = (gl_FragCoord.xy + vec2(-winSize.x, 0)) / winSize; - - // Draw 4 quadrants - if (texCoord.x > 0.5) { // Right - if (texCoord.y > 0.5) { // Top - gl_FragColor = vec4(texture2D(normal, vec2(texCoord.x - 0.5, texCoord.y - 0.5) * 2.0).xyz, 1.0); - } else { // Bottom - gl_FragColor = vec4(texture2D(color, vec2(texCoord.x - 0.5, texCoord.y) * 2.0).xyz, 1.0); - } - } else { // Left - if (texCoord.y > 0.5) { // Top - gl_FragColor = texture2D(position, vec2(texCoord.x, texCoord.y - 0.5) * 2.0); - } else { // Bottom - gl_FragColor = vec4(texture2D(depth, texCoord * 2.0).rrr, 1.0); - } - } - gl_FragColor.a = 0.5; - }" + vertexShaderCode: loadSource("qrc:/debug_es2.vert") + fragmentShaderCode: loadSource("qrc:/debug_es2.frag") + } + } + }, + Technique { + graphicsApiFilter {api : GraphicsApiFilter.OpenGL; profile : GraphicsApiFilter.CoreProfile; minorVersion : 2; majorVersion : 3 } + renderPasses: RenderPass { + filterKeys: FilterKey { name: "pass"; value: "final" } + shaderProgram: ShaderProgram { + vertexShaderCode: loadSource("qrc:/debug_gl3.vert") + fragmentShaderCode: loadSource("qrc:/debug_gl3.frag") } } } diff --git a/tests/manual/deferred-renderer-qml/debug_es2.frag b/tests/manual/deferred-renderer-qml/debug_es2.frag new file mode 100644 index 000000000..8438ca916 --- /dev/null +++ b/tests/manual/deferred-renderer-qml/debug_es2.frag @@ -0,0 +1,28 @@ +#version 110 + +uniform sampler2D color; +uniform sampler2D position; +uniform sampler2D normal; +uniform sampler2D depth; +uniform vec2 winSize; + +void main() +{ + vec2 texCoord = (gl_FragCoord.xy + vec2(-winSize.x, 0)) / winSize; + + // Draw 4 quadrants + if (texCoord.x > 0.5) { // Right + if (texCoord.y > 0.5) { // Top + gl_FragColor = vec4(texture2D(normal, vec2(texCoord.x - 0.5, texCoord.y - 0.5) * 2.0).xyz, 1.0); + } else { // Bottom + gl_FragColor = vec4(texture2D(color, vec2(texCoord.x - 0.5, texCoord.y) * 2.0).xyz, 1.0); + } + } else { // Left + if (texCoord.y > 0.5) { // Top + gl_FragColor = texture2D(position, vec2(texCoord.x, texCoord.y - 0.5) * 2.0); + } else { // Bottom + gl_FragColor = vec4(texture2D(depth, texCoord * 2.0).rrr, 1.0); + } + } + gl_FragColor.a = 0.5; +} diff --git a/tests/manual/deferred-renderer-qml/debug_es2.vert b/tests/manual/deferred-renderer-qml/debug_es2.vert new file mode 100644 index 000000000..a907e10ca --- /dev/null +++ b/tests/manual/deferred-renderer-qml/debug_es2.vert @@ -0,0 +1,9 @@ +#version 110 + +attribute vec4 vertexPosition; +uniform mat4 modelMatrix; + +void main() +{ + gl_Position = modelMatrix * vertexPosition; +} diff --git a/tests/manual/deferred-renderer-qml/debug_gl3.frag b/tests/manual/deferred-renderer-qml/debug_gl3.frag new file mode 100644 index 000000000..571174d3b --- /dev/null +++ b/tests/manual/deferred-renderer-qml/debug_gl3.frag @@ -0,0 +1,30 @@ +#version 150 + +uniform sampler2D color; +uniform sampler2D position; +uniform sampler2D normal; +uniform sampler2D depth; +uniform vec2 winSize; + +out vec4 fragColor; + +void main() +{ + vec2 texCoord = (gl_FragCoord.xy + vec2(-winSize.x, 0)) / winSize; + + // Draw 4 quadrants + if (texCoord.x > 0.5) { // Right + if (texCoord.y > 0.5) { // Top + fragColor = vec4(texture(normal, vec2(texCoord.x - 0.5, texCoord.y - 0.5) * 2.0).xyz, 1.0); + } else { // Bottom + fragColor = vec4(texture(color, vec2(texCoord.x - 0.5, texCoord.y) * 2.0).xyz, 1.0); + } + } else { // Left + if (texCoord.y > 0.5) { // Top + fragColor = texture(position, vec2(texCoord.x, texCoord.y - 0.5) * 2.0); + } else { // Bottom + fragColor = vec4(texture(depth, texCoord * 2.0).rrr, 1.0); + } + } + fragColor.a = 0.5; +} diff --git a/tests/manual/deferred-renderer-qml/debug_gl3.vert b/tests/manual/deferred-renderer-qml/debug_gl3.vert new file mode 100644 index 000000000..2ed46a471 --- /dev/null +++ b/tests/manual/deferred-renderer-qml/debug_gl3.vert @@ -0,0 +1,9 @@ +#version 150 + +in vec4 vertexPosition; +uniform mat4 modelMatrix; + +void main() +{ + gl_Position = modelMatrix * vertexPosition; +} diff --git a/tests/manual/deferred-renderer-qml/deferred-renderer-qml.qrc b/tests/manual/deferred-renderer-qml/deferred-renderer-qml.qrc index 6ee17f42d..a2ca88cf9 100644 --- a/tests/manual/deferred-renderer-qml/deferred-renderer-qml.qrc +++ b/tests/manual/deferred-renderer-qml/deferred-renderer-qml.qrc @@ -12,5 +12,9 @@ <file>final_gl3.vert</file> <file>final_es2.frag</file> <file>GBufferDebugger.qml</file> + <file>debug_gl3.vert</file> + <file>debug_gl3.frag</file> + <file>debug_es2.frag</file> + <file>debug_es2.vert</file> </qresource> </RCC> diff --git a/tests/manual/paintedtexture-cpp/main.cpp b/tests/manual/paintedtexture-cpp/main.cpp index d8f5c515c..4651acd65 100644 --- a/tests/manual/paintedtexture-cpp/main.cpp +++ b/tests/manual/paintedtexture-cpp/main.cpp @@ -73,7 +73,7 @@ int main(int argc, char **argv) QApplication app(argc, argv); Qt3DExtras::Qt3DWindow *view = new Qt3DExtras::Qt3DWindow(); - view->defaultFramegraph()->setClearColor(QColor(QRgb(0x4d4d4f))); + view->defaultFrameGraph()->setClearColor(QColor(QRgb(0x4d4d4f))); QWidget *container = QWidget::createWindowContainer(view); QSize screenSize = view->screen()->size(); container->setMinimumSize(QSize(200, 100)); |