Three.js - Responsive Design



On resizing the screen, you can observe that the scene is not responsive. Making a web page responsive generally refers to the page displaying well on different sized displays from desktops to tablets to phones. In this chapter, you can see how to solve some fundamental problems of your Three.js app.

Automatically resize the output when the browser size changes

When you resize the browser, we have to notify the Three.js to know how wide the <canvas> element should be. For the camera, we need to update the aspect property, which holds the aspect ratio of the screen, and for the renderer, we need to change its size.

window.addEventListener('resize', () => {
   // update display width and height
   width = window.innerWidth
   height = window.innerHeight
   // update camera aspect
   camera.aspect = width / height
   camera.updateProjectionMatrix()
   // update renderer
   renderer.setSize(width, height)
   renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))
   renderer.render(scene, camera)
})

Example

The above code gives responsiveness to your Three.js project.

resize-browser.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 – Resizing browser</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="threejs-container"></div>
      <script type="module">
         // Adding responsiveness for Three.js
         // sizes
         let width = window.innerWidth
         let height = window.innerHeight
         const gui = new dat.GUI()
         // scene
         const scene = new THREE.Scene()
         scene.background = new THREE.Color(0x262626)
         // camera
         const camera = new THREE.PerspectiveCamera(45, width / height, 0.1, 100)
         camera.position.set(0, 0, 10)
         // cube
         const geometry = new THREE.BoxGeometry(2, 2, 2)
         const material = new THREE.MeshBasicMaterial({
            color: 0xffffff,
            wireframe: true
         })
         const cube = new THREE.Mesh(geometry, material)
         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(width, height)
         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('#threejs-container')
         container.append(renderer.domElement)
         renderer.render(scene, camera)
         animate()
      </script>
   </body>
</html>

Output

When you execute the code, it will produce the following output −

Now, resize the browser. Due to the responsive design, the object will always reposition itself at the center of the browser.

Anti-aliasing

The aliasing effect is the appearance of jagged edges or "jaggies" (also known as stair-stepped lines) on edges and objects (rendered using pixels).

Anti Aliasing

Example

antialiasing.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 - Anti-aliasing</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="threejs-container"></div>
      <script type="module">
         // Adding anti-aliasing to Three.js app for removing jaggies
         // sizes
         let width = window.innerWidth
         let height = window.innerHeight
         const gui = new dat.GUI()
         // scene
         const scene = new THREE.Scene()
         scene.background = new THREE.Color(0x262626)
         // camera
         const camera = new THREE.PerspectiveCamera(45, width / height, 0.1, 100)
         camera.position.set(0, 0, 10)
         // cube
         const geometry = new THREE.BoxGeometry(2, 2, 2)
         const material = new THREE.MeshBasicMaterial({
            color: 0xffffff,
            wireframe: true
         })
         const cube = new THREE.Mesh(geometry, material)
         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 - anti-aliasing
         const renderer = new THREE.WebGLRenderer({ antialias: true })
         renderer.physicallyCorrectLights = true
         renderer.setSize(width, height)
         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('#threejs-container')
         container.append(renderer.domElement)
         renderer.render(scene, camera)
         animate()
      </script>
   </body>
</html>

Output

Aliasing in our Hello cube app looks like this.

Web Renderer

We can turn on anti-aliasing by setting antialias property of the WebGLRenderer to true. By default, it is false. Here, we set the antialias parameter to true −

const renderer = new WebGLRenderer({ antialias: true })
renderer.physicallyCorrectLights = true

After antialiasing, it looks smooth without jaggies like the one below.

Without Jaggies

The property physicallyCorrectLights tells Three.js whether to use physically correct lighting mode. Default is false. Setting it to true helps increase the detail of the object.

Advertisements