Sunday, May 19, 2024

Global details

It's time to think about adding detail to the planets. The ultimate aim is to create regional maps similar to those in the old version of Undiscovered Worlds, but wrapped onto the sphere. My initial thought was to generate an entire globe's worth of these while the user is looking at the globe, adding them on as they are generated - but that is too much detail to hold in memory at once. We need, then, a more dynamic system, which can generate new regional maps and delete old ones as the user moves around the globe, so we only store the ones we actually need.

This creates a problem though. Here again is how the cubesphere is constructed:


If this is a large world, then each of the small panels corresponds to a single regional map. (With small or medium-sized worlds, it's still constructed from the same number of panels, but a single regional map would be spread over several panels - four each for a medium-sized world, or sixteen for a small one.) So as the user moves around the globe, each panel will display either its portion of the global map texture or its own regional map, depending on how close it is to the viewer.

Clearly, for this to work well, we want to display regional maps only when they are pretty close to the viewer. Otherwise we would have to be generating masses of them every time the user scrolls around even a little bit.

The problem is that the global texture looks quite blocky quite quickly as you zoom in. It's just not highly detailed enough to let us get away with generating only very close regions.

The solution is to make the global texture more detailed. Rather than making the world object (that is, the data structure that holds all the information about the world) more detailed itself (as I did once before), I've created a much simpler data structure that only holds information needed to generate the map textures - basically elevation, temperature, rainfall, river flow, and one or two other things. Since it's much simpler than the "real" world object, it can be four times as detailed without taking up too much memory. Once the world is generated, we populate this "simple world" on the basis of the "real" one, mostly using a simple diamond-square algorithm similar to the one used for regional maps. Mountain ranges and rivers are drawn more directly on, to maintain their detail. Then we just use that to create the main world textures. Since the "simple world" is only used for generating those textures, and doesn't contain information that the user can access otherwise, we don't have to worry about details such as carving out river valleys and the like, so it's very quick to generate.

The "simple world" has a resolution of 4x4 the "real" world, which means that the global textures can now be 16 times as detailed. This only applies to the main textures, showing the world pseudo-realistically - the other textures, showing information such as elevation, temperature, etc., remain in the old resolution. So for example, here are some shots of a single area showing elevation, rivers, and basic terrain colours, all in the "true" resolution:




And here is the same area with the higher-detailed texture plus fancy shaders (and clouds dialled right down so you can see the details more clearly):


It's a pretty simple technique, and there are certainly a fair few wrinkles still to be ironed out, but I think the initial results are quite decent:


With this in place, we can now zoom in a fair way before the map looks too blocky. That means that, in theory, we can generate regional-scale maps and apply them to the appropriate parts of the globe only when the view is quite close - so we don't need to display many of them at the same time. Whether it will actually work like that, though, remains to be seen!