Skip to main content

Introduction to 3D Lighting

Lighting is crucial for creating atmosphere and visual depth in 3D scenes. Godot provides three main light types and advanced global illumination techniques to achieve realistic and performant lighting.
All light nodes inherit from the base Light3D class (doc/classes/Light3D.xml:2).

Light Types

DirectionalLight3D

Simulates distant light sources like the sun

OmniLight3D

Point light radiating in all directions

SpotLight3D

Cone-shaped light like a flashlight

DirectionalLight3D

Models infinite parallel rays from a distant source, typically used for sunlight or moonlight.

Basic Setup

var sun = DirectionalLight3D.new()
add_child(sun)

# Position doesn't matter - only rotation affects direction
sun.rotation_degrees = Vector3(-45, 30, 0)

# Configure light properties
sun.light_color = Color(1.0, 0.95, 0.8)  # Warm sunlight
sun.light_energy = 1.0
See doc/classes/DirectionalLight3D.xml:7-8
Light is emitted in the -Z direction of the node’s global basis. For an unrotated light, this means light travels forward.

Shadow Configuration

# Enable shadows
sun.shadow_enabled = true

# Shadow quality modes
sun.directional_shadow_mode = DirectionalLight3D.SHADOW_PARALLEL_4_SPLITS

# Shadow distance
sun.directional_shadow_max_distance = 200.0
sun.directional_shadow_fade_start = 0.8
See doc/classes/DirectionalLight3D.xml:24, 21-22

Shadow Split Configuration

For better shadow quality, directional lights use cascaded shadow maps:
sun.directional_shadow_mode = DirectionalLight3D.SHADOW_PARALLEL_2_SPLITS
sun.directional_shadow_split_1 = 0.1  # 10% of max distance
Good balance between quality and performance.
See doc/classes/DirectionalLight3D.xml:30-37

Sky Mode

# Control if light affects scene, sky, or both
sun.sky_mode = DirectionalLight3D.SKY_MODE_LIGHT_AND_SKY
  • SKY_MODE_LIGHT_AND_SKY: Affects both scene and sky (default)
  • SKY_MODE_LIGHT_ONLY: Only lights the scene
  • SKY_MODE_SKY_ONLY: Only affects sky shader
See doc/classes/DirectionalLight3D.xml:39-40

OmniLight3D

Emits light in all directions from a point, like a light bulb or candle.

Basic Setup

var bulb = OmniLight3D.new()
add_child(bulb)
bulb.position = Vector3(0, 3, 0)

# Configure range and attenuation
bulb.omni_range = 10.0
bulb.omni_attenuation = 2.0  # Physically accurate inverse square

# Light properties
bulb.light_color = Color(1.0, 0.8, 0.6)  # Warm white
bulb.light_energy = 1.5
See doc/classes/OmniLight3D.xml:23-25
Only 8 omni lights can affect each mesh in Mobile/Compatibility rendering methods. Exceeding this limit causes flickering.

Attenuation

Controls how light fades with distance:
# Linear falloff (constant brightness, smooth edge)
bulb.omni_attenuation = 0.0

# Realistic inverse square (physically accurate)
bulb.omni_attenuation = 2.0

# Custom curve
bulb.omni_attenuation = 1.5
See doc/classes/OmniLight3D.xml:17-21

Shadow Modes

# Enable shadows
bulb.shadow_enabled = true

# Shadow quality
bulb.omni_shadow_mode = OmniLight3D.SHADOW_CUBE  # Higher quality
# or
bulb.omni_shadow_mode = OmniLight3D.SHADOW_DUAL_PARABOLOID  # Faster
See doc/classes/OmniLight3D.xml:27-28, 32-37

SpotLight3D

Cone-shaped light emission, useful for flashlights, car headlights, or stage lights.

Basic Setup

var spotlight = SpotLight3D.new()
add_child(spotlight)
spotlight.position = Vector3(0, 5, 0)
spotlight.rotation_degrees = Vector3(-90, 0, 0)  # Point down

# Cone configuration
spotlight.spot_angle = 45.0  # Angular radius in degrees
spotlight.spot_range = 15.0
spotlight.spot_attenuation = 1.0
spotlight.spot_angle_attenuation = 1.0
See doc/classes/SpotLight3D.xml:21-23, 34-36
Light is emitted in the -Z direction. The spot_angle is the angular radius (from center to edge), so a 45° angle creates a 90° cone.

Angle and Range

# Wide cone (like a lantern)
spotlight.spot_angle = 60.0

# Narrow cone (like a laser pointer)
spotlight.spot_angle = 15.0

# Adjust range
spotlight.spot_range = 20.0

Attenuation Curves

# Distance attenuation (how light fades with distance)
spotlight.spot_attenuation = 2.0  # Inverse square

# Angular attenuation (how light fades toward cone edge)
spotlight.spot_angle_attenuation = 1.0  # Linear falloff
See doc/classes/SpotLight3D.xml:25-26, 28-32

Common Light Parameters

All light types share these properties from the Light3D base class:

Energy and Color

# Light intensity multiplier
light.light_energy = 1.0

# Light color in sRGB
light.light_color = Color(1.0, 1.0, 1.0)

# Specular contribution (shiny highlights)
light.light_specular = 1.0
See doc/classes/Light3D.xml:66-67, 73-74, 102-103

Physical Light Units

For realistic lighting, enable physical units in Project Settings:
# For DirectionalLight3D (Lux)
sun.light_intensity_lux = 100000  # Clear sunny day

# For OmniLight3D and SpotLight3D (Lumens)
bulb.light_intensity_lumens = 800  # ~60W light bulb
See doc/classes/Light3D.xml:85-87, 80-83

Color Temperature

# Simulate real-world light temperatures (Kelvin)
light.light_temperature = 6500  # Daylight
light.light_temperature = 2700  # Warm incandescent
light.light_temperature = 5500  # Camera flash
See doc/classes/Light3D.xml:105-107

Negative Lights

Create areas of darkness:
light.light_negative = true
light.light_energy = 0.5  # Darkness intensity
See doc/classes/Light3D.xml:89-90

Indirect Lighting

Control contribution to global illumination:
# Secondary multiplier for GI
light.light_indirect_energy = 1.0

# Volumetric fog contribution
light.light_volumetric_fog_energy = 1.0
See doc/classes/Light3D.xml:76-78, 109-111

Shadows

Enabling Shadows

light.shadow_enabled = true
See doc/classes/Light3D.xml:122-123
Shadows have significant performance cost. Use them judiciously and enable distance_fade_enabled for distant lights.

Shadow Quality Parameters

# Reduce shadow acne (self-shadowing artifacts)
light.shadow_bias = 0.1

# Reduce peter-panning (shadows separated from casters)
light.shadow_normal_bias = 2.0

# Shadow softness
light.shadow_blur = 1.0

# Shadow opacity
light.shadow_opacity = 1.0
See doc/classes/Light3D.xml:113-114, 125-126, 116-117, 128-129

Percentage-Closer Soft Shadows (PCSS)

Create realistic soft shadows:
# For DirectionalLight3D
sun.light_angular_distance = 0.5  # Sun's angular size

# For OmniLight3D and SpotLight3D
bulb.light_size = 0.2  # Light source size in Godot units
See doc/classes/Light3D.xml:57-60, 97-100
PCSS is only supported in Forward+ rendering (not Mobile or Compatibility).

Shadow Cull Mask

# Only cast shadows from specific layers
light.shadow_caster_mask = 0b00000001  # Only layer 1
See doc/classes/Light3D.xml:119-120

Distance Fade (LOD)

Optimize performance by fading distant lights:
light.distance_fade_enabled = true
light.distance_fade_begin = 40.0
light.distance_fade_length = 10.0
light.distance_fade_shadow = 50.0
See doc/classes/Light3D.xml:38-53

Light Projectors (Cookies/Gobos)

Project textures through lights:
light.light_projector = preload("res://textures/window_gobo.png")
light.shadow_enabled = true  # Required for projectors
See doc/classes/Light3D.xml:92-95
Light projectors are only supported in Forward+ and Mobile rendering methods.

Global Illumination (GI)

Godot offers multiple GI techniques:

Bake Modes

# Light doesn't affect GI (fastest)
light.light_bake_mode = Light3D.BAKE_DISABLED

# Static GI (baked, no real-time updates)
light.light_bake_mode = Light3D.BAKE_STATIC

# Dynamic GI (real-time updates)
light.light_bake_mode = Light3D.BAKE_DYNAMIC
See doc/classes/Light3D.xml:62-64, 204-214

LightmapGI

Bake static lighting for best performance:
1

Add LightmapGI Node

Add a LightmapGI node to your scene.
2

Configure Lights

Set lights to BAKE_STATIC mode:
sun.light_bake_mode = Light3D.BAKE_STATIC
3

Bake Lightmaps

Select the LightmapGI node and click “Bake Lightmaps” in the toolbar.
4

Use Baked Result

Lightmaps are automatically applied to static meshes.

VoxelGI

Real-time voxel-based global illumination:
var voxel_gi = VoxelGI.new()
add_child(voxel_gi)
voxel_gi.extents = Vector3(20, 10, 20)

# Bake the GI volume
voxel_gi.bake()

# Set light to dynamic mode for real-time updates
sun.light_bake_mode = Light3D.BAKE_DYNAMIC

SDFGI (Signed Distance Field GI)

Enable in WorldEnvironment for large open worlds:
var env = Environment.new()
env.sdfgi_enabled = true
world_environment.environment = env

# Lights contribute automatically if bake mode allows
sun.light_bake_mode = Light3D.BAKE_DYNAMIC

Lighting Best Practices

Always use DirectionalLight3D for primary outdoor lighting:
var sun = DirectionalLight3D.new()
sun.light_energy = 1.0
sun.light_color = Color(1.0, 0.95, 0.8)
sun.rotation_degrees = Vector3(-45, 30, 0)
Too many lights hurt performance. Use distance fade:
light.distance_fade_enabled = true
light.distance_fade_begin = 30.0
light.distance_fade_length = 10.0
For static scenes, use LightmapGI:
light.light_bake_mode = Light3D.BAKE_STATIC
Don’t render shadows too far away:
sun.directional_shadow_max_distance = 100.0
sun.directional_shadow_fade_start = 0.8
Exclude unnecessary objects from lighting:
light.light_cull_mask = 0b00000011  # Only layers 1 and 2

Common Lighting Scenarios

Outdoor Daytime

var sun = DirectionalLight3D.new()
sun.light_color = Color(1.0, 0.98, 0.95)
sun.light_energy = 1.0
sun.rotation_degrees = Vector3(-50, 20, 0)
sun.shadow_enabled = true
sun.directional_shadow_mode = DirectionalLight3D.SHADOW_PARALLEL_4_SPLITS

Indoor Room with Window

# Sunlight through window
var sun = DirectionalLight3D.new()
sun.light_energy = 0.3  # Dimmer indoors
sun.light_color = Color(1.0, 0.95, 0.9)

# Ceiling light
var ceiling_light = OmniLight3D.new()
ceiling_light.position = Vector3(0, 3, 0)
ceiling_light.omni_range = 8.0
ceiling_light.light_energy = 2.0
ceiling_light.light_color = Color(1.0, 0.9, 0.8)

Night Scene with Moonlight

var moon = DirectionalLight3D.new()
moon.light_color = Color(0.7, 0.8, 1.0)  # Cool blue tint
moon.light_energy = 0.2  # Dim
moon.rotation_degrees = Vector3(-60, 0, 0)
moon.shadow_enabled = true

Torch/Flashlight

var torch = SpotLight3D.new()
torch.spot_angle = 30.0
torch.spot_range = 10.0
torch.spot_attenuation = 2.0
torch.light_color = Color(1.0, 0.7, 0.4)  # Warm fire glow
torch.light_energy = 3.0

Debugging Lights

# Check if light is in the tree
if light.is_inside_tree():
    print("Light active")

# Print light properties
print("Energy: ", light.light_energy)
print("Color: ", light.light_color)
print("Shadows: ", light.shadow_enabled)

# Editor-only lights
light.editor_only = true  # Not visible at runtime
See doc/classes/Light3D.xml:54-55

Performance Monitoring

# Disable lights that are too far
func _process(_delta):
    var camera_pos = get_viewport().get_camera_3d().global_position
    var distance = global_position.distance_to(camera_pos)
    
    if distance > 50.0:
        visible = false
    else:
        visible = true

3D Overview

3D fundamentals and transforms

Meshes and Materials

How materials interact with lighting

Environment

Sky, fog, and ambient lighting

Shaders

Custom lighting in shaders

Resources

Build docs developers (and LLMs) love