Skip to main content

Command Palette

Search for a command to run...

Mastering Three.js Lighting: Illuminating Your 3D World

Updated
14 min read
Mastering Three.js Lighting: Illuminating Your 3D World

Welcome back! 👋 In my previous posts, I covered Three.js basics, geometries and materials. Today, I'm diving into lighting - one of the most important aspects of creating realistic 3D scenes.

Good lighting can make or break your 3D scene. It's the difference between a flat, lifeless render and a vibrant, realistic world. Let's explore how to light our scenes like a professional photographer!

What is Lighting in Three.js?

Lighting in Three.js simulates how light behaves in the real world. Different light types mimic different real-world light sources:

  • Sun (DirectionalLight)

  • Light bulbs (PointLight)

  • Flashlights (SpotLight)

  • Sky lighting (HemisphereLight)

  • Overall brightness (AmbientLight)

Understanding when and how to use each light type is key to creating the mood and atmosphere you want.

The Photography Analogy

Think of Three.js lighting is like setting up a photography or film studio:

  • Key Light (main light source) - DirectionalLight or SpotLight

  • Fill Light (softens shadows) - AmbientLight or HemisphereLight

  • Rim/Back Light (separates subject from background) - PointLight or SpotLight

  • Practical Lights (visible light sources) - PointLight with visible geometry

Just like in photography, you rarely use just one light. The magic happens when you combine multiple lights!

Project Setup

Here's our HTML structure with controls:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Three.js Lighting Guide</title>
    <style>
        body { 
            margin: 0; 
            overflow: hidden;
            font-family: Arial, sans-serif;
        }
        canvas { 
            display: block; 
        }
        #controls {
            position: absolute;
            top: 20px;
            right: 20px;
            color: white;
            background: rgba(0, 0, 0, 0.85);
            padding: 20px;
            border-radius: 8px;
            font-size: 13px;
            max-width: 280px;
            max-height: 90vh;
            overflow-y: auto;
        }
        #controls h3 {
            margin-top: 0;
            color: #4ecdc4;
            font-size: 16px;
        }
        .light-section {
            margin: 15px 0;
            padding: 10px;
            background: rgba(255, 255, 255, 0.05);
            border-radius: 4px;
        }
        .light-section h4 {
            margin: 0 0 10px 0;
            color: #ffe66d;
            font-size: 14px;
        }
        .control-group {
            margin: 8px 0;
        }
        .control-group label {
            display: block;
            margin-bottom: 3px;
            color: #aaa;
            font-size: 11px;
        }
        input[type="range"] {
            width: 100%;
        }
        input[type="checkbox"] {
            margin-right: 5px;
        }
        .toggle-label {
            display: flex;
            align-items: center;
            cursor: pointer;
        }
        #info {
            position: absolute;
            top: 20px;
            left: 20px;
            color: white;
            background: rgba(0, 0, 0, 0.85);
            padding: 15px;
            border-radius: 8px;
            font-size: 13px;
            max-width: 250px;
        }
        #info h3 {
            margin-top: 0;
            color: #4ecdc4;
        }
    </style>
</head>
<body>
    <canvas id="canvas"></canvas>

    <div id="info">
        <h3>Lighting Demo</h3>
        <p>Toggle different lights to see how they affect the scene. Light helpers show light positions.</p>
    </div>

    <div id="controls">
        <h3>Light Controls</h3>

        <div class="light-section">
            <h4>Ambient Light</h4>
            <div class="control-group">
                <label class="toggle-label">
                    <input type="checkbox" id="ambientToggle" checked>
                    Enable
                </label>
            </div>
            <div class="control-group">
                <label>Intensity: <span id="ambientIntensity">0.3</span></label>
                <input type="range" id="ambientSlider" min="0" max="1" step="0.1" value="0.3">
            </div>
        </div>

        <div class="light-section">
            <h4>Directional Light</h4>
            <div class="control-group">
                <label class="toggle-label">
                    <input type="checkbox" id="directionalToggle" checked>
                    Enable
                </label>
            </div>
            <div class="control-group">
                <label>Intensity: <span id="directionalIntensity">1.0</span></label>
                <input type="range" id="directionalSlider" min="0" max="2" step="0.1" value="1">
            </div>
        </div>

        <div class="light-section">
            <h4>Point Light</h4>
            <div class="control-group">
                <label class="toggle-label">
                    <input type="checkbox" id="pointToggle" checked>
                    Enable
                </label>
            </div>
            <div class="control-group">
                <label>Intensity: <span id="pointIntensity">1.0</span></label>
                <input type="range" id="pointSlider" min="0" max="2" step="0.1" value="1">
            </div>
        </div>

        <div class="light-section">
            <h4>Spot Light</h4>
            <div class="control-group">
                <label class="toggle-label">
                    <input type="checkbox" id="spotToggle" checked>
                    Enable
                </label>
            </div>
            <div class="control-group">
                <label>Intensity: <span id="spotIntensity">1.0</span></label>
                <input type="range" id="spotSlider" min="0" max="2" step="0.1" value="1">
            </div>
            <div class="control-group">
                <label>Angle: <span id="spotAngle">0.5</span></label>
                <input type="range" id="spotAngleSlider" min="0" max="1.57" step="0.1" value="0.5">
            </div>
        </div>

        <div class="light-section">
            <h4>Hemisphere Light</h4>
            <div class="control-group">
                <label class="toggle-label">
                    <input type="checkbox" id="hemisphereToggle">
                    Enable
                </label>
            </div>
            <div class="control-group">
                <label>Intensity: <span id="hemisphereIntensity">0.5</span></label>
                <input type="range" id="hemisphereSlider" min="0" max="1" step="0.1" value="0.5">
            </div>
        </div>

        <div class="light-section">
            <h4>Helpers</h4>
            <div class="control-group">
                <label class="toggle-label">
                    <input type="checkbox" id="helpersToggle" checked>
                    Show Light Helpers
                </label>
            </div>
        </div>
    </div>

    <script type="module" src="/src/lighting.js"></script>
</body>
</html>

Building Our Lighting Scene

Let's create a scene that demonstrates most used light types!

Step 1: Scene and Camera Setup

import * as THREE from "three";

const canvas = document.getElementById("canvas");

// Scene setup
const scene = new THREE.Scene();
scene.background = new THREE.Color(0x0a0a0a); // Very dark background

// Camera setup
const camera = new THREE.PerspectiveCamera(
    75,
    window.innerWidth / window.innerHeight,
    0.1,
    1000
);
camera.position.set(0, 8, 20);
camera.lookAt(0, 0, 0);

Step 2: Creating Scene Objects

Let's create a simple scene with objects that will show off the lighting:

// Create a ground plane
const groundGeometry = new THREE.PlaneGeometry(50, 50);
const groundMaterial = new THREE.MeshStandardMaterial({
  color: 0x333333,
  roughness: 0.8,
  metalness: 0.2,
});
const ground = new THREE.Mesh(groundGeometry, groundMaterial);
ground.rotation.x = -Math.PI / 2; // Rotate to be horizontal
ground.position.y = -2;
scene.add(ground);

// Create center sphere
const sphereGeometry = new THREE.SphereGeometry(2, 64, 64);
const sphereMaterial = new THREE.MeshStandardMaterial({
  color: 0xffffff,
  roughness: 0.3,
  metalness: 0.7,
});
const sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
sphere.position.set(0, 0, 0);
scene.add(sphere);

// Create surrounding cubes to show light distribution
const cubeGeometry = new THREE.BoxGeometry(1.5, 1.5, 1.5);
const cubeMaterial = new THREE.MeshStandardMaterial({
  color: 0x4ecdc4,
  roughness: 0.5,
  metalness: 0.3,
});

const cubes = [];
const cubePositions = [
  [-6, -0.5, 0], // Left
  [6, -0.5, 0], // Right
  [0, -0.5, 6], // Front
];

cubePositions.forEach((pos) => {
  const cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
  cube.position.set(pos[0], pos[1], pos[2]);
  cubes.push(cube);
  scene.add(cube);
});

// Add a torus for variety
const torusGeometry = new THREE.TorusGeometry(1.5, 0.5, 16, 100);
const torusMaterial = new THREE.MeshStandardMaterial({
  color: 0xff6b6b,
  roughness: 0.4,
  metalness: 0.6,
});
const torus = new THREE.Mesh(torusGeometry, torusMaterial);
torus.position.set(0, 5, 0);
scene.add(torus);

Step 3: Creating All Light Types

Now let's create each of the six light types with their helpers!

// ============================================
// 1. AMBIENT LIGHT
// Provides overall base illumination, no direction
// Does not cast shadows
// Use case: Base lighting so nothing is completely black.
// Never use alone, combine with directional lights.
// Performance: Very cheap, no calculations needed.

// No helper for ambient light (it's everywhere equally)
// ============================================
const ambientLight = new THREE.AmbientLight(
  0xffffff, // White light
  0.3 // Low intensity
);
scene.add(ambientLight);

// ============================================
// 2. DIRECTIONAL LIGHT
// Parallel rays like sunlight, illuminates from a direction
// Use case: Outdoor scenes (sun/moon), main key light.
// All rays are parallel regardless of distance.
// Performance: Cheap, good for primary light source.
// ============================================
const directionalLight = new THREE.DirectionalLight(
  0xffffff, // White light
  1.0 // Full intensity
);
directionalLight.position.set(5, 10, 5);
scene.add(directionalLight);

// Helper to visualize light direction
const directionalHelper = new THREE.DirectionalLightHelper(
  directionalLight,
  2 // Helper size
);
scene.add(directionalHelper);

// ============================================
// 3. POINT LIGHT
// Radiates light in all directions from a point (like a light bulb)
// Use case: Light bulbs, lamps, candles, explosions.
// Light diminishes with distance (uses distance and decay).
// Performance: Medium cost, use sparingly for many lights.
// ============================================
const pointLight = new THREE.PointLight(
  0xff00ff, // Magenta color
  1.0, // Intensity
  50, // Distance (light fades to 0 at this distance)
  2 // Decay (how fast light fades, 2 = realistic)
);
pointLight.position.set(-8, 3, 0);
scene.add(pointLight);

// Helper to visualize light position and range
const pointHelper = new THREE.PointLightHelper(
  pointLight,
  0.5 // Helper sphere size
);
scene.add(pointHelper);

// ============================================
// 4. SPOT LIGHT
// Cone of light from a point (like a flashlight or stage light)
// Use case: Flashlights, stage spotlights, car headlights.
// Creates dramatic focused lighting with soft edges.
// Performance: Most expensive, use carefully.
// ============================================
const spotLight = new THREE.SpotLight(
  0x00ffff, // Cyan color
  1.0, // Intensity
  30, // Distance
  Math.PI / 10, // Angle (cone width in radians)
  0.5, // Penumbra (softness of edge, 0-1)
  2 // Decay
);
spotLight.position.set(-6, 10, 0);
spotLight.target.position.set(0, 0, 0); // Point at center
scene.add(spotLight);
scene.add(spotLight.target); // Target must be in scene

// Helper to visualize cone
const spotHelper = new THREE.SpotLightHelper(spotLight);
scene.add(spotHelper);

// ============================================
// 5. HEMISPHERE LIGHT
// Sky/ground ambient lighting (different colors from top/bottom)
// Use case: Outdoor scenes with sky lighting, subtle ambient variation.
// Creates natural-looking ambient from above (sky) and below (ground bounce).
// Performance: Cheap, great alternative to plain ambient light.
// ============================================
const hemisphereLight = new THREE.HemisphereLight(
  0x0066ff, // Sky color (blue)
  0xff6600, // Ground color (orange)
  0.5 // Intensity
);
hemisphereLight.position.set(0, 10, 0);
scene.add(hemisphereLight);

// Helper shows sky and ground colors
const hemisphereHelper = new THREE.HemisphereLightHelper(
  hemisphereLight,
  2 // Helper size
);
scene.add(hemisphereHelper);

// Store references for toggling
const helpers = {
  directional: directionalHelper,
  point: pointHelper,
  spot: spotHelper,
  hemisphere: hemisphereHelper,
};

// Initially hide some lights to avoid overwhelming the scene
hemisphereLight.visible = false;
hemisphereHelper.visible = false;

Step 4: Interactive Controls

Let's wire up all the controls to adjust lights in real-time:

// Ambient Light Controls
const ambientToggle = document.getElementById("ambientToggle");
const ambientSlider = document.getElementById("ambientSlider");
const ambientIntensityDisplay = document.getElementById("ambientIntensity");

ambientToggle.addEventListener("change", (e) => {
  ambientLight.visible = e.target.checked;
});

ambientSlider.addEventListener("input", (e) => {
  const value = parseFloat(e.target.value);
  ambientLight.intensity = value;
  ambientIntensityDisplay.textContent = value.toFixed(1);
});

// Directional Light Controls
const directionalToggle = document.getElementById("directionalToggle");
const directionalSlider = document.getElementById("directionalSlider");
const directionalIntensityDisplay = document.getElementById(
  "directionalIntensity"
);

directionalToggle.addEventListener("change", (e) => {
  directionalLight.visible = e.target.checked;
  directionalHelper.visible = e.target.checked;
});

directionalSlider.addEventListener("input", (e) => {
  const value = parseFloat(e.target.value);
  directionalLight.intensity = value;
  directionalIntensityDisplay.textContent = value.toFixed(1);
});

// Point Light Controls
const pointToggle = document.getElementById("pointToggle");
const pointSlider = document.getElementById("pointSlider");
const pointIntensityDisplay = document.getElementById("pointIntensity");

pointToggle.addEventListener("change", (e) => {
  pointLight.visible = e.target.checked;
  pointHelper.visible = e.target.checked;
});

pointSlider.addEventListener("input", (e) => {
  const value = parseFloat(e.target.value);
  pointLight.intensity = value;
  pointIntensityDisplay.textContent = value.toFixed(1);
});

// Spot Light Controls
const spotToggle = document.getElementById("spotToggle");
const spotSlider = document.getElementById("spotSlider");
const spotAngleSlider = document.getElementById("spotAngleSlider");
const spotIntensityDisplay = document.getElementById("spotIntensity");
const spotAngleDisplay = document.getElementById("spotAngle");

spotToggle.addEventListener("change", (e) => {
  spotLight.visible = e.target.checked;
  spotHelper.visible = e.target.checked;
});

spotSlider.addEventListener("input", (e) => {
  const value = parseFloat(e.target.value);
  spotLight.intensity = value;
  spotIntensityDisplay.textContent = value.toFixed(1);
});

spotAngleSlider.addEventListener("input", (e) => {
  const value = parseFloat(e.target.value);
  spotLight.angle = value;
  spotAngleDisplay.textContent = value.toFixed(2);
});

// Hemisphere Light Controls
const hemisphereToggle = document.getElementById("hemisphereToggle");
const hemisphereSlider = document.getElementById("hemisphereSlider");
const hemisphereIntensityDisplay = document.getElementById(
  "hemisphereIntensity"
);

hemisphereToggle.addEventListener("change", (e) => {
  hemisphereLight.visible = e.target.checked;
  hemisphereHelper.visible = e.target.checked;
});

hemisphereSlider.addEventListener("input", (e) => {
  const value = parseFloat(e.target.value);
  hemisphereLight.intensity = value;
  hemisphereIntensityDisplay.textContent = value.toFixed(1);
});

// Helpers Toggle
const helpersToggle = document.getElementById("helpersToggle");
helpersToggle.addEventListener("change", (e) => {
  const visible = e.target.checked;
  Object.values(helpers).forEach((helper) => {
    // Only show helper if its light is also visible
    const lightVisible = helper.light ? helper.light.visible : true;
    helper.visible = visible && lightVisible;
  });
});

Step 5: Renderer and Animation

// Renderer setup
const renderer = new THREE.WebGLRenderer({
  canvas: canvas,
  antialias: true,
});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);

// Animation loop
function animate() {
  requestAnimationFrame(animate);

  const time = Date.now() * 0.001;

  // Rotate center sphere
  sphere.rotation.y = time * 0.3;

  // Rotate torus
  torus.rotation.x = time * 0.5;
  torus.rotation.y = time * 0.05;

  // Gently bob cubes up and down
  cubes.forEach((cube, index) => {
    cube.position.y = -0.5 + Math.sin(time + index) * 0.3;
    cube.rotation.y = time * 0.5;
  });

  // Animate point light in a circle
  pointLight.position.x = Math.cos(time * 0.5) * 8;
  pointLight.position.z = Math.sin(time * 0.5) * 8;

  // Update helpers
  if (spotHelper.visible) spotHelper.update();
  if (directionalHelper.visible) directionalHelper.update();

  renderer.render(scene, camera);
}

animate();

// Handle window resize
window.addEventListener("resize", () => {
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();
  renderer.setSize(window.innerWidth, window.innerHeight);
});

Understanding Light Properties

Common Properties (Most Lights)

Colour - The colour of the light

light.color = new THREE.Color(0xff0000); // Red light

intensity - How bright the light is

light.intensity = 1.5; // 150% brightness

Distance-Based Properties (Point & Spot Lights)

distance - Maximum range of the light (0 = infinite)

pointLight.distance = 50; // Light fades to 0 at 50 units

decay - How quickly light diminishes with distance

pointLight.decay = 2; // Physically accurate (inverse square law)
// 1 = linear falloff
// 2 = realistic falloff (default)

Spot Light Specific

angle - Width of the light cone (in radians)

spotLight.angle = Math.PI / 6; // 30 degrees

penumbra - Softness of the cone edge (0-1)

spotLight.penumbra = 0.5; // 50% soft edge
// 0 = hard edge
// 1 = very soft edge

target - What the spotlight points at

spotLight.target.position.set(0, 0, 0);
scene.add(spotLight.target); // Must add target to scene!

Hemisphere Light Specific

groundColor - Colour of light from below

hemisphereLight.groundColor = new THREE.Color(0x080820);

When to Use Each Light Type

AmbientLight

Performance: ⚡⚡⚡⚡⚡ (Cheapest)
When to use:

  • Base lighting, so objects aren't completely black

  • Fill light to soften harsh shadows

  • Quick prototyping before adding complex lighting

Best practices:

  • Keep intensity low (0.2-0.4)

  • Never use as the only light source

  • Combine with directional lights

Real-world equivalent: Overcast day, diffused light everywhere

DirectionalLight

Performance: ⚡⚡⚡⚡ (Very Cheap)
When to use:

  • Outdoor scenes (sun or moon)

  • Main key light in any scene

  • When you need parallel light rays

Best practices:

  • Position far from scene center

  • Use as primary light source

  • Great for casting consistent shadows

Real-world equivalent: Sunlight, moonlight

PointLight

Performance: ⚡⚡⚡ (Medium)
When to use:

  • Light bulbs, lamps, candles

  • Explosions or fire effects

  • Small localized light sources

Best practices:

  • Set appropriate distance and decay

  • Don't use too many (expensive with many)

  • Great for accent lighting

Real-world equivalent: Light bulb, candle, torch

SpotLight

Performance: ⚡⚡ (Expensive)
When to use:

  • Flashlights, car headlights

  • Stage lighting, theatrical effects

  • Drawing attention to specific objects

Best practices:

  • Use sparingly (most expensive)

  • Adjust angle and penumbra for desired effect

  • Remember to add target to scene

Real-world equivalent: Flashlight, stage spotlight, car headlight

HemisphereLight

Performance: ⚡⚡⚡⚡ (Cheap)
When to use:

  • Outdoor scenes with sky

  • Natural-looking ambient lighting

  • When you want colour variation (sky vs ground)

Best practices:

  • Better than plain Ambient Light for realism

  • Use sky and ground colours that make sense

  • Great for outdoor environments

Real-world equivalent: Natural sky lighting with ground bounce

RectAreaLight

Performance: ⚡ (Most Expensive)
When to use:

  • Windows or doors letting in light

  • TV screens, monitors, LED panels

  • Soft box photography lighting

  • When you need realistic area lighting

Best practices:

  • Only works with Standard/Physical materials!

  • Use very sparingly (heavy performance cost)

  • Great for hero objects or key scenes

Real-world equivalent: Window, LED panel, soft box light

Performance Tips and Light Combinations

Performance Hierarchy (Cheapest to Most Expensive)

  1. AmbientLight / HemisphereLight - No calculations

  2. DirectionalLight - Simple directional calculations

  3. PointLight - Distance-based calculations

  4. SpotLight - Cone + distance calculations

  5. RectAreaLight - Complex area calculations

Basic Scene (Best Performance)

const ambient = new THREE.AmbientLight(0xffffff, 0.4);
const directional = new THREE.DirectionalLight(0xffffff, 1.0);

Outdoor Scene

const hemisphere = new THREE.HemisphereLight(0x87CEEB, 0x8B4513, 0.6);
const directional = new THREE.DirectionalLight(0xffffff, 0.8);

Indoor Scene

const ambient = new THREE.AmbientLight(0xffffff, 0.3);
const pointLight1 = new THREE.PointLight(0xffffee, 1.0, 20);
const pointLight2 = new THREE.PointLight(0xffffee, 0.8, 15);

Dramatic/Cinematic

const ambient = new THREE.AmbientLight(0xffffff, 0.2);
const spot1 = new THREE.SpotLight(0xffffff, 1.5); // Key light
const spot2 = new THREE.SpotLight(0x4444ff, 0.5); // Rim light

High-Quality Product Visualization

const ambient = new THREE.AmbientLight(0xffffff, 0.3);
const rectArea = new THREE.RectAreaLight(0xffffff, 2.0, 10, 10);
const directional = new THREE.DirectionalLight(0xffffff, 0.8);

What I Learned

1. Lighting Makes or Breaks a Scene

The same geometry and materials look entirely different under different lighting. Good lighting is often more important than complex geometry!

2. Combine Multiple Lights

Professional scenes rarely use just one light. The "three-point lighting" technique from photography (key, fill, rim) applies to 3D too!

3. Light Helpers Are Essential

Always use light helpers when setting up your scene. They show exactly where lights are positioned and what they're illuminating. Turn them off for final render.

4. Performance Matters

More lights = worse performance. Start with cheap lights (Ambient, Directional) and add expensive ones (Spot, RectArea) only where needed.

5. Distance and Decay Are Critical

For Point and Spot lights, setting appropriate distance and decay values is crucial. A decay of 2 is physically accurate and usually looks best.

6. RectAreaLight Limitations

RectAreaLight only works with MeshStandardMaterial and MeshPhysicalMaterial. If your objects look unlit, check your material type!

7. Colour Temperature Matters

Real lights have colour! Sunlight is slightly yellow (0xffffee), fluorescent lights are cooler (0xeeeeff), candlelight is warm orange (0xff8844). Adding subtle colour makes scenes more realistic.

8. Light Position Is Key

The same light at different positions creates entirely different moods. Experiment with positioning lights high, low, front, back, and sides.

9. Hemisphere Light Is Underrated

Instead of plain AmbientLight, HemisphereLight adds subtle colour variation from sky and ground that makes outdoor scenes look much more natural.

10. Start Simple, Then Add

Begin with just ambient + directional light. Once that looks good, add accent lights (point, spot) for drama and interest.

Common Lighting Recipes

Here are some lighting setups I found useful:

Sunny Day

const hemisphere = new THREE.HemisphereLight(0x87CEEB, 0x8B7355, 0.6);
const sun = new THREE.DirectionalLight(0xffffee, 1.0);
sun.position.set(10, 20, 10);

Overcast Day

const ambient = new THREE.AmbientLight(0xcccccc, 0.8);
const directional = new THREE.DirectionalLight(0xffffff, 0.3);

Night Scene with Moon

const ambient = new THREE.AmbientLight(0x111144, 0.2);
const moon = new THREE.DirectionalLight(0xaaaaff, 0.5);
moon.position.set(-10, 20, 5);

Indoor Warm Lighting

const ambient = new THREE.AmbientLight(0x332211, 0.3);
const lamp1 = new THREE.PointLight(0xffaa66, 1.0, 15, 2);
const lamp2 = new THREE.PointLight(0xffaa66, 0.8, 12, 2);

Studio/Gallery Lighting

const ambient = new THREE.AmbientLight(0xffffff, 0.4);
const key = new THREE.SpotLight(0xffffff, 1.5, 30, Math.PI/6, 0.3);
const fill = new THREE.SpotLight(0xffffff, 0.5, 25, Math.PI/4, 0.5);
const rim = new THREE.DirectionalLight(0x8888ff, 0.6);

Debugging Lighting Issues

If your scene looks wrong, check these:

Objects Are Completely Black

  • Are lights added to the scene?

  • Do materials need lights? (Basic doesn't, others do)

  • Is ambient light intensity too low?

Lights Don't Seem to Work

  • Check light visibility (light.visible = true)

  • Verify light helpers are showing correct positions

  • For SpotLight, did you add the target to scene?

  • For RectAreaLight, are you using Standard/Physical material?

Scene Is Too Dark/Bright

  • Adjust ambient light intensity (start around 0.3)

  • Change directional light intensity (start around 1.0)

  • Check camera exposure (some renderers support this)

Point/Spot Lights Fade Too Fast

  • Increase distance property

  • Check decay value (2 is realistic but you can adjust)

  • Increase intensity

Next Steps

Now that I understand lighting, here's what I'm planning to explore:

  • Adding shadows to lights for more realism

  • Using textures on materials

  • Environment maps for realistic reflections

  • Post-processing effects (bloom, ambient occlusion)

  • Combining great lighting with textured materials

Try experimenting with:

  • Different light colour combinations

  • Three-point lighting setups key (directional), fill (ambient) and rim (spot light)

  • Animating light positions for dynamic effects

  • Adjusting intensity to create different moods

  • Combining lights to simulate real environments

Understanding lighting is a game-changer. Happy illuminating! 💡