Displaying Shadows and Softening Shadow Edges in Three.js[r145]
This article explains in detail how to display and blur shadows, introducing key points for creating realistic 3D scenes.
By enabling shadow maps in Three.js, you can render shadows.
You can also soften the edges of shadows.
- Enable shadow maps in the renderer
- renderer.shadowMap.enabled = true;
- Enable the light to cast shadows
- light.castShadow = true;
- Enable the mesh to cast shadows
- mesh.castShadow = true;
- Enable the mesh to receive shadows
- mesh.receiveShadow = true;
- Set the blur strength for shadow edges in the light
- light.shadow.radius = 4;
Left mouse drag rotates, right mouse drag moves the camera, and the wheel zooms in/out.
Swipe to rotate, drag with two fingers on the screen to move the camera, and pinch in/out to zoom.
Source Code
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0,user-scalable=yes">
<script src="./js/three.min.js"></script>
<script src="./js/OrbitControls.js"></script>
<script>
var scene,camera;
var main = function () {
// Get the target canvas and retrieve width and height
let can=document.getElementById('can');
let w = parseInt(can.style.width); // get width
let h = parseInt(can.style.height); // get height
// ■ Scene
scene = new THREE.Scene();
// ■ Camera
// THREE.PerspectiveCamera( field of view (degrees), aspect ratio, near clipping plane, far clipping plane );
camera = new THREE.PerspectiveCamera(20, w/h, 0.1, 10000);
camera.position.set(-50, 100, 150); // set camera position
//camera.rotation.set(0,0,0); // set camera angle to (0,0,0)
camera.lookAt(new THREE.Vector3(0, 0, 0)); // set camera direction to (0,0,0)
scene.add(camera); // add camera to the scene
// ■ Renderer
renderer = new THREE.WebGLRenderer({canvas:can, antialias: true}); // enable antialiasing
renderer.setSize(w, h);
// Enable shadow maps
renderer.shadowMap.enabled = true;
renderer.setClearColor(0x000000, 1); // set background color
// ■ Lighting
// Ambient light (applied to all objects from all directions, prevents completely black areas)
var AmbientLight=new THREE.AmbientLight(0xffffff,0.4);
scene.add( AmbientLight ); // add ambient light to the scene
// Spotlight (color, intensity, distance, angle)
const spotLight=new THREE.SpotLight(0xffffff, 2,1000,Math.PI/8);
spotLight.position.set(100,400,300);
spotLight.target.position.set(0,0,0);
spotLight.castShadow=true; // enable shadow casting
spotLight.shadow.mapSize.width = 1024; // default is 512; larger size makes shadows smoother
spotLight.shadow.mapSize.height = 1024; // default is 512; larger size makes shadows smoother
spotLight.shadow.radius=4; // set blur strength for shadow edges
scene.add(spotLight);
scene.add(spotLight.target);
// ■ Lambert material (non-glossy material affected by light sources)
let material=new THREE.MeshLambertMaterial({color:0x6699FF});
// ■ Box geometry (width, height, depth)
let boxGeometry=new THREE.BoxGeometry(40, 30, 20);
// ■ Create mesh from box geometry and Lambert material
let mesh=new THREE.Mesh(boxGeometry, material);
mesh.castShadow=true; // allow this mesh to cast shadows
scene.add(mesh); // add mesh to the scene
// ■ Plane geometry (width, height)
let planeGeometry=new THREE.PlaneGeometry(500,500);
// ■ Create mesh from plane geometry and Lambert material
let planeMesh=new THREE.Mesh(planeGeometry, material);
planeMesh.rotation.x=-Math.PI/2; // rotate -90 degrees around x-axis
planeMesh.position.set(0,-40,0); // move position
planeMesh.receiveShadow=true; // allow this mesh to receive shadows
scene.add(planeMesh);
// ■ Create OrbitControls (camera moves with mouse drag, wheel, etc.)
const controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.target.set(0,0,0);
controls.update();
renderLoop();
}
function renderLoop () {
requestAnimationFrame(renderLoop);
renderer.render(scene, camera);
}
window.addEventListener('DOMContentLoaded', main, false);
</script>
</head>
<body>
<canvas id="can" style="width:500px; height:300px;-ms-touch-action:none;touch-action:none;">
</canvas>
</body>
</html>
