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 | |
12 | QT_BEGIN_NAMESPACE |
13 | |
14 | using namespace Qt3DCore; |
15 | |
16 | namespace Qt3DRender { |
17 | |
18 | QRenderPassPrivate::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 | */ |
174 | QRenderPass::QRenderPass(QNode *parent) |
175 | : QNode(*new QRenderPassPrivate, parent) |
176 | { |
177 | } |
178 | |
179 | /*! \internal */ |
180 | QRenderPass::~QRenderPass() |
181 | { |
182 | } |
183 | |
184 | /*! \internal */ |
185 | QRenderPass::QRenderPass(QRenderPassPrivate &dd, QNode *parent) |
186 | : QNode(dd, parent) |
187 | { |
188 | } |
189 | |
190 | void 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 | |
215 | QShaderProgram *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 | */ |
224 | void 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 | */ |
248 | void 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 | */ |
263 | QList<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 | */ |
277 | void 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 | */ |
297 | void 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 | */ |
312 | QList<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 | */ |
321 | void 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 | */ |
345 | void 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 | */ |
359 | ParameterList QRenderPass::parameters() const |
360 | { |
361 | Q_D(const QRenderPass); |
362 | return d->m_parameters; |
363 | } |
364 | |
365 | } // namespace Qt3DRender |
366 | |
367 | QT_END_NAMESPACE |
368 | |
369 | #include "moc_qrenderpass.cpp" |
370 | |