如何在二维网格中的固定值之间进行插值以生成生物群落



我目前正在游戏中实现生物群落生成,我想使生物群落的类型取决于由渐变噪声生成的humiditytemperature值。

不同的生物群落应该有不同的高度,如果没有插值,这将导致生物群落边界上的突然高度差异。

我试着把两个相邻的生物群落也放在网格中,并测量每个生物群落的混合百分比。

稍后,我从生物群落中获得3个不同的height值,并将每个值乘以其各自的blend值。

这是我用来获取生物群落的简化和精简代码:

const BIOME_GRID_SIZE: usize = 2;
const BIOME_INDEX_SIZE: usize = BIOME_GRID_SIZE - 1;
const BIOME_GRID: [[Biomes; BIOME_GRID_SIZE]; BIOME_GRID_SIZE] =
[
[Biomes::Mountains, Biomes::Forest],
[Biomes::Desert   , Biomes::Mesa  ],
];
fn get_height(coord: [i64; 2], noise: &Noise) -> i64 {
let temperature = (noise.get_2d(coord) + 0.5).clamp(0.0, 1.0);
let humidity = (noise.get_2d(coord /* + some offset */) + 0.5).clamp(0.0, 1.0);
let x = BIOME_GRID_SIZE as f64 * humidity;
let y = BIOME_GRID_SIZE as f64 * temperature;
let x_frac = (x.fract() - 0.5) * 2.0;
let y_frac = (y.fract() - 0.5) * 2.0;
let x_blending = x_frac.abs();
let y_blending = y_frac.abs();
let own_blending = 2.0 - x_blending - y_blending;
// direction of neighbour biomes
let x_direction = x_frac.signum() as isize;
let y_direction = y_frac.signum() as isize;
let x_index = (x.trunc() as isize).clamp(0, BIOME_INDEX_SIZE as isize);
let y_index = (y.trunc() as isize).clamp(0, BIOME_INDEX_SIZE as isize);
let biomes = get_biomes(x_index, y_index, x_direction, y_direction);
blend(
coord,
noise,
biomes,
[
own_blending,
x_blending,
y_blending,
]
),
}
// get main and neighbour biomes
fn get_biomes(x: isize, y: isize, x_direction: isize, y_direction: isize) -> [Biomes; 3] {
let mut biomes = [Biomes::Ocean; 3];
for (i, (d_x, d_y)) in [(0, 0), (x_direction, 0), (0, y_direction)].iter().enumerate() {
let x_index = (x + d_x).clamp(0, BIOME_INDEX_SIZE as isize) as usize;
let y_index = (y + d_y).clamp(0, BIOME_INDEX_SIZE as isize) as usize;
let biome = BIOME_GRID[x_index][y_index];
biomes[i] = biome;
}
biomes
}
pub fn blend(
coord: [i64; 2],
noise: &Noise,
biomes: [Biomes; 4],
blending: [f64; 4],
) -> i64 {
let heights: Vec<f64> = biomes
.iter()
.map(|x| x.get().height(coord, noise) as f64)
.collect();
let height = heights[0] * blending[0] + heights[1] * blending[1] + heights[2] * blending[2];
let height = height as i64;
height
}

这在某些情况下效果良好,但在另一些情况下则完全失败。

我不确定2个邻居是否足够,以及如何正确获得blend值。

这个问题有更好的解决办法吗?

对于双线性混合,通常使用四个点。如果我正确理解你的代码,那就是每个生物群落的四张高度图。然后,您通过一个轴(例如湿度(对具有相同另一个轴的两对进行lerp,然后再次通过另一个轴线(例如温度(对两个混合值进行lerp。