Baking static light into textures is one of the most impactful optimizations a game developer can make — and Godot 4's LightmapGI system makes the process accessible without sacrificing quality. This guide walks through the complete workflow: scene setup, texel density tuning, baking parameters, and squeezing the best results from low-end and mobile targets.
Setting up your scene for LightmapGI
Before you bake a single photon, your scene geometry needs to be ready. LightmapGI requires every mesh that will receive baked light to have a dedicated UV2 channel — a non-overlapping unwrap that the baker writes shadow and GI data into.
![]()
In Blender, generate a lightmap UV before exporting to GLB:
```python
# Blender Python — auto-generate lightmap UVs for selected meshes
import bpy
for obj in bpy.context.selected_objects:
if obj.type == 'MESH':
bpy.context.view_layer.objects.active = obj
bpy.ops.object.mode_set(mode='EDIT')
bpy.ops.mesh.select_all(action='SELECT')
bpy.ops.uv.lightmap_pack(
PREF_CONTEXT='ALL_FACES',
PREF_PACK_IN_ONE=True,
PREF_NEW_UVLAYER=True,
PREF_MARGIN_DIV=0.1
)
bpy.ops.object.mode_set(mode='OBJECT')
```
Alternatively, enable Lightmap Unwrap on import inside Godot's import settings (Scene tab → Lightmap → `generate_lightmap_uvs: true`). This works for simple meshes but gives less control over seam placement and texel distribution on complex geometry.
Scene setup checklist before baking:
- All static geometry set to Static mode (top of the Inspector)
- `GeometryInstance3D.gi_mode` set to `STATIC` (not `DYNAMIC` or `DISABLED`)
- `MeshInstance3D` nodes have `UV2` present — check in the Mesh resource inspector
- Lights contributing to bake have `LightmapGIData` mode enabled (default for `DirectionalLight3D` and `OmniLight3D`)
- Sky contribution: set your `WorldEnvironment` sky before baking — it contributes indirect light
LightmapGI node placement
Add a single `LightmapGI` node to the root of your scene (not nested under any geometry). Key properties:
| Property | Recommended starting value | Notes |
|---|---|---|
| `Quality` | Medium | High for final bake, Low for iteration |
| `Bounces` | 2–3 | 1 bounce for indoor-only scenes |
| `Texel Scale` | 1.0 | Increase for higher resolution |
| `Max Texture Size` | 4096 | 8192 only if texture budget allows |
| `Environment Mode` | Scene | Uses your WorldEnvironment sky |
| `Interior` | false | Enable for fully enclosed spaces |
Baking lightmaps with LightmapGI
With the scene prepared, bake from Scene → Bake Lightmaps (or the LightmapGI node's "Bake" button). Godot writes a `.lmbake` file containing packed light data textures into your project.
![]()
Texel density is the most important quality lever. Higher `Texel Scale` means more lightmap pixels per world unit — sharper shadow edges but larger texture memory.
```
# Rule of thumb for texel scale by asset type
Small props (< 0.5m): Texel Scale 0.5–1.0
Room-scale geometry: Texel Scale 1.0–2.0
Exterior terrain: Texel Scale 0.25–0.5
Character (rare): Texel Scale 2.0–4.0
```
Probes: LightmapGI automatically scatters Lightmap Probes for dynamic objects. Add `LightmapProbe` nodes manually near areas with strong light variation (doorways, windows, under arches). Dynamic `MeshInstance3D` nodes (gi_mode = `DYNAMIC`) sample these probes at runtime with zero performance cost versus fully dynamic GI.
Common baking pitfalls
- Dark patches under small gaps: increase `Bounces` to 3 and enable `Environment Mode: Scene`
- Seam artifacts at UV islands: increase margin in UV2 unwrap; add padding in Blender's lightmap pack
- Blotchy indirect light: raise `Quality` to High or increase probe density with manual `LightmapProbe` nodes
- Build time too long: reduce `Max Texture Size` to 2048 during iteration; only bake at 4096+ for final build
Optimizing baked light for mobile and low-end targets
On mobile (Android/iOS) and low-spec desktop, lightmap texture memory is your main constraint. A 4096×4096 lightmap at RGBA8 costs 64 MB uncompressed — multiply that by slice count and you're over budget fast.
Compression settings: in Project Settings → Rendering → Lightmapping, enable Compress Lightmaps (on by default). Godot uses ETC2 on mobile (OpenGL ES 3.0+) and BC6H on desktop Vulkan. Both cut lightmap memory by ~6×.
Atlas packing: Godot automatically packs multiple meshes into shared lightmap atlases. You can check the final atlas layout with the `lmbake` file — import it as a texture to inspect packing efficiency. If atlas utilization is below ~70%, reduce `Max Texture Size` and let the packer use more, smaller textures.
Per-mesh lightmap scale: override lightmap resolution per mesh with `GeometryInstance3D.lightmap_scale`. Set small or distant props to `0.5×` or even `0.25×` to free up atlas space for hero geometry.
```gdscript
# GDScript — reduce lightmap scale for distant props at runtime
func set_lod_lightmap_scale(mesh: MeshInstance3D, distance: float) -> void:
if distance > 30.0:
mesh.lightmap_scale = GeometryInstance3D.LIGHTMAP_SCALE_2X # 0.5x
elif distance > 15.0:
mesh.lightmap_scale = GeometryInstance3D.LIGHTMAP_SCALE_1X # default
```
Mobile bake targets checklist:
- Total lightmap atlas memory < 128 MB (sum all atlases × 2 bytes/px for ETC2)
- `Interior: true` for enclosed scenes — skips expensive sky sampling
- `Bounces: 1` on low-end targets — single bounce captures 85% of indirect light
- `Quality: Low` + upscale with denoiser for fast iteration on mobile hardware
Lightmap baking in Godot 4: quick reference
Assets from BitSoul's marketplace ship with correct UV2 data already embedded in the GLB, so you can drop them into a scene, add a `LightmapGI` node, and bake immediately without touching Blender. Scenes built entirely from BitSoul assets can typically achieve a complete lightmap bake in under 5 minutes on modern hardware.
For full scene integration guidance and ready-to-bake environment kits, browse the BitSoul marketplace — all 747 models are GLB format with engine-ready UV2 channels.
---
*This post is part of the Ultimate Guide to Free 3D Game Assets — BitSoul's complete reference for formats, texturing, rigging, optimization, and engine integration.*