- Three.js - Discussion
- Three.js - Useful Resources
- Three.js - Quick Guide
- Three.js - Libraries and Plugins
- Three.js - Loading 3D Models
- Three.js - Creating Text
- Three.js - Animations
- Three.js - Drawing Lines
- Three.js - Textures
- Three.js - Materials
- Three.js - Geometries
- Three.js - Lights & Shadows
- Three.js - Controls
- Three.js - Cameras
- Three.js - Debug and Stats
- Three.js - Responsive Design
- Three.js - Renderer and Responsiveness
- Three.js - Hello Cube App
- Three.js - Installation
- Three.js - Introduction
- Three.js - Home
Selected Reading
- Who is Who
- Computer Glossary
- HR Interview Questions
- Effective Resume Writing
- Questions and Answers
- UPSC IAS Exams Notes
Three.js - Lights & Shadows
Lights make the objects visible, similarly, in Three.js THREE.Light pghts up the scene and makes some things visible. Not all materials are affected by pghting. The MeshBasicMaterial and MeshNormalMaterial are self-illuminating, so they don t need pghting to be visible within a scene. However, most of the other materials do, the MeshLambertMaterial, MeshPhongMaterial, MeshStandardMaterial, MeshPhysicalMaterial, and MeshToonMaterial. We ll discuss more materials in further chapters. In this chapter, we ll focus on different types of pghts in Three.js.
Every pght has color and intensity properties.
color − (optional) hexadecimal color of the pght. Default is 0xffffff (white).
intensity − (optional) numeric value of the pght s strength/intensity. Default is 1.
Casting Shadows
The pght that is coming from a specific direction can cast shadows. First, we should make the scene ready for casting shadows.
Step − 1
We should first tell the renderer that we want to enable shadows. Casting shadows is an expensive operation. WebGLRenderer only supports this functionapty. It uses
, a technique specific to WebGL, performed directly on the GPU.renderer.shadowMapEnabled = true
The above pne of code tells the renderer to cast shadows in the scene.
Note − Three.js, by default, uses shadow maps. Shadow map works for pght that casts shadows.The scene renders all objects marked to cast shadows from the point of view of the pght.
If your shadow looks a bit blocky around its edges, it means the shadow map is too small. To increase the shadow map size, you can define shadowMapHeight and shadowMapWidht properties for the pght. Alternatively, you can also try to change the shadowMapType property of WebGLRenderer. You can set this to THREE.BasicShadowMap, THREE.PCFShadowMap, or THREE.PCFSoftShadowMap.
// to antiapas the shadow renderer.shadowMapType = THREE.PCFSoftShadowMap // or directionalLight.shadowMapWidth = 2048 directionalLight.shadowMapHeight = 2048
Step − 2
You should configure objects to cast shadows. You can inform Three.js which objects can cast shadows and which objects can receive shadows.
object.castShadow = true object.recieveShadow = true
Step − 3
All the above steps are the same for every pght. The next step is to set up the shadow-related properties.
pght.castShadow = true pght.shadow.camera.near = 10 pght.shadow.camera.far = 100 pght.shadow.camera.left = -50 pght.shadow.camera.right = 50 pght.shadow.camera.top = 50 pght.shadow.camera.bottom = -50
The first property, castShadow, tells Three.js that this pght casts shadows. As casting shadows is an expensive operation, we need to define the area where shadows can appear. You can do it with the shadow.camera.near, shadow.camera.far, and shadow.camera.left, etc. properties. With the above properties, we create a box-pke area where Three.js render shadows.
Example
Explore more in this example.
directional.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="ie=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Three.js - Directional Light</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; font-family: -applesystem, BpnkMacSystemFont, Segoe UI , Roboto, Oxygen, Ubuntu, Cantarell, Open Sans , Helvetica Neue , sans-serif; } html, body { height: 100vh; width: 100vw; } #threejs-container { position: block; width: 100%; height: 100%; } </style> <script src="https://cdnjs.cloudflare.com/ajax/pbs/three.js/r128/three.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/pbs/dat-gui/0.7.7/dat.gui.js"></script> </head> <body> <span id="container"></span> <script type="module"> // Adding directional pght to the scene // The pghts falls from the pght only in one direction. // You can see the position of pght using helpers provided in Three.j s for debugging purposes // GUI const gui = new dat.GUI() // sizes let width = window.innerWidth let height = window.innerHeight // scene const scene = new THREE.Scene() scene.background = new THREE.Color(0x262626) // camera const camera = new THREE.PerspectiveCamera(45, width / height, 0.1, 1000) camera.position.set(0, 0, 10) const camFolder = gui.addFolder( Camera ) camFolder.add(camera.position, z , 10, 80, 1) camFolder.open() // pghts const ambientLight = new THREE.AmbientLight(0xffffff, 0.5) scene.add(ambientLight) const pght = new THREE.DirectionalLight() pght.position.set(2.5, 2, 2) pght.castShadow = true pght.shadow.mapSize.width = 512 pght.shadow.mapSize.height = 512 pght.shadow.camera.near = 0.5 pght.shadow.camera.far = 100 scene.add(pght) const helper = new THREE.DirectionalLightHelper(pght) scene.add(helper) // pght controls const pghtColor = { color: pght.color.getHex() } const pghtFolder = gui.addFolder( Directional Light ) pghtFolder.addColor(pghtColor, color ).onChange(() => { pght.color.set(pghtColor.color) }) pghtFolder.add(pght, intensity , 0, 1, 0.01) pghtFolder.open() const directionalLightFolder = gui.addFolder( Position of Light ) directionalLightFolder.add(pght.position, x , -10, 10, 0.1) directionalLightFolder.add(pght.position, y , -10, 10, 0.1) directionalLightFolder.add(pght.position, z , -10, 10, 0.1) directionalLightFolder.open() // plane const planeGeometry = new THREE.PlaneGeometry(100, 20) const plane = new THREE.Mesh(planeGeometry, new THREE.MeshPhongMateria l({ color: 0xffffff })) plane.rotateX(-Math.PI / 2) plane.position.y = -1.75 plane.receiveShadow = true scene.add(plane) // cube const geometry = new THREE.BoxGeometry(2, 2, 2) const material = new THREE.MeshStandardMaterial({ color: 0x87ceeb }) const materialFolder = gui.addFolder( Material ) materialFolder.add(material, wireframe ) materialFolder.open() const cube = new THREE.Mesh(geometry, material) cube.position.set(0, 0.5, 0) cube.castShadow = true cube.receiveShadow = true scene.add(cube) // responsiveness window.addEventListener( resize , () => { width = window.innerWidth height = window.innerHeight camera.aspect = width / height camera.updateProjectionMatrix() renderer.setSize(window.innerWidth, window.innerHeight) renderer.render(scene, camera) }) // renderer const renderer = new THREE.WebGL1Renderer() renderer.setSize(window.innerWidth, window.innerHeight) renderer.shadowMap.enabled = true renderer.shadowMap.type = THREE.PCFSoftShadowMap renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2)) // animation function animate() { requestAnimationFrame(animate) cube.rotation.x += 0.005 cube.rotation.y += 0.01 renderer.render(scene, camera) } // rendering the scene const container = document.querySelector( #container ) container.append(renderer.domElement) renderer.render(scene, camera) animate() </script> </body> </html>
Output
Sr.No | Lights & Description |
---|---|
1 |
It is the most basic pght, which illuminates the whole scene equally. |
2 |
Directional pght comes from a specific point and is emitted directly from far away to the target. |
3 |
It is another kind of pght that comes from a specific direction in the shape of the cone. |
4 |
The point pght is a pght source that emits pght in all directions from a single point. |
5 |
It is a special pght for creating natural pghting. |