I have lately been up to some terrain generation using the unity engine and C#, I was able to conquer most of the issues that I ran into but this one got me stuck without an efficient solution:
So before I explain my problem I'll explain what iv'e Achieved so far; By using perlin noise I have been able to generate a mesh and apply different heights to its vertices by combining multiple heightmaps. I'm also able to generate and destroy terrain chunks as well as manage the chunks' LOD based on the viewer's position, for optimization purposes. Next I attended to the biome area distribution system, for the area distribution I used a combination of 2 perlin noise functions representing temperture and moisture levels, with voronoi cell distribution, the world is divided into virtual squares by some modulo and another perlin noise function is used to create a function which returns a voronoi control point based on the virtual square it recieves as an input, so far just a voronoi control point distribution algorithm I had in mind, so far so good...
Next I wanted to make the terrain more interesting (It's designed for a survival game) so I started making my way towards having a unique noise function combination for each biome (Each voronoi cell) but this isn't going to be that easy... the seams between biomes will surely start to show and therefore a biome interpolation system is needed, at first i thought a simple weight function will do the work, meaning for each vertex calculate it's distance from adjacent biome cells and calculate the weight each cell has on that vertex: A value between 0 and 1, 0 = lowest effect(The biome point is really far away, too far to have any effect on the vertex); 1 = highest effect(The biome point is in the exact same position as the vertex, thus, it will have a maximum effect on the vertex's height and will be solely composited of the biome's unique noise function) and then calculate the sum of multiplying each biome's weight on the vertex by the biomes noise function at the vertex's position (Side note: The sum of all the biome points weights should always be 1).
Example of weight calculation for adjacent points:
In the picture: The weight of the biome pointed by the blue arrow will be about 0.1f (Small value because it's far away from the sample point thus it will have minimal effect on the height of the sample point). The weight of the biome pointed by the green arrow will be about 0.45f. The weight of the biome pointed by the pink arrow will be about 0.45f (same as the green pointed biome because it's the same distance from the sample point). Orange point = the sample point which the weights will be calculated accurding to it.
There is a type of algorithm using noise called cellular noise, It's some kind of voronoi distribution with something similar to what I'm looking for but it doesn't take into account the effect of other adjacent biomes to the final value, meaning the furthur a point is away from any biome control point the lowest it's going to be but it doesn't blend different biomes which is a must have for me, I hope I explained well my issues with this algorithm. Anyway, here is an example.
An example of Cellular noise heightmap:
A small chunk of code to clerify the final vertex height:
float HeightAtPosition(float x, float z)
{
//Returns an array containing information of all the adjacent biome
//control points(mainly their position and their biome type)
BiomeControlPoint[] adjacentControlPoints = GetAdjacentBiomePoints(x, z);
//Returns an array containing values between 0 and 1
//Iputs: An array of all the adjacent biome points, a sample coordinate
//Output: A float array containing the weight of each biome on the
// coordinate(between 0 and 1)
float[] weights = CalcWeights(adjacentControlPoints, new Vector2(x, z));
float finalHeight = 0;
for (int i = 0; i < adjacentControlPoints.Length; i++)
{
finalHeight += adjacentControlPoints[i] * weights[i];
}
return finalHeight;
}
This would have been a good solution if I could make these functions more performance efficient: GetAdjacentBiomePoints(x, z) and CalcWeights(adjacentControlPoints, new Vector2(x, z))
Another method I read about was bilinear interpolation but i didn't quite understand it's implementation so I'd be glad to learn from another source. this video discusses this method: https://www.youtube.com/watch?v=ujGW5y1x7JgCreating Minecraft in C++/ OpenGL - Part Four
I'd be glad to learn any new information and/or ideas from you :) Thank you in advance!

