diff options
author | Laszlo Agocs <laszlo.agocs@qt.io> | 2019-08-16 09:54:03 +0200 |
---|---|---|
committer | Laszlo Agocs <laszlo.agocs@qt.io> | 2019-08-22 16:10:19 +0200 |
commit | ef2715251e1785e273873e4000ed08fd99962ab7 (patch) | |
tree | 719be474a8cc13fe0a38bbf109501b090526e860 /examples | |
parent | 7b130535cf590b310f23c8167986588d3982ad20 (diff) |
Add missing scenegraph example docs
Change-Id: I72e18136a26cdfb52f204ce7d0491d14411956a4
Reviewed-by: Christian Strømme <christian.stromme@qt.io>
Diffstat (limited to 'examples')
-rw-r--r-- | examples/quick/scenegraph/d3d11underqml/doc/images/d3d11underqml-example.jpg | bin | 0 -> 79343 bytes | |||
-rw-r--r-- | examples/quick/scenegraph/d3d11underqml/doc/src/d3d11underqml.qdoc | 58 | ||||
-rw-r--r-- | examples/quick/scenegraph/metalunderqml/doc/images/metalunderqml-example.jpg | bin | 0 -> 55194 bytes | |||
-rw-r--r-- | examples/quick/scenegraph/metalunderqml/doc/src/metalunderqml.qdoc | 68 | ||||
-rw-r--r-- | examples/quick/scenegraph/openglunderqml/doc/src/openglunderqml.qdoc | 5 | ||||
-rw-r--r-- | examples/quick/scenegraph/rendernode/customrenderitem.cpp | 4 | ||||
-rw-r--r-- | examples/quick/scenegraph/rendernode/doc/images/rendernode-example.jpg | bin | 0 -> 77210 bytes | |||
-rw-r--r-- | examples/quick/scenegraph/rendernode/doc/src/rendernode.qdoc | 163 | ||||
-rw-r--r-- | examples/quick/scenegraph/rendernode/main.cpp | 2 | ||||
-rw-r--r-- | examples/quick/scenegraph/rendernode/main.qml | 8 | ||||
-rw-r--r-- | examples/quick/scenegraph/rendernode/openglrenderer.cpp | 11 | ||||
-rw-r--r-- | examples/quick/scenegraph/rendernode/openglrenderer.h | 2 |
12 files changed, 320 insertions, 1 deletions
diff --git a/examples/quick/scenegraph/d3d11underqml/doc/images/d3d11underqml-example.jpg b/examples/quick/scenegraph/d3d11underqml/doc/images/d3d11underqml-example.jpg Binary files differnew file mode 100644 index 0000000000..9f1e53ad61 --- /dev/null +++ b/examples/quick/scenegraph/d3d11underqml/doc/images/d3d11underqml-example.jpg diff --git a/examples/quick/scenegraph/d3d11underqml/doc/src/d3d11underqml.qdoc b/examples/quick/scenegraph/d3d11underqml/doc/src/d3d11underqml.qdoc new file mode 100644 index 0000000000..d7b60d3b81 --- /dev/null +++ b/examples/quick/scenegraph/d3d11underqml/doc/src/d3d11underqml.qdoc @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and 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 Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: https://www.gnu.org/licenses/fdl-1.3.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \example scenegraph/d3d11underqml + \title Scene Graph - Direct3D 11 Under QML + \ingroup qtquickexamples + \brief Shows how to render directly with Direct3D 11 under a Qt Quick scene. + + \image d3d11underqml-example.jpg + + The Direct3D 11 Under QML example shows how an application can make use + of the \l QQuickWindow::beforeRendering() signal to draw custom + D3D11 content under a Qt Quick scene. This signal is emitted at + the start of every frame, before the scene graph starts its + rendering, thus any D3D11 draw calls that are made as a response + to this signal, will stack under the Qt Quick items. + + As an alternative, applications that wish to render D3D11 content + on top of the Qt Quick scene, can do so by connecting to the \l + QQuickWindow::afterRendering() signal. + + In this example, we will also see how it is possible to have + values that are exposed to QML which affect the D3D11 + rendering. We animate the threshold value using a NumberAnimation + in the QML file and this value is used by the HLSL shader + program that draws the squircles. + + The example is equivalent in most ways to the \l{Scene Graph - OpenGL Under + QML}{OpenGL Under QML} and \l{Scene Graph - Metal Under QML}{Metal Under + QML} examples, they all render the same custom content, just via different + native APIs. + + */ diff --git a/examples/quick/scenegraph/metalunderqml/doc/images/metalunderqml-example.jpg b/examples/quick/scenegraph/metalunderqml/doc/images/metalunderqml-example.jpg Binary files differnew file mode 100644 index 0000000000..98085773de --- /dev/null +++ b/examples/quick/scenegraph/metalunderqml/doc/images/metalunderqml-example.jpg diff --git a/examples/quick/scenegraph/metalunderqml/doc/src/metalunderqml.qdoc b/examples/quick/scenegraph/metalunderqml/doc/src/metalunderqml.qdoc new file mode 100644 index 0000000000..d499f47de3 --- /dev/null +++ b/examples/quick/scenegraph/metalunderqml/doc/src/metalunderqml.qdoc @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and 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 Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: https://www.gnu.org/licenses/fdl-1.3.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \example scenegraph/metalunderqml + \title Scene Graph - Metal Under QML + \ingroup qtquickexamples + \brief Shows how to render directly with Metal under a Qt Quick scene. + + \image metalunderqml-example.jpg + + The Metal Under QML example shows how an application can make use + of the \l QQuickWindow::beforeRendering() and \l + QQuickWindow::beforeRenderPassRecording() signals to draw custom + Metal content under a Qt Quick scene. This signal is emitted at + the start of every frame, before the scene graph starts its + rendering, thus any Metal draw calls that are made as a response + to this signal, will stack under the Qt Quick items. There are two + signals, because the custom Metal commands are recorded onto the + same command buffer with the same render command encoder that the + scene graph uses. beforeRendering() on its own is not sufficient + for this because it gets emitted at the start of the frame, before + having an + \l{https://developer.apple.com/documentation/metal/mtlrendercommandencoder}{MTLRenderCommandEncoder} + available. By also connecting to beforeRenderPassRecording(), the + application can gain access to the necessary native objects. + + As an alternative, applications that wish to render Metal content + on top of the Qt Quick scene, can do so by connecting to the \l + QQuickWindow::afterRendering() and \l + QQuickWindow::afterRenderPassRecording() signals. + + In this example, we will also see how it is possible to have + values that are exposed to QML which affect the Metal + rendering. We animate the threshold value using a NumberAnimation + in the QML file and this value is used by the Metal shader + program that draws the squircles. + + The example is equivalent in most ways to the \l{Scene Graph - OpenGL Under + QML}{OpenGL Under QML} and \l{Scene Graph - Direct3D 11 Under QML}{Direct3D + 11 Under QML} examples, they all render the same custom content, just via + different native APIs. + + */ diff --git a/examples/quick/scenegraph/openglunderqml/doc/src/openglunderqml.qdoc b/examples/quick/scenegraph/openglunderqml/doc/src/openglunderqml.qdoc index 69a9d2ce4b..ed46b40420 100644 --- a/examples/quick/scenegraph/openglunderqml/doc/src/openglunderqml.qdoc +++ b/examples/quick/scenegraph/openglunderqml/doc/src/openglunderqml.qdoc @@ -50,6 +50,11 @@ in the QML file and this value is used by the OpenGL shader program that draws the squircles. + The example is equivalent in most ways to the \l{Scene Graph - Direct3D 11 Under + QML}{Direct3D 11 Under QML} and \l{Scene Graph - Metal Under QML}{Metal Under + QML} examples, they all render the same custom content, just via different + native APIs. + \snippet scenegraph/openglunderqml/squircle.h 2 First of all, we need an object we can expose to QML. This is a diff --git a/examples/quick/scenegraph/rendernode/customrenderitem.cpp b/examples/quick/scenegraph/rendernode/customrenderitem.cpp index 9dbe8d86a0..7ba9286afa 100644 --- a/examples/quick/scenegraph/rendernode/customrenderitem.cpp +++ b/examples/quick/scenegraph/rendernode/customrenderitem.cpp @@ -56,13 +56,16 @@ #include "d3d12renderer.h" #include "softwarerenderer.h" +//! [1] CustomRenderItem::CustomRenderItem(QQuickItem *parent) : QQuickItem(parent) { // Our item shows something so set the flag. setFlag(ItemHasContents); } +//! [1] +//! [2] QSGNode *CustomRenderItem::updatePaintNode(QSGNode *node, UpdatePaintNodeData *) { QSGRenderNode *n = static_cast<QSGRenderNode *>(node); @@ -98,3 +101,4 @@ QSGNode *CustomRenderItem::updatePaintNode(QSGNode *node, UpdatePaintNodeData *) return n; } +//! [2] diff --git a/examples/quick/scenegraph/rendernode/doc/images/rendernode-example.jpg b/examples/quick/scenegraph/rendernode/doc/images/rendernode-example.jpg Binary files differnew file mode 100644 index 0000000000..cbb59b950d --- /dev/null +++ b/examples/quick/scenegraph/rendernode/doc/images/rendernode-example.jpg diff --git a/examples/quick/scenegraph/rendernode/doc/src/rendernode.qdoc b/examples/quick/scenegraph/rendernode/doc/src/rendernode.qdoc new file mode 100644 index 0000000000..e7864387cc --- /dev/null +++ b/examples/quick/scenegraph/rendernode/doc/src/rendernode.qdoc @@ -0,0 +1,163 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and 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 Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: https://www.gnu.org/licenses/fdl-1.3.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \example scenegraph/rendernode + \title Scene Graph - Custom Rendering with QSGRenderNode + \ingroup qtquickexamples + \brief Shows how to integrate drawing via the native graphics API with the Qt Quick scene graph. + + \image rendernode-example.jpg + + \l QSGRenderNode allows integrating draw and other calls made directly via + the Qt Quick scene graph's underlying native graphics API (such as, Vulkan, + Metal, Direct 3D, or OpenGL). This example demonstrates implementing a + custom QQuickItem backed by a QSGRenderNode implementation, where the node + renders a triangle directly via the graphics API. The rest of the scene + (background, text, rectangles) are standard Qt Quick items. + + The custom item behaves like any other Qt Quick item, meaning it + participates and stacking and clipping as usual, which is a big difference + to the alternative approaches like having the custom rendering as an + overlay (connecting to \l QQuickWindow::afterRendering()) and underlay + (connecting to \l QQuickWindow::beforeRendering()) because those do not + offer the possibility of proper mixing of the custom content with the Qt + Quick scene. + + Another important feature is that QSGRenderNode can be helpful to preserve + performance, when compared to some of the alternatives. Going through \l + QQuickFramebufferObject allows creating a custom item similarly to what + this example does, but it does it by rendering the custom content in a + texture, and then drawing a textured quad with that texture. This can be + expensive on some systems due to the cost of texturing and blending. + QSGRenderNode avoids this since the native graphics calls are issued in + line with the draw calls for the scene graph's batches. + + All this comes at the cost of being more complex, and not necessarily being + suitable for all types of 3D content, in particular where vertices and + different depth would clash with the 2D content in the Qt Quick scene + graph's batches (those are better served by "flattening" into a 2D texture + via approaches like QQuickFramebufferObject). Therefore QSGRenderNode is + not always the right choice. It can however a good and powerful choice in + many cases. This is what the example demonstrates. + + Let's go through the most important parts of the code: + + \snippet scenegraph/rendernode/main.cpp 1 + + Our custom QML type is implemented in the class CustomRenderItem. + + \snippet scenegraph/rendernode/main.qml 2 + + The corresponding import in the QML document. + + \snippet scenegraph/rendernode/main.qml 3 + + The CustomRenderItem object. It is positioned to fill a big part of the + scene, covering its parent (the yellow rectangle; this will be used to + demonstrate clipping). The item will have its scale and rotation animated. + + \snippet scenegraph/rendernode/main.qml 4 + + Text items are used to show some helpful information, such as, the + active graphics API Qt Quick uses. + + \snippet scenegraph/rendernode/main.qml 5 + + Clicking the left mouse button is used to toggle clipping on the custom + item's parent item. By default this is done using scissoring (GL_SCISSOR_TEST + with OpenGL). A well-written QSGRenderNode implementation is expected to be + able to take this into account and enable scissor testing when the scene graph + indicates that it is necessary. + + The right mouse button is used to toggle an animation on the rotation of + the parent item. With clipping enabled, this demonstrates clipping via the + stencil buffer since a rectangular scissor is not appropriate when we need + to clip to a rotated rectangle shape. The scene graph fills up the stencil + buffer as necessary, the QSGRenderNode implementation just has to enable + stencil testing using the provided reference value. + + \snippet scenegraph/rendernode/customrenderitem.cpp 1 + + Moving on to the CustomRenderItem implementation. This is a visual item. + + \snippet scenegraph/rendernode/customrenderitem.cpp 2 + + The implementation of \l QQuickItem::updatePaintNode() creates (if not yet + done) and returns an instance of a suitable QSGRenderNode subclass. The + example supports multiple graphics APIs, and also the \c software backend. + + Let's look at the the render node for OpenGL (supporting both the + traditional, direct OpenGL-based scene graph, and also the modern, + abstracted variant using the RHI). For other graphics APIs, the concepts + and the outline of a QSGRenderNode implementation are the same. It is worth + noting that in some cases it will also be necessary to connect to a signal + like \l QQuickWindow::beforeRendering() to perform copy type of operations + (such as, vertex buffer uploads). This is not necessary for OpenGL, but it + is essential for Vulkan or Metal since there such operations cannot be + issued in render() as there is a renderpass being recorded when render() is + called. + + \snippet scenegraph/rendernode/openglrenderer.h 1 + + The main job is to provide implementations of the virtual QSGRenderNode functions. + + \snippet scenegraph/rendernode/openglrenderer.cpp 1 + + The pattern for safe graphics resource management is to do any cleanup in + \l{QSGRenderNode::releaseResources()}{releaseResources()}, while also + calling this from the destructor. + + \snippet scenegraph/rendernode/openglrenderer.cpp 2 + + The render() function initializes graphics resources (in this case, an + OpenGL shader program and a vertex buffer), if not yet done. It then + makes sure the necessary resources are bound and updates uniforms. + The transformation matrix and the opacity are provided by the scene graph + either via the \c state argument or base class functions. + + \snippet scenegraph/rendernode/openglrenderer.cpp 5 + + This render node is well-behaving since it basically renders in 2D, + respecting the item's geometry. This is not mandatory, but then flags() has + to return (or not return) the appropriate flags. + + \snippet scenegraph/rendernode/openglrenderer.cpp 3 + + After setting up vertex inputs, but before recording a draw call for our + triangle, it is important to set some state in order to integrate with the + rest of the scene correctly. Setting scissor and stencil as instructed by + \c state allows our item to render correctly even when there are one or + more clips in the parent chain. + + \snippet scenegraph/rendernode/openglrenderer.cpp 4 + + As shown above, we only really render in 2D (no depth), within the item's + geometry. changedStates() returns the flags corresponding to the OpenGL + states render() touches. + +*/ diff --git a/examples/quick/scenegraph/rendernode/main.cpp b/examples/quick/scenegraph/rendernode/main.cpp index 21419abfc9..146d787e50 100644 --- a/examples/quick/scenegraph/rendernode/main.cpp +++ b/examples/quick/scenegraph/rendernode/main.cpp @@ -58,7 +58,9 @@ int main(int argc, char **argv) { QGuiApplication app(argc, argv); +//! [1] qmlRegisterType<CustomRenderItem>("SceneGraphRendering", 2, 0, "CustomRenderItem"); +//! [1] QQuickView view; diff --git a/examples/quick/scenegraph/rendernode/main.qml b/examples/quick/scenegraph/rendernode/main.qml index 85060261c5..c89d6136c7 100644 --- a/examples/quick/scenegraph/rendernode/main.qml +++ b/examples/quick/scenegraph/rendernode/main.qml @@ -49,7 +49,9 @@ ****************************************************************************/ import QtQuick 2.8 +//! [2] import SceneGraphRendering 2.0 +//! [2] Item { Rectangle { @@ -60,6 +62,7 @@ Item { GradientStop { position: 1; color: "black" } } + //! [5] MouseArea { anchors.fill: parent acceptedButtons: Qt.LeftButton | Qt.RightButton @@ -73,6 +76,7 @@ Item { } } } + // ![5] Rectangle { id: clipper @@ -88,6 +92,7 @@ Item { running: false } + //! [3] CustomRenderItem { id: renderer width: bg.width - 20 @@ -102,6 +107,7 @@ Item { Translate { id: txIn; x: renderer.width / 2; y: renderer.height / 2 } ] } + //! [3] } SequentialAnimation { @@ -124,6 +130,7 @@ Item { loops: Animation.Infinite } + //! [4] Text { id: label anchors.bottom: parent.bottom @@ -146,6 +153,7 @@ Item { + "\nLeft click to toggle clipping to yellow rect" + "\nRight click to rotate (can be used to exercise stencil clip instead of scissor)" } + // ![4] } Text { diff --git a/examples/quick/scenegraph/rendernode/openglrenderer.cpp b/examples/quick/scenegraph/rendernode/openglrenderer.cpp index 5e6b9e3656..0633731617 100644 --- a/examples/quick/scenegraph/rendernode/openglrenderer.cpp +++ b/examples/quick/scenegraph/rendernode/openglrenderer.cpp @@ -57,6 +57,7 @@ #include <QOpenGLBuffer> #include <QOpenGLFunctions> +//! [1] OpenGLRenderNode::OpenGLRenderNode(QQuickItem *item) : m_item(item) { @@ -74,6 +75,7 @@ void OpenGLRenderNode::releaseResources() delete m_vbo; m_vbo = nullptr; } +//! [1] void OpenGLRenderNode::init() { @@ -121,19 +123,21 @@ void OpenGLRenderNode::init() m_vbo->release(); } +//! [2] void OpenGLRenderNode::render(const RenderState *state) { if (!m_program) init(); QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions(); - m_program->bind(); m_program->setUniformValue(m_matrixUniform, *state->projectionMatrix() * *matrix()); m_program->setUniformValue(m_opacityUniform, float(inheritedOpacity())); +//! [2] m_vbo->bind(); +//! [5] QPointF p0(m_item->width() - 1, m_item->height() - 1); QPointF p1(0, 0); QPointF p2(0, m_item->height() - 1); @@ -142,6 +146,7 @@ void OpenGLRenderNode::render(const RenderState *state) GLfloat(p1.x()), GLfloat(p1.y()), GLfloat(p2.x()), GLfloat(p2.y()) }; m_vbo->write(0, vertices, sizeof(vertices)); +//! [5] m_program->setAttributeBuffer(0, GL_FLOAT, 0, 2); m_program->setAttributeBuffer(1, GL_FLOAT, sizeof(vertices), 3); @@ -152,6 +157,7 @@ void OpenGLRenderNode::render(const RenderState *state) // (abstracted by RHI) OpenGL scenegraph. So set all the states that are // important to us. + //! [3] f->glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); f->glEnable(GL_BLEND); @@ -170,8 +176,10 @@ void OpenGLRenderNode::render(const RenderState *state) } f->glDrawArrays(GL_TRIANGLES, 0, 3); + //! [3] } +//! [4] QSGRenderNode::StateFlags OpenGLRenderNode::changedStates() const { return BlendState | ScissorState | StencilState; @@ -186,5 +194,6 @@ QRectF OpenGLRenderNode::rect() const { return QRect(0, 0, m_item->width(), m_item->height()); } +//! [4] #endif // opengl diff --git a/examples/quick/scenegraph/rendernode/openglrenderer.h b/examples/quick/scenegraph/rendernode/openglrenderer.h index ac640405c5..8d2d3caad1 100644 --- a/examples/quick/scenegraph/rendernode/openglrenderer.h +++ b/examples/quick/scenegraph/rendernode/openglrenderer.h @@ -63,6 +63,7 @@ class QOpenGLBuffer; QT_END_NAMESPACE +//! [1] class OpenGLRenderNode : public QSGRenderNode { public: @@ -74,6 +75,7 @@ public: StateFlags changedStates() const override; RenderingFlags flags() const override; QRectF rect() const override; +//! [1] private: void init(); |