”;
Lights make the objects visible, similarly, in Three.js THREE.Light lights up the scene and makes some things visible. Not all materials are affected by lighting. The MeshBasicMaterial and MeshNormalMaterial are self-illuminating, so they don”t need lighting 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 lights in Three.js.
Every light has color and intensity properties.
-
color − (optional) hexadecimal color of the light. Default is 0xffffff (white).
-
intensity − (optional) numeric value of the light”s strength/intensity. Default is 1.
Casting Shadows
The light 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 functionality. It uses Shadow mapping, a technique specific to WebGL, performed directly on the GPU.
renderer.shadowMapEnabled = true
The above line of code tells the renderer to cast shadows in the scene.
Note − Three.js, by default, uses shadow maps. Shadow map works for light that casts shadows.
The scene renders all objects marked to cast shadows from the point of view of the light.
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 light. 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 antialias 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 light. The next step is to set up the shadow-related properties.
light.castShadow = true light.shadow.camera.near = 10 light.shadow.camera.far = 100 light.shadow.camera.left = -50 light.shadow.camera.right = 50 light.shadow.camera.top = 50 light.shadow.camera.bottom = -50
The first property, castShadow, tells Three.js that this light 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-like 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, BlinkMacSystemFont, ''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/libs/three.js/r128/three.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.7.7/dat.gui.js"></script> </head> <body> <div id="container"></div> <script type="module"> // Adding directional light to the scene // The lights falls from the light only in one direction. // You can see the position of light 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() // lights const ambientLight = new THREE.AmbientLight(0xffffff, 0.5) scene.add(ambientLight) const light = new THREE.DirectionalLight() light.position.set(2.5, 2, 2) light.castShadow = true light.shadow.mapSize.width = 512 light.shadow.mapSize.height = 512 light.shadow.camera.near = 0.5 light.shadow.camera.far = 100 scene.add(light) const helper = new THREE.DirectionalLightHelper(light) scene.add(helper) // light controls const lightColor = { color: light.color.getHex() } const lightFolder = gui.addFolder(''Directional Light'') lightFolder.addColor(lightColor, ''color'').onChange(() => { light.color.set(lightColor.color) }) lightFolder.add(light, ''intensity'', 0, 1, 0.01) lightFolder.open() const directionalLightFolder = gui.addFolder(''Position of Light'') directionalLightFolder.add(light.position, ''x'', -10, 10, 0.1) directionalLightFolder.add(light.position, ''y'', -10, 10, 0.1) directionalLightFolder.add(light.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 light, which illuminates the whole scene equally.
|
2 |
Directional light comes from a specific point and is emitted directly from far away to the target.
|
3 |
It is another kind of light that comes from a specific direction in the shape of the cone.
|
4 |
The point light is a light source that emits light in all directions from a single point.
|
5 |
It is a special light for creating natural lighting.
|
”;