Three.js - Stats



Stats

Statistics play an important role in large-scale applications. Suppose you are creating a larger Three.js project with many objects and animations. It is good to monitor the performance of the code like fps (frames per second), memory allocated, etc. The creator of Three.js also created a small JavaScript library, Stats.js, to monitor the rendering.

Installation

Like any other library, you can simply add it to your project in any of the three ways, as discussed previously.

You can download it from GitHub and import it to your HTML page. Or you can add the CDN link to the HTML page.

<script src="https://cdnjs.cloudflare.com/ajax/libs/stats.js/r17/Stats.min.js"></script>

If you're using a node app, install the npm package and import it into your project.

npm install stats.js

or

yarn add stats.js
import * as stats from 'stats.js'

Functionality

You can monitor the following properties using Stats.js.

  • FPS − Frames rendered in the last second (0).
  • MS − Milliseconds needed to render a frame (1).
  • MB − MBytes of allocated memory (2) (Run Chrome with --enable-precise-memoryinfo)
  • CUSTOM − you can define the thing you want to monitor—user-defined panel support (3).

How does it work?

If you're monitoring the frame rate, it counts how often the update was called within the last second and shows that value. If you're tracking the render time, it just shows the time between calls and the update function.

Usage

You can add this functionality to your code in a few simple steps.

Create the stats object and add it to the HTML page using the DOM.

const stats = new Stats()
stats.showPanel(1) // 0: fps, 1: ms, 2: mb, 3+: custom
document.body.appendChild(stats.dom)

Note − You can show the panel you want using showPanel(). By default, Stats.js displays the fps panel, and you can toggle between panels by clicking on the panel.

Select the code you want to monitor.

stats.begin()
// monitored code goes here
// in our case the render function
renderer.render(scene, camera)
stats.end()

If you are using animations, you should update the stats whenever the frame is rendered.

function animate() {
   requestAnimationFrame(render)
   // our animations
   renderer.render(scene, camera)
   stats.update()
}

Example

Check this working example.

stats.js

<!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 - Stats.js</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>
      <script src="http://mrdoob.github.io/stats.js/build/stats.min.js"></script>
   </head>
   <body>
      <div id="threejs-container"></div>
      <script type="module">
         // Adding stats panel to moniter application statistics
         const gui = new dat.GUI()
         const stats = new Stats()
         //stats.showPanel(0)
         //stats.showPanel(1)
         document.body.appendChild(stats.dom)
         // width, height
         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(30, width / height, 0.1, 100)
         camera.position.set(0, 0, 10)
         // cube
         const geometry = new THREE.BoxGeometry(1, 1, 1)
         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)
            stats.update()
         }
         // rendering the scene
         const container = document.querySelector('#threejs-container')
         container.append(renderer.domElement)
         stats.begin()
         renderer.render(scene, camera)
         stats.end()
         animate()
      </script>
   </body>
</html>

Output

Show Panel
threejs_debug_and_stats.htm
Advertisements