What is Voxelius, actually?
Voxelius (or VGame in code) is my WIP FOSS voxel-based game that attempts to resemble Minecraft in as much ways as possible.
I drank liters of coffee and wrote a somewhat working ECS-based client-side code. Now I am struggling with networking without coffee.
Coffee and Components
I decided to use EnTT as it’s a perfect ECS implementation that is not GPL-ed to the bones. Pure ECS design, however has some disadvantages but that’s the reason why the design pattern I choose is called ECS-based
Troubles with purity
Because Voxelius tries to resemble Minecraft in many ways, things need to be split into chunks. I decided to abandon the 16x16x256 chunks in favor of 16x16x16 cubic chunks as they are a bit easier to work with in terms of maths.
But the main problem with chunks is that you would often need to get a specific voxel at a specific position in the world while in ECS you could do that only by looping though a list of components; see where is it going?
That’s right, a separate “system” is needed to store the voxel data that is linked to the ECS. Voxelius uses a hash map abstraction called Chunk manager.
Chunk manager’s behavior is defined by the side (client or server) it is being compiled.
At first I tried to make things as simple as possible and wrote a basic bitfield-based naive mesher which was nice but the amount of vertices rendered per-frame kept bothering me as my laptop started to heat up and cool itself louder.
As the amount of vertices being drawn grew, framerate was decreasing so drastically I decided that things are not going to stay as they are right now.
So I started my glorious journey on packing vertices and reducing their count.
First attempts were utterly messy with my system failing on voxel face lookups resulting in nice but slow grids of triangles but by gradually optimizing the code I came to this nice result:
Final try with threads™
Speaking of the Devil and YouTube, as Hopson said the article about greedy meshing algorithm is very… yeah… even disregarding the fact that I am unable to read large chunks of English text. But the algorithm itself is simple: you just create a mask of a slice and make quads out of it by using just two counters.
After the base meshing code was done, things were getting slow again.
See, at that state the game was generating the world, then meshing the data. This meshing stage was taking a long time because it was freezing the entire game loop for a while so I used a thread pool to counter this.
Also at the time I’ve finally decided to abandon using UVRE in this project due to complexities in the development (it’s hard to work on both projects while having only one origin in the git, etc etc).
So before Greedy meshing my meshes looked like this:
And now they look like this:
From the first day of development I was strictly for deferred shading as it definitely the case when you draw lots and lots of similar things that need to be lit in the same way.
I really has nothing to say about that as my OpenGL wrapper literally covered all the complications so here’s a screenshot of this neat shadow filtering alhorithm I
yoinked ported to GLSL from Source SDK
Tea and packets
Yes, I’ve added Dear ImGui to the project just to draw things like debug overlays and dev menus.
For now I have no plans on using ImGui as the main Game UI but time will tell.
Because I mentioned Hopson and their video about voxel meshes you can probably guesses by what project Voxelius is inspired aside of Minecraft. That’s right!
But since OB is multiplayer, so should be my game, right?
But unlike OB I decided to stick with Minecraft-ish style of doing things and started making a nice protocol with compile-time packets that are serialized/deserialized via Bitsery. These little guys are then sent through UDP via ENet.
Now I am working on movement code but I also re-done mostly everything regarding the protocol itself (see, I can’t choose a good name for server->client settings and info packets).
ECS through packets
And again, entities need to be accessed fast enough to be updated via network; and thus an another system for handling them is needed.
In Voxelius this sytem is called Shared Entity Manager (I know, that’s a bad name but whatever).
What makes an entity shared?
When an entity has a unique 32-bit ID that is shared between server and clients, the entity is considered shared. Entity IDs are now in the stage of a concept but they will probably be derived from ECS entities on serverside.
Short answer: no.
Longer answer: not yet.
For now I need to setup a basic protocol for the server to “chat” with clients. So no compression for now. Be still my compressing Zlib.
- You can check out the GitHub repo of the project.
- You can contribute to the project if you will. I would really appreciate this as I am having hard time wrapping my head around networking.