Thursday, April 25, 2013

Video: 5 minutes to the top, and the challenges of making a voxel world

This is a long video clip showing an ascent from deep in the caves up into the sky. I made this video to help show the scale of the game world.
Getting a voxel engine to do this has been no small challenge. I will never forget how when I started on this engine how I thought, essentially, "How hard could it possibly be? Cubes are about as simple as it gets!". I was sure it would be a quick thing to do and get a game out. I couldn't have been more wrong. While it is in fact relatively trivial to get a basic voxel renderer with hidden face elimination up on the screen, that's just a tiny fraction of the work involved with making it a full feature of a game with decent performance on the XBox using XNA. Here's a short list of some of the surprisingly complicated tasks that go along with it:

Physics: Just cubes, you say? Sure, but you have to have an optimized system for dealing with all the physics because you sure can't add & remove hundreds of thousands of blocks to a physics engine and expect it to work well. Solving this means having a deep understanding of whatever physics engine you are using. Why not go simple, and roll my own physics and just keep it basic? Because, frankly, I wanted more physics than simple block collision and I know from experience that reinventing the wheel when it comes to physics engines is just not smart for a sole developer. Thanks to Bepu, which is awesome, this game has proper physics and it enables a lot of interesting dynamics. But it comes at a pretty big cost, especially with the voxels both in terms of runtime and dev time.

Rendering performance & quality: Managing all the blocks so they don't kill the framerate just by being on screen was an enormous task in itself. Almost as important is that because of all the competition in the indie game space, it's essential the visual quality is competitive in order to minimize how many people will dismiss the game out of hand for just not looking good enough during the first impression. This engine has some nice rendering features that I think help it stand out, but it wasn't easy or quick to come up with these solutions. Voxel spanning textures was hard to get right both from performance and content pipeline/management standpoints. Getting decent lighting has been probably 10x the effort I thought it would be, and it's still not where I want it to be. A big part of the time invested in this area was that I needed to refresh my graphics skills which hadn't been seriously used in a long time. It's been great to be up to speed on shaders though!

Procedural worlds: Fractals are the ultimate rabbit hole task, where you can find yourself endlessly tweaking parameters trying to get it to look good. Performance wise, the XBox has terrible floating point performance under XNA which doesn't help one bit. Getting this to work well has been a very time consuming task, but it's been worth it; I'm pretty happy with how the world looks these days. I do wish the caves weren't so vertical near the ground, but I've already spent more than enough time tweaking it.

Memory: The XBox 360 has 512MB of ram. You can use most of it, but there is no virtual memory. Voxels are pretty cheap, but any 3D array starts adding up quick when you want to see at any reasonably entertaining distance.

Serialization: Moving around the world, offloading and loading chunks, and stitching them to the existing geometry doesn't sound too bad until you start thinking about the light system and how the radiosity and vertex lighting has to propagate changes to neighbor chunks. The fact that this game is unlimited in all directions only complicates things further. And that's not even touching the general issue of how much data is generated and stored or keeping the IO work from messing up the main game thread which is another whole area of complexity. To top it off, the XBox file system is hideously slow. Wow, just, wow. It's no wonder most voxel games are fixed arenas.

Content management: Depending on how it is configured, each face of a voxel will have several textures that have to be authored and integrated into the game data. Creating the assets, using them in game, and generally keeping these organized is an ongoing and increasingly time consuming task as the number of voxel types has grown. I have put serious time into creating custom tools which alleviate this problem, but again it's another level of cost that is easy to overlook when making an engine for rendering cubes.

The challenges of making a voxel world game are not to be underestimated. I could have extended the above list quite a lot but I think I've made my point. As someone who likes complicated problems, the more I realized the real scope of complexity here the more I found myself compelled to solve them. To all the other voxel world devs out there I just have to say kudos for pulling it off. For me this has been a very interesting process and it is a great feeling to be nearly done with the first release of Thunder Moon. Hopefully players will enjoy it.