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 "qparameter.h" |
5 | #include "qparameter_p.h" |
6 | #include <Qt3DRender/private/renderlogging_p.h> |
7 | #include <Qt3DRender/qtexture.h> |
8 | #include <QtCore/qiterable.h> |
9 | #include <QtCore/qsequentialiterable.h> |
10 | |
11 | /*! |
12 | \qmltype Parameter |
13 | \instantiates Qt3DRender::QParameter |
14 | \inqmlmodule Qt3D.Render |
15 | \brief Provides storage for a name and value pair. This maps to a shader uniform. |
16 | |
17 | A Parameter can be referenced by a RenderPass, Technique, Effect, Material, |
18 | TechniqueFilter, RenderPassFilter. At runtime, depending on which shader is |
19 | selected for a given step of the rendering, the value contained in a |
20 | Parameter will be converted and uploaded if the shader contains a uniform |
21 | with a name matching that of the Parameter. |
22 | |
23 | \code |
24 | Parameter { |
25 | name: "diffuseColor" |
26 | value: "blue" |
27 | } |
28 | |
29 | // Works with the following GLSL uniform shader declarations |
30 | // uniform vec4 diffuseColor; |
31 | // uniform vec3 diffuseColor; |
32 | // uniform vec2 diffuseColor; |
33 | // uniform float diffuseColor; |
34 | \endcode |
35 | |
36 | \note some care must be taken to ensure the value wrapped by a Parameter |
37 | can actually be converted to what the real uniform expect. Giving a value |
38 | stored as an int where the actual shader uniform is of type float could |
39 | result in undefined behaviors. |
40 | |
41 | \note when the targeted uniform is an array, the name should be the name |
42 | of the uniform with [0] appended to it. |
43 | |
44 | \note Parameter node can not be disabled. |
45 | |
46 | \code |
47 | Parameter { |
48 | name: "diffuseValues[0]" |
49 | value: [0.0, 1.0. 2.0, 3.0, 4.0, 883.0, 1340.0, 1584.0] |
50 | } |
51 | |
52 | // Matching GLSL shader uniform declaration |
53 | // uniform float diffuseValues[8]; |
54 | \endcode |
55 | |
56 | When it comes to texture support, the Parameter value should be set to the |
57 | appropriate \l {Qt3DRender::QAbstractTexture}{texture} subclass that matches the sampler type of the shader |
58 | uniform. |
59 | |
60 | \code |
61 | Parameter { |
62 | name: "diffuseTexture" |
63 | value: Texture2D { ... } |
64 | } |
65 | |
66 | // Works with the following GLSL uniform shader declaration |
67 | // uniform sampler2D diffuseTexture |
68 | \endcode |
69 | |
70 | \sa Qt3DRender::QAbstractTexture |
71 | */ |
72 | |
73 | /*! |
74 | \class Qt3DRender::QParameter |
75 | \inheaderfile Qt3DRender/QParameter |
76 | \inmodule Qt3DRender |
77 | \brief Provides storage for a name and value pair. This maps to a shader uniform. |
78 | |
79 | A QParameter can be referenced by a QRenderPass, QTechnique, QEffect, QMaterial, |
80 | QTechniqueFilter, QRenderPassFilter. At runtime, depending on which shader is |
81 | selected for a given step of the rendering, the value contained in a |
82 | QParameter will be converted and uploaded if the shader contains a uniform |
83 | with a name matching that of the QParameter. |
84 | |
85 | \code |
86 | QParameter *param = new QParameter(); |
87 | param->setName(QStringLiteral("diffuseColor")); |
88 | param->setValue(QColor::fromRgbF(0.0f, 0.0f, 1.0f, 1.0f)); |
89 | |
90 | // Alternatively you can create and set a QParameter this way |
91 | QParameter *param2 = new QParameter(QStringLiteral("diffuseColor"), QColor::fromRgbF(0.0f, 0.0f, 1.0f, 1.0f)); |
92 | |
93 | // Such QParameters will work with the following GLSL uniform shader declarations |
94 | // uniform vec4 diffuseColor; |
95 | // uniform vec3 diffuseColor; |
96 | // uniform vec2 diffuseColor; |
97 | // uniform float diffuseColor; |
98 | \endcode |
99 | |
100 | \note some care must be taken to ensure the value wrapped by a QParameter |
101 | can actually be converted to what the real uniform expect. Giving a value |
102 | stored as an int where the actual shader uniform is of type float could |
103 | result in undefined behaviors. |
104 | |
105 | \note when the targeted uniform is an array, the name should be the name |
106 | of the uniform with [0] appended to it. |
107 | |
108 | \note QParameter node can not be disabled. |
109 | |
110 | \code |
111 | QParameter *param = new QParameter(); |
112 | QVariantList values = QVariantList() << 0.0f << 1.0f << 2.0f << 3.0f << 4.0f << 883.0f << 1340.0f << 1584.0f; |
113 | |
114 | param->setName(QStringLiteral("diffuseValues[0]")); |
115 | param->setValue(values); |
116 | |
117 | // Matching GLSL shader uniform declaration |
118 | // uniform float diffuseValues[8]; |
119 | \endcode |
120 | |
121 | When it comes to texture support, the QParameter value should be set to the |
122 | appropriate QAbstractTexture subclass that matches the sampler type of the shader |
123 | uniform. |
124 | |
125 | \code |
126 | QTexture2D *texture = new QTexture2D(); |
127 | ... |
128 | QParameter *param = new QParameter(); |
129 | param->setName(QStringLiteral("diffuseTexture")); |
130 | param->setValue(QVariant::fromValue(texture)); |
131 | |
132 | // Works with the following GLSL uniform shader declaration |
133 | // uniform sampler2D diffuseTexture |
134 | \endcode |
135 | |
136 | \sa QAbstractTexture |
137 | */ |
138 | |
139 | QT_BEGIN_NAMESPACE |
140 | |
141 | using namespace Qt3DCore; |
142 | |
143 | namespace Qt3DRender { |
144 | |
145 | QParameterPrivate::QParameterPrivate() |
146 | : QNodePrivate() |
147 | { |
148 | } |
149 | |
150 | namespace { |
151 | |
152 | /*! \internal */ |
153 | inline QVariant toBackendValue(const QVariant &v) |
154 | { |
155 | if (auto nodeValue = v.value<Qt3DCore::QNode*>()) |
156 | return QVariant::fromValue(value: nodeValue->id()); |
157 | return v; |
158 | } |
159 | |
160 | } // anonymous |
161 | |
162 | void QParameterPrivate::setValue(const QVariant &v) |
163 | { |
164 | if (v.metaType().id() == QMetaType::QVariantList) { |
165 | QSequentialIterable iterable = v.value<QSequentialIterable>(); |
166 | QVariantList variants; |
167 | variants.reserve(asize: iterable.size()); |
168 | for (const auto &v : iterable) |
169 | variants.append(t: toBackendValue(v)); |
170 | m_backendValue = variants; |
171 | } else { |
172 | m_backendValue = toBackendValue(v); |
173 | } |
174 | m_value = v; |
175 | } |
176 | |
177 | /*! \internal */ |
178 | QParameter::QParameter(QParameterPrivate &dd, QNode *parent) |
179 | : QNode(dd, parent) |
180 | { |
181 | } |
182 | |
183 | /*! |
184 | \fn Qt3DRender::QParameter::QParameter(Qt3DCore::QNode *parent) |
185 | Constructs a new QParameter with the specified \a parent. |
186 | */ |
187 | QParameter::QParameter(QNode *parent) |
188 | : QNode(*new QParameterPrivate, parent) |
189 | { |
190 | } |
191 | |
192 | /*! |
193 | \fn Qt3DRender::QParameter::QParameter(const QString &name, const QVariant &value, QNode *parent) |
194 | Constructs a new QParameter with the specified \a parent \a name and \a value. |
195 | */ |
196 | QParameter::QParameter(const QString &name, const QVariant &value, QNode *parent) |
197 | : QNode(*new QParameterPrivate, parent) |
198 | { |
199 | Q_D(QParameter); |
200 | d->m_name = name; |
201 | setValue(value); |
202 | } |
203 | |
204 | /*! |
205 | \fn Qt3DRender::QParameter::QParameter(const QString &name, QAbstractTexture *texture, QNode *parent) |
206 | Constructs a new QParameter with the specified \a parent \a name and takes its value from \a texture. |
207 | */ |
208 | QParameter::QParameter(const QString &name, QAbstractTexture *texture, QNode *parent) |
209 | : QNode(*new QParameterPrivate, parent) |
210 | { |
211 | Q_D(QParameter); |
212 | d->m_name = name; |
213 | setValue(QVariant::fromValue(value: texture)); |
214 | } |
215 | |
216 | /*! \internal */ |
217 | QParameter::~QParameter() |
218 | { |
219 | } |
220 | |
221 | /*! |
222 | \qmlproperty QString Qt3D.Render::Parameter::name |
223 | Specifies the name of the parameter |
224 | */ |
225 | |
226 | /*! |
227 | \property Qt3DRender::QParameter::name |
228 | Specifies the name of the parameter |
229 | */ |
230 | void QParameter::setName(const QString &name) |
231 | { |
232 | Q_D(QParameter); |
233 | if (d->m_name != name) { |
234 | d->m_name = name; |
235 | emit nameChanged(name); |
236 | } |
237 | } |
238 | |
239 | QString QParameter::name() const |
240 | { |
241 | Q_D(const QParameter); |
242 | return d->m_name; |
243 | } |
244 | |
245 | /*! |
246 | \qmlproperty QVariant Qt3D.Render::Parameter::value |
247 | Specifies the value of the parameter |
248 | */ |
249 | |
250 | /*! |
251 | \property Qt3DRender::QParameter::value |
252 | Specifies the value of the parameter |
253 | */ |
254 | void QParameter::setValue(const QVariant &dv) |
255 | { |
256 | Q_D(QParameter); |
257 | if (d->m_value != dv) { |
258 | |
259 | QNode *oldNodeValue = d->m_value.value<QNode *>(); |
260 | if (oldNodeValue != nullptr) |
261 | d->unregisterDestructionHelper(node: oldNodeValue); |
262 | |
263 | // In case node values are declared inline |
264 | QNode *nodeValue = dv.value<QNode *>(); |
265 | if (nodeValue != nullptr && !nodeValue->parent()) |
266 | nodeValue->setParent(this); |
267 | |
268 | d->setValue(dv); |
269 | |
270 | // Ensures proper bookkeeping |
271 | if (nodeValue != nullptr) |
272 | d->registerDestructionHelper(node: nodeValue, func: &QParameter::setValue, nodeValue, resetValue: QVariant()); |
273 | |
274 | emit valueChanged(value: dv); |
275 | } |
276 | } |
277 | |
278 | QVariant QParameter::value() const |
279 | { |
280 | Q_D(const QParameter); |
281 | return d->m_value; |
282 | } |
283 | |
284 | } // namespace Qt3DRender |
285 | |
286 | QT_END_NAMESPACE |
287 | |
288 | #include "moc_qparameter.cpp" |
289 | |