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 | |
9 | QT_BEGIN_NAMESPACE |
10 | |
11 | using namespace Qt3DCore; |
12 | |
13 | namespace Qt3DRender { |
14 | |
15 | QTechniquePrivate::QTechniquePrivate() |
16 | : QNodePrivate() |
17 | { |
18 | } |
19 | |
20 | QTechniquePrivate::~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 | |
179 | QTechnique::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 */ |
187 | QTechnique::~QTechnique() |
188 | { |
189 | } |
190 | |
191 | /*! \internal */ |
192 | QTechnique::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 */ |
200 | void QTechniquePrivate::_q_graphicsApiFilterChanged() |
201 | { |
202 | update(); |
203 | } |
204 | |
205 | /*! |
206 | Add \a filterKey to the Qt3DRender::QTechnique local filter keys. |
207 | */ |
208 | void 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 | */ |
232 | void 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 | */ |
247 | QList<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 | */ |
256 | void 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 | */ |
280 | void 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 | */ |
294 | void 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 | */ |
318 | void 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 | */ |
332 | QList<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 | */ |
341 | QList<QParameter *> QTechnique::parameters() const |
342 | { |
343 | Q_D(const QTechnique); |
344 | return d->m_parameters; |
345 | } |
346 | |
347 | QGraphicsApiFilter *QTechnique::graphicsApiFilter() |
348 | { |
349 | Q_D(QTechnique); |
350 | return &d->m_graphicsApiFilter; |
351 | } |
352 | |
353 | const QGraphicsApiFilter *QTechnique::graphicsApiFilter() const |
354 | { |
355 | Q_D(const QTechnique); |
356 | return &d->m_graphicsApiFilter; |
357 | } |
358 | |
359 | } // of namespace Qt3DRender |
360 | |
361 | QT_END_NAMESPACE |
362 | |
363 | #include "moc_qtechnique.cpp" |
364 | |