I am always a little surprised when I look at the search engine metrics for the Proverbs website. Usually, I find that something has been broken with an update or another, which I really shouldn’t be surprised about. However, I recently discovered that the website shows up in quite a few searches for Voxel Generation and Voxel Terrain Generation, even with how stagnant the website had been. I have even received an email or two from “newer” game developers looking for shortcuts into the world of Voxels.
This is to be expected with the success of games like Minecraft, 7 Days to Die, and other open-world Voxel (or pseudo-voxel) games. There are definite advantages to using voxels for procedurally generated worlds, the three biggest being (1) truly vertical surfaces, (2) underground areas, & (3) destroyable land. However, there are disadvantages as well, such as (1) memory requirements, (2) generation time, & (3) complexity of displaying voxel data. I talked a little bit about the first two advantages and disadvantages in my post, A High Level Guide to Poly-Voxel Procedural Generation, so I won’t bother to cover them here. Still, I will cover the last one with a quick introductory course on Voxels.
First off, if you are looking for Voxel Terrain Generation, you probably don’t know what a voxel is. Don’t feel bad or be offended; I know plenty of seasoned game developers who do not know what a voxel is. They have never needed to deal with them, and so they, like most people, believe a voxel is a box. They both have the letter ‘X’ in them, right? It is actually almost correct in that a box is a three-dimensional object, and a voxel is a three-dimensional storage container. But I jump ahead of myself.
A voxel is a three-dimensional storage container. There, now we are all caught up. That really is it. If I have n numbers in a row, it would be a one-dimensional list (container) like 1, 2, 3, …, n. Add a list of m numbers going down in columns, and you have a two-dimensional container. Followed by l numbers deep makes a three-dimensional container. Most developers know them as Arrays, but they can be any type of storage container, really. What makes a Voxel a Voxel is that it is storing something very specific in each of those indices: display data.
In the case of the simplest terrain voxel, that display data is going to consist of two things: the land type and the land health (why have voxels unless you are going to destroy them?). I can see the confused look where you are wondering (a) what I am talking about, (b) why are you still reading this, and (3) how does all this get turned into graphics? Voxels, boredom, and magic (without the k). All joking aside, this is where it gets complicated, so it might as well be magic for most people. Let’s backtrack a little first—terrain generation.
Hopefully, at this point in your development career, you understand normal distributions, random number generation, and how to fill an array. If you have those three things down, you can generate the voxel data for an entire world. You don’t need me. Except you probably do because you will do what all the other people have done before you and make your players wait 18 minutes to generate a 5,000mX5,000mX2000m land plot, whereas I generate them in seconds. Read the previously mentioned article A High Level Guide to Poly-Voxel Procedural Generation and see if you can figure out where everyone else is going wrong and why I can be so smug about it.
Once we have our container of biome data filled up before the player could say, “the world is generating,” we can move onto the difficult part. Displaying the voxel data is not really that tough, depending on the previous design choices you’ve made. Before generating your landmass, you will have decided on the size each voxel will represent in world space, usually 1 cubic meter. With that information and the two pieces of info in each index—the land type and health—you are set to render to screen.
Alright, I lied. It is going to be difficult. Not because it has to be, but because of the design choices you have made for your game up to this point combined with your inexperience with Voxels. You want beautiful, smooth rolling hills that are more realistic looking than those found in Skyrim. You also want to write the entire game in Unity or Unreal. You want 240fps. And your knowledge of programming in Graphics Library Shader Language (GLSL) is limited to knowing there is more than one shader. Yep, difficult.
See, graphics cards display things as pixels. They are generally limited to accepting only a small handful of types of primitive data to display, such as points, lines, and triangles. They then turn these types of data into those pixels. The easiest way to display voxels on a screen is to mimic what Minecraft does. Convert each three number index into a world point (indices become coordinates) and send it to the graphics card as a box with the texture set to match both the land type and health. You can do that without knowing about GLSL, and you can do that in either Unity or Unreal. It will still be relatively slow, but not painfully such. No one expects 240fps from a Minecraft clone.
Now, if, while reading the last paragraph, you piped up with “and patches,” then there is hope. Patches are another type of primitive that graphics cards accept, and patches get used by the Tessellation shader. Similar to our Minecraft example above, you can send the array block that you are displaying to the Tessellation shader (there are actually a couple of tessellation shaders, but we’ll keep it simple) as patches. In the Tessellation shader, you convert the indices to coordinates, then create a shape made of triangles around that point. The shape’s size would start at 1 in-game meter and be reduced based on the land health. All those new triangles then get passed to the other shaders you have probably heard of, have a texture added based on the land type, and get displayed on the screen. This is really the base of an ideal Voxel system—simplistic, incredibly fast, and low CPU overhead.
I am not quite certain, but I believe 7 Days to Die uses some type of sphere as their base land shape (wood blocks are obviously cubes). It is difficult to tell because all the spheres (blocks, whatever) overlap, and they use an algorithm to join the outside of each sphere to the next, thus creating smooth surfaces. Marching Cubes is one of the more popular algorithms for tying Voxel points together, although it is often used for things people call Voxels but are not.
There you have it, a quick explanation of how to generate and display voxel-based terrain. If you really want to know more, you should learn GLSL inside and out. Learn how to write your own shaders from scratch off the top of your head and learn how to offload all the heavy lifting of creating a voxel terrain onto the GPU (it’s designed to handle it) through Tessellation shaders. Do that, and then design that game with those beautiful, smooth rolling hills.