Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qquick3dshaderutils.cpp
Go to the documentation of this file.
1// Copyright (C) 2020 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
5
6#include <QtCore/qfile.h>
7#include <QtQml/qqmlcontext.h>
8#include <QtQml/qqmlfile.h>
9
13
15
16/*!
17 \qmltype Shader
18 \inherits QtObject
19 \inqmlmodule QtQuick3D
20 \brief Container component for defining shader code used by post-processing effects.
21
22 The Shader type is used for populating the \l{Pass::shaders}{shaders} list in the
23 render \l{Pass}{pass} of an \l Effect.
24
25 A shader is code which is executed directly on the graphic hardware at a particular
26 \l{Shader::stage}{stage} of the rendering pipeline.
27
28 \sa Effect
29*/
30/*!
31 \qmlproperty url Shader::shader
32 Specifies the name of the shader source file. For details on how to write shader code,
33 see the \l Effect documentation.
34
35 \warning Shader snippets are assumed to be trusted content. Application
36 developers are advised to carefully consider the potential implications
37 before allowing the loading of user-provided content that is not part of the
38 application.
39*/
40/*!
41 \qmlproperty enumeration Shader::stage
42 Specifies the stage of the rendering pipeline when the shader code will be executed.
43 The default is \c Shader.Fragment
44
45 \value Shader.Vertex The shader is a vertex shader. This code is run once per vertex
46 in the input geometry and can be used to modify it before the geometry is rasterized
47 (scan converted). In the case of effects, the input geometry is always a quad (four
48 vertexes representing the corners of the render target).
49 \value Shader.Fragment The shader is a fragment shader. After vertex processing,
50 the modified geometry is turned into fragments (rasterization). Then a fragment shader
51 is executed for each fragment, assigning a color to it. Fragments are a related concept
52 to pixels, but with additional information attached. Also, as a result of some
53 anti-aliasing strategies, there may be more than one fragment for each pixel in the
54 output.
55*/
56
57/*!
58 \qmltype TextureInput
59 \inherits QtObject
60 \inqmlmodule QtQuick3D
61 \brief Specifies a texture exposed to the shaders of a CustomMaterial or Effect.
62
63 This is a type which can be used for exposing a \l Texture to a shader, either
64 in the \l{Pass}{render pass} of an \l Effect, or in a \l CustomMaterial. It exists
65 primarily to assign a local name to the \l Texture that can be referenced from
66 shaders.
67
68 When a TextureInput property is declared in an \l Effect or a \l CustomMaterial,
69 it will automatically be available as a sampler in all shaders by its property
70 name.
71*/
72/*!
73 \qmlproperty Texture TextureInput::texture
74 The texture for which this TextureInput serves as an indirection.
75*/
76/*!
77 \qmlproperty bool TextureInput::enabled
78 The property determines if this TextureInput is enabled. The default value
79 is true. When disabled, the shaders of the effect sample a dummy, opaque
80 black texture instead of the one specified by \l texture.
81*/
82
83/*!
84 \qmltype Pass
85 \inherits QtObject
86 \inqmlmodule QtQuick3D
87 \brief Defines a render pass in an Effect.
88
89 An \l Effect may consist of multiple render passes. Each render pass has a
90 setup phase where the list of \l{Pass::commands}{render commands} are executed,
91 a \l{Pass::output}{output buffer} and a list of \l{Pass::shaders}{shaders} to
92 use for rendering the effect.
93
94 See the documentation for \l Effect for more details on how to set up multiple
95 rendering passes.
96*/
97/*!
98 \qmlproperty Buffer Pass::output
99 Specifies the output \l {Buffer}{buffer} of the pass.
100*/
101/*!
102 \qmlproperty list Pass::commands
103 Specifies the list of render \l {Command}{commands} of the pass.
104*/
105/*!
106 \qmlproperty list Pass::shaders
107 Specifies the list of \l {Shader}{shaders} of the pass.
108*/
109
110/*!
111 \qmltype Command
112 \inherits QtObject
113 \inqmlmodule QtQuick3D
114 \brief Supertype of commands to be performed as part of a pass in an Effect.
115
116 The Command type should not be instantiated by itself, but only exists as a
117 polymorphic supertype for the different actions that can be performed as part
118 of a \l{Pass}{render pass}.
119
120 \sa BufferInput, SetUniformValue, Effect
121*/
122
123/*!
124 \qmltype BufferInput
125 \inherits Command
126 \inqmlmodule QtQuick3D
127 \brief Defines an input buffer to be used as input for a pass of an Effect.
128
129 BufferInput is a \l Command which can be added to the list of commands in the \l Pass of
130 an \l Effect. When executed, it will expose the buffer as a sample to the shaders
131 in the render pass. The shaders must declare a sampler with the name given in the
132 BufferInput's \c sampler property.
133
134 This can be used for sharing intermediate results between the different passes of an
135 effect.
136
137 \sa TextureInput
138*/
139/*!
140 \qmlproperty Buffer BufferInput::buffer
141 Specifies the \l {Buffer}{buffer} which should be exposed to the shader.
142*/
143/*!
144 \qmlproperty string BufferInput::sampler
145 Specifies the name under which the buffer is exposed to the shader.
146 When this property is not set, the buffer is exposed with the built-in name \c INPUT.
147*/
148
149/*!
150 \qmltype Buffer
151 \inherits QtObject
152 \inqmlmodule QtQuick3D
153 \brief Creates or references a color buffer to be used for a pass of an Effect.
154
155 A Buffer can be used to create intermediate buffers to share data between
156 \l{Pass}{render passes} in an \l Effect.
157
158 \note If the \l name property of the Buffer is empty, it will reference the
159 default output texture of the render pass.
160*/
161/*!
162 \qmlproperty enumeration Buffer::format
163 Specifies the texture format. The default value is Buffer.RGBA8.
164
165 \value Buffer.RGBA8
166 \value Buffer.RGBA16F
167 \value Buffer.RGBA32F
168 \value Buffer.R8
169 \value Buffer.R16
170 \value Buffer.R16F
171 \value Buffer.R32F
172*/
173/*!
174 \qmlproperty enumeration Buffer::textureFilterOperation
175 Specifies the texture filtering mode when sampling the contents of the
176 Buffer. The default value is Buffer.Linear.
177
178 \value Buffer.Nearest Use nearest-neighbor filtering.
179 \value Buffer.Linear Use linear filtering.
180*/
181/*!
182 \qmlproperty enumeration Buffer::textureCoordOperation
183 Specifies the behavior for texture coordinates when sampling outside the [0, 1] range.
184 The default is Buffer.ClampToEdge.
185
186 \value Buffer.ClampToEdge Clamp coordinates to the edges.
187 \value Buffer.Repeat Wrap the coordinates at the edges to tile the texture.
188 \value Buffer.MirroredRepeat Wrap the coordinate at the edges, but mirror the texture
189 when tiling it.
190*/
191/*!
192 \qmlproperty real Buffer::sizeMultiplier
193 Specifies the size multiplier of the buffer. For instance, a value of \c 1.0 creates
194 a buffer with the same size as the effect's input texture while \c 0.5 creates buffer
195 where both width and height is half as big. The default value is 1.0.
196*/
197/*!
198 \qmlproperty enumeration Buffer::bufferFlags
199 Specifies the buffer allocation flags. The default is Buffer.None.
200
201 \value Buffer.None No special behavior.
202 \value Buffer.SceneLifetime The buffer is allocated for the whole lifetime of the scene.
203*/
204/*!
205 \qmlproperty string Buffer::name
206 Specifies the name of the buffer.
207
208 \note When this property is empty, the Buffer will refer to the default output texture
209 of the \l{Pass}{render pass} instead of allocating a buffer. This can be useful to
210 override certain settings of the output, such as the texture format, without introducing
211 a new, separate intermediate texture.
212*/
213
214/*!
215 \qmltype SetUniformValue
216 \inherits Command
217 \inqmlmodule QtQuick3D
218 \brief Defines a value to be set during a single \l {Pass}{pass}.
219 \since 5.15
220
221 SetUniformValue is a \l Command which can be added to the list of commands in a \l Pass. When
222 executed, it will set the uniform given by the \l{SetUniformValue::target}{target} property
223 to \l{SetUniformValue::value}{value}.
224
225 \note The value set by this command is will only be set during the \l {Pass}{pass} it occurs in.
226 For consecutive passes the value will be revert to the initial value of the uniform as it
227 was defined in the \l Effect item.
228
229 \sa BufferInput
230*/
231/*!
232 \qmlproperty string SetUniformValue::target
233 Specifies the name of the uniform that will have its value changed during the \l {Pass}{pass}.
234 This must match the name of an existing property in the \l Effect.
235*/
236/*!
237 \qmlproperty Variant SetUniformValue::value
238 Specifies the value that will be set on the \c target uniform.
239*/
240
242
244
249
250QByteArray resolveShader(const QUrl &fileUrl, const QQmlContext *context, QByteArray &shaderPathKey)
251{
253 QByteArray shaderData;
254 if (resolveShaderOverride(fileUrl, context, shaderData, shaderPathKey))
255 return shaderData;
256 }
257
258 if (!shaderPathKey.isEmpty())
259 shaderPathKey.append('>');
260
261 const QUrl loadUrl = context ? context->resolvedUrl(fileUrl) : fileUrl;
262 const QString filePath = QQmlFile::urlToLocalFileOrQrc(loadUrl);
263
264 QFile f(filePath);
265 if (f.open(QIODevice::ReadOnly | QIODevice::Text)) {
266 shaderPathKey += loadUrl.fileName().toUtf8();
267 return f.readAll();
268 } else {
269 qWarning("Failed to read shader code from %s", qPrintable(filePath));
270 }
271
272 return QByteArray();
273}
274
275// These are the QMetaTypes that we convert into uniforms.
293
294template<>
296{
298 static QByteArray name() { return QByteArrayLiteral("float"); }
299};
300
301template<>
303{
305 static QByteArray name() { return QByteArrayLiteral("bool"); }
306};
307
308template<>
310{
312 static QByteArray name() { return QByteArrayLiteral("int"); }
313};
314
315template<>
317{
319 static QByteArray name() { return QByteArrayLiteral("vec2"); }
320};
321
322template<>
324{
326 static QByteArray name() { return QByteArrayLiteral("vec3"); }
327};
328
329template<>
331{
333 static QByteArray name() { return QByteArrayLiteral("vec4"); }
334};
335
336template<>
338{
340 static QByteArray name() { return QByteArrayLiteral("vec4"); }
341};
342
343template<>
345{
347 static QByteArray name() { return QByteArrayLiteral("vec2"); }
348};
349
350template<>
352{
354 static QByteArray name() { return QByteArrayLiteral("vec2"); }
355};
356
357template<>
359{
361 static QByteArray name() { return QByteArrayLiteral("vec2"); }
362};
363
364template<>
366{
368 static QByteArray name() { return QByteArrayLiteral("vec2"); }
369};
370
371template<>
373{
375 static QByteArray name() { return QByteArrayLiteral("vec4"); }
376};
377
378template<>
380{
382 static QByteArray name() { return QByteArrayLiteral("vec4"); }
383};
384
385template<>
387{
389 static QByteArray name() { return QByteArrayLiteral("vec4"); }
390};
391
392template<>
394{
396 static QByteArray name() { return QByteArrayLiteral("mat4"); }
397};
398
400{
401 switch (type.id()) {
402 case QMetaType::Double:
403 case QMetaType::Float:
404 return ShaderType<QMetaType::Double>::name();
405 case QMetaType::Bool:
406 return ShaderType<QMetaType::Bool>::name();
407 case QMetaType::QVector2D:
408 return ShaderType<QMetaType::QVector2D>::name();
409 case QMetaType::QVector3D:
410 return ShaderType<QMetaType::QVector3D>::name();
411 case QMetaType::QVector4D:
412 return ShaderType<QMetaType::QVector4D>::name();
413 case QMetaType::Int:
414 return ShaderType<QMetaType::Int>::name();
415 case QMetaType::QColor:
416 return ShaderType<QMetaType::QColor>::name();
417 case QMetaType::QSize:
418 return ShaderType<QMetaType::QSize>::name();
419 case QMetaType::QSizeF:
420 return ShaderType<QMetaType::QSizeF>::name();
421 case QMetaType::QPoint:
422 return ShaderType<QMetaType::QPoint>::name();
423 case QMetaType::QPointF:
424 return ShaderType<QMetaType::QPointF>::name();
425 case QMetaType::QRect:
426 return ShaderType<QMetaType::QRect>::name();
427 case QMetaType::QRectF:
428 return ShaderType<QMetaType::QRectF>::name();
429 case QMetaType::QQuaternion:
430 return ShaderType<QMetaType::QQuaternion>::name();
431 case QMetaType::QMatrix4x4:
432 return ShaderType<QMetaType::QMatrix4x4>::name();
433 default:
434 return QByteArray();
435 }
436}
437
438QByteArray uniformTypeName(QSSGRenderShaderValue::Type type)
439{
440 switch (type) {
441 case QSSGRenderShaderValue::Float:
442 return ShaderType<QMetaType::Double>::name();
443 case QSSGRenderShaderValue::Boolean:
444 return ShaderType<QMetaType::Bool>::name();
445 case QSSGRenderShaderValue::Integer:
446 return ShaderType<QMetaType::Int>::name();
447 case QSSGRenderShaderValue::Vec2:
448 return ShaderType<QMetaType::QVector2D>::name();
449 case QSSGRenderShaderValue::Vec3:
450 return ShaderType<QMetaType::QVector3D>::name();
451 case QSSGRenderShaderValue::Vec4:
452 return ShaderType<QMetaType::QVector4D>::name();
453 case QSSGRenderShaderValue::Rgba:
454 return ShaderType<QMetaType::QColor>::name();
455 case QSSGRenderShaderValue::Size:
456 return ShaderType<QMetaType::QSize>::name();
457 case QSSGRenderShaderValue::SizeF:
458 return ShaderType<QMetaType::QSizeF>::name();
459 case QSSGRenderShaderValue::Point:
460 return ShaderType<QMetaType::QPoint>::name();
461 case QSSGRenderShaderValue::PointF:
462 return ShaderType<QMetaType::QPointF>::name();
463 case QSSGRenderShaderValue::Rect:
464 return ShaderType<QMetaType::QRect>::name();
465 case QSSGRenderShaderValue::RectF:
466 return ShaderType<QMetaType::QRectF>::name();
467 case QSSGRenderShaderValue::Quaternion:
468 return ShaderType<QMetaType::QQuaternion>::name();
469 case QSSGRenderShaderValue::Matrix4x4:
470 return ShaderType<QMetaType::QMatrix4x4>::name();
471 default:
472 return QByteArray();
473 }
474}
475
477{
478 switch (type.id()) {
479 case QMetaType::Double:
480 case QMetaType::Float:
481 return ShaderType<QMetaType::Double>::type();
482 case QMetaType::Bool:
483 return ShaderType<QMetaType::Bool>::type();
484 case QMetaType::QVector2D:
485 return ShaderType<QMetaType::QVector2D>::type();
486 case QMetaType::QVector3D:
487 return ShaderType<QMetaType::QVector3D>::type();
488 case QMetaType::QVector4D:
489 return ShaderType<QMetaType::QVector4D>::type();
490 case QMetaType::Int:
491 return ShaderType<QMetaType::Int>::type();
492 case QMetaType::QColor:
493 return ShaderType<QMetaType::QColor>::type();
494 case QMetaType::QSize:
495 return ShaderType<QMetaType::QSize>::type();
496 case QMetaType::QSizeF:
497 return ShaderType<QMetaType::QSizeF>::type();
498 case QMetaType::QPoint:
499 return ShaderType<QMetaType::QPoint>::type();
500 case QMetaType::QPointF:
501 return ShaderType<QMetaType::QPointF>::type();
502 case QMetaType::QRect:
503 return ShaderType<QMetaType::QRect>::type();
504 case QMetaType::QRectF:
505 return ShaderType<QMetaType::QRectF>::type();
506 case QMetaType::QQuaternion:
507 return ShaderType<QMetaType::QQuaternion>::type();
508 case QMetaType::QMatrix4x4:
509 return ShaderType<QMetaType::QMatrix4x4>::type();
510 default:
511 return QSSGRenderShaderValue::Unknown;
512 }
513}
514
516{
517 return {std::begin(qssg_metatype_list), std::end(qssg_metatype_list)};
518}
519
520}
521
522QQuick3DShaderUtilsBuffer::TextureFormat QQuick3DShaderUtilsBuffer::mapRenderTextureFormat(QSSGRenderTextureFormat::Format fmt)
523{
524 using TextureFormat = QQuick3DShaderUtilsBuffer::TextureFormat;
525 switch (fmt) {
526 case QSSGRenderTextureFormat::RGBA8: return TextureFormat::RGBA8;
527 case QSSGRenderTextureFormat::RGBA16F: return TextureFormat::RGBA16F;
528 case QSSGRenderTextureFormat::RGBA32F: return TextureFormat::RGBA32F;
529 case QSSGRenderTextureFormat::R8: return TextureFormat::R8;
530 case QSSGRenderTextureFormat::R16: return TextureFormat::R16;
531 case QSSGRenderTextureFormat::R16F: return TextureFormat::R16F;
532 case QSSGRenderTextureFormat::R32F: return TextureFormat::R32F;
533 default:
534 break;
535 }
536 return TextureFormat::Unknown;
537}
538
539QSSGRenderTextureFormat::Format QQuick3DShaderUtilsBuffer::mapTextureFormat(QQuick3DShaderUtilsBuffer::TextureFormat fmt)
540{
541 using TextureFormat = QQuick3DShaderUtilsBuffer::TextureFormat;
542 switch (fmt) {
543 case TextureFormat::RGBA8: return QSSGRenderTextureFormat::RGBA8;
544 case TextureFormat::RGBA16F: return QSSGRenderTextureFormat::RGBA16F;
545 case TextureFormat::RGBA32F: return QSSGRenderTextureFormat::RGBA32F;
546 case TextureFormat::R8: return QSSGRenderTextureFormat::R8;
547 case TextureFormat::R16: return QSSGRenderTextureFormat::R16;
548 case TextureFormat::R16F: return QSSGRenderTextureFormat::R16F;
549 case TextureFormat::R32F: return QSSGRenderTextureFormat::R32F;
550 default:
551 break;
552 }
553 return QSSGRenderTextureFormat::Unknown;
554}
555
556QQuick3DShaderUtilsBuffer::TextureFormat QQuick3DShaderUtilsBuffer::format() const
557{
558 return mapRenderTextureFormat(command.m_format.format);
559}
560
561void QQuick3DShaderUtilsBuffer::setFormat(TextureFormat format)
562{
563 QSSGRenderTextureFormat::Format mappedTextureFormat = mapTextureFormat(format);
564 if (command.m_format == mappedTextureFormat)
565 return;
566
567 command.m_format = mappedTextureFormat;
568 emit changed();
569}
570
571void QQuick3DShaderUtilsBuffer::setTextureFilterOperation(TextureFilterOperation op)
572{
573 if (command.m_filterOp == QSSGRenderTextureFilterOp(op))
574 return;
575
576 command.m_filterOp = QSSGRenderTextureFilterOp(op);
577 emit changed();
578}
579
580void QQuick3DShaderUtilsBuffer::setTextureCoordOperation(TextureCoordOperation texCoordOp)
581{
582 if (command.m_texCoordOp == QSSGRenderTextureCoordOp(texCoordOp))
583 return;
584
585 command.m_texCoordOp = QSSGRenderTextureCoordOp(texCoordOp);
586 emit changed();
587}
588
589void QQuick3DShaderUtilsBuffer::setBufferFlags(AllocateBufferFlagValues flag)
590{
591 if (quint32(command.m_bufferFlags) == quint32(flag))
592 return;
593
594 command.m_bufferFlags = quint32(flag);
595 emit changed();
596}
597
598void QQuick3DShaderUtilsRenderPass::qmlAppendCommand(QQmlListProperty<QQuick3DShaderUtilsRenderCommand> *list,
599 QQuick3DShaderUtilsRenderCommand *command)
600{
601 if (!command)
602 return;
603
604 QQuick3DShaderUtilsRenderPass *that = qobject_cast<QQuick3DShaderUtilsRenderPass *>(list->object);
605 that->m_commands.push_back(command);
606 emit that->changed();
607}
608
609QQuick3DShaderUtilsRenderCommand *QQuick3DShaderUtilsRenderPass::qmlCommandAt(QQmlListProperty<QQuick3DShaderUtilsRenderCommand> *list,
610 qsizetype index)
611{
612 QQuick3DShaderUtilsRenderPass *that = qobject_cast<QQuick3DShaderUtilsRenderPass *>(list->object);
613 return that->m_commands.at(index);
614}
615
616qsizetype QQuick3DShaderUtilsRenderPass::qmlCommandCount(QQmlListProperty<QQuick3DShaderUtilsRenderCommand> *list)
617{
618 QQuick3DShaderUtilsRenderPass *that = qobject_cast<QQuick3DShaderUtilsRenderPass *>(list->object);
619 return that->m_commands.size();
620}
621
622void QQuick3DShaderUtilsRenderPass::qmlCommandClear(QQmlListProperty<QQuick3DShaderUtilsRenderCommand> *list)
623{
624 QQuick3DShaderUtilsRenderPass *that = qobject_cast<QQuick3DShaderUtilsRenderPass *>(list->object);
625 that->m_commands.clear();
626 emit that->changed();
627}
628
629QQmlListProperty<QQuick3DShaderUtilsRenderCommand> QQuick3DShaderUtilsRenderPass::commands()
630{
631 return QQmlListProperty<QQuick3DShaderUtilsRenderCommand>(this,
632 nullptr,
633 QQuick3DShaderUtilsRenderPass::qmlAppendCommand,
634 QQuick3DShaderUtilsRenderPass::qmlCommandCount,
635 QQuick3DShaderUtilsRenderPass::qmlCommandAt,
636 QQuick3DShaderUtilsRenderPass::qmlCommandClear);
637}
638
639void QQuick3DShaderUtilsRenderPass::qmlAppendShader(QQmlListProperty<QQuick3DShaderUtilsShader> *list,
640 QQuick3DShaderUtilsShader *shader)
641{
642 if (!shader)
643 return;
644
645 QQuick3DShaderUtilsRenderPass *that = qobject_cast<QQuick3DShaderUtilsRenderPass *>(list->object);
646
647 // An append implementation CANNOT rely on the object (shader in this case)
648 // being complete. When the list references a Shader object living under
649 // another Effect, its properties may not be set at the point of this
650 // function being called, so accessing shader->stage is not allowed since
651 // it may still have its default value, not what is set from QML...
652
653 // the only thing we can do is to append to our list, do not try to be clever
654 that->m_shaders.append(shader);
655
656 connect(shader, &QQuick3DShaderUtilsShader::shaderChanged, that, &QQuick3DShaderUtilsRenderPass::changed);
657 connect(shader, &QQuick3DShaderUtilsShader::stageChanged, that, &QQuick3DShaderUtilsRenderPass::changed);
658
659 emit that->changed();
660}
661
662QQuick3DShaderUtilsShader *QQuick3DShaderUtilsRenderPass::qmlShaderAt(QQmlListProperty<QQuick3DShaderUtilsShader> *list,
663 qsizetype index)
664{
665 QQuick3DShaderUtilsRenderPass *that = qobject_cast<QQuick3DShaderUtilsRenderPass *>(list->object);
666 return that->m_shaders.at(index);
667}
668
669qsizetype QQuick3DShaderUtilsRenderPass::qmlShaderCount(QQmlListProperty<QQuick3DShaderUtilsShader> *list)
670{
671 QQuick3DShaderUtilsRenderPass *that = qobject_cast<QQuick3DShaderUtilsRenderPass *>(list->object);
672 return that->m_shaders.size();
673}
674
675void QQuick3DShaderUtilsRenderPass::qmlShaderClear(QQmlListProperty<QQuick3DShaderUtilsShader> *list)
676{
677 QQuick3DShaderUtilsRenderPass *that = qobject_cast<QQuick3DShaderUtilsRenderPass *>(list->object);
678
679 for (QQuick3DShaderUtilsShader *shader : that->m_shaders)
680 shader->disconnect(that);
681
682 that->m_shaders.clear();
683
684 emit that->changed();
685}
686
687QQmlListProperty<QQuick3DShaderUtilsShader> QQuick3DShaderUtilsRenderPass::shaders()
688{
689 return QQmlListProperty<QQuick3DShaderUtilsShader>(this,
690 nullptr,
691 QQuick3DShaderUtilsRenderPass::qmlAppendShader,
692 QQuick3DShaderUtilsRenderPass::qmlShaderCount,
693 QQuick3DShaderUtilsRenderPass::qmlShaderAt,
694 QQuick3DShaderUtilsRenderPass::qmlShaderClear);
695}
696
697QQuick3DShaderUtilsTextureInput::QQuick3DShaderUtilsTextureInput(QObject *p) : QObject(p) {}
698
699QQuick3DShaderUtilsTextureInput::~QQuick3DShaderUtilsTextureInput()
700{
701}
702
703void QQuick3DShaderUtilsTextureInput::setTexture(QQuick3DTexture *texture)
704{
705 if (m_texture == texture)
706 return;
707
708 QObject *p = parent();
709 while (p != nullptr) {
710 if (QQuick3DCustomMaterial *mat = qobject_cast<QQuick3DCustomMaterial *>(p)) {
711 mat->setDynamicTextureMap(this);
712 QQuick3DObjectPrivate::attachWatcherPriv(mat, this, &QQuick3DShaderUtilsTextureInput::setTexture, texture, m_texture);
713 break;
714 } else if (QQuick3DEffect *efx = qobject_cast<QQuick3DEffect *>(p)) {
715 efx->setDynamicTextureMap(this);
716 QQuick3DObjectPrivate::attachWatcherPriv(efx, this, &QQuick3DShaderUtilsTextureInput::setTexture, texture, m_texture);
717 break;
718 }
719 p = p->parent();
720 }
721
722 if (p == nullptr) {
723 qWarning("A TextureInput was defined without a CustomMaterial or Effect ancestor. This should be avoided.");
724 }
725
726 m_texture = texture;
727 Q_EMIT textureChanged();
728}
729
730QT_END_NAMESPACE
\qmltype Shader \inherits QtObject \inqmlmodule QtQuick3D
ResolveFunction resolveShaderOverride
QSSGRenderShaderValue::Type uniformType(QMetaType type)
QByteArray uniformTypeName(QMetaType type)
bool(*)(const QUrl &url, const QQmlContext *context, QByteArray &shaderData, QByteArray &shaderPathKey) ResolveFunction
static constexpr QMetaType::Type qssg_metatype_list[]
QByteArray resolveShader(const QUrl &fileUrl, const QQmlContext *context, QByteArray &shaderPathKey)
MetaTypeList supportedMetatypes()
void setResolveFunction(ResolveFunction fn)