Directional Shadow Visualizer

Inspect directional light shadow camera and map size.

What this code does

- DirectionalLight: parallel light rays casting shadows from infinite distance.
- Shadow Camera: orthographic camera that defines shadow casting area.
- CameraHelper: wireframe visualization of the shadow camera frustum.
- PCF Soft Shadows: renderer.shadowMap.type = PCFSoftShadowMap for soft edges.
- Shadow Bias: prevents shadow acne artifacts on surfaces.
- Interactive Controls: adjust shadow bias, map resolution, and frustum visibility.

JavaScript (plain)

import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'

const scene = new THREE.Scene()
const camera = new THREE.PerspectiveCamera(60, width / height, 0.1, 100)
camera.position.set(3, 3, 5)

const renderer = new THREE.WebGLRenderer({ antialias: true })
renderer.shadowMap.enabled = true
renderer.shadowMap.type = THREE.PCFSoftShadowMap
renderer.setSize(width, height)

document.querySelector('#app').appendChild(renderer.domElement)

const controls = new OrbitControls(camera, renderer.domElement)
controls.target.set(0, 0.5, 0)
controls.update()

const plane = new THREE.Mesh(
  new THREE.PlaneGeometry(12, 12),
  new THREE.MeshStandardMaterial({ color: 0x141414 })
)
plane.rotation.x = -Math.PI / 2
plane.receiveShadow = true
scene.add(plane)

const box = new THREE.Mesh(
  new THREE.BoxGeometry(1, 1, 1),
  new THREE.MeshStandardMaterial({ color: 0x22aaff })
)
box.position.set(0, 0.5, 0)
box.castShadow = true
scene.add(box)

const light = new THREE.DirectionalLight(0xffffff, 1)
light.position.set(3, 5, 2)
light.castShadow = true
scene.add(light)

const cam = light.shadow.camera
cam.near = 0.5
cam.far = 20
cam.left = -4
cam.right = 4
cam.top = 4
cam.bottom = -4
light.shadow.bias = -0.0005
light.shadow.mapSize.set(1024, 1024)

const shadowHelper = new THREE.CameraHelper(light.shadow.camera)
scene.add(shadowHelper)

function animate() {
  requestAnimationFrame(animate)
  box.rotation.y += 0.01
  shadowHelper.update()
  controls.update()
  renderer.render(scene, camera)
}
animate()