Minecraft Clone
A downloadable game for Windows
Overview
This Minecraft-inspired clone features infinite terrain generation, distance-based block fading, async chunk loading, and bit-packed face data for optimal performance. Players can build and break structures with six block types: dirt, grass, stone, cobblestone, wooden planks, and wooden logs. This project is designed for experimentation and learning, not for sale.
Controls
- WASD --> move
- Mouse --> look
- LMB/RMB --> place/break blocks
- Q/E --> switch current block type
- Scroll Wheel --> adjust move speed
- F1 --> toggle render mode
- Escape --> quit
You can find the Github repository here.
Challenges
Greedy Meshing and Bit-Packing
One interesting issue I had was how to optimally store face data? My first thought was to use an approach called 'greedy meshing', basically instead of storing a quad for every single 1x1 face, you try to fill the space with as few faces as possible. You can see how this looked in this LinkedIn post of mine below.
As you can hopefully see, if the entire chunk is one flat plane, then one big face is generated spanning the entire chunk. This seems like it should be a good approach but there are a couple major issues, 1. it makes generating the chunks soooo much slower, and 2. the way I stored the face data took up quite a bit of space, it looked like this at the time:
struct FaceData {
vec3 offset; // 3 * 32 bits
int8_t blockFaceId; // 8 bits
vec2 texcoordStart; // 2 * 32 bits
vec3 size; // 3 * 32 bits
}
This was very inefficient, needing to store a whopping 264 bits! Per face! And then I just happened to come across another persons implementation where they came across the same issue, needing to store extra data because greedy meshing faces are off grid, and tested bit-packing v greedy meshing. They found that even though there are less faces with greedy meshing, the data required completely erased that advantage. So I opted to remove greedy meshing in favor of bit-packed face data, and since the faces were now on grid I could get away with only a handful of bits for position and a few more for the face direction / id. With that optimization, the new face data looked like this:
struct FaceData {
uint16_t position; // x, y, z => 4, 4, 8 bits
uint8_t direction_id; // direction, id => 3, 4 bits
}
Now each face only needed 23 bits! Obviously with byte alignment, but still! Much better :) .
Async Chunk Loading
Another annoying challenge I had was how to load chunks efficiently, as originally I had this running on the main thread which lead to the game freezing while new chunks were loaded ... very bad for the player. So, I had the bright idea of off-loading the chunk loading to its' very own thread ... with basically no prior multi-threading experience ... and no clue what I was doing.
After many, many attempts I got a 'ChunkManager' to start up its' own thread and then exposed a couple functions 'removeChunk' and 'addChunk'. Add chunk would store the chunk index to load at some later point, and then on the background thread we load the chunk at chunkIndex and then ensure the queue is locked while we push into it. Remove chunk would simply erase the chunk at chunkIndex from the worldChunks map.
The final code then looked like this:
queue<vec2> indexToLoad; // indices to load at some point queue<Chunk*> loadedChunks; // chunks ready to add to world map<vec2, Chunk*> worldChunks; // active world chunks
This solution is most definitely not optimal, but it did work at the time, and once you add a little graphical distraction (*ahem* distance fog *ahem*), then it seems like the world is always loaded at all times :) . Below is a LinkedIn post of the async loading in action:
What would I do differently?
Better Terrain Generation
Add more interesting terrain generation, it is currently very lackluster, as it is just a noise function that is used for the height of the blocks. At the very least I would want to add some sort of cave generation, just to give the world more variety, and something more for the player to do. Another small detail would be trees, and maybe structures? Depends exactly how I would implement trees, if they are pre-defined blocky structures then I could adapt that into proper structure generation which would be cool!
Migrate to Vulkan
Another small thing that I think would mainly help the performance of the application would be to build it using Vulkan instead of OpenGL, but I would need to do some testing to really figure out if it is worth the switch. Considering that official support for OpenGL was ended when Vulkan came out, it probably would be worth doing. I just found OpenGL easier at the time, but Vulkan should be more performant as it is more modern and still getting support at the time of writing.
| Updated | 24 days ago |
| Status | Released |
| Platforms | Windows |
| Author | E-Dawkins |
| Genre | Educational |
| Tags | 3D, Minecraft, Sandbox, Voxel |
| Links | GitHub |
| Content | No generative AI was used |
Download
Install instructions
Unzip and enjoy!


Comments
Log in with itch.io to leave a comment.
exe doesn't run :/
Issue should be fixed in 1.2 :)