0
votes

I recently made a project in WebGL, using Javascript and the 3D library three.js

However its perfomance is very poor, slow at the beginning and at best gets close to okay.

The objects of my game are: 1 car, 6 oranges, 161 cheerios, 1 table, 1 fork, 6 candles.

  1. You control the car as in a race game (WASD or directional keys), which you drive through a circuit limited by cheerios. The car is composed of several three.js geometries (box, torus, cylinder, sphere). If an orange collides with the car, the player goes back to the beginning of the track and loses 1 life.
  2. All oranges move in a straight uniform movement, and can kill the car if they collide with it. The orange model is composed of three.js geometry sphere and cylinder.
  3. The table is a cube scaled to be 300x1x300 in xyz coordinates.
  4. Each candle is a pointlight source, which intensity varies to give a flickering sensation.
  5. Besides the 6 pointlights, there is also ambient light and 1 directional light, all created with three.js.
  6. The fork as a billboard-like behaviour that rotates to be always pointing toward the current active camera, represented by a plane.
  7. Whenever an orange reaches the end of its trajectory and temporarily disappears, or the car finishes a lap, an explosion of particles occurs.
  8. Each explosion can have several particles (at least 100), and each particle is a very small plane with billboard-like behaviour.
  9. Upon the creation of an explosion, all its particles are individually created and added to the scene.
  10. Each explosion also has a time to live in miliseconds, usually 1000. When it expires, the explosion is removed from the scene.
  11. All objects of the game have their own textures, and not all textures have a "good" size, i.e, dimensions as powers of 2 (32x32, 256x256, 1024x1024, etc). Each texture is loaded with a deprecated method THREE.ImageUtils.loadTexture(URL).
  12. Everything was built with three.js, from the scene, cameras and lights, to the meshes, geometries and materials.

I noticed that after adding so many cheerios the perfomance diminished dramatically, so the problem may be rooted in the large amount of cheerios rendered each frame.

Since they all share the same model (a simple torus with a simple texture), is there any way of using only 1 model for all the cheerios (much like in openGL with VS libs)?

How can I improve its perfomance?

Tell me if you need more specific information regarding the problem.

2
Place the cheerios inside of a container object? I'm not sure the exact issue with performance you're having but perhaps you could batch some of the computation you're doing on the cheerios by treating them as a single itemAndrue Anderson
Are you using physics? How are you doing collisions. I'd guess the issue is not three.js it's your collisions and physics system. Turn off all collisions and see if it runs fast. After that check your particle system.gman
@gman I am currently using a brute force collision check (our teacher demanded some type of collision detection and suggested the AABB algorithm). So every time I update the game I also check for all possible collisions, which is clearly not optimized by any more advanced collision techniques (unfortunately we don't approach those things in our course).Razraal

2 Answers

0
votes

Create a geometry. Then create cheerios meshes. After creating a mesh do not add it to the scene but merge it into geometry with

var globalCheeriosGeometry = new THREE.Geometry();
// create 161 cherios meshes and add them to global geometry
globalCheeriosGeometry.mergeMesh( cheeriosMesh );

thus you will create one geometry containing all the cherios from the scene. Then create one mesh with this geometry and add it to the scene. That will significantly reduce the number of draw calls from your scene.

0
votes

I would guess its something along the lines of that you are calling an expensive (in terms of computation power) three.js method too many times. I would profile your game first to determine if problem is in cpu bound or gpu bound.

Besides the 6 pointlights, there is also ambient light and 1 directional light, all created with three.js.

lighting calculations are expensive individually per pixel, and they have to be done for every pixel. consider cutting down the light sources.

Each explosion can have several particles (at least 100), and each particle is a very small plane with billboard-like behaviour.

I hope this is done via a billboard particle system and not as individual planes. Otherwise three js will probably do one draw call per plane.