1// Copyright (C) 2019 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
4#include "qquick3ddefaultmaterial_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/*!
14 \qmltype DefaultMaterial
15 \inherits Material
16 \inqmlmodule QtQuick3D
17 \brief Lets you define a material for 3D items using the specular/glossiness workflow.
18
19 Before a Model can be rendered in a scene, it must have at least one material attached
20 to it that describes how the mesh should be shaded. The DefaultMaterial is an easy to
21 use material that lets you describe your material using a specular/glossiness type workflow.
22 The material has sensible default and can be used to shade a model without changing any properties.
23
24 \section1 Specular/Glossiness workflow
25
26 The Default material provides a way to create materials using a specular/glossiness
27 type workflow. The main properties of the material are controlled through the
28 \l {DefaultMaterial::specularMap} {specular}, \l {DefaultMaterial::roughnessMap} {roughness},
29 and the \l {DefaultMaterial::diffuseMap} {diffuse color} property.
30
31 \section2 Specular
32
33 The \l {DefaultMaterial::specularMap} {specular reflectivity} describes the specular
34 amount and color of an object's surface. For reflective materials the main color
35 contribution, comes from this property.
36
37 \section2 Glossiness (Roughness)
38
39 The glossiness of a surface depends on how smooth or irregular the surface is.
40 A smooth surface will have a more intense light reflection then a rough surface, where
41 the light reflection will be more spread out. In the Default material the material's glossiness
42 is controlled through the \l {DefaultMaterial::roughnessMap} {roughness} property.
43
44 \section2 Diffuse color
45
46 The \l {DefaultMaterial::diffuseMap} {diffuse color} property describes the basic color
47 of the material, and unlike the \l {PrincipledMaterial}'s base color, the diffuse color
48 does not contain any information about the material reflectance. However, for
49 reflective surfaces the diffuse color should be set to a black tint, as that will allow
50 for the specular color to contribute.
51*/
52
53/*!
54 \qmlproperty enumeration DefaultMaterial::lighting
55
56 This property defines which lighting method is used when generating this
57 material.
58
59 The default value is \c DefaultMaterial.FragmentLighting
60
61 When using \c DefaultMaterial.FragmentLighting, diffuse and specular lighting are
62 calculated for each rendered pixel. Certain effects (such as a Fresnel or bump map) require
63 \c DefaultMaterial.FragmentLighting to work.
64
65 When using \c DefaultMaterial.NoLighting no lighting is calculated. This
66 mode is (predictably) very fast, and quite effective when image maps are
67 used that do not need to be shaded by lighting.
68
69 \value DefaultMaterial.NoLighting No lighting is calculated.
70 \value DefaultMaterial.FragmentLighting Per-fragment lighting is calculated.
71*/
72
73/*!
74 \qmlproperty enumeration DefaultMaterial::blendMode
75
76 This property determines how the colors of the model rendered blend with
77 those behind it.
78
79 \value DefaultMaterial.SourceOver Default blend mode. Opaque objects
80 occlude objects behind them. This default mode does not guarantee alpha
81 blending in the rendering pipeline on its own for models that use this
82 material, but rather makes the decision dependent on a number of factors:
83 if the object's and material's total opacity is \c{1.0} and there are no
84 texture maps in the material with semi-transparent pixels in them, then the
85 model is treated as opaque, meaning it is rendered with depth testing and
86 depth write enabled, together with other opaque objects, with blending
87 disabled. Otherwise the model is treated as semi-transparent, and is
88 rendered after the opaque objects, together with other semi-transparent
89 objects in a back-to-front order based on their center's distance from the
90 camera, with alpha blending enabled.
91
92 \value DefaultMaterial.Screen Colors are blended using an inverted
93 multiply, producing a lighter result. This blend mode is order-independent;
94 if you are using semi-opaque objects and experiencing \e popping as faces
95 or models sort differently, using Screen blending is one way to produce
96 results without popping.
97
98 \value DefaultMaterial.Multiply Colors are blended using a multiply,
99 producing a darker result. This blend mode is also order-independent.
100
101 \sa {Qt Quick 3D Architecture}
102*/
103
104/*!
105 \qmlproperty color DefaultMaterial::diffuseColor
106
107 This property determines the diffuse color (albedo) for the material. Setting the
108 diffuse color to a black tint will create a purely-specular material (e.g. metals or mirrors).
109 */
110
111/*!
112 \qmlproperty Texture DefaultMaterial::diffuseMap
113
114 This property defines a Texture to apply to the material. Using Texture
115 with transparency will also apply the alpha channel as an opacity map.
116 */
117
118/*!
119 \qmlproperty vector3d DefaultMaterial::emissiveFactor
120
121 This property determines the color of self-illumination for this material.
122 If an emissive map is set, the x, y, and z components are used as factors
123 (multipliers) for the R, G and B channels of the texture, respectively.
124 The default value is (0, 0, 0) and it means no emissive contribution at all.
125
126 \note Setting the lightingMode to DefaultMaterial.NoLighting means emissive
127 Factor does not have an effect on the scene.
128*/
129
130/*!
131 \qmlproperty Texture DefaultMaterial::emissiveMap
132
133 This property sets a RGB Texture to be used to specify the intensity of the
134 emissive color.
135
136 \sa emissiveFactor
137*/
138
139/*!
140 \qmlproperty Texture DefaultMaterial::specularReflectionMap
141
142 This property sets a Texture used for specular highlights on the material.
143
144 This is typically used to perform environment mapping: as the model is
145 rotated, the map will appear as though it is reflecting from the
146 environment. For this to work as expected, the Texture's
147 \l{Texture::mappingMode}{mappingMode} needs to be set to
148 Texture.Environment. Specular reflection maps are an easy way to add a
149 high-quality look with a relatively low cost.
150
151 \note Associating a \l{SceneEnvironment::lightProbe}{light probe} with the
152 \l SceneEnvironment, and thus relying on image-based lighting, can achieve
153 similar environmental reflection effects. Light probes are however a
154 conceptually different, and when it comes to performance, potentially more
155 expensive solution. Each approaches have their own specific uses, and the
156 one to use needs to be decided on a case by case basis. When it comes to
157 the Texture set to the property, specularReflectionMap has an advantage,
158 because it presents no limitations and supports all types of textures,
159 including ones that source their data from a Qt Quick sub-scene via
160 \l{Texture::sourceItem}{sourceItem}.
161
162 \note Crisp images cause your material to look very glossy; the more you
163 blur your image the softer your material will appear.
164
165 \sa Texture::mappingMode
166*/
167
168/*!
169 \qmlproperty Texture DefaultMaterial::specularMap
170
171 This property defines a RGB Texture to modulate the amount and the color of
172 specularity across the surface of the material. These values are multiplied
173 by the specularAmount.
174*/
175
176/*!
177 \qmlproperty enumeration DefaultMaterial::specularModel
178
179 This property determines which functions are used to calculate specular
180 highlights for lights in the scene.
181
182 \value DefaultMaterial.Default Specular lighting uses default lighting model.
183 \value DefaultMaterial.KGGX Specular lighting uses GGX lighting model.
184*/
185
186/*!
187 \qmlproperty color DefaultMaterial::specularTint
188
189 This property defines a color used to adjust the specular reflections.
190 Use white for no effect
191*/
192
193/*!
194 \qmlproperty real DefaultMaterial::indexOfRefraction
195
196 This property controls what angles of reflections are affected by the
197 fresnelPower. The default is \c 1.45. The value must be greater or equal to \c 1.0.
198 \note No known material in the world have ior much greater than \c 3.0.
199*/
200
201/*!
202 \qmlproperty real DefaultMaterial::fresnelPower
203
204 This property decreases head-on reflections (looking directly at the
205 surface) while maintaining reflections seen at grazing angles.
206 The default value is \c 0 disabling the fresnel effect.
207*/
208
209/*!
210 \qmlproperty real DefaultMaterial::specularAmount
211
212 This property controls the strength of specularity (highlights and
213 reflections). The default value is \c 0 disabling the specularity. The range is [0.0, 1.0].
214
215 \note This property does not affect the \l specularReflectionMap, but does
216 affect the amount of reflections from a scene's SceneEnvironment::lightProbe.
217
218 \note Unless your mesh is high resolution, you may need to use
219 \c DefaultMaterial.FragmentLighting to get good specular highlights from scene
220 lights.
221*/
222
223/*!
224 \qmlproperty real DefaultMaterial::specularRoughness
225
226 This property controls the size of the specular highlight generated from
227 lights, and the clarity of reflections in general. Larger values increase
228 the roughness, softening specular highlights and blurring reflections.
229 The range is [0.0, 1.0]. The default value is 0.
230*/
231
232/*!
233 \qmlproperty Texture DefaultMaterial::roughnessMap
234
235 This property defines a Texture to control the specular roughness of the
236 material. If the texture contains multiple channels(RGBA), then the correct channel
237 can be set using the roughnessChannel property.
238*/
239
240/*!
241 \qmlproperty enumeration DefaultMaterial::roughnessChannel
242
243 This property defines the texture channel used to read the roughness value from roughnessMap.
244 The default value is \c Material.R.
245
246 \value Material.R Read value from texture R channel.
247 \value Material.G Read value from texture G channel.
248 \value Material.B Read value from texture B channel.
249 \value Material.A Read value from texture A channel.
250*/
251
252/*!
253 \qmlproperty real DefaultMaterial::opacity
254
255 This property drops the opacity of just this material, separate from the model.
256 The default is \c 1.0. The range is [0.0, 1.0].
257*/
258
259/*!
260 \qmlproperty Texture DefaultMaterial::opacityMap
261
262 This property defines a Texture used to control the opacity differently for
263 different parts of the material.
264*/
265
266/*!
267 \qmlproperty enumeration DefaultMaterial::opacityChannel
268
269 This property defines the texture channel used to read the opacity value from opacityMap.
270 The default value is \c Material.A.
271
272 \value Material.R Read value from texture R channel.
273 \value Material.G Read value from texture G channel.
274 \value Material.B Read value from texture B channel.
275 \value Material.A Read value from texture A channel.
276*/
277
278/*!
279 \qmlproperty Texture DefaultMaterial::bumpMap
280
281 This property defines a grayscale Texture to simulate fine geometry
282 displacement across the surface of the material. Brighter pixels indicate
283 raised regions. The amount of the effect is controlled by the
284 \l bumpAmount property.
285
286 \note bump maps will not affect the silhouette of a model.
287
288*/
289
290/*!
291 \qmlproperty real DefaultMaterial::bumpAmount
292
293 This property controls the amount of simulated displacement for the
294 \l bumpMap or \l normalMap. The default value is \c 0 disabling the bump effect.
295 The range is [0, 1].
296
297*/
298
299/*!
300 \qmlproperty Texture DefaultMaterial::normalMap
301
302 This property defines a RGB image used to simulate fine geometry
303 displacement across the surface of the material. The RGB channels indicate
304 XYZ normal deviations. The amount of the effect is controlled by the
305 \l bumpAmount property.
306
307 \note Normal maps will not affect the silhouette of a model.
308*/
309
310/*!
311 \qmlproperty Texture DefaultMaterial::translucencyMap
312
313 This property defines a grayscale Texture controlling how much light can
314 pass through the material from behind.
315*/
316
317/*!
318 \qmlproperty enumeration DefaultMaterial::translucencyChannel
319
320 This property defines the texture channel used to read the translucency value from translucencyMap.
321 The default value is \c Material.A.
322
323 \value Material.R Read value from texture R channel.
324 \value Material.G Read value from texture G channel.
325 \value Material.B Read value from texture B channel.
326 \value Material.A Read value from texture A channel.
327*/
328
329/*!
330 \qmlproperty real DefaultMaterial::translucentFalloff
331
332 This property defines the amount of falloff for the translucency based on the
333 angle of the normals of the object to the light source.
334*/
335
336/*!
337 \qmlproperty real DefaultMaterial::diffuseLightWrap
338
339 This property determines the amount of light wrap for the translucency map.
340 A value of 0 will not wrap the light at all, while a value of 1 will wrap
341 the light all around the object.
342*/
343
344/*!
345 \qmlproperty bool DefaultMaterial::vertexColorsEnabled
346
347 When this property is enabled, the material will use vertex colors from the
348 mesh. These will be multiplied by any other colors specified for the
349 material.
350*/
351
352/*!
353 \qmlproperty real DefaultMaterial::pointSize
354
355 This property determines the size of the points rendered, when the geometry
356 is using a primitive type of points. The default value is 1.0. This
357 property is not relevant when rendering other types of geometry, such as,
358 triangle meshes.
359
360 \warning Point sizes other than 1 may not be supported at run time,
361 depending on the underyling graphics API. For example, setting a size other
362 than 1 has no effect with Direct 3D.
363*/
364
365/*!
366 \qmlproperty real DefaultMaterial::lineWidth
367
368 This property determines the width of the lines rendered, when the geometry
369 is using a primitive type of lines or line strips. The default value is
370 1.0. This property is not relevant when rendering other types of geometry,
371 such as, triangle meshes.
372
373 \warning Line widths other than 1 may not be suported at run time,
374 depending on the underlying graphics API. When that is the case, the
375 request to change the width is ignored. For example, none of the following
376 can be expected to support wide lines: Direct3D, Metal, OpenGL with core
377 profile contexts.
378
379 \note Unlike most other material properties, the line width is under the
380 hood baked in to a graphics pipeline object, similarly to blendMode.
381 Therefore, a different value leads to having to create a new pipeline
382 object, which over time can become costly (performance and resource usage)
383 if the property is frequently changed to many different values. For
384 example, animating this property is possible, but should be avoided.
385 */
386
387QQuick3DDefaultMaterial::QQuick3DDefaultMaterial(QQuick3DObject *parent)
388 : QQuick3DMaterial(*(new QQuick3DObjectPrivate(QQuick3DObjectPrivate::Type::DefaultMaterial)), parent)
389 , m_diffuseColor(Qt::white)
390 , m_specularTint(Qt::white)
391{}
392
393QQuick3DDefaultMaterial::~QQuick3DDefaultMaterial()
394{
395}
396
397QQuick3DDefaultMaterial::Lighting QQuick3DDefaultMaterial::lighting() const
398{
399 return m_lighting;
400}
401
402QQuick3DDefaultMaterial::BlendMode QQuick3DDefaultMaterial::blendMode() const
403{
404 return m_blendMode;
405}
406
407QColor QQuick3DDefaultMaterial::diffuseColor() const
408{
409 return m_diffuseColor;
410}
411
412QQuick3DTexture *QQuick3DDefaultMaterial::diffuseMap() const
413{
414 return m_diffuseMap;
415}
416
417QVector3D QQuick3DDefaultMaterial::emissiveFactor() const
418{
419 return m_emissiveFactor;
420}
421
422QQuick3DTexture *QQuick3DDefaultMaterial::emissiveMap() const
423{
424 return m_emissiveMap;
425}
426
427QQuick3DTexture *QQuick3DDefaultMaterial::specularReflectionMap() const
428{
429 return m_specularReflectionMap;
430}
431
432QQuick3DTexture *QQuick3DDefaultMaterial::specularMap() const
433{
434 return m_specularMap;
435}
436
437QQuick3DDefaultMaterial::SpecularModel QQuick3DDefaultMaterial::specularModel() const
438{
439 return m_specularModel;
440}
441
442QColor QQuick3DDefaultMaterial::specularTint() const
443{
444 return m_specularTint;
445}
446
447float QQuick3DDefaultMaterial::indexOfRefraction() const
448{
449 return m_indexOfRefraction;
450}
451
452float QQuick3DDefaultMaterial::fresnelPower() const
453{
454 return m_fresnelPower;
455}
456
457float QQuick3DDefaultMaterial::specularAmount() const
458{
459 return m_specularAmount;
460}
461
462float QQuick3DDefaultMaterial::specularRoughness() const
463{
464 return m_specularRoughness;
465}
466
467QQuick3DTexture *QQuick3DDefaultMaterial::roughnessMap() const
468{
469 return m_roughnessMap;
470}
471
472float QQuick3DDefaultMaterial::opacity() const
473{
474 return m_opacity;
475}
476
477QQuick3DTexture *QQuick3DDefaultMaterial::opacityMap() const
478{
479 return m_opacityMap;
480}
481
482QQuick3DTexture *QQuick3DDefaultMaterial::bumpMap() const
483{
484 return m_bumpMap;
485}
486
487float QQuick3DDefaultMaterial::bumpAmount() const
488{
489 return m_bumpAmount;
490}
491
492QQuick3DTexture *QQuick3DDefaultMaterial::normalMap() const
493{
494 return m_normalMap;
495}
496
497QQuick3DTexture *QQuick3DDefaultMaterial::translucencyMap() const
498{
499 return m_translucencyMap;
500}
501
502float QQuick3DDefaultMaterial::translucentFalloff() const
503{
504 return m_translucentFalloff;
505}
506
507float QQuick3DDefaultMaterial::diffuseLightWrap() const
508{
509 return m_diffuseLightWrap;
510}
511
512bool QQuick3DDefaultMaterial::vertexColorsEnabled() const
513{
514 return m_vertexColorsEnabled;
515}
516
517QQuick3DMaterial::TextureChannelMapping QQuick3DDefaultMaterial::roughnessChannel() const
518{
519 return m_roughnessChannel;
520}
521
522QQuick3DMaterial::TextureChannelMapping QQuick3DDefaultMaterial::opacityChannel() const
523{
524 return m_opacityChannel;
525}
526
527QQuick3DMaterial::TextureChannelMapping QQuick3DDefaultMaterial::translucencyChannel() const
528{
529 return m_translucencyChannel;
530}
531
532float QQuick3DDefaultMaterial::pointSize() const
533{
534 return m_pointSize;
535}
536
537float QQuick3DDefaultMaterial::lineWidth() const
538{
539 return m_lineWidth;
540}
541
542void QQuick3DDefaultMaterial::markAllDirty()
543{
544 m_dirtyAttributes = 0xffffffff;
545 QQuick3DMaterial::markAllDirty();
546}
547
548
549void QQuick3DDefaultMaterial::setLighting(QQuick3DDefaultMaterial::Lighting lighting)
550{
551 if (m_lighting == lighting)
552 return;
553
554 m_lighting = lighting;
555 emit lightingChanged(lighting: m_lighting);
556 markDirty(type: LightingModeDirty);
557}
558
559void QQuick3DDefaultMaterial::setBlendMode(QQuick3DDefaultMaterial::BlendMode blendMode)
560{
561 if (m_blendMode == blendMode)
562 return;
563
564 m_blendMode = blendMode;
565 emit blendModeChanged(blendMode: m_blendMode);
566 markDirty(type: BlendModeDirty);
567}
568
569void QQuick3DDefaultMaterial::setDiffuseColor(QColor diffuseColor)
570{
571 if (m_diffuseColor == diffuseColor)
572 return;
573
574 m_diffuseColor = diffuseColor;
575 emit diffuseColorChanged(diffuseColor: m_diffuseColor);
576 markDirty(type: DiffuseDirty);
577}
578
579void QQuick3DDefaultMaterial::setDiffuseMap(QQuick3DTexture *diffuseMap)
580{
581 if (m_diffuseMap == diffuseMap)
582 return;
583
584 QQuick3DObjectPrivate::attachWatcher(context: this, setter: &QQuick3DDefaultMaterial::setDiffuseMap, newO: diffuseMap, oldO: m_diffuseMap);
585
586 m_diffuseMap = diffuseMap;
587 emit diffuseMapChanged(diffuseMap: m_diffuseMap);
588 markDirty(type: DiffuseDirty);
589}
590
591void QQuick3DDefaultMaterial::setEmissiveFactor(QVector3D emissiveFactor)
592{
593 if (m_emissiveFactor == emissiveFactor)
594 return;
595
596 m_emissiveFactor = emissiveFactor;
597 emit emissiveFactorChanged(emissiveFactor: m_emissiveFactor);
598 markDirty(type: EmissiveDirty);
599}
600
601void QQuick3DDefaultMaterial::setEmissiveMap(QQuick3DTexture *emissiveMap)
602{
603 if (m_emissiveMap == emissiveMap)
604 return;
605
606 QQuick3DObjectPrivate::attachWatcher(context: this, setter: &QQuick3DDefaultMaterial::setEmissiveMap, newO: emissiveMap, oldO: m_emissiveMap);
607
608 m_emissiveMap = emissiveMap;
609 emit emissiveMapChanged(emissiveMap: m_emissiveMap);
610 markDirty(type: EmissiveDirty);
611}
612
613void QQuick3DDefaultMaterial::setSpecularReflectionMap(QQuick3DTexture *specularReflectionMap)
614{
615 if (m_specularReflectionMap == specularReflectionMap)
616 return;
617
618 QQuick3DObjectPrivate::attachWatcher(context: this, setter: &QQuick3DDefaultMaterial::setSpecularReflectionMap, newO: specularReflectionMap, oldO: m_specularReflectionMap);
619
620 m_specularReflectionMap = specularReflectionMap;
621 emit specularReflectionMapChanged(specularReflectionMap: m_specularReflectionMap);
622 markDirty(type: SpecularDirty);
623}
624
625void QQuick3DDefaultMaterial::setSpecularMap(QQuick3DTexture *specularMap)
626{
627 if (m_specularMap == specularMap)
628 return;
629
630 QQuick3DObjectPrivate::attachWatcher(context: this, setter: &QQuick3DDefaultMaterial::setSpecularMap, newO: specularMap, oldO: m_specularMap);
631
632 m_specularMap = specularMap;
633 emit specularMapChanged(specularMap: m_specularMap);
634 markDirty(type: SpecularDirty);
635}
636
637void QQuick3DDefaultMaterial::setSpecularModel(QQuick3DDefaultMaterial::SpecularModel specularModel)
638{
639 if (m_specularModel == specularModel)
640 return;
641
642 m_specularModel = specularModel;
643 emit specularModelChanged(specularModel: m_specularModel);
644 markDirty(type: SpecularDirty);
645}
646
647void QQuick3DDefaultMaterial::setSpecularTint(QColor specularTint)
648{
649 if (m_specularTint == specularTint)
650 return;
651
652 m_specularTint = specularTint;
653 emit specularTintChanged(specularTint: m_specularTint);
654 markDirty(type: SpecularDirty);
655}
656
657void QQuick3DDefaultMaterial::setIndexOfRefraction(float indexOfRefraction)
658{
659 if (qFuzzyCompare(p1: m_indexOfRefraction, p2: indexOfRefraction))
660 return;
661
662 m_indexOfRefraction = indexOfRefraction;
663 emit indexOfRefractionChanged(indexOfRefraction: m_indexOfRefraction);
664 markDirty(type: SpecularDirty);
665}
666
667void QQuick3DDefaultMaterial::setFresnelPower(float fresnelPower)
668{
669 if (qFuzzyCompare(p1: m_fresnelPower, p2: fresnelPower))
670 return;
671
672 m_fresnelPower = fresnelPower;
673 emit fresnelPowerChanged(fresnelPower: m_fresnelPower);
674 markDirty(type: SpecularDirty);
675}
676
677void QQuick3DDefaultMaterial::setSpecularAmount(float specularAmount)
678{
679 if (qFuzzyCompare(p1: m_specularAmount, p2: specularAmount))
680 return;
681
682 m_specularAmount = specularAmount;
683 emit specularAmountChanged(specularAmount: m_specularAmount);
684 markDirty(type: SpecularDirty);
685}
686
687void QQuick3DDefaultMaterial::setSpecularRoughness(float specularRoughness)
688{
689 if (qFuzzyCompare(p1: m_specularRoughness, p2: specularRoughness))
690 return;
691
692 m_specularRoughness = specularRoughness;
693 emit specularRoughnessChanged(specularRoughness: m_specularRoughness);
694 markDirty(type: SpecularDirty);
695}
696
697void QQuick3DDefaultMaterial::setRoughnessMap(QQuick3DTexture *roughnessMap)
698{
699 if (m_roughnessMap == roughnessMap)
700 return;
701
702 QQuick3DObjectPrivate::attachWatcher(context: this, setter: &QQuick3DDefaultMaterial::setRoughnessMap, newO: roughnessMap, oldO: m_roughnessMap);
703
704 m_roughnessMap = roughnessMap;
705 emit roughnessMapChanged(roughnessMap: m_roughnessMap);
706 markDirty(type: SpecularDirty);
707}
708
709void QQuick3DDefaultMaterial::setOpacity(float opacity)
710{
711 if (qFuzzyCompare(p1: m_opacity, p2: opacity))
712 return;
713
714 if (opacity > 1.0f)
715 opacity = 1.0f;
716
717 if (opacity < 0.0f)
718 opacity = 0.0f;
719
720 m_opacity = opacity;
721 emit opacityChanged(opacity: m_opacity);
722 markDirty(type: OpacityDirty);
723}
724
725void QQuick3DDefaultMaterial::setOpacityMap(QQuick3DTexture *opacityMap)
726{
727 if (m_opacityMap == opacityMap)
728 return;
729
730 QQuick3DObjectPrivate::attachWatcher(context: this, setter: &QQuick3DDefaultMaterial::setOpacityMap, newO: opacityMap, oldO: m_opacityMap);
731
732 m_opacityMap = opacityMap;
733 emit opacityMapChanged(opacityMap: m_opacityMap);
734 markDirty(type: OpacityDirty);
735}
736
737void QQuick3DDefaultMaterial::setBumpMap(QQuick3DTexture *bumpMap)
738{
739 if (m_bumpMap == bumpMap)
740 return;
741
742 QQuick3DObjectPrivate::attachWatcher(context: this, setter: &QQuick3DDefaultMaterial::setBumpMap, newO: bumpMap, oldO: m_bumpMap);
743
744 m_bumpMap = bumpMap;
745 emit bumpMapChanged(bumpMap: m_bumpMap);
746 markDirty(type: BumpDirty);
747}
748
749void QQuick3DDefaultMaterial::setBumpAmount(float bumpAmount)
750{
751 if (qFuzzyCompare(p1: m_bumpAmount, p2: bumpAmount))
752 return;
753
754 m_bumpAmount = bumpAmount;
755 emit bumpAmountChanged(bumpAmount: m_bumpAmount);
756 markDirty(type: BumpDirty);
757}
758
759void QQuick3DDefaultMaterial::setNormalMap(QQuick3DTexture *normalMap)
760{
761 if (m_normalMap == normalMap)
762 return;
763
764 QQuick3DObjectPrivate::attachWatcher(context: this, setter: &QQuick3DDefaultMaterial::setNormalMap, newO: normalMap, oldO: m_normalMap);
765
766 m_normalMap = normalMap;
767 emit normalMapChanged(normalMap: m_normalMap);
768 markDirty(type: NormalDirty);
769}
770
771void QQuick3DDefaultMaterial::setTranslucencyMap(QQuick3DTexture *translucencyMap)
772{
773 if (m_translucencyMap == translucencyMap)
774 return;
775
776 QQuick3DObjectPrivate::attachWatcher(context: this, setter: &QQuick3DDefaultMaterial::setTranslucencyMap, newO: translucencyMap, oldO: m_translucencyMap);
777
778 m_translucencyMap = translucencyMap;
779 emit translucencyMapChanged(translucencyMap: m_translucencyMap);
780 markDirty(type: TranslucencyDirty);
781}
782
783void QQuick3DDefaultMaterial::setTranslucentFalloff(float translucentFalloff)
784{
785 if (qFuzzyCompare(p1: m_translucentFalloff, p2: translucentFalloff))
786 return;
787
788 m_translucentFalloff = translucentFalloff;
789 emit translucentFalloffChanged(translucentFalloff: m_translucentFalloff);
790 markDirty(type: TranslucencyDirty);
791}
792
793void QQuick3DDefaultMaterial::setDiffuseLightWrap(float diffuseLightWrap)
794{
795 if (qFuzzyCompare(p1: m_diffuseLightWrap, p2: diffuseLightWrap))
796 return;
797
798 m_diffuseLightWrap = diffuseLightWrap;
799 emit diffuseLightWrapChanged(diffuseLightWrap: m_diffuseLightWrap);
800 markDirty(type: DiffuseDirty);
801}
802
803void QQuick3DDefaultMaterial::setVertexColorsEnabled(bool vertexColors)
804{
805 if (m_vertexColorsEnabled == vertexColors)
806 return;
807
808 m_vertexColorsEnabled = vertexColors;
809 emit vertexColorsEnabledChanged(vertexColorsEnabled: m_vertexColorsEnabled);
810 markDirty(type: VertexColorsDirty);
811}
812
813void QQuick3DDefaultMaterial::setRoughnessChannel(TextureChannelMapping channel)
814{
815 if (m_roughnessChannel == channel)
816 return;
817 m_roughnessChannel = channel;
818 emit roughnessChannelChanged(channel);
819 markDirty(type: SpecularDirty);
820}
821
822void QQuick3DDefaultMaterial::setOpacityChannel(TextureChannelMapping channel)
823{
824 if (m_opacityChannel == channel)
825 return;
826 m_opacityChannel = channel;
827 emit opacityChannelChanged(channel);
828 markDirty(type: OpacityDirty);
829}
830
831void QQuick3DDefaultMaterial::setTranslucencyChannel(TextureChannelMapping channel)
832{
833 if (m_translucencyChannel == channel)
834 return;
835 m_translucencyChannel = channel;
836 emit translucencyChannelChanged(channel);
837 markDirty(type: TranslucencyDirty);
838}
839
840void QQuick3DDefaultMaterial::setPointSize(float size)
841{
842 if (qFuzzyCompare(p1: m_pointSize, p2: size))
843 return;
844 m_pointSize = size;
845 emit pointSizeChanged();
846 markDirty(type: PointSizeDirty);
847}
848
849void QQuick3DDefaultMaterial::setLineWidth(float width)
850{
851 if (qFuzzyCompare(p1: m_lineWidth, p2: width))
852 return;
853 m_lineWidth = width;
854 emit lineWidthChanged();
855 markDirty(type: LineWidthDirty);
856}
857
858QSSGRenderGraphObject *QQuick3DDefaultMaterial::updateSpatialNode(QSSGRenderGraphObject *node)
859{
860 if (!node) {
861 markAllDirty();
862 node = new QSSGRenderDefaultMaterial(QSSGRenderGraphObject::Type::DefaultMaterial);
863 }
864
865 static const auto channelMapping = [](TextureChannelMapping mapping) {
866 return QSSGRenderDefaultMaterial::TextureChannelMapping(mapping);
867 };
868
869 // Set common material properties
870 QQuick3DMaterial::updateSpatialNode(node);
871
872 QSSGRenderDefaultMaterial *material = static_cast<QSSGRenderDefaultMaterial *>(node);
873
874 if (m_dirtyAttributes & LightingModeDirty) {
875 material->lighting = QSSGRenderDefaultMaterial::MaterialLighting(m_lighting);
876 // If the lighthing mode changes it affects the emissive property
877 m_dirtyAttributes |= EmissiveDirty;
878 }
879
880 if (m_dirtyAttributes & BlendModeDirty)
881 material->blendMode = QSSGRenderDefaultMaterial::MaterialBlendMode(m_blendMode);
882
883 if (m_dirtyAttributes & DiffuseDirty) {
884 material->color = QSSGUtils::color::sRGBToLinear(color: m_diffuseColor);
885 if (!m_diffuseMap)
886 material->colorMap = nullptr;
887 else
888 material->colorMap = m_diffuseMap->getRenderImage();
889
890 material->diffuseLightWrap = m_diffuseLightWrap;
891 }
892
893 if (m_dirtyAttributes & EmissiveDirty) {
894 if (!m_emissiveMap)
895 material->emissiveMap = nullptr;
896 else
897 material->emissiveMap = m_emissiveMap->getRenderImage();
898
899 material->emissiveColor = m_emissiveFactor;
900 }
901
902 if (m_dirtyAttributes & SpecularDirty) {
903 if (!m_specularReflectionMap)
904 material->specularReflection = nullptr;
905 else
906 material->specularReflection = m_specularReflectionMap->getRenderImage();
907
908 if (!m_specularMap)
909 material->specularMap = nullptr;
910 else
911 material->specularMap = m_specularMap->getRenderImage();
912
913 material->specularModel = QSSGRenderDefaultMaterial::MaterialSpecularModel(m_specularModel);
914 material->specularTint = QSSGUtils::color::sRGBToLinear(color: m_specularTint).toVector3D();
915 material->ior = m_indexOfRefraction;
916 material->fresnelPower = m_fresnelPower;
917 material->specularAmount = m_specularAmount;
918 material->specularRoughness = m_specularRoughness;
919 material->roughnessChannel = channelMapping(m_roughnessChannel);
920
921 if (!m_roughnessMap)
922 material->roughnessMap = nullptr;
923 else
924 material->roughnessMap = m_roughnessMap->getRenderImage();
925 }
926
927 if (m_dirtyAttributes & OpacityDirty) {
928 material->opacity = m_opacity;
929 material->opacityChannel = channelMapping(m_opacityChannel);
930 if (!m_opacityMap)
931 material->opacityMap = nullptr;
932 else
933 material->opacityMap = m_opacityMap->getRenderImage();
934 }
935
936 if (m_dirtyAttributes & BumpDirty) {
937 if (!m_bumpMap)
938 material->bumpMap = nullptr;
939 else
940 material->bumpMap = m_bumpMap->getRenderImage();
941 material->bumpAmount = m_bumpAmount;
942 }
943
944 if (m_dirtyAttributes & NormalDirty) {
945 if (!m_normalMap)
946 material->normalMap = nullptr;
947 else
948 material->normalMap = m_normalMap->getRenderImage();
949 }
950
951 if (m_dirtyAttributes & TranslucencyDirty) {
952 if (!m_translucencyMap)
953 material->translucencyMap = nullptr;
954 else
955 material->translucencyMap = m_translucencyMap->getRenderImage();
956 material->translucentFalloff = m_translucentFalloff;
957 material->translucencyChannel = channelMapping(m_translucencyChannel);
958 }
959
960 if (m_dirtyAttributes & VertexColorsDirty)
961 material->vertexColorsEnabled = m_vertexColorsEnabled;
962
963 if (m_dirtyAttributes & PointSizeDirty)
964 material->pointSize = m_pointSize;
965
966 if (m_dirtyAttributes & LineWidthDirty)
967 material->lineWidth = m_lineWidth;
968
969 m_dirtyAttributes = 0;
970
971 return node;
972}
973
974void QQuick3DDefaultMaterial::itemChange(QQuick3DObject::ItemChange change, const QQuick3DObject::ItemChangeData &value)
975{
976 if (change == QQuick3DObject::ItemSceneChange)
977 updateSceneManager(sceneManager: value.sceneManager);
978}
979
980void QQuick3DDefaultMaterial::updateSceneManager(QQuick3DSceneManager *sceneManager)
981{
982 // Check all the resource value's windows, and update as necessary
983 if (sceneManager) {
984 QQuick3DObjectPrivate::refSceneManager(obj: m_diffuseMap, mgr&: *sceneManager);
985 QQuick3DObjectPrivate::refSceneManager(obj: m_emissiveMap, mgr&: *sceneManager);
986 QQuick3DObjectPrivate::refSceneManager(obj: m_specularReflectionMap, mgr&: *sceneManager);
987 QQuick3DObjectPrivate::refSceneManager(obj: m_specularMap, mgr&: *sceneManager);
988 QQuick3DObjectPrivate::refSceneManager(obj: m_roughnessMap, mgr&: *sceneManager);
989 QQuick3DObjectPrivate::refSceneManager(obj: m_opacityMap, mgr&: *sceneManager);
990 QQuick3DObjectPrivate::refSceneManager(obj: m_bumpMap, mgr&: *sceneManager);
991 QQuick3DObjectPrivate::refSceneManager(obj: m_normalMap, mgr&: *sceneManager);
992 QQuick3DObjectPrivate::refSceneManager(obj: m_translucencyMap, mgr&: *sceneManager);
993 } else {
994 QQuick3DObjectPrivate::derefSceneManager(obj: m_diffuseMap);
995 QQuick3DObjectPrivate::derefSceneManager(obj: m_emissiveMap);
996 QQuick3DObjectPrivate::derefSceneManager(obj: m_specularReflectionMap);
997 QQuick3DObjectPrivate::derefSceneManager(obj: m_specularMap);
998 QQuick3DObjectPrivate::derefSceneManager(obj: m_roughnessMap);
999 QQuick3DObjectPrivate::derefSceneManager(obj: m_opacityMap);
1000 QQuick3DObjectPrivate::derefSceneManager(obj: m_bumpMap);
1001 QQuick3DObjectPrivate::derefSceneManager(obj: m_normalMap);
1002 QQuick3DObjectPrivate::derefSceneManager(obj: m_translucencyMap);
1003 }
1004}
1005
1006void QQuick3DDefaultMaterial::markDirty(QQuick3DDefaultMaterial::DirtyType type)
1007{
1008 if (!(m_dirtyAttributes & quint32(type))) {
1009 m_dirtyAttributes |= quint32(type);
1010 update();
1011 }
1012}
1013
1014QT_END_NAMESPACE
1015

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