We now have a team dedicated to terrain, and our initial efforts will soon be publicly available! Unity 2018.3 will ship with an update to the terrain system. This update features improved tools and performance by taking better advantage of the GPU. It also adds support for the HD and LW render pipelines, while being backward compatible with the built-in render pipeline and the existing Unity Terrain system.
Get the Unity 2018.3 beta now to get early access to the updates! Please be aware that the user interface and the API are both still subject to change as the beta is still under active development.
On the performance side, we added a GPU-instanced render path for terrain. In most cases, instancing yields a dramatic reduction in the number of draw calls issued. Many of our tests saw more than a 50% reduction in CPU costs (though, of course, actual numbers will depend on your platform and use case). You can choose this new render path by enabling ‘Draw Instanced’ in the Terrain settings:
When enabled, Unity transforms all of the heavy terrain data, like height maps and splat maps, into textures on the GPU. Instead of constructing a custom mesh for each terrain patch on the CPU, we can use GPU instancing to replicate a single mesh and sample the height map texture to produce the correct geometry. This reduces the terrain CPU workload by orders of magnitude, as a few instanced draw calls replace potentially thousands of custom mesh draws.
As a nice side effect, it also improves our load times! Not only can we skip building all of those custom meshes, but we can also use the GPU to build the basemap (pre-blended LOD texture); the GPU is much faster at that kind of thing. This also means that if you have your own custom terrain shader, you can now override the ‘build basemap’ shader and generate matching basemap LOD textures.
Instancing also improves the appearance of terrain normals; we decouple the terrain mesh normals from the geometry by storing them in a normal map texture that is generated from the heightmap and sampled in the pixel shader. This means the normals are independent of the mesh LOD level. Consequently, you can increase the ‘pixel error rate’ to decrease vertex cost, with fewer artifacts.
We also developed terrain shaders for both the HD and LW render pipelines, available in package versions 4.0.0 or later, with support for instanced rendering and per-pixel normals. The HD shader was further enhanced to support new features such as height and density blend modes, normal scaling, texture controlled surface metalness and smoothness. The HD terrain shader is limited to a single pass, but it does support blending up to 8 terrain layers in one pass.
On the editor side, we have exposed a script API for building your own custom terrain tools, along with a suite of utility functions you can use to easily implement seamless cross-tile sculpting and painting operations on the GPU. The new TerrainAPI includes TerrainPaintTool<T0>, a base class for terrain tools, and TerrainPaintUtility, containing utility functions for modifying terrain data.
Applying these changes, we converted all of the existing terrain tools to GPU operations. Aside from making these tools much faster, this also gave us larger brush sizes, improved brush previews, and the ability to paint across terrain tile borders with automatic seam-stitching.
We’ve also begun experimenting with brush features such as brush rotation and randomization and more advanced painting tools, like heightmap and mesh stamping, clone brushes, and more. These painting tools features are currently not in 2018.3, but we are making them available via our GitHub Terrain Tools project.
We made it easier to work with multiple terrain tiles. Aside from seamless painting between terrains, you can now manage the connections between neighboring terrains automatically. Previously, this required writing a script to connect neighbors manually.
Enable ‘Auto connect’ in the Terrain Settings, and the Terrain will automatically connect to its neighbors with the same grouping ID.
When expanding your existing terrain, you can use our new ‘Create Neighbor Terrain’ tool to quickly add matching terrain tiles along empty borders.
We are also working to make resizing and resolution changes less destructive. In 2018.3, the heightmap and splat maps will resample when you change their resolution, instead of the previous behavior of clearing the data and losing all of your work. We are working towards improving all resizing operations in the near future.
In order to simplify workflows, we also created two new terrain-related asset types: the TerrainLayer asset and the Brush asset.
|TerrainLayer lets us define terrain materials independent of the terrain object so that we can easily track the same material across multiple terrains. This helps with seamless painting and material modification. We also extend the TerrainLayer asset to support “mask map” textures, which can be used for arbitrary shading purposes, and a script interface to provide shader-dependent custom GUI for the TerrainLayer asset.
|The Brush represents the GPU brush shapes used by painting and sculpting tools. They are now defined by a texture and a radial falloff curve. This makes it much easier to create and tweak brush shapes (which previously required dropping arcanely crafted image files into a specially named folder).
We also added support for the R16 texture format (a single channel 16-bit format) to Unity. This allows us to avoid 8-bit quantization on our brush shapes, which can cause undesirable ‘terracing’ effects if used as a heightmap stamp.