Threejs Lighting

Design and automate dynamic Three.js lighting setups with seamless integration

Three.js Lighting is a community skill for configuring lighting in Three.js scenes, covering ambient light, directional light, point and spot lights, shadow mapping, and environment lighting for realistic 3D illumination.

What Is This?

Overview

Three.js Lighting provides guidance on illuminating 3D scenes using the Three.js lighting system. It covers ambient light that provides uniform base illumination to all objects in a scene, directional light that simulates sunlight with parallel rays and shadow casting, point and spot lights that create localized illumination with distance falloff and cone angles, shadow mapping that renders realistic cast shadows from light sources onto receiving surfaces, and environment lighting that uses HDR images and probes for image-based illumination and reflections. The skill helps developers create visually compelling 3D scenes.

Who Should Use This

This skill serves web developers building lit 3D scenes, creative developers designing interactive visual experiences, and product teams creating realistic 3D viewers with proper illumination.

Why Use It?

Problems It Solves

Scenes without proper lighting appear flat and unrealistic. Shadow configuration requires balancing quality against rendering performance. Multiple light sources without optimization cause frame rate drops. Environment-based lighting needs HDR setup that is complex to configure correctly.

Core Highlights

Light configurator sets up ambient, directional, and point lights. Shadow manager configures shadow maps with quality settings. Environment mapper loads HDR images for image-based lighting. Performance tuner optimizes light count and shadow resolution.

How to Use It?

Basic Usage

// Lighting setup
import * as THREE from
  'three';

function setupLighting(
  scene, renderer
) {
  renderer.shadowMap
    .enabled = true;
  renderer.shadowMap
    .type = THREE
    .PCFSoftShadowMap;

  const ambient =
    new THREE
    .AmbientLight(
      0x404040, 0.5);
  scene.add(ambient);

  const dirLight =
    new THREE
    .DirectionalLight(
      0xffffff, 1.0);
  dirLight.position.set(
    5, 10, 7);
  dirLight.castShadow
    = true;
  dirLight.shadow
    .mapSize.set(
      2048, 2048);
  dirLight.shadow
    .camera.near = 0.5;
  dirLight.shadow
    .camera.far = 50;
  const d = 10;
  dirLight.shadow
    .camera.left = -d;
  dirLight.shadow
    .camera.right = d;
  dirLight.shadow
    .camera.top = d;
  dirLight.shadow
    .camera.bottom = -d;
  scene.add(dirLight);

  const pointLight =
    new THREE
    .PointLight(
      0xff6600, 1, 20);
  pointLight.position
    .set(-3, 4, 0);
  scene.add(pointLight);

  return {
    ambient,
    dirLight,
    pointLight };
}

Real-World Examples

// Environment lighting
import * as THREE from
  'three';
import { RGBELoader }
  from 'three/addons/'
  + 'loaders/'
  + 'RGBELoader.js';

class LightingManager {
  constructor(
    scene, renderer
  ) {
    this.scene = scene;
    this.renderer =
      renderer;
    this.lights = [];
  }

  async loadEnvMap(
    hdrPath
  ) {
    const loader =
      new RGBELoader();
    const texture =
      await loader
      .loadAsync(hdrPath);
    texture.mapping =
      THREE
      .EquirectangularReflectionMapping;
    this.scene
      .environment =
      texture;
    return texture;
  }

  addSpotLight(
    pos, target,
    color, angle
  ) {
    const spot =
      new THREE
      .SpotLight(
        color, 1,
        50, angle);
    spot.position.copy(
      pos);
    spot.target.position
      .copy(target);
    spot.castShadow = true;
    spot.shadow.mapSize
      .set(1024, 1024);
    this.scene.add(spot);
    this.scene.add(
      spot.target);
    this.lights.push(
      spot);
    return spot;
  }

  setIntensity(
    factor
  ) {
    for (const light
      of this.lights
    ) {
      light.intensity =
        factor;
    }
  }
}

// const mgr =
//   new LightingManager(
//     scene, renderer);
// await mgr.loadEnvMap(
//   'studio.hdr');

Advanced Tips

Use PCFSoftShadowMap for smoother shadow edges at moderate performance cost. Set shadow camera bounds tightly around the scene to maximize shadow map resolution. Combine environment maps with a single directional light for realistic indoor and outdoor scenes.

When to Use It?

Use Cases

Configure realistic lighting for a product viewer with shadows and reflections. Build an architectural visualization with indoor spot lights and ambient occlusion. Create a stylized scene with colored point lights for artistic effect.

Related Topics

Three.js, WebGL, 3D lighting, shadow mapping, HDR environment maps, physically-based rendering, and image-based lighting.

Important Notes

Requirements

Three.js library with WebGLRenderer for shadow-capable rendering. HDR images in RGBE format for environment-based lighting setups. Materials that respond to lighting such as MeshStandardMaterial or MeshPhysicalMaterial for physically accurate illumination.

Usage Recommendations

Do: limit shadow-casting lights to reduce rendering overhead since each shadow requires an extra render pass. Use helper objects like DirectionalLightHelper to debug light positioning. Adjust shadow bias to prevent shadow acne artifacts on surfaces.

Don't: enable shadows on every light in the scene since this multiplies render passes. Use large shadow map sizes without checking frame rate impact on target devices. Forget to set castShadow and receiveShadow on meshes since shadows require both flags configured.

Limitations

Real-time shadow quality is limited by shadow map resolution and filtering method. Many simultaneous lights degrade performance especially on mobile GPUs. Global illumination effects like bounced light require specialized techniques beyond standard Three.js lighting.