Lighting Components
Light component for DirectionalLight, PointLight, and SpotLight with shadow support and Environment settings.
Lighting components enable realistic illumination and shadows in your scenes. Web Engine uses Three.js lighting with support for directional, point, and spot lights, plus advanced features like shadow mapping and environmental lighting.
Light Component#
The Light component is a unified component for all light types. The type field determines whether the entity is a directional, point, or spot light.
Properties#
| Property | Type | Default | Description |
|---|---|---|---|
| type | ui8 | 0 | Light type: 0=Point, 1=Directional, 2=Spot |
| color | [f32, 3] | [1, 1, 1] | Light color [r, g, b] in linear space (0-1) |
| intensity | f32 | 1.0 | Light intensity/brightness |
| range | f32 | 10.0 | Light range in meters (Point and Spot only) |
| angle | f32 | 0.785 | Cone angle in radians (Spot only, π/4 = 45°) |
| castShadow | ui8 | 0 | Whether light casts shadows (0=no, 1=yes) |
Light Types#
- Point (0): Emits light in all directions from a point (like a light bulb)
- Directional (1): Parallel rays from infinite distance (like the sun)
- Spot (2): Emits light in a cone shape (like a flashlight)
DirectionalLight#
Directional lights simulate sunlight with parallel rays from an infinite distance. Perfect for outdoor scenes, day/night cycles, and primary scene illumination.
Usage#
import { addComponent, Light, Transform } from '@web-engine/core'; // Create sun (directional light)const sun = world.addEntity();addComponent(world, Transform, sun);addComponent(world, Light, sun); // Position doesn't matter (infinite distance), only rotationTransform.position[sun] = [0, 20, 0]; // Height is visual onlyTransform.rotation[sun] = [ -Math.PI / 4, // 45° downward tilt Math.PI / 4, // 45° angle from side 0]; // Configure as directional lightLight.type[sun] = 1; // DirectionalLight.color[sun][0] = 1.0; // White lightLight.color[sun][1] = 1.0;Light.color[sun][2] = 1.0;Light.intensity[sun] = 1.5; // Bright sunlightLight.castShadow[sun] = 1; // Enable shadowsCommon Configurations#
// Noon sunlight (overhead)Transform.rotation[sun] = [-Math.PI / 2, 0, 0]; // Straight downLight.color[sun] = [1.0, 0.98, 0.95]; // Slight warm tintLight.intensity[sun] = 2.0; // Sunset lightingTransform.rotation[sun] = [-0.3, Math.PI / 3, 0]; // Low angleLight.color[sun] = [1.0, 0.6, 0.3]; // Orange-redLight.intensity[sun] = 1.2; // MoonlightTransform.rotation[sun] = [-0.5, 0, 0];Light.color[sun] = [0.6, 0.7, 1.0]; // Blue tintLight.intensity[sun] = 0.3; // DimDirectional Light Position
Directional lights simulate infinitely distant light sources, so the position doesn't affect lighting. Only the rotation (direction) matters. Position is only used for visual representation in the editor.
PointLight#
Point lights emit light in all directions from a single point, like a light bulb or torch. They have a limited range and use distance-based attenuation.
Usage#
import { addComponent, Light, Transform } from '@web-engine/core'; // Create torch (point light)const torch = world.addEntity();addComponent(world, Transform, torch);addComponent(world, Light, torch); // Position matters - place where light should emit fromTransform.position[torch] = [5, 2, 0]; // Wall-mounted torch at 2m height // Configure as point lightLight.type[torch] = 0; // PointLight.color[torch][0] = 1.0; // Orange flame colorLight.color[torch][1] = 0.6;Light.color[torch][2] = 0.2;Light.intensity[torch] = 2.0;Light.range[torch] = 10.0; // 10 meter rangeLight.castShadow[torch] = 1;Common Configurations#
// CandleLight.type[entity] = 0;Light.color[entity] = [1.0, 0.7, 0.3];Light.intensity[entity] = 0.5;Light.range[entity] = 3.0; // Light bulbLight.type[entity] = 0;Light.color[entity] = [1.0, 0.95, 0.8];Light.intensity[entity] = 1.5;Light.range[entity] = 8.0; // Explosion flashLight.type[entity] = 0;Light.color[entity] = [1.0, 0.8, 0.3];Light.intensity[entity] = 10.0;Light.range[entity] = 20.0; // Neon signLight.type[entity] = 0;Light.color[entity] = [0.0, 1.0, 0.8]; // CyanLight.intensity[entity] = 2.0;Light.range[entity] = 5.0;Light Attenuation#
Point lights use physically-based inverse square falloff with configurable range:
// Light intensity decreases with distance:// intensity_at_distance = intensity / (distance^2 + 1)// At range distance, light contribution approaches zero // Small radius, bright centerLight.range[lamp] = 5.0;Light.intensity[lamp] = 3.0; // Large radius, even spreadLight.range[lamp] = 15.0;Light.intensity[lamp] = 1.0;SpotLight#
Spot lights emit light in a cone shape, like a flashlight or stage spotlight. They have position, direction, range, and cone angle.
Usage#
import { addComponent, Light, Transform } from '@web-engine/core'; // Create flashlight (spot light)const flashlight = world.addEntity();addComponent(world, Transform, flashlight);addComponent(world, Light, flashlight); // Position and rotation both matterTransform.position[flashlight] = [0, 1.5, 0]; // Eye levelTransform.rotation[flashlight] = [0, 0, 0]; // Forward direction // Configure as spot lightLight.type[flashlight] = 2; // SpotLight.color[flashlight][0] = 1.0;Light.color[flashlight][1] = 1.0;Light.color[flashlight][2] = 0.9;Light.intensity[flashlight] = 3.0;Light.range[flashlight] = 20.0; // 20m beam distanceLight.angle[flashlight] = Math.PI / 6; // 30° cone (π/6 radians)Light.castShadow[flashlight] = 1;Common Configurations#
// FlashlightLight.type[entity] = 2;Light.angle[entity] = Math.PI / 6; // 30° coneLight.range[entity] = 20.0;Light.intensity[entity] = 3.0; // Stage spotlight (narrow beam)Light.type[entity] = 2;Light.angle[entity] = Math.PI / 12; // 15° coneLight.range[entity] = 30.0;Light.intensity[entity] = 5.0; // Street lampLight.type[entity] = 2;Light.angle[entity] = Math.PI / 3; // 60° coneLight.range[entity] = 15.0;Light.intensity[entity] = 2.0; // Car headlightLight.type[entity] = 2;Light.angle[entity] = Math.PI / 4; // 45° coneLight.range[entity] = 50.0;Light.intensity[entity] = 4.0;Spotlight Direction#
// Spotlight points in entity's local -Z direction// Rotate to aim spotlight // Point down (ceiling lamp)Transform.rotation[spotlight] = [Math.PI / 2, 0, 0]; // Point forwardTransform.rotation[spotlight] = [0, 0, 0]; // Point at 45° angle down and rightTransform.rotation[spotlight] = [Math.PI / 4, Math.PI / 4, 0]; // Attach to player camera for flashlightconst camera = getCameraEntity(world);Transform.parent[flashlight] = camera;Transform.position[flashlight] = [0, -0.2, 0]; // Offset slightly downShadow Configuration#
All light types support shadow casting. Shadows are computed using shadow mapping with configurable quality and distance.
Enabling Shadows#
// Enable shadow casting on lightLight.castShadow[sun] = 1; // Enable shadow casting on meshMeshRenderer.castShadow[character] = 1; // Enable shadow receiving on meshMeshRenderer.receiveShadow[floor] = 1; // Both casting and receivingMeshRenderer.castShadow[rock] = 1;MeshRenderer.receiveShadow[rock] = 1;Shadow Performance
Shadow rendering is expensive. Limit shadow-casting lights to 1-3 per scene. Use castShadow=1 only on important lights (sun, player flashlight). Disable shadows on small or distant objects for better performance.
Shadow Quality#
// Shadow quality is configured globally via renderer settings// Higher resolution = sharper shadows but more expensive const renderer = getRenderer(world); // Low quality (mobile)renderer.shadowMap.enabled = true;renderer.shadowMap.type = THREE.BasicShadowMap; // 1024x1024 // Medium quality (default)renderer.shadowMap.type = THREE.PCFShadowMap; // 2048x2048, soft edges // High quality (desktop)renderer.shadowMap.type = THREE.PCFSoftShadowMap; // 4096x4096, very soft // Ultra quality (cinematic)renderer.shadowMap.type = THREE.VSMShadowMap; // Variance shadow mapsLight Properties Deep Dive#
Color and Temperature#
Light colors are specified in linear RGB space (0-1). Use color temperature presets for realistic lighting:
// Color temperature presets (Kelvin to RGB)const LIGHT_COLORS = { // Warm lights candle: [1.0, 0.58, 0.16], // 1500K sunset: [1.0, 0.54, 0.0], // 2000K tungsten: [1.0, 0.78, 0.55], // 3200K halogen: [1.0, 0.94, 0.88], // 3400K // Neutral lights fluorescent: [0.99, 1.0, 0.98], // 4000K daylight: [1.0, 1.0, 1.0], // 5500K flash: [1.0, 1.0, 1.0], // 5500K // Cool lights overcast: [0.78, 0.84, 1.0], // 6500K shade: [0.64, 0.73, 1.0], // 8000K clearSky: [0.25, 0.5, 1.0], // 10000K // Colored lights fire: [1.0, 0.5, 0.0], lava: [1.0, 0.3, 0.0], neonBlue: [0.0, 0.5, 1.0], neonPink: [1.0, 0.0, 0.5], poison: [0.5, 1.0, 0.0],}; // Apply color presetLight.color[torch] = LIGHT_COLORS.tungsten;Light.color[neonSign] = LIGHT_COLORS.neonBlue;Intensity Guidelines#
| Light Type | Typical Intensity | Use Case |
|---|---|---|
| Directional (Sun) | 1.0 - 3.0 | Outdoor daylight, primary illumination |
| Directional (Moon) | 0.1 - 0.5 | Night scenes, subtle ambient |
| Point (Candle) | 0.3 - 0.8 | Small intimate lighting |
| Point (Bulb) | 1.0 - 2.0 | Room lighting, lamps |
| Point (Explosion) | 5.0 - 20.0 | Temporary bright flash |
| Spot (Flashlight) | 2.0 - 5.0 | Player equipment, exploration |
| Spot (Stage) | 3.0 - 10.0 | Dramatic lighting, highlights |
Environment Component#
The Environment component controls global scene lighting including skybox, fog, ambient light, and HDRI environment maps.
Properties#
| Property | Type | Default | Description |
|---|---|---|---|
| preset | ui8 | 0 | Environment preset (0=None, 1=Sunset, 2=Dawn, etc.) |
| background | ui8 | 1 | Show skybox as background (0=no, 1=yes) |
| blur | f32 | 0.0 | Background blur amount (0-1) |
| sunPosition | [f32, 3] | [10, 10, 10] | Sun position for preset environments |
| ambientIntensity | f32 | 0.5 | Ambient light intensity |
| fogColor | [f32, 3] | [0.5, 0.5, 0.5] | Fog color [r, g, b] |
| fogDensity | f32 | 0.0 | Fog density (0=no fog, 0.01=light fog, 0.1=heavy fog) |
| csmEnabled | ui8 | 0 | Cascaded shadow maps enabled (0=no, 1=yes) |
| csmIntensity | f32 | 1.0 | CSM shadow intensity |
| volumetricFog | ui8 | 0 | Volumetric fog/god rays (0=no, 1=yes) |
| envMapAssetId | ui32 | 0 | Custom HDRI environment map asset ID |
| toneMappingExposure | f32 | 1.0 | Global exposure for tone mapping |
Usage#
import { addComponent, Environment } from '@web-engine/core'; // Create environment entityconst env = world.addEntity();addComponent(world, Environment, env); // Sunset presetEnvironment.preset[env] = 1; // SunsetEnvironment.background[env] = 1;Environment.ambientIntensity[env] = 0.6;Environment.sunPosition[env] = [10, 2, 5]; // Low sun angle // Add fogEnvironment.fogColor[env] = [0.8, 0.6, 0.5]; // Warm fogEnvironment.fogDensity[env] = 0.02; // Light fog // Tone mappingEnvironment.toneMappingExposure[env] = 1.2;Environment Presets#
| Preset | Value | Description |
|---|---|---|
| None | 0 | No preset environment |
| Sunset | 1 | Orange sunset sky with warm lighting |
| Dawn | 2 | Early morning sky with cool lighting |
| Night | 3 | Dark night sky with stars |
| Warehouse | 4 | Indoor warehouse HDRI |
| Forest | 5 | Forest clearing HDRI |
| Apartment | 6 | Interior apartment HDRI |
| Studio | 7 | Photo studio HDRI |
| City | 8 | Urban cityscape HDRI |
| Park | 9 | Outdoor park HDRI |
| Lobby | 10 | Interior lobby HDRI |
Fog Configuration#
// Atmospheric fog (distance fog)Environment.fogColor[env] = [0.7, 0.8, 0.9]; // Sky blueEnvironment.fogDensity[env] = 0.01; // Gradual fade // Heavy fog (horror game)Environment.fogColor[env] = [0.3, 0.3, 0.35]; // GrayEnvironment.fogDensity[env] = 0.08; // UnderwaterEnvironment.fogColor[env] = [0.0, 0.3, 0.5]; // Blue-greenEnvironment.fogDensity[env] = 0.15; // No fogEnvironment.fogDensity[env] = 0.0;Best Practices#
- Use one directional light as the primary light source (sun/moon)
- Limit shadow-casting lights to 1-3 per scene for performance
- Use point lights for local illumination (torches, lamps, fires)
- Use spot lights for focused beams (flashlights, headlights, stage lights)
- Set appropriate light ranges to minimize overlap and improve performance
- Use ambient light (Environment.ambientIntensity) to fill shadows
- Match fog color to background color for seamless blending
- Enable castShadow only on important objects (characters, props)
- Use color temperature to create mood (warm = cozy, cool = clinical)
- Add slight color tint to lights for visual interest (not pure white)
- Use HDRI environment maps for realistic reflections and ambient lighting
- Combine multiple lights for depth: key light (bright), fill light (soft), rim light (edge)
Common Lighting Scenarios#
Outdoor Day Scene#
// Sun (directional)const sun = world.addEntity();addComponent(world, Light, sun);Light.type[sun] = 1;Light.color[sun] = [1.0, 0.98, 0.95];Light.intensity[sun] = 2.0;Light.castShadow[sun] = 1;Transform.rotation[sun] = [-Math.PI / 3, Math.PI / 4, 0]; // Environmentconst env = world.addEntity();addComponent(world, Environment, env);Environment.preset[env] = 1; // SunsetEnvironment.ambientIntensity[env] = 0.5;Environment.fogDensity[env] = 0.005;Indoor Room#
// Ceiling lamp (point)const lamp = world.addEntity();addComponent(world, Light, lamp);Light.type[lamp] = 0;Light.color[lamp] = [1.0, 0.95, 0.85];Light.intensity[lamp] = 1.5;Light.range[lamp] = 8.0;Transform.position[lamp] = [0, 3, 0]; // Window light (spot, simulating sunbeam)const window = world.addEntity();addComponent(world, Light, window);Light.type[window] = 2;Light.color[window] = [1.0, 1.0, 0.98];Light.intensity[window] = 2.0;Light.range[window] = 10.0;Light.angle[window] = Math.PI / 6;Light.castShadow[window] = 1;Transform.position[window] = [5, 3, 0];Transform.rotation[window] = [0, -Math.PI / 2, 0];Horror Atmosphere#
// Dim moonlightconst moon = world.addEntity();addComponent(world, Light, moon);Light.type[moon] = 1;Light.color[moon] = [0.5, 0.6, 0.8];Light.intensity[moon] = 0.3;Transform.rotation[moon] = [-0.5, 0, 0]; // Flickering candle (point)const candle = world.addEntity();addComponent(world, Light, candle);Light.type[candle] = 0;Light.color[candle] = [1.0, 0.7, 0.3];Light.intensity[candle] = 0.8; // Flicker in scriptLight.range[candle] = 4.0; // Heavy fogconst env = world.addEntity();addComponent(world, Environment, env);Environment.fogColor[env] = [0.1, 0.1, 0.15];Environment.fogDensity[env] = 0.05;Environment.ambientIntensity[env] = 0.1;