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