/Voxels

GPU-based implementation of Dual Contouring in Unity for destructible voxel terrain.

Primary LanguageC#MIT LicenseMIT

Voxels.mp4

Voxels

GPU-based implementation of Dual Contouring in Unity for destructible voxel terrain.

The core features are:

  • Infinite procedural world
  • Seamless chunked level of detail
  • Multiple materials with smooth material transitions
  • Graph-based terrain generation using XNode

Note: Sharp voxel terrain features are preserved, not by solving the QEF as described in the paper above, but by using the Schmitz Particle method instead, which is much easier to implement and supposedly faster.

Note: The Unity version used is 2021.1.16f1.

Materials

The voxel terrain can be made up of a practically infinite amount of different materials. Materials are defined via a simple enumeration called MaterialIndex. Since the implementation is leveraging the GPU for generating the mesh, some structures have been defined multiple times, once in C# and once in HLSL. This is also the case for the MaterialIndex. The HLSL implementation can be found here.

Each material can be assigned a different texture through a ScriptableObject:

Material Config

The material index of a voxel is encoded as an unsigned integer and is used later on (as a custom VertexAttribute) to render the generated mesh with the correct textures. The material index can be queried from scripting, as well.

Texturing

Texturing of the voxel terrain is done with a custom URP PBR shader and supports:

  • albedo mapping
  • normal mapping
  • metallic mapping
  • occlusion mapping
  • height mapping
  • smoothness/roughness mapping

Since the procedurally generated terrain doesn't have any UV coordinates, Triplanar mapping is used to apply the various textures.

Note: I'm using a custom shader because Unity's shader graph doesn't support a geometry pass, which I need to enable smooth transitions between different voxel materials.

Note: Textures are taken from https://ambientcg.com/ and fall under the Creative Commons CC0 1.0 Universal License.

Terrain Generation

Terrain generation can be configured through a graph-based editor:

Generation Graph

Features include:

  • Fractional Brownian Motion nodes
  • Domain Warping nodes
  • CSG primitive nodes, namely a cuboid and a sphere primitive node.
  • Material nodes.
  • CSG operation nodes to combine FBM noises and CSG primitives.
  • Transform nodes to translate, scale, rotate FBM noises and CSG primitives.

Note: Keijiro's Noise Shader Library is used to generate simplex noise on the GPU.

Note: See this question for more insight on how I evaluate the graph to generate the terrain on the GPU.

Level of Detail

LOD

The implementation for LOD is inspired by Sebastian Lague's video "Procedural Landmass Generation (E21: fixing gaps)". Just like in the video, the skirts of a chunk are always generated at the highest level of detail, ensuring that there are no gaps between different level of details. The actual implementation obviously differs quite a lot since I'm not dealing with heightmap terrain.

Why publish it for free?

I spent quite some time on implementing various voxel terrain algorithms (Marching Cubes, Cubical Marching Squares, Dual Contouring) and noticed during the process that although there are implementations online, they often lack features like level of detail or multiple material support.

Furthermore, getting voxel terrain to be performant can be quite hard although I'm sure my implementation can be improved, too. That being said, my whole GPU-based approach might be suboptimal in the first place since I have to read back the mesh to the CPU.

In the end I kind of lost motivation to continue working on this project and decided to move on. The project is nowhere near feature-complete to be released as an asset. Besides, I do not want to deal with providing customer support. Releasing it for free was basically the easiest way of getting it out to the public.

I hope - by making this publicly available - I can help some people who are interested in voxel terrain.