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

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