Terrain engine upgrade #6
During the past two months, I have been working 50/50 on Overview and SpaceEngine. Work on Overview continues: we are still not released on the Oculus Store, and are preparing some updates for the Steam and Viveport releases.
Regarding SE, I continue to work on the new terrain textures. The work has really taken too long, I started it in September(!). So I am planning to stop it soon and switch to other tasks (ray-marched nebulae and preparation for the release). I was not satisfied with the performance of the last experiments with real-time texture splatting, so I switched to pre-generated textures, which work like regular textures in the SE terrain engine. Instead of the material ID and material weight textures, generated for the last few levels of the terrain quadtree (typically, level 13 on an Earth-sized planet), SE now generates an additional 10 levels of quadtree nodes. Yes, such a large quadree depth is required to achieve 1 mm resolution. Previously, the maximum texture resolution was 1 meter per pixel, but if we want 1 millimeter, we need 1000 times greater resolution, i.e. log2(1000) ~= 10 more levels. The finest octree nodes have a "physical" size of just half a meter!
The new node textures have the same resolution of 256x256 as the regular textures, and contain only the result (color and normal maps) of the detail textures mixed by the new "splatting" shader. The shader's code is moved from the planet rendering shader with almost no changes. The visual result is the same as before, but with large advantages:
- Framerate is high again, 100+ FPS (on GTX 1060 at 1080p), like before implementing the detail textures. Additional nodes barely affect the performance.
- Framerate does not depend on the amount of materials used on the planet. The current limit is 64, but it can easily be increased to a few hundred. Complexity affects only the generation/loading time.
- No more sharp transitions, seams, or aliasing artifacts, caused by the limited number of materials stored in the splat textures, and discontinuities in the interpolation function. The splatting shader simply cycles through all materials used on the planet and blends them all together based on weights, which are computed in the same shader.
- Enables the ability to implement texture-heavy effects like parallax occlusion mapping (see below).
But this method has some disadvantages (as usual in computer science):
- Increased generation time. Now you have to wait while all super-fine additional levels are generated. The engine does this quite fast though, the splatting shader is much faster than the procedural texture generation shaders, used on the coarser levels of the planet.
- Increased video memory usage: the engine needs to store the textures of 10 additional levels of the quadtree. Using some optimal quality-to-speed settings, terrain now requires 700-800 MB of video memory, in addition to the 900 MB needed by the detail textures atlas. But this is without compression, which I plan to implement to reduce memory usage by 3-4 times.
- No more real-time changes of textures in the material editor, you have to press the "Update planet" button. However, I've implemented a fast reloading of the planet: SE just re-generates the textures that are in the field of view, not the entire planet.
Experimental POM (parallax occlusion mapping): it makes pebbles look volumetric, but reduces performance by one-third (but still 60 FPS on GTX 1060 at 1080p). POM is a heavy effect in all games. But it looks incredible, especially in VR! (Look at rocks on the right side of the screenshot). You can notice some seams - they appear because each terrain node has access only to its own textures for rendering. When a ray goes outside the texture boundaries, the shader doesn't know where to take pixels from. This can be addressed by passing all eight neighboring textures to the shader, or by a more elegant solution - virtual textures or clipmaps. In these techniques, quadtree tiles are stored in a single large texture in a continuous manner, so the POM shader can easily jump to the next node by simply ignoring its boundary. Or maybe I will implement a more radical method - tessellation. Of course, all of this is for future versions, I want to stop working on terrain as soon as possible, so as not to delay the 0.990 release any more.
The new texturing method works on real planets as well. They still lack intermediate details (on the scale of hundreds of meters), but I will not work on this for 0.990.
Discuss this post on the forum.