Reference images for this post
Issues with terrain rendering in Civ games
I first played Civ in 16 colours (EGA), and it was fine albeit a little ugly for the time. Moving to 256 colours when we got a new computer felt like seeing in colour for the first time – the world was beautiful! I loved the animations of sea waves breaking on the shore.
But Civ’s policy of “no elevation in game, all tiles are same height above sea level” has made it near impossible for the designers/developers to keep improving graphic quality without making it look bad. Let’s be clear: there are no easy wins here!
Experimentally, I feel Civ3 and Civ4 were the last ones to gamble and succeed. Civ5 gambled and ended up jumping the shark: photo-realistic mountains that are barely taller than a tall tree. After a while it looks awful, and I’m suspicious it messes with your brain: mountains are not fractal, and your subconscious knows that they are horribly out of scale when it plays Civ5. Either way, it looks wonky. I feel that route is a dead end, inspiring me to explore other routes.
My game is mostly true to Civ games, but one of the big changes is that I add “elevation”. I belief this is something Sid would have put in the early games if it had been technically feasible at the time. It doesn’t have to affect gameplay – it could be purely cosmetic – although I’d like to experiment with using elevation as a small modifier on combat, city output, random events, etc.
Biggest problem: if you get it wrong, it’s almost impossible to see at a glance what’s going on while playing the game.
Civ4 took the route of “reduce graphical quality, guarantee gameplay and UX”. Civ5 went the opposite. Look at images 5a and 5b and ask yourself: where are the hills? Where are the plains? Where do they begin and end?
I want both: beautiful graphics, and easy gameplay via great UX. This is a very hard challenge. I’m starting with Civ4’s approach – clarity over quality – but I want to move towards Civ5 photorealism over the course of development.
It’s a mess. Since hills massively affect gameplay (movement costs and combat outcomes) you need to be able to clearly see these things at a glance without any mental effort. Civ5 hills look pretty but IME are too hard to spot.
Civ4 wasn’t ideal: the modding community fixed it in almost every mod by throwing-out the texture packs and making ones where hills were clearer. But in image 4a you can see what stock Civ4 did: every hill had a major change in the colour-scheme (added grey) to make it clear what it was.
Look at the bottom left corner of 5d. Which tiles are covered by trees? How few tree-tiles will the unit have to move through (if it wants to avoid them)? … how far can it move within them without wasting moves (if it wants to keep in tree-cover)?
I’ve no idea. The hex-grid and the representation of forests combine to make it utterly opaque and impossible to “read” quickly and easily. Compare with 4a, where Civ4’s plain regular square grid makes reading much easier, and they didn’t need to worry about their tree layout. (Although they stuck more rigidly to tile edges, favouring clarity and gameplay over pretty screenshots).
Compare 5a to 5c. The sand-dunes are taller than the hills. This is ridiculous, and it’s a side effect of trying to make both look visually appealling. It again messes with the player’s head: you get used to it, but your brain is being taxed whether you are aware of it or not (this is one of the things about UX design that is hard: many UX costs are invisible, hard to detect without external measurement).
Look at the mountains in 5d: they barely overreach the trees – and some of those trees are standing on supposedly sea-level plains!
But what’s much worse is that they’ve been built by an artist at 1000x the scale of the neighbouring tiles, so the snow cover represents miles of distance in the same space that a tree represents metres.
Alone, the mountains are beautiful; placed in-scene, they are horrible. The best way to check this is to open up the 3D models in a modelling app and play with the scales. You should find that cranking up/down the scaling causes the scene elements to suddenly “pop” and look and feel many times better. This is your subconscious crying out “Uncanny valley! Uncanny valley! Spare me this terrifying place!”
Time for Civ5 to shine: look at 5e, a thickly-forrested area. Here Civ5’s tree-placement looks great, and it causes no significant gameplay problems.
Sure, there’s an issue that visually counting distance is difficult with the non-square grid, but surrounding tiles give a consistent benchmark for probable distance and scale, and the “fully covered by trees” effect works fine. You have the interactive GUI to quickly confirm/reject the scale your eyes have guesstimated.
…can we retain some of these wins of Civ5? Definitely worth it, IMHO.
Solutions and current status
So … by comparison, my current pre-alpha build looks absolutely, horrifyingly, tear-jerkingly ugly:
…with my only consolation being that it used to look even worse:
An urgent problem
Looking this ugly is getting to annoy me – now that most of the core gameplay is up and running, this unrealistically ugly landscape makes it harder to test the game realistically. Graphics matter, even when building prototypes.
But also: to implement fog-of-war, I want to re-colour tiles e.g. into black-and-white. That doesn’t work when each tile is the same, and only distinguished by colour (or in extreme cases – my mountains and TALLER hills – by spikiness):
The only way out is to start using geometry to distinguish different tile-types.
Geometry differences in terrain
All my tiles are already procedurally generated – there are no pre-made meshes/objects here. This has some nice side-effects, e.g. the way hills get gradually spikier as altitude increases, and ditto mountains.
Once we start playing with better geometry algorithms, there are a couple of issues to attack all with the same hammer:
- Hexes in a line have horribly obvious jagged edges; we can either smooth it a little, or smooth it a lot (make lines actually straight! Hide the hexes!)
- Terrains of different type that border each other probably have a height raise/drop. Most obviously: hills and mountains that directly border seas should have cliffs.
- Terrains that create visually-expected intersections need custom massaging of the intersection. Most obviously: plains that border seas and lakes should have beaches. This requires not just careful meshes, but custom materials so that the beach area is coloured/textured differently from the plains
- Special cases need special detaild geometry. Most obviously: rivers (currently implemented as full-size hexes) should be drawn as water only in the middle, and the visual representation should get wider as the river flows downhill. I’m already tracking the river “width” in the underlying game rules! I urgently need to start rendering it too
The difficult question that remains is … how? Not technically, but algorithmically / design.
- Should the beach be drawn just inside the edge of the Plains tile, or just inside the edge of the Sea tile?
- To create cliffs, how do you interact with the mathematically-generated height-field?
- At the moment, seas are calculated arbitrarily, so that there are no sudden drops in height leading to sea
- The underlying heightfield moves smoothly from sea to hills. Ouch.
- Rivers can’t be generated in the height-field since we need to place them sensibly in hexes; they are done by post-processing
- Do rivers steadily drop in height from source to sink?
- Currently, yes: that’s part of my post-processing; but how will custom geometry handle this?
I need to pick one of these to work on first. Not sure which one I’ll go with – and I fear it’ll fail horribly and I’ll be back to square one. Let’s see what happens…