Demo Video

New demo video for the project:

The video shows the usage of our demo application, which could generates different terrains given different user-specified parameters, render them, and manipulates them in real time. I found the mouse position in the video is not quite correct, but that’s due to the problem of my screen recording software.

Texturing Terrain

Texturing is essential to improve the visual appearance of object. When texturing, the 3D position on the surface of object is transformed to a 2D uv coordinate for sampling. In heightmap-based terrain, this could be easily done by one planar projection. However, due to the topological complexity of voxel terrain, single planar projection would cause distortion along different direction.

To avoid distortion, we instead uses an elegant technique named triplanar texturing, also suggested by GPU Gem. Triplanar texturing literally performs three planar projections respectively on xy-plane, yz-plane, and xz-plane. Triplanar texture then performs a weighted sum of three values, where the weight is the outward normal vector. For example, if the outward normal vector points mostly in x direction, the value of yz-plane would be the main component. Here let’s have a look at the effect of triplanar texturing (of course with bump mapping):

Triplanar texturing

Triplanar texturing

Indeed, there is no distortion. However, we can easily notice repeated tiling of the texture. The tiling artifact remains a dilemma in texturing large areas like terrains. If the texture scale is small, tilling artifact becomes obvious in a distant view; If the texture scale is large, the detail of terrain becomes blurry. In this project, we try to reduce the artifact by employing several techniques.

The first technique is called Multi-UV mixing, which is described on https://udn.epicgames.com/Three/TerrainAdvancedTextures.html. Multi-UV mixing is a low-cost method for improving terrain textures and decreasing apparent tiling by mixing one texture at two different UV scales. The advantage of using the same texture twice is that it does not require additional resources. For example, given a UV coordinate (u,v), the texture is sampled both at (u, v) and (0.25*u, 0.25*v). The latter value serves as a low frequency component to be modulated (multiplied) by the former value which serves as a high frequency component. The repeating period thus gets a 4x increase. Let’s see what the terrain looks like after applying the technique. After mixing different UV scale, the repeatedness is reduced remarkably.

Multi-UV Mixing

Multi-UV Mixing

The second technique is coherent noise. Coherent noise is the “ultimate weapon” against repeatedness. A noise function can be considered as an infinitely large texture with infinite preciseness. Coherent noise also generates natural or visually appealing pattern which is easy to blend into other patterns. To further break the repeatedness, here we add an extra macro layer of noise to adjust the color of the terrain:

Noise blended in

Noise blended in

Note that the brightness and the color of terrain is more variant now.

Finally, terrain texturing should support multiple textures for more diverse look. To control the distribution of multiple textures, an extra volumetric splatmap is introduced. Here, the four channels of a splatmap could be used to control four terrain textures. The terrain starts to become cool, and even more awesome with some lights and a skybox!!

Multiple textures

Multiple textures

Here is some more zoomed-in screenshots. We can see the terrain has pretty rich details and variation:

Zoom-in 1

Zoom-in 1

Zoom-in 2

Zoom-in 2

Marching Cubes on GPU

After one week of hard work, we have successfully implemented a GPU version of the Marching Cubes algorithm. Here are some  screenshots (Although it would be nicer to have a Unity web player, it seems to not be able to support compute shader and other dx11 features):

A simple sphere shape

A simple sphere shape

A heightmap-based terrain

A heightmap-based terrain

And a intrinsic terrain generated by 3D noise

And an intrinsic terrain generated by 3D noise

So what basically the algorithm does is to transform the 3D representation of voxel terrain into triangular mesh, which can be then sent to the rendering pipeline. A voxel terrain is usually defined by a 3D density function, let’s say p(x,y,z). For any point (x0,y0,z0) in 3D space, if p(x0,y0,z0) < 0 then the point is located in empty space, if p(x0,y0,z0) > 0 then the point is located in solid terrain, and if p(x0,y0,z0) = 0 then the point lies on the surface of the terrain. To actually render such voxel terrain, it is necessary to find out the surface or boundary of the terrain, and that’s what the Marching Cubes does. For more details, see the original paper: Lorensen W E, Cline H E. Marching cubes: A high resolution 3D surface construction algorithm[C]//ACM siggraph computer graphics. ACM, 1987, 21(4): 163-169.

The algorithm works on individual cube blocks of 3D space, generating triangles for each of them. The Marching Cubes algorithm could be parallelized naturally because it processes the whole volume in a block-by-block fashion. Therefore, this project implements a Direct Compute version of the Marching Cubes algorithm that utilizes the parallel computing ability of GPU for remarkable acceleration. This idea is first inspired by the first chapter of GPU Gem 3: http://http.developer.nvidia.com/GPUGems3/gpugems3_ch01.html. We have also found another exciting blog that introduces one implementation based on Direct Compute: http://scrawkblog.com/2014/10/16/marching-cubes-on-the-gpu-in-unity/.

In the original paper, the algorithm is based on a precomputed lookup table that map all possible cases of a block to a sequence of vertices that form the triangles. Although conceptually only one lookup table is required, using only this table is not efficient enough in implementation. The number of triangles per block is not determined until it has been processed. Thus, the output buffer must be allocated with the largest possible size (5 triangles per block), which would both cause serious waste of memory and worsen the bottleneck of transferring data between CPU and GPU. To remove redundant storage and calculation, we come up with a two-pass solution that uses an additional lookup table that stores the number of triangle per block for each possible case. Based on the additional table, The first pass only collects the actual number of all triangles. Finally, the second pass uses that number to allocate appropriate size of buffer, and actually runs the Marching Cubes algorithm. (The idea is inspired from Ludwig Pethrus Engström, a KTH master student.)

Staring Point: Project Specification

Hey there! We are Yanbo Huang, Huiting Wang, and Yang Zhou. This is the blog for the course project of DH2323 Computer Graphics and Interaction in KTH. As the blog title suggests, the project is about procedural generation and rendering of terrain. Terrain in games or other graphics application is essential because it is usually the major visual element, and…well we simply love to see a massive badass terrain with complex shape and rich detail, like those in the latest AAA titles (ok I admit that’s far too beyond our scope, but we’ll try).

The project consists of two part: terrain generation and terrain rendering. We plan to follow a two-stage process: First, generating data for various components that define terrain, and second, rendering the terrain in 3D environment. For the first stage, we consider these components so far:

  • Elevation: The most basic information that defines the shape of terrain. Different elevation values and gradients leads to different fundamental geometric structure, such as summit, canyon, plain, etc.
  • Water: An important component of terrain in real world. The distribution of water resources as well as the shape of river network vary greatly under different conditions. Moreover, the complicated physical interaction between water and land is a major factor that influence the appearance of a terrain.
  • Biome: Biomes add great visual realism and diversity to a terrain. To our knowledge, however, biome generation on a terrain seems to lack attention, compared with generation of other components.

Since there are several types of information we need to generate, it is essential to discover a structure to store or annotate them. We are interested in dividing the whole terrain to multiple polygonal areas, and annotate these areas procedurally. We will see how to actually do it later.

Although the generation part of this project maybe limited to heightmap, on the other hand we want to be able to render voxel terrain in the rendering part. Therefore, after the initial generation, it is possible to edit the terrain, such as digging holes, in real time, just like what people do in Minecraft. Although the real-time editing may not be implemented in this project, voxel terrain rendering keep the possibility for it. Here, the most famous isosurface extraction algorithm, namely the Marching Cubes algorithm will be adapted. However, inspired by the first chapter in GPU gem 3, we intend to utilize GPU power to accelerate the algorithm.

The game engine Unity is selected as the platform for implementation. On GPU side, we choose to use Direct Compute, which is also integrated in Unity. The final deliverable is expected to be a middleware of the engine, given user-specified parameters to generate unique terrain every time.