Game Development

Blog 747: Terrain’t No Other Way

I mentioned in my last post that when I first tried to make hand-crafted levels, I lacked the tools to make it work; hence my slide into the clutches of procedural generation. So what’s changed?

Why, I’ve started to reimplement the Warcraft III terrain editor.

Terrain’t No Other Way

Traditionally, one would start building landscapes with a heightmap terrain system; Unity even comes with one built-in. However, I could never be content with mere heightmap terrains because I spent so long being spoilt by one of the most artistically maligned features of Warcraft 3: the so-called “Blizzard cliffs”. WC3 terrains don’t have to undulate gently, they can make sharp jumps too, putting hard boundaries into the landscape and — most importantly of all — marking them with sheer cliffs rather than stretchy textures.

Before you get too mad at me, I did spend some time scouting round the Asset Store, looking for low-poly terrain systems that included sheer cliffs. While I found several low-poly terrain editors, however, not one of them offered me proper cliffs. There was only one way this could end…

Blizzard cliffs took up much more space than they needed to and were limited to only two tiers for a sheer drop, so naturally I had to fix that…

Blizzard cliffs were implemented by a hundred-odd cliff models that are conditionally jammed into the terrain mesh, but there’s no way I’d be able to hand-roll so many potential variations. I needed to build a system to do it for me.

I called it Terragne, because I find myself hilarious.

The critical lesson I learned from previously trying to build a voxel terrain editor is splitting the terrain into chunks. This means that editing an area only needs to regenerate a small portion of the world with each touch, perhaps two or three neighbours if you’re editing a chunk edge, rather than all of it. This makes editing very fast and responsive, and I’m hoping it will also let Unity cull off-screen chunks instead of always trying to render a single monstrous landscape mesh.

The second lesson was getting mouse controls in. For some reason mouse controls evaded me in the voxel level editor, but they’re an absolute necessity for a tool that I’ll be spending a hella lot of time using. Turns out it’s no more difficult than the logic I use to select units in the actual game, so not sure how I failed that one last time.

The control interface could probably do with a bit of work, but seeing as it’s only me looking at it this is not a high priority.

Actually generating the terrain geometry is where things get a bit shaky. Each tile has four corner vertices, any of which it might or might not share with more than one of its eight neighbours depending on their heights. Each tile could also be a ramp instead of a flat…

It’s not so much difficult as finicky. Even if each tile only generates geometry within that space, it might still be generating walls up to a high neighbour and down to a low neighbour and it’s got to check whether it’s a ramp or the neighbour’s a ramp or…

This is also where the downside of building discrete chunks comes in — flat shading around the edges. Within a single mesh you can ensure everything is welded nicely to get smooth lighting on each point by telling Unity to auto-calculate the normals, but there’s no such convenience between two totally separate meshes.

I basically brute-force this: for each chunk, I generate the ring of tiles outside it to get the normals from its would-be neighbours (which may or may not actually exist at this point) and then combine them manually with the edge normals of the current chunk. It seems to work but I’m sure I’ve spotted the occasional not-quite-right edge still in there…

You might be able to see the tiles repeating at this height, but I bet you can’t see where the chunk edges are!

So far, that only gets me brick terrain with perfect square tiles, so we’ve still not reached the promised land — Warcraft III allowed you to choose from “natural” or “city” cliffs depending on your environmental needs.

My answer is Perlin noise. What I’ve done is give each tile a “distortion” value, from 0 for hard edges to 1 for maximum natural crunch. I generate the terrain meshes completely as normal in square mode, then apply the noisy offset based on the final vertex positions. Since my tiles are small enough, and my cliff tiers shallow enough, this gives me the perfect rugged late-90s-3D natural look I need — and because it’s controlled by a value, I can turn it on or off as necessary.

At the moment, turning off distortion is most useful for embedding artificial structures like this lift in the ground, but I reckon I can use it to make straight-up buildings and bunkers in future.

Finally, we need tile painting. I was a bit leery about how to easily and efficiently switch between grass and mud and so on, until I realised that I could write my own shaders

So what I’m doing is using vertex colours to indicate tiles. While generating a mesh traditionally means geometry and UV-mapping, it turns out this weird and wonderful modern world also allows you to assign a colour to each vertex. These colours then fade smoothly between vertices without further effort. Thus, by feeding this colour into a handy shader, it can be used as a switch to choose which texture layer to expose.

There is one downside, in that I’m limited to four tiles (black, red, green, blue), as opposed to Warcraft‘s 8-12. However, I’m banking on 4 being enough for most natural environments — and I’ll lay solid platters of actual geometry on top to do roads and other artificial tiles. And if I need another biome in the same level, well, I can always add a separate Terragne with a different tileset…

Had to add a few extra edge cases so that tiles don’t spill over cliff edges but do spill over smooth ground and ramps.

And with that, I am able to construct levels in a very comfortable way that suits all my graphical needs. There are still a few rough edges and features to add, but it’s now very stable and I’ve safely started to build up the outdoor area of my first Assault mode scenario. Huzzah!

The dock and the beach weren’t even in the original plan, I was inspired to add them just by working with the landscape — this is exactly the process I wanted to encourage!

And you tell me...

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.