Light Types Compared

Each light type adds shader code and, with shadows on, a render pass of its own, so a scene usually combines one or two direct lights with cheap fill from a hemisphere light or an environment map (Environment Maps):

Three.js 30,815 light types
Light How it shines Shadows Notes
AmbientLight Equally everywhere No Flattens form; prefer a hemisphere
HemisphereLight Sky color above, ground color below No Cheap outdoor or room fill
DirectionalLight Parallel rays toward a target Orthographic map Sun; the chapter's 'sun'
PointLight All directions from a point Six-face cube map Candela; decay 2
SpotLight A cone (angle, penumbra) Perspective map Candela; can project a map
RectAreaLight From a rectangle No Standard and physical materials only
LightProbe Irradiance as spherical harmonics No Baked ambient from an environment

A DirectionalLight or SpotLight aims at light.target, an Object3D that must be in the scene when you move it. RectAreaLight needs RectAreaLightUniformsLib.init() from the add-ons with WebGLRenderer, and the SunLight add-on, new in r186, is a directional light with cascaded shadow maps for large outdoor scenes.

Six light types on the same books, rendered into six viewports of one canvasHTMLLive
<!doctype html>
<style>
  body { margin: 0; background: #f5f1e8; font: 12px system-ui, sans-serif; color: #263238; }
  #wrap { position: relative; width: 600px; max-width: 100%; }
  canvas { display: block; }
  .tag { position: absolute; width: 200px; text-align: center; font-weight: 600; }
</style>
<script type="importmap">
{ "imports": {
  "three": "https://cdn.jsdelivr.net/npm/three@0.186.1/build/three.module.js",
  "three/addons/": "https://cdn.jsdelivr.net/npm/three@0.186.1/examples/jsm/" } }
</script>
<div id="wrap"></div>
<script type="module">
import * as THREE from 'three';
import { RectAreaLightUniformsLib } from 'three/addons/lights/RectAreaLightUniformsLib.js';
import { RectAreaLightHelper } from 'three/addons/helpers/RectAreaLightHelper.js';

RectAreaLightUniformsLib.init();                       // RectAreaLight needs this with WebGLRenderer
const wrap = document.getElementById('wrap');
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setPixelRatio(Math.min(devicePixelRatio, 2));
renderer.setSize(600, 360);
renderer.setScissorTest(true);
wrap.appendChild(renderer.domElement);
const camera = new THREE.PerspectiveCamera(40, 200 / 180, 0.1, 30);
camera.position.set(0, 1.4, 3.4);
camera.lookAt(0, 0.2, 0);

// Each viewport gets its own scene: the same books and floor, a different light
function booksScene() {
  const scene = new THREE.Scene();
  scene.background = new THREE.Color('#1d2327');
  const floor = new THREE.Mesh(new THREE.PlaneGeometry(6, 6), new THREE.MeshStandardMaterial({ color: '#cfc6b5' }));
  floor.rotation.x = -Math.PI / 2;
  scene.add(floor);
  ['#1f5f8b', '#e09a10', '#b5452f'].forEach((color, i) => {
    const book = new THREE.Mesh(new THREE.BoxGeometry(0.5, 0.9, 0.16), new THREE.MeshStandardMaterial({ color, roughness: 0.5 }));
    book.position.set((i - 1) * 0.7, 0.45, 0);
    book.rotation.y = (i - 1) * 0.4;
    scene.add(book);
  });
  return scene;
}
const spot = new THREE.SpotLight('#ffffff', 25, 0, 0.45, 0.4);   // candela; cone angle; penumbra
spot.position.set(0, 3, 1.5);
const point = new THREE.PointLight('#fff3e0', 6);                 // decay 2: physically correct falloff
point.position.set(0.3, 1.2, 0.8);
const sun = new THREE.DirectionalLight('#ffffff', 3);
sun.position.set(-2, 3, 2);
const area = new THREE.RectAreaLight('#ffe0b0', 6, 1.6, 0.5);     // standard/physical materials only
area.position.set(0, 1.6, 1.4);
area.lookAt(0, 0.4, 0);
area.add(new RectAreaLightHelper(area));

const views = [
  ['AmbientLight', new THREE.AmbientLight('#ffffff', 1.2)],
  ['HemisphereLight', new THREE.HemisphereLight('#bfe3ff', '#8d6e63', 2)],
  ['DirectionalLight', sun],
  ['PointLight', point],
  ['SpotLight', spot],
  ['RectAreaLight', area],
].map(([name, light], i) => {
  const scene = booksScene();
  scene.add(light);
  if (light.isSpotLight || light.isDirectionalLight) scene.add(light.target);  // the aim point
  if (light.isPointLight) {
    const bulb = new THREE.Mesh(new THREE.SphereGeometry(0.04), new THREE.MeshBasicMaterial({ color: '#fff3e0' }));
    bulb.position.copy(light.position);
    scene.add(bulb);
  }
  const tag = wrap.appendChild(document.createElement('div'));
  tag.className = 'tag';
  tag.textContent = name;
  tag.style.cssText = `left:${(i % 3) * 200}px; top:${Math.floor(i / 3) * 180 + 4}px; color:#fff`;
  return { scene, light, x: (i % 3) * 200, y: Math.floor(i / 3) * 180 };
});

renderer.setAnimationLoop((time) => {
  point.position.x = Math.sin(time / 700) * 0.9;
  views[3].scene.children.at(-1).position.copy(point.position);
  spot.target.position.x = Math.sin(time / 900) * 0.8;
  for (const v of views) {
    // viewport y counts from the bottom of the canvas
    renderer.setViewport(v.x, 360 - v.y - 180, 200, 180);
    renderer.setScissor(v.x, 360 - v.y - 180, 199, 179);
    renderer.render(v.scene, camera);
  }
});
</script>