Now that we've explored the fundamental concepts of lighting and shadows in Three.js, let's bring it all together with a practical example. We'll create a simple scene with a few objects, experiment with different light sources, and then introduce shadows to add depth and realism. This hands-on approach will solidify your understanding and give you a solid foundation for building more complex 3D experiences.
Our goal is to create a scene that demonstrates the interplay between light, material, and shadows. We'll set up a basic environment and then gradually introduce lighting elements. The following steps outline the process, from initialization to adding the final touches.
First, let's set up our basic Three.js scene. This includes creating a scene, a camera, and a renderer. We'll also add a simple ground plane and a few geometric shapes to cast shadows upon.
import * as THREE from 'three';
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
const renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
// Add a ground plane
const groundGeometry = new THREE.PlaneGeometry( 10, 10 );
const groundMaterial = new THREE.MeshStandardMaterial( { color: 0x808080, side: THREE.DoubleSide } );
const ground = new THREE.Mesh( groundGeometry, groundMaterial );
ground.rotation.x = -Math.PI / 2;
scene.add( ground );
// Add some objects
const boxGeometry = new THREE.BoxGeometry( 1, 1, 1 );
const sphereGeometry = new THREE.SphereGeometry( 0.7, 32, 32 );
const redMaterial = new THREE.MeshStandardMaterial( { color: 0xff0000 } );
const blueMaterial = new THREE.MeshStandardMaterial( { color: 0x0000ff } );
const box = new THREE.Mesh( boxGeometry, redMaterial );
box.position.set( -2, 0.5, 0 );
scene.add( box );
const sphere = new THREE.Mesh( sphereGeometry, blueMaterial );
sphere.position.set( 2, 0.7, 0 );
scene.add( sphere );
camera.position.z = 5;
function animate() {
requestAnimationFrame( animate );
renderer.render( scene, camera );
}Next, we'll introduce a light source. For shadows to be cast, we need a light that can project them. The DirectionalLight is a good choice for simulating sunlight, which casts parallel rays. Remember to enable shadows on the renderer.
renderer.shadowMap.enabled = true;
const directionalLight = new THREE.DirectionalLight( 0xffffff, 0.8 );
directionalLight.position.set( 5, 5, 5 );
directionalLight.castShadow = true;
scene.add( directionalLight );For shadows to be cast and received, both the light source and the objects involved need to be configured correctly. The castShadow property should be set to true for the light and for any meshes that should cast or receive shadows. We also need to configure the shadow map for the light.
box.castShadow = true;
sphere.castShadow = true;
ground.receiveShadow = true;
directionalLight.shadow.mapSize.width = 1024;
directionalLight.shadow.mapSize.height = 1024;
directionalLight.shadow.camera.near = 0.5;
directionalLight.shadow.camera.far = 50;
directionalLight.shadow.camera.left = -10;
directionalLight.shadow.camera.right = 10;
directionalLight.shadow.camera.top = 10;
directionalLight.shadow.camera.bottom = -10;Finally, we'll start the animation loop to render our scene. This will display the objects, the directional light, and the shadows they cast on the ground. You should see the red box and blue sphere casting distinct shadows.
animate();This example demonstrates the core principles of setting up lighting and shadows in Three.js. By adjusting the light type, position, color, intensity, and shadow map properties, you can achieve a wide range of visual effects. Experiment with different light sources like AmbientLight, PointLight, and SpotLight to see how they affect the scene and shadow rendering.
graph TD;
A[Initialize Scene, Camera, Renderer] --> B{Add Objects};
B --> C[Add Ground Plane];
B --> D[Add Movable Objects];
C --> E[Configure Ground to Receive Shadows];
D --> F[Configure Objects to Cast Shadows];
G[Add Light Source] --> H{Configure Light};
H --> I[Enable Shadow Mapping on Renderer];
H --> J[Set Light to Cast Shadows];
H --> K[Configure Light's Shadow Map Properties];
E & F & J --> L[Render Scene];
L --> M[Animate Loop];