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