Many of you may remember how the map would sometimes take a while to load or leave a white area while you were zooming and panning around. This was due to a series of downloads, data handling and image processing in a large number of simultaneous worker threads. One of the extra complexities was the enhancement of the contrast between deep and shallow water when the map was moved around.
The entire process has recently been redesigned. And here’s how it works:
The maps of Sailaway are not stored as 2D maps but as tiles with 900 by 900 height samples of the surface of the earth. Each tile is 0.25 by 0.25 degrees. These tiles are used to generate the terrain in the game and to deduct the map image.
The earth is 360 x 180 degrees, which means 360 / 0.25 x 180 / 0.25 = 1,036,800 tiles. If someone would zoom out to view the entire earth, roughly 1 million tiles would have to be downloaded and converted into a giant map image. To prevent such madness the data is also stored in copies with a lower resolution where 1 tile measures 0.5, 1, 2.5, 7.5, 22.5, 45, 90 and 180 degrees. When slowly zooming in from world size down to a detail of a specific port, all those levels are loaded and processed one by one, starting at the highest level of 180 degrees per tile down to the deepest level of 0.25 degrees per tile.
You can imagine this is a lot of data to download at run time and to increase the speed a bit we packed the top 6 levels of 2.5 – 180 degrees with the game, which is why the initial download when installing the game is somewhat big.
When you view a section of the map, it could be that you are looking at 1 tile, but as you pan the map, you will encounter a corner of that tile. Instead of 1 tile you are now looking at the 4 tiles that are located around that corner. In the old map window, we’d move 4 textures around behind the viewing rectangle when you were panning the map. In the new map window there are 4 static images layered on top of each other. Each will have the height map data of a single tile. If a pixel is outside the scope of the tile, it becomes transparent, allowing the image beneath it to show through. To the viewer, the 4 layered images appear as a single image that covers the viewed area entirely. This means that the conversion from height map data to a visual image (4 images) is now entirely done inside a shader and no longer processed in advance by the CPU.
Loading map tiles from the server is a slow process. Loading it from a local cached file is faster, but still not instantly. This means that the visible map will be loading at times when the user zooms in or pans around because the loader threads can’t keep up. Previously this would sometimes give white areas. In the new maps, there are 3 levels (of 4 tiles) and 1 base level (of 2 tiles) displayed all the time.
Basically this is a stack of layers with increasing resolution that each can transfer height map data into an image and may or may not be transparent to show the lower resolution beneath it. This way, the map may be blurry while a high resolution layer is loading, but it will never be white.
Finally the contrast between deep and shallow water needs to be optimized. When you are viewing deep ocean together with a shallow coastline, the dark blue of the deep ocean may represent a depth of 4800 meters and the light blue of shallow water may represent a depth of 150 meters.
But when you zoom in on the coastline, the colors change. The deepest water is now 170 meters and the shallow water 0 meters. Previously the whole map image had to be recomputed in a background thread on the CPU. With the new map window all that happens is that new values for the deepest and shallowest point are passed to the shader. These 2 parameters are set every frame, which allows for the nice gradual contrast enrichment effect that can be seen now.
The cool thing about all this is that it took only a week to code, test and optimize this all, but it took a few months before the idea to use a special shader instead of CPU image processing to appear and evolve in my head. That’s game development: You are pushing to get something done in time, which then sort of works but is not optimal. And then later on when you take some distance and look at the same problem from a different perspective you see how you should have build it in the first place. Usually there is no time or budget for a full rewrite, but Sailaway is my passion and it fully deserves a little extra effort every now and then.