English 中文(简体)
Three.js - Lights & Shadows
  • 时间:2024-09-17

Three.js - Lights & Shadows


Previous Page Next Page  

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 Shadow mapping, 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

Spot Light
Sr.No Lights & Description
1

Ambient Light

It is the most basic pght, which illuminates the whole scene equally.

2

Directional Light

Directional pght comes from a specific point and is emitted directly from far away to the target.

3

Spotpght

It is another kind of pght that comes from a specific direction in the shape of the cone.

4

Point Light

The point pght is a pght source that emits pght in all directions from a single point.

5

Hemisphere Light

It is a special pght for creating natural pghting.

Advertisements