How to optimise my voxel engine code

Hi everyone!

I’m creating a minecraft style voxel game and have hit a slight performance issue on the javascript side, with applyToMesh taking a long time.

Currently I’m generating a chunk mesh on each block placement/removal which creates an entirely new mesh. Here’s a sketch of the code which does this:

// meshData has been generated by iterating through the chunk...

let mesh = new BABYLON.Mesh('chunk', scene);

let vertexData = new BABYLON.VertexData();
vertexData.positions = meshData.positions;
vertexData.indices = meshData.indices;
vertexData.normals = meshData.normals;

vertexData.applyToMesh(mesh);

I’ve profiled the code and a significant bottleneck is the applyToMesh function. In fact, this takes roughly as long (~30ms for a 32x32x32 chunk worst case scenario) as it takes to generate the positions/indices/normals arrays in the first place.

It looks like this function is slow because it is creating a vertexbuffer object and copying a lot of data from the vertex data object. This seems like a lot of unnecessary overhead, so would my best approach here be to try and create a vertexbuffer directly, or is there another way which is better? And if so, is this supported by the engine or will I have to use unsupported apis/properties for this? No problem if I have to hack the engine, I just want to make sure I have the right approach.

Thanks. :slight_smile:

1 Like

Hi @tyro and welcome to the forum.
Any reason why you are using a custom mesh approach? Not knowing very much at all about minecraft I would have thought using individual blocks would allow you to mine easier? Babylon.js Playground

FYI: Minecraft classic (classic.minecraft.net ) uses Babylon.js

Hi @JohnK,

Thanks for the reply.

Minecraft style engines typically render the entire chunk (16x256x16 blocks for Minecraft) as a single mesh as this significantly reduces the render time. The trade-off (as you state) is that adding/removing blocks is slower computationally, however it’s a trade off that works for this case - see here for more info.

ps. Minecraft classic uses this engine which I believe also uses the custom mesh approach with vertex data.

1 Like

OK I understand. It might be worth looking to see how the Minecraft classic engine optimizes and then renders with Babylon.js.

Hopefully other might have better advice.

1 Like

Noa engine is based on Babylon.js :slight_smile:

1 Like

I think the SolidParticleSystem might be the answer to your troubles, in combination with some smart algorithms to re-use & only render visible boxes.

// 10k boxes
https://playground.babylonjs.com/#LXXL6Y#22

// SPS docs
https://doc.babylonjs.com/how_to/solid_particles

  • By re-use i mean that you shouldn’t need 65k boxes in your scene,
    superset a position array saying “at position x/y/z, a box is located with this uv(texture)”, then re-use geometry, move them around depending on your player’s position.

  • Minimalize the original box if possible, remove any meshData you don’t need. (it’s replicated in the SPS mesh, bloating memory that isn’t used)

Edit; wrong PG.

Hi @aWeirdo,

Thanks for the reply! I don’t think SPS is a good fit for me here as it only uses one material and doesn’t seem (?) to support shader attributes which I would need to apply on a per block face basis (for flood fill lighting).

However, I will check out the SPS source to see if it has a different approach to creating the mesh vertexbuffer.

@tyro may also benefit by looking at the code for open source Minecraft-inspired games like Minetest. It is definitely a cool idea. I am hoping to do something similar with BabylonJS after I advance my coding skills a little more.

2 Likes