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
qquick3dtexturedata.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
8#include <QtQuick3DUtils/private/qssgutils_p.h>
9#include <QtQuick3DRuntimeRender/private/qssgrendertexturedata_p.h>
10
12
13/*!
14 \qmltype TextureData
15 \inherits Object3D
16 \inqmlmodule QtQuick3D
17 \nativetype QQuick3DTextureData
18 \brief Base type for custom texture data.
19
20 Custom texture data allows using application-generated texture data, that
21 can possibly change dynamically as well. To use custom texture data set the
22 \l{Texture::textureData}{textureData} property of \l {Texture} to reference
23 a TextureData object.
24
25 Custom Texture data is implemented in C++ by creating a QQuick3DTextureData
26 instance, often subclassing it. The QQuick3DTextureData type is registered to
27 QML under the name of TextureData. Once the subclass is registered to QML,
28 Texture objects can start referencing it.
29
30 An example of when to use this API is when there is a need to procedurally
31 generate a texture at runtime rather than loading a static image from a file.
32
33 \code
34 import MyCustomTexture 1.0
35
36 Model {
37 source: "#Cube"
38 materials: [
39 DefaultMaterial {
40 diffuseMap: diffuseMapCustomTexture
41 }
42 ]
43 }
44
45 Texture {
46 id: diffuseMapCustomTexture
47 textureData: MyCustomTextureData {
48
49 }
50 }
51
52 \endcode
53
54 \sa Texture
55*/
56
57/*!
58 \class QQuick3DTextureData
59 \inmodule QtQuick3D
60 \inherits QQuick3DObject
61 \since 6.0
62 \brief Base class for defining custom texture data.
63
64 The QQuick3DTextureData class can be used to specify custom texture data for a
65 \l {Texture} in a Qt Quick 3D scene.
66
67 While not strictly required, the typical usage is to inherit from this class.
68 The subclass is then exposed to QML by registering it to the type system. The
69 \l{Texture::textureData}{textureData} property of a \l {QtQuick3D::Texture}{Texture}
70 can then be set to reference an instance of the registered type.
71
72 Example implementation:
73
74 \code
75 class CustomTextureData : public QQuick3DTextureData
76 {
77 Q_OBJECT
78 ... properties ...
79
80 public:
81 CustomTextureData() { regenerateTextureData(); }
82
83 void setProperty(...)
84 {
85 // Change relevant internal data.
86 // ...
87
88 // Update the texture data
89 regenerateTextureData();
90
91 // Finally, trigger an update. This is relevant in case nothing else
92 // is changed in the scene; this way we make sure a new frame will
93 // be rendered
94 update();
95 }
96 private:
97 void regenerateTextureData()
98 {
99 QByteArray textureData;
100 textureData = generateTextureData();
101 setTextureData(textureData);
102 setSize(QSize(256, 256));
103 setFormat(QQuick3DTextureData::Format::RGBA8)
104 setHasTransparency(true);
105 }
106 };
107 \endcode
108
109 This class can then be registered as a QML type and used with \l {QtQuick3D::Texture}{Texture}.
110
111 In Qt 5 type registration happened with qmlRegisterType:
112 \code
113 qmlRegisterType<MyCustomTextureData>("Example", 1, 0, "MyCustomTextureData");
114 \endcode
115
116 In Qt 6 the default approach is to use automatic registration with the help
117 of the build system. Instead of calling qmlRegisterType, the \c{.pro} file
118 can now contain:
119
120 \code
121 CONFIG += qmltypes
122 QML_IMPORT_NAME = Example
123 QML_IMPORT_MAJOR_VERSION = 1
124 \endcode
125
126 With CMake, automatic registration is the default behavior, so no special
127 settings are needed beyond basic QML module setup:
128 \code
129 qt_add_qml_module(application
130 URI Example
131 VERSION 1.0
132 )
133 \endcode
134
135 The class implementation should add QML_NAMED_ELEMENT:
136
137 \code
138 class CustomTextureData : public QQuick3DTextureData
139 {
140 Q_OBJECT
141 QML_NAMED_ELEMENT(MyCustomTextureData)
142 ...
143 };
144 \endcode
145
146 The QML code can then use the custom type:
147
148 \code
149 import Example 1.0
150
151 Model {
152 source: "#Cube"
153 materials: [
154 DefaultMaterial {
155 diffuseMap: diffuseMapCustomTexture
156 }
157 ]
158 Texture {
159 id: diffuseMapCustomTexture
160 textureData: MyCustomTextureData { }
161 }
162 }
163 \endcode
164*/
165
166/*!
167 \enum QQuick3DTextureData::Format
168 Returns the color format of the texture data assigned in \l textureData property.
169
170 \value None The color format is not defined
171 \value RGBA8 The color format is considered as 8-bit integer in R, G, B and alpha channels.
172 \value RGBA16F The color format is considered as 16-bit float in R,G,B and alpha channels.
173 \value RGBA32F The color format is considered as 32-bit float in R, G, B and alpha channels.
174 \value RGBE8 The color format is considered as 8-bit mantissa in the R, G, and B channels and 8-bit shared exponent.
175 \value R8 The color format is considered as 8-bit integer in R channel.
176 \value R16 The color format is considered as 16-bit integer in R channel.
177 \value R16F The color format is considered as 16-bit float in R channel.
178 \value R32F The color format is considered as 32-bit float R channel.
179 \value BC1 The color format is considred as BC1 compressed format with R, G, B, and alpha channels.
180 \value BC2 The color format is considred as BC2 compressed format with R, G, B, and alpha channels.
181 \value BC3 The color format is considred as BC3 compressed format with R, G, B, and alpha channels.
182 \value BC4 The color format is considred as BC4 compressed format with one color channel.
183 \value BC5 The color format is considred as BC5 compressed format with two color channels.
184 \value BC6H The color format is considred as BC6H compressed format with three high dynamic range color channels.
185 \value BC7 The color format is considred as BC7 compressed format with R, G, B, and alpha channels.
186 \value DXT1_RGBA The color format is considered as DXT1 compressed format with R, G, B and alpha channels.
187 \value DXT1_RGB The color format is considered as DXT1 compressed format with R, G and B channels.
188 \value DXT3_RGBA The color format is considered as DXT3 compressed format with R, G, B and alpha channels.
189 \value DXT5_RGBA The color format is considered as DXT5 compressed format with R, G, B and alpha channels.
190 \value ETC2_RGB8 The color format is considered as ETC2 compressed format for RGB888 data
191 \value ETC2_RGB8A1 The color format is considered as ETC2 compressed format for RGBA data where alpha is 1-bit.
192 \value ETC2_RGBA8 The color format is considered as ETC2 compressed format with RGBA8888 data.
193 \value ASTC_4x4 The color format is considered as ASTC compressed format with 4x4 block footprint.
194 \value ASTC_5x4 The color format is considered as ASTC compressed format with 5x4 block footprint.
195 \value ASTC_5x5 The color format is considered as ASTC compressed format with 5x5 block footprint.
196 \value ASTC_6x5 The color format is considered as ASTC compressed format with 6x5 block footprint.
197 \value ASTC_6x6 The color format is considered as ASTC compressed format with 6x6 block footprint.
198 \value ASTC_8x5 The color format is considered as ASTC compressed format with 8x5 block footprint.
199 \value ASTC_8x6 The color format is considered as ASTC compressed format with 8x6 block footprint.
200 \value ASTC_8x8 The color format is considered as ASTC compressed format with 8x8 block footprint.
201 \value ASTC_10x5 The color format is considered as ASTC compressed format with 10x5 block footprint.
202 \value ASTC_10x6 The color format is considered as ASTC compressed format with 10x6 block footprint.
203 \value ASTC_10x8 The color format is considered as ASTC compressed format with 10x8 block footprint.
204 \value ASTC_10x10 The color format is considered as ASTC compressed format with 10x10 block footprint.
205 \value ASTC_12x10 The color format is considered as ASTC compressed format with 12x10 block footprint.
206 \value ASTC_12x12 The color format is considered as ASTC compressed format with 12x12 block footprint.
207
208 \note With the exception of \c RGBA8, not every format is supported at runtime as this
209 depends on which backend is being used as well which hardware is being used.
210
211 \note \c RGBE is internally represented as an \c RGBA8 but is intepreted as described when used
212 as a lightProbe or skybox texture.
213
214 \note Using the value \c None will assume the default value of \c RGBA8
215*/
216
217
218QQuick3DTextureDataPrivate::QQuick3DTextureDataPrivate()
219 : QQuick3DObjectPrivate(QQuick3DTextureDataPrivate::Type::TextureData)
220{
221
222}
223
224QQuick3DTextureData::QQuick3DTextureData(QQuick3DObject *parent)
225 : QQuick3DObject(*new QQuick3DTextureDataPrivate, parent)
226{
227
228}
229
230QQuick3DTextureData::~QQuick3DTextureData()
231{
232
233}
234
235/*!
236 Returns the current texture data defined by this item.
237*/
238const QByteArray QQuick3DTextureData::textureData() const
239{
240 const Q_D(QQuick3DTextureData);
241 return d->textureData;
242
243}
244
245/*!
246 Sets the texture data. The contents of \a data must respect the \l size and
247 \l format properties as the backend will try and upload and use the data as if
248 it were a texture of size and format, and if there is any deviation the result
249 will be somewhere between incorrect rendering of the texture, or potentially a crash.
250*/
251
252void QQuick3DTextureData::setTextureData(const QByteArray &data)
253{
254 Q_D(QQuick3DTextureData);
255 d->textureData = data;
256 d->textureDataDirty = true;
257 update();
258}
259
260/*!
261 Returns the size of the texture data in pixels.
262*/
263QSize QQuick3DTextureData::size() const
264{
265 const Q_D(QQuick3DTextureData);
266 return d->size;
267}
268
269/*!
270 Sets the \a size of the texture data in pixels.
271*/
272void QQuick3DTextureData::setSize(const QSize &size)
273{
274 Q_D(QQuick3DTextureData);
275 d->size = size;
276 update();
277}
278
279/*!
280 Returns the depth of the texture data in pixels.
281*/
282int QQuick3DTextureData::depth() const
283{
284 const Q_D(QQuick3DTextureData);
285 return d->depth;
286}
287
288/*!
289 Sets the \a depth of the texture data in pixels. Setting the depth above
290 0 means that the texture is handled as a 3D texture.
291*/
292void QQuick3DTextureData::setDepth(int depth)
293{
294 Q_D(QQuick3DTextureData);
295 d->depth = depth;
296 update();
297}
298
299/*!
300 Returns the format of the texture data.
301*/
302QQuick3DTextureData::Format QQuick3DTextureData::format() const
303{
304 const Q_D(QQuick3DTextureData);
305 return d->format;
306}
307
308/*!
309 Sets the \a format of the texture data.
310
311 The default format is /c RGBA8
312*/
313void QQuick3DTextureData::setFormat(QQuick3DTextureData::Format format)
314{
315 Q_D(QQuick3DTextureData);
316 d->format = format;
317 update();
318}
319
320/*!
321 Returns \c true if the texture data has transparency.
322
323 The default value is \c false.
324*/
325bool QQuick3DTextureData::hasTransparency() const
326{
327 const Q_D(QQuick3DTextureData);
328 return d->hasTransparency;
329}
330
331/*!
332 Set \a hasTransparency to true if the texture data has an active alpha
333 channel with non-opaque values.
334
335 This is used as an optimization by the engine so that for formats that
336 do support an alpha channel do not need to have each value checked for
337 non-opaque values.
338*/
339void QQuick3DTextureData::setHasTransparency(bool hasTransparency)
340{
341 Q_D(QQuick3DTextureData);
342 d->hasTransparency = hasTransparency;
343 update();
344}
345
346
347static QSSGRenderTextureFormat::Format convertToBackendFormat(QQuick3DTextureData::Format format)
348{
349 switch (format) {
350 case QQuick3DTextureData::None:
351 case QQuick3DTextureData::RGBA8:
352 return QSSGRenderTextureFormat::RGBA8;
353 case QQuick3DTextureData::RGBA16F:
354 return QSSGRenderTextureFormat::RGBA16F;
355 case QQuick3DTextureData::RGBA32F:
356 return QSSGRenderTextureFormat::RGBA32F;
357 case QQuick3DTextureData::RGBE8:
358 return QSSGRenderTextureFormat::RGBE8;
359 case QQuick3DTextureData::R8:
360 return QSSGRenderTextureFormat::R8;
361 case QQuick3DTextureData::R16:
362 return QSSGRenderTextureFormat::R16;
363 case QQuick3DTextureData::R16F:
364 return QSSGRenderTextureFormat::R16F;
365 case QQuick3DTextureData::R32F:
366 return QSSGRenderTextureFormat::R32F;
367 case QQuick3DTextureData::BC1:
368 return QSSGRenderTextureFormat::BC1;
369 case QQuick3DTextureData::BC2:
370 return QSSGRenderTextureFormat::BC2;
371 case QQuick3DTextureData::BC3:
372 return QSSGRenderTextureFormat::BC3;
373 case QQuick3DTextureData::BC4:
374 return QSSGRenderTextureFormat::BC4;
375 case QQuick3DTextureData::BC5:
376 return QSSGRenderTextureFormat::BC5;
377 case QQuick3DTextureData::BC6H:
378 return QSSGRenderTextureFormat::BC6H;
379 case QQuick3DTextureData::BC7:
380 return QSSGRenderTextureFormat::BC7;
381 case QQuick3DTextureData::DXT1_RGBA:
382 return QSSGRenderTextureFormat::RGBA_DXT1;
383 case QQuick3DTextureData::DXT1_RGB:
384 return QSSGRenderTextureFormat::RGB_DXT1;
385 case QQuick3DTextureData::DXT3_RGBA:
386 return QSSGRenderTextureFormat::RGBA_DXT3;
387 case QQuick3DTextureData::DXT5_RGBA:
388 return QSSGRenderTextureFormat::RGBA_DXT5;
389 case QQuick3DTextureData::ETC2_RGB8:
390 return QSSGRenderTextureFormat::RGB8_ETC2;
391 case QQuick3DTextureData::ETC2_RGB8A1:
392 return QSSGRenderTextureFormat::RGB8_PunchThrough_Alpha1_ETC2;
393 case QQuick3DTextureData::ETC2_RGBA8:
394 return QSSGRenderTextureFormat::RGBA8_ETC2_EAC;
395 case QQuick3DTextureData::ASTC_4x4:
396 return QSSGRenderTextureFormat::RGBA_ASTC_4x4;
397 case QQuick3DTextureData::ASTC_5x4:
398 return QSSGRenderTextureFormat::RGBA_ASTC_5x4;
399 case QQuick3DTextureData::ASTC_5x5:
400 return QSSGRenderTextureFormat::RGBA_ASTC_5x5;
401 case QQuick3DTextureData::ASTC_6x5:
402 return QSSGRenderTextureFormat::RGBA_ASTC_6x5;
403 case QQuick3DTextureData::ASTC_6x6:
404 return QSSGRenderTextureFormat::RGBA_ASTC_6x6;
405 case QQuick3DTextureData::ASTC_8x5:
406 return QSSGRenderTextureFormat::RGBA_ASTC_8x5;
407 case QQuick3DTextureData::ASTC_8x6:
408 return QSSGRenderTextureFormat::RGBA_ASTC_8x6;
409 case QQuick3DTextureData::ASTC_8x8:
410 return QSSGRenderTextureFormat::RGBA_ASTC_8x8;
411 case QQuick3DTextureData::ASTC_10x5:
412 return QSSGRenderTextureFormat::RGBA_ASTC_10x5;
413 case QQuick3DTextureData::ASTC_10x6:
414 return QSSGRenderTextureFormat::RGBA_ASTC_10x6;
415 case QQuick3DTextureData::ASTC_10x8:
416 return QSSGRenderTextureFormat::RGBA_ASTC_10x8;
417 case QQuick3DTextureData::ASTC_10x10:
418 return QSSGRenderTextureFormat::RGBA_ASTC_10x10;
419 case QQuick3DTextureData::ASTC_12x10:
420 return QSSGRenderTextureFormat::RGBA_ASTC_12x10;
421 case QQuick3DTextureData::ASTC_12x12:
422 return QSSGRenderTextureFormat::RGBA_ASTC_12x12;
423 default:
424 return QSSGRenderTextureFormat::RGBA8;
425 }
426}
427
428/*!
429 \internal
430*/
431QSSGRenderGraphObject *QQuick3DTextureData::updateSpatialNode(QSSGRenderGraphObject *node)
432{
433 Q_D(QQuick3DTextureData);
434 if (!node) {
435 markAllDirty();
436 node = new QSSGRenderTextureData();
437 }
438 QQuick3DObject::updateSpatialNode(node);
439 auto *textureData = static_cast<QSSGRenderTextureData*>(node);
440
441 bool changed = false;
442
443 // Use a dirty flag so we don't compare large buffer values
444 if (d->textureDataDirty) {
445 d->textureDataDirty = false;
446 textureData->setTextureData(d->textureData);
447 changed = true;
448 }
449
450 // Can't use qUpdateIfNeeded unfortunately
451 if (d->size != textureData->size()) {
452 textureData->setSize(d->size);
453 changed = true;
454 }
455
456 if (d->depth != textureData->depth()) {
457 textureData->setDepth(d->depth);
458 changed = true;
459 }
460
461 QSSGRenderTextureFormat format = convertToBackendFormat(d->format);
462 if (format != textureData->format()) {
463 textureData->setFormat(format);
464 changed = true;
465 }
466
467 if (d->hasTransparency != textureData->hasTransparency()) {
468 textureData->setHasTransparency(d->hasTransparency);
469 changed = true;
470 }
471
472 if (changed)
473 emit textureDataNodeDirty();
474
475 DebugViewHelpers::ensureDebugObjectName(textureData, this);
476
477 return node;
478}
479
480void QQuick3DTextureData::markAllDirty()
481{
482 QQuick3DObject::markAllDirty();
483}
484
485
486QT_END_NAMESPACE
Combined button and popup list for selecting options.
static QSSGRenderTextureFormat::Format convertToBackendFormat(QQuick3DTextureData::Format format)