So I have this plane generated with two different Perlin noises. It has mainly 3 regions, divided by color. I want to smooth out the lines, to create a "gradient" so there are no abrupt color changes:
Each zone corresponds to a biome which is decided by a PerlinNoise called Humidity and another one called Temperature, so each vertex receives a biome according to the following chart with its corresponding humidity and temperature vertices' height:
So this is my code (I commented almost every step):
//CREATES the terrain material and geometry + adds the color attribute
let TerrainMaterial = new THREE.MeshPhongMaterial({side:THREE.DoubleSide, flatShading: true,vertexColors: true});
let TerrainGeometry = new THREE.PlaneGeometry(step, step, 16,16);
TerrainGeometry.setAttribute( 'color', new THREE.BufferAttribute( new Float32Array( TerrainGeometry.attributes.position.count * 3), 3 ) )
const colors = TerrainGeometry.attributes.color;
//The position like this is to create a grid so every tile is next to eachother
let terrain = new THREE.Mesh(TerrainGeometry,TerrainMaterial)
terrain.position.set(x, 0, z).multiplyScalar(step)
this.experience.scene.add(terrain)
// Create some variables
const TemperatureVertices = TemperatureTerrain.attributes.position;
const HumidityVertices = HumidityTerrain.attributes.position;
let pos = TerrainGeometry.attributes.position;
const lerp = (a, b, amount) => (1 - amount) * a + amount * b;
//iteration through each vertex
for(let i = 0; i < pos.count; i++){
//gets temperature and humidity maps vertex height
let temperature = TemperatureVertices.getY(i) * 2;
let humidity = HumidityVertices.getY(i)* 2;
//this function returns the biome according with the chart in the post by giving it temperature and humidity variables
let BIOME = this.Biomes.determineBiome(temperature,humidity,new THREE.Vector2(x, z),i);
//This retrieves the fractional part of the numer, ex: frac(-2.8) = 0.8 or frac(10.09) = 0.9
var a = Math.abs(temperature) - Math.floor(Math.abs(temperature))
var b = Math.abs(humidity) - Math.floor(Math.abs(humidity))
//This variables determine the "blending zone", wich you will understand later
let AMPLIFIER = 0.1;
let AMPLIFIER1 = 0.9;
//Instantiates the temperature and humidity variables
let temperature_blending = temperature;
let temperature_weight = 1;
let humidity_blending = humidity;
let humidity_weight = 1;
//This is executed if the temperature is close to the next biome chart row/column
if(a < AMPLIFIER){
//This algorithm gives me like a percentage of how much the vertex is influenced by the other biome.
let x = Math.abs(temperature);
temperature_weight = (x - Math.floor(x)) / AMPLIFIER
//here based on the temperature, I can detect what is the closer column-
if(temperature > 0){
temperature_blending -= 0.5
}else{
temperature_blending += 0.5
}
//here I repeat the process but backwards as my function has to work with negative numbers when the closest biome column is further away than the original one.
}else if(a > AMPLIFIER1){
let x = -Math.abs(temperature);
temperature_weight = (x - Math.floor(x)) / AMPLIFIER
if(temperature < 0){
temperature_blending -= 0.5
}else{
temperature_blending += 0.5
}
}
//here I repeat all the process but for humidity
if(b < AMPLIFIER){
let x = Math.abs(humidity);
humidity_weight = (x - Math.floor(x)) / AMPLIFIER
if(humidity > 0){
humidity_blending -= 0.5
}else{
humidity_blending += 0.5
}
}else if(b > AMPLIFIER1){
let x = -Math.abs(humidity);
humidity_weight = (x - Math.floor(x)) / AMPLIFIER
if(humidity < 0){
humidity_blending -= 0.5
}else{
humidity_blending += 0.5
}
}
//Once we get here, We have the original vertex biome and the closest biome to it (if it is in the blending zone: very close to another biome implying that it has to start blending with it)
let BIOME1 = this.Biomes.determineBiome(temperature_blending,humidity_blending,new THREE.Vector2(x, z),i);
//I am very lost from here, I also think that the way to calculate the weights is incorrect.
//this calculate the average between both climatic factors
let average = (humidity_weight+temperature_weight)/2
//Here I try blending the colors between them using the average
colors.setXYZ( i, lerp(BIOME.color.r,BIOME1.color.r,average), lerp(BIOME.color.g,BIOME1.color.g,average), lerp(BIOME.color.b,BIOME1.color.b,average));
}
The result which doesn't look well:
So if you know how I can correct it, or if an algorithm already exists please tell me. Thanks a lot!
EDIT:
I got to make it work thanks to enter link description here steps. (note that the heights are rounded numbers by preset):