Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qquick3dsimplequadrenderpass.cpp
Go to the documentation of this file.
1// Copyright (C) 2025 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
5
7
8#include <QtQuick3D/private/qquick3dobject_p.h>
9
10#include <QtQuick3DRuntimeRender/private/qssglayerrenderdata_p.h>
11#include <QtQuick3DRuntimeRender/private/qssgrenderer_p.h>
12#include <QtQuick3DRuntimeRender/private/qssgrhiquadrenderer_p.h>
13#include <QtQuick3DRuntimeRender/private/qssgrendershadercache_p.h>
14#include <QtQuick3DRuntimeRender/private/qssgrendererimplshaders_p.h>
15#include <QtQuick3DRuntimeRender/private/qssgrendercommands_p.h>
16
17#include <QtQuick3DRuntimeRender/private/qssgrenderbuffermanager_p.h>
18
19#include <ssg/qssgrendercontextcore.h>
20#include <ssg/qssgrenderextensions.h>
21
22#include <rhi/qrhi.h>
23
25
26/*!
27 \qmltype SimpleQuadRenderer
28 \nativetype QQuick3DSimpleQuadRenderer
29 \inqmlmodule QtQuick3D.Helpers
30 \inherits RenderExtension
31 \since 6.11
32 \brief Renders a full-screen textured quad to the main render target.
33
34 SimpleQuadRenderer is a \l RenderExtension that blits a \l Texture across
35 the entire screen. It runs at the \c PostColor stage in the \c Main render
36 mode, which means it executes after the scene has been drawn but before any
37 post-processing effects, and it writes directly into the \l View3D's main
38 render target, overwriting whatever was drawn by the scene.
39
40 The most common use case is building a fully custom rendering pipeline:
41 set \l {View3D::renderFormat}{View3D.renderFormat} to disable Qt Quick 3D's
42 built-in passes with \c {View3D.DisableInternalPasses}, render the scene
43 content into one or more \l RenderPass targets, and then use
44 SimpleQuadRenderer to composite the result back onto the screen.
45
46 \note SimpleQuadRenderer is automatically registered as an extension with the
47 scene — it does not need to be added to \l {View3D::extensions}{View3D.extensions}
48 manually.
49
50 \qml
51 import QtQuick3D
52 import QtQuick3D.Helpers
53
54 View3D {
55 // Disable the built-in render passes so we can provide our own output
56 renderFormat: View3D.DisableInternalPasses
57
58 // A custom offscreen pass that renders scene content
59 RenderPass {
60 id: mainColorPass
61 commands: [
62 RenderablesFilter { renderableTypes: RenderablesFilter.Opaque | RenderablesFilter.Transparent }
63 ]
64 }
65
66 // Blit the result of the custom pass to the screen
67 SimpleQuadRenderer {
68 texture: Texture {
69 textureProvider: RenderOutputProvider {
70 renderPass: mainColorPass
71 }
72 }
73 }
74 }
75 \endqml
76
77 \sa RenderOutputProvider, RenderPass, View3D
78*/
79
80/*!
81 \qmlproperty Texture SimpleQuadRenderer::texture
82 The texture to render across the full-screen quad. This can be any \l Texture,
83 including one whose \l {Texture::textureProvider}{textureProvider} is set to a
84 \l RenderOutputProvider to display output from a \l RenderPass or one of Qt Quick 3D's
85 built-in passes (such as the depth texture or AO texture).
86*/
87
89{
90 static constexpr FlagT flags = FlagT(Flags::HasGraphicsResources) | FlagT(QSSGRenderGraphObjectUtils::InternalFlags::AutoRegisterExtension);
91public:
96
97 virtual bool prepareData(QSSGFrameData &data) final
98 {
99 bool wasDirty = true;
100
101 if (image)
102 renderImage = data.contextInterface()->bufferManager()->loadRenderImage(image);
103 else
104 renderImage = QSSGRenderImageTexture();
105
106 wasDirty = (renderImage.m_texture != nullptr);
107
108 return wasDirty;
109 }
110
111 virtual void prepareRender(QSSGFrameData &data) final
112 {
113 if (renderImage.m_texture) {
114 const auto &rhiCtx = data.contextInterface()->rhiContext();
115 const auto &renderer = data.contextInterface()->renderer();
116 QRhiResourceUpdateBatch *rub = rhiCtx->rhi()->nextResourceUpdateBatch();
117 renderer->rhiQuadRenderer()->prepareQuad(rhiCtx.get(), rub);
118 }
119 }
120
121 virtual void render(QSSGFrameData &data) final
122 {
123 if (renderImage.m_texture) {
124 const auto &rhiCtx = data.contextInterface()->rhiContext();
125 const auto &renderer = data.contextInterface()->renderer();
126 const auto &shaderCache = data.contextInterface()->shaderCache();
127
128 QSSGRhiGraphicsPipelineState ps = data.getPipelineState();
129 QRhiCommandBuffer *cb = rhiCtx->commandBuffer();
130 cb->debugMarkBegin(QByteArrayLiteral("QtQuick3D Blit Pass"));
131
132 const auto tonemapMode = QSSGLayerRenderData::getCurrent(data)->layer.tonemapMode;
133 const auto &shaderPipeline = shaderCache->getBuiltInRhiShaders().getRhiSimpleQuadShader(ps.viewCount, tonemapMode);
134
135 QRhiSampler *sampler = rhiCtx->sampler({ QRhiSampler::Linear, QRhiSampler::Linear, QRhiSampler::None,
136 QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge });
137 QSSGRhiShaderResourceBindingList bindings;
138 bindings.addTexture(0, QRhiShaderResourceBinding::FragmentStage, renderImage.m_texture, sampler);
139 QSSGRhiContextPrivate *rhiCtxD = QSSGRhiContextPrivate::get(rhiCtx.get());
140 QRhiShaderResourceBindings *srb = rhiCtxD->srb(bindings);
141
142 QSSGRhiGraphicsPipelineStatePrivate::setShaderPipeline(ps, shaderPipeline.get());
143 renderer->rhiQuadRenderer()->recordRenderQuad(rhiCtx.get(), &ps, srb, rhiCtx->mainRenderPassDescriptor(), QSSGRhiQuadRenderer::UvCoords | QSSGRhiQuadRenderer::PremulBlend);
144 cb->debugMarkEnd();
145 }
146 }
147 virtual void resetForFrame() final {}
148 virtual RenderMode mode() const final { return RenderMode::Main; }
149 virtual RenderStage stage() const final { return RenderStage::PostColor; }
150
155};
156
157
158QQuick3DSimpleQuadRenderer::QQuick3DSimpleQuadRenderer() { }
159
160QSSGRenderGraphObject *QQuick3DSimpleQuadRenderer::updateSpatialNode(QSSGRenderGraphObject *node)
161{
162 if (!node)
164
165 QSSGRenderSimpleQuadRenderer *blitPass = static_cast<QSSGRenderSimpleQuadRenderer *>(node);
166 if (m_source)
167 blitPass->image = m_source->getRenderImage();
168 else
169 blitPass->image = nullptr;
170
171 return node;
172}
173
174void QQuick3DSimpleQuadRenderer::itemChange(QQuick3DObject::ItemChange change, const QQuick3DObject::ItemChangeData &value)
175{
176 if (change == QQuick3DObject::ItemSceneChange)
177 updateSceneManager(value.sceneManager);
178}
179
180QQuick3DTexture *QQuick3DSimpleQuadRenderer::texture() const
181{
182 return m_source;
183}
184
185void QQuick3DSimpleQuadRenderer::setTexture(QQuick3DTexture *newSource)
186{
187 if (m_source == newSource)
188 return;
189
190 QQuick3DObjectPrivate::attachWatcher(this, &QQuick3DSimpleQuadRenderer::setTexture, newSource, m_source);
191
192 m_source = newSource;
193 emit textureChanged();
194
195 update();
196}
197
198void QQuick3DSimpleQuadRenderer::updateSceneManager(QQuick3DSceneManager *sceneManager)
199{
200 if (sceneManager)
201 QQuick3DObjectPrivate::refSceneManager(m_source, *sceneManager);
202 else
203 QQuick3DObjectPrivate::derefSceneManager(m_source);
204}
205
206QT_END_NAMESPACE
\qmlproperty Texture SimpleQuadRenderer::texture The texture to render across the full-screen quad.
virtual void render(QSSGFrameData &data) final
Record the render pass.
virtual void resetForFrame() final
Called each time a new frame starts.
virtual RenderStage stage() const final
virtual void prepareRender(QSSGFrameData &data) final
Prepare data for rendering.
virtual bool prepareData(QSSGFrameData &data) final
Called after scene data is collected, but before any render data or rendering in the current frame ha...
virtual RenderMode mode() const final
Combined button and popup list for selecting options.