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

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