Where do you even start developing a game? There's so many things you need to work on at the same time.
A good starting point probably is the terrain and general environment, so let's take a look at how that developed.
As with any feature, it starts very simple. Over time we get a better idea for what exactly we need and we keep iterating to improve and expand.
Since we knew it would be a grid-based game again our starting point was the Parkitect terrain. The main challenge is that you have to be able to build paths and buildings on the terrain, which means the terrain can't be too bumpy, but we still wanted it to look somewhat smooth and natural.
What we came up with is not too different from Parkitects terrain actually - it's secretly still using the same blocky slopes that work well for putting paths on them, but then we add a bunch more polygons to it, smoothen it using ideas from Bezier surfaces and add a bit of random bumpiness.
This creates the problem of the bumps in the terrain clipping through the paths...
...which we can solve by flattening the terrain wherever a path is.
Another technical challenge we had to solve that our terrain could only be a single big rectangle initially, but we wanted to create maps that are very irregularly shaped sprawling woods, with little pockets where you can build.
Creating this kind of playable space inside a big rectangle would mean there'd be a lot of wasted space, which is bad for performance. We solved it by splitting up the terrain into lots of small rectangles that can be created wherever we want, which allows us to give the map a much more freeform shape.
And since the terrain was more detailed than Parkitects we also had to add a system for reducing details in far-away areas.
Finally, to make the terrain look more interesting we added a way to paint it with a bunch of different textures.
To decorate the terrain even more we wanted a way to place lots of objects on it, for example blades of grass.
Figuring out a fitting style for the grass took some iterations. Especially early on we didn't fully know what the game was going to look like yet, so the first version was more of a technical test:
Eventually we figured out that having a nice transition between the terrain texture and the grass is really important for it to look good.
On the technical side, the key to achieving this was to give the grass the same normals as the terrain to make everything look less messy, and to fade its color towards the terrain texture at the bottom.
Here's a test where they blend together more nicely:
And finally it received some more texture to reach the current state. In addition to the grass there's a couple of other objects that can be spammed across the terrain.
This is getting quite technical now, but there were a few questions that stumped us for a while:
- how do you store grass in the savegame? Obviously you can't store the position of each individual blade of grass, that'd be way too much data
- how do you even keep the grass in memory? Keeping hundreds of thousands of positions for the grass blades on a huge map in memory would be too much
The answers came from a great video on the grass in Ghost of Tsushima: you create a low-resolution density map that says how much grass should be in an area, then when that area becomes visible you generate the data you need for the grass instances (i.e. the position, rotation, which mesh to use) - we do this in a compute shader, so it's super fast. When the area goes invisible you can unload all that instance data. So all you ever need to have in memory is what's visible, and all you need to store in the savegame is the low-resolution density map.
This allows to spawn large amounts of small objects at low performance cost.