Posts Tagged Biomes
There’s not too much to say about the obvious mechanisms of the 0.5.0 in-game grass: it uses the billboard system which I explained a while back. I could mention the other technical details: it only draws a few, nearby, vegetation nodes, grazing affects the length of the entire node, it fades out at a distance because there’s way too much of it to draw it across the entire map… okay, done that, now what?
Well, seeing as how talking about implementation is boring, I guess we might as well talk about the design aspects.
The moment I decided on grazing as a feature for 0.5.0, I knew I’d have to represent it somehow. The grass itself, though, wasn’t originally meant to be that representation. Indeed, I’m still not entirely convinced that grass is the best representation for it: rendering grass has limitations that make it less than ideal.
Okay, I’m in the middle of typing up this post and I’m beginning to realise that the height of the billboard grass really isn’t the best way to represent grazable material. That’s what I get for blogging about a feature I’m in the middle of coding. Oh the joys of an evolving project.
Okay, new approach: I’m going to use this post as an opportunity to get my thoughts in order before I go off and play with the code a bit more.
The plan (prior to about about 30 seconds ago) was to include a grazables container or bucket within each square of terrain. This container would contain all the energy that creatures could graze from, and how ‘full’ it was would determine how long the grass in that square was. Fertility loss due to grazing would occur when the bucket was empty and had to ‘buy’ more energy to regrow.
The big pro to this approach is that grass height shows you at a glance how much grazable energy the local area has. Unfortunately, there’s also a lot of cons:
– all grazable scatter-material grows like grass and is edible, regardless of what it actually looks like. This includes pebbles on rocky terrain, shells on the beach, salt in a salt plain, and lava rocks in lava.
– grass in an area is all the same height. Since an ‘area’ is an exact square of roughly 10m x 10m, this would be especially noticable at borders where grass on one side is short and grass on the other is long.
– fertility loss is applied on an area-scale, not on a local one. A creature eating at the very corner of an area will affect the fertility of ground 14.1421m away (+/- 10m, anyway. Oh who am I kidding, I have no idea how big the vegetation squares are), while not affecting the ground just behind it.
– Grass is invisible at a distance, so you can’t see the direct effects of grazing from far away.
Now, all of these are things that can be dealt with to eliminate or reduce their effect: scattering a squares vegetation a bit beyond it’s border would blur the straight line between squares, by applying fertility loss on a macro level makes it less apparent that it’s related to overall area and not to the actions of individual creatures.
But what if we could deal with all of these problems just by changing the way ‘grazable energy’ is stored? This is the idea I’ve just had:
Eliminate the energy buckets in terrain squares, and effectively remove all terrain-based control over grazable energy. Grass no longer has any limit: creatures can just keep grazing and grazing within their biome… until the biome changes.
With this system, a creature emits a ‘death aura’ while grazing, gradually reducing the fertility in a small area directly underneath themselves. Eventually, the biome under them degrades. This introduces a direct correlation between fertility and energy: a creature absorbs fertility from the ground and gains energy in exchange.
Since grazables are no longer dependant on area but on biome, we’ll be able to introduce a variety of biome dependant statistics (starting with a simple isGrazable boolean) as a central function of the simulation, rather than as something tacked on afterwards as was originally planned.
A conventient bonus is the fact that the ‘death aura’ code already exists, in the form of biome stabilisation from trees. The only difference is that where tree’s stabilise the habitat they’re best suited for (with the exception of some unbalanced pioneering species which make the simulation more dynamic by stabilising towards biomes they can’t survive in), grazing creatures stabilise the habitat towards arid, desert biomes, and then have to move on to find more grass.
Of course, I’ll have to rework some of the code for this: the ‘buckets’ system already exists in the development version. But that’s the nature of prototyping.
[The following day]
Welp, that’s done. This actually makes the environment feel a lot more ‘directed’, since you can now pinpoint the source of every fertility change: it’s either grazing creatures, trees or water. I might have to add a few more fertility-change sources, just to make it less predictable.
Ultimately, this change leaves the grass itself as little more than an aesthetic item. Oh well: the system’s in place now, it’s useful in defining the presence and quantity of grazable material in each biome, and when even the placeholder art looks good, you know you’re doing something right..
He doesn’t mean it about the vegans. We actually think vegans are pretty awesome: it must take a lot of willpower and strength of conviction.
Please don’t kill us with your psychic vegan powers.
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)”