1// Copyright (C) 2019 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
4#include "qquick3dprincipledmaterial_p.h"
5#include "qquick3dobject_p.h"
6
7#include <QtQuick3DRuntimeRender/private/qssgrenderdefaultmaterial_p.h>
8#include <QtQuick3DUtils/private/qssgutils_p.h>
9
10QT_BEGIN_NAMESPACE
11
12/*!
13 \qmltype PrincipledMaterial
14 \inherits Material
15 \inqmlmodule QtQuick3D
16 \brief Lets you define a material for 3D items using the metal/roughness workflow.
17
18 Before a Model can be rendered in a scene, it must have at least one material attached
19 to it that describes how the mesh should be shaded. The PrincipledMaterial is a PBR
20 metal/roughness material that aims at being an easy to use material with a minimal
21 set of parameters.
22 In addition to having few parameters, all input values are strictly normalized
23 between 0 and 1 and have sensible defaults, meaning even without changing any values,
24 the material can be used to shader a model. For an introduction on how the
25 different properties of the principled material affects how a model is shaded,
26 see the \l{Qt Quick 3D - Principled Material Example}{Principled Material example}.
27
28 \section1 Metal/Roughness workflow
29
30 The Principled material is what's known as a metal/roughness material, in essence
31 that means the main characteristics of the material is controlled through
32 the \l {PrincipledMaterial::metalnessMap} {metallness}, \l {PrincipledMaterial::roughnessMap} {roughness},
33 and the \l {PrincipledMaterial::baseColorMap} {base color} property.
34
35 \section2 Metalness
36
37 Real world materials are put into two main categories, metals and dielectrics (non-metals).
38 In the Principled material, the category a material belongs to is decided by the
39 \c metalness value. Setting the \c metalness value to 0, means the material is a dialectric,
40 while everything above 0 is a considered to be a metal. In reality metals will have
41 a \c metalness value of 1, but values between 0 and 1 are possible, and usually used
42 for metals with reduced reflectance. For example, to render corrosion, or similar,
43 on a material, the \c metalness of the material should be reduced to give the output
44 properties more similar to a dielectric material.
45 Since the \c metalness value affects the reflectance of the material it might be tempting to
46 use the metalness to adjust glossiness, but consider what type of material you want
47 to describe first. Increasing the \c metalness value to give a dielectric material
48 a more polished look, will introduce properties that are not accurate for a dielectric
49 material, so consider if it would be more appropriate to adjust, for example,
50 the \c roughness value instead.
51
52 \section2 Roughness
53
54 The \c roughness of a material describes the condition of an object's surface.
55 A low \c roughness value means the object has a smooth surface and therefore be more
56 reflective then a material with a higher \c roughness value.
57
58 \section2 Base color
59
60 The \l {PrincipledMaterial::baseColorMap} {base color} of a metal/roughness material
61 contains both the diffuse and the specular data, how much the base color is interpreted
62 as one or the other is primarily dictated by the \c metalness value. For example,
63 a material with a metalness value of 1, will have most of its base color interpreted
64 as specular color, while the diffuse color would be a black tint. The opposite would
65 happen for a material with a metalness value of 0. This is of course a bit simplified,
66 but gives a rough idea how the \l {PrincipledMaterial::baseColor} {base color} and
67 \c metalness value interacts. For those more familiar with a Specular/Glossiness workflow,
68 there's a clear difference here which is worth noting, namely that the color data of the
69 two materials are not directly compatible, since in a Specular/Glossiness
70 \l {DefaultMaterial} {material}, the diffuse and specular color comes from separate inputs.
71*/
72
73/*!
74 \qmlproperty enumeration PrincipledMaterial::lighting
75
76 This property defines which lighting method is used when generating this
77 material.
78
79 The default value is \c PrincipledMaterial.FragmentLighting
80
81 When using \c PrincipledMaterial.FragmentLighting, diffuse and specular lighting is
82 calculated for each rendered pixel. Certain effects (such as a Fresnel or normal map) require
83 \c PrincipledMaterial.FragmentLighting to work.
84
85 When using \c PrincipledMaterial.NoLighting no lighting is calculated. This
86 mode is (predictably) very fast, and is quite effective when image maps are
87 used that you do not need to be shaded by lighting. All other shading
88 properties except baseColor values, alpha values, and vertex colors will be
89 ignored.
90
91 \value PrincipledMaterial.NoLighting
92 \value PrincipledMaterial.FragmentLighting
93*/
94
95/*!
96 \qmlproperty enumeration PrincipledMaterial::blendMode
97
98 This property determines how the colors of the model rendered blends with
99 those behind it.
100
101 \value PrincipledMaterial.SourceOver Default blend mode. Opaque objects
102 occlude objects behind them. This default mode does not guarantee alpha
103 blending in the rendering pipeline on its own for models that use this
104 material, but rather makes the decision dependent on a number of factors:
105 if the object's and material's total opacity is \c{1.0}, there is no
106 opacity map in the material, and \l alphaMode is not set to a value that
107 enforces alpha blending, then the model is treated as opaque, meaning it is
108 rendered with depth testing and depth write enabled, together with other
109 opaque objects, with blending disabled. Otherwise the model is treated as
110 semi-transparent, and is rendered after the opaque objects, together with
111 other semi-transparent objects in a back-to-front order based on their
112 center's distance from the camera, with alpha blending enabled.
113
114 \value PrincipledMaterial.Screen Colors are blended using an inverted
115 multiply, producing a lighter result. This blend mode is order-independent;
116 if you are using semi-opaque objects and experiencing 'popping' as faces or
117 models sort differently, using Screen blending is one way to produce
118 results without popping.
119
120 \value PrincipledMaterial.Multiply Colors are blended using a multiply,
121 producing a darker result. This blend mode is also order-independent.
122
123 \sa alphaMode, {Qt Quick 3D Architecture}
124*/
125
126/*!
127 \qmlproperty color PrincipledMaterial::baseColor
128
129 This property sets the base color for the material. Depending on the type
130 of material specified (metal or dielectric) the diffuse and specular channels will be
131 set appropriately. For example, a dielectric material will have a diffuse color equal to
132 the base color, while it's specular color, depending on the specular amount, will have a
133 bright specular color. For metals the diffuse and specular channels will be mixed from
134 the base color and have a dark diffuse channel and a specular channel close to the base color.
135
136 \sa baseColorMap, alphaMode
137*/
138
139/*!
140 \qmlproperty Texture PrincipledMaterial::baseColorMap
141
142 This property defines the texture used to set the base color of the material.
143
144 \sa baseColor, alphaMode
145*/
146
147/*!
148 \qmlproperty real PrincipledMaterial::metalness
149
150 The metalness property defines the \e metalness of the the material. The value
151 is normalized, where 0.0 means the material is a \e dielectric (non-metallic) material and
152 a value of 1.0 means the material is a metal.
153
154 \note In principle, materials are either dielectrics with a metalness of 0, or metals with a
155 metalness of 1. Metalness values between 0 and 1 are still allowed and will give a material that
156 is a blend between the different models.
157
158 The range is [0.0, 1.0]. The default value is 0.
159*/
160
161/*!
162 \qmlproperty Texture PrincipledMaterial::metalnessMap
163
164 This property sets a Texture to be used to set the metalness amount for the
165 different parts of the material.
166*/
167
168/*!
169 \qmlproperty enumeration PrincipledMaterial::metalnessChannel
170
171 This property defines the texture channel used to read the metalness value from metalnessMap.
172 The default value is \c Material.B.
173
174 \value Material.R Read value from texture R channel.
175 \value Material.G Read value from texture G channel.
176 \value Material.B Read value from texture B channel.
177 \value Material.A Read value from texture A channel.
178*/
179
180/*!
181 \qmlproperty Texture PrincipledMaterial::emissiveMap
182
183 This property sets a RGB Texture to be used to specify the intensity of the
184 emissive color.
185*/
186
187/*!
188 \qmlproperty vector3d PrincipledMaterial::emissiveFactor
189
190 This property determines the color of self-illumination for this material.
191 If an emissive map is set, the x, y, and z components are used as factors
192 (multipliers) for the R, G and B channels of the texture, respectively.
193 The default value is (0, 0, 0) and it means no emissive contribution at all.
194
195 \note Setting the lightingMode to DefaultMaterial.NoLighting means emissive
196 Factor does not have an effect on the scene.
197*/
198
199/*!
200 \qmlproperty Texture PrincipledMaterial::specularReflectionMap
201
202 This property sets a Texture used for specular highlights on the material.
203
204 This is typically used to perform environment mapping: as the model is
205 rotated, the map will appear as though it is reflecting from the
206 environment. For this to work as expected, the Texture's
207 \l{Texture::mappingMode}{mappingMode} needs to be set to
208 Texture.Environment. Specular reflection maps are an easy way to add a
209 high-quality look with a relatively low cost.
210
211 \note Associating a \l{SceneEnvironment::lightProbe}{light probe} with the
212 \l SceneEnvironment, and thus relying on image-based lighting, can achieve
213 similar environmental reflection effects. Light probes are however a
214 conceptually different, and when it comes to performance, potentially more
215 expensive solution. Each approaches have their own specific uses, and the
216 one to use needs to be decided on a case by case basis. When it comes to
217 the Texture set to the property, specularReflectionMap has an advantage,
218 because it presents no limitations and supports all types of textures,
219 including ones that source their data from a Qt Quick sub-scene via
220 \l{Texture::sourceItem}{sourceItem}.
221
222 \note Crisp images cause your material to look very glossy; the more you
223 blur your image the softer your material will appear.
224
225 \sa Texture::mappingMode
226*/
227
228/*!
229 \qmlproperty Texture PrincipledMaterial::specularMap
230
231 The property defines a RGB Texture to modulate the amount and the color of
232 specularity across the surface of the material. These values are multiplied
233 by the specularAmount.
234
235 \note The specular map will be ignored unless the material is dielectric.
236*/
237
238/*!
239 \qmlproperty real PrincipledMaterial::specularTint
240
241 This property defines how much of the base color contributes to the specular reflections.
242
243 \note This property does only apply to dielectric materials.
244*/
245
246/*!
247 \qmlproperty real PrincipledMaterial::specularAmount
248
249 This property controls the strength of specularity (highlights and
250 reflections).
251
252 The range is [0.0, 1.0]. The default value is \c 1.0.
253
254 \note For non-dielectrics (metals) this property has no effect.
255
256 \note This property does not affect the specularReflectionMap, but does affect the amount of
257 reflections from a scenes SceneEnvironment::lightProbe.
258*/
259
260/*!
261 \qmlproperty real PrincipledMaterial::roughness
262
263 This property controls the size of the specular highlight generated from
264 lights, and the clarity of reflections in general. Larger values increase
265 the roughness, softening specular highlights and blurring reflections.
266 The range is [0.0, 1.0]. The default value is 0.
267*/
268
269/*!
270 \qmlproperty Texture PrincipledMaterial::roughnessMap
271
272 This property defines a Texture to control the specular roughness of the
273 material.
274*/
275
276/*!
277 \qmlproperty enumeration PrincipledMaterial::roughnessChannel
278
279 This property defines the texture channel used to read the roughness value from roughnessMap.
280 The default value is \c Material.G.
281
282 \value Material.R Read value from texture R channel.
283 \value Material.G Read value from texture G channel.
284 \value Material.B Read value from texture B channel.
285 \value Material.A Read value from texture A channel.
286*/
287
288/*!
289 \qmlproperty real PrincipledMaterial::opacity
290
291 This property drops the opacity of just this material, separate from the
292 model.
293*/
294
295/*!
296 \qmlproperty Texture PrincipledMaterial::opacityMap
297
298 This property defines a Texture used to control the opacity differently for
299 different parts of the material.
300*/
301
302/*!
303 \qmlproperty enumeration PrincipledMaterial::opacityChannel
304
305 This property defines the texture channel used to read the opacity value from opacityMap.
306 The default value is \c Material.A.
307
308 \value Material.R Read value from texture R channel.
309 \value Material.G Read value from texture G channel.
310 \value Material.B Read value from texture B channel.
311 \value Material.A Read value from texture A channel.
312*/
313
314/*!
315 \qmlproperty Texture PrincipledMaterial::normalMap
316
317 This property defines an RGB image used to simulate fine geometry
318 displacement across the surface of the material. The RGB channels indicate
319 XYZ normal deviations.
320
321 \note Normal maps will not affect the silhouette of a model.
322*/
323
324/*!
325 \qmlproperty real PrincipledMaterial::normalStrength
326
327 This property controls the amount of simulated displacement for the normalMap.
328*/
329
330/*!
331 \qmlproperty real PrincipledMaterial::occlusionAmount
332
333 This property contains the factor used to modify the values from the \l occlusionMap texture.
334 The value should be between 0.0 to 1.0. The default is 1.0
335*/
336
337/*!
338 \qmlproperty Texture PrincipledMaterial::occlusionMap
339
340 This property defines a texture used to determine how much light the
341 different areas of the material should receive. Values are expected to be
342 linear from 0.0 to 1.0, where 0.0 means no lighting and 1.0 means the
343 effect of the lighting is left unchanged.
344
345 \sa occlusionAmount
346*/
347
348/*!
349 \qmlproperty enumeration PrincipledMaterial::occlusionChannel
350
351 This property defines the texture channel used to read the occlusion value from occlusionMap.
352 The default value is \c Material.R.
353
354 \value Material.R Read value from texture R channel.
355 \value Material.G Read value from texture G channel.
356 \value Material.B Read value from texture B channel.
357 \value Material.A Read value from texture A channel.
358*/
359
360/*!
361 \qmlproperty enumeration PrincipledMaterial::alphaMode
362
363 This property specifies how the alpha color value from \l baseColor and the
364 alpha channel of a \l{baseColorMap}{base color map} are used.
365
366 \note The alpha cutoff test only considers the base color alpha. \l opacity
367 and \l [QtQuick3D] {Node::opacity} are not taken into account there.
368
369 \note When sampling a base color map, the effective alpha value is the
370 sampled alpha multiplied by the \l baseColor alpha.
371
372 \value PrincipledMaterial.Default No test is applied, the effective alpha
373 value is passed on as-is. Note that a \l baseColor or \l baseColorMap alpha
374 less than \c 1.0 does not automatically imply alpha blending, the object
375 with the material may still be treated as opaque, if no other relevant
376 properties (such as, an opacity less than 1, the presence of an opacity
377 map, or a non-default \l blendMode value) trigger treating the object as
378 semi-transparent. To ensure alpha blending happens regardless of any other
379 object or material property, set \c Blend instead.
380
381 \value PrincipledMaterial.Blend No cutoff test is applied, but guarantees
382 that alpha blending happens. The object with this material will therefore
383 never be treated as opaque by the renderer.
384
385 \value PrincipledMaterial.Opaque No cutoff test is applied and the rendered
386 object is assumed to be fully opaque, meaning the alpha values in the
387 vertex color, base color, and base color map are ignored and a value of 1.0
388 is substituted instead. This mode does not guarantee alpha blending does
389 not happen. If relevant properties (such as, an opacity less than 1, an
390 opacity map, or a non-default \l blendMode) say so, then the object will
391 still be treated as semi-transparent by the rendering pipeline, just like
392 with the \c Default alphaMode.
393
394 \value PrincipledMaterial.Mask A test based on \l alphaCutoff is applied.
395 If the effective alpha value falls below \l alphaCutoff, the fragment is
396 changed to fully transparent and is discarded (with all implications of
397 discarding: the depth buffer is not written for that fragment). Otherwise
398 the alpha is changed to 1.0, so that the fragment will become fully opaque.
399 When it comes to alpha blending, the behavior of this mode is identical to
400 \c Opaque, regardless of the cutoff test's result. This means that the
401 \l{https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#alpha-coverage}{glTF
402 2 spec's alpha coverage} Implementation Notes are fulfilled. Objects with
403 alpha cutoff tests can also cast shadows since they behave like opaque
404 objects by default, unless the relevant properties (such as, an opacity
405 less than 1, an opacity map, or a non-default \l blendMode) imply otherwise
406 (in which case casting shadows will not be possible).
407
408 \sa alphaCutoff, blendMode
409*/
410
411/*!
412 \qmlproperty real PrincipledMaterial::alphaCutoff
413
414 The alphaCutoff property can be used to specify the cutoff value when using
415 the \l{alphaMode}{Mask alphaMode}. Fragments where the alpha value falls
416 below the threshold will be rendered fully transparent (\c{0.0} for all
417 color channels). When the alpha value is equal or greater than the cutoff
418 value, the color will not be affected in any way.
419
420 The default value is 0.5.
421
422 \sa alphaMode
423*/
424
425/*!
426 \qmlproperty real PrincipledMaterial::pointSize
427
428 This property determines the size of the points rendered, when the geometry
429 is using a primitive type of points. The default value is 1.0. This
430 property is not relevant when rendering other types of geometry, such as,
431 triangle meshes.
432
433 \warning Point sizes other than 1 may not be supported at run time,
434 depending on the underyling graphics API. For example, setting a size other
435 than 1 has no effect with Direct 3D.
436*/
437
438/*!
439 \qmlproperty real PrincipledMaterial::lineWidth
440
441 This property determines the width of the lines rendered, when the geometry
442 is using a primitive type of lines or line strips. The default value is
443 1.0. This property is not relevant when rendering other types of geometry,
444 such as, triangle meshes.
445
446 \warning Line widths other than 1 may not be suported at run time,
447 depending on the underlying graphics API. When that is the case, the
448 request to change the width is ignored. For example, none of the following
449 can be expected to support wide lines: Direct3D, Metal, OpenGL with core
450 profile contexts.
451*/
452
453/*!
454 \qmlproperty Texture PrincipledMaterial::heightMap
455
456 This property defines a texture used to determine the height the texture
457 will be displaced when rendered through the use of Parallax Mapping. Values
458 are expected to be linear from 0.0 to 1.0, where 0.0 means no displacement
459 and 1.0 means means maximum displacement.
460
461*/
462
463/*!
464 \qmlproperty enumeration PrincipledMaterial::heightChannel
465
466 This property defines the texture channel used to read the height value
467 from heightMap. The default value is \c Material.R.
468
469 \value Material.R Read value from texture R channel.
470 \value Material.G Read value from texture G channel.
471 \value Material.B Read value from texture B channel.
472 \value Material.A Read value from texture A channel.
473
474*/
475
476/*!
477 \qmlproperty real PrincipledMaterial::heightAmount
478
479 This property contains the factor used to modify the values from the
480 \l heightMap texture. The value should be between 0.0 to 1.0. The default
481 value is 0.0 which means that height displacement will be disabled, even
482 if a height map set.
483*/
484
485/*!
486 \qmlproperty int PrincipledMaterial::minHeightMapSamples
487
488 This property defines the minimum number of samples used for performing
489 Parallex Occlusion Mapping using the \l heightMap. The minHeightMapSamples
490 value is the number of samples of the heightMap are used when looking directly
491 at a surface (when the camera view is perpendicular to the fragment).
492 The default value is 8.
493
494 The actual number of samples used for each fragment will be between
495 \l minHeightMapSamples and \l maxHeightMapSamples depending on the angle of
496 the camera relative to the surface being rendered.
497
498 \note This value should only be adjusted to fine tune materials using a
499 \l heightMap in the case undesired artifacts are present.
500*/
501
502/*!
503 \qmlproperty int PrincipledMaterial::maxHeightMapSamples
504
505 This property defines the maximum number of samples used for performing
506 Parallex Occlusion Mapping using the \l heightMap. The maxHeightMapSamples
507 value is the number of samples of the heightMap are used when looking
508 parallel to a surface.
509 The default value is 32.
510
511 The actual number of samples used for each fragment will be between
512 \l minHeightMapSamples and \l maxHeightMapSamples depending on the angle of
513 the camera relative to the surface being rendered.
514
515 \note This value should only be adjusted to fine tune materials using a
516 \l heightMap in the case undesired artifacts are present.
517*/
518
519/*!
520 \qmlproperty float PrincipledMaterial::clearcoatAmount
521
522 This property defines the intensity of the clearcoat layer.
523
524 The default value is \c 0.0
525*/
526
527/*!
528 \qmlproperty Texture PrincipledMaterial::clearcoatMap
529
530 This property defines a texture used to determine the intensity of the
531 clearcoat layer. The value of\l clearcoatAmount will be multiplied by
532 the value read from this texture.
533
534*/
535
536/*!
537 \qmlproperty enumeration PrincipledMaterial::clearcoatChannel
538
539 This property defines the texture channel used to read the clearcoat amount
540 value from \l clearcoatMap. The default value is \c Material.R.
541
542 \value Material.R Read value from texture R channel.
543 \value Material.G Read value from texture G channel.
544 \value Material.B Read value from texture B channel.
545 \value Material.A Read value from texture A channel.
546
547*/
548
549/*!
550 \qmlproperty float PrincipledMaterial::clearcoatRoughnessAmount
551
552 This property defines the roughness of the clearcoat layer.
553 The default value is \c 0.0
554*/
555
556/*!
557 \qmlproperty Texture PrincipledMaterial::clearcoatRoughnessMap
558
559 This property defines a texture used to determine the roughness of the
560 clearcoat layer. The value of\l clearcoatRoughnessAmount will be
561 multiplied by the value read from this texture.
562
563*/
564
565/*!
566 \qmlproperty enumeration PrincipledMaterial::clearcoatRoughnessChannel
567
568 This property defines the texture channel used to read the clearcoat
569 roughness amount from \l clearcoatRoughnessMap.
570 The default value is \c Material.G.
571
572 \value Material.R Read value from texture R channel.
573 \value Material.G Read value from texture G channel.
574 \value Material.B Read value from texture B channel.
575 \value Material.A Read value from texture A channel.
576
577*/
578
579/*!
580 \qmlproperty Texture PrincipledMaterial::clearcoatNormalMap
581
582 This property defines a texture used to determine the normal mapping
583 applied to the clearcoat layer.
584
585*/
586
587/*!
588 \qmlproperty float PrincipledMaterial::transmissionFactor
589
590 This property defines the percentage of light that is transmitted through
591 the material's surface.
592 The default value is \c 0.0
593*/
594
595/*!
596 \qmlproperty Texture PrincipledMaterial::transmissionMap
597
598 This property defines a texture used to determine percentage of light that
599 is transmitted through the surface.. The value of
600 \l transmissionFactor will be multiplied by the value read from this
601 texture.
602
603*/
604
605/*!
606 \qmlproperty enumeration PrincipledMaterial::transmissionChannel
607
608 This property defines the texture channel used to read the transmission
609 percentage from \l transmissionMap.
610 The default value is \c Material.R.
611
612 \value Material.R Read value from texture R channel.
613 \value Material.G Read value from texture G channel.
614 \value Material.B Read value from texture B channel.
615 \value Material.A Read value from texture A channel.
616
617*/
618
619/*!
620 \qmlproperty float PrincipledMaterial::thicknessFactor
621
622 This property defines the thickness of the volume beneath the surface.
623 Unlike many other properties of PrincipledMaterial, the value in defined
624 in thicknessFactor is a value from 0.0 to +infinity for thickness in the
625 models coordinate space. A value of 0.0 means that the material is
626 thin-walled.
627 The default value is \c 0.0
628*/
629
630/*!
631 \qmlproperty Texture PrincipledMaterial::thicknessMap
632
633 This property defines a texture used to define the thickness of a
634 material volume. The value of \l thicknessFactor will be multiplied by the
635 value read from this texture.
636
637*/
638
639/*!
640 \qmlproperty enumeration PrincipledMaterial::thicknessChannel
641
642 This property defines the texture channel used to read the thickness
643 amount from \l transmissionMap.
644 The default value is \c Material.G.
645
646 \value Material.R Read value from texture R channel.
647 \value Material.G Read value from texture G channel.
648 \value Material.B Read value from texture B channel.
649 \value Material.A Read value from texture A channel.
650
651*/
652
653/*!
654 \qmlproperty float PrincipledMaterial::attenuationDistance
655
656 This property defines the Density of the medium given as the average
657 distance that light travels in the medium before interacting with a
658 particle. The value is given in world space.
659 The default value is \c +infinity.
660*/
661
662/*!
663 \qmlproperty color PrincipledMaterial::attenuationColor
664
665 This property defines the color that white lights turns into due to
666 absorption when reaching the attenuation distance.
667 The default value is \c Qt.White
668
669*/
670
671/*!
672 \qmlproperty real PrincipledMaterial::indexOfRefraction
673
674 This property defines the index of refraction of the material. The default
675 value of \c 1.5 will be the ideal value for materials like plastics or glass
676 but other materials like water, asphalt, sapphire, or diamond would require
677 and adjusted value to look more realistic. For realistic materials the
678 indexOfRefraction should usually be between \c 1.0 and \c 3.0
679
680 Some examples of common materials' index of refractions are:
681
682 \table
683 \header
684 \li Material
685 \li Index of Refraction
686 \row
687 \li Air
688 \li 1.0
689 \row
690 \li Water
691 \li 1.33
692 \row
693 \li Glass
694 \li 1.55
695 \row
696 \li Sapphire
697 \li 1.76
698 \row
699 \li Diamond
700 \li 2.42
701 \endtable
702
703 \note No known material in the world have ior much greater than \c 3.0.
704*/
705
706/*!
707 \qmlproperty bool PrincipledMaterial::vertexColorsEnabled
708 \since 6.5
709
710 When this property is enabled, the material will use vertex colors from the
711 mesh. These will be multiplied by any other colors specified for the
712 material. The default value is true.
713*/
714
715inline static float ensureNormalized(float val) { return qBound(min: 0.0f, val, max: 1.0f); }
716
717QQuick3DPrincipledMaterial::QQuick3DPrincipledMaterial(QQuick3DObject *parent)
718 : QQuick3DMaterial(*(new QQuick3DObjectPrivate(QQuick3DObjectPrivate::Type::PrincipledMaterial)), parent)
719{}
720
721QQuick3DPrincipledMaterial::~QQuick3DPrincipledMaterial()
722{
723}
724
725QQuick3DPrincipledMaterial::Lighting QQuick3DPrincipledMaterial::lighting() const
726{
727 return m_lighting;
728}
729
730QQuick3DPrincipledMaterial::BlendMode QQuick3DPrincipledMaterial::blendMode() const
731{
732 return m_blendMode;
733}
734
735QColor QQuick3DPrincipledMaterial::baseColor() const
736{
737 return m_baseColor;
738}
739
740QQuick3DTexture *QQuick3DPrincipledMaterial::baseColorMap() const
741{
742 return m_baseColorMap;
743}
744
745QQuick3DTexture *QQuick3DPrincipledMaterial::emissiveMap() const
746{
747 return m_emissiveMap;
748}
749
750QVector3D QQuick3DPrincipledMaterial::emissiveFactor() const
751{
752 return m_emissiveFactor;
753}
754
755QQuick3DTexture *QQuick3DPrincipledMaterial::specularReflectionMap() const
756{
757 return m_specularReflectionMap;
758}
759
760QQuick3DTexture *QQuick3DPrincipledMaterial::specularMap() const
761{
762 return m_specularMap;
763}
764
765float QQuick3DPrincipledMaterial::specularTint() const
766{
767 return m_specularTint;
768}
769
770float QQuick3DPrincipledMaterial::specularAmount() const
771{
772 return m_specularAmount;
773}
774
775float QQuick3DPrincipledMaterial::roughness() const
776{
777 return m_roughness;
778}
779
780QQuick3DTexture *QQuick3DPrincipledMaterial::roughnessMap() const
781{
782 return m_roughnessMap;
783}
784
785float QQuick3DPrincipledMaterial::opacity() const
786{
787 return m_opacity;
788}
789
790QQuick3DTexture *QQuick3DPrincipledMaterial::opacityMap() const
791{
792 return m_opacityMap;
793}
794
795QQuick3DTexture *QQuick3DPrincipledMaterial::normalMap() const
796{
797 return m_normalMap;
798}
799
800float QQuick3DPrincipledMaterial::metalness() const
801{
802 return m_metalnessAmount;
803}
804
805QQuick3DTexture *QQuick3DPrincipledMaterial::metalnessMap() const
806{
807 return m_metalnessMap;
808}
809
810float QQuick3DPrincipledMaterial::normalStrength() const
811{
812 return m_normalStrength;
813}
814
815QQuick3DTexture *QQuick3DPrincipledMaterial::occlusionMap() const
816{
817 return m_occlusionMap;
818}
819
820float QQuick3DPrincipledMaterial::occlusionAmount() const
821{
822 return m_occlusionAmount;
823}
824
825QQuick3DPrincipledMaterial::AlphaMode QQuick3DPrincipledMaterial::alphaMode() const
826{
827 return m_alphaMode;
828}
829
830float QQuick3DPrincipledMaterial::alphaCutoff() const
831{
832 return m_alphaCutoff;
833}
834
835QQuick3DMaterial::TextureChannelMapping QQuick3DPrincipledMaterial::roughnessChannel() const
836{
837 return m_roughnessChannel;
838}
839
840QQuick3DMaterial::TextureChannelMapping QQuick3DPrincipledMaterial::opacityChannel() const
841{
842 return m_opacityChannel;
843}
844
845QQuick3DMaterial::TextureChannelMapping QQuick3DPrincipledMaterial::metalnessChannel() const
846{
847 return m_metalnessChannel;
848}
849
850QQuick3DMaterial::TextureChannelMapping QQuick3DPrincipledMaterial::occlusionChannel() const
851{
852 return m_occlusionChannel;
853}
854
855float QQuick3DPrincipledMaterial::pointSize() const
856{
857 return m_pointSize;
858}
859
860float QQuick3DPrincipledMaterial::lineWidth() const
861{
862 return m_lineWidth;
863}
864
865QQuick3DTexture *QQuick3DPrincipledMaterial::heightMap() const
866{
867 return m_heightMap;
868}
869
870QQuick3DMaterial::TextureChannelMapping QQuick3DPrincipledMaterial::heightChannel() const
871{
872 return m_heightChannel;
873}
874
875float QQuick3DPrincipledMaterial::heightAmount() const
876{
877 return m_heightAmount;
878}
879
880int QQuick3DPrincipledMaterial::minHeightMapSamples() const
881{
882 return m_minHeightMapSamples;
883}
884
885int QQuick3DPrincipledMaterial::maxHeightMapSamples() const
886{
887 return m_maxHeightMapSamples;
888}
889
890void QQuick3DPrincipledMaterial::markAllDirty()
891{
892 m_dirtyAttributes = 0xffffffff;
893 QQuick3DMaterial::markAllDirty();
894}
895
896void QQuick3DPrincipledMaterial::setLighting(QQuick3DPrincipledMaterial::Lighting lighting)
897{
898 if (m_lighting == lighting)
899 return;
900
901 m_lighting = lighting;
902 emit lightingChanged(lighting: m_lighting);
903 markDirty(type: LightingModeDirty);
904}
905
906void QQuick3DPrincipledMaterial::setBlendMode(QQuick3DPrincipledMaterial::BlendMode blendMode)
907{
908 if (m_blendMode == blendMode)
909 return;
910
911 m_blendMode = blendMode;
912 emit blendModeChanged(blendMode: m_blendMode);
913 markDirty(type: BlendModeDirty);
914}
915
916void QQuick3DPrincipledMaterial::setBaseColor(QColor diffuseColor)
917{
918 if (m_baseColor == diffuseColor)
919 return;
920
921 m_baseColor = diffuseColor;
922 emit baseColorChanged(baseColor: m_baseColor);
923 markDirty(type: BaseColorDirty);
924}
925
926void QQuick3DPrincipledMaterial::setBaseColorMap(QQuick3DTexture *baseColorMap)
927{
928 if (m_baseColorMap == baseColorMap)
929 return;
930
931 QQuick3DObjectPrivate::attachWatcher(context: this, setter: &QQuick3DPrincipledMaterial::setBaseColorMap, newO: baseColorMap, oldO: m_baseColorMap);
932
933 m_baseColorMap = baseColorMap;
934 emit baseColorMapChanged(baseColorMap: m_baseColorMap);
935 markDirty(type: BaseColorDirty);
936}
937
938void QQuick3DPrincipledMaterial::setEmissiveMap(QQuick3DTexture *emissiveMap)
939{
940 if (m_emissiveMap == emissiveMap)
941 return;
942
943 QQuick3DObjectPrivate::attachWatcher(context: this, setter: &QQuick3DPrincipledMaterial::setEmissiveMap, newO: emissiveMap, oldO: m_emissiveMap);
944
945 m_emissiveMap = emissiveMap;
946 emit emissiveMapChanged(emissiveMap: m_emissiveMap);
947 markDirty(type: EmissiveDirty);
948}
949
950void QQuick3DPrincipledMaterial::setEmissiveFactor(QVector3D emissiveFactor)
951{
952 if (m_emissiveFactor == emissiveFactor)
953 return;
954
955 m_emissiveFactor = emissiveFactor;
956 emit emissiveFactorChanged(emissiveFactor: m_emissiveFactor);
957 markDirty(type: EmissiveDirty);
958}
959
960void QQuick3DPrincipledMaterial::setSpecularReflectionMap(QQuick3DTexture *specularReflectionMap)
961{
962 if (m_specularReflectionMap == specularReflectionMap)
963 return;
964
965 QQuick3DObjectPrivate::attachWatcher(context: this, setter: &QQuick3DPrincipledMaterial::setSpecularReflectionMap, newO: specularReflectionMap, oldO: m_specularReflectionMap);
966
967 m_specularReflectionMap = specularReflectionMap;
968 emit specularReflectionMapChanged(specularReflectionMap: m_specularReflectionMap);
969 markDirty(type: SpecularDirty);
970}
971
972void QQuick3DPrincipledMaterial::setSpecularMap(QQuick3DTexture *specularMap)
973{
974 if (m_specularMap == specularMap)
975 return;
976
977 QQuick3DObjectPrivate::attachWatcher(context: this, setter: &QQuick3DPrincipledMaterial::setSpecularMap, newO: specularMap, oldO: m_specularMap);
978
979 m_specularMap = specularMap;
980 emit specularMapChanged(specularMap: m_specularMap);
981 markDirty(type: SpecularDirty);
982}
983
984void QQuick3DPrincipledMaterial::setSpecularTint(float specularTint)
985{
986 specularTint = ensureNormalized(val: specularTint);
987 if (qFuzzyCompare(p1: m_specularTint, p2: specularTint))
988 return;
989
990 m_specularTint = specularTint;
991 emit specularTintChanged(specularTint: m_specularTint);
992 markDirty(type: SpecularDirty);
993}
994
995void QQuick3DPrincipledMaterial::setSpecularAmount(float specularAmount)
996{
997 specularAmount = ensureNormalized(val: specularAmount);
998 if (qFuzzyCompare(p1: m_specularAmount, p2: specularAmount))
999 return;
1000
1001 m_specularAmount = specularAmount;
1002 emit specularAmountChanged(specularAmount: m_specularAmount);
1003 markDirty(type: SpecularDirty);
1004}
1005
1006void QQuick3DPrincipledMaterial::setRoughness(float roughness)
1007{
1008 roughness = ensureNormalized(val: roughness);
1009 if (qFuzzyCompare(p1: m_roughness, p2: roughness))
1010 return;
1011
1012 m_roughness = roughness;
1013 emit roughnessChanged(roughness: m_roughness);
1014 markDirty(type: RoughnessDirty);
1015}
1016
1017void QQuick3DPrincipledMaterial::setRoughnessMap(QQuick3DTexture *roughnessMap)
1018{
1019 if (m_roughnessMap == roughnessMap)
1020 return;
1021
1022 QQuick3DObjectPrivate::attachWatcher(context: this, setter: &QQuick3DPrincipledMaterial::setRoughnessMap, newO: roughnessMap, oldO: m_roughnessMap);
1023
1024 m_roughnessMap = roughnessMap;
1025 emit roughnessMapChanged(roughnessMap: m_roughnessMap);
1026 markDirty(type: RoughnessDirty);
1027}
1028
1029void QQuick3DPrincipledMaterial::setOpacity(float opacity)
1030{
1031 opacity = ensureNormalized(val: opacity);
1032 if (qFuzzyCompare(p1: m_opacity, p2: opacity))
1033 return;
1034
1035 m_opacity = opacity;
1036 emit opacityChanged(opacity: m_opacity);
1037 markDirty(type: OpacityDirty);
1038}
1039
1040void QQuick3DPrincipledMaterial::setOpacityMap(QQuick3DTexture *opacityMap)
1041{
1042 if (m_opacityMap == opacityMap)
1043 return;
1044
1045 QQuick3DObjectPrivate::attachWatcher(context: this, setter: &::QQuick3DPrincipledMaterial::setOpacityMap, newO: opacityMap, oldO: m_opacityMap);
1046
1047 m_opacityMap = opacityMap;
1048 emit opacityMapChanged(opacityMap: m_opacityMap);
1049 markDirty(type: OpacityDirty);
1050}
1051
1052void QQuick3DPrincipledMaterial::setNormalMap(QQuick3DTexture *normalMap)
1053{
1054 if (m_normalMap == normalMap)
1055 return;
1056
1057 QQuick3DObjectPrivate::attachWatcher(context: this, setter: &QQuick3DPrincipledMaterial::setNormalMap, newO: normalMap, oldO: m_normalMap);
1058
1059 m_normalMap = normalMap;
1060 emit normalMapChanged(normalMap: m_normalMap);
1061 markDirty(type: NormalDirty);
1062}
1063
1064void QQuick3DPrincipledMaterial::setMetalness(float metalnessAmount)
1065{
1066 metalnessAmount = ensureNormalized(val: metalnessAmount);
1067 if (qFuzzyCompare(p1: m_metalnessAmount, p2: metalnessAmount))
1068 return;
1069
1070 m_metalnessAmount = metalnessAmount;
1071 emit metalnessChanged(metalness: m_metalnessAmount);
1072 markDirty(type: MetalnessDirty);
1073}
1074
1075void QQuick3DPrincipledMaterial::setMetalnessMap(QQuick3DTexture *metallicMap)
1076{
1077 if (m_metalnessMap == metallicMap)
1078 return;
1079
1080 QQuick3DObjectPrivate::attachWatcher(context: this, setter: &QQuick3DPrincipledMaterial::setMetalnessMap, newO: metallicMap, oldO: m_metalnessMap);
1081
1082 m_metalnessMap = metallicMap;
1083 emit metalnessMapChanged(metalnessMap: m_metalnessMap);
1084 markDirty(type: MetalnessDirty);
1085}
1086
1087void QQuick3DPrincipledMaterial::setNormalStrength(float factor)
1088{
1089 factor = ensureNormalized(val: factor);
1090 if (qFuzzyCompare(p1: m_normalStrength, p2: factor))
1091 return;
1092
1093 m_normalStrength = factor;
1094 emit normalStrengthChanged(normalStrength: m_normalStrength);
1095 markDirty(type: NormalDirty);
1096}
1097
1098void QQuick3DPrincipledMaterial::setOcclusionMap(QQuick3DTexture *occlusionMap)
1099{
1100 if (m_occlusionMap == occlusionMap)
1101 return;
1102
1103 QQuick3DObjectPrivate::attachWatcher(context: this, setter: &QQuick3DPrincipledMaterial::setOcclusionMap, newO: occlusionMap, oldO: m_occlusionMap);
1104
1105 m_occlusionMap = occlusionMap;
1106 emit occlusionMapChanged(occlusionMap: m_occlusionMap);
1107 markDirty(type: OcclusionDirty);
1108}
1109
1110void QQuick3DPrincipledMaterial::setOcclusionAmount(float occlusionAmount)
1111{
1112 if (qFuzzyCompare(p1: m_occlusionAmount, p2: occlusionAmount))
1113 return;
1114
1115 m_occlusionAmount = occlusionAmount;
1116 emit occlusionAmountChanged(occlusionAmount: m_occlusionAmount);
1117 markDirty(type: OcclusionDirty);
1118}
1119
1120void QQuick3DPrincipledMaterial::setAlphaMode(QQuick3DPrincipledMaterial::AlphaMode alphaMode)
1121{
1122 if (m_alphaMode == alphaMode)
1123 return;
1124
1125 m_alphaMode = alphaMode;
1126 emit alphaModeChanged(alphaMode: m_alphaMode);
1127 markDirty(type: AlphaModeDirty);
1128}
1129
1130void QQuick3DPrincipledMaterial::setAlphaCutoff(float alphaCutoff)
1131{
1132 if (qFuzzyCompare(p1: m_alphaCutoff, p2: alphaCutoff))
1133 return;
1134
1135 m_alphaCutoff = alphaCutoff;
1136 emit alphaCutoffChanged(alphaCutoff: m_alphaCutoff);
1137 markDirty(type: AlphaModeDirty);
1138}
1139
1140void QQuick3DPrincipledMaterial::setMetalnessChannel(TextureChannelMapping channel)
1141{
1142 if (m_metalnessChannel == channel)
1143 return;
1144
1145 m_metalnessChannel = channel;
1146 emit metalnessChannelChanged(channel);
1147 markDirty(type: MetalnessDirty);
1148}
1149
1150void QQuick3DPrincipledMaterial::setRoughnessChannel(TextureChannelMapping channel)
1151{
1152 if (m_roughnessChannel == channel)
1153 return;
1154
1155 m_roughnessChannel = channel;
1156 emit roughnessChannelChanged(channel);
1157 markDirty(type: RoughnessDirty);
1158}
1159
1160void QQuick3DPrincipledMaterial::setOpacityChannel(TextureChannelMapping channel)
1161{
1162 if (m_opacityChannel == channel)
1163 return;
1164
1165 m_opacityChannel = channel;
1166 emit opacityChannelChanged(channel);
1167 markDirty(type: OpacityDirty);
1168}
1169
1170void QQuick3DPrincipledMaterial::setOcclusionChannel(TextureChannelMapping channel)
1171{
1172 if (m_occlusionChannel == channel)
1173 return;
1174
1175 m_occlusionChannel = channel;
1176 emit occlusionChannelChanged(channel);
1177 markDirty(type: OcclusionDirty);
1178}
1179
1180void QQuick3DPrincipledMaterial::setPointSize(float size)
1181{
1182 if (qFuzzyCompare(p1: m_pointSize, p2: size))
1183 return;
1184 m_pointSize = size;
1185 emit pointSizeChanged();
1186 markDirty(type: PointSizeDirty);
1187}
1188
1189void QQuick3DPrincipledMaterial::setLineWidth(float width)
1190{
1191 if (qFuzzyCompare(p1: m_lineWidth, p2: width))
1192 return;
1193 m_lineWidth = width;
1194 emit lineWidthChanged();
1195 markDirty(type: LineWidthDirty);
1196}
1197
1198void QQuick3DPrincipledMaterial::setHeightMap(QQuick3DTexture *heightMap)
1199{
1200 if (m_heightMap == heightMap)
1201 return;
1202
1203 QQuick3DObjectPrivate::attachWatcher(context: this, setter: &QQuick3DPrincipledMaterial::setHeightMap, newO: heightMap, oldO: m_heightMap);
1204
1205 m_heightMap = heightMap;
1206 emit heightMapChanged(heightMap: m_heightMap);
1207 markDirty(type: HeightDirty);
1208}
1209
1210void QQuick3DPrincipledMaterial::setHeightChannel(QQuick3DMaterial::TextureChannelMapping channel)
1211{
1212 if (m_heightChannel == channel)
1213 return;
1214
1215 m_heightChannel = channel;
1216 emit heightChannelChanged(channel: m_heightChannel);
1217 markDirty(type: HeightDirty);
1218}
1219
1220void QQuick3DPrincipledMaterial::setHeightAmount(float heightAmount)
1221{
1222 if (m_heightAmount == heightAmount)
1223 return;
1224
1225 m_heightAmount = heightAmount;
1226 emit heightAmountChanged(heightAmount: m_heightAmount);
1227 markDirty(type: HeightDirty);
1228}
1229
1230void QQuick3DPrincipledMaterial::setMinHeightMapSamples(int samples)
1231{
1232 if (m_minHeightMapSamples == samples)
1233 return;
1234
1235 m_minHeightMapSamples = samples;
1236 emit minHeightMapSamplesChanged(samples);
1237 markDirty(type: HeightDirty);
1238}
1239
1240void QQuick3DPrincipledMaterial::setMaxHeightMapSamples(int samples)
1241{
1242 if (m_maxHeightMapSamples == samples)
1243 return;
1244
1245 m_maxHeightMapSamples = samples;
1246 emit maxHeightMapSamplesChanged(samples);
1247 markDirty(type: HeightDirty);
1248}
1249
1250QSSGRenderGraphObject *QQuick3DPrincipledMaterial::updateSpatialNode(QSSGRenderGraphObject *node)
1251{
1252 static const auto channelMapping = [](TextureChannelMapping mapping) {
1253 return QSSGRenderDefaultMaterial::TextureChannelMapping(mapping);
1254 };
1255
1256 if (!node) {
1257 markAllDirty();
1258 node = new QSSGRenderDefaultMaterial(QSSGRenderGraphObject::Type::PrincipledMaterial);
1259 }
1260
1261 // Set common material properties
1262 QQuick3DMaterial::updateSpatialNode(node);
1263
1264 QSSGRenderDefaultMaterial *material = static_cast<QSSGRenderDefaultMaterial *>(node);
1265
1266 material->specularModel = QSSGRenderDefaultMaterial::MaterialSpecularModel::KGGX;
1267
1268 if (m_dirtyAttributes & LightingModeDirty)
1269 material->lighting = QSSGRenderDefaultMaterial::MaterialLighting(m_lighting);
1270
1271 if (m_dirtyAttributes & BlendModeDirty)
1272 material->blendMode = QSSGRenderDefaultMaterial::MaterialBlendMode(m_blendMode);
1273
1274 if (m_dirtyAttributes & BaseColorDirty) {
1275 if (!m_baseColorMap)
1276 material->colorMap = nullptr;
1277 else
1278 material->colorMap = m_baseColorMap->getRenderImage();
1279
1280 material->color = QSSGUtils::color::sRGBToLinear(color: m_baseColor);
1281 }
1282
1283 if (m_dirtyAttributes & EmissiveDirty) {
1284 if (!m_emissiveMap)
1285 material->emissiveMap = nullptr;
1286 else
1287 material->emissiveMap = m_emissiveMap->getRenderImage();
1288
1289 material->emissiveColor = m_emissiveFactor;
1290 }
1291
1292 material->fresnelPower = 5.0f;
1293 material->vertexColorsEnabled = false;
1294
1295 if (m_dirtyAttributes & RoughnessDirty) {
1296 if (!m_roughnessMap)
1297 material->roughnessMap = nullptr;
1298 else
1299 material->roughnessMap = m_roughnessMap->getRenderImage();
1300
1301 material->specularRoughness = m_roughness;
1302 material->roughnessChannel = channelMapping(m_roughnessChannel);
1303 }
1304
1305 if (m_dirtyAttributes & MetalnessDirty) {
1306 if (!m_metalnessMap)
1307 material->metalnessMap = nullptr;
1308 else
1309 material->metalnessMap = m_metalnessMap->getRenderImage();
1310
1311 material->metalnessAmount = m_metalnessAmount;
1312 material->metalnessChannel = channelMapping(m_metalnessChannel);
1313
1314 }
1315
1316 if (m_dirtyAttributes & SpecularDirty) {
1317 if (!m_specularReflectionMap)
1318 material->specularReflection = nullptr;
1319 else
1320 material->specularReflection = m_specularReflectionMap->getRenderImage();
1321
1322 if (!m_specularMap) {
1323 material->specularMap = nullptr;
1324 } else {
1325 material->specularMap = m_specularMap->getRenderImage();
1326 }
1327
1328 material->specularAmount = m_specularAmount;
1329 material->specularTint = QVector3D(m_specularTint, m_specularTint, m_specularTint);
1330 material->ior = m_indexOfRefraction;
1331 }
1332
1333 if (m_dirtyAttributes & OpacityDirty) {
1334 material->opacity = m_opacity;
1335 if (!m_opacityMap)
1336 material->opacityMap = nullptr;
1337 else
1338 material->opacityMap = m_opacityMap->getRenderImage();
1339
1340 material->opacity = m_opacity;
1341 material->opacityChannel = channelMapping(m_opacityChannel);
1342 }
1343
1344 if (m_dirtyAttributes & NormalDirty) {
1345 if (!m_normalMap)
1346 material->normalMap = nullptr;
1347 else
1348 material->normalMap = m_normalMap->getRenderImage();
1349
1350 material->bumpAmount = m_normalStrength;
1351 }
1352
1353 if (m_dirtyAttributes & OcclusionDirty) {
1354 if (!m_occlusionMap)
1355 material->occlusionMap = nullptr;
1356 else
1357 material->occlusionMap = m_occlusionMap->getRenderImage();
1358 material->occlusionAmount = m_occlusionAmount;
1359 material->occlusionChannel = channelMapping(m_occlusionChannel);
1360 }
1361
1362 if (m_dirtyAttributes & AlphaModeDirty) {
1363 material->alphaMode = QSSGRenderDefaultMaterial::MaterialAlphaMode(m_alphaMode);
1364 material->alphaCutoff = m_alphaCutoff;
1365 }
1366
1367 if (m_dirtyAttributes & PointSizeDirty)
1368 material->pointSize = m_pointSize;
1369
1370 if (m_dirtyAttributes & LineWidthDirty)
1371 material->lineWidth = m_lineWidth;
1372
1373 if (m_dirtyAttributes & HeightDirty) {
1374 if (!m_heightMap)
1375 material->heightMap = nullptr;
1376 else
1377 material->heightMap = m_heightMap->getRenderImage();
1378 material->heightAmount = m_heightAmount;
1379 material->minHeightSamples = m_minHeightMapSamples;
1380 material->maxHeightSamples = m_maxHeightMapSamples;
1381 material->heightChannel = channelMapping(m_heightChannel);
1382 }
1383
1384 if (m_dirtyAttributes & ClearcoatDirty) {
1385 material->clearcoatAmount = m_clearcoatAmount;
1386 if (!m_clearcoatMap)
1387 material->clearcoatMap = nullptr;
1388 else
1389 material->clearcoatMap = m_clearcoatMap->getRenderImage();
1390 material->clearcoatChannel = channelMapping(m_clearcoatChannel);
1391 material->clearcoatRoughnessAmount = m_clearcoatRoughnessAmount;
1392 if (!m_clearcoatRoughnessMap)
1393 material->clearcoatRoughnessMap = nullptr;
1394 else
1395 material->clearcoatRoughnessMap = m_clearcoatRoughnessMap->getRenderImage();
1396 material->clearcoatRoughnessChannel = channelMapping(m_clearcoatRoughnessChannel);
1397 if (!m_clearcoatNormalMap)
1398 material->clearcoatNormalMap = nullptr;
1399 else
1400 material->clearcoatNormalMap = m_clearcoatNormalMap->getRenderImage();
1401 }
1402
1403 if (m_dirtyAttributes & TransmissionDirty) {
1404 material->transmissionFactor = m_transmissionFactor;
1405 if (!m_transmissionMap)
1406 material->transmissionMap = nullptr;
1407 else
1408 material->transmissionMap = m_transmissionMap->getRenderImage();
1409 material->transmissionChannel = channelMapping(m_transmissionChannel);
1410 }
1411
1412 if (m_dirtyAttributes & VolumeDirty) {
1413 material->thicknessFactor = m_thicknessFactor;
1414 if (!m_thicknessMap)
1415 material->thicknessMap = nullptr;
1416 else
1417 material->thicknessMap = m_thicknessMap->getRenderImage();
1418 material->thicknessChannel = channelMapping(m_thicknessChannel);
1419
1420 material->attenuationDistance = m_attenuationDistance;
1421 material->attenuationColor = QSSGUtils::color::sRGBToLinear(color: m_attenuationColor).toVector3D();
1422 }
1423
1424 if (m_dirtyAttributes & VertexColorsDirty)
1425 material->vertexColorsEnabled = m_vertexColorsEnabled;
1426
1427 m_dirtyAttributes = 0;
1428
1429 return node;
1430}
1431
1432void QQuick3DPrincipledMaterial::itemChange(QQuick3DObject::ItemChange change, const QQuick3DObject::ItemChangeData &value)
1433{
1434 if (change == QQuick3DObject::ItemSceneChange)
1435 updateSceneManager(window: value.sceneManager);
1436}
1437
1438void QQuick3DPrincipledMaterial::updateSceneManager(QQuick3DSceneManager *sceneManager)
1439{
1440 // Check all the resource value's scene manager, and update as necessary.
1441 if (sceneManager) {
1442 QQuick3DObjectPrivate::refSceneManager(obj: m_baseColorMap, mgr&: *sceneManager);
1443 QQuick3DObjectPrivate::refSceneManager(obj: m_emissiveMap, mgr&: *sceneManager);
1444 QQuick3DObjectPrivate::refSceneManager(obj: m_specularReflectionMap, mgr&: *sceneManager);
1445 QQuick3DObjectPrivate::refSceneManager(obj: m_specularMap, mgr&: *sceneManager);
1446 QQuick3DObjectPrivate::refSceneManager(obj: m_roughnessMap, mgr&: *sceneManager);
1447 QQuick3DObjectPrivate::refSceneManager(obj: m_opacityMap, mgr&: *sceneManager);
1448 QQuick3DObjectPrivate::refSceneManager(obj: m_normalMap, mgr&: *sceneManager);
1449 QQuick3DObjectPrivate::refSceneManager(obj: m_metalnessMap, mgr&: *sceneManager);
1450 QQuick3DObjectPrivate::refSceneManager(obj: m_occlusionMap, mgr&: *sceneManager);
1451 QQuick3DObjectPrivate::refSceneManager(obj: m_heightMap, mgr&: *sceneManager);
1452 QQuick3DObjectPrivate::refSceneManager(obj: m_clearcoatMap, mgr&: *sceneManager);
1453 QQuick3DObjectPrivate::refSceneManager(obj: m_clearcoatRoughnessMap, mgr&: *sceneManager);
1454 QQuick3DObjectPrivate::refSceneManager(obj: m_clearcoatNormalMap, mgr&: *sceneManager);
1455 QQuick3DObjectPrivate::refSceneManager(obj: m_transmissionMap, mgr&: *sceneManager);
1456 QQuick3DObjectPrivate::refSceneManager(obj: m_thicknessMap, mgr&: *sceneManager);
1457 } else {
1458 QQuick3DObjectPrivate::derefSceneManager(obj: m_baseColorMap);
1459 QQuick3DObjectPrivate::derefSceneManager(obj: m_emissiveMap);
1460 QQuick3DObjectPrivate::derefSceneManager(obj: m_specularReflectionMap);
1461 QQuick3DObjectPrivate::derefSceneManager(obj: m_specularMap);
1462 QQuick3DObjectPrivate::derefSceneManager(obj: m_roughnessMap);
1463 QQuick3DObjectPrivate::derefSceneManager(obj: m_opacityMap);
1464 QQuick3DObjectPrivate::derefSceneManager(obj: m_normalMap);
1465 QQuick3DObjectPrivate::derefSceneManager(obj: m_metalnessMap);
1466 QQuick3DObjectPrivate::derefSceneManager(obj: m_occlusionMap);
1467 QQuick3DObjectPrivate::derefSceneManager(obj: m_heightMap);
1468 QQuick3DObjectPrivate::derefSceneManager(obj: m_clearcoatMap);
1469 QQuick3DObjectPrivate::derefSceneManager(obj: m_clearcoatRoughnessMap);
1470 QQuick3DObjectPrivate::derefSceneManager(obj: m_clearcoatNormalMap);
1471 QQuick3DObjectPrivate::derefSceneManager(obj: m_transmissionMap);
1472 QQuick3DObjectPrivate::derefSceneManager(obj: m_thicknessMap);
1473 }
1474}
1475
1476void QQuick3DPrincipledMaterial::markDirty(QQuick3DPrincipledMaterial::DirtyType type)
1477{
1478 if (!(m_dirtyAttributes & quint32(type))) {
1479 m_dirtyAttributes |= quint32(type);
1480 update();
1481 }
1482}
1483
1484float QQuick3DPrincipledMaterial::clearcoatAmount() const
1485{
1486 return m_clearcoatAmount;
1487}
1488
1489void QQuick3DPrincipledMaterial::setClearcoatAmount(float newClearcoatAmount)
1490{
1491 if (qFuzzyCompare(p1: m_clearcoatAmount, p2: newClearcoatAmount))
1492 return;
1493 m_clearcoatAmount = newClearcoatAmount;
1494 emit clearcoatAmountChanged(amount: m_clearcoatAmount);
1495 markDirty(type: ClearcoatDirty);
1496}
1497
1498QQuick3DTexture *QQuick3DPrincipledMaterial::clearcoatMap() const
1499{
1500 return m_clearcoatMap;
1501}
1502
1503void QQuick3DPrincipledMaterial::setClearcoatMap(QQuick3DTexture *newClearcoatMap)
1504{
1505 if (m_clearcoatMap == newClearcoatMap)
1506 return;
1507
1508 QQuick3DObjectPrivate::attachWatcher(context: this, setter: &QQuick3DPrincipledMaterial::setClearcoatMap, newO: newClearcoatMap, oldO: m_clearcoatMap);
1509
1510 m_clearcoatMap = newClearcoatMap;
1511 emit clearcoatMapChanged(texture: m_clearcoatMap);
1512 markDirty(type: ClearcoatDirty);
1513}
1514
1515QQuick3DMaterial::TextureChannelMapping QQuick3DPrincipledMaterial::clearcoatChannel() const
1516{
1517 return m_clearcoatChannel;
1518}
1519
1520void QQuick3DPrincipledMaterial::setClearcoatChannel(QQuick3DMaterial::TextureChannelMapping newClearcoatChannel)
1521{
1522 if (m_clearcoatChannel == newClearcoatChannel)
1523 return;
1524 m_clearcoatChannel = newClearcoatChannel;
1525 emit clearcoatChannelChanged(channel: m_clearcoatChannel);
1526 markDirty(type: ClearcoatDirty);
1527}
1528
1529float QQuick3DPrincipledMaterial::clearcoatRoughnessAmount() const
1530{
1531 return m_clearcoatRoughnessAmount;
1532}
1533
1534void QQuick3DPrincipledMaterial::setClearcoatRoughnessAmount(float newClearcoatRoughnessAmount)
1535{
1536 if (qFuzzyCompare(p1: m_clearcoatRoughnessAmount, p2: newClearcoatRoughnessAmount))
1537 return;
1538 m_clearcoatRoughnessAmount = newClearcoatRoughnessAmount;
1539 emit clearcoatRoughnessAmountChanged(amount: m_clearcoatRoughnessAmount);
1540 markDirty(type: ClearcoatDirty);
1541}
1542
1543QQuick3DMaterial::TextureChannelMapping QQuick3DPrincipledMaterial::clearcoatRoughnessChannel() const
1544{
1545 return m_clearcoatRoughnessChannel;
1546}
1547
1548void QQuick3DPrincipledMaterial::setClearcoatRoughnessChannel(QQuick3DMaterial::TextureChannelMapping newClearcoatRoughnessChannel)
1549{
1550 if (m_clearcoatRoughnessChannel == newClearcoatRoughnessChannel)
1551 return;
1552 m_clearcoatRoughnessChannel = newClearcoatRoughnessChannel;
1553 emit clearcoatRoughnessChannelChanged(channel: m_clearcoatRoughnessChannel);
1554 markDirty(type: ClearcoatDirty);
1555}
1556
1557QQuick3DTexture *QQuick3DPrincipledMaterial::clearcoatRoughnessMap() const
1558{
1559 return m_clearcoatRoughnessMap;
1560}
1561
1562void QQuick3DPrincipledMaterial::setClearcoatRoughnessMap(QQuick3DTexture *newClearcoatRoughnessMap)
1563{
1564 if (m_clearcoatRoughnessMap == newClearcoatRoughnessMap)
1565 return;
1566
1567 QQuick3DObjectPrivate::attachWatcher(context: this, setter: &QQuick3DPrincipledMaterial::setClearcoatRoughnessMap, newO: newClearcoatRoughnessMap, oldO: m_clearcoatRoughnessMap);
1568
1569 m_clearcoatRoughnessMap = newClearcoatRoughnessMap;
1570 emit clearcoatRoughnessMapChanged(texture: m_clearcoatRoughnessMap);
1571 markDirty(type: ClearcoatDirty);
1572}
1573
1574QQuick3DTexture *QQuick3DPrincipledMaterial::clearcoatNormalMap() const
1575{
1576 return m_clearcoatNormalMap;
1577}
1578
1579void QQuick3DPrincipledMaterial::setClearcoatNormalMap(QQuick3DTexture *newClearcoatNormalMap)
1580{
1581 if (m_clearcoatNormalMap == newClearcoatNormalMap)
1582 return;
1583
1584 QQuick3DObjectPrivate::attachWatcher(context: this, setter: &QQuick3DPrincipledMaterial::setClearcoatNormalMap, newO: newClearcoatNormalMap, oldO: m_clearcoatNormalMap);
1585
1586 m_clearcoatNormalMap = newClearcoatNormalMap;
1587 emit clearcoatNormalMapChanged(texture: m_clearcoatNormalMap);
1588 markDirty(type: ClearcoatDirty);
1589}
1590
1591float QQuick3DPrincipledMaterial::transmissionFactor() const
1592{
1593 return m_transmissionFactor;
1594}
1595
1596void QQuick3DPrincipledMaterial::setTransmissionFactor(float newTransmissionFactor)
1597{
1598 if (qFuzzyCompare(p1: m_transmissionFactor, p2: newTransmissionFactor))
1599 return;
1600 m_transmissionFactor = newTransmissionFactor;
1601 emit transmissionFactorChanged(amount: m_transmissionFactor);
1602 markDirty(type: TransmissionDirty);
1603}
1604
1605QQuick3DTexture *QQuick3DPrincipledMaterial::transmissionMap() const
1606{
1607 return m_transmissionMap;
1608}
1609
1610void QQuick3DPrincipledMaterial::setTransmissionMap(QQuick3DTexture *newTransmissionMap)
1611{
1612 if (m_transmissionMap == newTransmissionMap)
1613 return;
1614
1615 QQuick3DObjectPrivate::attachWatcher(context: this, setter: &QQuick3DPrincipledMaterial::setTransmissionMap, newO: newTransmissionMap, oldO: m_transmissionMap);
1616
1617 m_transmissionMap = newTransmissionMap;
1618 emit transmissionMapChanged(texture: m_transmissionMap);
1619 markDirty(type: TransmissionDirty);
1620}
1621
1622QQuick3DMaterial::TextureChannelMapping QQuick3DPrincipledMaterial::transmissionChannel() const
1623{
1624 return m_transmissionChannel;
1625}
1626
1627float QQuick3DPrincipledMaterial::indexOfRefraction() const
1628{
1629 return m_indexOfRefraction;
1630}
1631
1632bool QQuick3DPrincipledMaterial::vertexColorsEnabled() const
1633{
1634 return m_vertexColorsEnabled;
1635}
1636
1637void QQuick3DPrincipledMaterial::setTransmissionChannel(QQuick3DMaterial::TextureChannelMapping newTransmissionChannel)
1638{
1639 if (m_transmissionChannel == newTransmissionChannel)
1640 return;
1641 m_transmissionChannel = newTransmissionChannel;
1642 emit transmissionChannelChanged(channel: m_transmissionChannel);
1643 markDirty(type: TransmissionDirty);
1644}
1645
1646float QQuick3DPrincipledMaterial::thicknessFactor() const
1647{
1648 return m_thicknessFactor;
1649}
1650
1651void QQuick3DPrincipledMaterial::setThicknessFactor(float newThicknessFactor)
1652{
1653 if (qFuzzyCompare(p1: m_thicknessFactor, p2: newThicknessFactor))
1654 return;
1655 m_thicknessFactor = newThicknessFactor;
1656 emit thicknessFactorChanged(amount: m_thicknessFactor);
1657 markDirty(type: VolumeDirty);
1658}
1659
1660QQuick3DTexture *QQuick3DPrincipledMaterial::thicknessMap() const
1661{
1662 return m_thicknessMap;
1663}
1664
1665void QQuick3DPrincipledMaterial::setThicknessMap(QQuick3DTexture *newThicknessMap)
1666{
1667 if (m_thicknessMap == newThicknessMap)
1668 return;
1669
1670 QQuick3DObjectPrivate::attachWatcher(context: this, setter: &QQuick3DPrincipledMaterial::setThicknessMap, newO: newThicknessMap, oldO: m_thicknessMap);
1671
1672 m_thicknessMap = newThicknessMap;
1673 emit thicknessMapChanged(texture: m_thicknessMap);
1674 markDirty(type: VolumeDirty);
1675}
1676
1677const QQuick3DMaterial::TextureChannelMapping &QQuick3DPrincipledMaterial::thicknessChannel() const
1678{
1679 return m_thicknessChannel;
1680}
1681
1682void QQuick3DPrincipledMaterial::setThicknessChannel(const QQuick3DMaterial::TextureChannelMapping &newThicknessChannel)
1683{
1684 if (m_thicknessChannel == newThicknessChannel)
1685 return;
1686 m_thicknessChannel = newThicknessChannel;
1687 emit thicknessChannelChanged(channel: m_thicknessChannel);
1688 markDirty(type: VolumeDirty);
1689}
1690
1691float QQuick3DPrincipledMaterial::attenuationDistance() const
1692{
1693 return m_attenuationDistance;
1694}
1695
1696void QQuick3DPrincipledMaterial::setAttenuationDistance(float newAttenuationDistance)
1697{
1698 if (qFuzzyCompare(p1: m_attenuationDistance, p2: newAttenuationDistance))
1699 return;
1700 m_attenuationDistance = newAttenuationDistance;
1701 emit attenuationDistanceChanged(distance: m_attenuationDistance);
1702 markDirty(type: VolumeDirty);
1703}
1704
1705const QColor &QQuick3DPrincipledMaterial::attenuationColor() const
1706{
1707 return m_attenuationColor;
1708}
1709
1710void QQuick3DPrincipledMaterial::setAttenuationColor(const QColor &newAttenuationColor)
1711{
1712 if (m_attenuationColor == newAttenuationColor)
1713 return;
1714 m_attenuationColor = newAttenuationColor;
1715 emit attenuationColorChanged(color: m_attenuationColor);
1716 markDirty(type: VolumeDirty);
1717}
1718
1719void QQuick3DPrincipledMaterial::setIndexOfRefraction(float indexOfRefraction)
1720{
1721 if (qFuzzyCompare(p1: m_indexOfRefraction, p2: indexOfRefraction))
1722 return;
1723
1724 m_indexOfRefraction = indexOfRefraction;
1725 emit indexOfRefractionChanged(indexOfRefraction: m_indexOfRefraction);
1726 markDirty(type: SpecularDirty);
1727}
1728
1729void QQuick3DPrincipledMaterial::setVertexColorsEnabled(bool vertexColors)
1730{
1731 if (m_vertexColorsEnabled == vertexColors)
1732 return;
1733
1734 m_vertexColorsEnabled = vertexColors;
1735 emit vertexColorsEnabledChanged(vertexColorsEnabled: m_vertexColorsEnabled);
1736 markDirty(type: VertexColorsDirty);
1737}
1738
1739QT_END_NAMESPACE
1740

source code of qtquick3d/src/quick3d/qquick3dprincipledmaterial.cpp