Karolina
Motužytė




Raymarched Terrain Shadows for Large-Scale Simulation
I worked on this during my internship at MultiSIM - a company specializing in flight simulation for training. During this I was tasked with researching and implementing large-scale shadows for their terrain.
This blog post follows the demo I worked on as a prototype before moving to their code-base.
The code can be found here.
A more technical blog post can be found here.

Why raymarching?
-
Visual quality
-
Heightfield raymarching is similar to ray tracing, so techniques like Monte Carlo sampling can be used for realistic soft shadows.
-
Since the scene has only one main light source, there is more performance budget for better shadow quality.
-
-
Suitability for terrains
-
Generating SDFs from mesh geometry can be expensive and may make raymarching less practical.
-
Terrains already provide a heightmap, which is usually enough for direct heightfield raymarching.
-

The Core Challenge: Heightfields are not SDFs
-
The Issue: Using standard sphere-tracing rules leads to "overshooting," where the ray passes through steep mountain slopes, causing holes and visual artifacts.
-
The Fix: I redesigned the traversal logic using adaptive step size control, lerping the step size based on the gap between the ray and the surface to maintain precision where it mattered most.

Ensuring peak performance
Naive raymarching of a massive terrain is prohibitively slow, often dropping performance to ~13 FPS. More performance issues include VR and the scale of the terrain.
I implemented several layers of acceleration to reach 150 FPS.
-
Max Mip Maps - inspired by this paper, I built a hierarchical acceleration structure where each mip level stores the maximum height of its children. I used
-
DDA Grid Traversal: I used Digital Differential Analyzer (DDA) algorithm to traverse through texels of the heightmap. By using simple additions to find the next grid boundary, I boosted performance by nearly 25%.

Dealing with massive scale
Problems:
-
The terrain is composed of hundreds of chunks, so i needed to find a smart way to raymarch through all of them
-
The chunks account for the Earth’s curvature, meaning they are often slightly rotated. This presented a significant hurdle for DDA.
Solutions:
-
Bayer Dither shadow updates: Shadows were baked and updated every frame using the Bayer dither pattern to account for the moving sun. This way only 1/16 of the texture was updated per frame.
-
Building a BVH: I built a BVH for the chunks, thus greatly accelerating chunk traversal.



.png)




.png)