Voxel World Visualization

Recently I wanted to make a game with terraria and modded minecraft as main inspiration. One of the biggest features of both of those games is everything can be broken or build. So if I wanted to make this project work I need to make a voxel world.

Currently I the base of the world gen visualization with a temporary fillup made with multiple overlapping noisemaps for testing purposes. To make this project happen I took it step by step, starting with generating a single cube. After that I stepped it up from drawing multiple tiles to culling the faces that aren’t visible.

After that I went to begin thinking about optimizing this. For that I took minecraft as inspiration of splitting it up in chunks and only rendering a select few that are close enough and in view. I then started on implementing ways to generate different materials and fixing bugs caused by Unity limitations

This project is still in progress, but It is a good beginning of what I want it to be.

Tiles and chunks

I see voxels as visually processing tile data, while making it ofcourse look good but also doing this fast and light in performance. Because of this it would you should set up a good system to reference those tiles.

The way I handled this is by making a 2 dimensional construct array containing a 3 dimensional int array. The 2 dimensional array is for the chunks so you can just put in the indexes of the required chunk and get the information. The 3 dimensional array in the construct is for the tiles inside of the chunk. By using the 3 dimensional array you can easily access the tiles instead of going through each one untill you get the correct one.

The Int used in the 3 dimensional array is the index of the type of block the tile is. With 0 being air, and higher numbers being a block. This way you can easily add more type of block with just adding references to the index with the right tile properties.

Currently the information in the tiles is randomly generated by added multiple noise maps together for testing purposes.

Mesh Generation and Unity Limitations

The mesh generation makes use of the information in the tiles and chunks. Once all the information is generated for the world it uses it to generate the meshes. It does this chunk by chunk that are added in a queue.

When a chunk is being generated It first makes a sepperate list of all the tiles that have faces to draw, while also saving the info of what faces a tile should draw. This list is also saved for when a tile is being edited, it then doesn’t have to recheck the whole chunk but just use that information and edit the tiles surrounding the tile that has been edited.

It then generates height layers that are sadly needed for a unity limitation. When working on this I had a problem of a chunk only making part of the mesh. This ended up being a Unity limitation. When generating a mesh through code there is a limitation on the vertices that are allowed to be generated. To bypass this limitation I made multiple layers of different meshes inside of a chunk. That way it would never reach that limit.

After this it comes to the main part of this, drawing the faces. This was a bit of a struggle since you have to add the vertices in a spific order to have the normals the right way. So for each face I had to write if the vertices would be added clockwise or counter clockwise. After this it would add it’s information of the tries, normals and uv’s. 

When this is all done a list of meshes will be saved as the draw information of this chunk. And this is accesed when the chunk is visually drawn.

Optimizations

This is quite a heavy thing to be drawn since you are generating a lot of vertices and rendering them to the player. So optimizing this where possible is a must.

One of the most required optimization is to not draw faces that aren’t visible. In short I only need to draw the faces on the outside that are visible to the player. The rest can just be ignored.

Besides that I also added chunk culling, only drawing chunks that are close enough the the player, and only when they are also in view. I also added a few chunks behind the player that should be drawn in order to get better shadows and when you look down you always have a floor.

I eventually want to add multithreading to this but I first want to make it better and add more optimizations to better feel the impact those optimizations have.