Skip to content

Stats Panel

Tip

This course was updated in 2024. For the newer content, please visit Stats Panel

Video Lecture

Stats Panel

Description

When developing a Three.js application, it is useful to understand how the performance changes as you develop your code. We can add a statistics panel to our HTML document that outlines several properties such as the frames per second and how long a section of code takes to execute.

The Stats Panel

If you click the statistics panel, it will show you some different measurements.

Stats Panel Panels

The three/examples/jsm/libs folder contains a module named stats.module that we can include in our code.

import Stats from 'three/examples/jsm/libs/stats.module'

Later on we can add it to our HTML document

const stats = Stats()
document.body.appendChild(stats.dom)

In our animation loop, we can call the stats.update() method, and it will update the statistics panel on the HTML document.

function animate() {
    ...
    stats.update()
}

Below is the client.ts how it is left at the end of the instructional video.

Note how I am using the animation loop to also update the stats panel. The Stats panel runs independently of Three.js, and you can use it in other unrelated projects if you wish. It is included in the Three.js install and features in many Three.js examples that you will find online. mrdoob (https://github.com/mrdoob), who is the founding author of Three.js also happens to be the founding author of the Stats.js panel (https://github.com/mrdoob/stats.js)

Lesson Script

./src/client/client.ts

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
import Stats from 'three/examples/jsm/libs/stats.module'

const scene = new THREE.Scene()

const camera = new THREE.PerspectiveCamera(
    75,
    window.innerWidth / window.innerHeight,
    0.1,
    1000
)
camera.position.z = 2

const renderer = new THREE.WebGLRenderer()
renderer.setSize(window.innerWidth, window.innerHeight)
document.body.appendChild(renderer.domElement)

const controls = new OrbitControls(camera, renderer.domElement)
//controls.addEventListener('change', render)

const geometry = new THREE.BoxGeometry()
const material = new THREE.MeshBasicMaterial({
    color: 0x00ff00,
    wireframe: true,
})

const cube = new THREE.Mesh(geometry, material)
scene.add(cube)

window.addEventListener('resize', onWindowResize, false)
function onWindowResize() {
    camera.aspect = window.innerWidth / window.innerHeight
    camera.updateProjectionMatrix()
    renderer.setSize(window.innerWidth, window.innerHeight)
    render()
}

const stats = new Stats()
document.body.appendChild(stats.dom)

function animate() {
    requestAnimationFrame(animate)

    cube.rotation.x += 0.01
    cube.rotation.y += 0.01

    render()

    stats.update()
}

function render() {
    renderer.render(scene, camera)
}

animate()
//render()

Boilerplate stats Branch

The course boilerplate also contains a branch including the Stats panel in case you need.

You can clone the boilerplate into a new folder somewhere and checkout the stats branch.

git clone https://github.com/Sean-Bradley/Three.js-TypeScript-Boilerplate.git ./my-custom-folder
cd my-custom-folder
git checkout stats
npm install
npm run dev

Visit http://127.0.0.1:8080/

The Stats Panel

Stats.js : https://github.com/mrdoob/stats.js

Troubleshooting

Error : This module is declared with 'export =', and can only be used with a default import when using the 'allowSyntheticDefaultImports' flag.

@types/three@0.150.0 and several versions later changed how stats.module.js was being referenced. Depending on the version of Threejs you are using, you can add "allowSyntheticDefaultImports": true to your tsconfig.json to counteract the error. This fix no longer seems to be necessary since Three r154.

Example,

1
2
3
4
5
6
7
8
9
{
    "compilerOptions": {
        "target": "ES6",
        "moduleResolution": "node",
        "strict": true,
        "allowSyntheticDefaultImports": true
    },
    "include": ["**/*.ts"]
}

And we also now need to instantiate using the syntax,

const stats = new Stats()

In previous versions of @types/three, we could use the syntax,

const stats = Stats()

'new' expression, whose target lacks a construct signature, implicitly has an 'any' type

If using @types/three@0.148.0 or earlier with stats.module, instantiating a new Stats() (using the new keyword) would cause the error new' expression, whose target lacks a construct signature, implicitly has an 'any' type since stats is exported as a function and not a class.

In @types/three@0.148.0 and earlier, you could use the syntax,

const stats = Stats()

If using versions equal to and between @types/three@0.149.0 and @types/three@0.154.0, then you need to add "allowSyntheticDefaultImports": true to your tsconfig.json.

And, you need to now instantiate stats using the syntax, in all versions since @types/three@0.149.0.

const stats = new Stats()

Comments