【Godot】Godot 2D Lighting Guide: Deep Expression with PointLight2D and Shadows

Created: 2025-12-10Last updated: 2025-12-16

Learn how to implement 2D lighting and shadows using PointLight2D and LightOccluder2D. From basic setup to common problem solutions and performance optimization.

Overview

In 2D games made with Godot Engine, lighting serves more than just decorative purposes. Properly configured light and shadow give scenes depth and atmosphere, guide player attention, and enhance the game's world.

This article focuses on PointLight2D node—the core of Godot's 2D lighting system—and shadow configuration, explaining practical best practices while addressing common pitfalls for beginners.


Fundamental Elements of 2D Lighting

Godot's 2D lighting works through the coordination of three main nodes.

ElementRepresentative NodeRole
Light SourcePointLight2D, DirectionalLight2DThe entity that emits light into the scene. Determines light type like point or directional.
OccluderLightOccluder2DDefines shapes that block light and generate shadows. Independent of physics collision detection.
SubjectSprite2D, TileMap, etc.All nodes inheriting from CanvasItem. Affected by light—illuminated or hidden in shadow.

How PointLight2D Works

PointLight2D is the most basic light source, radiating light in all directions from a single point. The light's shape and color can be finely adjusted in the inspector properties.

  • Enabled: Enables/disables this light source.
  • Texture: Texture defining light shape and falloff. Usually uses a radial gradient (GradientTexture2D) that's white in the center and fades to black outward.
  • Color: Light color. #FFFFFF (white) is default.
  • Energy: Light intensity. Higher values are brighter.
  • Shadow > Enabled: Determines if this light source generates shadows. Enable only on necessary lights as it affects performance.

Tip: After adding PointLight2D to a scene, click [empty] on the Texture property in the inspector and select [New GradientTexture2D]. Then click the displayed GradientTexture2D and change Fill to Radial—that's all you need for a basic light source texture.

Shadow Boundaries: LightOccluder2D

Shadows aren't generated automatically. You need to tell Godot "what blocks light." That's the role of the LightOccluder2D node.

Add this node as a child of objects you want to cast shadows—walls, pillars, characters, etc. Then create a new OccluderPolygon2D resource in the Occluder property, and draw a polygon to block light by adding vertices from the editor's top toolbar.


Common Mistakes and Best Practices

2D lighting setup is intuitive, but several pitfalls exist.

Mistake (Anti-pattern)ProblemSolution (Best Practice)
Not using LightOccluder2DEven with PointLight2D's Shadow > Enabled on, no shadows generate because no occluders are defined.Add LightOccluder2D to all objects (or their parents) that should cast shadows, and precisely define occlusion ranges with OccluderPolygon2D.
Setting CanvasModulate to blackEntire scene goes pitch black, only lit areas visible.CanvasModulate color is applied via multiply blend and becomes the color where no Light2D exists. Set slightly bright gray (e.g., #202020) instead of complete darkness to ensure minimum visibility.
Too many OccluderPolygon2D verticesComplex polygons increase per-frame shadow calculation cost, causing performance drops especially on mobile devices.Create polygons with minimum necessary vertices to represent the occluder shape. For TileMap especially, set Occlusion in the TileSet editor rather than individual tiles, letting the engine optimize.
Enabling shadows on all lightsCalculates shadows even for decorative small lights or lights where performance doesn't matter, causing unnecessary load.Enable shadows only on important lights that directly affect player gameplay (e.g., flashlight, main streetlights), and disable Shadow > Enabled for auxiliary atmospheric lights.
Not utilizing Light MaskAll lights affect all objects, causing unintended lighting or missing optimization opportunities.Use Range > Item Cull Mask (light side) and Visibility > Light Mask (object side) to layer lighting.

Dynamic Lighting Control with GDScript

Using GDScript to dynamically control lights makes games more interactive.

Flashlight Implementation Example

A flashlight that follows the player with energy management.

# Player.gd (Expects child node named "Flashlight" as PointLight2D)
extends CharacterBody2D

@onready var flashlight: PointLight2D = $Flashlight

@export var max_light_energy: float = 1.0
@export var energy_drain_rate: float = 0.02 # Energy consumed per second

var current_energy: float

func _ready() -> void:
    current_energy = max_light_energy
    flashlight.enabled = false

func _unhandled_input(event: InputEvent) -> void:
    if event.is_action_pressed("toggle_light"):
        flashlight.enabled = not flashlight.enabled
        get_viewport().set_input_as_handled()

func _process(delta: float) -> void:
    if not flashlight.enabled:
        return

    # Gradually decrease energy
    current_energy -= energy_drain_rate * delta
    if current_energy <= 0.0:
        current_energy = 0.0
        flashlight.enabled = false

    # Change light intensity based on remaining energy
    flashlight.energy = lerp(0.5, 1.5, current_energy / max_light_energy)

    # Point flashlight toward mouse cursor
    # Note: PointLight2D radiates light radially, so rotation doesn't change appearance.
    # For a cone-shaped flashlight effect, you need a cone-shaped gradient image as Texture.
    var mouse_pos = get_global_mouse_position()
    flashlight.rotation = (mouse_pos - global_position).angle()

# Function to restore energy
func restore_energy(amount: float) -> void:
    current_energy = min(current_energy + amount, max_light_energy)
    if not flashlight.enabled and current_energy > 0:
        flashlight.enabled = true

Comparison with DirectionalLight2D

While PointLight2D is a point light source, DirectionalLight2D is a parallel light source that shines from one direction across the entire scene, like sunlight or moonlight.

FeaturePointLight2DDirectionalLight2D
Light ShapeRadiates outward from a pointFalls parallel across entire scene
Primary UsesTorches, light bulbs, magical lights—light sources at specific locationsSunlight, moonlight, outdoor ambient light
Shadow BehaviorShadows extend in all directions based on light positionShadows extend in one direction based on light angle
PerformanceLoad increases with many placedUsually one or two per scene. Relatively light.

Usage Tips: For outdoor scenes, first set overall brightness and shadow direction with DirectionalLight2D, then supplement with PointLight2D for cave entrances, campfires, etc.


Summary

Understanding the combination of PointLight2D and LightOccluder2D is key to success with Godot's 2D lighting.

  • PointLight2D: The light source itself. Adjust light appearance with texture and energy.
  • LightOccluder2D: Boundaries for casting shadows. Essential node for generating shadows.

Master these fundamentals and your 2D games will evolve from flat monotony to worlds with depth woven from light and shadow. Recommended next steps include Normal Maps for more realistic lighting expression and custom shaders for extending light effects.