Using Lightmap global illumination

Baked lightmaps are a workflow for adding indirect (or fully baked) lighting to a scene. Unlike the VoxelGI and SDFGI approaches, baked lightmaps work fine on low-end PCs and mobile devices, as they consume almost no resources at run-time. Also unlike VoxelGI and SDFGI, baked lightmaps can optionally be used to store direct lighting, which provides even further performance gains.

Unlike VoxelGI and SDFGI, baked lightmaps are completely static. Once baked, they can't be modified at all. They also don't provide the scene with reflections, so using Reflection probes together with it on interiors (or using a Sky on exteriors) is a requirement to get good quality.

As they are baked, they have fewer problems than VoxelGI and SDFGI regarding light bleeding, and indirect light will often look better. The downside is that baking lightmaps takes longer compared to baking VoxelGI. While baking VoxelGI can be done in a matter of seconds, baking lightmaps can take several minutes if not more. This can slow down iteration speed significantly, so it is recommended to bake lightmaps only when you actually need to see changes in lighting. Since Godot 4.0, lightmaps are baked on the GPU, making light baking faster if you have a mid-range or high-end dedicated GPU.

Baking lightmaps will also reserve baked materials' UV2 slot, which means you can no longer use it for other purposes in materials (either in the built-in Standard Material 3D and ORM Material 3D or in custom shaders).

Despite their lack of flexibility, baked lightmaps typically offer both the best quality and performance at the same time in (mostly) static scenes. This makes lightmaps still popular in game development, despite lightmaps being the oldest technique for global illumination in video games.

See also

Not sure if LightmapGI is suited to your needs? See Which global illumination technique should I use? for a comparison of GI techniques available in Godot 4.

Visual comparison

LightmapGI disabled.

LightmapGI disabled.

LightmapGI enabled (with indirect light baked only).

LightmapGI enabled (with indirect light baked only). Direct light is still real-time, allowing for subtle changes during gameplay.

LightmapGI enabled (with direct and indirect light baked).

LightmapGI enabled (with direct and indirect light baked). Best performance, but lower quality visuals. Notice the blurrier sun shadow in the top-right corner.

Visual comparison

Here are some comparisons of how LightmapGI vs. VoxelGI look. Notice that lightmaps are more accurate, but also suffer from the fact that lighting is on an unwrapped texture, so transitions and resolution may not be that good. VoxelGI looks less accurate (as it's an approximation), but smoother overall.

../../../_images/lightmap_gi_comparison.png

SDFGI is also less accurate compared to LightmapGI. However, SDFGI can support large open worlds without any need for baking.

Setting up

First of all, before the lightmapper can do anything, the objects to be baked need an UV2 layer and a texture size. An UV2 layer is a set of secondary texture coordinates that ensures any face in the object has its own place in the UV map. Faces must not share pixels in the texture.

There are a few ways to ensure your object has a unique UV2 layer and texture size:

Unwrap from within Godot

Warning

If this Mesh menu operation is used on an imported 3D scene, the generated UV2 will be lost when the scene is reloaded.

Godot has an option to unwrap meshes and visualize the UV channels. After selecting a MeshInstance3D node, it can be found in the Mesh menu at the top of the 3D editor viewport:

../../../_images/lightmap_gi_mesh_menu.png

This will generate a second set of UV2 coordinates which can be used for baking. It will also set the texture size automatically.

Unwrap from your 3D modeling software

The last option is to do it from your favorite 3D app. This approach is generally not recommended, but it's explained so that you know it exists. The main advantage is that, on complex objects that you may want to re-import a lot, the texture generation process can be quite costly within Godot, so having it unwrapped before import can be faster.

Simply do an unwrap on the second UV2 layer.

../../../_images/lightmap_gi_blender.png

Then import the 3D scene normally. Remember you will need to set the texture size on the mesh after import.

../../../_images/lightmap_gi_lmsize.png

If you use external meshes on import, the size will be kept. Be wary that most unwrappers in 3D modeling software are not quality-oriented, as they are meant to work quickly. You will mostly need to use seams or other techniques to create better unwrapping.

Generating UV2 for primitive meshes

Note

This option is only available for primitive meshes such as BoxMesh, CylinderMesh, PlaneMesh, etc.

Enabling UV2 on primitive meshes allows you to make them receive and contribute to baked lighting. This can be used in certain lighting setups. For instance, you could hide a torus that has an emissive material after baking lightmaps to create an area light that follows the shape of a torus.

By default, primitive meshes do not have UV2 generated to save resources (as these meshes may be created during gameplay). You can edit a primitive mesh in the inspector and enable Add UV2 to make the engine procedurally generate UV2 for a primitive mesh. The default UV2 Padding value is tuned to avoid most lightmap bleeding, without wasting too much space on the edges. If you notice lightmap bleeding on a specific primitive mesh only, you may have to increase UV2 Padding.

Lightmap Size Hint represents the size taken by a single mesh on the lightmap texture, which varies depending on the mesh's size properties and the UV2 Padding value. Lightmap Size Hint should not be manually changed, as any modifications will be lost when the scene is reloaded.

Checking UV2

In the Mesh menu mentioned before, the UV2 texture coordinates can be visualized. If something is failing, double-check that the meshes have these UV2 coordinates:

../../../_images/lightmap_gi_uvchannel.png

Setting up the scene

Before anything is done, a LightmapGI node needs to be added to a scene. This will enable light baking on all nodes (and sub-nodes) in that scene, even on instanced scenes.

../../../_images/lightmap_gi_scene.png

A sub-scene can be instanced several times, as this is supported by the baker. Each instance will be assigned a lightmap of its own. To avoid issues with inconsistent lightmap texel scaling, make sure to respect the rule about mesh scaling mentioned before.

Setting up meshes

For a MeshInstance3D node to take part in the baking process, it needs to have its bake mode set to Static. Meshes that have their bake mode set to Disabled or Dynamic will be ignored by the lightmapper.

../../../_images/lightmap_gi_use.png

When auto-generating lightmaps on scene import, this is enabled automatically.

Setting up lights

Lights are baked with indirect light only by default. This means that shadowmapping and lighting are still dynamic and affect moving objects, but light bounces from that light will be baked.

Lights can be disabled (no bake) or be fully baked (direct and indirect). This can be controlled from the Bake Mode menu in lights:

../../../_images/lightmap_gi_bake_mode.png

The modes are:

Disabled

The light is ignored when baking lightmaps. Keep in mind hiding a light will have no effect for baking, so this must be used instead of hiding the Light node.

This is the mode to use for dynamic lighting effects such as explosions and weapon effects.

Dynamic

This is the default mode, and is a compromise between performance and real-time friendliness. Only indirect lighting will be baked. Direct light and shadows are still real-time, as they would be without LightmapGI.