summaryrefslogtreecommitdiffstats
path: root/src/quick3d/imports/scene3d/scene3ditem.cpp
diff options
context:
space:
mode:
authorPaul Lemire <paul.lemire@kdab.com>2019-08-06 12:51:05 +0200
committerPaul Lemire <paul.lemire@kdab.com>2019-08-27 12:10:09 +0200
commit1fcbcf06da29a1fadd64f1fd53f6cac27f417fe1 (patch)
tree5344980743a7c8ddf084e0b7491793bda993800c /src/quick3d/imports/scene3d/scene3ditem.cpp
parent5344d87197c83feb7d00931a6756eea870be953c (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.cpp90
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;
}