Skip to the content.

Procedural Terrain Generation in Unreal

Matan Botansky

The broad idea of this project was to make an actor in UE4 that generates a tile of terrain based on a 3-layer noise calculation that mimics real-life terrain, while utilising a mix of textures in reference to the noise calculation to form its material, all while involving a PRNG seed system that can regenerate the base noise maps for each terrain sample.

Generating the Noise:
In order to generate the noise in this project, I effectively created a two-demensional array of FVectors, where each component of the vector holds a different noise calculation. To do this, I tried to build around the PerlinNoise2D function from the FMath library. However, due to the geometry created by raw Perlin noise, I decided to add some complexity by introducing octaves, as well as several other components. After playing around with different iterations of noise maps, I decided to have the first of the three vector components (i.e. the red value in Figure 1) act as a primary for the height values of the mesh. The calculation for this component was done through simply taking a weighted average of the Perlin noise as generated by the seed value and its magnitude, where the magnitude holds a much higher weight, resulting in a lot more natural looking topography. The other two components of the noisemap, which are only used in the material, are also made of the same average with inverted weights and the same weighted average with the next seed, respectively. This process was repeated over each index combination, to provide noise values for each entry and acts as the backbone for the rest of the project.

Figure 1: NoiseMap at Seed 1 NoiseMap_Sample_1



Creating and Updating the Terrain Mesh:
To create the mesh I used Unreal’s ProceduralMeshComponent which is a dependency that has to be manually added in order to generate meshes of procedural geometry. Using asynchronous cooking, I was able to quite quickly render sections of mesh that could be updated by the editor when parameters are adjusted. This was done through several parameter arrays which I created from the first component of the noise data, most importantly including aspects such as the vertices and triangles of the mesh, as well as UV values such that the entire mesh could be covered by a single iteration of a texture. Naturally, the mesh is also created in a matter that can support collision and physics data.

Figure 2: NoiseMesh at Seed 1 NoiseMesh_Sample_1



Adding Textures the Mesh Material:
After the mesh was created, I went ahead and created a basic material that took the 3-layer noise map into account. In order to keep things simple, I decided that it would only interpolate between three textures (in this case grass, rock and snow). To get access to these textures I used the Megascans plugin which offers free surface textures when used in Unreal. As you can see by the example below, I made use of all three components of generated noise in order to keep the mix of materials look more natural. I went for this approach rather than going into landscape materials as I wanted everything to be rendered by the sole actor. I see landscape materials as something that is much more suited to manual creation than procedural generation as there are a lot more subjective factors involved when it comes to the looks of the final output.

Figure 3: TerrainMesh at Seed 1 TerrainMesh_Sample_1



In conclusion, this was a very enjoyable project, and while it did take some time it was well worth it. I believe I achieved what I set out to, and believe that while there is are endless features I could add (i.e. infinite terrain with LODs, foliage, fractals to the noise) that would improve this actor, this feels like a good stopping point for now. I may come back to this in the future.

~ March 13, 2022

Updated version to Unreal Engine 5.

~ July 20, 2022