Sébastien Morris

sebw.morris@gmail.com

Back

Procedural island generator

Runtime procedural island generation with GPU mesh calculation and rendering

A personal project exploring procedural generations techniques to dynamically construct floating islands at runtime. Using compute, vertex and fragment shaders to optimise both the generation and rendering.
An earlier implementation was used for the procedural generation in one of my other projects Skybound Odyssey.

Technical features:

Mesh calculation:

  • Marching Cubes Core: Marching Cubes algorithm using 3D Perlin Noise to calculate and save mesh vertices and triangle data directly into a GPU buffer.
  • 3D Perlin Noise implementation: Custom 3D Perlin noise using hash functions for the calculation of gradient vectors. 
  • Enhanced Mesh Verticality: Combining Marching Cubes with 3D Perlin Noise allows for the generation of more complex terrain, including overhangs and tunnels.
  • Border Smoothing: Applies a custom falloff function to the noise data, smoothly fading out island borders to guarantee a seamless and closed mesh surface.
  • Geometry Buffer: Calculates normal vectors for each vertex, saving them into a structured buffer alongside their object-space positions.
  • Indirect Arguments: Utlises and Indirect Arguments buffer to track and store the vertex count of the generated mesh.
  • GPU Optimisation: The mesh calculation is entirely executed on the GPU using compute shaders, making use of its multithreading capabilities.

Mesh rendering:

  • Shader Pipeline: Custom vertex and fragment shaders retrieve calculated position and normal data arrays from the compute buffer to draw the geometry.
  • Lighting & Depth Pass: Calculates the real-time diffuse lighting and dynamic shadow depth map in the fragment shader.
  • Shadow Pass: Processes the shadow depth map in a dedicated shadow casting pass.
  • Texturing: Triplanar UV mapping within the fragment shader to handle 2D texture sampling and ratio-based blending.

Generation:

  • Dynamic Chunk System: Outside chunk's dimensions shrink or grow dynamically. This accommodates for any world size rather than forcing multiples of a set chunk size value.
  • Batching: This system allows for larger chunk sizes, resulting in more efficient rendering batches. While a maximum chunk size gives further control based on the Culling performance demands.  
  • Separated Calculations: The chunks mesh calculation and rendering of are handled by the respective chunks.
  • Minimal CPU Usage: Once the compute shader is dispatched, The calculated vertex buffer is directly bound to the rendering shader pipeline. This avoids any data being handled on the CPU.
  • Indirect Rendering: The rendering shader is executed using indirect draw calls.

Future improvements:

  • Triplanar normal mapping for more detailed surface lighting.
  • Terraforming, for real-time adding and digging of the terrain.
  • GPU instancing of vegetation and props (trees, rocks, ...) using Poisson Disc Sampling.
  • Collisions and physics simulation

Motivations:

I started this project to further explore different procedural generation techniques. Specifically more complex mesh generation rather than voxel generation. This project was originally used in Skybound Odyssey and since then I have made many modifications, greatly improving its performance, making better use of the GPU and compute, vertex and fragment shaders. A challenge I have really enjoyed.
This project was also inspired by Sebastien Lague, while watching a few of his videos, during which he talked about different techniques for generation, rendering and optimisation. I then wanted to experiment and adapt them for my specific uses.

    Unity 3D, Compute Shader, Vertex/Fragment Shader