Efficient runtime-generated 3d-tile-based terrain implementation techniques

I need to generate a large, procedural noise-based, 3d, tile-based terrain at runtime. The terrain needs to be streamable as players move about and terrain textures need to blend (e.g. blending grass/sand borders).

What is the best way(s) to achieve this from both a runtime performance and workflow efficiency perspective?

Reference:

A prototype (in Unity):

Possible Approaches

I’ve come across some viable solutions for this in Unreal, but given the number of possible approaches and my inexperience with Unreal’s rendering and mesh architecture, I’m unable to quantify the tradeoffs for each approach. Some help, please?

1) Define terrain tile mesh faces in code and generate static meshes at runtime for chunks of NxN tiles

  1. [Pro] Supports per-chunk occlusion
  2. [Pro] ? Texture blending possible (through custom vertex shader to which I pass data about terrain type of surrounding vertices)
  3. [Pro] ? No need to prune redundant vertices from generated chunks since Nanite makes this a non-issue
  4. [Con] Tedious and artistically limiting to define vertices in code for each terrain tile shape

2) Create tile meshes in 3d modelling software and instantiate them at runtime as ISMs

  1. [Pro] Can be more expressive in model implementation, while still maintaining exact border edges so that tiles fit together properly
  2. [Pro] Technically simple, and no need for tedious code which explicitly defines tile vertex positions
  3. [Pro] Supports per-tile occlusion
  4. [Pro] ? Texture blending still supported in the same manner as described above
  5. [Con] ? Cannot join these tiles into chunks of terrain at runtime, increasing frequency at which terrain is rendered/un-rendered (maybe this is not an important issue due to instancing of the static meshes?)

3) Use Procedural Mesh or Runtime Mesh Component to define tiles in code

Suggested here.

  1. [Pro] Potentially simpler code to define and instantiate tile/chunk meshes
  2. [Con] Procedural Mesh needs to be converted to a static mesh, which is possible but means there’s no performance gain over approach 1)
  3. [Con] Runtime Mesh Component costs money and adds a dependency to the project while likely not providing any performance benefit over approach 1)

4) ???

I’m guessing there are other possibilities and considerations I’m just not aware of, and probably I’ve made some incorrect assumptions. If so, please let me know, thanks!!

EDITS

  • Fixed typos
  • Changed approach 1) to generate static meshes and not instanced static meshes. There will be very little opportunity to benefit from instancing since few chunks will be identical, and it will be painful to identify identical chunks.