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// Qt-Security score:significant reason:default
4
5
7
8#include <QtCore/qfile.h>
9#include <QtQml/qqmlcontext.h>
10#include <QtQml/qqmlfile.h>
11
16#include <ssg/qssgrenderextensions.h>
17#include <ssg/qquick3dextensionhelpers.h>
18
19#include <QtQuick3DRuntimeRender/private/qssgrenderimage_p.h>
20
21#include <QtCore/QLoggingCategory>
22
24
25Q_LOGGING_CATEGORY(lcSubRenderPass, "qt.quick3d.subrenderpass")
26
27/*!
28 \qmltype Shader
29 \inherits QtObject
30 \inqmlmodule QtQuick3D
31 \brief Container component for defining shader code used by post-processing effects.
32
33 The Shader type is used for populating the \l{Pass::shaders}{shaders} list in the
34 render \l{Pass}{pass} of an \l Effect.
35
36 A shader is code which is executed directly on the graphic hardware at a particular
37 \l{Shader::stage}{stage} of the rendering pipeline.
38
39 \sa Effect
40*/
41/*!
42 \qmlproperty url Shader::shader
43 Specifies the name of the shader source file. For details on how to write shader code,
44 see the \l Effect documentation.
45
46 \warning Shader snippets are assumed to be trusted content. Application
47 developers are advised to carefully consider the potential implications
48 before allowing the loading of user-provided content that is not part of the
49 application.
50*/
51/*!
52 \qmlproperty enumeration Shader::stage
53 Specifies the stage of the rendering pipeline when the shader code will be executed.
54 The default is \c Shader.Fragment
55
56 \value Shader.Vertex The shader is a vertex shader. This code is run once per vertex
57 in the input geometry and can be used to modify it before the geometry is rasterized
58 (scan converted). In the case of effects, the input geometry is always a quad (four
59 vertexes representing the corners of the render target).
60 \value Shader.Fragment The shader is a fragment shader. After vertex processing,
61 the modified geometry is turned into fragments (rasterization). Then a fragment shader
62 is executed for each fragment, assigning a color to it. Fragments are a related concept
63 to pixels, but with additional information attached. Also, as a result of some
64 anti-aliasing strategies, there may be more than one fragment for each pixel in the
65 output.
66*/
67
68/*!
69 \qmltype TextureInput
70 \inherits QtObject
71 \inqmlmodule QtQuick3D
72 \brief Specifies a texture exposed to the shaders of a CustomMaterial or Effect.
73
74 This is a type which can be used for exposing a \l Texture to a shader, either
75 in the \l{Pass}{render pass} of an \l Effect, or in a \l CustomMaterial. It exists
76 primarily to assign a local name to the \l Texture that can be referenced from
77 shaders.
78
79 When a TextureInput property is declared in an \l Effect or a \l CustomMaterial,
80 it will automatically be available as a sampler in all shaders by its property
81 name.
82*/
83/*!
84 \qmlproperty Texture TextureInput::texture
85 The texture for which this TextureInput serves as an indirection.
86*/
87/*!
88 \qmlproperty bool TextureInput::enabled
89 The property determines if this TextureInput is enabled. The default value
90 is true. When disabled, the shaders of the effect sample a dummy, opaque
91 black texture instead of the one specified by \l texture.
92*/
93
94/*!
95 \qmltype Pass
96 \inherits QtObject
97 \inqmlmodule QtQuick3D
98 \brief Defines a render pass in an Effect.
99
100 An \l Effect may consist of multiple render passes. Each render pass has a
101 setup phase where the list of \l{Pass::commands}{render commands} are executed,
102 a \l{Pass::output}{output buffer} and a list of \l{Pass::shaders}{shaders} to
103 use for rendering the effect.
104
105 See the documentation for \l Effect for more details on how to set up multiple
106 rendering passes.
107*/
108/*!
109 \qmlproperty Buffer Pass::output
110 Specifies the output \l {Buffer}{buffer} of the pass.
111*/
112/*!
113 \qmlproperty list Pass::commands
114 Specifies the list of render \l {Command}{commands} of the pass.
115*/
116/*!
117 \qmlproperty list Pass::shaders
118 Specifies the list of \l {Shader}{shaders} of the pass.
119*/
120
121/*!
122 \qmltype Command
123 \inherits QtObject
124 \inqmlmodule QtQuick3D
125 \brief Supertype of commands to be performed as part of a pass in an Effect.
126
127 The Command type should not be instantiated by itself, but only exists as a
128 polymorphic supertype for the different actions that can be performed as part
129 of a \l{Pass}{render pass}.
130
131 \sa BufferInput, SetUniformValue, Effect
132*/
133
134/*!
135 \qmltype BufferInput
136 \inherits Command
137 \inqmlmodule QtQuick3D
138 \brief Defines an input buffer to be used as input for a pass of an Effect.
139
140 BufferInput is a \l Command which can be added to the list of commands in the \l Pass of
141 an \l Effect. When executed, it will expose the buffer as a sample to the shaders
142 in the render pass. The shaders must declare a sampler with the name given in the
143 BufferInput's \c sampler property.
144
145 This can be used for sharing intermediate results between the different passes of an
146 effect.
147
148 \sa TextureInput
149*/
150/*!
151 \qmlproperty Buffer BufferInput::buffer
152 Specifies the \l {Buffer}{buffer} which should be exposed to the shader.
153*/
154/*!
155 \qmlproperty string BufferInput::sampler
156 Specifies the name under which the buffer is exposed to the shader.
157 When this property is not set, the buffer is exposed with the built-in name \c INPUT.
158*/
159
160/*!
161 \qmltype Buffer
162 \inherits QtObject
163 \inqmlmodule QtQuick3D
164 \brief Creates or references a color buffer to be used for a pass of an Effect.
165
166 A Buffer can be used to create intermediate buffers to share data between
167 \l{Pass}{render passes} in an \l Effect.
168
169 \note If the \l name property of the Buffer is empty, it will reference the
170 default output texture of the render pass.
171*/
172/*!
173 \qmlproperty enumeration Buffer::format
174 Specifies the texture format. The default value is Buffer.RGBA8.
175
176 \value Buffer.RGBA8
177 \value Buffer.RGBA16F
178 \value Buffer.RGBA32F
179 \value Buffer.R8
180 \value Buffer.R16
181 \value Buffer.R16F
182 \value Buffer.R32F
183*/
184/*!
185 \qmlproperty enumeration Buffer::textureFilterOperation
186 Specifies the texture filtering mode when sampling the contents of the
187 Buffer. The default value is Buffer.Linear.
188
189 \value Buffer.Nearest Use nearest-neighbor filtering.
190 \value Buffer.Linear Use linear filtering.
191*/
192/*!
193 \qmlproperty enumeration Buffer::textureCoordOperation
194 Specifies the behavior for texture coordinates when sampling outside the [0, 1] range.
195 The default is Buffer.ClampToEdge.
196
197 \value Buffer.ClampToEdge Clamp coordinates to the edges.
198 \value Buffer.Repeat Wrap the coordinates at the edges to tile the texture.
199 \value Buffer.MirroredRepeat Wrap the coordinate at the edges, but mirror the texture
200 when tiling it.
201*/
202/*!
203 \qmlproperty real Buffer::sizeMultiplier
204 Specifies the size multiplier of the buffer. For instance, a value of \c 1.0 creates
205 a buffer with the same size as the effect's input texture while \c 0.5 creates buffer
206 where both width and height is half as big. The default value is 1.0.
207*/
208/*!
209 \qmlproperty enumeration Buffer::bufferFlags
210 Specifies the buffer allocation flags. The default is Buffer.None.
211
212 \value Buffer.None No special behavior.
213 \value Buffer.SceneLifetime The buffer is allocated for the whole lifetime of the scene.
214*/
215/*!
216 \qmlproperty string Buffer::name
217 Specifies the name of the buffer.
218
219 \note When this property is empty, the Buffer will refer to the default output texture
220 of the \l{Pass}{render pass} instead of allocating a buffer. This can be useful to
221 override certain settings of the output, such as the texture format, without introducing
222 a new, separate intermediate texture.
223*/
224
225/*!
226 \qmltype SetUniformValue
227 \inherits Command
228 \inqmlmodule QtQuick3D
229 \brief Defines a value to be set during a single \l {Pass}{pass}.
230 \since 5.15
231
232 SetUniformValue is a \l Command which can be added to the list of commands in a \l Pass. When
233 executed, it will set the uniform given by the \l{SetUniformValue::target}{target} property
234 to \l{SetUniformValue::value}{value}.
235
236 \note The value set by this command is will only be set during the \l {Pass}{pass} it occurs in.
237 For consecutive passes the value will be revert to the initial value of the uniform as it
238 was defined in the \l Effect item.
239
240 \sa BufferInput
241*/
242/*!
243 \qmlproperty string SetUniformValue::target
244 Specifies the name of the uniform that will have its value changed during the \l {Pass}{pass}.
245 This must match the name of an existing property in the \l Effect.
246*/
247/*!
248 \qmlproperty Variant SetUniformValue::value
249 Specifies the value that will be set on the \c target uniform.
250*/
251
252/*!
253 \qmltype renderTargetBlend
254 \inqmlmodule QtQuick3D
255 \brief Defines blending parameters for a single color attachment of a render pass.
256 \since 6.11
257
258 The renderTargetBlend type is used to specify blending parameters for a single
259 color attachment of a \l RenderPass. An instance of renderTargetBlend can be
260 assigned to one of the \c PipelineStateOverride::targetBlendN properties, where N
261 is the index of the color attachment to configure.
262
263 \qmlproperty bool renderTargetBlend::blendEnabled
264 If set to true, enables blending for the color attachment. If set to false,
265 disables blending.
266
267 \qmlproperty enumeration renderTargetBlend::colorWrite
268 Sets the color channels that will be written to the color attachment.
269 \value renderTargetBlend.R
270 \value renderTargetBlend.G
271 \value renderTargetBlend.B
272 \value renderTargetBlend.A
273
274 \qmlproperty enumeration renderTargetBlend::srcColor
275 Sets the source color blend factor for the color attachment.
276 \value renderTargetBlend.Zero
277 \value renderTargetBlend.One
278 \value renderTargetBlend.SrcColor
279 \value renderTargetBlend.OneMinusSrcColor
280 \value renderTargetBlend.DstColor
281 \value renderTargetBlend.OneMinusDstColor
282 \value renderTargetBlend.SrcAlpha
283 \value renderTargetBlend.OneMinusSrcAlpha
284 \value renderTargetBlend.DstAlpha
285 \value renderTargetBlend.OneMinusDstAlpha
286 \value renderTargetBlend.ConstantColor
287 \value renderTargetBlend.OneMinusConstantColor
288 \value renderTargetBlend.ConstantAlpha
289 \value renderTargetBlend.OneMinusConstantAlpha
290 \value renderTargetBlend.SrcAlphaSaturate
291 \value renderTargetBlend.Src1Color
292 \value renderTargetBlend.OneMinusSrc1Color
293 \value renderTargetBlend.Src1Alpha
294 \value renderTargetBlend.OneMinusSrc1Alpha
295
296 \qmlproperty enumeration renderTargetBlend::dstColor
297 Sets the destination color blend factor for the color attachment.
298 \value renderTargetBlend.Zero
299 \value renderTargetBlend.One
300 \value renderTargetBlend.SrcColor
301 \value renderTargetBlend.OneMinusSrcColor
302 \value renderTargetBlend.DstColor
303 \value renderTargetBlend.OneMinusDstColor
304 \value renderTargetBlend.SrcAlpha
305 \value renderTargetBlend.OneMinusSrcAlpha
306 \value renderTargetBlend.DstAlpha
307 \value renderTargetBlend.OneMinusDstAlpha
308 \value renderTargetBlend.ConstantColor
309 \value renderTargetBlend.OneMinusConstantColor
310 \value renderTargetBlend.ConstantAlpha
311 \value renderTargetBlend.OneMinusConstantAlpha
312 \value renderTargetBlend.SrcAlphaSaturate
313 \value renderTargetBlend.Src1Color
314 \value renderTargetBlend.OneMinusSrc1Color
315 \value renderTargetBlend.Src1Alpha
316 \value renderTargetBlend.OneMinusSrc1Alpha
317
318 \qmlproperty enumeration renderTargetBlend::opColor
319 Sets the color blend operation for the color attachment.
320 \value renderTargetBlend.Add
321 \value renderTargetBlend.Subtract
322 \value renderTargetBlend.ReverseSubtract
323 \value renderTargetBlend.Min
324 \value renderTargetBlend.Max
325
326 \qmlproperty enumeration renderTargetBlend::srcAlpha
327 Sets the source alpha blend factor for the color attachment.
328 \value renderTargetBlend.Zero
329 \value renderTargetBlend.One
330 \value renderTargetBlend.SrcColor
331 \value renderTargetBlend.OneMinusSrcColor
332 \value renderTargetBlend.DstColor
333 \value renderTargetBlend.OneMinusDstColor
334 \value renderTargetBlend.SrcAlpha
335 \value renderTargetBlend.OneMinusSrcAlpha
336 \value renderTargetBlend.DstAlpha
337 \value renderTargetBlend.OneMinusDstAlpha
338 \value renderTargetBlend.ConstantColor
339 \value renderTargetBlend.OneMinusConstantColor
340 \value renderTargetBlend.ConstantAlpha
341 \value renderTargetBlend.OneMinusConstantAlpha
342 \value renderTargetBlend.SrcAlphaSaturate
343 \value renderTargetBlend.Src1Color
344 \value renderTargetBlend.OneMinusSrc1Color
345 \value renderTargetBlend.Src1Alpha
346 \value renderTargetBlend.OneMinusSrc1Alpha
347
348 \qmlproperty enumeration renderTargetBlend::dstAlpha
349 Sets the destination alpha blend factor for the color attachment.
350 \value renderTargetBlend.Zero
351 \value renderTargetBlend.One
352 \value renderTargetBlend.SrcColor
353 \value renderTargetBlend.OneMinusSrcColor
354 \value renderTargetBlend.DstColor
355 \value renderTargetBlend.OneMinusDstColor
356 \value renderTargetBlend.SrcAlpha
357 \value renderTargetBlend.OneMinusSrcAlpha
358 \value renderTargetBlend.DstAlpha
359 \value renderTargetBlend.OneMinusDstAlpha
360 \value renderTargetBlend.ConstantColor
361 \value renderTargetBlend.OneMinusConstantColor
362 \value renderTargetBlend.ConstantAlpha
363 \value renderTargetBlend.OneMinusConstantAlpha
364 \value renderTargetBlend.SrcAlphaSaturate
365 \value renderTargetBlend.Src1Color
366 \value renderTargetBlend.OneMinusSrc1Color
367 \value renderTargetBlend.Src1Alpha
368 \value renderTargetBlend.OneMinusSrc1Alpha
369
370 \qmlproperty enumeration renderTargetBlend::opAlpha
371 Sets the alpha blend operation for the color attachment.
372 \value renderTargetBlend.Add
373 \value renderTargetBlend.Subtract
374 \value renderTargetBlend.ReverseSubtract
375 \value renderTargetBlend.Min
376 \value renderTargetBlend.Max
377 */
378
379/*!
380 \qmltype PipelineStateOverride
381 \inherits Command
382 \inqmlmodule QtQuick3D
383 \brief Defines pipeline state overrides for a single \l {RenderPass}{pass}.
384 \since 6.11
385
386 PipelineStateOverride is a \l Command which can be added to the list of commands in a \l RenderPass.
387 When executed, it will override the pipeline state in the render pass according to the properties set on
388 the PipelineStateOverride. Only values that are set will override the existing pipeline state's values.
389 If you want to reset a value that has been overriden to the default, then make sure to set the property
390 to \c undefined.
391
392
393 \qmlproperty bool PipelineStateOverride::depthTestEnabled
394 If set to true, enables depth testing for the render pass. If set to false, disables depth testing.
395 Setting this property to true requires a depth attachment for the render pass.
396
397 \qmlproperty bool PipelineStateOverride::depthWriteEnabled
398 If set to true, enables depth writing for the render pass. If set to false, disables depth writing.
399 Setting this property to true requires a depth attachment for the render pass.
400
401 \qmlproperty bool PipelineStateOverride::blendEnabled
402 If set to true, enables blending for the render pass. If set to false, disables blending.
403
404 \qmlproperty bool PipelineStateOverride::usesStencilReference
405 If set to true, enables the use of stencil reference value for the render pass. If set to false,
406 disables the use of stencil reference value.
407
408 \qmlproperty bool PipelineStateOverride::usesScissor
409 If set to true, enables the use of scissor test for the render pass. If set to false,
410 disables the use of scissor test.
411
412 \qmlproperty enumeration PipelineStateOverride::depthFunction
413 Sets the depth comparison function for the render pass.
414 \value PipelineStateOverride.Never
415 \value PipelineStateOverride.Less
416 \value PipelineStateOverride.Equal
417 \value PipelineStateOverride.LessOrEqual
418 \value PipelineStateOverride.Greater
419 \value PipelineStateOverride.NotEqual
420 \value PipelineStateOverride.GreaterOrEqual
421 \value PipelineStateOverride.Always
422
423 \qmlproperty enumeration PipelineStateOverride::cullMode
424 Sets the face culling mode for the render pass.
425 \value PipelineStateOverride.None
426 \value PipelineStateOverride.Front
427 \value PipelineStateOverride.Back
428
429 \qmlproperty enumeration PipelineStateOverride::polygonMode
430 Sets the polygon rasterization mode for the render pass.
431 \value PipelineStateOverride.Fill
432 \value PipelineStateOverride.Line
433
434 \qmlproperty uint PipelineStateOverride::stencilWriteMask
435 Sets the stencil write mask for the render pass.
436
437 \qmlproperty uint PipelineStateOverride::stencilReference
438 Sets the stencil reference value for the render pass.
439
440 \qmlproperty Rectangle PipelineStateOverride::viewport
441 Sets the viewport rectangle for the render pass.
442
443 \qmlproperty Rectangle PipelineStateOverride::scissor
444 Sets the scissor rectangle for the render pass.
445
446 \qmlproperty TargetBlend PipelineStateOverride::targetBlend0
447 Sets the blending parameters for color attachment 0 of the render pass.
448
449 \qmlproperty TargetBlend PipelineStateOverride::targetBlend1
450 Sets the blending parameters for color attachment 1 of the render pass.
451
452 \qmlproperty TargetBlend PipelineStateOverride::targetBlend2
453 Sets the blending parameters for color attachment 2 of the render pass.
454
455 \qmlproperty TargetBlend PipelineStateOverride::targetBlend3
456 Sets the blending parameters for color attachment 3 of the render pass.
457
458 \qmlproperty TargetBlend PipelineStateOverride::targetBlend4
459 Sets the blending parameters for color attachment 4 of the render pass.
460
461 \qmlproperty TargetBlend PipelineStateOverride::targetBlend5
462 Sets the blending parameters for color attachment 5 of the render pass.
463
464 \qmlproperty TargetBlend PipelineStateOverride::targetBlend6
465 Sets the blending parameters for color attachment 6 of the render pass.
466
467 \qmlproperty TargetBlend PipelineStateOverride::targetBlend7
468 Sets the blending parameters for color attachment 7 of the render pass.
469*/
470
471/*!
472 \qmltype DepthStencilAttachment
473 \inherits Command
474 \inqmlmodule QtQuick3D
475 \brief Defines a depth-stencil attachment for a RenderPass.
476 \since 6.11
477
478 The DepthStencilAttachment type is used to specify a depth-stencil attachment
479 for a \l RenderPass. This represents a render buffer attachment, so it cannot be
480 directly sampled in shaders.
481*/
482
483
485
487
492
493QByteArray resolveShader(const QUrl &fileUrl, const QQmlContext *context, QByteArray &shaderPathKey)
494{
496 QByteArray shaderData;
497 if (resolveShaderOverride(fileUrl, context, shaderData, shaderPathKey))
498 return shaderData;
499 }
500
501 if (!shaderPathKey.isEmpty())
502 shaderPathKey.append('>');
503
504 const QUrl loadUrl = context ? context->resolvedUrl(fileUrl) : fileUrl;
505 const QString filePath = QQmlFile::urlToLocalFileOrQrc(loadUrl);
506
507 QFile f(filePath);
508 if (f.open(QIODevice::ReadOnly | QIODevice::Text)) {
509 shaderPathKey += loadUrl.fileName().toUtf8();
510 return f.readAll();
511 } else {
512 qWarning("Failed to read shader code from %s", qPrintable(filePath));
513 }
514
515 return QByteArray();
516}
517
518// These are the QMetaTypes that we convert into uniforms.
536
537template<>
539{
541 static QByteArray name() { return QByteArrayLiteral("float"); }
542};
543
544template<>
546{
548 static QByteArray name() { return QByteArrayLiteral("bool"); }
549};
550
551template<>
553{
555 static QByteArray name() { return QByteArrayLiteral("int"); }
556};
557
558template<>
560{
562 static QByteArray name() { return QByteArrayLiteral("vec2"); }
563};
564
565template<>
567{
569 static QByteArray name() { return QByteArrayLiteral("vec3"); }
570};
571
572template<>
574{
576 static QByteArray name() { return QByteArrayLiteral("vec4"); }
577};
578
579template<>
581{
583 static QByteArray name() { return QByteArrayLiteral("vec4"); }
584};
585
586template<>
588{
590 static QByteArray name() { return QByteArrayLiteral("vec2"); }
591};
592
593template<>
595{
597 static QByteArray name() { return QByteArrayLiteral("vec2"); }
598};
599
600template<>
602{
604 static QByteArray name() { return QByteArrayLiteral("vec2"); }
605};
606
607template<>
609{
611 static QByteArray name() { return QByteArrayLiteral("vec2"); }
612};
613
614template<>
616{
618 static QByteArray name() { return QByteArrayLiteral("vec4"); }
619};
620
621template<>
623{
625 static QByteArray name() { return QByteArrayLiteral("vec4"); }
626};
627
628template<>
630{
632 static QByteArray name() { return QByteArrayLiteral("vec4"); }
633};
634
635template<>
637{
639 static QByteArray name() { return QByteArrayLiteral("mat4"); }
640};
641
643{
644 switch (type.id()) {
645 case QMetaType::Double:
646 case QMetaType::Float:
647 return ShaderType<QMetaType::Double>::name();
648 case QMetaType::Bool:
649 return ShaderType<QMetaType::Bool>::name();
650 case QMetaType::QVector2D:
651 return ShaderType<QMetaType::QVector2D>::name();
652 case QMetaType::QVector3D:
653 return ShaderType<QMetaType::QVector3D>::name();
654 case QMetaType::QVector4D:
655 return ShaderType<QMetaType::QVector4D>::name();
656 case QMetaType::Int:
657 return ShaderType<QMetaType::Int>::name();
658 case QMetaType::QColor:
659 return ShaderType<QMetaType::QColor>::name();
660 case QMetaType::QSize:
661 return ShaderType<QMetaType::QSize>::name();
662 case QMetaType::QSizeF:
663 return ShaderType<QMetaType::QSizeF>::name();
664 case QMetaType::QPoint:
665 return ShaderType<QMetaType::QPoint>::name();
666 case QMetaType::QPointF:
667 return ShaderType<QMetaType::QPointF>::name();
668 case QMetaType::QRect:
669 return ShaderType<QMetaType::QRect>::name();
670 case QMetaType::QRectF:
671 return ShaderType<QMetaType::QRectF>::name();
672 case QMetaType::QQuaternion:
673 return ShaderType<QMetaType::QQuaternion>::name();
674 case QMetaType::QMatrix4x4:
675 return ShaderType<QMetaType::QMatrix4x4>::name();
676 default:
677 return QByteArray();
678 }
679}
680
681QByteArray uniformTypeName(QSSGRenderShaderValue::Type type)
682{
683 switch (type) {
684 case QSSGRenderShaderValue::Float:
685 return ShaderType<QMetaType::Double>::name();
686 case QSSGRenderShaderValue::Boolean:
687 return ShaderType<QMetaType::Bool>::name();
688 case QSSGRenderShaderValue::Integer:
689 return ShaderType<QMetaType::Int>::name();
690 case QSSGRenderShaderValue::Vec2:
691 return ShaderType<QMetaType::QVector2D>::name();
692 case QSSGRenderShaderValue::Vec3:
693 return ShaderType<QMetaType::QVector3D>::name();
694 case QSSGRenderShaderValue::Vec4:
695 return ShaderType<QMetaType::QVector4D>::name();
696 case QSSGRenderShaderValue::Rgba:
697 return ShaderType<QMetaType::QColor>::name();
698 case QSSGRenderShaderValue::Size:
699 return ShaderType<QMetaType::QSize>::name();
700 case QSSGRenderShaderValue::SizeF:
701 return ShaderType<QMetaType::QSizeF>::name();
702 case QSSGRenderShaderValue::Point:
703 return ShaderType<QMetaType::QPoint>::name();
704 case QSSGRenderShaderValue::PointF:
705 return ShaderType<QMetaType::QPointF>::name();
706 case QSSGRenderShaderValue::Rect:
707 return ShaderType<QMetaType::QRect>::name();
708 case QSSGRenderShaderValue::RectF:
709 return ShaderType<QMetaType::QRectF>::name();
710 case QSSGRenderShaderValue::Quaternion:
711 return ShaderType<QMetaType::QQuaternion>::name();
712 case QSSGRenderShaderValue::Matrix4x4:
713 return ShaderType<QMetaType::QMatrix4x4>::name();
714 default:
715 return QByteArray();
716 }
717}
718
720{
721 switch (type.id()) {
722 case QMetaType::Double:
723 case QMetaType::Float:
724 return ShaderType<QMetaType::Double>::type();
725 case QMetaType::Bool:
726 return ShaderType<QMetaType::Bool>::type();
727 case QMetaType::QVector2D:
728 return ShaderType<QMetaType::QVector2D>::type();
729 case QMetaType::QVector3D:
730 return ShaderType<QMetaType::QVector3D>::type();
731 case QMetaType::QVector4D:
732 return ShaderType<QMetaType::QVector4D>::type();
733 case QMetaType::Int:
734 return ShaderType<QMetaType::Int>::type();
735 case QMetaType::QColor:
736 return ShaderType<QMetaType::QColor>::type();
737 case QMetaType::QSize:
738 return ShaderType<QMetaType::QSize>::type();
739 case QMetaType::QSizeF:
740 return ShaderType<QMetaType::QSizeF>::type();
741 case QMetaType::QPoint:
742 return ShaderType<QMetaType::QPoint>::type();
743 case QMetaType::QPointF:
744 return ShaderType<QMetaType::QPointF>::type();
745 case QMetaType::QRect:
746 return ShaderType<QMetaType::QRect>::type();
747 case QMetaType::QRectF:
748 return ShaderType<QMetaType::QRectF>::type();
749 case QMetaType::QQuaternion:
750 return ShaderType<QMetaType::QQuaternion>::type();
751 case QMetaType::QMatrix4x4:
752 return ShaderType<QMetaType::QMatrix4x4>::type();
753 default:
754 return QSSGRenderShaderValue::Unknown;
755 }
756}
757
759{
760 return {std::begin(qssg_metatype_list), std::end(qssg_metatype_list)};
761}
762
763}
764
765QQuick3DShaderUtilsBuffer::TextureFormat QQuick3DShaderUtilsBuffer::mapRenderTextureFormat(QSSGRenderTextureFormat::Format fmt)
766{
767 using TextureFormat = QQuick3DShaderUtilsBuffer::TextureFormat;
768 switch (fmt) {
769 case QSSGRenderTextureFormat::RGBA8: return TextureFormat::RGBA8;
770 case QSSGRenderTextureFormat::RGBA16F: return TextureFormat::RGBA16F;
771 case QSSGRenderTextureFormat::RGBA32F: return TextureFormat::RGBA32F;
772 case QSSGRenderTextureFormat::R8: return TextureFormat::R8;
773 case QSSGRenderTextureFormat::R16: return TextureFormat::R16;
774 case QSSGRenderTextureFormat::R16F: return TextureFormat::R16F;
775 case QSSGRenderTextureFormat::R32F: return TextureFormat::R32F;
776 default:
777 break;
778 }
779 return TextureFormat::Unknown;
780}
781
782QSSGRenderTextureFormat::Format QQuick3DShaderUtilsBuffer::mapTextureFormat(QQuick3DShaderUtilsBuffer::TextureFormat fmt)
783{
784 using TextureFormat = QQuick3DShaderUtilsBuffer::TextureFormat;
785 switch (fmt) {
786 case TextureFormat::RGBA8: return QSSGRenderTextureFormat::RGBA8;
787 case TextureFormat::RGBA16F: return QSSGRenderTextureFormat::RGBA16F;
788 case TextureFormat::RGBA32F: return QSSGRenderTextureFormat::RGBA32F;
789 case TextureFormat::R8: return QSSGRenderTextureFormat::R8;
790 case TextureFormat::R16: return QSSGRenderTextureFormat::R16;
791 case TextureFormat::R16F: return QSSGRenderTextureFormat::R16F;
792 case TextureFormat::R32F: return QSSGRenderTextureFormat::R32F;
793 default:
794 break;
795 }
796 return QSSGRenderTextureFormat::Unknown;
797}
798
799QQuick3DShaderUtilsBuffer::TextureFormat QQuick3DShaderUtilsBuffer::format() const
800{
801 return mapRenderTextureFormat(command.m_format.format);
802}
803
804void QQuick3DShaderUtilsBuffer::setFormat(TextureFormat format)
805{
806 QSSGRenderTextureFormat::Format mappedTextureFormat = mapTextureFormat(format);
807 if (command.m_format == mappedTextureFormat)
808 return;
809
810 command.m_format = mappedTextureFormat;
811 emit changed();
812}
813
814void QQuick3DShaderUtilsBuffer::setTextureFilterOperation(TextureFilterOperation op)
815{
816 if (command.m_filterOp == QSSGRenderTextureFilterOp(op))
817 return;
818
819 command.m_filterOp = QSSGRenderTextureFilterOp(op);
820 emit changed();
821}
822
823void QQuick3DShaderUtilsBuffer::setTextureCoordOperation(TextureCoordOperation texCoordOp)
824{
825 if (command.m_texCoordOp == QSSGRenderTextureCoordOp(texCoordOp))
826 return;
827
828 command.m_texCoordOp = QSSGRenderTextureCoordOp(texCoordOp);
829 emit changed();
830}
831
832void QQuick3DShaderUtilsBuffer::setBufferFlags(AllocateBufferFlagValues flag)
833{
834 if (quint32(command.m_bufferFlags) == quint32(flag))
835 return;
836
837 command.m_bufferFlags = quint32(flag);
838 emit changed();
839}
840
841QQuick3DShaderUtilsRenderPass::~QQuick3DShaderUtilsRenderPass()
842{
843
844}
845
846void QQuick3DShaderUtilsRenderPass::qmlAppendCommand(QQmlListProperty<QQuick3DShaderUtilsRenderCommand> *list,
847 QQuick3DShaderUtilsRenderCommand *command)
848{
849 if (!command)
850 return;
851
852 QQuick3DShaderUtilsRenderPass *that = qobject_cast<QQuick3DShaderUtilsRenderPass *>(list->object);
853 that->m_commands.push_back(command);
854 emit that->changed();
855}
856
857QQuick3DShaderUtilsRenderCommand *QQuick3DShaderUtilsRenderPass::qmlCommandAt(QQmlListProperty<QQuick3DShaderUtilsRenderCommand> *list,
858 qsizetype index)
859{
860 QQuick3DShaderUtilsRenderPass *that = qobject_cast<QQuick3DShaderUtilsRenderPass *>(list->object);
861 return that->m_commands.at(index);
862}
863
864qsizetype QQuick3DShaderUtilsRenderPass::qmlCommandCount(QQmlListProperty<QQuick3DShaderUtilsRenderCommand> *list)
865{
866 QQuick3DShaderUtilsRenderPass *that = qobject_cast<QQuick3DShaderUtilsRenderPass *>(list->object);
867 return that->m_commands.size();
868}
869
870void QQuick3DShaderUtilsRenderPass::qmlCommandClear(QQmlListProperty<QQuick3DShaderUtilsRenderCommand> *list)
871{
872 QQuick3DShaderUtilsRenderPass *that = qobject_cast<QQuick3DShaderUtilsRenderPass *>(list->object);
873 that->m_commands.clear();
874 emit that->changed();
875}
876
877QQmlListProperty<QQuick3DShaderUtilsRenderCommand> QQuick3DShaderUtilsRenderPass::commands()
878{
879 return QQmlListProperty<QQuick3DShaderUtilsRenderCommand>(this,
880 nullptr,
881 QQuick3DShaderUtilsRenderPass::qmlAppendCommand,
882 QQuick3DShaderUtilsRenderPass::qmlCommandCount,
883 QQuick3DShaderUtilsRenderPass::qmlCommandAt,
884 QQuick3DShaderUtilsRenderPass::qmlCommandClear);
885}
886
887void QQuick3DShaderUtilsRenderPass::qmlAppendShader(QQmlListProperty<QQuick3DShaderUtilsShader> *list,
888 QQuick3DShaderUtilsShader *shader)
889{
890 if (!shader)
891 return;
892
893 QQuick3DShaderUtilsRenderPass *that = qobject_cast<QQuick3DShaderUtilsRenderPass *>(list->object);
894
895 // An append implementation CANNOT rely on the object (shader in this case)
896 // being complete. When the list references a Shader object living under
897 // another Effect, its properties may not be set at the point of this
898 // function being called, so accessing shader->stage is not allowed since
899 // it may still have its default value, not what is set from QML...
900
901 // the only thing we can do is to append to our list, do not try to be clever
902 that->m_shaders.append(shader);
903
904 connect(shader, &QQuick3DShaderUtilsShader::shaderChanged, that, &QQuick3DShaderUtilsRenderPass::changed);
905 connect(shader, &QQuick3DShaderUtilsShader::stageChanged, that, &QQuick3DShaderUtilsRenderPass::changed);
906
907 emit that->changed();
908}
909
910QQuick3DShaderUtilsShader *QQuick3DShaderUtilsRenderPass::qmlShaderAt(QQmlListProperty<QQuick3DShaderUtilsShader> *list,
911 qsizetype index)
912{
913 QQuick3DShaderUtilsRenderPass *that = qobject_cast<QQuick3DShaderUtilsRenderPass *>(list->object);
914 return that->m_shaders.at(index);
915}
916
917qsizetype QQuick3DShaderUtilsRenderPass::qmlShaderCount(QQmlListProperty<QQuick3DShaderUtilsShader> *list)
918{
919 QQuick3DShaderUtilsRenderPass *that = qobject_cast<QQuick3DShaderUtilsRenderPass *>(list->object);
920 return that->m_shaders.size();
921}
922
923void QQuick3DShaderUtilsRenderPass::qmlShaderClear(QQmlListProperty<QQuick3DShaderUtilsShader> *list)
924{
925 QQuick3DShaderUtilsRenderPass *that = qobject_cast<QQuick3DShaderUtilsRenderPass *>(list->object);
926
927 for (QQuick3DShaderUtilsShader *shader : that->m_shaders)
928 shader->disconnect(that);
929
930 that->m_shaders.clear();
931
932 emit that->changed();
933}
934
935QQmlListProperty<QQuick3DShaderUtilsShader> QQuick3DShaderUtilsRenderPass::shaders()
936{
937 return QQmlListProperty<QQuick3DShaderUtilsShader>(this,
938 nullptr,
939 QQuick3DShaderUtilsRenderPass::qmlAppendShader,
940 QQuick3DShaderUtilsRenderPass::qmlShaderCount,
941 QQuick3DShaderUtilsRenderPass::qmlShaderAt,
942 QQuick3DShaderUtilsRenderPass::qmlShaderClear);
943}
944
945QQuick3DShaderUtilsTextureInput::QQuick3DShaderUtilsTextureInput(QQuick3DObject *p) : QQuick3DObject(p) {}
946
947QQuick3DShaderUtilsTextureInput::~QQuick3DShaderUtilsTextureInput()
948{
949}
950
951void QQuick3DShaderUtilsTextureInput::setTexture(QQuick3DTexture *texture)
952{
953 if (m_texture == texture)
954 return;
955
956 QObject *p = parent();
957 while (p != nullptr) {
958 if (QQuick3DCustomMaterial *mat = qobject_cast<QQuick3DCustomMaterial *>(p)) {
959 mat->setDynamicTextureMap(this);
960 QQuick3DObjectPrivate::attachWatcherPriv(mat, this, &QQuick3DShaderUtilsTextureInput::setTexture, texture, m_texture);
961 break;
962 } else if (QQuick3DEffect *efx = qobject_cast<QQuick3DEffect *>(p)) {
963 efx->setDynamicTextureMap(this);
964 QQuick3DObjectPrivate::attachWatcherPriv(efx, this, &QQuick3DShaderUtilsTextureInput::setTexture, texture, m_texture);
965 break;
966 }
967 p = p->parent();
968 }
969
970 if (p == nullptr) {
971 qWarning("A TextureInput was defined without a CustomMaterial or Effect ancestor. This should be avoided.");
972 }
973
974 m_texture = texture;
975 Q_EMIT textureChanged();
976}
977
978/*!
979 \qmltype RenderablesFilter
980 \inherits Command
981 \inqmlmodule QtQuick3D
982 \brief Defines a filter for selecting which renderables to affect in a \l {RenderPass}{pass}.
983 \since 6.11
984
985 The RenderablesFilter type is used to specify which renderables in the scene
986 should be affected by a \l RenderPass. By setting the \c renderableTypes property,
987 you can control whether the pass affects Opaque, Transparent, or no objects at all.
988
989 Setting \c renderableTypes to \c None is useful when a RenderPass acts as a container
990 for SubRenderPasses and should not render any objects itself.
991
992 In addition to filtering by renderable types, you can also use the \l{RenderablesFilter::layerMask}{layerMask}
993 to further refine which renderables are affected based on their assigned \l{QtQuick3D::Node::layers}{layers}.
994*/
995
996/*!
997 \qmlproperty int RenderablesFilter::layerMask
998 Sets the layer mask for the filter. Only renderables on the specified layers will be affected by the filter.
999
1000 \sa l{QtQuick3D::Node::layers}
1001*/
1002
1003/*!
1004 \qmlproperty enumeration RenderablesFilter::renderableTypes
1005 Sets the types of renderables that the filter will affect.
1006
1007 \value RenderablesFilter.None No renderables will be rendered. Useful for container passes that only have SubRenderPasses.
1008 \value RenderablesFilter.Opaque Only opaque renderables will be rendered.
1009 \value RenderablesFilter.Transparent Only transparent renderables will be rendered.
1010
1011 \note Multiple values can be combined using the | operator.
1012
1013 \default RenderablesFilter.Opaque | RenderablesFilter.Transparent
1014*/
1015QQuick3DShaderUtilsRenderablesFilter::RenderableTypes QQuick3DShaderUtilsRenderablesFilter::renderableTypes() const
1016{
1017 return static_cast<QQuick3DShaderUtilsRenderablesFilter::RenderableTypes>(command.renderableTypes);
1018}
1019
1020QQuick3DShaderUtilsRenderablesFilter::~QQuick3DShaderUtilsRenderablesFilter()
1021{
1022
1023}
1024
1025void QQuick3DShaderUtilsRenderablesFilter::setRenderableTypes(RenderableTypes types)
1026{
1027 command.renderableTypes = static_cast<QSSGRenderablesFilterCommand::RenderableTypeT>(types.toInt());
1028}
1029
1030QQuick3DShaderUtilsPipelineStateOverride::~QQuick3DShaderUtilsPipelineStateOverride()
1031{
1032
1033}
1034
1035bool QQuick3DShaderUtilsPipelineStateOverride::depthTestEnabled() const
1036{
1037 if (command.m_depthTestEnabled)
1038 return *command.m_depthTestEnabled;
1039 return false;
1040}
1041
1042void QQuick3DShaderUtilsPipelineStateOverride::setDepthTestEnabled(bool newDepthTestEnabled)
1043{
1044 if (command.m_depthTestEnabled && *command.m_depthTestEnabled == newDepthTestEnabled)
1045 return;
1046 command.m_depthTestEnabled = newDepthTestEnabled;
1047 emit depthTestEnabledChanged();
1048}
1049
1050void QQuick3DShaderUtilsPipelineStateOverride::resetDepthTestEnabled()
1051{
1052 command.m_depthTestEnabled.reset();
1053 emit depthTestEnabledChanged();
1054}
1055
1056bool QQuick3DShaderUtilsPipelineStateOverride::depthWriteEnabled() const
1057{
1058 if (command.m_depthWriteEnabled)
1059 return *command.m_depthWriteEnabled;
1060 return false;
1061}
1062
1063void QQuick3DShaderUtilsPipelineStateOverride::setDepthWriteEnabled(bool newDepthWriteEnabled)
1064{
1065 if (command.m_depthWriteEnabled && *command.m_depthWriteEnabled == newDepthWriteEnabled)
1066 return;
1067 command.m_depthWriteEnabled = newDepthWriteEnabled;
1068 emit depthWriteEnabledChanged();
1069}
1070
1071void QQuick3DShaderUtilsPipelineStateOverride::resetDepthWriteEnabled()
1072{
1073 command.m_depthWriteEnabled.reset();
1074 emit depthWriteEnabledChanged();
1075}
1076
1077bool QQuick3DShaderUtilsPipelineStateOverride::blendEnabled() const
1078{
1079 if (command.m_blendEnabled)
1080 return *command.m_blendEnabled;
1081 return false;
1082}
1083
1084void QQuick3DShaderUtilsPipelineStateOverride::setBlendEnabled(bool newBlendEnabled)
1085{
1086 if (command.m_blendEnabled && *command.m_blendEnabled == newBlendEnabled)
1087 return;
1088 command.m_blendEnabled = newBlendEnabled;
1089 emit blendEnabledChanged();
1090}
1091
1092void QQuick3DShaderUtilsPipelineStateOverride::resetBlendEnabled()
1093{
1094 command.m_blendEnabled.reset();
1095 emit blendEnabledChanged();
1096}
1097
1098bool QQuick3DShaderUtilsPipelineStateOverride::usesStencilReference() const
1099{
1100 if (command.m_usesStencilReference)
1101 return *command.m_usesStencilReference;
1102 return false;
1103}
1104
1105void QQuick3DShaderUtilsPipelineStateOverride::setUsesStencilReference(bool newUsesStencilReference)
1106{
1107 if (command.m_usesStencilReference && *command.m_usesStencilReference == newUsesStencilReference)
1108 return;
1109 command.m_usesStencilReference = newUsesStencilReference;
1110 emit usesStencilReferenceChanged();
1111}
1112
1113void QQuick3DShaderUtilsPipelineStateOverride::resetUsesStencilReference()
1114{
1115 command.m_usesStencilReference.reset();
1116 emit usesStencilReferenceChanged();
1117}
1118
1119bool QQuick3DShaderUtilsPipelineStateOverride::usesScissor() const
1120{
1121 if (command.m_usesScissor)
1122 return *command.m_usesScissor;
1123 return false;
1124}
1125
1126void QQuick3DShaderUtilsPipelineStateOverride::setUsesScissor(bool newUsesScissor)
1127{
1128 if (command.m_usesScissor && *command.m_usesScissor == newUsesScissor)
1129 return;
1130 command.m_usesScissor = newUsesScissor;
1131 emit usesScissorChanged();
1132}
1133
1134void QQuick3DShaderUtilsPipelineStateOverride::resetUsesScissor()
1135{
1136 command.m_usesScissor.reset();
1137 emit usesScissorChanged();
1138}
1139
1140QQuick3DShaderUtilsPipelineStateOverride::CompareOperation QQuick3DShaderUtilsPipelineStateOverride::depthFunction() const
1141{
1142 if (command.m_depthFunction)
1143 return CompareOperation(*command.m_depthFunction);
1144 return CompareOperation::Less;
1145}
1146
1147void QQuick3DShaderUtilsPipelineStateOverride::setDepthFunction(CompareOperation newDepthFunction)
1148{
1149 if (command.m_depthFunction && *command.m_depthFunction == QRhiGraphicsPipeline::CompareOp(newDepthFunction))
1150 return;
1151 command.m_depthFunction = QRhiGraphicsPipeline::CompareOp(newDepthFunction);
1152 emit depthFunctionChanged();
1153}
1154
1155void QQuick3DShaderUtilsPipelineStateOverride::resetDepthFunction()
1156{
1157 command.m_depthFunction.reset();
1158 emit depthFunctionChanged();
1159}
1160
1161QQuick3DShaderUtilsPipelineStateOverride::CullMode QQuick3DShaderUtilsPipelineStateOverride::cullMode() const
1162{
1163 if (command.m_cullMode)
1164 return CullMode(*command.m_cullMode);
1165 return CullMode::Back;
1166}
1167
1168void QQuick3DShaderUtilsPipelineStateOverride::setCullMode(CullMode newCullMode)
1169{
1170 if (command.m_cullMode && *command.m_cullMode == QRhiGraphicsPipeline::CullMode(newCullMode))
1171 return;
1172 command.m_cullMode = QRhiGraphicsPipeline::CullMode(newCullMode);
1173 emit cullModeChanged();
1174}
1175
1176void QQuick3DShaderUtilsPipelineStateOverride::resetCullMode()
1177{
1178 command.m_cullMode.reset();
1179 emit cullModeChanged();
1180}
1181
1182QQuick3DShaderUtilsPipelineStateOverride::PolygonMode QQuick3DShaderUtilsPipelineStateOverride::polygonMode() const
1183{
1184 if (command.m_polygonMode)
1185 return PolygonMode(*command.m_polygonMode);
1186 return PolygonMode::Fill;
1187}
1188
1189void QQuick3DShaderUtilsPipelineStateOverride::setPolygonMode(PolygonMode newPolygonMode)
1190{
1191 if (command.m_polygonMode && *command.m_polygonMode == QRhiGraphicsPipeline::PolygonMode(newPolygonMode))
1192 return;
1193 command.m_polygonMode = QRhiGraphicsPipeline::PolygonMode(newPolygonMode);
1194 emit polygonModeChanged();
1195}
1196
1197void QQuick3DShaderUtilsPipelineStateOverride::resetPolygonMode()
1198{
1199 command.m_polygonMode.reset();
1200 emit polygonModeChanged();
1201}
1202
1203quint32 QQuick3DShaderUtilsPipelineStateOverride::stencilWriteMask() const
1204{
1205 if (command.m_stencilWriteMask)
1206 return *command.m_stencilWriteMask;
1207 return 0;
1208}
1209
1210void QQuick3DShaderUtilsPipelineStateOverride::setStencilWriteMask(quint32 newStencilWriteMask)
1211{
1212 if (command.m_stencilWriteMask && *command.m_stencilWriteMask == newStencilWriteMask)
1213 return;
1214 command.m_stencilWriteMask = newStencilWriteMask;
1215 emit stencilWriteMaskChanged();
1216}
1217
1218void QQuick3DShaderUtilsPipelineStateOverride::resetStencilWriteMask()
1219{
1220 command.m_stencilWriteMask.reset();
1221 emit stencilWriteMaskChanged();
1222}
1223
1224quint32 QQuick3DShaderUtilsPipelineStateOverride::stencilReference() const
1225{
1226 if (command.m_stencilReference)
1227 return *command.m_stencilReference;
1228 return 0;
1229}
1230
1231void QQuick3DShaderUtilsPipelineStateOverride::setStencilReference(quint32 newStencilReference)
1232{
1233 if (command.m_stencilReference && *command.m_stencilReference == newStencilReference)
1234 return;
1235 command.m_stencilReference = newStencilReference;
1236 emit stencilReferenceChanged();
1237}
1238
1239void QQuick3DShaderUtilsPipelineStateOverride::resetStencilReference()
1240{
1241 command.m_stencilReference.reset();
1242 emit stencilReferenceChanged();
1243}
1244
1245QRectF QQuick3DShaderUtilsPipelineStateOverride::viewport() const
1246{
1247 if (command.m_viewport) {
1248 const QRhiViewport &vp = *command.m_viewport;
1249 return QRectF(vp.viewport()[0], vp.viewport()[1], vp.viewport()[2], vp.viewport()[3]);
1250 }
1251 return QRectF();
1252}
1253
1254void QQuick3DShaderUtilsPipelineStateOverride::setViewport(const QRectF &newViewport)
1255{
1256 if (command.m_viewport) {
1257 const QRhiViewport &vp = *command.m_viewport;
1258 if (vp.viewport()[0] == newViewport.x() &&
1259 vp.viewport()[1] == newViewport.y() &&
1260 vp.viewport()[2] == newViewport.width() &&
1261 vp.viewport()[3] == newViewport.height())
1262 return;
1263 }
1264 command.m_viewport = QRhiViewport(newViewport.x(), newViewport.y(), newViewport.width(), newViewport.height());
1265 emit viewportChanged();
1266}
1267
1268void QQuick3DShaderUtilsPipelineStateOverride::resetViewport()
1269{
1270 command.m_viewport.reset();
1271 emit viewportChanged();
1272}
1273
1274QRect QQuick3DShaderUtilsPipelineStateOverride::scissor() const
1275{
1276 if (command.m_scissor) {
1277 const QRhiScissor &sc = *command.m_scissor;
1278 return QRect(sc.scissor()[0], sc.scissor()[1], sc.scissor()[2], sc.scissor()[3]);
1279 }
1280 return QRect();
1281}
1282
1283void QQuick3DShaderUtilsPipelineStateOverride::setScissor(const QRect &newScissor)
1284{
1285 if (command.m_viewport) {
1286 const QRhiScissor &sc = *command.m_scissor;
1287 if (sc.scissor()[0] == newScissor.x() &&
1288 sc.scissor()[1] == newScissor.y() &&
1289 sc.scissor()[2] == newScissor.width() &&
1290 sc.scissor()[3] == newScissor.height())
1291 return;
1292 }
1293 command.m_scissor = QRhiScissor(newScissor.x(), newScissor.y(), newScissor.width(), newScissor.height());
1294 emit scissorChanged();
1295}
1296
1297void QQuick3DShaderUtilsPipelineStateOverride::resetScissor()
1298{
1299 command.m_scissor.reset();
1300}
1301
1302QQuick3DRenderPassTargetBlend QQuick3DShaderUtilsPipelineStateOverride::targetBlend0() const
1303{
1304 if (command.m_targetBlend0)
1305 return *command.m_targetBlend0;
1306 return {};
1307}
1308
1309void QQuick3DShaderUtilsPipelineStateOverride::setTargetBlend0(const QQuick3DRenderPassTargetBlend &newTargetBlend0)
1310{
1311 if (command.m_targetBlend0 && QQuick3DRenderPassTargetBlend(*command.m_targetBlend0) == newTargetBlend0)
1312 return;
1313
1314 command.m_targetBlend0 = newTargetBlend0.toRhiTargetBlend();;
1315 emit targetBlend0Changed();
1316}
1317
1318void QQuick3DShaderUtilsPipelineStateOverride::resetTargetBlend0()
1319{
1320 command.m_targetBlend0.reset();
1321 emit targetBlend0Changed();
1322}
1323
1324QQuick3DRenderPassTargetBlend QQuick3DShaderUtilsPipelineStateOverride::targetBlend1() const
1325{
1326 if (command.m_targetBlend1)
1327 return *command.m_targetBlend1;
1328 return {};
1329}
1330
1331void QQuick3DShaderUtilsPipelineStateOverride::setTargetBlend1(const QQuick3DRenderPassTargetBlend &newTargetBlend1)
1332{
1333 if (command.m_targetBlend1 && QQuick3DRenderPassTargetBlend(*command.m_targetBlend1) == newTargetBlend1)
1334 return;
1335 command.m_targetBlend1 = newTargetBlend1.toRhiTargetBlend();
1336 emit targetBlend1Changed();
1337}
1338
1339void QQuick3DShaderUtilsPipelineStateOverride::resetTargetBlend1()
1340{
1341 command.m_targetBlend1.reset();
1342 emit targetBlend1Changed();
1343}
1344
1345QQuick3DRenderPassTargetBlend QQuick3DShaderUtilsPipelineStateOverride::targetBlend2() const
1346{
1347 if (command.m_targetBlend2)
1348 return *command.m_targetBlend2;
1349 return {};
1350}
1351
1352void QQuick3DShaderUtilsPipelineStateOverride::setTargetBlend2(const QQuick3DRenderPassTargetBlend &newTargetBlend2)
1353{
1354 if (command.m_targetBlend2 && QQuick3DRenderPassTargetBlend(*command.m_targetBlend2) == newTargetBlend2)
1355 return;
1356 command.m_targetBlend2 = newTargetBlend2.toRhiTargetBlend();
1357 emit targetBlend2Changed();
1358}
1359
1360void QQuick3DShaderUtilsPipelineStateOverride::resetTargetBlend2()
1361{
1362 command.m_targetBlend2.reset();
1363 emit targetBlend2Changed();
1364}
1365
1366QQuick3DRenderPassTargetBlend QQuick3DShaderUtilsPipelineStateOverride::targetBlend3() const
1367{
1368 if (command.m_targetBlend3)
1369 return *command.m_targetBlend3;
1370 return {};
1371}
1372
1373void QQuick3DShaderUtilsPipelineStateOverride::setTargetBlend3(const QQuick3DRenderPassTargetBlend &newTargetBlend3)
1374{
1375 if (command.m_targetBlend3 && QQuick3DRenderPassTargetBlend(*command.m_targetBlend3) == newTargetBlend3)
1376 return;
1377 command.m_targetBlend3 = newTargetBlend3.toRhiTargetBlend();
1378 emit targetBlend3Changed();
1379}
1380
1381void QQuick3DShaderUtilsPipelineStateOverride::resetTargetBlend3()
1382{
1383 command.m_targetBlend3.reset();
1384 emit targetBlend3Changed();
1385}
1386
1387QQuick3DRenderPassTargetBlend QQuick3DShaderUtilsPipelineStateOverride::targetBlend4() const
1388{
1389 if (command.m_targetBlend4)
1390 return *command.m_targetBlend4;
1391 return {};
1392}
1393
1394void QQuick3DShaderUtilsPipelineStateOverride::setTargetBlend4(const QQuick3DRenderPassTargetBlend &newTargetBlend4)
1395{
1396 if (command.m_targetBlend4 && QQuick3DRenderPassTargetBlend(*command.m_targetBlend4) == newTargetBlend4)
1397 return;
1398 command.m_targetBlend4 = newTargetBlend4.toRhiTargetBlend();
1399 emit targetBlend4Changed();
1400}
1401
1402void QQuick3DShaderUtilsPipelineStateOverride::resetTargetBlend4()
1403{
1404 command.m_targetBlend4.reset();
1405 emit targetBlend4Changed();
1406}
1407
1408QQuick3DRenderPassTargetBlend QQuick3DShaderUtilsPipelineStateOverride::targetBlend5() const
1409{
1410 if (command.m_targetBlend5)
1411 return *command.m_targetBlend5;
1412 return {};
1413}
1414
1415void QQuick3DShaderUtilsPipelineStateOverride::setTargetBlend5(const QQuick3DRenderPassTargetBlend &newTargetBlend5)
1416{
1417 if (command.m_targetBlend5 && QQuick3DRenderPassTargetBlend(*command.m_targetBlend5) == newTargetBlend5)
1418 return;
1419 command.m_targetBlend5 = newTargetBlend5.toRhiTargetBlend();
1420 emit targetBlend5Changed();
1421}
1422
1423void QQuick3DShaderUtilsPipelineStateOverride::resetTargetBlend5()
1424{
1425 command.m_targetBlend5.reset();
1426 emit targetBlend5Changed();
1427}
1428
1429QQuick3DRenderPassTargetBlend QQuick3DShaderUtilsPipelineStateOverride::targetBlend6() const
1430{
1431 if (command.m_targetBlend6)
1432 return *command.m_targetBlend6;
1433 return {};
1434}
1435
1436void QQuick3DShaderUtilsPipelineStateOverride::setTargetBlend6(const QQuick3DRenderPassTargetBlend &newTargetBlend6)
1437{
1438 if (command.m_targetBlend6 && QQuick3DRenderPassTargetBlend(*command.m_targetBlend6) == newTargetBlend6)
1439 return;
1440 command.m_targetBlend6 = newTargetBlend6.toRhiTargetBlend();
1441 emit targetBlend6Changed();
1442}
1443
1444void QQuick3DShaderUtilsPipelineStateOverride::resetTargetBlend6()
1445{
1446 command.m_targetBlend6.reset();
1447 emit targetBlend6Changed();
1448}
1449
1450QQuick3DRenderPassTargetBlend QQuick3DShaderUtilsPipelineStateOverride::targetBlend7() const
1451{
1452 if (command.m_targetBlend7)
1453 return *command.m_targetBlend7;
1454 return {};
1455}
1456
1457void QQuick3DShaderUtilsPipelineStateOverride::setTargetBlend7(const QQuick3DRenderPassTargetBlend &newTargetBlend7)
1458{
1459 if (command.m_targetBlend7 && QQuick3DRenderPassTargetBlend(*command.m_targetBlend7) == newTargetBlend7)
1460 return;
1461 command.m_targetBlend7 = newTargetBlend7.toRhiTargetBlend();
1462 emit targetBlend7Changed();
1463}
1464
1465void QQuick3DShaderUtilsPipelineStateOverride::resetTargetBlend7()
1466{
1467 command.m_targetBlend7.reset();
1468 emit targetBlend7Changed();
1469}
1470
1471/*!
1472 \qmltype RenderPassTexture
1473 \inherits Command
1474 \inqmlmodule QtQuick3D
1475 \brief Defines a texture to be used as a render target in a \l {RenderPass}{pass}.
1476 \since 6.11
1477
1478 The RenderPassTexture type is used to specify a texture that will be used
1479 as a render target in a \l RenderPass. You can define the format of the
1480 texture using the \c format property.
1481
1482 Once defined, the texture can be attached as a color or depth attachment. The texture will
1483 be automatically created and managed by the rendering system.
1484
1485 \sa ColorAttachment, DepthTextureAttachment
1486*/
1487
1488/*!
1489 \qmlproperty enumeration RenderPassTexture::format
1490 Sets the format of the render target texture.
1491
1492 Available formats are:
1493
1494 \value RenderPassTexture.Unknown
1495 \value RenderPassTexture.RGBA8
1496 \value RenderPassTexture.RGBA16F
1497 \value RenderPassTexture.RGBA32F
1498 \value RenderPassTexture.R8
1499 \value RenderPassTexture.R16
1500 \value RenderPassTexture.R16F
1501 \value RenderPassTexture.R32F
1502 \value RenderPassTexture.Depth16
1503 \value RenderPassTexture.Depth24
1504 \value RenderPassTexture.Depth32
1505 \value RenderPassTexture.Depth24Stencil8
1506*/
1507
1508QQuick3DShaderUtilsRenderPassTexture::TextureFormat QQuick3DShaderUtilsRenderPassTexture::format() const
1509{
1510 return fromRenderTextureFormat(command->format());
1511}
1512
1513QQuick3DShaderUtilsRenderPassTexture::~QQuick3DShaderUtilsRenderPassTexture()
1514{
1515
1516}
1517
1518void QQuick3DShaderUtilsRenderPassTexture::setFormat(TextureFormat newFormat)
1519{
1520 if (!command)
1521 command = std::make_shared<QSSGAllocateTexture>();
1522 command->setFormat(asRenderTextureFormat(newFormat));
1523}
1524
1525QSSGRenderTextureFormat QQuick3DShaderUtilsRenderPassTexture::asRenderTextureFormat(TextureFormat fmt)
1526{
1527 switch (fmt) {
1528 case TextureFormat::Unknown: return QSSGRenderTextureFormat::Unknown;
1529 case TextureFormat::RGBA8: return QSSGRenderTextureFormat::RGBA8;
1530 case TextureFormat::RGBA16F: return QSSGRenderTextureFormat::RGBA16F;
1531 case TextureFormat::RGBA32F: return QSSGRenderTextureFormat::RGBA32F;
1532 case TextureFormat::R8: return QSSGRenderTextureFormat::R8;
1533 case TextureFormat::R16: return QSSGRenderTextureFormat::R16;
1534 case TextureFormat::R16F: return QSSGRenderTextureFormat::R16F;
1535 case TextureFormat::R32F: return QSSGRenderTextureFormat::R32F;
1536 case TextureFormat::Depth16: return QSSGRenderTextureFormat::Depth16;
1537 case TextureFormat::Depth24: return QSSGRenderTextureFormat::Depth24;
1538 case TextureFormat::Depth32: return QSSGRenderTextureFormat::Depth32;
1539 case TextureFormat::Depth24Stencil8: return QSSGRenderTextureFormat::Depth24Stencil8;
1540 default:
1541 break;
1542 }
1543 return QSSGRenderTextureFormat::Unknown;
1544}
1545
1546QQuick3DShaderUtilsRenderPassTexture::TextureFormat QQuick3DShaderUtilsRenderPassTexture::fromRenderTextureFormat(QSSGRenderTextureFormat fmt)
1547{
1548 switch (fmt.format) {
1549 case QSSGRenderTextureFormat::Unknown: return TextureFormat::Unknown;
1550 case QSSGRenderTextureFormat::RGBA8: return TextureFormat::RGBA8;
1551 case QSSGRenderTextureFormat::RGBA16F: return TextureFormat::RGBA16F;
1552 case QSSGRenderTextureFormat::RGBA32F: return TextureFormat::RGBA32F;
1553 case QSSGRenderTextureFormat::R8: return TextureFormat::R8;
1554 case QSSGRenderTextureFormat::R16: return TextureFormat::R16;
1555 case QSSGRenderTextureFormat::R16F: return TextureFormat::R16F;
1556 case QSSGRenderTextureFormat::R32F: return TextureFormat::R32F;
1557 case QSSGRenderTextureFormat::Depth16: return TextureFormat::Depth16;
1558 case QSSGRenderTextureFormat::Depth24: return TextureFormat::Depth24;
1559 case QSSGRenderTextureFormat::Depth32: return TextureFormat::Depth32;
1560 case QSSGRenderTextureFormat::Depth24Stencil8: return TextureFormat::Depth24Stencil8;
1561 default:
1562 break;
1563 }
1564 return TextureFormat::Unknown;
1565}
1566
1567/*!
1568 \qmltype ColorAttachment
1569 \inherits Command
1570 \inqmlmodule QtQuick3D
1571 \brief Defines a color attachment for a \l {RenderPass}{pass}.
1572 \since 6.11
1573
1574 The ColorAttachment type is used to specify a color attachment for a \l RenderPass.
1575 The \l name property is used to identify the attachment within the render pass.
1576 If the \l {RenderPass.AugmentMaterial}{AugmentMaterial} mode is used, the name will be
1577 exposed as an output wiht \c name in the fragment shader.
1578
1579 \sa RenderPassTexture
1580
1581 \qml
1582 RenderPass {
1583 // Define a render target texture
1584 RenderPassTexture {
1585 id: colorTexture
1586 format: RenderPassTexture.RGBA16F
1587 }
1588
1589 commands: [
1590 // Define a color attachment using the texture
1591 ColorAttachment {
1592 name: "color0"
1593 target: colorTexture
1594 }
1595 ]
1596 }
1597 \endqml
1598*/
1599
1600QQuick3DShaderUtilsRenderPassColorAttachment::~QQuick3DShaderUtilsRenderPassColorAttachment()
1601{
1602
1603}
1604
1605QByteArray QQuick3DShaderUtilsRenderPassColorAttachment::name() const
1606{
1607 return m_name;
1608}
1609
1610void QQuick3DShaderUtilsRenderPassColorAttachment::setName(const QByteArray &newName)
1611{
1612 m_name = newName;
1613}
1614
1615QSSGCommand *QQuick3DShaderUtilsRenderPassColorAttachment::cloneCommand()
1616{
1617 if (target) {
1618 QSSGColorAttachment *cmd = new QSSGColorAttachment(m_name);
1619 cmd->m_textureCmd = target->command;
1620 return cmd;
1621 }
1622
1623 return nullptr;
1624}
1625
1630
1631void QQuick3DPropertyChangedTracker::extractProperties(UniformPropertyList &outUniforms)
1632{
1633 // Ensure we start with a clean list
1634 outUniforms.clear();
1635
1636 auto metaObject = m_owner->metaObject();
1637
1638 // Properties -> uniforms
1639 const int propCount = metaObject->propertyCount();
1640 int propOffset = metaObject->propertyOffset();
1641
1642 // Classes can have multilayered inheritance structure, so find the actual propOffset by
1643 // walking up the inheritance chain.
1644 const QMetaObject *superClass = metaObject->superClass();
1645 while (superClass && qstrcmp(superClass->className(), m_superClassName) != 0) {
1646 propOffset = superClass->propertyOffset();
1647 superClass = superClass->superClass();
1648 }
1649
1650 static auto getSamplerHint = [](const QQuick3DTexture &texture) {
1651 if (auto *po = QQuick3DObjectPrivate::get(&texture)) {
1652 if (po->type == QQuick3DObjectPrivate::Type::TextureProvider) {
1653 auto textureProvider = static_cast<QQuick3DTextureProviderExtension *>(texture.textureProvider());
1654 switch (textureProvider->samplerHint()) {
1655 case QQuick3DTextureProviderExtension::SamplerHint::Sampler2D:
1656 return QSSGRenderSamplerType::Sampler2D;
1657 case QQuick3DTextureProviderExtension::SamplerHint::Sampler2DArray:
1658 return QSSGRenderSamplerType::Sampler2DArray;
1659 case QQuick3DTextureProviderExtension::SamplerHint::Sampler3D:
1660 return QSSGRenderSamplerType::Sampler3D;
1661 case QQuick3DTextureProviderExtension::SamplerHint::SamplerCube:
1662 return QSSGRenderSamplerType::SamplerCube;
1663 case QQuick3DTextureProviderExtension::SamplerHint::SamplerCubeArray:
1664 return QSSGRenderSamplerType::SamplerCubeArray;
1665 case QQuick3DTextureProviderExtension::SamplerHint::SamplerBuffer:
1666 return QSSGRenderSamplerType::SamplerBuffer;
1667 }
1668 } else if (po->type == QQuick3DObjectPrivate::Type::ImageCube) {
1669 return QSSGRenderSamplerType::SamplerCube;
1670 } else if (texture.textureData() && texture.textureData()->depth() > 0) {
1671 return QSSGRenderSamplerType::Sampler3D;
1672 }
1673 }
1674
1675 return QSSGRenderSamplerType::Sampler2D;
1676 };
1677
1678 const auto addTextureToUniforms = [&](const char *name, QQuick3DTexture *texture, int propertyIndex) {
1679 QSSGRenderImage *ri = static_cast<QSSGRenderImage *>(QQuick3DObjectPrivate::get(texture)->spatialNode);
1680 auto samplerName = QSSGBaseTypeHelpers::toString(getSamplerHint(*texture));
1681 outUniforms.emplace_back(name, samplerName, QVariant::fromValue(ri), QSSGRenderShaderValue::Texture, propertyIndex);
1682 };
1683
1684 // The TextureInput type needs extra watchers for its properties...
1685 const auto addTextureInputWatchers = [&](QMetaProperty property, QQuick3DShaderUtilsTextureInput *textureInput) {
1686 QObject::connect(textureInput, &QQuick3DShaderUtilsTextureInput::enabledChanged, m_owner, [this, property, textureInput](){ addPropertyWatcher(property, DirtyPropertyHint::Reference, textureInput); }, Qt::UniqueConnection);
1687 QObject::connect(textureInput, &QQuick3DShaderUtilsTextureInput::textureChanged, m_owner, [this, property, textureInput](){ addPropertyWatcher(property, DirtyPropertyHint::Reference, textureInput); }, Qt::UniqueConnection);
1688 if (auto *texture = textureInput->texture())
1689 addTextureToUniforms(property.name(), texture, property.propertyIndex());
1690 };
1691
1692 for (int i = propOffset; i != propCount; ++i) {
1693 const QMetaProperty property = metaObject->property(i);
1694 if (Q_UNLIKELY(!property.isValid()))
1695 continue;
1696
1697 const char *name = property.name();
1698 QMetaType propType = property.metaType();
1699 QVariant propValue = property.read(m_owner);
1700 if (propType == QMetaType(QMetaType::QVariant))
1701 propType = propValue.metaType();
1702
1703 const auto type = QSSGShaderUtils::uniformType(propType);
1704 if (type != QSSGRenderShaderValue::Unknown) {
1705 outUniforms.emplace_back(name, QSSGShaderUtils::uniformTypeName(propType),
1706 propValue, QSSGShaderUtils::uniformType(propType), i);
1707 addPropertyWatcher(property, DirtyPropertyHint::Value);
1708 } else {
1709 if (propType.id() >= QMetaType::User) {
1710 if (propType.id() == qMetaTypeId<QQuick3DTexture *>()) {
1711 if (QQuick3DTexture *texture = property.read(m_owner).value<QQuick3DTexture *>()) {
1712 addTextureToUniforms(name, texture, i);
1713 addPropertyWatcher(property, DirtyPropertyHint::Reference, texture);
1714 }
1715 } else if (propType.id() == qMetaTypeId<QQuick3DShaderUtilsTextureInput *>()) { // For compatibility, also check for texture input types
1716 if (QQuick3DShaderUtilsTextureInput *textureInput = property.read(m_owner).value<QQuick3DShaderUtilsTextureInput *>(); textureInput && textureInput->texture()) {
1717 addTextureInputWatchers(property, textureInput);
1718 addPropertyWatcher(property, DirtyPropertyHint::Reference, textureInput);
1719 }
1720 }
1721 } else if (propType == QMetaType(QMetaType::QObjectStar)) {
1722 if (QQuick3DTexture *texture = qobject_cast<QQuick3DTexture *>(propValue.value<QObject *>())) {
1723 addTextureToUniforms(name, texture, i);
1724 addPropertyWatcher(property, DirtyPropertyHint::Reference, texture);
1725 } else if (QQuick3DShaderUtilsTextureInput *textureInput = qobject_cast<QQuick3DShaderUtilsTextureInput *>(propValue.value<QObject *>()); textureInput && textureInput->texture()) {
1726 addTextureInputWatchers(property, textureInput);
1727 addPropertyWatcher(property, DirtyPropertyHint::Reference, textureInput);
1728 }
1729 }
1730 }
1731 }
1732}
1733
1734void QQuick3DPropertyChangedTracker::addPropertyWatcher(QMetaProperty property, DirtyPropertyHint hint, QQuick3DObject *object)
1735{
1736 if (property.isValid() && property.hasNotifySignal()) {
1737 // Check if we're already watching this property.
1738 const auto pid = property.propertyIndex();
1739 Q_ASSERT(pid != -1);
1740 auto it = std::find_if(m_trackedProperties.begin(), m_trackedProperties.end(), [pid](const Tracked &tp) { return tp.pid == pid; });
1741 const bool found = (it != m_trackedProperties.end());
1742 QQuick3DObject *oldObj = nullptr;
1743 if (!found) {
1744 QQuick3DPropertyWatcher *watcher = new QQuick3DPropertyWatcher(this, property);
1745 m_trackedProperties.push_back({watcher, object, pid});
1746 it = std::prev(m_trackedProperties.end());
1747 } else {
1748 oldObj = it->object;
1749 it->object = object;
1750 }
1751
1752 if (hint == DirtyPropertyHint::Reference) {
1753 const auto &sm = QQuick3DObjectPrivate::get(m_owner)->sceneManager;
1754
1755 // First check if the object changed
1756 const bool changed = (oldObj != object);
1757
1758 // Deref old object
1759 if (changed && oldObj) {
1760 QQuick3DObjectPrivate::get(oldObj)->derefSceneManager();
1761 QObject::disconnect(oldObj, &QObject::destroyed, m_owner, nullptr);
1762 }
1763
1764 // Ref new object
1765 if (changed && object) {
1766 QQuick3DObjectPrivate::get(object)->refSceneManager(*sm);
1767 QObject::connect(object, &QObject::destroyed, m_owner, [this, property](QObject *obj) {
1768 Q_UNUSED(obj);
1769 addPropertyWatcher(property, DirtyPropertyHint::Reference, nullptr);
1770 });
1771 }
1772 }
1773
1774 markTrackedPropertyDirty(property, hint);
1775 }
1776}
1777
1779{
1780 Q_UNUSED(property);
1781 Q_UNUSED(hint);
1782 QSSG_CHECK_X(false, "QQuick3DPropertyChangedTracker::onPropertyDirty implementation missing");
1783}
1784
1785QQuick3DPropertyWatcher::QQuick3DPropertyWatcher(QQuick3DPropertyChangedTracker *tracker, QMetaProperty property)
1786 : m_tracker(tracker)
1787 , m_property(property)
1788{
1789 Q_ASSERT(tracker != nullptr);
1790 Q_ASSERT(property.isValid() && property.hasNotifySignal());
1791
1792 const bool isPointerType = (property.metaType().flags().testFlag(QMetaType::IsPointer));
1793
1794 if (!isPointerType) {
1795 // Value change notification
1796 const auto idx = staticMetaObject.indexOfSlot("onValuePropertyChanged()");
1797 if (QSSG_GUARD_X(idx != -1, "Method not found!")) {
1798 auto onPropertyChangedMethod = staticMetaObject.method(idx);
1799 connect(m_tracker->m_owner, property.notifySignal(), this, onPropertyChangedMethod);
1800 }
1801 } else {
1802 // Pointer value change notification
1803 const auto idx = staticMetaObject.indexOfSlot("onPointerPropertyChanged()");
1804 if (QSSG_GUARD_X(idx != -1, "Method not found!")) {
1805 auto onPointerPropertyChangedMethod = staticMetaObject.method(idx);
1806 connect(m_tracker->m_owner, property.notifySignal(), this, onPointerPropertyChangedMethod);
1807 }
1808 }
1809}
1810
1811void QQuick3DPropertyWatcher::onValuePropertyChanged()
1812{
1813 m_tracker->markTrackedPropertyDirty(m_property, QQuick3DPropertyChangedTracker::DirtyPropertyHint::Value);
1814}
1815
1817{
1818 m_tracker->markTrackedPropertyDirty(m_property, QQuick3DPropertyChangedTracker::DirtyPropertyHint::Reference);;
1819}
1820
1821/*!
1822 \qmltype AddDefine
1823 \inherits Command
1824 \inqmlmodule QtQuick3D
1825 \brief Adds a preprocessor define to the shader compilation for a \l {RenderPass}{pass}.
1826 \since 6.11
1827
1828 The AddDefine type is used to specify a preprocessor define that will be
1829 added to the shader compilation process for a \l RenderPass. This allows
1830 you to customize the shader behavior by defining specific macros.
1831*/
1832
1833QQuick3DShaderUtilsRenderPassAddDefine::QQuick3DShaderUtilsRenderPassAddDefine()
1834{
1835
1836}
1837
1838QQuick3DShaderUtilsRenderPassAddDefine::~QQuick3DShaderUtilsRenderPassAddDefine() = default;
1839
1840QSSGCommand *QQuick3DShaderUtilsRenderPassAddDefine::cloneCommand() {
1841 QSSGAddShaderDefine *cmd = new QSSGAddShaderDefine(command);
1842 return cmd;
1843}
1844
1845QQuick3DShaderUtilsSubRenderPass::~QQuick3DShaderUtilsSubRenderPass()
1846{
1847
1848}
1849
1850QSSGCommand *QQuick3DShaderUtilsSubRenderPass::cloneCommand()
1851{
1852 QSSGSubRenderPass *cmd = nullptr;
1853
1854 if (!m_renderPass) {
1855 if (!m_hasWarnedAboutInvalidId) {
1856 qCWarning(lcSubRenderPass, "SubRenderPass: No render pass specified. Set the 'renderPass' property.");
1857 m_hasWarnedAboutInvalidId = true;
1858 }
1859 return nullptr;
1860 }
1861
1862 QSSGResourceId userPassId = QQuick3DExtensionHelpers::getResourceId(*m_renderPass);
1863 // Ensure we have a valid resource id before continuing.
1864 if (userPassId != QSSGResourceId::Invalid) {
1865 cmd = new QSSGSubRenderPass();
1866 cmd->setSubPass(userPassId);
1867 // Reset warning flag on success
1868 m_hasWarnedAboutInvalidId = false;
1869 } else {
1870 // Resource ID is not ready yet - this is expected during initialization
1871 qCDebug(lcSubRenderPass, "SubRenderPass: Render pass resource ID not yet available, will retry.");
1872 update();
1873 }
1874
1875 return cmd;
1876}
1877
1878QSSGRenderGraphObject *QQuick3DShaderUtilsSubRenderPass::updateSpatialNode(QSSGRenderGraphObject *node)
1879{
1880 return node;
1881}
1882
1883void QQuick3DShaderUtilsSubRenderPass::itemChange(ItemChange change, const ItemChangeData &value)
1884{
1885 if (change == QQuick3DObject::ItemSceneChange)
1886 updateSceneManager(value.sceneManager);
1887}
1888
1889void QQuick3DShaderUtilsSubRenderPass::updateSceneManager(QQuick3DSceneManager *sceneManager)
1890{
1891 if (sceneManager)
1892 QQuick3DObjectPrivate::refSceneManager(m_renderPass, *sceneManager);
1893 else
1894 QQuick3DObjectPrivate::derefSceneManager(m_renderPass);
1895}
1896
1897QQuick3DRenderPass *QQuick3DShaderUtilsSubRenderPass::renderPass() const
1898{
1899 return m_renderPass;
1900}
1901
1902void QQuick3DShaderUtilsSubRenderPass::setRenderPass(QQuick3DRenderPass *newRenderPass)
1903{
1904 if (m_renderPass == newRenderPass)
1905 return;
1906
1907 QQuick3DObjectPrivate::attachWatcher(this, &QQuick3DShaderUtilsSubRenderPass::setRenderPass, newRenderPass, m_renderPass);
1908
1909 if (newRenderPass)
1910 newRenderPass->update();
1911
1912 m_renderPass = newRenderPass;
1913 m_hasWarnedAboutInvalidId = false; // Reset warning flag when property changes
1914 emit renderPassChanged();
1915}
1916
1917/*!
1918 \qmltype DepthTextureAttachment
1919 \inherits Command
1920 \inqmlmodule QtQuick3D
1921 \brief Defines a depth texture attachment for a \l {RenderPass}{pass}.
1922 \since 6.11
1923
1924 The DepthTextureAttachment type is used to specify a depth texture
1925 that will be used as a depth attachment in a \l RenderPass. The texture
1926 will be automatically created and managed by the rendering system.
1927
1928 \sa RenderPassTexture
1929*/
1930
1931QQuick3DShaderUtilsRenderPassDepthTextureAttachment::~QQuick3DShaderUtilsRenderPassDepthTextureAttachment()
1932{
1933
1934}
1935
1936QSSGCommand *QQuick3DShaderUtilsRenderPassDepthTextureAttachment::cloneCommand()
1937{
1938 if (target) {
1939 QSSGDepthTextureAttachment *cmd = new QSSGDepthTextureAttachment(QByteArrayLiteral("__depth__"));
1940 cmd->m_textureCmd = target->command;
1941 return cmd;
1942 }
1943
1944 return nullptr;
1945}
1946
1947QQuick3DShaderUtilsRenderPassDepthStencilAttachment::~QQuick3DShaderUtilsRenderPassDepthStencilAttachment()
1948{
1949
1950}
1951
1952QSSGCommand *QQuick3DShaderUtilsRenderPassDepthStencilAttachment::cloneCommand()
1953{
1954 QSSGDepthStencilAttachment *cmd = new QSSGDepthStencilAttachment;
1955 return cmd;
1956}
1957
1958QT_END_NAMESPACE
void extractProperties(UniformPropertyList &outUniforms)
void addPropertyWatcher(QMetaProperty property, DirtyPropertyHint hint, QQuick3DObject *object=nullptr)
virtual void markTrackedPropertyDirty(QMetaProperty property, DirtyPropertyHint hint)=0
\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)
Combined button and popup list for selecting options.