diff options
Diffstat (limited to 'src/quick3d/imports/scene3d')
-rw-r--r-- | src/quick3d/imports/scene3d/plugins.qmltypes | 38 | ||||
-rw-r--r-- | src/quick3d/imports/scene3d/scene3ditem.cpp | 81 | ||||
-rw-r--r-- | src/quick3d/imports/scene3d/scene3drenderer.cpp | 23 | ||||
-rw-r--r-- | src/quick3d/imports/scene3d/scene3drenderer_p.h | 3 | ||||
-rw-r--r-- | src/quick3d/imports/scene3d/scene3dsgmaterialshader.cpp | 1 | ||||
-rw-r--r-- | src/quick3d/imports/scene3d/scene3dview.cpp | 2 |
6 files changed, 125 insertions, 23 deletions
diff --git a/src/quick3d/imports/scene3d/plugins.qmltypes b/src/quick3d/imports/scene3d/plugins.qmltypes index da3d7ec3e..aca01ac25 100644 --- a/src/quick3d/imports/scene3d/plugins.qmltypes +++ b/src/quick3d/imports/scene3d/plugins.qmltypes @@ -4,7 +4,7 @@ import QtQuick.tooling 1.2 // It is used for QML tooling purposes only. // // This file was auto-generated by: -// 'qmlplugindump -nonrelocatable -dependencies dependencies.json QtQuick.Scene3D 2.13' +// 'qmlplugindump -nonrelocatable -dependencies dependencies.json QtQuick.Scene3D 2.14' Module { dependencies: ["Qt3D.Core 2.0", "QtQuick 2.0"] @@ -12,8 +12,11 @@ Module { name: "Qt3DRender::Scene3DItem" defaultProperty: "entity" prototype: "QQuickItem" - exports: ["QtQuick.Scene3D/Scene3D 2.0"] - exportMetaObjectRevisions: [0] + exports: [ + "QtQuick.Scene3D/Scene3D 2.0", + "QtQuick.Scene3D/Scene3D 2.14" + ] + exportMetaObjectRevisions: [0, 14] Enum { name: "CameraAspectRatioMode" values: { @@ -21,11 +24,19 @@ Module { "UserAspectRatio": 1 } } + Enum { + name: "CompositingMode" + values: { + "FBO": 0, + "Underlay": 1 + } + } Property { name: "entity"; type: "Qt3DCore::QEntity"; isPointer: true } Property { name: "aspects"; type: "QStringList" } Property { name: "multisample"; type: "bool" } Property { name: "cameraAspectRatioMode"; type: "CameraAspectRatioMode" } Property { name: "hoverEnabled"; type: "bool" } + Property { name: "compositingMode"; revision: 14; type: "CompositingMode" } Signal { name: "cameraAspectRatioModeChanged" Parameter { name: "mode"; type: "CameraAspectRatioMode" } @@ -47,9 +58,30 @@ Module { Parameter { name: "enabled"; type: "bool" } } Method { + name: "setCompositingMode" + Parameter { name: "mode"; type: "CompositingMode" } + } + Method { name: "setItemAreaAndDevicePixelRatio" Parameter { name: "area"; type: "QSize" } Parameter { name: "devicePixelRatio"; type: "double" } } } + Component { + name: "Qt3DRender::Scene3DView" + defaultProperty: "entity" + prototype: "QQuickItem" + exports: ["QtQuick.Scene3D/Scene3DView 2.14"] + exportMetaObjectRevisions: [0] + Property { name: "entity"; type: "Qt3DCore::QEntity"; isPointer: true } + Property { name: "scene3D"; type: "Qt3DRender::Scene3DItem"; isPointer: true } + Method { + name: "setEntity" + Parameter { name: "entity"; type: "Qt3DCore::QEntity"; isPointer: true } + } + Method { + name: "setScene3D" + Parameter { name: "scene3D"; type: "Scene3DItem"; isPointer: true } + } + } } diff --git a/src/quick3d/imports/scene3d/scene3ditem.cpp b/src/quick3d/imports/scene3d/scene3ditem.cpp index f3f7acd71..f824d2c4e 100644 --- a/src/quick3d/imports/scene3d/scene3ditem.cpp +++ b/src/quick3d/imports/scene3d/scene3ditem.cpp @@ -137,6 +137,11 @@ namespace Qt3DRender { \li The Scene3D instance is instantiated prior to any Scene3DView \li The Scene3D entity property is left unset \endlist + + \note Åšetting the visibility of the Scene3D element to false will halt the + Qt 3D simulation loop. This means that binding the visible property to an + expression that depends on property updates driven by the Qt 3D simulation + loop (FrameAction) will never reavaluates. */ Scene3DItem::Scene3DItem(QQuickItem *parent) : QQuickItem(parent) @@ -154,6 +159,7 @@ Scene3DItem::Scene3DItem(QQuickItem *parent) , m_disableClearWindow(false) , m_cameraAspectRatioMode(AutomaticAspectRatio) , m_compositingMode(FBO) + , m_dummySurface(nullptr) { setFlag(QQuickItem::ItemHasContents, true); setAcceptedMouseButtons(Qt::MouseButtonMask); @@ -427,12 +433,26 @@ void Scene3DItem::applyRootEntityChange() bool Scene3DItem::needsRender() { + // We need the dirty flag which is connected to the change arbiter + // receiving updates to know whether something in the scene has changed + + // Ideally we would use shouldRender() alone but given that it becomes true + // only after the arbiter has sync the changes and might be reset before + // process jobs is completed, we cannot fully rely on it. It would require + // splitting processFrame in 2 parts. + + // We only use it for cases where Qt3D render may require several loops of + // the simulation to fully process a frame (e.g shaders are loaded in frame + // n and we can only build render commands for the new shader at frame n + + // This is where renderer->shouldRender() comes into play as it knows + // whether some states remain dirty or not (even after processFrame is + // called) + auto renderAspectPriv = static_cast<QRenderAspectPrivate*>(QRenderAspectPrivate::get(m_renderAspect)); const bool dirty = m_dirty || (renderAspectPriv && renderAspectPriv->m_renderer - && renderAspectPriv->m_renderer->settings() - && renderAspectPriv->m_renderer->settings()->renderPolicy() == QRenderSettings::Always); + && renderAspectPriv->m_renderer->shouldRender()); m_dirty = false; return dirty; } @@ -454,8 +474,12 @@ bool Scene3DItem::needsRender() // processFrame will block and wait for renderer to have been finished void Scene3DItem::onBeforeSync() { - // Has anything in the 3D scene actually changed that requires us to render? - if (!needsRender()) + static bool dontRenderWhenHidden = !qgetenv("QT3D_SCENE3D_STOP_RENDER_HIDDEN").isEmpty(); + + // If we are not visible, don't processFrame changes as we would end up + // waiting forever for the scene to be rendered which won't happen + // if the Scene3D item is not visible + if (!isVisible() && dontRenderWhenHidden) return; Q_ASSERT(QThread::currentThread() == thread()); @@ -498,6 +522,7 @@ void Scene3DItem::onBeforeSync() // start rendering before this function has been called // We add in a safety to skip such frames as this could otherwise // make Qt3D enter a locked state + m_renderer->setSkipFrame(!needsRender()); m_renderer->allowRender(); // Note: it's too early to request an update at this point as @@ -546,7 +571,7 @@ void Scene3DItem::setWindowSurface(QObject *rootObject) /*! \qmlmethod void Scene3D::setItemAreaAndDevicePixelRatio(size area, real devicePixelRatio) - \brief \TODO + Sets the item area to \a area and the pixel ratio to \a devicePixelRatio. */ void Scene3DItem::setItemAreaAndDevicePixelRatio(QSize area, qreal devicePixelRatio) { @@ -569,25 +594,45 @@ bool Scene3DItem::isHoverEnabled() const void Scene3DItem::setCameraAspectModeHelper() { - switch (m_cameraAspectRatioMode) { - case AutomaticAspectRatio: - connect(this, &Scene3DItem::widthChanged, this, &Scene3DItem::updateCameraAspectRatio); - connect(this, &Scene3DItem::heightChanged, this, &Scene3DItem::updateCameraAspectRatio); - // Update the aspect ratio the first time the surface is set - updateCameraAspectRatio(); - break; - case UserAspectRatio: - disconnect(this, &Scene3DItem::widthChanged, this, &Scene3DItem::updateCameraAspectRatio); - disconnect(this, &Scene3DItem::heightChanged, this, &Scene3DItem::updateCameraAspectRatio); - break; + if (m_compositingMode == FBO) { + switch (m_cameraAspectRatioMode) { + case AutomaticAspectRatio: + connect(this, &Scene3DItem::widthChanged, this, &Scene3DItem::updateCameraAspectRatio); + connect(this, &Scene3DItem::heightChanged, this, &Scene3DItem::updateCameraAspectRatio); + // Update the aspect ratio the first time the surface is set + updateCameraAspectRatio(); + break; + case UserAspectRatio: + disconnect(this, &Scene3DItem::widthChanged, this, &Scene3DItem::updateCameraAspectRatio); + disconnect(this, &Scene3DItem::heightChanged, this, &Scene3DItem::updateCameraAspectRatio); + break; + } + } else { + // In Underlay mode, we rely on the window for aspect ratio and not the size of the Scene3DItem + switch (m_cameraAspectRatioMode) { + case AutomaticAspectRatio: + connect(window(), &QWindow::widthChanged, this, &Scene3DItem::updateCameraAspectRatio); + connect(window(), &QWindow::heightChanged, this, &Scene3DItem::updateCameraAspectRatio); + // Update the aspect ratio the first time the surface is set + updateCameraAspectRatio(); + break; + case UserAspectRatio: + disconnect(window(), &QWindow::widthChanged, this, &Scene3DItem::updateCameraAspectRatio); + disconnect(window(), &QWindow::heightChanged, this, &Scene3DItem::updateCameraAspectRatio); + break; + } } } void Scene3DItem::updateCameraAspectRatio() { if (m_camera) { - m_camera->setAspectRatio(static_cast<float>(width()) / - static_cast<float>(height())); + if (m_compositingMode == FBO) + m_camera->setAspectRatio(static_cast<float>(width()) / + static_cast<float>(height())); + else + m_camera->setAspectRatio(static_cast<float>(window()->width()) / + static_cast<float>(window()->height())); } } diff --git a/src/quick3d/imports/scene3d/scene3drenderer.cpp b/src/quick3d/imports/scene3d/scene3drenderer.cpp index 1e375ccbb..fafeeedf4 100644 --- a/src/quick3d/imports/scene3d/scene3drenderer.cpp +++ b/src/quick3d/imports/scene3d/scene3drenderer.cpp @@ -161,7 +161,9 @@ Scene3DRenderer::Scene3DRenderer(Scene3DItem *item, Qt3DCore::QAspectEngine *asp , m_forceRecreate(false) , m_shouldRender(false) , m_dirtyViews(false) + , m_skipFrame(false) , m_allowRendering(0) + , m_compositingMode(Scene3DItem::FBO) { Q_CHECK_PTR(m_item); Q_CHECK_PTR(m_item->window()); @@ -277,6 +279,19 @@ void Scene3DRenderer::beforeSynchronize() // We could otherwise enter a deadlock state if (!m_allowRendering.tryAcquire(std::max(m_allowRendering.available(), 1))) return; + + // In the case of OnDemand rendering, we still need to get to this + // point to ensure we have processed jobs for all aspects. + // We also still need to call render() to allow proceeding with the + // next frame. However it won't be performing any 3d rendering at all + // so we do it here and return early. This prevents a costly QtQuick + // SceneGraph update for nothing + if (m_skipFrame) { + m_skipFrame = false; + static_cast<QRenderAspectPrivate*>(QRenderAspectPrivate::get(m_renderAspect))->renderSynchronous(false); + return; + } + m_shouldRender = true; // Check size / multisampling @@ -359,6 +374,11 @@ void Scene3DRenderer::setCompositingMode(Scene3DItem::CompositingMode mode) m_compositingMode = mode; } +void Scene3DRenderer::setSkipFrame(bool skip) +{ + m_skipFrame = skip; +} + // Main Thread, Render Thread locked void Scene3DRenderer::setScene3DViews(const QVector<Scene3DView *> views) { @@ -422,7 +442,8 @@ void Scene3DRenderer::render() // Only show the node once Qt3D has rendered to it // Avoids showing garbage on the first frame - m_node->show(); + if (m_node) + m_node->show(); } // Reset the state used by the Qt Quick scenegraph to avoid any diff --git a/src/quick3d/imports/scene3d/scene3drenderer_p.h b/src/quick3d/imports/scene3d/scene3drenderer_p.h index 4f3651cd3..08a2c60a3 100644 --- a/src/quick3d/imports/scene3d/scene3drenderer_p.h +++ b/src/quick3d/imports/scene3d/scene3drenderer_p.h @@ -87,7 +87,7 @@ public: void setCleanerHelper(Scene3DCleaner *cleaner); void allowRender(); void setCompositingMode(Scene3DItem::CompositingMode mode); - + void setSkipFrame(bool skip); void setScene3DViews(const QVector<Scene3DView *> views); public Q_SLOTS: @@ -119,6 +119,7 @@ private: bool m_forceRecreate; bool m_shouldRender; bool m_dirtyViews; + bool m_skipFrame; QSemaphore m_allowRendering; Scene3DItem::CompositingMode m_compositingMode; QVector<Scene3DView *> m_views; diff --git a/src/quick3d/imports/scene3d/scene3dsgmaterialshader.cpp b/src/quick3d/imports/scene3d/scene3dsgmaterialshader.cpp index 55538ad1f..cfe39e8c7 100644 --- a/src/quick3d/imports/scene3d/scene3dsgmaterialshader.cpp +++ b/src/quick3d/imports/scene3d/scene3dsgmaterialshader.cpp @@ -76,6 +76,7 @@ Scene3DSGMaterialShader::Scene3DSGMaterialShader() : QSGMaterialShader() , m_matrixId(-1) , m_opacityId(-1) + , m_visibleId(-1) { } diff --git a/src/quick3d/imports/scene3d/scene3dview.cpp b/src/quick3d/imports/scene3d/scene3dview.cpp index 9d298b435..f38d135f0 100644 --- a/src/quick3d/imports/scene3d/scene3dview.cpp +++ b/src/quick3d/imports/scene3d/scene3dview.cpp @@ -278,6 +278,8 @@ QSGNode *Scene3DView::updatePaintNode(QSGNode *node, QQuickItem::UpdatePaintNode if (m_dirtyFlags & DirtyTexture) { fboNode->setTexture(m_texture); m_dirtyFlags.setFlag(DirtyTexture, false); + // Show FBO Node at this point + fboNode->show(); } if (m_dirtyFlags & DirtyNode) { fboNode->markDirty(QSGNode::DirtyMaterial); |