1 | // Copyright (C) 2019 The Qt Company Ltd. |
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only |
3 | |
4 | #include "qquick3dsceneenvironment_p.h" |
5 | #include "qquick3dobject_p.h" |
6 | #include "qquick3dtexture_p.h" |
7 | #include "qquick3dcubemaptexture_p.h" |
8 | #include "qquick3ddebugsettings_p.h" |
9 | |
10 | QT_BEGIN_NAMESPACE |
11 | |
12 | /*! |
13 | \qmltype SceneEnvironment |
14 | \inherits Object3D |
15 | \inqmlmodule QtQuick3D |
16 | \brief Lets you configure how a scene is rendered. |
17 | |
18 | SceneEnvironment defines a set of global properties for how a scene should be rendered. |
19 | |
20 | \note The QtQuick3D.Helpers module offers an \l ExtendedSceneEnvironment |
21 | type which inherits from SceneEnvironment and adds a number of built-in |
22 | effects on top. |
23 | |
24 | To use SceneEnvironment or \l ExtendedSceneEnvironment, associate the |
25 | \l{View3D::environment}{environment property} of a View3D with an instance |
26 | of these types. The object can be declared inline, for example like this: |
27 | |
28 | \qml |
29 | View3D { |
30 | environment: SceneEnvironment { |
31 | antialiasingMode: SceneEnvironment.MSAA |
32 | tonemapMode: SceneEnvironment.TonemapModeFilmic |
33 | backgroundMode: SceneEnvironment.SkyBox |
34 | lightProbe: Texture { |
35 | source: "panoramic_hdri_background.hdr" |
36 | } |
37 | } |
38 | } |
39 | \endqml |
40 | |
41 | Alternatively, the environment object can be defined separately. It can |
42 | then be referenced by one or more View3D objects. An example code snippet, |
43 | using \l ExtendedSceneEnvironment this time: |
44 | |
45 | \qml |
46 | ExtendedSceneEnvironment { |
47 | id: myEnv |
48 | vignetteEnabled: true |
49 | } |
50 | |
51 | View3D { |
52 | width: parent.width / 2 |
53 | environment: myEnv |
54 | } |
55 | |
56 | View3D { |
57 | width: parent.width / 2 |
58 | x: parent.width / 2 |
59 | environment: myEnv |
60 | } |
61 | \endqml |
62 | |
63 | \section1 Feature Overview |
64 | |
65 | \list |
66 | |
67 | \li Anti-aliasing settings. See \l{Anti-Aliasing Best Practices} for an |
68 | overview of this topic. The relevant properties are \l antialiasingMode, \l |
69 | antialiasingQuality, \l specularAAEnabled, \l temporalAAEnabled, \l |
70 | temporalAAStrength. In addition, if \l ExtendedSceneEnvironment is used, |
71 | another method is available via |
72 | \l{ExtendedSceneEnvironment::fxaaEnabled}{fxaaEnabled}. |
73 | |
74 | \li Screen space ambient occlusion. The relevant properties are |
75 | \l aoEnabled, \l aoStrength, \l aoBias, \l aoDistance, \l aoDither, |
76 | \l aoSampleRate, \l aoSoftness. |
77 | |
78 | \li Clear color, skybox, image-based lighting. For more information on IBL, |
79 | see \l{Using Image-Based Lighting}. The relevant properties are \l |
80 | backgroundMode, \l clearColor, \l lightProbe, \l probeExposure, \l |
81 | probeHorizon, \l probeOrientation, \l skyboxBlurAmount, \l skyBoxCubeMap. |
82 | |
83 | \li Tonemapping. \l tonemapMode configures the tonemapping method that is |
84 | used to convert the high dynamic range color values to the 0-1 range at the |
85 | end of the graphics pipeline. \l ExtendedSceneEnvironment offers a few |
86 | additional properties, such as |
87 | \l{ExtendedSceneEnvironment::whitePoint}{whitePoint} and |
88 | \l{ExtendedSceneEnvironment::sharpnessAmount}{sharpnessAmount} that can be |
89 | used to tune the tonemapping calculations. |
90 | |
91 | \li Depth buffer settings. The relevant properties are \l |
92 | depthPrePassEnabled, \l depthTestEnabled. |
93 | |
94 | \li Post-processing effects. In addition to the built-in post-processing |
95 | effects provided by \l ExtendedSceneEnvironment, applications can provide |
96 | their own custom effects via the \l Effect type. The \l effects property is |
97 | a list of \l Effect instances. |
98 | |
99 | \li Debug visualization settings, such as wireframe mode or rendering only |
100 | certain color contributions for the materials. This is controlled by the \l |
101 | DebugSettings object referenced from the \l debugSettings property. Most of |
102 | these settings can also be controlled interactively when a \l DebugView |
103 | item is added to the scene. |
104 | |
105 | \li Fog settings. To enable fog, set an appropriately configured |
106 | \l [QML] Fog object in the \l [QML] fog property. |
107 | |
108 | \li Lightmap baking settings. When pre-baked lightmaps are used for some |
109 | models in the scene, the \l Lightmapper object set in the \l lightmapper |
110 | property defines the settings used during the baking process. |
111 | |
112 | \li Scissor settings. To apply a scissor different than the viewport, set |
113 | the \l scissorRect property. |
114 | |
115 | \endlist |
116 | |
117 | \sa ExtendedSceneEnvironment |
118 | */ |
119 | |
120 | QQuick3DSceneEnvironment::QQuick3DSceneEnvironment(QQuick3DObject *parent) |
121 | : QQuick3DObject(*(new QQuick3DObjectPrivate(QQuick3DObjectPrivate::Type::SceneEnvironment)), parent) |
122 | { |
123 | m_debugSettings = new QQuick3DDebugSettings(this); |
124 | m_debugSettingsSignalConnection = QObject::connect(sender: m_debugSettings, signal: &QQuick3DDebugSettings::changed, context: this, |
125 | slot: [this] { update(); }); |
126 | QObject::connect(sender: m_debugSettings, signal: &QObject::destroyed, context: this, |
127 | slot: [this](QObject *obj) { |
128 | if (m_debugSettings == obj) { |
129 | m_debugSettings = nullptr; |
130 | update(); |
131 | } |
132 | }); |
133 | } |
134 | |
135 | QQuick3DSceneEnvironment::~QQuick3DSceneEnvironment() |
136 | { |
137 | } |
138 | |
139 | /*! |
140 | \qmlproperty enumeration QtQuick3D::SceneEnvironment::antialiasingMode |
141 | \since 5.15 |
142 | |
143 | This property controls the antialiasing mode that is applied when rendering |
144 | the scene. |
145 | |
146 | Possible values are: |
147 | \value SceneEnvironment.NoAA No antialiasing is applied. |
148 | \value SceneEnvironment.SSAA Supersample antialiasing is applied. |
149 | \value SceneEnvironment.MSAA Multisample antialiasing is applied. |
150 | \value SceneEnvironment.ProgressiveAA Progressive antialiasing is applied. |
151 | |
152 | The default value is \c SceneEnvironment.NoAA. |
153 | |
154 | \b Supersampling |
155 | |
156 | The scene is rendered in a higher resolution, and then scaled down to |
157 | actual resolution. |
158 | |
159 | \b Pros: High quality. Antialiases all scene content and not just geometry |
160 | silhouettes. |
161 | |
162 | \b Cons: Usually more expensive than MSAA. Increases video memory usage. |
163 | Supported with View3D items with all renderMode except Inline, but since |
164 | the technique implies rendering to a texture first, enabling SSAA with a |
165 | renderMode of Underlay or Overlay will result in using an intermediate |
166 | texture and render pass that would normally not be needed, meaning the |
167 | performance costs may be more noticeable. It is recommended to use SSAA |
168 | only when the renderMode is the default Offscreen. |
169 | |
170 | \b Multisampling |
171 | |
172 | The edges of geometry are super-sampled, resulting in smoother silhouettes. |
173 | This technique has no effect on the materials inside geometry, however. |
174 | |
175 | \b Pros: Works with any View3D item regardless of the renderMode. Good |
176 | results on geometry silhouettes, where aliasing is often most noticeable; |
177 | works with fast animation without issues. Performance depends purely on the |
178 | system's (GPU) capabilities. |
179 | |
180 | \b Cons: Does not help with texture or reflection issues. Increases video |
181 | memory usage. Can be expensive to use on less powerful graphics hardware. |
182 | Can be controlled on a per-window basis or for individual View3D items |
183 | depending on the renderMode. When using Underlay/Overlay with an effect |
184 | applied or Offscreen, MSAA can be controlled for each View3D item. On the |
185 | other hand, using Underlay/Overlay without any effect or Inline will make |
186 | MSAA controlled per-window. |
187 | |
188 | \note For View3D items with a \l{QtQuick3D::View3D::renderMode}{renderMode} |
189 | other than Underlay/Overlay with effects or Offscreen, multisampling can only |
190 | be enabled via the \l{QSurfaceFormat::setSamples()}{QSurfaceFormat} of the |
191 | QQuickWindow or QQuickView. This will then affect all content, |
192 | both 2D and 3D, in that window. |
193 | |
194 | \b {Progressive antialiasing} |
195 | |
196 | This property enables and sets the level of progressive antialiasing |
197 | applied to the scene. |
198 | |
199 | When all content of the scene has stopped moving, the camera is jiggled |
200 | very slightly between frames, and the result of each new frame is blended |
201 | with the previous frames. The more frames you accumulate, the better |
202 | looking the result. |
203 | |
204 | \b Pros: Provides great results when all content in the scene is standing still. |
205 | |
206 | \b Cons: Does not take effect if any visual changes are occurring. |
207 | Expensive due to having to accumulate and blend. Increases video memory |
208 | usage. |
209 | |
210 | \note Progressing antialiasing is not currently supported with multiview |
211 | rendering, and should not be used in VR/AR applications. |
212 | |
213 | See \l{Anti-Aliasing Best Practices} for further discussion on |
214 | anti-aliasing methods. |
215 | */ |
216 | QQuick3DSceneEnvironment::QQuick3DEnvironmentAAModeValues QQuick3DSceneEnvironment::antialiasingMode() const |
217 | { |
218 | return m_antialiasingMode; |
219 | } |
220 | |
221 | /*! |
222 | \qmlproperty enumeration QtQuick3D::SceneEnvironment::antialiasingQuality |
223 | \since 5.15 |
224 | |
225 | This property sets the level of antialiasing applied to the scene. |
226 | Behavior depends on used antialiasingMode. With antialiasingMode |
227 | property set to \c NoAA this property doesn't have an effect. |
228 | |
229 | Possible values are: |
230 | \value SceneEnvironment.Medium |
231 | SSAA: Antialiasing uses 1.2x supersampling resolution.\br |
232 | MSAA: Antialiasing uses 2 samples per pixel.\br |
233 | ProgressiveAA: Antialiasing uses 2 frames for final image. |
234 | \value SceneEnvironment.High |
235 | SSAA: Antialiasing uses 1.5x supersampling resolution.\br |
236 | MSAA: Antialiasing uses 4 samples per pixel.\br |
237 | ProgressiveAA: Antialiasing uses 4 frames for final image. |
238 | \value SceneEnvironment.VeryHigh |
239 | SSAA: Antialiasing uses 2.0x supersampling resolution.\br |
240 | MSAA: Antialiasing uses 8 samples per pixel.\br |
241 | ProgressiveAA: Antialiasing uses 8 frames for final image. |
242 | |
243 | The default value is \c SceneEnvironment.High |
244 | */ |
245 | |
246 | QQuick3DSceneEnvironment::QQuick3DEnvironmentAAQualityValues QQuick3DSceneEnvironment::antialiasingQuality() const |
247 | { |
248 | return m_antialiasingQuality; |
249 | } |
250 | |
251 | /*! |
252 | \qmlproperty enumeration QtQuick3D::SceneEnvironment::backgroundMode |
253 | |
254 | This property controls if and how the background of the scene should be |
255 | cleared. |
256 | |
257 | \note The clearing of the color buffer backing the View 3D does not always |
258 | happen: depending on the \l{QtQuick3D::View3D::renderMode}{renderMode} |
259 | property the View3D may not perform any clearing on its own, in which case |
260 | \c{SceneEnvironment.Transparent} and \c{SceneEnvironment.Color} have no |
261 | effect. Only the default \c Offscreen \l{View3D::renderMode}{render mode} |
262 | (rendering into a texture) supports all clearing modes. With the \c |
263 | Underlay mode, use \l{QQuickWindow::setColor()} or |
264 | \l[QtQuick]{Window::color}{Window.color} to control the clear color for the |
265 | Qt Quick scene. SkyBox is handled differently, as it implies drawing actual |
266 | geometry, so that works identically across all render modes. |
267 | |
268 | \value SceneEnvironment.Transparent |
269 | The scene is cleared to be transparent. This is useful to render 3D content on top of another item. |
270 | This mode has no effect when the View3D is using a renderMode of Underlay or Overlay without any |
271 | post processing enabled. |
272 | \value SceneEnvironment.Color |
273 | The scene is cleared with the color specified by the clearColor property. |
274 | This mode has no effect when the View3D is using a renderMode of Underlay or Overlay without any |
275 | post processing enabled. |
276 | \value SceneEnvironment.SkyBox |
277 | The scene will not be cleared, but instead a SkyBox or Skydome will be rendered. The SkyBox |
278 | is defined using the HDRI map defined in the lightProbe property. |
279 | \value SceneEnvironment.SkyBoxCubeMap |
280 | The scene will not be cleared, but instead a SkyBox or Skydome will be rendered. The SkyBox |
281 | is defined using the cubemap defined in the skyBoxCubeMap property. |
282 | |
283 | The default value is \c SceneEnvironment.Transparent |
284 | |
285 | Take the following example. The Suzanne model is expected to be |
286 | pre-processed with the \c balsam tool and is sourced from the |
287 | \l{https://github.com/KhronosGroup/glTF-Sample-Models}{glTF Sample Models} |
288 | repository. |
289 | |
290 | \qml |
291 | import QtQuick |
292 | import QtQuick3D |
293 | import QtQuick3D.Helpers |
294 | |
295 | Item { |
296 | width: 1280 |
297 | height: 720 |
298 | |
299 | View3D { |
300 | id: v3d |
301 | anchors.fill: parent |
302 | |
303 | environment: ExtendedSceneEnvironment { |
304 | backgroundMode: SceneEnvironment.SkyBox |
305 | lightProbe: Texture { source: "00455_OpenfootageNET_field_low.hdr" } |
306 | |
307 | glowEnabled: true |
308 | glowStrength: 1.25 |
309 | glowBloom: 0.25 |
310 | glowBlendMode: ExtendedSceneEnvironment.GlowBlendMode.Additive |
311 | } |
312 | |
313 | DirectionalLight { |
314 | } |
315 | |
316 | Suzanne { |
317 | scale: Qt.vector3d(50, 50, 50) |
318 | z: -500 |
319 | } |
320 | |
321 | PerspectiveCamera { |
322 | id: camera |
323 | } |
324 | |
325 | WasdController { |
326 | controlledObject: camera |
327 | } |
328 | } |
329 | } |
330 | \endqml |
331 | |
332 | Using image-based lighting in additional to the DirectionalLight and also |
333 | using the light probe texture as the skybox gives us the following: |
334 | |
335 | \image sceneenvironment_background_ibl.jpg |
336 | |
337 | What happens if there is no light probe? |
338 | |
339 | \qml |
340 | backgroundMode: SceneEnvironment.Transparent |
341 | \endqml |
342 | |
343 | Here the background is provided not by the View3D but by the QQuickWindow |
344 | or QQuickView hosting the 2D and 3D scene. Lighting is based on the |
345 | DirectionalLight only. |
346 | |
347 | \image sceneenvironment_background_transparent.jpg |
348 | |
349 | Using a fixed clear color: |
350 | |
351 | \qml |
352 | backgroundMode: SceneEnvironment.Color |
353 | clearColor: "green" |
354 | \endqml |
355 | |
356 | \image sceneenvironment_background_color.jpg |
357 | |
358 | \sa lightProbe, QQuickWindow::setColor(), Window::color, View3D |
359 | */ |
360 | |
361 | QQuick3DSceneEnvironment::QQuick3DEnvironmentBackgroundTypes QQuick3DSceneEnvironment::backgroundMode() const |
362 | { |
363 | return m_backgroundMode; |
364 | } |
365 | |
366 | /*! |
367 | \qmlproperty color QtQuick3D::SceneEnvironment::clearColor |
368 | |
369 | This property defines which color will be used to clear the viewport when |
370 | using \c SceneEnvironment.Color for the backgroundMode property. |
371 | |
372 | The default value is \c Qt::black |
373 | |
374 | \sa backgroundMode |
375 | */ |
376 | |
377 | QColor QQuick3DSceneEnvironment::clearColor() const |
378 | { |
379 | return m_clearColor; |
380 | } |
381 | |
382 | /*! |
383 | \qmlproperty float QtQuick3D::SceneEnvironment::aoStrength |
384 | |
385 | This property defines the amount of ambient occulusion applied. Ambient |
386 | occulusion is a form of approximated global illumination which causes |
387 | non-directional self-shadowing where objects are close together. |
388 | A value of 100 causes full darkness shadows; lower values cause the |
389 | shadowing to appear lighter. A value of 0 disables ambient occlusion |
390 | entirely, improving performance at a cost to the visual realism of 3D |
391 | objects rendered in the scene. |
392 | |
393 | All values other than 0 have the same impact to the performance. |
394 | |
395 | The default value is 0.0. The maximum value is 100.0. |
396 | |
397 | A value of 0 is equivalent to setting \l aoEnabled to false. |
398 | |
399 | Pictured here with the default aoSoftness and aoDistance: |
400 | |
401 | \table |
402 | \header |
403 | \li aoStrength of 0 (AO disabled) |
404 | \li aoStrength of 100 |
405 | \li aoStrength of 50 |
406 | \row |
407 | \li \image sceneenvironment_ao_off.jpg |
408 | \li \image sceneenvironment_ao_full_strength.jpg |
409 | \li \image sceneenvironment_ao_half_strength.jpg |
410 | \endtable |
411 | |
412 | \note Getting visually good-looking screen space ambient occlusion is |
413 | dependent on carefully tuning a number of related parameters, such as \l |
414 | aoStrength, \l aoSoftness, \l aoDistance, \l aoDither, \l aoBias, and \l |
415 | aoSampleRate. |
416 | |
417 | \sa aoEnabled, aoDistance, aoSoftness |
418 | */ |
419 | float QQuick3DSceneEnvironment::aoStrength() const |
420 | { |
421 | return m_aoStrength; |
422 | } |
423 | |
424 | /*! |
425 | \qmlproperty float QtQuick3D::SceneEnvironment::aoDistance |
426 | |
427 | This property defines roughly how far ambient occlusion shadows spread away |
428 | from objects. Greater distances cause increasing impact to performance. |
429 | |
430 | The default value is 5.0. |
431 | |
432 | Pictured here with the default aoSoftness and the maximum aoStrength: |
433 | |
434 | \table |
435 | \header |
436 | \li aoDistance of 5 |
437 | \li aoDistance of 1 |
438 | \row |
439 | \li \image sceneenvironment_ao_distance_5.jpg |
440 | \li \image sceneenvironment_ao_distance_1.jpg |
441 | \endtable |
442 | |
443 | \note Getting visually good-looking screen space ambient occlusion is |
444 | dependent on carefully tuning a number of related parameters, such as \l |
445 | aoStrength, \l aoSoftness, \l aoDistance, \l aoDither, \l aoBias, and \l |
446 | aoSampleRate. |
447 | |
448 | \sa aoStrength, aoSoftness |
449 | */ |
450 | float QQuick3DSceneEnvironment::aoDistance() const |
451 | { |
452 | return m_aoDistance; |
453 | } |
454 | |
455 | /*! |
456 | \qmlproperty float QtQuick3D::SceneEnvironment::aoSoftness |
457 | |
458 | This property defines how smooth the edges of the ambient occlusion shading |
459 | are. |
460 | |
461 | The value must be between 0.0 and 50.0. The default value is 50.0. |
462 | |
463 | Pictured here with the default aoDistance and the maximum aoStrength: |
464 | |
465 | \table |
466 | \header |
467 | \li aoSoftness of 50 |
468 | \li aoSoftness of 25 |
469 | \row |
470 | \li \image sceneenvironment_ao_softness_default.jpg |
471 | \li \image sceneenvironment_ao_softness_half.jpg |
472 | \endtable |
473 | |
474 | \note Getting visually good-looking screen space ambient occlusion is |
475 | dependent on carefully tuning a number of related parameters, such as \l |
476 | aoStrength, \l aoSoftness, \l aoDistance, \l aoDither, \l aoBias, and \l |
477 | aoSampleRate. |
478 | |
479 | \sa aoStrength, aoDistance |
480 | */ |
481 | float QQuick3DSceneEnvironment::aoSoftness() const |
482 | { |
483 | return m_aoSoftness; |
484 | } |
485 | |
486 | /*! |
487 | \qmlproperty bool QtQuick3D::SceneEnvironment::aoDither |
488 | |
489 | When this property is enabled it scatters the edges of the ambient |
490 | occlusion shadow bands to improve smoothness (at the risk of sometimes |
491 | producing obvious patterned artifacts). |
492 | |
493 | \note Very large distances between the clipping planes of your camera may |
494 | cause problems with ambient occlusion. If you are seeing odd banding in |
495 | your ambient occlusion, try adjusting the \l {PerspectiveCamera::}{clipFar} |
496 | property of your camera to be closer to your content. |
497 | |
498 | The default value is \c false. |
499 | |
500 | \sa {QtQuick3D::PerspectiveCamera::clipFar}{PerspectiveCamera.clipFar}, |
501 | {QtQuick3D::OrthographicCamera::clipFar}{OrthographicCamera.clipFar} |
502 | */ |
503 | bool QQuick3DSceneEnvironment::aoDither() const |
504 | { |
505 | return m_aoDither; |
506 | } |
507 | |
508 | /*! |
509 | \qmlproperty int QtQuick3D::SceneEnvironment::aoSampleRate |
510 | |
511 | This property defines ambient occlusion quality (more shades of gray) at |
512 | the expense of performance. |
513 | |
514 | The value must be 2, 3, or 4. The default value is 2. |
515 | */ |
516 | int QQuick3DSceneEnvironment::aoSampleRate() const |
517 | { |
518 | return m_aoSampleRate; |
519 | } |
520 | |
521 | /*! |
522 | \qmlproperty float QtQuick3D::SceneEnvironment::aoBias |
523 | |
524 | This property defines a cutoff distance preventing objects from exhibiting |
525 | ambient occlusion at close distances. Higher values increase the distance |
526 | required between objects before ambient occlusion is seen. |
527 | |
528 | \note If you see ambient occlusion shadowing on objects where there should |
529 | be no shadowing, increase the value slightly to clip away close results. |
530 | |
531 | The default value is 0.0. |
532 | */ |
533 | float QQuick3DSceneEnvironment::aoBias() const |
534 | { |
535 | return m_aoBias; |
536 | } |
537 | |
538 | /*! |
539 | \qmlproperty QtQuick3D::Texture QtQuick3D::SceneEnvironment::lightProbe |
540 | |
541 | This property defines an image used to light the scene, either instead of, |
542 | or in addition to standard lights. |
543 | |
544 | The image is preferably a high-dynamic range image or a \l{Pre-generating |
545 | IBL cubemap}{pre-generated cubemap}. Pre-baking provides significant |
546 | performance improvements at run time, because no time is spent on filtering |
547 | and mipmap generation. If the source is a .hdr or other image, the GPU-based |
548 | pre-processing happens at run time after loading the image file, and that |
549 | can be potentially time consuming, in particular on embedded and mobile |
550 | hardware. Therefore, it is strongly recommended that applications |
551 | pre-process .hdr images at latest at build time, as described |
552 | \l{Pre-generating IBL cubemap}{here}. |
553 | |
554 | \note Using a Texture with \l{Texture::sourceItem}{sourceItem} is not |
555 | supported in combination with this property. Pre-filtering of all mip |
556 | levels for dynamic Qt Quick content is typically not reasonable in practice |
557 | due to performance implications. |
558 | |
559 | For more information on image-based lighting, see \l{Using Image-Based Lighting}. |
560 | |
561 | \note The light probe texture, when the property is set to a valid Texture, |
562 | is used for lighting regardless of the \l backgroundMode. However, when \l |
563 | backgroundMode is set to \c{SceneEnvironment.SkyBox}, the texture is also |
564 | used to render the scene background as a skybox. |
565 | |
566 | The examples below were generated with varying the \l backgroundMode in the |
567 | environment of the following scene. The scene has no DirectionLight, |
568 | PointLight, or SpotLight. All lighting is based on the panoramic HDRI |
569 | image. |
570 | |
571 | \qml |
572 | import QtQuick |
573 | import QtQuick3D |
574 | import QtQuick3D.Helpers |
575 | |
576 | Item { |
577 | width: 1280 |
578 | height: 720 |
579 | |
580 | View3D { |
581 | id: v3d |
582 | anchors.fill: parent |
583 | |
584 | environment: ExtendedSceneEnvironment { |
585 | backgroundMode: SceneEnvironment.SkyBox |
586 | lightProbe: Texture { source: "00455_OpenfootageNET_field_low.hdr" } |
587 | |
588 | tonemapMode: SceneEnvironment.TonemapModeFilmic |
589 | sharpnessAmount: 0.4 |
590 | |
591 | glowEnabled: true |
592 | glowStrength: 1.25 |
593 | glowBloom: 0.25 |
594 | glowBlendMode: ExtendedSceneEnvironment.GlowBlendMode.Additive |
595 | } |
596 | |
597 | Node { |
598 | scale: Qt.vector3d(100, 100, 100) |
599 | |
600 | Sponza { |
601 | } |
602 | |
603 | Suzanne { |
604 | y: 1 |
605 | scale: Qt.vector3d(0.5, 0.5, 0.5) |
606 | eulerRotation.y: -90 |
607 | } |
608 | } |
609 | |
610 | PerspectiveCamera { |
611 | id: camera |
612 | y: 100 |
613 | } |
614 | |
615 | WasdController { |
616 | controlledObject: camera |
617 | } |
618 | } |
619 | } |
620 | \endqml |
621 | |
622 | Results with the above environment: |
623 | |
624 | \image sceneenvironment_lightprobe.jpg |
625 | \image sceneenvironment_lightprobe_2.jpg |
626 | |
627 | Switching the backgroundMode to \c{SceneEnvironment.Transparent} would give us: |
628 | |
629 | \image sceneenvironment_lightprobe_transparent.jpg |
630 | \image sceneenvironment_lightprobe_transparent_2.jpg |
631 | |
632 | Here the lighting of the 3D scene is the same as before, meaning the |
633 | materials use the light probe in the lighting calculations the same way as |
634 | before, but there is no skybox rendered. The background is white since that |
635 | is the default clear color of the QQuickWindow hosting the 2D and 3D scene. |
636 | |
637 | It is valid to set the lightProbe property value back to the default null. |
638 | This unassigns the previously associated texture. For example, let's use |
639 | the Delete key to dynamically toggle between image-based lighting with a |
640 | skybox, and no image-based lighting with a fixed clear color for the |
641 | background: |
642 | |
643 | \qml |
644 | environment: ExtendedSceneEnvironment { |
645 | id: env |
646 | |
647 | backgroundMode: SceneEnvironment.SkyBox |
648 | lightProbe: iblTex |
649 | |
650 | tonemapMode: SceneEnvironment.TonemapModeFilmic |
651 | sharpnessAmount: 0.4 |
652 | |
653 | glowEnabled: true |
654 | glowStrength: 1.25 |
655 | glowBloom: 0.25 |
656 | glowBlendMode: ExtendedSceneEnvironment.GlowBlendMode.Additive |
657 | } |
658 | |
659 | Texture { |
660 | id: iblTex |
661 | source: "00455_OpenfootageNET_field_low.hdr" |
662 | } |
663 | |
664 | focus: true |
665 | Keys.onDeletePressed: { |
666 | if (env.backgroundMode == SceneEnvironment.SkyBox) { |
667 | env.backgroundMode = SceneEnvironment.Color; |
668 | env.clearColor = "green"; |
669 | env.lightProbe = null; |
670 | } else { |
671 | env.backgroundMode = SceneEnvironment.SkyBox; |
672 | env.lightProbe = iblTex; |
673 | } |
674 | } |
675 | \endqml |
676 | |
677 | Pressing Delete gives the following result. Remember that the scene used |
678 | here has no lights so all 3D models appear completely black. |
679 | |
680 | \image sceneenvironment_lightprobe_null.jpg |
681 | \image sceneenvironment_lightprobe_null_2.jpg |
682 | |
683 | While lightProbe is commonly used in combination with Texture instances |
684 | that source their data from an image file (typically .hdr or .ktx), it can |
685 | also makes sense to associate with a Texture that uses in-memory, |
686 | \l{Texture::textureData}{procedurally generated image data}. A prime |
687 | example of this is a Texture where the image data is generated by \l |
688 | ProceduralSkyTextureData from the QtQuick3D.Helpers module: |
689 | |
690 | \qml |
691 | backgroundMode: SceneEnvironment.SkyBox |
692 | lightProbe: Texture { |
693 | textureData: ProceduralSkyTextureData { |
694 | } |
695 | } |
696 | \endqml |
697 | |
698 | This gives us a procedurally generated HDR skybox texture that is now used |
699 | both as the skybox and for image-based lighting: |
700 | |
701 | \image sceneenvironment_lightprobe_proceduralsky.jpg |
702 | |
703 | \sa backgroundMode, {Using Image-Based Lighting}, {Pre-generating IBL |
704 | cubemap}, probeExposure, probeHorizon, probeOrientation, ProceduralSkyTextureData |
705 | */ |
706 | QQuick3DTexture *QQuick3DSceneEnvironment::lightProbe() const |
707 | { |
708 | return m_lightProbe; |
709 | } |
710 | |
711 | /*! |
712 | \qmlproperty float QtQuick3D::SceneEnvironment::probeExposure |
713 | |
714 | This property modifies the amount of light emitted by the light probe. Part |
715 | of the tonemapping is exposure mapping, and this property adjusts how |
716 | the light values in the light probes get tonemaped. |
717 | |
718 | By default exposure is set to is 1.0 |
719 | |
720 | \note This property does not have an effect when \l tonemapMode is set to |
721 | \c SceneEnvironment.TonemapModeNone. |
722 | |
723 | \sa lightProbe, probeHorizon, probeOrientation |
724 | */ |
725 | float QQuick3DSceneEnvironment::probeExposure() const |
726 | { |
727 | return m_probeExposure; |
728 | } |
729 | |
730 | /*! |
731 | \qmlproperty float QtQuick3D::SceneEnvironment::probeHorizon |
732 | |
733 | This property when defined with increasing values adds darkness (black) |
734 | to the bottom half of the environment, forcing the lighting to come |
735 | predominantly from the top of the image (and removing specific reflections |
736 | from the lower half). This property is useful for accounting for a ground |
737 | plane that would have the effect of obscuring the reflection of the light |
738 | probe from the ground. This is necessary because light probe contributions |
739 | come directily from the image without consideration for the content of the |
740 | scene. |
741 | |
742 | The expected value range for the probeHorizon property is between 0.0 |
743 | and 1.0. Any value outside of this range will be clamped to the |
744 | expected range. |
745 | |
746 | By default probeHorizon is set to 0.0 which means the whole light probe |
747 | is used without adjustment. |
748 | |
749 | \note The probeHorizon property only affects materials lighting, and has |
750 | no effect on the rendering of the sky box. |
751 | |
752 | \sa lightProbe, probeExposure, probeOrientation |
753 | */ |
754 | float QQuick3DSceneEnvironment::probeHorizon() const |
755 | { |
756 | return m_probeHorizon; |
757 | } |
758 | |
759 | /*! |
760 | \qmlproperty vector3d QtQuick3D::SceneEnvironment::probeOrientation |
761 | |
762 | This property when defines the orientation of the light probe. Orientation |
763 | is defined in terms of euler angles in degrees over the x, y, and z axes. |
764 | |
765 | \note This value augments how the lightProbe Texture is sampled in combination |
766 | with any texture rotations and offsets set on the lightProbe texture. |
767 | |
768 | \sa lightProbe, probeHorizon, probeExposure |
769 | */ |
770 | QVector3D QQuick3DSceneEnvironment::probeOrientation() const |
771 | { |
772 | return m_probeOrientation; |
773 | } |
774 | |
775 | /*! |
776 | \qmlproperty bool QtQuick3D::SceneEnvironment::temporalAAEnabled |
777 | |
778 | When this property is enabled temporal antialiasing will be used. |
779 | |
780 | The camera is jiggled very slightly between frames, and the result of each |
781 | new frame is blended with the previous frame. |
782 | |
783 | \note Temporal antialiasing doesn't have an effect when antialiasingMode is MSAA. |
784 | \note When combined with ProgressiveAA antialiasingMode, temporalAA is used |
785 | when scene animates while ProgressiveAA is used once animations stop. |
786 | |
787 | \b Pros: Due to the jiggling camera it finds real details that were otherwise |
788 | lost; low impact on performance. |
789 | |
790 | \b Cons: Fast-moving objects cause one-frame ghosting. |
791 | |
792 | \default false |
793 | |
794 | \note Temporal antialiasing is not currently supported with multiview |
795 | rendering, and should not be used in VR/AR applications. |
796 | */ |
797 | bool QQuick3DSceneEnvironment::temporalAAEnabled() const |
798 | { |
799 | return m_temporalAAEnabled; |
800 | } |
801 | |
802 | /*! |
803 | \qmlproperty float QtQuick3D::SceneEnvironment::temporalAAStrength |
804 | \since 5.15 |
805 | |
806 | This property modifies the amount of temporal movement (antialiasing). |
807 | This has an effect only when temporalAAEnabled property is true. |
808 | |
809 | \default 0.3 |
810 | |
811 | \sa temporalAAEnabled |
812 | */ |
813 | float QQuick3DSceneEnvironment::temporalAAStrength() const |
814 | { |
815 | return m_temporalAAStrength; |
816 | } |
817 | |
818 | /*! |
819 | \qmlproperty bool QtQuick3D::SceneEnvironment::specularAAEnabled |
820 | \since 6.4 |
821 | |
822 | When this property is enabled, specular aliasing will be mitigated. |
823 | Specular aliasing is often visible in form of bright dots, possibly |
824 | flickering when moving the camera around. |
825 | |
826 | The default value is false. |
827 | |
828 | \table |
829 | \header |
830 | \li Specular AA disabled |
831 | \li Specular AA enabled |
832 | \row |
833 | \li \image specular_aa_off.jpg |
834 | \li \image specular_aa_on.jpg |
835 | \endtable |
836 | */ |
837 | bool QQuick3DSceneEnvironment::specularAAEnabled() const |
838 | { |
839 | return m_specularAAEnabled; |
840 | } |
841 | |
842 | /*! |
843 | \qmlproperty bool QtQuick3D::SceneEnvironment::depthTestEnabled |
844 | |
845 | The default value is \c true. By default the renderer classifies the objects |
846 | in the scene either as \c opaque or as \c semi-transparent. The objects |
847 | (sub-meshes with the associated material) in the \c opaque list are rendered |
848 | first, with depth testing and depth write enabled, providing optimal |
849 | Z-culling for typical 3D objects that have no semi-transparent regions. The |
850 | objects in the \c semi-transparent list are rendered with depth write |
851 | disabled, although still with depth testing enabled (to test against the |
852 | opaque objects), in back to front order (sorted based on their center point's |
853 | distance from the camera). This allows correct blending ("see through") for |
854 | 3D objects that involve semi-transparent regions on their surface, either |
855 | due to the \l{Node::opacity}{node opacity} or due to some color or texture |
856 | map in the material. |
857 | |
858 | When this property is set to \c {false}, the Z-buffer is not written and |
859 | tested against, the depth test is skipped, and all objects, including fully |
860 | opaque ones, are rendered in one go, sorted back to front. |
861 | |
862 | Setting this property to \c false should be rarely needed. It can be useful |
863 | in scenes where it is known that there is little benefit in the two-round |
864 | approach because either there are very few opaque objects, or they are |
865 | transformed in a way that a single back to front sorted pass performs |
866 | better. |
867 | |
868 | \note Setting this property to \c false may cause rendering errors in |
869 | certain scenes. In addition, some features, such as shadows, ambient |
870 | occlusion, \c SCREEN_TEXTURE and \c DEPTH_TEXTURE in custom materials and |
871 | effects, will not behave correctly without enabling depth buffer usage. |
872 | |
873 | \note This flag has no control over the presence of a depth or |
874 | depth-stencil buffer. Such buffers may still be allocated even when this is |
875 | set to \c false. |
876 | */ |
877 | bool QQuick3DSceneEnvironment::depthTestEnabled() const |
878 | { |
879 | return m_depthTestEnabled; |
880 | } |
881 | /*! |
882 | \qmlproperty bool QtQuick3D::SceneEnvironment::depthPrePassEnabled |
883 | |
884 | When enabled, the renderer performs a Z-prepass for opaque objects, meaning |
885 | it renders them with a simple shader and color write disabled in order to |
886 | get the depth buffer pre-filled before issuing draw calls for the main |
887 | rendering passes. |
888 | |
889 | This can improve performance depending on the scene contents. It is |
890 | typically scenes with lots of overlapping objects and expensive fragment |
891 | shading that benefit from this. At the same time, it is worth noting that |
892 | the renderer performs front to back sorting for opaque objects, which in |
893 | itself helps reducing unnecessary fragment shading, and therefore the |
894 | Z-prepass does not always bring significant improvements. |
895 | |
896 | On GPUs that use a tiled rendering architecture, which is common in mobile |
897 | and embedded systems, it is recommended to set this to \c false. |
898 | |
899 | The default value is \c false. |
900 | |
901 | \note This property has no effect when depth testing is disabled. |
902 | */ |
903 | bool QQuick3DSceneEnvironment::depthPrePassEnabled() const |
904 | { |
905 | return m_depthPrePassEnabled; |
906 | } |
907 | |
908 | /*! |
909 | \qmlproperty List<QtQuick3D::Effect> QtQuick3D::SceneEnvironment::effects |
910 | \since 5.15 |
911 | |
912 | This property contains a list of post-processing effects that will be |
913 | applied to the entire viewport. The result of each effect is fed to the |
914 | next so the order is significant. |
915 | |
916 | \note For technical reasons, adding the same \l{QtQuick3D::Effect}{Effect} |
917 | node several times to the list is unsupported and will give unexpected results. |
918 | */ |
919 | QQmlListProperty<QQuick3DEffect> QQuick3DSceneEnvironment::effects() |
920 | { |
921 | return QQmlListProperty<QQuick3DEffect>(this, |
922 | nullptr, |
923 | QQuick3DSceneEnvironment::qmlAppendEffect, |
924 | QQuick3DSceneEnvironment::qmlEffectsCount, |
925 | QQuick3DSceneEnvironment::qmlEffectAt, |
926 | QQuick3DSceneEnvironment::qmlClearEffects); |
927 | } |
928 | |
929 | /*! |
930 | \qmlproperty enumeration QtQuick3D::SceneEnvironment::tonemapMode |
931 | \since 6.0 |
932 | |
933 | This property defines how colors are tonemapped before rendering. All |
934 | rendering in Qt Quick 3D is performed in linear color space and can in |
935 | many cases lead to generating color values that are not displayable. The |
936 | tonemapMode determines the technique that is used to remap colors into a |
937 | displayable range. |
938 | |
939 | The default value is \c SceneEnvironment.TonemapModeLinear |
940 | |
941 | \value SceneEnvironment.TonemapModeNone |
942 | All Tonemapping is bypassed. This mode is useful when performing post |
943 | processing effects. |
944 | \value SceneEnvironment.TonemapModeLinear |
945 | Linear tonemapping is applied. Colors are gamma corrected and returned |
946 | in sRGB color space. |
947 | \value SceneEnvironment.TonemapModeAces |
948 | Academy Color Encoding System tonemapping is applied. |
949 | \value SceneEnvironment.TonemapModeHejlDawson |
950 | Hejl-Dawson tonemapping is applied. |
951 | \value SceneEnvironment.TonemapModeFilmic |
952 | Filmic tonemapping is applied. |
953 | |
954 | See \l{ExtendedSceneEnvironment::tonemapMode}{ExtendedSceneEnvironment} for |
955 | an example of these different modes. |
956 | |
957 | \note When using post-processing effects, most effects expect untonemapped |
958 | linear color data. With application-provided, custom effects implemented |
959 | via the \l Effect type, it is important to know that starting with Qt 6.5 |
960 | effects can safely assume that they work with linear color data, and |
961 | tonemapping is performed automatically on the output of the last effect in |
962 | the chain. If there is a need to customize tonemapping completely, consider |
963 | setting the \c SceneEnvironment.TonemapModeNone value to disable the |
964 | built-in tonemapper, and perform the appropriate adjustments on the color |
965 | value in the last effect in the chain instead. This does not apply to the |
966 | built-in effects of \l ExtendedSceneEnvironment, because those |
967 | automatically take care of proper tonemapping regardless of what |
968 | combination of built-in effects are enabled in the environment. |
969 | */ |
970 | QQuick3DSceneEnvironment::QQuick3DEnvironmentTonemapModes QQuick3DSceneEnvironment::tonemapMode() const |
971 | { |
972 | return m_tonemapMode; |
973 | } |
974 | |
975 | /*! |
976 | \qmlproperty float QtQuick3D::SceneEnvironment::skyboxBlurAmount |
977 | \since 6.4 |
978 | |
979 | This property determines how much much the skybox should be blurred when |
980 | using \c SceneEnvironment.SkyBox for the \l backgroundMode property. The |
981 | default value is \c 0.0 which means there is no blurring. |
982 | |
983 | Acceptable values range between 0.0 and 1.0, all other values will be clamped |
984 | to this range. |
985 | |
986 | */ |
987 | |
988 | float QQuick3DSceneEnvironment::skyboxBlurAmount() const |
989 | { |
990 | return m_skyboxBlurAmount; |
991 | } |
992 | |
993 | /*! |
994 | \qmlproperty QtQuick3D::DebugSettings QtQuick3D::SceneEnvironment::debugSettings |
995 | \since 6.5 |
996 | |
997 | This property specifies a \c DebugSettings object which is used to |
998 | configure the debugging tools of the renderer. During construction |
999 | the SceneEnvironment automatically creates a DebugSettings object |
1000 | associated with itself, and therefore setting a custom DebugSettings |
1001 | is usually not required. |
1002 | |
1003 | An example of rendering the scene with wireframe mode enabled: |
1004 | \image debugsettings_wireframe.jpg |
1005 | |
1006 | Visualizing the normal vectors of the meshes: |
1007 | \image debugsettings_normals.jpg |
1008 | |
1009 | Visualizing the specular lighting contribution: |
1010 | \image debugsettings_specular.jpg |
1011 | |
1012 | \sa DebugSettings |
1013 | */ |
1014 | |
1015 | QQuick3DDebugSettings *QQuick3DSceneEnvironment::debugSettings() const |
1016 | { |
1017 | return m_debugSettings; |
1018 | } |
1019 | |
1020 | /*! |
1021 | \qmlproperty rect QtQuick3D::SceneEnvironment::scissorRect |
1022 | \since 6.5 |
1023 | |
1024 | This property defines a scissor rectangle in view coordinates, with the |
1025 | top-left corner at [0, 0] |
1026 | */ |
1027 | |
1028 | QRect QQuick3DSceneEnvironment::scissorRect() const |
1029 | { |
1030 | return m_scissorRect; |
1031 | } |
1032 | |
1033 | void QQuick3DSceneEnvironment::setAntialiasingMode(QQuick3DSceneEnvironment::QQuick3DEnvironmentAAModeValues antialiasingMode) |
1034 | { |
1035 | if (m_antialiasingMode == antialiasingMode) |
1036 | return; |
1037 | |
1038 | m_antialiasingMode = antialiasingMode; |
1039 | emit antialiasingModeChanged(); |
1040 | update(); |
1041 | } |
1042 | |
1043 | void QQuick3DSceneEnvironment::setAntialiasingQuality(QQuick3DSceneEnvironment::QQuick3DEnvironmentAAQualityValues antialiasingQuality) |
1044 | { |
1045 | if (m_antialiasingQuality == antialiasingQuality) |
1046 | return; |
1047 | |
1048 | m_antialiasingQuality = antialiasingQuality; |
1049 | emit antialiasingQualityChanged(); |
1050 | update(); |
1051 | } |
1052 | |
1053 | void QQuick3DSceneEnvironment::setBackgroundMode(QQuick3DSceneEnvironment::QQuick3DEnvironmentBackgroundTypes backgroundMode) |
1054 | { |
1055 | if (m_backgroundMode == backgroundMode) |
1056 | return; |
1057 | |
1058 | m_backgroundMode = backgroundMode; |
1059 | emit backgroundModeChanged(); |
1060 | update(); |
1061 | } |
1062 | |
1063 | void QQuick3DSceneEnvironment::setClearColor(const QColor &clearColor) |
1064 | { |
1065 | if (m_clearColor == clearColor) |
1066 | return; |
1067 | |
1068 | m_clearColor = clearColor; |
1069 | emit clearColorChanged(); |
1070 | update(); |
1071 | } |
1072 | |
1073 | void QQuick3DSceneEnvironment::setAoStrength(float aoStrength) |
1074 | { |
1075 | if (qFuzzyCompare(p1: m_aoStrength, p2: aoStrength)) |
1076 | return; |
1077 | |
1078 | m_aoStrength = aoStrength; |
1079 | |
1080 | const bool aoEnabled = !(qFuzzyIsNull(f: m_aoStrength) || qFuzzyIsNull(f: m_aoDistance)); |
1081 | setAoEnabled(aoEnabled); |
1082 | |
1083 | emit aoStrengthChanged(); |
1084 | update(); |
1085 | } |
1086 | |
1087 | void QQuick3DSceneEnvironment::setAoDistance(float aoDistance) |
1088 | { |
1089 | if (qFuzzyCompare(p1: m_aoDistance, p2: aoDistance)) |
1090 | return; |
1091 | |
1092 | m_aoDistance = aoDistance; |
1093 | |
1094 | const bool aoEnabled = !(qFuzzyIsNull(f: m_aoStrength) || qFuzzyIsNull(f: m_aoDistance)); |
1095 | setAoEnabled(aoEnabled); |
1096 | |
1097 | emit aoDistanceChanged(); |
1098 | update(); |
1099 | } |
1100 | |
1101 | void QQuick3DSceneEnvironment::setAoSoftness(float aoSoftness) |
1102 | { |
1103 | if (qFuzzyCompare(p1: m_aoSoftness, p2: aoSoftness)) |
1104 | return; |
1105 | |
1106 | m_aoSoftness = aoSoftness; |
1107 | emit aoSoftnessChanged(); |
1108 | update(); |
1109 | } |
1110 | |
1111 | void QQuick3DSceneEnvironment::setAoDither(bool aoDither) |
1112 | { |
1113 | if (m_aoDither == aoDither) |
1114 | return; |
1115 | |
1116 | m_aoDither = aoDither; |
1117 | emit aoDitherChanged(); |
1118 | update(); |
1119 | } |
1120 | |
1121 | void QQuick3DSceneEnvironment::setAoSampleRate(int aoSampleRate) |
1122 | { |
1123 | if (m_aoSampleRate == aoSampleRate) |
1124 | return; |
1125 | |
1126 | m_aoSampleRate = aoSampleRate; |
1127 | emit aoSampleRateChanged(); |
1128 | update(); |
1129 | } |
1130 | |
1131 | void QQuick3DSceneEnvironment::setAoBias(float aoBias) |
1132 | { |
1133 | if (qFuzzyCompare(p1: m_aoBias, p2: aoBias)) |
1134 | return; |
1135 | |
1136 | m_aoBias = aoBias; |
1137 | emit aoBiasChanged(); |
1138 | update(); |
1139 | } |
1140 | |
1141 | void QQuick3DSceneEnvironment::setLightProbe(QQuick3DTexture *lightProbe) |
1142 | { |
1143 | if (m_lightProbe == lightProbe) |
1144 | return; |
1145 | |
1146 | QQuick3DObjectPrivate::attachWatcher(context: this, setter: &QQuick3DSceneEnvironment::setLightProbe, newO: lightProbe, oldO: m_lightProbe); |
1147 | |
1148 | m_lightProbe = lightProbe; |
1149 | emit lightProbeChanged(); |
1150 | update(); |
1151 | } |
1152 | |
1153 | void QQuick3DSceneEnvironment::setProbeExposure(float probeExposure) |
1154 | { |
1155 | if (qFuzzyCompare(p1: m_probeExposure, p2: probeExposure)) |
1156 | return; |
1157 | |
1158 | m_probeExposure = probeExposure; |
1159 | emit probeExposureChanged(); |
1160 | update(); |
1161 | } |
1162 | |
1163 | void QQuick3DSceneEnvironment::setProbeHorizon(float probeHorizon) |
1164 | { |
1165 | // clamp value to expected range |
1166 | probeHorizon = qBound(min: 0.0f, val: probeHorizon, max: 1.0f); |
1167 | |
1168 | if (qFuzzyCompare(p1: m_probeHorizon, p2: probeHorizon)) |
1169 | return; |
1170 | |
1171 | m_probeHorizon = probeHorizon; |
1172 | emit probeHorizonChanged(); |
1173 | update(); |
1174 | } |
1175 | |
1176 | void QQuick3DSceneEnvironment::setProbeOrientation(const QVector3D &orientation) |
1177 | { |
1178 | if (qFuzzyCompare(v1: m_probeOrientation, v2: orientation)) |
1179 | return; |
1180 | |
1181 | m_probeOrientation = orientation; |
1182 | emit probeOrientationChanged(); |
1183 | update(); |
1184 | } |
1185 | |
1186 | void QQuick3DSceneEnvironment::setDepthTestEnabled(bool depthTestEnabled) |
1187 | { |
1188 | if (m_depthTestEnabled == depthTestEnabled) |
1189 | return; |
1190 | |
1191 | m_depthTestEnabled = depthTestEnabled; |
1192 | emit depthTestEnabledChanged(); |
1193 | update(); |
1194 | } |
1195 | |
1196 | void QQuick3DSceneEnvironment::setDepthPrePassEnabled(bool depthPrePassEnabled) |
1197 | { |
1198 | if (m_depthPrePassEnabled == depthPrePassEnabled) |
1199 | return; |
1200 | |
1201 | m_depthPrePassEnabled = depthPrePassEnabled; |
1202 | emit depthPrePassEnabledChanged(); |
1203 | update(); |
1204 | } |
1205 | |
1206 | void QQuick3DSceneEnvironment::setTonemapMode(QQuick3DSceneEnvironment::QQuick3DEnvironmentTonemapModes tonemapMode) |
1207 | { |
1208 | if (m_tonemapMode == tonemapMode) |
1209 | return; |
1210 | |
1211 | m_tonemapMode = tonemapMode; |
1212 | emit tonemapModeChanged(); |
1213 | update(); |
1214 | } |
1215 | |
1216 | bool QQuick3DSceneEnvironment::useBuiltinTonemapper() const |
1217 | { |
1218 | return true; |
1219 | } |
1220 | |
1221 | QSSGRenderGraphObject *QQuick3DSceneEnvironment::updateSpatialNode(QSSGRenderGraphObject *node) |
1222 | { |
1223 | // Don't do anything, these properties get set by the scene renderer |
1224 | return node; |
1225 | } |
1226 | |
1227 | void QQuick3DSceneEnvironment::itemChange(QQuick3DObject::ItemChange change, const QQuick3DObject::ItemChangeData &value) |
1228 | { |
1229 | if (change == QQuick3DObject::ItemSceneChange) |
1230 | updateSceneManager(manager: value.sceneManager); |
1231 | } |
1232 | |
1233 | const QVector<QQuick3DEffect *> &QQuick3DSceneEnvironment::effectList() const |
1234 | { |
1235 | return m_effects; |
1236 | } |
1237 | |
1238 | void QQuick3DSceneEnvironment::updateSceneManager(QQuick3DSceneManager *manager) |
1239 | { |
1240 | if (manager) { |
1241 | QQuick3DObjectPrivate::refSceneManager(obj: m_lightProbe, mgr&: *manager); |
1242 | QQuick3DObjectPrivate::refSceneManager(obj: m_skyBoxCubeMap, mgr&: *manager); |
1243 | } else { |
1244 | QQuick3DObjectPrivate::derefSceneManager(obj: m_lightProbe); |
1245 | QQuick3DObjectPrivate::derefSceneManager(obj: m_skyBoxCubeMap); |
1246 | } |
1247 | } |
1248 | |
1249 | void QQuick3DSceneEnvironment::setTemporalAAEnabled(bool temporalAAEnabled) |
1250 | { |
1251 | if (m_temporalAAEnabled == temporalAAEnabled) |
1252 | return; |
1253 | |
1254 | m_temporalAAEnabled = temporalAAEnabled; |
1255 | emit temporalAAEnabledChanged(); |
1256 | update(); |
1257 | } |
1258 | |
1259 | void QQuick3DSceneEnvironment::setTemporalAAStrength(float strength) |
1260 | { |
1261 | if (qFuzzyCompare(p1: m_temporalAAStrength, p2: strength)) |
1262 | return; |
1263 | |
1264 | m_temporalAAStrength = strength; |
1265 | emit temporalAAStrengthChanged(); |
1266 | update(); |
1267 | } |
1268 | |
1269 | void QQuick3DSceneEnvironment::setSpecularAAEnabled(bool enabled) |
1270 | { |
1271 | if (m_specularAAEnabled == enabled) |
1272 | return; |
1273 | |
1274 | m_specularAAEnabled = enabled; |
1275 | emit specularAAEnabledChanged(); |
1276 | update(); |
1277 | } |
1278 | |
1279 | void QQuick3DSceneEnvironment::qmlAppendEffect(QQmlListProperty<QQuick3DEffect> *list, QQuick3DEffect *effect) |
1280 | { |
1281 | if (effect == nullptr) |
1282 | return; |
1283 | QQuick3DSceneEnvironment *self = static_cast<QQuick3DSceneEnvironment *>(list->object); |
1284 | self->m_effects.push_back(t: effect); |
1285 | |
1286 | if (effect->parentItem() == nullptr) |
1287 | effect->setParentItem(self); |
1288 | |
1289 | for (QQuick3DEffect *e : self->m_effects) |
1290 | e->effectChainDirty(); |
1291 | |
1292 | self->update(); |
1293 | } |
1294 | |
1295 | QQuick3DEffect *QQuick3DSceneEnvironment::qmlEffectAt(QQmlListProperty<QQuick3DEffect> *list, qsizetype index) |
1296 | { |
1297 | QQuick3DSceneEnvironment *self = static_cast<QQuick3DSceneEnvironment *>(list->object); |
1298 | return self->m_effects.at(i: index); |
1299 | } |
1300 | |
1301 | qsizetype QQuick3DSceneEnvironment::qmlEffectsCount(QQmlListProperty<QQuick3DEffect> *list) |
1302 | { |
1303 | QQuick3DSceneEnvironment *self = static_cast<QQuick3DSceneEnvironment *>(list->object); |
1304 | return self->m_effects.size(); |
1305 | } |
1306 | |
1307 | void QQuick3DSceneEnvironment::qmlClearEffects(QQmlListProperty<QQuick3DEffect> *list) |
1308 | { |
1309 | QQuick3DSceneEnvironment *self = static_cast<QQuick3DSceneEnvironment *>(list->object); |
1310 | self->m_effects.clear(); |
1311 | self->update(); |
1312 | } |
1313 | |
1314 | void QQuick3DSceneEnvironment::setSkyboxBlurAmount(float newSkyboxBlurAmount) |
1315 | { |
1316 | newSkyboxBlurAmount = qBound(min: 0.0f, val: newSkyboxBlurAmount, max: 1.0f); |
1317 | |
1318 | if (qFuzzyCompare(p1: m_skyboxBlurAmount, p2: newSkyboxBlurAmount)) |
1319 | return; |
1320 | |
1321 | m_skyboxBlurAmount = newSkyboxBlurAmount; |
1322 | emit skyboxBlurAmountChanged(); |
1323 | update(); |
1324 | } |
1325 | |
1326 | /*! |
1327 | \qmlproperty Lightmapper QtQuick3D::SceneEnvironment::lightmapper |
1328 | |
1329 | When this property is set to a valid Lightmapper object, the settings |
1330 | specified by the object will be taken into account when baking lightmaps. |
1331 | |
1332 | The default value is null, which means using default values for all the |
1333 | baking-related settings. |
1334 | |
1335 | For more information on how to bake lightmaps, see the \l Lightmapper |
1336 | documentation. |
1337 | |
1338 | When lightmaps are not relevant to an application and baked lighting is |
1339 | never generated, the property and the associated object serve no purpose in |
1340 | practice. |
1341 | |
1342 | \sa Model::usedInBakedLighting, Model::bakedLightmap, Light::bakeMode, Lightmapper |
1343 | */ |
1344 | |
1345 | QQuick3DLightmapper *QQuick3DSceneEnvironment::lightmapper() const |
1346 | { |
1347 | return m_lightmapper; |
1348 | } |
1349 | |
1350 | void QQuick3DSceneEnvironment::setLightmapper(QQuick3DLightmapper *lightmapper) |
1351 | { |
1352 | if (m_lightmapper == lightmapper) |
1353 | return; |
1354 | |
1355 | if (m_lightmapper) |
1356 | m_lightmapper->disconnect(m_lightmapperSignalConnection); |
1357 | |
1358 | m_lightmapper = lightmapper; |
1359 | |
1360 | m_lightmapperSignalConnection = QObject::connect(sender: m_lightmapper, signal: &QQuick3DLightmapper::changed, context: this, |
1361 | slot: [this] { update(); }); |
1362 | |
1363 | QObject::connect(sender: m_lightmapper, signal: &QObject::destroyed, context: this, |
1364 | slot: [this](QObject *obj) |
1365 | { |
1366 | if (m_lightmapper == obj) { |
1367 | m_lightmapper = nullptr; |
1368 | update(); |
1369 | } |
1370 | }); |
1371 | |
1372 | emit lightmapperChanged(); |
1373 | update(); |
1374 | } |
1375 | |
1376 | /*! |
1377 | \qmlproperty QtQuick3D::CubeMapTexture QtQuick3D::SceneEnvironment::skyBoxCubeMap |
1378 | |
1379 | This property defines a cubemap to be used as a skybox when the background mode is \c SkyBoxCubeMap. |
1380 | |
1381 | \since 6.4 |
1382 | */ |
1383 | QQuick3DCubeMapTexture *QQuick3DSceneEnvironment::skyBoxCubeMap() const |
1384 | { |
1385 | return m_skyBoxCubeMap; |
1386 | } |
1387 | |
1388 | void QQuick3DSceneEnvironment::setSkyBoxCubeMap(QQuick3DCubeMapTexture *newSkyBoxCubeMap) |
1389 | { |
1390 | if (m_skyBoxCubeMap == newSkyBoxCubeMap) |
1391 | return; |
1392 | |
1393 | QQuick3DObjectPrivate::attachWatcher(context: this, setter: &QQuick3DSceneEnvironment::setSkyBoxCubeMap, newO: newSkyBoxCubeMap, oldO: m_skyBoxCubeMap); |
1394 | |
1395 | m_skyBoxCubeMap = newSkyBoxCubeMap; |
1396 | emit skyBoxCubeMapChanged(); |
1397 | } |
1398 | |
1399 | void QQuick3DSceneEnvironment::setDebugSettings(QQuick3DDebugSettings *newDebugSettings) |
1400 | { |
1401 | if (m_debugSettings == newDebugSettings) |
1402 | return; |
1403 | |
1404 | if (m_debugSettings) |
1405 | m_debugSettings->disconnect(m_debugSettingsSignalConnection); |
1406 | |
1407 | m_debugSettings = newDebugSettings; |
1408 | |
1409 | m_debugSettingsSignalConnection = QObject::connect(sender: m_debugSettings, signal: &QQuick3DDebugSettings::changed, context: this, |
1410 | slot: [this] { update(); }); |
1411 | QObject::connect(sender: m_debugSettings, signal: &QObject::destroyed, context: this, |
1412 | slot: [this](QObject *obj) { |
1413 | if (m_debugSettings == obj) { |
1414 | m_debugSettings = nullptr; |
1415 | update(); |
1416 | } |
1417 | }); |
1418 | |
1419 | emit debugSettingsChanged(); |
1420 | update(); |
1421 | } |
1422 | |
1423 | void QQuick3DSceneEnvironment::setScissorRect(QRect rect) |
1424 | { |
1425 | if (m_scissorRect == rect) |
1426 | return; |
1427 | |
1428 | m_scissorRect = rect; |
1429 | emit scissorRectChanged(); |
1430 | update(); |
1431 | } |
1432 | |
1433 | bool QQuick3DSceneEnvironment::gridEnabled() const |
1434 | { |
1435 | return m_gridEnabled; |
1436 | } |
1437 | |
1438 | void QQuick3DSceneEnvironment::setGridEnabled(bool newGridEnabled) |
1439 | { |
1440 | if (m_gridEnabled == newGridEnabled) |
1441 | return; |
1442 | m_gridEnabled = newGridEnabled; |
1443 | update(); |
1444 | } |
1445 | |
1446 | float QQuick3DSceneEnvironment::gridScale() const |
1447 | { |
1448 | return m_gridScale; |
1449 | } |
1450 | |
1451 | void QQuick3DSceneEnvironment::setGridScale(float newGridScale) |
1452 | { |
1453 | if (qFuzzyCompare(p1: m_gridScale, p2: newGridScale)) |
1454 | return; |
1455 | m_gridScale = newGridScale; |
1456 | update(); |
1457 | } |
1458 | |
1459 | uint QQuick3DSceneEnvironment::gridFlags() const |
1460 | { |
1461 | return m_gridFlags; |
1462 | } |
1463 | |
1464 | void QQuick3DSceneEnvironment::setGridFlags(uint newGridFlags) |
1465 | { |
1466 | if (m_gridFlags == newGridFlags) |
1467 | return; |
1468 | m_gridFlags = newGridFlags; |
1469 | update(); |
1470 | } |
1471 | |
1472 | /*! |
1473 | \qmlproperty bool SceneEnvironment::aoEnabled |
1474 | \since 6.5 |
1475 | |
1476 | Enable or disable ambient occlusion. |
1477 | |
1478 | The default value is \c false, which means ambient occlusion is disabled. |
1479 | |
1480 | \note If \l aoStrength or \ aoDistance is 0, then setting this property to |
1481 | \c true will also set those values appropriately to make the ambient |
1482 | occlusion effective. |
1483 | |
1484 | \note Getting visually good-looking screen space ambient occlusion is |
1485 | dependent on carefully tuning a number of related parameters, such as \l |
1486 | aoStrength, \l aoSoftness, \l aoDistance, \l aoDither, \l aoBias, and \l |
1487 | aoSampleRate. |
1488 | |
1489 | \sa aoStrength, aoDistance |
1490 | */ |
1491 | |
1492 | bool QQuick3DSceneEnvironment::aoEnabled() const |
1493 | { |
1494 | return m_aoEnabled; |
1495 | } |
1496 | |
1497 | void QQuick3DSceneEnvironment::setAoEnabled(bool newAoEnabled) |
1498 | { |
1499 | if (m_aoEnabled == newAoEnabled) |
1500 | return; |
1501 | |
1502 | m_aoEnabled = newAoEnabled; |
1503 | |
1504 | if (m_aoEnabled) { |
1505 | if (qFuzzyIsNull(f: m_aoStrength)) |
1506 | setAoStrength(100.0f); |
1507 | if (qFuzzyIsNull(f: m_aoDistance)) |
1508 | setAoDistance(defaultAoDistance()); |
1509 | } |
1510 | |
1511 | emit aoEnabledChanged(); |
1512 | update(); |
1513 | } |
1514 | |
1515 | /*! |
1516 | \qmlproperty QtQuick3D::Fog QtQuick3D::SceneEnvironment::fog |
1517 | \since 6.5 |
1518 | |
1519 | When this property is set to a valid \l {QtQuick3D::Fog}{Fog} object, it is |
1520 | used to configure the renderer's built-in fog support. |
1521 | |
1522 | The default value is null, which means no fog. This is equivalent to |
1523 | setting a Fog object with \l{Fog::enabled}{enabled} set to false. |
1524 | |
1525 | \image fog.jpg |
1526 | |
1527 | \sa {QtQuick3D::Fog}{Fog} |
1528 | */ |
1529 | |
1530 | QQuick3DFog *QQuick3DSceneEnvironment::fog() const |
1531 | { |
1532 | return m_fog; |
1533 | } |
1534 | |
1535 | void QQuick3DSceneEnvironment::setFog(QQuick3DFog *fog) |
1536 | { |
1537 | if (m_fog == fog) |
1538 | return; |
1539 | |
1540 | if (m_fog) |
1541 | m_fog->disconnect(m_fogSignalConnection); |
1542 | |
1543 | m_fog = fog; |
1544 | |
1545 | m_fogSignalConnection = QObject::connect(sender: m_fog, signal: &QQuick3DFog::changed, context: this, slot: [this] { update(); }); |
1546 | |
1547 | QObject::connect(sender: m_fog, signal: &QObject::destroyed, context: this, |
1548 | slot: [this](QObject *obj) |
1549 | { |
1550 | if (m_fog == obj) { |
1551 | m_fog = nullptr; |
1552 | update(); |
1553 | } |
1554 | }); |
1555 | |
1556 | emit fogChanged(); |
1557 | update(); |
1558 | } |
1559 | |
1560 | QT_END_NAMESPACE |
1561 | |