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 | |
10 | QT_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 | |
393 | QQuick3DDefaultMaterial::QQuick3DDefaultMaterial(QQuick3DObject *parent) |
394 | : QQuick3DMaterial(*(new QQuick3DObjectPrivate(QQuick3DObjectPrivate::Type::DefaultMaterial)), parent) |
395 | , m_diffuseColor(Qt::white) |
396 | , m_specularTint(Qt::white) |
397 | {} |
398 | |
399 | QQuick3DDefaultMaterial::~QQuick3DDefaultMaterial() |
400 | { |
401 | } |
402 | |
403 | QQuick3DDefaultMaterial::Lighting QQuick3DDefaultMaterial::lighting() const |
404 | { |
405 | return m_lighting; |
406 | } |
407 | |
408 | QQuick3DDefaultMaterial::BlendMode QQuick3DDefaultMaterial::blendMode() const |
409 | { |
410 | return m_blendMode; |
411 | } |
412 | |
413 | QColor QQuick3DDefaultMaterial::diffuseColor() const |
414 | { |
415 | return m_diffuseColor; |
416 | } |
417 | |
418 | QQuick3DTexture *QQuick3DDefaultMaterial::diffuseMap() const |
419 | { |
420 | return m_diffuseMap; |
421 | } |
422 | |
423 | QVector3D QQuick3DDefaultMaterial::emissiveFactor() const |
424 | { |
425 | return m_emissiveFactor; |
426 | } |
427 | |
428 | QQuick3DTexture *QQuick3DDefaultMaterial::emissiveMap() const |
429 | { |
430 | return m_emissiveMap; |
431 | } |
432 | |
433 | QQuick3DTexture *QQuick3DDefaultMaterial::specularReflectionMap() const |
434 | { |
435 | return m_specularReflectionMap; |
436 | } |
437 | |
438 | QQuick3DTexture *QQuick3DDefaultMaterial::specularMap() const |
439 | { |
440 | return m_specularMap; |
441 | } |
442 | |
443 | QQuick3DDefaultMaterial::SpecularModel QQuick3DDefaultMaterial::specularModel() const |
444 | { |
445 | return m_specularModel; |
446 | } |
447 | |
448 | QColor QQuick3DDefaultMaterial::specularTint() const |
449 | { |
450 | return m_specularTint; |
451 | } |
452 | |
453 | float QQuick3DDefaultMaterial::indexOfRefraction() const |
454 | { |
455 | return m_indexOfRefraction; |
456 | } |
457 | |
458 | float QQuick3DDefaultMaterial::fresnelPower() const |
459 | { |
460 | return m_fresnelPower; |
461 | } |
462 | |
463 | float QQuick3DDefaultMaterial::specularAmount() const |
464 | { |
465 | return m_specularAmount; |
466 | } |
467 | |
468 | float QQuick3DDefaultMaterial::specularRoughness() const |
469 | { |
470 | return m_specularRoughness; |
471 | } |
472 | |
473 | QQuick3DTexture *QQuick3DDefaultMaterial::roughnessMap() const |
474 | { |
475 | return m_roughnessMap; |
476 | } |
477 | |
478 | float QQuick3DDefaultMaterial::opacity() const |
479 | { |
480 | return m_opacity; |
481 | } |
482 | |
483 | QQuick3DTexture *QQuick3DDefaultMaterial::opacityMap() const |
484 | { |
485 | return m_opacityMap; |
486 | } |
487 | |
488 | QQuick3DTexture *QQuick3DDefaultMaterial::bumpMap() const |
489 | { |
490 | return m_bumpMap; |
491 | } |
492 | |
493 | float QQuick3DDefaultMaterial::bumpAmount() const |
494 | { |
495 | return m_bumpAmount; |
496 | } |
497 | |
498 | QQuick3DTexture *QQuick3DDefaultMaterial::normalMap() const |
499 | { |
500 | return m_normalMap; |
501 | } |
502 | |
503 | QQuick3DTexture *QQuick3DDefaultMaterial::translucencyMap() const |
504 | { |
505 | return m_translucencyMap; |
506 | } |
507 | |
508 | float QQuick3DDefaultMaterial::translucentFalloff() const |
509 | { |
510 | return m_translucentFalloff; |
511 | } |
512 | |
513 | float QQuick3DDefaultMaterial::diffuseLightWrap() const |
514 | { |
515 | return m_diffuseLightWrap; |
516 | } |
517 | |
518 | bool QQuick3DDefaultMaterial::vertexColorsEnabled() const |
519 | { |
520 | return m_vertexColorsEnabled; |
521 | } |
522 | |
523 | QQuick3DMaterial::TextureChannelMapping QQuick3DDefaultMaterial::roughnessChannel() const |
524 | { |
525 | return m_roughnessChannel; |
526 | } |
527 | |
528 | QQuick3DMaterial::TextureChannelMapping QQuick3DDefaultMaterial::opacityChannel() const |
529 | { |
530 | return m_opacityChannel; |
531 | } |
532 | |
533 | QQuick3DMaterial::TextureChannelMapping QQuick3DDefaultMaterial::translucencyChannel() const |
534 | { |
535 | return m_translucencyChannel; |
536 | } |
537 | |
538 | float QQuick3DDefaultMaterial::pointSize() const |
539 | { |
540 | return m_pointSize; |
541 | } |
542 | |
543 | float QQuick3DDefaultMaterial::lineWidth() const |
544 | { |
545 | return m_lineWidth; |
546 | } |
547 | |
548 | void QQuick3DDefaultMaterial::markAllDirty() |
549 | { |
550 | m_dirtyAttributes = 0xffffffff; |
551 | QQuick3DMaterial::markAllDirty(); |
552 | } |
553 | |
554 | |
555 | void 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 | |
565 | void 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 | |
575 | void 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 | |
585 | void 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 | |
597 | void 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 | |
607 | void 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 | |
619 | void 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 | |
631 | void 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 | |
643 | void 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 | |
653 | void 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 | |
663 | void 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 | |
673 | void 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 | |
683 | void 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 | |
693 | void 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 | |
703 | void 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 | |
715 | void 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 | |
731 | void 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 | |
743 | void 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 | |
755 | void 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 | |
765 | void 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 | |
777 | void 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 | |
789 | void 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 | |
799 | void 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 | |
809 | void 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 | |
819 | void 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 | |
828 | void 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 | |
837 | void 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 | |
846 | void 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 | |
855 | void 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 | |
864 | QSSGRenderGraphObject *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 | |
980 | void QQuick3DDefaultMaterial::itemChange(QQuick3DObject::ItemChange change, const QQuick3DObject::ItemChangeData &value) |
981 | { |
982 | if (change == QQuick3DObject::ItemSceneChange) |
983 | updateSceneManager(sceneManager: value.sceneManager); |
984 | } |
985 | |
986 | void 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 | |
1012 | void QQuick3DDefaultMaterial::markDirty(QQuick3DDefaultMaterial::DirtyType type) |
1013 | { |
1014 | if (!(m_dirtyAttributes & quint32(type))) { |
1015 | m_dirtyAttributes |= quint32(type); |
1016 | update(); |
1017 | } |
1018 | } |
1019 | |
1020 | QT_END_NAMESPACE |
1021 | |