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 | 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 | |
387 | QQuick3DDefaultMaterial::QQuick3DDefaultMaterial(QQuick3DObject *parent) |
388 | : QQuick3DMaterial(*(new QQuick3DObjectPrivate(QQuick3DObjectPrivate::Type::DefaultMaterial)), parent) |
389 | , m_diffuseColor(Qt::white) |
390 | , m_specularTint(Qt::white) |
391 | {} |
392 | |
393 | QQuick3DDefaultMaterial::~QQuick3DDefaultMaterial() |
394 | { |
395 | } |
396 | |
397 | QQuick3DDefaultMaterial::Lighting QQuick3DDefaultMaterial::lighting() const |
398 | { |
399 | return m_lighting; |
400 | } |
401 | |
402 | QQuick3DDefaultMaterial::BlendMode QQuick3DDefaultMaterial::blendMode() const |
403 | { |
404 | return m_blendMode; |
405 | } |
406 | |
407 | QColor QQuick3DDefaultMaterial::diffuseColor() const |
408 | { |
409 | return m_diffuseColor; |
410 | } |
411 | |
412 | QQuick3DTexture *QQuick3DDefaultMaterial::diffuseMap() const |
413 | { |
414 | return m_diffuseMap; |
415 | } |
416 | |
417 | QVector3D QQuick3DDefaultMaterial::emissiveFactor() const |
418 | { |
419 | return m_emissiveFactor; |
420 | } |
421 | |
422 | QQuick3DTexture *QQuick3DDefaultMaterial::emissiveMap() const |
423 | { |
424 | return m_emissiveMap; |
425 | } |
426 | |
427 | QQuick3DTexture *QQuick3DDefaultMaterial::specularReflectionMap() const |
428 | { |
429 | return m_specularReflectionMap; |
430 | } |
431 | |
432 | QQuick3DTexture *QQuick3DDefaultMaterial::specularMap() const |
433 | { |
434 | return m_specularMap; |
435 | } |
436 | |
437 | QQuick3DDefaultMaterial::SpecularModel QQuick3DDefaultMaterial::specularModel() const |
438 | { |
439 | return m_specularModel; |
440 | } |
441 | |
442 | QColor QQuick3DDefaultMaterial::specularTint() const |
443 | { |
444 | return m_specularTint; |
445 | } |
446 | |
447 | float QQuick3DDefaultMaterial::indexOfRefraction() const |
448 | { |
449 | return m_indexOfRefraction; |
450 | } |
451 | |
452 | float QQuick3DDefaultMaterial::fresnelPower() const |
453 | { |
454 | return m_fresnelPower; |
455 | } |
456 | |
457 | float QQuick3DDefaultMaterial::specularAmount() const |
458 | { |
459 | return m_specularAmount; |
460 | } |
461 | |
462 | float QQuick3DDefaultMaterial::specularRoughness() const |
463 | { |
464 | return m_specularRoughness; |
465 | } |
466 | |
467 | QQuick3DTexture *QQuick3DDefaultMaterial::roughnessMap() const |
468 | { |
469 | return m_roughnessMap; |
470 | } |
471 | |
472 | float QQuick3DDefaultMaterial::opacity() const |
473 | { |
474 | return m_opacity; |
475 | } |
476 | |
477 | QQuick3DTexture *QQuick3DDefaultMaterial::opacityMap() const |
478 | { |
479 | return m_opacityMap; |
480 | } |
481 | |
482 | QQuick3DTexture *QQuick3DDefaultMaterial::bumpMap() const |
483 | { |
484 | return m_bumpMap; |
485 | } |
486 | |
487 | float QQuick3DDefaultMaterial::bumpAmount() const |
488 | { |
489 | return m_bumpAmount; |
490 | } |
491 | |
492 | QQuick3DTexture *QQuick3DDefaultMaterial::normalMap() const |
493 | { |
494 | return m_normalMap; |
495 | } |
496 | |
497 | QQuick3DTexture *QQuick3DDefaultMaterial::translucencyMap() const |
498 | { |
499 | return m_translucencyMap; |
500 | } |
501 | |
502 | float QQuick3DDefaultMaterial::translucentFalloff() const |
503 | { |
504 | return m_translucentFalloff; |
505 | } |
506 | |
507 | float QQuick3DDefaultMaterial::diffuseLightWrap() const |
508 | { |
509 | return m_diffuseLightWrap; |
510 | } |
511 | |
512 | bool QQuick3DDefaultMaterial::vertexColorsEnabled() const |
513 | { |
514 | return m_vertexColorsEnabled; |
515 | } |
516 | |
517 | QQuick3DMaterial::TextureChannelMapping QQuick3DDefaultMaterial::roughnessChannel() const |
518 | { |
519 | return m_roughnessChannel; |
520 | } |
521 | |
522 | QQuick3DMaterial::TextureChannelMapping QQuick3DDefaultMaterial::opacityChannel() const |
523 | { |
524 | return m_opacityChannel; |
525 | } |
526 | |
527 | QQuick3DMaterial::TextureChannelMapping QQuick3DDefaultMaterial::translucencyChannel() const |
528 | { |
529 | return m_translucencyChannel; |
530 | } |
531 | |
532 | float QQuick3DDefaultMaterial::pointSize() const |
533 | { |
534 | return m_pointSize; |
535 | } |
536 | |
537 | float QQuick3DDefaultMaterial::lineWidth() const |
538 | { |
539 | return m_lineWidth; |
540 | } |
541 | |
542 | void QQuick3DDefaultMaterial::markAllDirty() |
543 | { |
544 | m_dirtyAttributes = 0xffffffff; |
545 | QQuick3DMaterial::markAllDirty(); |
546 | } |
547 | |
548 | |
549 | void 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 | |
559 | void 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 | |
569 | void 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 | |
579 | void 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 | |
591 | void 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 | |
601 | void 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 | |
613 | void 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 | |
625 | void 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 | |
637 | void 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 | |
647 | void 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 | |
657 | void 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 | |
667 | void 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 | |
677 | void 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 | |
687 | void 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 | |
697 | void 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 | |
709 | void 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 | |
725 | void 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 | |
737 | void 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 | |
749 | void 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 | |
759 | void 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 | |
771 | void 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 | |
783 | void 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 | |
793 | void 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 | |
803 | void 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 | |
813 | void 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 | |
822 | void 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 | |
831 | void 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 | |
840 | void 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 | |
849 | void 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 | |
858 | QSSGRenderGraphObject *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 | |
974 | void QQuick3DDefaultMaterial::itemChange(QQuick3DObject::ItemChange change, const QQuick3DObject::ItemChangeData &value) |
975 | { |
976 | if (change == QQuick3DObject::ItemSceneChange) |
977 | updateSceneManager(sceneManager: value.sceneManager); |
978 | } |
979 | |
980 | void 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 | |
1006 | void QQuick3DDefaultMaterial::markDirty(QQuick3DDefaultMaterial::DirtyType type) |
1007 | { |
1008 | if (!(m_dirtyAttributes & quint32(type))) { |
1009 | m_dirtyAttributes |= quint32(type); |
1010 | update(); |
1011 | } |
1012 | } |
1013 | |
1014 | QT_END_NAMESPACE |
1015 | |