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