Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qtquick3d-lightmap.qdoc
Go to the documentation of this file.
1
// Copyright (C) 2022 The Qt Company Ltd.
2
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
3
4
/*!
5
6
\title Lightmaps and Global Illumination
7
\page quick3d-lightmap
8
9
\section1 Introduction
10
11
Global illumination (GI) is the indirect light that reaches a surface after
12
bouncing off other surfaces in a scene. Simulating GI produces effects such
13
as color bleeding between nearby surfaces and softer ambient shading.
14
15
\section1 Approaches to Global Illumination
16
17
Qt Quick 3D offers two approaches to global illumination (GI):
18
19
\list
20
\li \b{Screen-Space Global Illumination (SSGI):} A dynamic
21
indirect lighting method that uses screen-space buffers to approximate global
22
illumination. You can enable SSGI through
23
the \l{QtQuick3D.Helpers::ExtendedSceneEnvironment} type by setting the
24
\l{QtQuick3D.Helpers::ExtendedSceneEnvironment::}{ssgiEnabled} property to
25
\c true. SSGI is suitable for animated content where lights and geometry
26
change at runtime, though screen-space approximations reduce accuracy.
27
28
\li \b{Baked lightmaps:} A lighting method that uses raytraced lighting
29
baked into textures and sampled at runtime. Baked lightmaps provide
30
global illumination at lower runtime cost, which benefits static
31
models, materials, and lights.
32
\endlist
33
34
For a side-by-side visual and behavioral comparison of the two
35
techniques, see \l{Qt Quick 3D - SSGI Lightmap Example}.
36
37
\section1 Baked Lightmaps
38
39
Baked lightmaps allow pre-generating the \b{direct lighting} from lights such
40
as \l DirectionalLight, \l PointLight, and \l SpotLight, including the shadows
41
cast by the lights. At run time, instead of performing the appropriate
42
calculations in the fragment shader, and, in case of shadows, generating the
43
potentially costly shadow maps in real time, the pre-generated image map is
44
sampled instead.
45
46
A lightmap is generated per \l{Model}. Even if a \l{Model} has multiple submeshes, and
47
is therefore associated with multiple materials, there will be one single
48
lightmap image generated for the entire model.
49
50
Lightmaps are generated using raytracing, which by nature provides proper
51
occlusion ("light does not travel through walls"), and possibly more realistic
52
shadows than the real-time techniques for lighting and shadow mapping.
53
54
More importantly, lightmaps also allow baking \b{indirect lighting}, providing
55
a solution for global illumination. This takes light rays reflected from other
56
surfaces in the scene into account.
57
58
Below is a simple example. The scene contains four Rectangle and a Sphere
59
model, with a \l{DirectionalLight} pointing downwards and a PointLight. The rectangle
60
models are rotated 0 and 90 degrees, which exaggerates the limitations of the
61
real-time lighting calculations because they are all either parallel or
62
perpendicular to the \l{DirectionalLight}'s direction.
63
64
On the second image, the scene is rendered with lightmapping enabled, after having
65
lightmaps baked for all five models. Both lights are set to fully baked,
66
meaning both direct and indirect illumination is baked. Indirect lighting uses
67
256 \l{Lightmapper::}{samples} and a maximum of 3 \l{Lightmapper::}{bounces}.
68
The resulting lightmaps were then denoised. This gives a significantly more
69
realistic image.
70
71
\b{Real-time lighting}
72
73
\image lightmap_simple_none.jpg "Simple scene with sphere, rectangles, and two lights"
74
75
\b{Fully baked lighting}
76
77
\image lightmap_simple_all.jpg "The same scene with both lights set to fully baked"
78
79
Below is a snippet that shows how the lightmapped results were achieved. The
80
difference lies in the \l{Model::usedInBakedLighting}{usedInBakedLighting},
81
\l{Light::bakeMode}{bakeMode}, and \l{Model::bakedLightmap}{bakedLightmap}
82
properties. For this example, the lightmap size has been reduced using the
83
\l{Lightmapper::texelsPerUnit}{texelsPerUnit} property, to save
84
disk space and reduce application load times.
85
86
\qml
87
DirectionalLight {
88
bakeMode: Light.BakeModeAll
89
90
eulerRotation.x: -90
91
brightness: 0.5
92
castsShadow: true
93
shadowFactor: 75
94
}
95
PointLight {
96
bakeMode: Light.BakeModeAll
97
98
y: 200
99
z: 100
100
color: "#d9c62b"
101
castsShadow: true
102
shadowFactor: 75
103
}
104
Model {
105
usedInBakedLighting: true
106
bakedLightmap: BakedLightmap {
107
enabled: true
108
key: "sphere1"
109
}
110
111
source: "#Sphere"
112
materials: PrincipledMaterial { }
113
y: 100
114
}
115
Model {
116
usedInBakedLighting: true
117
bakedLightmap: BakedLightmap {
118
enabled: true
119
key: "rect1"
120
}
121
122
source: "#Rectangle"
123
materials: PrincipledMaterial { }
124
eulerRotation.x: -90
125
scale: Qt.vector3d(10, 10, 10)
126
}
127
128
// ... three additional Rectangle models, with rotations 0, 90, and -90
129
130
\endqml
131
132
The above example used fully baked lights. A light can also be configured to
133
only use baked lighting for indirect illumination, while performing direct
134
lighting and shadow mapping in real time. In the below scene there are 5 point
135
lights, all of which are set to \l{Light::bakeMode}{BakeModeIndirect} for the
136
second screenshot. While the direct lighting and shadows look identical, the
137
second image looks significantly better due to a degree of global illumination
138
added.
139
140
\b{Real-time lighting}
141
142
\image lightmap_sponza_none.jpg "Scene with Sponza and Suzanne models and 5 point lights"
143
144
\b{With baked indirect lighting added}
145
146
\image lightmap_sponza_indirect.jpg "Same scene with baked indirect but real-time direct lighting"
147
148
\section2 Important considerations when working with lightmaps
149
150
Lights contributing to baked lighting have their \l{Light::bakeMode}{bakeMode}
151
property set to either \l{Light::bakeMode}{Light.BakeModeIndirect} or \l{Light::bakeMode}{Light.BakeModeAll}. The latter indicates
152
that both the direct and indirect contribution for that particular light is
153
coming from the lightmap. The direct contribution always includes shadows as
154
well. On the other hand, if the intention with the lightmap is only to add
155
indirect illumination to the scene for a particular light, while still having
156
direct lighting calculated (and perform shadow mapping) in real time, then the
157
light should use \l{Light::bakeMode}{Light.BakeModeIndirect} instead.
158
159
\note Lightmaps are, generally speaking, suitable for models that are static
160
when it comes to transform, geometry, and materials. The same applies to the
161
lights participating in the baked lighting.
162
163
For example, a scene that rotates a \l{Model} by animating the
164
\l{Node::eulerRotation}{eulerRotation} property will give visually incorrect
165
results when applying a lightmap to that \l{Model}. The rendering results for that
166
particular \l{Model} will be incorrect, as the pre-generated lightmap only captures
167
one single rotation state for the object. The same would be true, taking
168
another example, if the material for one of the model's submeshes dynamically
169
changes its \l{PrincipledMaterial::baseColor}{baseColor} property based on time
170
(animation) or some user interaction. The lightmap can only capture one given
171
material \l{PrincipledMaterial::baseColor}{baseColor}. The same is true for
172
lights. For example, a \l DirectionalLight that rotates, changes its
173
brightness, color, etc. over time is not suitable for baked lighting.
174
175
\note On the other hand, it is always a designer choice when to use
176
lightmapping. Especially with \l{Light::bakeMode}{BakeModeIndirect} lights, it
177
is likely that there will be scenes where the results are still visually
178
satisfying, even though some of the objects in the lightmapped scene employ
179
dynamic behavior.
180
181
Lightmapping is a complex engine and tooling feature. It replaces and
182
reimplements several pieces of the engine's rendering pipeline. It works with a
183
fundamentally different rendering model when baking lightmaps, while still
184
consuming and interoperating with the same scene structure, asset data, and
185
engine data structures. The raytracing-based results will often outclass the
186
real-time alternatives, sometimes significantly, which comes at the expense of
187
limitations, such as the mandatory static-ness of the models and lights
188
involved, and, sometimes, quality and rendering artifact issues that are
189
specific to lightmapping.
190
191
In practice it will be an artistic choice by the designers what type of
192
lighting to use, and when. All three \l{Light::bakeMode}{bakeMode} settings
193
have their uses, and complex, larger scenes may very well utilize all three for
194
different lights, depending on what is deemed suitable for a given section of
195
the scene, and what sort of models, materials, and dynamic behavior are
196
present. Lightmapping is not a simple on/off type of toggle switch that can be
197
enabled for any scene and application, but a powerful feature that assumes
198
careful evaluation of the lighting needs of a given scene, and often requires
199
the scene contents and behavior to be designed accordingly, combined with a
200
test-and-tune loop where different lightmap baking and quality settings are
201
explored and tested before deciding on the final approach and the related
202
settings.
203
204
\note Lightmaps do not support two-sided surfaces. With real time lighting a
205
material with a \l{Material::cullMode}{cull mode} of \c
206
Material.NoCulling automatically inverts the normal as appropriate based on the
207
facing of the fragment. This is not an option for lightmaps since lightmap
208
baking does not operate in view space. Therefore, avoid baked lighting for
209
models that would rely on this.
210
211
\section1 Baking Lightmaps
212
213
Properties and types relevant for baking lightmaps, meaning the offline process
214
of generating the image maps that capture direct and indirect lighting and can
215
be used by the renderer in subsequent runs of the application:
216
217
\list
218
\li \l Model::usedInBakedLighting
219
\li \l Model::lightmapBaseResolution,
220
\li \l Light::bakeMode,
221
\li \l Lightmapper and \l SceneEnvironment::lightmapper
222
\li \l BakedLightmap and \l Model::bakedLightmap
223
\endlist
224
225
As of Qt 6.4, the lightmap baking process has to be triggered manually.
226
Whenever the command line argument \c{--bake-lightmaps} is present, or the
227
environment variable \c{QT_QUICK3D_BAKE_LIGHTMAPS} is set to \c 1 (or another
228
non-zero value), the engine will work in baking mode and exit the application
229
once baking has completed. The steps of the baking process can be followed by
230
checking the messages printed on the debug output. The result is a binary file
231
(\c{lightmaps.bin} by default) written to the current working directory
232
containing all the baked lightmaps in the scene. There will also be a \c{.raw}
233
file created that contains the whole lightmap and some extra data that is needed
234
for denoising. Each lightmap is uniquely identified in the file by the unique
235
key from \l{BakedLightmap::key}.
236
237
Preparing a lightmapped scene takes the following main steps:
238
239
\list
240
241
\li Identify which models should use a lightmap, and which models should
242
contribute to the lightmap. Models that are part of the lightmapped scene
243
should set \l Model::usedInBakedLighting to true. Models that are lightmapped
244
(i.e., a lightmap is to be baked for them) should in addition set \l
245
Model::bakedLightmap to an enabled \l BakedLightmap object, that provides a
246
unique key that will persistently identify the particular Model object
247
instance (this is because Qt needs a key to identify the model data in
248
persistent disk storage). Only models with static geometry, transformation, and
249
materials are guaranteed to have correct results when lightmapped at run-time.
250
Most commonly, anything that leads to a non-static world transform over time,
251
such as a dynamically changed or animated position, rotation, or scale, will
252
disqualify the model from participating. Artistic needs can override this,
253
however, especially for models that only contribute to baked indirect lighting
254
but are not themselves lightmapped. For these it may often be visually
255
acceptable to have dynamic transforms, but this always depends on the model and
256
the scene in question.
257
258
\li Identify which lights should contribute, and to which degree. \l
259
Light::bakeMode offers three options:
260
261
\list
262
263
\li Light.BakeModeDisabled, the default, which effectively makes the light
264
ignored for all lightmapping purposes.
265
266
\li Light.BakeModeIndirect is often the "safe" choice, if the only goal is
267
to have a level of global illumination (indirect lighting) in the scene,
268
while not affecting the rendering results for the light in other ways. In
269
this mode the renderer will continue to perform all lighting, including
270
diffuse, specular, sky/environment contributions, and shadow mapping for
271
this light using the standard real-time techniques. However, the light will
272
contribute to indirect lighting using the pre-baked data, possibly leading
273
to illuminating surfaces that are otherwise left untouched by the standard
274
real-time lighting calculations.
275
276
\li Light.BakeModeAll is an option which will likely be used for certain
277
lights only, based on the designers' evaluation for what is deemed
278
appropriate for a given scene. In this mode all contribution from the light
279
is baked, including shadows. As of Qt 6.4 specular lighting are not
280
supported as part of the baked lighting, so such lights will not have
281
specular contributions. They will, on the other hand generate raytraced,
282
baked shadows and have proper occlusion for the light (will not "pass
283
through walls", for instance) since here all the direct lighting
284
contributions resulting from the light are raytraced at lightmap baking
285
time, instead of being calculated at run time. In addition, indirect
286
lighting is baked, just as with BakeModeIndirect.
287
288
\endlist
289
290
\li Running the scene (application) in baking mode, ensuring lightmaps are
291
successfully generated. As of Qt 6.4, applications are expected to be
292
structured in a way that the lightmapped scene is the first view shown, or that
293
the scene in question can be loaded up with a QML viewer such as the \c qml
294
tool. Once baking completes, the progress of which can be followed on the
295
console/debug output, the application exits.
296
297
\li Running the scene (application) normally, to see how it looks with the
298
lightmaps loaded. The tuning can then begin:
299
300
\list
301
302
\li For some models it will make sense to reduce
303
\l{Model::texelsPerUnit}{texelsPerUnit} from the default value
304
to something smaller. This applies especially to the built-in
305
primitives and anything with simple enough geometry. This leads to smaller
306
lightmaps and faster bake times. When baking the first time, the default
307
should be sufficient, the value can be tuned afterwards.
308
309
\li The Lightmapper object exposes numerous settings that have reasonable
310
defaults, but it is not unlikely that some of these will need to be tuned
311
to match the designers' expectation. For example, \l {Lightmapper::}{samples}
312
and \l {Lightmapper::}{bounces} can be changed to affect the quality of
313
indirect lighting, while \l {Lightmapper::}{indirectLightFactor} allows
314
making the indirect contribution more prominent. If artifacts, in
315
particular around shadows, occur, \l {Lightmapper::}{bias} can be
316
fine-tuned.
317
318
\li Denoising the generate lightmaps is essential. Indirect lighting is
319
calculated using \l{https://en.wikipedia.org/wiki/Path_tracing}{path
320
tracing}, which produces noisy images depending on the number of the
321
\l {Lightmapper::}{samples} used. Increasing the sample count reduces noise,
322
but increases the time needed to generate the lightmap. Regardless of the
323
sample count, it will almost always make sense to run a denoiser on the
324
generated lightmaps, which are 32-bit RGBA floating point images stored
325
in a binary file.
326
327
\endlist
328
329
\endlist
330
331
As of Qt 6.5, a runtime solution is provided interactively through the DebugView.
332
Under Tools there is now a button that when pressed will trigger the baking process.
333
A window will pop up showing the current process. Canceling can be done by
334
either hitting the cancel button or closing this window. When complete, it will
335
write the lightmap binary to the current directory.
336
337
\section2 Denoising
338
339
Below is an example of a \l{https://en.wikipedia.org/wiki/Cornell_box}{Cornell
340
box} scene, rendered first using the lightmap baked with 256
341
\l {Lightmapper::}{samples} and a maximum of 3 \l {Lightmapper::}{bounces}. In
342
the second example, the generated image file has been denoised, and the results
343
look significantly better, with the noise mostly gone.
344
345
\b{Original}
346
347
\image lightmap_noise_original.jpg "Cornell box scene with one point light, fully baked lightmap"
348
349
\b{Denoised}
350
351
\image lightmap_noise_denoised.jpg "Cornell box scene with the lightmaps denoised"
352
353
Denoising is done automatically on every baked lightmap. It is possible to do
354
just denoising, if an existing baked \c{.raw} lightmap file exists in the working
355
directory, by clicking the \c{Denoise} button in the DebugView. It is also possible to
356
denoise by calling the application with the \c{--denoise-lightmaps} argument.
357
To tweak the strength of the denoising, the \l{Lightmapper::}{denoiseSigma} property
358
can be used.
359
360
\section2 Lightmap UVs
361
362
Lightmap UV coordinates do not use the same UV data as regular texturing. When
363
rendering with lightmaps, neither the UV0 nor UV1 data is used by the renderer
364
when sampling the lightmap. Instead, there is an additional, dedicated UV
365
channel in the mesh, containing UV charts laid out in a manner that is suitable
366
for the purposes of lightmapping. This involves avoiding overlaps and having
367
padding where appropriate. For regular UV data there are no such requirements,
368
and one may very well want to use the same U and V coordinates for more than
369
one vertex.
370
371
The process of generating a suitable UV set is called lightmap UV unwrapping. Qt
372
will perform this when baking lightmaps and store the resulting mesh in the lightmaps
373
file so that a compatible mesh is always loaded and used for the generated lightmap.
374
This means that, if a model will always use baked lighting, then the source mesh
375
file does not need to be shipped with the application.
376
377
\section2 Lightmap texture size
378
379
For each model, including all its submeshes, the lightmap baking process will
380
determine a suitable lightmap texture size during the lightmap UV generation
381
phase. This has an impact on quality, performance, and resource usage (both on
382
disk and in memory).
383
384
The default is often suitable and needs no adjustment, especially for models
385
with medium to high complexity.
386
387
For very simple models it may be desirable to manually reduce the size,
388
however, because a smaller lightmap size could still provide visually good
389
looking results, while reducing the asset (lightmap image) sizes saves both
390
disk space and memory. To do this, set the \l{Model::texelsPerUnit}{texelsPerUnit}
391
to a suitably small number. The actual lightmap width and height will then,
392
depending on the size and the geometry of the model, try to approximate the
393
texel density so that it matches \l{Model::texelsPerUnit}{texelsPerUnit}.
394
395
When changing the value, one should always rebake the lightmaps and visually
396
inspect the results in order to evaluate the effects of the changed lightmap
397
size.
398
399
\section1 Using Lightmaps at Run-Time
400
401
Properties and types relevant when using the pre-baked lightmaps at run time:
402
403
\list
404
\li \l Light::bakeMode,
405
\li \l BakedLightmap and \l Model::bakedLightmap
406
\endlist
407
408
Once the baking has successfully completed, running the application normally
409
(without the command-line argument or environment variable set) will now pick
410
up the generated lightmap images and render correctly, which is not possible
411
until the lightmaps have been baked first. If desired, the application can
412
place those in a different location, or ship them as part of the executable via
413
the Qt Resource System. This is enabled by the \l{Lightmapper::}{source}
414
property.
415
416
Taking the example code with the sphere and four rectangles from above, the
417
baking process generates a \c{lightmaps.bin} file containing all the baked
418
meshes and lightmaps. The application needs to ship this file, so that it can be
419
found by the engine, in the location specified by \l{Lightmapper::}{source}.
420
421
\sa {Qt Quick 3D - Baked Lightmap Example}
422
\sa {Qt Quick 3D - SSGI Lightmap Example}
423
424
*/
qtquick3d
src
quick3d
doc
src
qtquick3d-lightmap.qdoc
Generated on
for Qt by
1.16.1