diff options
author | Paul Lemire <paul.lemire@kdab.com> | 2019-08-06 12:51:05 +0200 |
---|---|---|
committer | Paul Lemire <paul.lemire@kdab.com> | 2019-08-27 12:10:09 +0200 |
commit | 1fcbcf06da29a1fadd64f1fd53f6cac27f417fe1 (patch) | |
tree | 5344980743a7c8ddf084e0b7491793bda993800c /src/quick3d/imports/scene3d/scene3ditem.cpp | |
parent | 5344d87197c83feb7d00931a6756eea870be953c (diff) |
Scene3D: introduce compositingMode (FBO or Underlay)
The default compositing mode is FBO.
One of the problematic aspects of Scene3D is its round trip
through a FBO, which is moderately expensive on low-end hardware,
although it makes it a fully fledged Qt Quick 2 item. If one
wants MSAA then things are even worse, as an intermediate MS'ed
FBO is needed, then resolving into the final one, whose color
texture is then sampled.
However, there's a significant use case for which these FBOs
can be avoided, and that's the case of a 3D scene "below" other
QQ2 content. In this setup, Qt3D can simply render to the
screen, driven by QQ2; then QQ2 can draw on top.
(It's the typical "underlay" scenario.) This can be enabled by setting
the compositing mode to Underlay
[ChangeLog] Scene3D add compositingMode property. Allows underlay rendering.
Task-number: QTBUG-74977
Change-Id: I1ec5f5d60eab45835dbdb2596a7bf1b2ac3624e0
Reviewed-by: Mike Krus <mike.krus@kdab.com>
Diffstat (limited to 'src/quick3d/imports/scene3d/scene3ditem.cpp')
-rw-r--r-- | src/quick3d/imports/scene3d/scene3ditem.cpp | 90 |
1 files changed, 85 insertions, 5 deletions
diff --git a/src/quick3d/imports/scene3d/scene3ditem.cpp b/src/quick3d/imports/scene3d/scene3ditem.cpp index 9da35a34f..54f1554fd 100644 --- a/src/quick3d/imports/scene3d/scene3ditem.cpp +++ b/src/quick3d/imports/scene3d/scene3ditem.cpp @@ -132,7 +132,10 @@ Scene3DItem::Scene3DItem(QQuickItem *parent) , m_rendererCleaner(new Scene3DCleaner()) , m_multisample(true) , m_dirty(true) + , m_clearsWindowByDefault(true) + , m_disableClearWindow(false) , m_cameraAspectRatioMode(AutomaticAspectRatio) + , m_compositingMode(FBO) { setFlag(QQuickItem::ItemHasContents, true); setAcceptedMouseButtons(Qt::MouseButtonMask); @@ -140,6 +143,11 @@ Scene3DItem::Scene3DItem(QQuickItem *parent) // Use manual drive mode when using Scene3D m_aspectEngine->setRunMode(Qt3DCore::QAspectEngine::Manual); + + // Give a default size so that if nothing is specified by the user + // we still won't get ignored by the QtQuick SG when in Underlay mode + setWidth(1); + setHeight(1); } Scene3DItem::~Scene3DItem() @@ -246,6 +254,45 @@ void Scene3DItem::setHoverEnabled(bool enabled) } /*! + \qmlproperty enumeration Scene3D::compositingMode + + \value FBO + Scene is rendered into a Frame Buffer Object which can be costly on + some platform and hardware but allows a greater amount of + flexibility. Automatic aspect ratio. This is the compositing mode to + choose if your Scene3D element shouldn't occupy the entire screen + and if you optionally plan on having it resized or animated. In this + mode, the position of the Scene3D in the QML file controls its + stacking order with regard to the other Qt Quick elements. + + \value Underlay + Suitable for full screen 3D scenes where using an FBO might be too + resource intensive. Scene3D behaves as a QtQuick underlay. + + Please note that when using this mode, the size of the Scene3D and + its transformations are ignored and the rendering will occupy the + whole screen. The position of the Scene3D in the QML file won't have + any effect either. The Qt 3D content will be drawn prior to any Qt + Quick content. Care has to be taken not to overdraw and hide the Qt + 3D content by overlapping Qt Quick content. + + Additionally when using this mode, the window clearBeforeRendering + will be set to false automatically. + + \since 5.14 + \default FBO + */ +void Scene3DItem::setCompositingMode(Scene3DItem::CompositingMode mode) +{ + if (m_compositingMode == mode) + return; + m_compositingMode = mode; + emit compositingModeChanged(); + + QQuickItem::update(); +} + +/*! \qmlproperty enumeration Scene3D::cameraAspectRatioMode \value Scene3D.AutomaticAspectRatio @@ -260,6 +307,11 @@ Scene3DItem::CameraAspectRatioMode Scene3DItem::cameraAspectRatioMode() const return m_cameraAspectRatioMode; } +Scene3DItem::CompositingMode Scene3DItem::compositingMode() const +{ + return m_compositingMode; +} + void Scene3DItem::applyRootEntityChange() { if (m_aspectEngine->rootEntity() != m_entity) { @@ -351,7 +403,13 @@ void Scene3DItem::onBeforeSync() m_renderer->allowRender(); // Request refresh for next frame - QQuickItem::update(); + + // When using the FBO mode, only the QQuickItem needs to be updated + // When using the Underlay mode, the whole windows needs updating + if (m_compositingMode == FBO) + QQuickItem::update(); + else + window()->update(); } void Scene3DItem::setWindowSurface(QObject *rootObject) @@ -474,13 +532,35 @@ QSGNode *Scene3DItem::updatePaintNode(QSGNode *node, QQuickItem::UpdatePaintNode m_renderer = new Scene3DRenderer(this, m_aspectEngine, m_renderAspect); m_renderer->setCleanerHelper(m_rendererCleaner); } + m_renderer->setCompositingMode(m_compositingMode); Scene3DSGNode *fboNode = static_cast<Scene3DSGNode *>(node); - if (fboNode == nullptr) { - fboNode = new Scene3DSGNode(); - m_renderer->setSGNode(fboNode); + const bool usesFBO = m_compositingMode == FBO; + if (usesFBO) { + if (fboNode == nullptr) { + fboNode = new Scene3DSGNode(); + m_renderer->setSGNode(fboNode); + } + fboNode->setRect(boundingRect()); + + // Reset clear flag if we've set it to false it's still set to that + if (m_disableClearWindow && !window()->clearBeforeRendering()) + window()->setClearBeforeRendering(m_clearsWindowByDefault); + m_disableClearWindow = false; + } else { + // In FBOLess node the Scene3DItem doesn't have any QSGNode to actually + // manager + if (fboNode != nullptr) { + delete fboNode; + fboNode = nullptr; + m_renderer->setSGNode(fboNode); + } + // Record clearBeforeRendering value before we force it to false + m_clearsWindowByDefault = window()->clearBeforeRendering(); + m_disableClearWindow = true; + if (m_clearsWindowByDefault) + window()->setClearBeforeRendering(false); } - fboNode->setRect(boundingRect()); return fboNode; } |