One of the priorities for 0.5.0 (the environmental update) has been to overhaul the multi-texturing system.
In 0.4.1 the best the engine could do was 4 textures (desert, grass, forests and cliffs), and those textures were placed at world-start, never changing. The end result was a very static map, very boring environment: basic tree loss/growth was the entire extent of environmental dynamics.
All this changes in 0.5.0. The design plan calls for a dynamic, responsive environment, and by crikey that’s what we’re going to have. (Crikey is Australian for… something. I dunno. Honestly I don’t even know what the word means, but it’s a stipulation of citizenship that we all say it at least once a week)
The first thing to add is more biomes. Desert/grass/forest works well as a basic, semi-tropical biome set, but what about colder biomes? Or warmer ones? Or wetter ones or drier ones? My current biome map concept has more than 20 different biomes drawn on a temperature/fertility map, including some hilariously extreme ones
But that many biomes means a whole different approach to multi-texturing… or at least, I thought it did. This was when development started to go bad…
In 0.4.1 I used a multitexturing method called ‘texture splatting’. Imagine you’re painting the ground texture on a blank canvas. What texture splatting does is gives you a ‘stencil’ for each texture: so you can paint forest through the red stencil, grass through the green stencil and desert through the blue one, and by the time you’ve used all the stencils you’ve painted the entire terrain. All these stencils are nicely wrapped up into a single texture, called the blend texture.
Unfortunately, this only works for a limited number of textures per draw call: you can’t load more than a set limit of textures onto the GPU without it having a fit. So in order to render an unlimited number of textures, I’d need to change how I was approaching it.
My first attempt at a replacement system was sort of like an extremely complicated colouring book, where each grid square is numbered 1,2,3,4,etc and our hypothetical artist fills in the grid with grass/desert/forest from a colour key. Since we can include as many numbers as we like in the key, we can have as many biomes as we want.
Once that’s done, our artist is faced with a problem: (s)he has to blur these colours together smoothly without pixilation or sharp edges. And since it’s going to be animated, a simple linear interpolation just isn’t going to cut it.
As it turns out, this is HARD. My own approach was to sample the biome-legend multiple times to give each pixel *four* biomes, each with a weighting value, which I then folded into the same channel as the key
(effectively, I designated the first digit of the channel as the key, and the remaining digits as the weight).
Honestly, the most surprising thing about this ridiculously complicated strategy is that it worked… mostly.
But “works in general”, doesn’t mean “works well enough to use”. On closer inspection, the system produced artifacts all over the terrain. (not a typo: graphical glitches are “artefacts”, ancient relics are “artifacts”. I read that somewhere and internalised it, so it must be true) I actually got it working perfectly wherever 2 biomes met, but that was the limit: at any intersection with more than 2 it produced hard edges and odd colours, and the moment it was animated these artefacts started jumping about and generally making themselves easy to spot.
So I ended up scrapping the idea entirely, and starting over with a new strategy, one requiring less math and more art.
This new strategy was much simpler: we go back to using the ‘stencil painting’ system, but this time once we’re done painting with the first 4 stencils (biomes), we put a new, transparent canvas over the existing canvas and keep on painting on that with a new set of stencils. Rinse and repeat.
This method turned out to have it’s own set of pitfalls, chief among them, alpha-blending and redrawing the entire terrain multiple times, with different textures each time. For an item which takes up as much of the screen as the terrain, this is a large graphics cost, and in a GPU-bound game probably would have spelled the end of this strategy. But Species is CPU-bound: it has GPU cycles to spare. So full-steam ahead.
The artefacts of this method also turned out to be quite different to the ones I faced with the other method. The other method loved to produce singular, localised artefacts: hard edges and biome colours where they shouldn’t be. This method’s artefacts usually affected the entire terrain. I’d say two in particular are worthy of noting here, mainly because I haven’t actually managed to fix them: double rendered polygons and biome-set edges.
Biome-set edges were where one transparent layer tried to fade out into another. I never had any trouble with the inter-set blending, but proper alpha blending is a temperamental thing. In this case, because the biome colour fades out at the same time as the opacity does, the end result was a faded-but-noticeable black ‘border’ between different blend-sets.
I managed to ‘fill-in’ the majority of these borders by extending the colour to the very edge, but there is still a faint one around the first draw pass. Thankfully it’s subtle, and dealing with it had some odd side effects, so I’m going to leave that one alone. It’s not hugely noticeable.
Double-rendered polygons, on the other hand, are a problem.
This isn’t actually a problem with the rendering method: it’s a problem with the QuadTerrain itself, which I didn’t know about until the rendering method made it visible. See, when the terrain is completely opaque, rendering a polygon twice has no effect. The colour from both renderings is the same, so it’s an invisible artefact. But when you render a *transparent* object, like, say… one of the 4-biome passes of the terrain… *then* it becomes quite visible, as you can see above.
But fixing it means re-familiarising myself with the QuadTerrain class, which I haven’t touched in quite some time. I’ve already made a little progress, eliminating about half of the artefacts above with one fix. Hopefully the next fix will get the rest, but I doubt it: bugs like this are often inversely exponential. You might be able to fix the majority of them easily, but there are always one or two subtle, extremely well hidden ones that you have next-to-no chance of ever finding.
Oh well, best I can do is to make sure I get most of them.
Currently, I have 23 biomes defined as rough shapes on a temperature/fertility axis. This includes ‘extreme’ biomes, like lava and salt-plains, and a number of underwater biomes that will only be found… err, underwater. (Fertility will at least partly be determined by height: everything below the water plain will be water).
So far everything is coming together as planned. Biomes are done, 3d trees are done (I’ll do a proper post on them later), I’m midway through tying the two together, and soon the nanozombies will be unleashed on the unsuspecting… oh wait wrong blog. You didn’t hear that.
“Other stipulations of Australian citizenship include:
– Must defend vegemite no matter personal opinion of taste. (sticky salty gunk)
– Must be willing to throw foreign tourists in front of a croc to save yourself. (Or was that the other way around?)
– Must know how to defend against drop-bears (trick question: there is no way to defend against drop bears)”