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 "qmaterial.h"
5#include "qmaterial_p.h"
6#include "qtexture.h"
7#include "qeffect.h"
8#include <Qt3DRender/private/renderlogging_p.h>
9#include "qparameter.h"
10
11/*!
12 \qmltype Material
13 \instantiates Qt3DRender::QMaterial
14 \inqmlmodule Qt3D.Render
15 \brief Non-creatable abstract base for materials.
16 \since 5.5
17
18 Material provides a way to specify the rendering of an \l{Qt3D.Core::Entity}{entity}.
19 Any aspect can define its own subtype of Material so that a
20 Material can be used to describe a visual element; for example, the way
21 sound should reflect off an element, the temperature of a surface,
22 and so on.
23
24 In itself, a Material doesn't do anything. It's only when it references an
25 Effect node that a Material becomes useful.
26
27 In practice, it often happens that a single Effect is being referenced by
28 several Material components. This allows to only create the effect,
29 techniques, passes and shaders once while allowing to specify the material
30 by adding Parameter instances.
31
32 A Parameter defined on a Material overrides parameter (of the same
33 name) defined in a Effect, Technique and RenderPass, but are overridden by parameters in
34 RenderPassFilter and TechniqueFilter.
35
36 \code
37 Effect {
38 id: effect
39
40 techniques: [
41 Technique {
42 id: gl3Technique
43 graphicsApiFilter {
44 api: GraphicsApiFilter.OpenGL
45 profile: GraphicsApiFilter.CoreProfile
46 majorVersion: 3
47 minorVersion: 1
48 }
49 renderPasses: [
50 RenderPass {
51 id: gl3Pass
52 shaderProgram: ShaderProgram {
53 ...
54 }
55 }
56 ]
57 }
58 ]
59 }
60
61 Material {
62 id: material1
63 parameters: [
64 Parameter { name: "color"; value: "green" }
65 ]
66 }
67
68 Material {
69 id: material2
70 parameters: [
71 Parameter { name: "color"; value: "white" }
72 ]
73 }
74 \endcode
75
76 \sa Effect, Technique, Parameter
77*/
78
79/*!
80 \class Qt3DRender::QMaterial
81 \inmodule Qt3DRender
82 \inherits Qt3DCore::QComponent
83 \brief Provides an abstract class that should be the base of all material component classes
84 in a scene.
85 \since 5.5
86
87 QMaterial provides a way to specify the rendering of an \l{Qt3DCore::QEntity}{entity}.
88 Any aspect can define its own subclass of QMaterial so that a
89 Material can be used to describe a visual element; for example, the way
90 sound should reflect off an element, the temperature of a surface,
91 and so on.
92
93 In itself, a QMaterial doesn't do anything. It's only when it references a
94 QEffect node that a QMaterial becomes useful.
95
96 In practice, it often happens that a single QEffect is being referenced by
97 several QMaterial components. This allows to only create the effect,
98 techniques, passes and shaders once while allowing to specify the material
99 by adding QParameter instances.
100
101 A QParameter defined on a QMaterial overrides parameter (of the same
102 name) defined in a QEffect, QTechnique and QRenderPass, but are overridden by parameter in
103 QRenderPassFilter and QTechniqueFilter.
104
105 \code
106 QMaterial *material1 = new QMaterial();
107 QMaterial *material2 = new QMaterial();
108
109 // Create effect, technique, render pass and shader
110 QEffect *effect = new QEffect();
111 QTechnique *gl3Technique = new QTechnique();
112 QRenderPass *gl3Pass = new QRenderPass();
113 QShaderProgram *glShader = new QShaderProgram();
114
115 // Set the shader on the render pass
116 gl3Pass->setShaderProgram(glShader);
117
118 // Add the pass to the technique
119 gl3Technique->addRenderPass(gl3Pass);
120
121 // Set the targeted GL version for the technique
122 gl3Technique->graphicsApiFilter()->setApi(QGraphicsApiFilter::OpenGL);
123 gl3Technique->graphicsApiFilter()->setMajorVersion(3);
124 gl3Technique->graphicsApiFilter()->setMinorVersion(1);
125 gl3Technique->graphicsApiFilter()->setProfile(QGraphicsApiFilter::CoreProfile);
126
127 // Add the technique to the effect
128 effect->addTechnique(gl3Technique);
129
130 // Set the effect on the materials
131 material1->setEffect(effect);
132 material2->setEffect(effect);
133
134 // Set different parameters on the materials
135 const QString parameterName = QStringLiteral("color");
136 material1->addParameter(new QParameter(parameterName, QColor::fromRgbF(0.0f, 1.0f, 0.0f, 1.0f);
137 material2->addParameter(new QParameter(parameterName, QColor::fromRgbF(1.0f, 1.0f, 1.0f, 1.0f);
138
139 \endcode
140
141 \sa QEffect, QTechnique, QParameter
142*/
143
144QT_BEGIN_NAMESPACE
145
146using namespace Qt3DCore;
147
148namespace Qt3DRender {
149
150QMaterialPrivate::QMaterialPrivate()
151 : QComponentPrivate()
152 , m_effect(nullptr)
153{
154}
155
156QMaterialPrivate::~QMaterialPrivate()
157{
158}
159
160QMaterial::QMaterial(QNode *parent)
161 : QComponent(*new QMaterialPrivate, parent)
162{
163}
164
165QMaterial::~QMaterial()
166{
167}
168
169/*! \internal */
170QMaterial::QMaterial(QMaterialPrivate &dd, QNode *parent)
171 : QComponent(dd, parent)
172{
173}
174
175/*!
176 \qmlproperty list<Parameter> Material::parameters
177
178 Holds the list of parameters used by the material.
179*/
180
181/*!
182 \qmlproperty Effect Material::effect
183
184 Specifies the effect to be used with the material.
185*/
186/*!
187 \property QMaterial::effect
188
189 Specifies the effect to be used with the material.
190 */
191void QMaterial::setEffect(QEffect *effect)
192{
193 Q_D(QMaterial);
194 if (effect != d->m_effect) {
195
196 if (d->m_effect)
197 d->unregisterDestructionHelper(node: d->m_effect);
198
199 // We need to add it as a child of the current node if it has been declared inline
200 // Or not previously added as a child of the current node so that
201 // 1) The backend gets notified about it's creation
202 // 2) When the current node is destroyed, it gets destroyed as well
203 if (effect && !effect->parent())
204 effect->setParent(this);
205 d->m_effect = effect;
206
207 // Ensures proper bookkeeping
208 if (d->m_effect)
209 d->registerDestructionHelper(node: d->m_effect, func: &QMaterial::setEffect, d->m_effect);
210
211 emit effectChanged(effect);
212 }
213}
214
215QEffect *QMaterial::effect() const
216{
217 Q_D(const QMaterial);
218 return d->m_effect;
219}
220
221/*!
222 * Add a \a parameter to the material's parameters.
223 */
224void QMaterial::addParameter(QParameter *parameter)
225{
226 Q_ASSERT(parameter);
227 Q_D(QMaterial);
228 if (!d->m_parameters.contains(t: parameter)) {
229 d->m_parameters.append(t: parameter);
230
231 // Ensures proper bookkeeping
232 d->registerDestructionHelper(node: parameter, func: &QMaterial::removeParameter, d->m_parameters);
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 (!parameter->parent())
239 parameter->setParent(this);
240
241 d->update();
242 }
243}
244
245/*!
246 * Remove a \a parameter from the material's parameters.
247 */
248void QMaterial::removeParameter(QParameter *parameter)
249{
250 Q_ASSERT(parameter);
251 Q_D(QMaterial);
252 if (!d->m_parameters.removeOne(t: parameter))
253 return;
254 d->update();
255}
256
257/*!
258 * Returns a vector of the material's current parameters
259 */
260QList<QParameter *> QMaterial::parameters() const
261{
262 Q_D(const QMaterial);
263 return d->m_parameters;
264}
265
266} // namespace Qt3DRender
267
268QT_END_NAMESPACE
269
270#include "moc_qmaterial.cpp"
271

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