1 /****************************************************************************
2 **
3 ** Copyright (C) 2020 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of Qt Quick 3D.
7 **
8 ** $QT_BEGIN_LICENSE:GPL$
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 General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU
19 ** General Public License version 3 or (at your option) any later version
20 ** approved by the KDE Free Qt Foundation. The licenses are as published by
21 ** the Free Software Foundation and appearing in the file LICENSE.GPL3
22 ** included in the packaging of this file. Please review the following
23 ** information to ensure the GNU General Public License requirements will
24 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
25 **
26 ** $QT_END_LICENSE$
27 **
28 ****************************************************************************/
29
30 #include "qquick3dshaderutils_p.h"
31
32 #include <QtCore/qfile.h>
33 #include <QtQml/qqml.h>
34 #include <QtQml/qqmlcontext.h>
35
36 #include <QtQuick3D/private/qquick3dmaterial_p.h>
37 #include <QtQuick3D/private/qquick3deffect_p.h>
38
39 QT_BEGIN_NAMESPACE
40
41 /*!
42 \qmltype Shader
43 \inherits Object
44 \inqmlmodule QtQuick3D
45 \brief Container component for defining shader code used by CustomMaterials and Effects.
46 */
47 /*!
48 \qmlproperty string Shader::shader
49 Specifies the name of the shader source file.
50 */
51 /*!
52 \qmlproperty enumeration Shader::stage
53 Specifies the shader stage. The default is \c Shader.Shared
54
55 \value Shader.Shared The shader can be shared among different stages
56 \value Shader.Vertex The shader is a vertex shader
57 \value Shader.Fragment The shader is a fragment shader
58 \value Shader.Geometry The shader is a geometry shader
59 \value Shader.Compute The shader is a compute shader
60 */
61
62 /*!
63 \qmltype ShaderInfo
64 \inherits Object
65 \inqmlmodule QtQuick3D
66 \brief Defines basic information about custom shader code for CustomMaterials.
67 */
68 /*!
69 \qmlproperty string ShaderInfo::version
70 Specifies the shader code version.
71 */
72 /*!
73 \qmlproperty string ShaderInfo::type
74 Specifies the shader code type.
75 */
76 /*!
77 \qmlproperty string ShaderInfo::shaderKey
78 Specifies the options used by the shader using the combination of shader key values.
79
80 \value ShaderInfo.Diffuse The shader uses diffuse lighting.
81 \value ShaderInfo.Specular The shader uses specular lighting.
82 \value ShaderInfo.Cutout The shader uses alpha cutout.
83 \value ShaderInfo.Refraction The shader uses refraction.
84 \value ShaderInfo.Transparent The shader uses transparency.
85 \value ShaderInfo.Displace The shader uses displacement mapping.
86 \value ShaderInfo.Transmissive The shader uses transmissiveness.
87 \value ShaderInfo.Glossy The shader is default glossy. This is a combination of \c ShaderInfo.Diffuse and
88 \c ShaderInfo.Specular.
89 */
90
91 /*!
92 \qmltype TextureInput
93 \inherits Object
94 \inqmlmodule QtQuick3D
95 \brief Defines a texture channel for a Custom Material or an Effect.
96 */
97 /*!
98 \qmlproperty Texture TextureInput::texture
99 Specifies the Texture to input.
100 */
101 /*!
102 \qmlproperty bool TextureInput::enabled
103 The property determines if this TextureInput is enabled.
104 */
105
106 /*!
107 \qmltype Pass
108 \inherits Object
109 \inqmlmodule QtQuick3D
110 \brief Defines a render pass in the CustomMaterial or the Effect.
111 */
112 /*!
113 \qmlproperty Buffer Pass::output
114 Specifies the output \l {Buffer}{buffer} of the pass.
115 */
116 /*!
117 \qmlproperty list Pass::commands
118 Specifies the list of render \l {Command}{commands} of the pass.
119 */
120 /*!
121 \qmlproperty list Pass::shaders
122 Specifies the list of \l {Shader}{shaders} of the pass.
123 */
124
125 /*!
126 \qmltype Command
127 \inherits Object
128 \inqmlmodule QtQuick3D
129 \brief Defines a command to be performed in a pass of a CustomMaterial or an Effect.
130 */
131
132 /*!
133 \qmltype BufferInput
134 \inherits Command
135 \inqmlmodule QtQuick3D
136 \brief Defines an input buffer to be used for a pass of a CustomMaterial or an Effect.
137 */
138 /*!
139 \qmlproperty Buffer BufferInput::buffer
140 Specifies the \l {Buffer}{buffer} used for the parameter.
141 */
142 /*!
143 \qmlproperty string BufferInput::param
144 Specifies the name of the input parameter in the shader.
145 */
146
147 /*!
148 \qmltype BufferBlit
149 \inherits Command
150 \inqmlmodule QtQuick3D
151 \brief Defines a copy operation between two buffers in a pass of a CustomMaterial or an Effect.
152 */
153 /*!
154 \qmlproperty Buffer BufferBlit::source
155 Specifies the source \l {Buffer}{buffer} of the copy operation.
156 */
157 /*!
158 \qmlproperty Buffer BufferBlit::destination
159 Specifies the destination \l {Buffer}{buffer} of the copy operation.
160 */
161
162 /*!
163 \qmltype Blending
164 \inherits Command
165 \inqmlmodule QtQuick3D
166 \brief Defines the blending state in a pass of a CustomMaterial or an Effect.
167 */
168 /*!
169 \qmlproperty enumeration Blending::srcBlending
170 Specifies the source blending function.
171
172 \value Blending.Unknown
173 \value Blending.Zero
174 \value Blending.One
175 \value Blending.SrcColor
176 \value Blending.OneMinusSrcColor
177 \value Blending.DstColor
178 \value Blending.OneMinusDstColor
179 \value Blending.SrcAlpha
180 \value Blending.OneMinusSrcAlpha
181 \value Blending.DstAlpha
182 \value Blending.OneMinusDstAlpha
183 \value Blending.ConstantColor
184 \value Blending.OneMinusConstantColor
185 \value Blending.ConstantAlpha
186 \value Blending.OneMinusConstantAlpha
187 \value Blending.SrcAlphaSaturate
188
189 */
190 /*!
191 \qmlproperty enumeration Blending::destBlending
192 Specifies the destination blending function.
193
194 \value Blending.Unknown
195 \value Blending.Zero
196 \value Blending.One
197 \value Blending.SrcColor
198 \value Blending.OneMinusSrcColor
199 \value Blending.DstColor
200 \value Blending.OneMinusDstColor
201 \value Blending.SrcAlpha
202 \value Blending.OneMinusSrcAlpha
203 \value Blending.DstAlpha
204 \value Blending.OneMinusDstAlpha
205 \value Blending.ConstantColor
206 \value Blending.OneMinusConstantColor
207 \value Blending.ConstantAlpha
208 \value Blending.OneMinusConstantAlpha
209 */
210
211 /*!
212 \qmltype Buffer
213 \inherits Object
214 \inqmlmodule QtQuick3D
215 \brief Defines a buffer to be used for a pass of a CustomMaterial or an Effect.
216 */
217 /*!
218 \qmlproperty enumeration Buffer::format
219 Specifies the buffer format.
220
221 \value Buffer.Unknown
222 \value Buffer.R8
223 \value Buffer.R16
224 \value Buffer.R16F
225 \value Buffer.R32I
226 \value Buffer.R32UI
227 \value Buffer.R32F
228 \value Buffer.RG8
229 \value Buffer.RGBA8
230 \value Buffer.RGB8
231 \value Buffer.SRGB8
232 \value Buffer.SRGB8A8
233 \value Buffer.RGB565
234 \value Buffer.RGBA16F
235 \value Buffer.RG16F
236 \value Buffer.RG32F
237 \value Buffer.RGB32F
238 \value Buffer.RGBA32F
239 \value Buffer.R11G11B10
240 \value Buffer.RGB9E5
241 \value Buffer.Depth16
242 \value Buffer.Depth24
243 \value Buffer.Depth32
244 \value Buffer.Depth24Stencil8
245 */
246 /*!
247 \qmlproperty enumeration Buffer::textureFilterOperation
248 Specifies the filter operation when a render \l {Pass}{pass} is reading the buffer that is
249 different size as the current output buffer.
250
251 \value Buffer.Unknown Value not set.
252 \value Buffer.Nearest Use nearest-neighbor.
253 \value Buffer.Linear Use linear filtering.
254 */
255 /*!
256 \qmlproperty enumeration Buffer::textureCoordOperation
257 Specifies the texture coordinate operation for coordinates outside [0, 1] range.
258
259 \value Buffer.Unknown Value not set.
260 \value Buffer.ClampToEdge Clamp coordinate to edge.
261 \value Buffer.MirroredRepeat Repeat the coordinate, but flip direction at the beginning and end.
262 \value Buffer.Repeat Repeat the coordinate always from the beginning.
263 */
264 /*!
265 \qmlproperty real Buffer::sizeMultiplier
266 Specifies the size multiplier of the buffer. \c 1.0 creates buffer with the same size while
267 \c 0.5 creates buffer with width and height halved.
268 */
269 /*!
270 \qmlproperty enumeration Buffer::bufferFlags
271 Specifies the buffer allocation flags.
272
273 \value Buffer.None Value not set.
274 \value Buffer.SceneLifetime The buffer is allocated for the whole lifetime of the scene.
275 */
276 /*!
277 \qmlproperty string Buffer::name
278 Specifies the name of the buffer
279 */
280
281 /*!
282 \qmltype RenderState
283 \inherits Command
284 \inqmlmodule QtQuick3D
285 \brief Defines the render state to be disabled in a pass of a CustomMaterial or an Effect.
286 */
287 /*!
288 \qmlproperty enumeration RenderState::renderState
289 Specifies the render state to enable/disable in a \l {Pass}{pass}.
290
291 \value RenderState.Unknown
292 \value RenderState.Blend
293 \value RenderState.CullFace
294 \value RenderState.DepthTest
295 \value RenderState.StencilTest
296 \value RenderState.ScissorTest
297 \value RenderState.DepthWrite
298 \value RenderState.Multisample
299 */
300 /*!
301 \qmlproperty bool RenderState::enable
302 Specifies if the state is enabled or disabled.
303 */
304
305 /*!
306 \qmltype CullMode
307 \inherits Command
308 \inqmlmodule QtQuick3D
309 \brief Defines the cull mode for render pass.
310 \since 5.15
311
312 \note This command can only be used with the CustomMaterial.
313 */
314 /*!
315 \qmlproperty enumeration CullMode::cullMode
316 Specifies the culling mode in a \l {Pass}{pass} when \c RenderState.CullFace is enabled.
317 The material culling mode is overridden.
318
319 \value Material.BackFaceCulling
320 \value Material.FrontFaceCulling
321 \value Material.NoCulling
322 */
323
324 /*!
325 \qmltype DepthInput
326 \inherits Command
327 \inqmlmodule QtQuick3D
328 \brief Defines the output texture for the depth buffer.
329 \since 5.15
330 */
331 /*!
332 \qmlproperty string DepthInput::param
333 Specifies the name of the texture the depth buffer will bind to.
334 */
335
336 /*!
337 \qmltype SetUniformValue
338 \inherits Command
339 \inqmlmodule QtQuick3D
340 \brief Defines a value to be set during a single \l {Pass}{pass}.
341 \since 5.15
342
343 \note The value set by this command is will only be set during the \l {Pass}{pass} it occurs in.
344 For consecutive passes the value will be revert to the initial value of the uniform as it
345 was defined in the effect or custom material item.
346 */
347 /*!
348 \qmlproperty string SetUniformValue::target
349 Specifies the name of the uniform that will have its value changed during the \l {Pass}{pass}.
350 */
351 /*!
352 \qmlproperty Variant SetUniformValue::value
353 Specifies the value that will be set on the \c target uniform.
354 */
355
addSnapperSampler(const QByteArray & texName,QByteArray & shaderPrefix)356 void QSSGShaderUtils::addSnapperSampler(const QByteArray &texName, QByteArray &shaderPrefix)
357 {
358 const char *filter = "linear";
359 const char *clamp = "clamp";
360 // Output macro so we can change the set of variables used for this
361 // independent of the
362 // meta data system.
363 shaderPrefix.append("SNAPPER_SAMPLER2D(");
364 shaderPrefix.append(texName);
365 shaderPrefix.append(", ");
366 shaderPrefix.append(texName);
367 shaderPrefix.append(", ");
368 shaderPrefix.append(filter);
369 shaderPrefix.append(", ");
370 shaderPrefix.append(clamp);
371 shaderPrefix.append(", ");
372 shaderPrefix.append("false )\n");
373 }
374
resolveShader(const QByteArray & shader,QByteArray & shaderPath,const QObject * qmlObj)375 QByteArray QSSGShaderUtils::resolveShader(const QByteArray &shader, QByteArray &shaderPath,
376 const QObject *qmlObj)
377 {
378 if (!shaderPath.isEmpty())
379 shaderPath.append('>');
380
381 int offset = -1;
382 if (shader.startsWith("qrc:/"))
383 offset = 3;
384 else if (shader.startsWith("file:/"))
385 offset = 6;
386 else if (shader.startsWith(":/"))
387 offset = 0;
388
389 QString path;
390 if (offset == -1) {
391 QUrl u(QString::fromUtf8(shader));
392 if (u.isLocalFile())
393 path = u.toLocalFile();
394 }
395
396 if (offset == -1 && path.isEmpty())
397 path = QString::fromLatin1(":/") + QString::fromLocal8Bit(shader);
398 else
399 path = QString::fromLocal8Bit(shader.constData() + offset);
400
401 QFile f(path);
402 if (f.open(QIODevice::ReadOnly | QIODevice::Text)) {
403 shaderPath += path.toLatin1();
404 return f.readAll();
405 } else if (offset == -1) {
406 // Plain schemeless string can also be a local file instead of resource, so let's try to
407 // load a local file relative to qml context
408 QQmlContext *context = qmlContext(qmlObj);
409 if (context) {
410 QUrl resolvedUrl = context->resolvedUrl(QUrl(QString::fromUtf8(shader)));
411 path = resolvedUrl.toLocalFile();
412 QFile file(path);
413 if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
414 shaderPath += path.toLatin1();
415 return file.readAll();
416 }
417 }
418 }
419
420 shaderPath += QByteArrayLiteral("Inline_") + QByteArray::number(qHash(shader, uint(qGlobalQHashSeed())));
421
422 return shader;
423 }
424
mergeShaderCode(const QByteArray & shared,const QByteArray & uniforms,const QByteArray & textures,const QByteArray & vertex,const QByteArray & geometry,const QByteArray & fragment)425 QByteArray QSSGShaderUtils::mergeShaderCode(const QByteArray &shared,
426 const QByteArray &uniforms,
427 const QByteArray &textures,
428 const QByteArray &vertex,
429 const QByteArray &geometry,
430 const QByteArray &fragment)
431 {
432 QByteArray shaderCode;
433 // Shared
434 if (!shared.isEmpty())
435 shaderCode.append(shared);
436
437 if (!textures.isEmpty())
438 shaderCode.append(textures);
439
440 if (!uniforms.isEmpty())
441 shaderCode.append(uniforms);
442
443 // Vetex
444 shaderCode.append(QByteArrayLiteral("\n#ifdef VERTEX_SHADER\n"));
445 if (!vertex.isEmpty())
446 shaderCode.append(vertex);
447 else
448 shaderCode.append(QByteArrayLiteral("void vert(){}"));
449 shaderCode.append(QByteArrayLiteral("\n#endif\n"));
450
451 // Geometry
452 if (!geometry.isEmpty()) {
453 shaderCode.append(QByteArrayLiteral("\n#ifdef USER_GEOMETRY_SHADER\n"));
454 shaderCode.append(geometry);
455 shaderCode.append(QByteArrayLiteral("\n#endif\n"));
456 }
457
458 // Fragment
459 shaderCode.append(QByteArrayLiteral("\n#ifdef FRAGMENT_SHADER\n"));
460 if (!fragment.isEmpty())
461 shaderCode.append(fragment);
462 else
463 shaderCode.append(QByteArrayLiteral("void frag(){}"));
464 shaderCode.append(QByteArrayLiteral("\n#endif\n"));
465
466 return shaderCode;
467 }
468
mapRenderTextureFormat(QSSGRenderTextureFormat::Format fmt)469 QQuick3DShaderUtilsBuffer::TextureFormat QQuick3DShaderUtilsBuffer::mapRenderTextureFormat(QSSGRenderTextureFormat::Format fmt)
470 {
471 using TextureFormat = QQuick3DShaderUtilsBuffer::TextureFormat;
472 switch (fmt) {
473 case QSSGRenderTextureFormat::R8: return TextureFormat::R8;
474 case QSSGRenderTextureFormat::R16: return TextureFormat::R16;
475 case QSSGRenderTextureFormat::R16F: return TextureFormat::R16F;
476 case QSSGRenderTextureFormat::R32I: return TextureFormat::R32I;
477 case QSSGRenderTextureFormat::R32UI: return TextureFormat::R32UI;
478 case QSSGRenderTextureFormat::R32F: return TextureFormat::R32F;
479 case QSSGRenderTextureFormat::RG8: return TextureFormat::RG8;
480 case QSSGRenderTextureFormat::RGBA8: return TextureFormat::RGBA8;
481 case QSSGRenderTextureFormat::RGB8: return TextureFormat::RGB8;
482 case QSSGRenderTextureFormat::SRGB8: return TextureFormat::SRGB8;
483 case QSSGRenderTextureFormat::SRGB8A8: return TextureFormat::SRGB8A8;
484 case QSSGRenderTextureFormat::RGB565: return TextureFormat::RGB565;
485 case QSSGRenderTextureFormat::RGBA16F: return TextureFormat::RGBA16F;
486 case QSSGRenderTextureFormat::RG16F: return TextureFormat::RG16F;
487 case QSSGRenderTextureFormat::RG32F: return TextureFormat::RG32F;
488 case QSSGRenderTextureFormat::RGB32F: return TextureFormat::RGB32F;
489 case QSSGRenderTextureFormat::RGBA32F: return TextureFormat::RGBA32F;
490 case QSSGRenderTextureFormat::R11G11B10: return TextureFormat::R11G11B10;
491 case QSSGRenderTextureFormat::RGB9E5: return TextureFormat::RGB9E5;
492 case QSSGRenderTextureFormat::Depth16: return TextureFormat::Depth16;
493 case QSSGRenderTextureFormat::Depth24: return TextureFormat::Depth24;
494 case QSSGRenderTextureFormat::Depth32: return TextureFormat::Depth32;
495 case QSSGRenderTextureFormat::Depth24Stencil8: return TextureFormat::Depth24Stencil8;
496 default:
497 break;
498 }
499 return TextureFormat::Unknown;
500 }
501
mapTextureFormat(QQuick3DShaderUtilsBuffer::TextureFormat fmt)502 QSSGRenderTextureFormat::Format QQuick3DShaderUtilsBuffer::mapTextureFormat(QQuick3DShaderUtilsBuffer::TextureFormat fmt)
503 {
504 using TextureFormat = QQuick3DShaderUtilsBuffer::TextureFormat;
505 switch (fmt) {
506 case TextureFormat::R8: return QSSGRenderTextureFormat::R8;
507 case TextureFormat::R16: return QSSGRenderTextureFormat::R16;
508 case TextureFormat::R16F: return QSSGRenderTextureFormat::R16F;
509 case TextureFormat::R32I: return QSSGRenderTextureFormat::R32I;
510 case TextureFormat::R32UI: return QSSGRenderTextureFormat::R32UI;
511 case TextureFormat::R32F: return QSSGRenderTextureFormat::R32F;
512 case TextureFormat::RG8: return QSSGRenderTextureFormat::RG8;
513 case TextureFormat::RGBA8: return QSSGRenderTextureFormat::RGBA8;
514 case TextureFormat::RGB8: return QSSGRenderTextureFormat::RGB8;
515 case TextureFormat::SRGB8: return QSSGRenderTextureFormat::SRGB8;
516 case TextureFormat::SRGB8A8: return QSSGRenderTextureFormat::SRGB8A8;
517 case TextureFormat::RGB565: return QSSGRenderTextureFormat::RGB565;
518 case TextureFormat::RGBA16F: return QSSGRenderTextureFormat::RGBA16F;
519 case TextureFormat::RG16F: return QSSGRenderTextureFormat::RG16F;
520 case TextureFormat::RG32F: return QSSGRenderTextureFormat::RG32F;
521 case TextureFormat::RGB32F: return QSSGRenderTextureFormat::RGB32F;
522 case TextureFormat::RGBA32F: return QSSGRenderTextureFormat::RGBA32F;
523 case TextureFormat::R11G11B10: return QSSGRenderTextureFormat::R11G11B10;
524 case TextureFormat::RGB9E5: return QSSGRenderTextureFormat::RGB9E5;
525 case TextureFormat::Depth16: return QSSGRenderTextureFormat::Depth16;
526 case TextureFormat::Depth24: return QSSGRenderTextureFormat::Depth24;
527 case TextureFormat::Depth32: return QSSGRenderTextureFormat::Depth32;
528 case TextureFormat::Depth24Stencil8: return QSSGRenderTextureFormat::Depth24Stencil8;
529 default:
530 break;
531 }
532 return QSSGRenderTextureFormat::Unknown;
533 }
534
format() const535 QQuick3DShaderUtilsBuffer::TextureFormat QQuick3DShaderUtilsBuffer::format() const
536 {
537 return mapRenderTextureFormat(command.m_format.format);
538 }
539
setFormat(TextureFormat format)540 void QQuick3DShaderUtilsBuffer::setFormat(TextureFormat format)
541 {
542 command.m_format = mapTextureFormat(format);
543 }
544
qmlAppendCommand(QQmlListProperty<QQuick3DShaderUtilsRenderCommand> * list,QQuick3DShaderUtilsRenderCommand * command)545 void QQuick3DShaderUtilsRenderPass::qmlAppendCommand(QQmlListProperty<QQuick3DShaderUtilsRenderCommand> *list,
546 QQuick3DShaderUtilsRenderCommand *command)
547 {
548 if (!command)
549 return;
550
551 QQuick3DShaderUtilsRenderPass *that = qobject_cast<QQuick3DShaderUtilsRenderPass *>(list->object);
552 that->m_commands.push_back(command);
553 }
554
qmlCommandAt(QQmlListProperty<QQuick3DShaderUtilsRenderCommand> * list,int index)555 QQuick3DShaderUtilsRenderCommand *QQuick3DShaderUtilsRenderPass::qmlCommandAt(QQmlListProperty<QQuick3DShaderUtilsRenderCommand> *list,
556 int index)
557 {
558 QQuick3DShaderUtilsRenderPass *that = qobject_cast<QQuick3DShaderUtilsRenderPass *>(list->object);
559 return that->m_commands.at(index);
560 }
561
qmlCommandCount(QQmlListProperty<QQuick3DShaderUtilsRenderCommand> * list)562 int QQuick3DShaderUtilsRenderPass::qmlCommandCount(QQmlListProperty<QQuick3DShaderUtilsRenderCommand> *list)
563 {
564 QQuick3DShaderUtilsRenderPass *that = qobject_cast<QQuick3DShaderUtilsRenderPass *>(list->object);
565 return that->m_commands.count();
566 }
567
qmlCommandClear(QQmlListProperty<QQuick3DShaderUtilsRenderCommand> * list)568 void QQuick3DShaderUtilsRenderPass::qmlCommandClear(QQmlListProperty<QQuick3DShaderUtilsRenderCommand> *list)
569 {
570 QQuick3DShaderUtilsRenderPass *that = qobject_cast<QQuick3DShaderUtilsRenderPass *>(list->object);
571 that->m_commands.clear();
572 }
573
commands()574 QQmlListProperty<QQuick3DShaderUtilsRenderCommand> QQuick3DShaderUtilsRenderPass::commands()
575 {
576 return QQmlListProperty<QQuick3DShaderUtilsRenderCommand>(this,
577 nullptr,
578 QQuick3DShaderUtilsRenderPass::qmlAppendCommand,
579 QQuick3DShaderUtilsRenderPass::qmlCommandCount,
580 QQuick3DShaderUtilsRenderPass::qmlCommandAt,
581 QQuick3DShaderUtilsRenderPass::qmlCommandClear);
582 }
583
qmlAppendShader(QQmlListProperty<QQuick3DShaderUtilsShader> * list,QQuick3DShaderUtilsShader * shader)584 void QQuick3DShaderUtilsRenderPass::qmlAppendShader(QQmlListProperty<QQuick3DShaderUtilsShader> *list,
585 QQuick3DShaderUtilsShader *shader)
586 {
587 if (!shader)
588 return;
589
590 QQuick3DShaderUtilsRenderPass *that = qobject_cast<QQuick3DShaderUtilsRenderPass *>(list->object);
591 that->m_shaders[int(shader->stage)] = shader;
592 }
593
qmlShaderAt(QQmlListProperty<QQuick3DShaderUtilsShader> * list,int index)594 QQuick3DShaderUtilsShader *QQuick3DShaderUtilsRenderPass::qmlShaderAt(QQmlListProperty<QQuick3DShaderUtilsShader> *list,
595 int index)
596 {
597 QQuick3DShaderUtilsRenderPass *that = qobject_cast<QQuick3DShaderUtilsRenderPass *>(list->object);
598 return that->m_shaders.at(index);
599 }
600
qmlShaderCount(QQmlListProperty<QQuick3DShaderUtilsShader> * list)601 int QQuick3DShaderUtilsRenderPass::qmlShaderCount(QQmlListProperty<QQuick3DShaderUtilsShader> *list)
602 {
603 QQuick3DShaderUtilsRenderPass *that = qobject_cast<QQuick3DShaderUtilsRenderPass *>(list->object);
604 return that->m_shaders.count();
605 }
606
qmlShaderClear(QQmlListProperty<QQuick3DShaderUtilsShader> * list)607 void QQuick3DShaderUtilsRenderPass::qmlShaderClear(QQmlListProperty<QQuick3DShaderUtilsShader> *list)
608 {
609 QQuick3DShaderUtilsRenderPass *that = qobject_cast<QQuick3DShaderUtilsRenderPass *>(list->object);
610 auto it = that->m_shaders.begin();
611 const auto end = that->m_shaders.end();
612 for (;it != end; ++it)
613 *it = nullptr;
614 }
615
shaders()616 QQmlListProperty<QQuick3DShaderUtilsShader> QQuick3DShaderUtilsRenderPass::shaders()
617 {
618 return QQmlListProperty<QQuick3DShaderUtilsShader>(this,
619 nullptr,
620 QQuick3DShaderUtilsRenderPass::qmlAppendShader,
621 QQuick3DShaderUtilsRenderPass::qmlShaderCount,
622 QQuick3DShaderUtilsRenderPass::qmlShaderAt,
623 QQuick3DShaderUtilsRenderPass::qmlShaderClear);
624 }
625
setTexture(QQuick3DTexture * texture)626 void QQuick3DShaderUtilsTextureInput::setTexture(QQuick3DTexture *texture)
627 {
628 if (m_texture == texture)
629 return;
630
631 QObject *p = parent();
632 while (p != nullptr) {
633 if (QQuick3DMaterial *mat = qobject_cast<QQuick3DMaterial *>(p)) {
634 mat->setDynamicTextureMap(texture, name);
635 break;
636 } else if (QQuick3DEffect *efx = qobject_cast<QQuick3DEffect *>(p)) {
637 efx->setDynamicTextureMap(texture, name);
638 break;
639 }
640 p = p->parent();
641 }
642
643 if (p == nullptr) {
644 qWarning("A texture was defined out of Material or Effect");
645 }
646
647 m_texture = texture;
648 Q_EMIT textureDirty(this);
649 }
650
651 QT_END_NAMESPACE
652