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

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