1// Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
2// Copyright (C) 2016 The Qt Company Ltd and/or its subsidiary(-ies).
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4
5#include "qrenderpass.h"
6#include "qrenderpass_p.h"
7#include "qparameter.h"
8#include "qfilterkey.h"
9#include "qrenderstate.h"
10#include <Qt3DCore/private/qnode_p.h>
11
12QT_BEGIN_NAMESPACE
13
14using namespace Qt3DCore;
15
16namespace Qt3DRender {
17
18QRenderPassPrivate::QRenderPassPrivate()
19 : QNodePrivate()
20 , m_shader(nullptr)
21{
22}
23/*!
24 \qmltype RenderPass
25 \instantiates Qt3DRender::QRenderPass
26 \inqmlmodule Qt3D.Render
27 \inherits Node
28 \since 5.7
29 \brief Encapsulates a Render Pass.
30
31 A RenderPass specifies a single rendering pass - an instance of shader program
32 execution - used by Technique. A Render pass consists of a ShaderProgram and
33 a list of FilterKey objects, a list of RenderState objects and a list
34 of \l Parameter objects.
35
36 RenderPass executes the ShaderProgram using the given RenderState and
37 Parameter nodes when at least one of FilterKey nodes being referenced
38 matches any of the FilterKey nodes in RenderPassFilter or when no
39 RenderPassFilter is present in the FrameGraph.
40
41 If the RenderPass defines a Parameter, it will be overridden by a Parameter
42 with the same name if it exists in any of the Technique, Effect, Material,
43 TechniqueFilter, RenderPassFilter associated with the pass at runtime. This
44 still can be useful to define sane default values.
45
46 At render time, for each leaf node of the FrameGraph a base render state is
47 recorded by accumulating states defined by all RenderStateSet nodes in the
48 FrameGraph branch. Each RenderPass can overload this base render state by
49 specifying its own RenderState nodes.
50
51 \qml
52 Technique {
53 filterKeys: [
54 FilterKey { name: "renderingStyle"; value: "forward" }
55 ]
56 graphicsApiFilter: {
57 api: GraphicsApiFilter.OpenGL
58 profile: GraphicsApiFilter.CoreProfile
59 majorVersion: 3
60 minorVersion: 1
61 }
62 renderPasses: [
63 RenderPass {
64 id: pass
65 shaderProgram: ShaderProgram {
66 // ...
67 }
68 parameters: [
69 Parameter { name: "color"; value: "red" }
70 ]
71 renderStates: [
72 DepthTest {}
73 ]
74 }
75 ]
76 }
77 \endqml
78
79 \sa RenderPassFilter, FilterKey, Parameter, RenderState, Effect, Technique
80 */
81
82/*!
83 \class Qt3DRender::QRenderPass
84 \inmodule Qt3DRender
85 \since 5.7
86 \brief Encapsulates a Render Pass.
87
88 A Qt3DRender::QRenderPass specifies a single rendering pass - an instance of shader
89 program execution - used by Qt3DRender::QTechnique. Render pass consists
90 of a Qt3DRender::QShaderProgram and a list of Qt3DRender::QFilterKey objects,
91 a list of Qt3DRender::QRenderState objects and a list of Qt3DRender::QParameter objects.
92
93 QRenderPass executes the QShaderProgram using the given QRenderState and
94 QParameter nodes when at least one of QFilterKey nodes being referenced
95 matches any of the QFilterKey nodes in QRenderPassFilter or when no
96 QFilterKey nodes are specified and no QRenderPassFilter is present in the
97 FrameGraph.
98
99 If the QRenderPass defines a QParameter, it will be overridden by a
100 QParameter with the same name if it exists in any of the QTechnique,
101 QEffect, QMaterial, QTechniqueFilter, QRenderPassFilter associated with the
102 pass at runtime. This still can be useful to define sane default values.
103
104 At render time, for each leaf node of the FrameGraph a base render state is
105 recorded by accumulating states defined by all QRenderStateSet nodes in the
106 FrameGraph branch. Each QRenderPass can overload this base render state by
107 specifying its own QRenderState nodes.
108
109 \code
110 // Create the render passes
111 QRenderPass *pass = new QRenderPass();
112
113 // Create shader program
114 QShaderProgram *glShader = new QShaderProgram();
115
116 // Set the shader on the render pass
117 pass->setShaderProgram(glShader);
118
119 // Create a FilterKey
120 QFilterKey *filterKey = new QFilterKey();
121 filterKey->setName(QStringLiteral("name"));
122 fitlerKey->setValue(QStringLiteral("zFillPass"));
123
124 // Add the FilterKey to the pass
125 pass->addFilterKey(filterKey);
126
127 // Create a QParameter
128 QParameter *colorParameter = new QParameter(QStringLiteral("color"), QColor::fromRgbF(0.0f, 0.0f, 1.0f, 1.0f));
129
130 // Add parameter to pass
131 pass->addParameter(colorParameter);
132
133 // Create a QRenderState
134 QDepthTest *depthTest = new QDepthTest();
135
136 // Add the render state to the pass
137 pass->addRenderState(depthTest);
138 \endcode
139
140 \sa QRenderPassFilter, QFilterKey, QParameter, QRenderState, QEffect, QTechnique
141 */
142/*!
143 \typedef ParameterList
144 \relates Qt3DRender::QRenderPass
145
146 A list of Qt3DRender::QParameter parameters.
147*/
148/*!
149 \qmlproperty ShaderProgram Qt3D.Render::RenderPass::shaderProgram
150 Holds the shader program to be used for this render pass.
151*/
152/*!
153 \qmlproperty list<FilterKey> Qt3D.Render::RenderPass::filterKeys
154 Holds the filter keys enabling the use of this render pass.
155*/
156/*!
157 \qmlproperty list<RenderState> Qt3D.Render::RenderPass::renderStates
158 Holds the render states used by the render pass.
159*/
160/*!
161 \qmlproperty list<Parameter> Qt3D.Render::RenderPass::parameters
162 Holds the shader parameter values used by the render pass.
163*/
164
165/*!
166 \property Qt3DRender::QRenderPass::shaderProgram
167 Specifies the shader program to be used for this render pass.
168 */
169
170/*!
171 \fn Qt3DRender::QRenderPass::QRenderPass(Qt3DCore::QNode *parent)
172 Constructs a new QRenderPass with the specified \a parent.
173 */
174QRenderPass::QRenderPass(QNode *parent)
175 : QNode(*new QRenderPassPrivate, parent)
176{
177}
178
179/*! \internal */
180QRenderPass::~QRenderPass()
181{
182}
183
184/*! \internal */
185QRenderPass::QRenderPass(QRenderPassPrivate &dd, QNode *parent)
186 : QNode(dd, parent)
187{
188}
189
190void QRenderPass::setShaderProgram(QShaderProgram *shaderProgram)
191{
192 Q_D(QRenderPass);
193 if (d->m_shader != shaderProgram) {
194
195 if (d->m_shader)
196 d->unregisterDestructionHelper(node: d->m_shader);
197
198 // We need to add it as a child of the current node if it has been declared inline
199 // Or not previously added as a child of the current node so that
200 // 1) The backend gets notified about it's creation
201 // 2) When the current node is destroyed, it gets destroyed as well
202 if (shaderProgram && !shaderProgram->parent())
203 shaderProgram->setParent(this);
204
205 d->m_shader = shaderProgram;
206
207 // Ensures proper bookkeeping
208 if (d->m_shader)
209 d->registerDestructionHelper(node: d->m_shader, func: &QRenderPass::setShaderProgram, d->m_shader);
210
211 emit shaderProgramChanged(shaderProgram);
212 }
213}
214
215QShaderProgram *QRenderPass::shaderProgram() const
216{
217 Q_D(const QRenderPass);
218 return d->m_shader;
219}
220
221/*!
222 Adds \a filterKey to the Qt3DRender::QRenderPass local filter keys.
223 */
224void QRenderPass::addFilterKey(QFilterKey *filterKey)
225{
226 Q_ASSERT(filterKey);
227 Q_D(QRenderPass);
228 if (!d->m_filterKeyList.contains(t: filterKey)) {
229 d->m_filterKeyList.append(t: filterKey);
230
231 // Ensures proper bookkeeping
232 d->registerDestructionHelper(node: filterKey, func: &QRenderPass::removeFilterKey, d->m_filterKeyList);
233
234 // We need to add it as a child of the current node if it has been declared inline
235 // Or not previously added as a child of the current node so that
236 // 1) The backend gets notified about it's creation
237 // 2) When the current node is destroyed, it gets destroyed as well
238 if (!filterKey->parent())
239 filterKey->setParent(this);
240
241 d->update();
242 }
243}
244
245/*!
246 Removes \a filterKey from the Qt3DRender::QRenderPass local filter keys.
247 */
248void QRenderPass::removeFilterKey(QFilterKey *filterKey)
249{
250 Q_ASSERT(filterKey);
251 Q_D(QRenderPass);
252 if (!d->m_filterKeyList.removeOne(t: filterKey))
253 return;
254 d->update();
255 // Remove bookkeeping connection
256 d->unregisterDestructionHelper(node: filterKey);
257}
258
259/*!
260 Returns the list of Qt3DRender::QFilterKey key objects making up the filter keys
261 of the Qt3DRender::QRenderPass.
262 */
263QList<QFilterKey *> QRenderPass::filterKeys() const
264{
265 Q_D(const QRenderPass);
266 return d->m_filterKeyList;
267}
268
269/*!
270 Adds a render \a state to the rendering pass. That implies that
271 when the pass is executed at render time, the globally set render state will
272 be modified by the states defined locally by the Qt3DRender::QRenderPass.
273
274 \note not defining any Qt3DRender::QRenderState in a pass will result in the pass using
275 the globally set render state for a given FrameGraph branch execution path.
276 */
277void QRenderPass::addRenderState(QRenderState *state)
278{
279 Q_ASSERT(state);
280 Q_D(QRenderPass);
281 if (!d->m_renderStates.contains(t: state)) {
282 d->m_renderStates.append(t: state);
283
284 // Ensures proper bookkeeping
285 d->registerDestructionHelper(node: state, func: &QRenderPass::removeRenderState, d->m_renderStates);
286
287 if (!state->parent())
288 state->setParent(this);
289
290 d->update();
291 }
292}
293
294/*!
295 Removes \a state from the Qt3DRender::QRenderPass local render state.
296 */
297void QRenderPass::removeRenderState(QRenderState *state)
298{
299 Q_ASSERT(state);
300 Q_D(QRenderPass);
301 if (!d->m_renderStates.removeOne(t: state))
302 return;
303 d->update();
304 // Remove bookkeeping connection
305 d->unregisterDestructionHelper(node: state);
306}
307
308/*!
309 Returns the list of Qt3DRender::QRenderState state objects making up the render
310 state of the Qt3DRender::QRenderPass.
311 */
312QList<QRenderState *> QRenderPass::renderStates() const
313{
314 Q_D(const QRenderPass);
315 return d->m_renderStates;
316}
317
318/*!
319 Add \a parameter to the render pass' parameters.
320 */
321void QRenderPass::addParameter(QParameter *parameter)
322{
323 Q_ASSERT(parameter);
324 Q_D(QRenderPass);
325 if (!d->m_parameters.contains(t: parameter)) {
326 d->m_parameters.append(t: parameter);
327
328 // Ensures proper bookkeeping
329 d->registerDestructionHelper(node: parameter, func: &QRenderPass::removeParameter, d->m_parameters);
330
331 // We need to add it as a child of the current node if it has been declared inline
332 // Or not previously added as a child of the current node so that
333 // 1) The backend gets notified about it's creation
334 // 2) When the current node is destroyed, the child parameters get destroyed as well
335 if (!parameter->parent())
336 parameter->setParent(this);
337
338 d->update();
339 }
340}
341
342/*!
343 Remove \a parameter from the render pass' parameters.
344 */
345void QRenderPass::removeParameter(QParameter *parameter)
346{
347 Q_ASSERT(parameter);
348 Q_D(QRenderPass);
349 if (!d->m_parameters.removeOne(t: parameter))
350 return;
351 d->update();
352 // Remove bookkeeping connection
353 d->unregisterDestructionHelper(node: parameter);
354}
355
356/*!
357 Returns a vector of the render pass' current parameters
358 */
359ParameterList QRenderPass::parameters() const
360{
361 Q_D(const QRenderPass);
362 return d->m_parameters;
363}
364
365} // namespace Qt3DRender
366
367QT_END_NAMESPACE
368
369#include "moc_qrenderpass.cpp"
370

source code of qt3d/src/render/materialsystem/qrenderpass.cpp