Having serious performance problems representing voxels

I’m making a procedural 2d space sim, and I’m generating about 30k voxels for a planet. The look I’m shooting for here is roughly like Terraria, but with these blocks (voxels) acting as planets. I already optimize well by only building what is necessary for the immediate view, but I’m still running into all kinds of problems.

I render one block (voxel) as a quadrilateral, but rotated and modified slightly to bend around the planets radius. 2 triangles per block. If I just use a single mesh and add all the vertices to that mesh, the performance is great.

However, the problem is that these blocks need to be individually textured/styled (think minecraft/terraria, etc). So, I tried making a mesh for each of them, and as you might imagine, the framerate plummeted to like 9 fps.

Then I tried using instanced geometry, where they’re all still their own meshes, but instances of the base mesh for the row that they’re in (because all voxels in one row are identical). Instancing the mesh helped a good deal, but still far worse than the single mesh implementation, and AFAIK doesn’t offer the ability to texture individual instances.

At this point I figured the only thing that seemed to work was the single mesh with all of the vertex data. So I started looking into multi materials. I followed this guide:

and started first with rows of voxels. I created a material and submesh per row. It worked, and the performance was actually decent, so I figured I’d go on to do it per voxels. Creating a submesh per voxel basically crashes the application.

Now I’m wondering if I’m out of options. I could use a single PBR material and UV the voxel geometry to different parts of the texture, but that’s also going to be quite limiting.

Any thoughts/feedback welcome.

HI @ralusek
I think Thin Instances might be the play here.

Textured Sample: 2 meshes & textures, 8k ThinInstances each (20 * 20 * 20 cube), 16k boxes total

Textured sample 2: 5 meshes & textures, 8k ThinInstances each (20 * 20 * 20 cube), 40k boxes total

Play around with it :slight_smile:

If some of your adjacent voxels use the same texture and you’re not already using greedy meshing check out Meshing in a Minecraft Game – 0 FPS

Hi and Welcome to the Community,
Did you check out this awesome demo from @lucas-divinestar
The subject is quite complex but may be he will be willing to share some information with you…are you?

Yeah I tried that multi material approach but that is a really bad idea for performance. Because the more materials you have the more work the engine has to do.
So, go here check out the section under “Research”. Here you will find my compiled findings and helpful links.
Divine Voxel Engine Wiki

Basically you can texture each face of a mesh using a texture atlas or a 2D array textures.

If you have animations on your textures using a 2d array texture is easier but if they are static then a texture atlas may work better.

For DVE I did not use instances. I used custom made meshes with relatively simple custom shaders.
Don’t waste your time on the solid particle system or instances.

Break your world down into chunks. Each chunk has it’s own mesh. If you have different voxel types separate them into their own mesh per chunk.

Many smaller meshes is better for performance on a GPU then a few huge meshes.

If you want you can use DVE as a starting place and make it suit your needs. Have any more questions let me know.


Thanks so much for taking the time to share your incredible knowledge with @ralusek and then, so swiftly. Have an amazing weekend :sunglasses: :sun_with_face:

1 Like

Thanks much everyone. I will be looking through these and will report back with results.


Yes, please do that. We love to get feedback on tech and XP… and meanwhile have a great weekend :sunglasses: :sun_with_face:

@lucas-divinestar thanks a lot for sharing back your acquired experience !!!

1 Like

Okay, started with @aWeirdo suggestion of Thin Instances. Performance was great, and I definitely like being able to instance geometry around, even if just conceptually, more than having to place a bunch of vertices all over the place in global coordinates (which was the only other performant solution thus far).

It sounds like what I’m giving up is going to be things like collisions, and it doesn’t seem like it’s particularly easy to vary materials across instances.

Just to make a little clearer what I’m doing, I’m generating voxels like this:

Here is a simplified version to make it clearer:

So, you should be able to see that the geometry for each column (lines towards center) within a row (ring) is identical, but varies between rows.

So what I did to implement in Babylon with Thin Instances was make a mesh per row and then created thin instances of the column around the ring (each color is a given mesh being instanced around that row for each column):

The thing is, given that I have to support N block types, unless I do some material hacks that let me have different materials per instance, I think the way to implement it would be to have a N meshes (one per block type) per row. It’s not horrible, because it’s still better than having 30k meshes, but it’s also not necessarily ideal. I can give it a go.

Now, @MCArth @lucas-divinestar @mawa it sounds like the direction you guys are going with is to make meshes independent of geometry, but rather do maybe something like a mesh per chunk. If I really need custom materials, maybe a mesh per block-type per chunk, but otherwise rely on UVs and a single material. I will finish this pass with Thin Instances and then give it a go.

Please keep us posted. I believe this is a very interesting reading for people wanting to achieve something similar. GL with your project and approach and have a great weekend :sunglasses: :sun_with_face:

One option to simulate different materials per instance would be having a custom shader that calculates the color in different ways based on a “type” attribute defined per instance: Thin instances simple example | Babylon.js Playground (babylonjs.com) :smiley: