~3 min read

Lighting and Shadows

DirectionalLight3D, OmniLight3D, SpotLight3D, lightmaps, and SDFGI.

Иллюстрация: Lighting and Shadows

Light nodes

Three built-in light types (plus the upcoming AreaLight3D in 4.7):

  • DirectionalLight3D — the sun. Parallel rays, infinitely far away. Usually one per scene.
  • OmniLight3D — point light (Unity’s Point Light). Emits from a point in all directions with an attenuation radius.
  • SpotLight3D — a cone from a point with an angle and a radius.
  • AreaLight3D — an area light (since 4.7). A rectangular/disc source.
$DirectionalLight3D.light_energy = 1.5
$DirectionalLight3D.light_color = Color(1.0, 0.95, 0.85)  # warm morning
$DirectionalLight3D.shadow_enabled = true

Key properties of each:

  • light_energy — brightness.
  • light_color — color.
  • light_indirect_energy — a multiplier for indirect light from this source (in GI).
  • shadow_enabled — draw shadows.
  • shadow_bias, shadow_normal_bias — shadow artifact settings.
  • light_bake_modeLight3D.BAKE_DISABLED / BAKE_STATIC (baked) / BAKE_DYNAMIC (real-time GI). In the Inspector it’s shown as Disabled/Static/Dynamic, but in code it has the BAKE_ prefix.

Realtime, baked, mixed

As in Unity, there are three usage modes:

Bake ModeWhere it’s computedUse case
DISABLEDRealtime, every frameDynamic sources (an explosion, a rocket)
STATICBaked onceStatic architecture
DYNAMICRealtime + participates in GI (SDFGI/VoxelGI)The main scene light, doesn’t move

Baking GI

Godot has three global illumination systems, with different costs:

1. LightmapGI — baked lightmaps

The most efficient at runtime, but requires baking. For static geometry.

  1. Mark objects as “static” (via the gi_mode = STATIC flag in the Inspector on MeshInstance3D).
  2. Add a LightmapGI node to the scene.
  3. Bake Lightmaps with the button in the editor.

For dynamic objects within the lightmap area, use LightmapProbe (like Unity Light Probes).

2. VoxelGI — voxel-based realtime GI

Divides the scene into a 3D voxel grid and computes GI in realtime. Expensive, but beautiful. The VoxelGI node; the Bake button creates the initial data. Suitable for interiors.

3. SDFGI — Signed Distance Field GI

The most powerful — dynamic GI without baking. Enabled in the Environment resource:

env.sdfgi_enabled = true
env.sdfgi_cascades = 6
env.sdfgi_min_cell_size = 0.5

Downsides: Forward+ only, expensive, and a noticeable “haze” near the cascade boundaries.

The recipe for most projects

Forward+ desktop: the main light is a DirectionalLight3D in DYNAMIC bake mode, with a sky/world environment using SDFGI or LightmapGI. Mobile: LightmapGI + DirectionalLight3D in STATIC.

Shadows — cascades for DirectionalLight3D

A DirectionalLight (the sun) draws shadows via shadow cascades — several shadow-map resolutions at different distances:

  • directional_shadow_modeORTHOGONAL / PARALLEL_2_SPLITS / PARALLEL_4_SPLITS.
  • directional_shadow_max_distance — the distance up to which shadows are drawn.
  • directional_shadow_split_1/2/3 — the cascade proportions.

The more cascades, the smoother the transition, but the more expensive it is. PARALLEL_4_SPLITS is the standard.

Skybox and Environment

WorldEnvironment + the Environment resource are the scene’s global settings. Environment.background_mode accepts values with the BG_ prefix:

  • Environment.BG_CLEAR_COLOR — one color.
  • Environment.BG_COLOR — another color.
  • Environment.BG_SKY — a Sky resource (procedural or panorama HDR).
  • Environment.BG_CANVAS — a 2D background.
  • Environment.BG_KEEP — don’t clear (for split-screen).
  • Environment.BG_CAMERA_FEED — AR / the device camera.

For HDRI:

var sky_mat = PanoramaSkyMaterial.new()
sky_mat.panorama = preload("res://hdri/sunset_4k.exr")
var sky = Sky.new()
sky.sky_material = sky_mat
env.sky = sky
env.background_mode = Environment.BG_SKY
env.ambient_light_source = Environment.AMBIENT_SOURCE_SKY

Panorama (equirectangular) HDR works out of the box — grab one from PolyHaven, drop it in, and the lighting gets “soaked” in that sky.

Reflection Probes

The ReflectionProbe node is a spherical environment map for reflections in a material. Place it in the center of a room:

  • box_projection — project the reflection onto a box so reflections don’t “drift” in corners.
  • update_modeONCE (a single baked one) / ALWAYS (every frame, expensive).

For metallic materials this is critical — without a probe they only reflect the sky.

What usually breaks for beginners

  1. All objects are dynamic, GI doesn’t work. Mark gi_mode = STATIC on non-moving geometry before baking.
  2. Too many realtime shadow-casting lights. An OmniLight3D with shadows in Forward is expensive. Limit it to 4–6 visible at once.
  3. The Compatibility renderer with SDFGI / VoxelGI. They don’t work together — use LightmapGI.
  4. Forgetting WorldEnvironment. Without it, the scene renders with the default environment (often a black background, no ambient).

In the next chapter — animation.