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

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