3
\$\begingroup\$

I'm working on a WebGL game using Three.js, its been a few days and I found my first issue, render time on big maps.

The game runs great, there are even some AI mobs that run around randomly like crazy, the problem comes when the game has to display many tiles at once (being many around 900 (30x30) on my Computer), if I zoom in the game runs at 60 solid FPS, here's the game demo so you can watch it in action.

http://kuxtal.oruga.biz/

You can move around with the classic WASD or arrow keys and zoom in and out with the MouseWheel.

Right now I'm creating a map like this (The project's code name is Kuxtal):

I have a singleton called Kuxtal, from which all the magic happens, I create a Kuxtal.Instance, which holds the renderer, scene, camera, and some functions to work with them.

Then I create a Kuxtal.Map, to which I pass the width & height as parameters and it runs:

for (var i = 0; i < this.width; i++) { // map.width
    for (var j = 0; j < this.height; j++) { // map.height
        var type = Math.ceil(Math.random() * 3); // 1-Grass 2-Dirt 3-Something else
        var tile = new Kuxtal.Tile(type, i, j);

        this.tiles.push(tile);
    }
}

This is my Kuxtal.Tile Class:

Kuxtal.Tile = function(type, x, z) {
    this.type = type;
    this.x = x;
    this.y = Math.random(); // A random elevation between 0 and 1 les me see the grid and looks nice
    this.z = z;

    this.sprite = new THREE.Mesh(new THREE.CubeGeometry(Kuxtal.TILE_SIZE, 1, Kuxtal.TILE_SIZE), new THREE.MeshPhongMaterial({color: 0xFFFFFF, map: Kuxtal.getTexture("grass")}));
    this.sprite.position.set(SELF.x * Kuxtal.TILE_SIZE, SELF.y, SELF.z * Kuxtal.TILE_SIZE);
    this.sprite.receiveShadow = true;= THREE.RepeatWrapping;
}

And the tiles are added to the scene on this Kuxtal.Instance.loadMap(map) function:

map.tiles.forEach(function(tile) {
    SELF.scene.add(tile.sprite);
});

Any suggestions on how to improve the performance?

\$\endgroup\$

1 Answer 1

4
\$\begingroup\$

great performance saving comes from caching geometries and materials.

In your case, create CubeGeometry and MeshPhongMaterial objects only once and then use them when creating tiles - each tile will be separate Mesh but all pointing to same instance of material and geometry objects.

Then do the same for all resources that can be reused - models, textures etc. Always think about what can you reuse and whether you really need to create a new object instance.

and btw - don't call those tile's meshes 'sprites' - it can be confusing as THREE.JS already has a type called Sprite.

\$\endgroup\$
4
  • \$\begingroup\$ Excellent! I knew that creating multiple instances of the same object many times was bad, now I feel stupid for doing it, thanks for making me remember such thing! \$\endgroup\$ Jan 23, 2014 at 22:52
  • \$\begingroup\$ Lovely! just lovely! I made the changes on the code, and I changed started increasing the number of tiles rendered on screen, I got to 10,000 tiles at once, sharing the geometry and the material, I had 60 solid FPS, I could continue increasing the number but the map was so big it went out of my skybox, so I will have to make changes to that if I want maps to be even bigger. Thanks again for your reply, the result was just awesome! \$\endgroup\$ Jan 24, 2014 at 19:13
  • \$\begingroup\$ I was glad to help, I had to go the same way and realize same things myself. Regarding your map going out of skybox - cool thing is to make skybox move with the camera. Every frame set skybox's position to be same as camera position (only position, not rotation) Then it will look more real (normally you don't see sky getting closer to you as you walk) and you also get rid of the problem that your map is getting out of skybox. \$\endgroup\$
    – lot
    Jan 27, 2014 at 15:32
  • \$\begingroup\$ Hello, how about tiles that has different geometries? Is there no way of optimizing? \$\endgroup\$
    – majidarif
    Nov 15, 2016 at 4:55

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .