logo
DirectionalLight

lighting

DirectionalLight

Free

Install with the CLI:

bjs download DirectionalLight

DirectionalLight

A sun-like light with parallel rays and optional shadow casting.

What it does

DirectionalLight is data-only: it holds a direction, a position, an intensity, diffuse/specular colors, and shadow settings. On entity attach the System reads those into a spec and calls createDirectionalLight on the renderer, storing the returned opaque handle back on the component (autoCreate gates this). Each frame it diffs the live component against a snapshot and pushes any change through updateLightIntensity, then announces it on the EventBus — directionallight.created, directionallight.shadow.created, directionallight.direction.changed, directionallight.intensity.changed, directionallight.color.changed. A sibling system that wants to react to the lighting (a day/night controller, a shadow-quality manager) subscribes to those events instead of holding the light itself.

Use it in a scene

A scene is just data — a list of entities, each with its components. At startup the SceneLoader turns this JSON into a live world; edit the file and reload to rebuild it.

Fastest path

bjs download scene DirectionalLight

Pulls this exact scene into your project and runs it — no copy-paste. Add --all to grab the components and assets it needs too.

Or build it from scratch with the bjs CLI:

  1. 1Scaffold a project
    npm create @babylonjsmarket/arcade@latest my-game

    World, renderer, and dev server — ready to run.

  2. 2Install dependencies
    cd my-game && npm install
  3. 3Add DirectionalLight
    bjs download DirectionalLight

    Copies its source into src/ so the scene resolves.

    First time? Run bjs login once.

  4. 4Paste the scene into src/scenes/arcade-room.ts and run
    npm run dev

    SceneLoader builds the world from the JSON; reload to rebuild.

JSON
{
  "Sun": {
    "components": {
      "DirectionalLight": {
        "direction": [-1, -3, -1],
        "position": [15, 30, 15],
        "intensity": 0.8,
        "diffuse": [1, 0.96, 0.86],
        "shadowEnabled": true,
        "shadowMapSize": 2048
      }
    }
  }
}

Props

  • direction ([x,y,z], default [-1, -3, -1]) — ray direction; normalized on construction (a zero vector falls back to straight down [0, -1, 0]).
  • position ([x,y,z], default [15, 30, 15]) — where the light sits, which anchors the shadow frustum.
  • intensity (number, default 0.8) — brightness; the one prop the System pushes to the renderer live each frame.
  • diffuse ([r,g,b], default [1, 1, 1]) — main lit-surface color.
  • specular ([r,g,b], default [1, 1, 1]) — highlight color.
  • shadowEnabled (boolean, default true) — generate a shadow map for this light.
  • shadowMinZ / shadowMaxZ (number, defaults 0 / 100) — near/far bounds of the shadow frustum.
  • shadowMapSize (number, default 1024) — shadow map resolution; raise for sharper edges, at a memory cost.
  • autoCreate (boolean, default true) — create the light on attach; set false to hold the data and build the light later.

Events

  • emits directionallight.created (DirectionalLightEvents.CREATED) once the light is built, with { entityId, direction, position, intensity }.
  • emits directionallight.shadow.created (SHADOW_CREATED) right after, when shadowEnabled, with { entityId, shadowMapSize }.
  • emits directionallight.intensity.changed (INTENSITY_CHANGED) when intensity drifts past the threshold, with { entityId, intensity }.
  • emits directionallight.direction.changed (DIRECTION_CHANGED) on a direction change, with { entityId, direction }.
  • emits directionallight.color.changed (COLOR_CHANGED) when diffuse or specular moves, with { entityId, diffuse, specular }.

Dependencies

None. DirectionalLight stands alone — it needs no sibling component on its own entity. To see shadows you separately need shadow-casting meshes in the scene (e.g. MeshPrimitive entities) and a ground surface to receive them.

Notes

  • Only intensity is reconciled to the renderer each frame; changing direction, diffuse, or specular at runtime emits its event but does not re-push the value through the adapter, so live re-aiming needs a system that listens for the change.
  • Change detection uses a 0.001 threshold per channel, so sub-millimetre jitter doesn't spam the bus.
  • The snapshot lives in a WeakMap keyed by the component, so it survives entity pooling without leaking when the entity is collected.
  • On entity removal the System disposes the handle and clears initialized, so re-adding the entity rebuilds the light cleanly.

More like this

CardFan
PokerTableCards
Shadow
AiPilot
Animation
ArcCamera
Asteroid
Bullet
CameraFollow
EnemySpawner
EnvironmentTexture
Flash
FreighterCar
FreighterChain
FreighterHead
GameConfig
Health
HemisphericLight
Jump
KeyboardInput
KeyboardMover
LensFlare
Lifetime
LineOfSight
MachineGun
Mesh
MeshPrimitive
Missile
MissileLauncher
MissionDirector
MouseInput
Movement
NebulaSky
Obstacle
ObstacleField
OilBlob
Parts
Physics
PlayerInput
PlayerWalkAnimator
Renderable
RespawnTimer
RoadTreadmill
RoundReset
Score
ShipDamageFX
ShipLoadout
SkeletonAnimator
Skybox
SmokeScreen
SpaceDust
SpaceShooterBullet
SpaceShooterFX
SpaceShooterHealth
SpaceShooterScore
ToneMapping
TwinStickEnemy
WaveDirector
Waypoint
WaypointTrack

Was this page helpful?

We read every note — tell us what's working and what isn't.

↑↓ NavigateEnter SelectEsc CloseCtrl+K Open Search