Biome blending
Dithering to biome edges
This commit is contained in:
@@ -64,7 +64,7 @@ pub fn generate_biome_chunk(
|
|||||||
let moisture = sample_point(
|
let moisture = sample_point(
|
||||||
x as f64 + chunk_x as f64 * Chunk::SIZE as f64,
|
x as f64 + chunk_x as f64 * Chunk::SIZE as f64,
|
||||||
z as f64 + chunk_y as f64 * Chunk::SIZE as f64,
|
z as f64 + chunk_y as f64 * Chunk::SIZE as f64,
|
||||||
&cfg.moisture_layer,
|
&cfg.moisture_noise,
|
||||||
&noise_m,
|
&noise_m,
|
||||||
cfg.size.as_vec2(),
|
cfg.size.as_vec2(),
|
||||||
cfg.border_size,
|
cfg.border_size,
|
||||||
@@ -72,7 +72,7 @@ pub fn generate_biome_chunk(
|
|||||||
let temperature = sample_point(
|
let temperature = sample_point(
|
||||||
x as f64 + chunk_x as f64 * Chunk::SIZE as f64,
|
x as f64 + chunk_x as f64 * Chunk::SIZE as f64,
|
||||||
z as f64 + chunk_y as f64 * Chunk::SIZE as f64,
|
z as f64 + chunk_y as f64 * Chunk::SIZE as f64,
|
||||||
&cfg.temperature_layer,
|
&cfg.temperature_noise,
|
||||||
&noise_t,
|
&noise_t,
|
||||||
cfg.size.as_vec2(),
|
cfg.size.as_vec2(),
|
||||||
cfg.border_size,
|
cfg.border_size,
|
||||||
@@ -80,7 +80,7 @@ pub fn generate_biome_chunk(
|
|||||||
let continentality = sample_point(
|
let continentality = sample_point(
|
||||||
x as f64 + chunk_x as f64 * Chunk::SIZE as f64,
|
x as f64 + chunk_x as f64 * Chunk::SIZE as f64,
|
||||||
z as f64 + chunk_y as f64 * Chunk::SIZE as f64,
|
z as f64 + chunk_y as f64 * Chunk::SIZE as f64,
|
||||||
&cfg.continent_layer,
|
&cfg.continent_noise,
|
||||||
&noise_c,
|
&noise_c,
|
||||||
cfg.size.as_vec2(),
|
cfg.size.as_vec2(),
|
||||||
cfg.border_size,
|
cfg.border_size,
|
||||||
@@ -109,8 +109,9 @@ pub fn generate_chunk(
|
|||||||
biome_chunk: &BiomeChunk,
|
biome_chunk: &BiomeChunk,
|
||||||
biome_painter: &BiomePainter,
|
biome_painter: &BiomePainter,
|
||||||
) -> Chunk {
|
) -> Chunk {
|
||||||
let mut result: [f32; Chunk::SIZE * Chunk::SIZE] = [0.; Chunk::SIZE * Chunk::SIZE];
|
let mut result: [f32; Chunk::SIZE * Chunk::SIZE] = [0.; Chunk::AREA];
|
||||||
let mut data = [BiomeData::default(); Chunk::SIZE * Chunk::SIZE];
|
let mut data = [BiomeData::default(); Chunk::AREA];
|
||||||
|
let mut biome_ids = [0; Chunk::AREA];
|
||||||
let noise = SuperSimplex::new(seed);
|
let noise = SuperSimplex::new(seed);
|
||||||
for z in 0..Chunk::SIZE {
|
for z in 0..Chunk::SIZE {
|
||||||
for x in 0..Chunk::SIZE {
|
for x in 0..Chunk::SIZE {
|
||||||
@@ -132,13 +133,16 @@ pub fn generate_chunk(
|
|||||||
cfg.border_size,
|
cfg.border_size,
|
||||||
) * blend;
|
) * blend;
|
||||||
}
|
}
|
||||||
result[x + z * Chunk::SIZE] = sample;
|
let idx = x + z * Chunk::SIZE;
|
||||||
data[x + z * Chunk::SIZE] = biome_data.clone();
|
biome_ids[idx] = biome_chunk.get_biome_id_dithered(x, z, &noise, cfg.biome_dither);
|
||||||
|
result[idx] = sample;
|
||||||
|
data[idx] = biome_data.clone();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Chunk {
|
return Chunk {
|
||||||
heights: result,
|
heights: result,
|
||||||
biome_data: data,
|
biome_data: data,
|
||||||
|
biome_id: biome_ids,
|
||||||
chunk_offset: IVec2::new(chunk_x as i32, chunk_z as i32),
|
chunk_offset: IVec2::new(chunk_x as i32, chunk_z as i32),
|
||||||
..default()
|
..default()
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
use bevy::math::{UVec2, Vec3};
|
use bevy::math::{UVec2, Vec3};
|
||||||
|
use noise::NoiseFn;
|
||||||
use rayon::iter::{IntoParallelIterator, ParallelIterator};
|
use rayon::iter::{IntoParallelIterator, ParallelIterator};
|
||||||
|
|
||||||
use super::chunk::Chunk;
|
use super::chunk::Chunk;
|
||||||
@@ -120,6 +121,15 @@ impl BiomeMap {
|
|||||||
return Some(chunk.get_biome(x as usize - cx * Chunk::SIZE, y as usize - cy * Chunk::SIZE));
|
return Some(chunk.get_biome(x as usize - cx * Chunk::SIZE, y as usize - cy * Chunk::SIZE));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_biome_id(&self, x: usize, y: usize) -> usize {
|
||||||
|
let cx = (x as f32 / Chunk::SIZE as f32).floor() as usize;
|
||||||
|
let cy = (y as f32 / Chunk::SIZE as f32).floor() as usize;
|
||||||
|
|
||||||
|
let chunk = &self.chunks[cx + cy * self.size.x as usize];
|
||||||
|
|
||||||
|
return chunk.get_biome_id(x - (cx * Chunk::SIZE), y - (cy * Chunk::SIZE));
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_biome_data(&self, x: usize, y: usize) -> &BiomeData {
|
pub fn get_biome_data(&self, x: usize, y: usize) -> &BiomeData {
|
||||||
let cx = (x as f32 / Chunk::SIZE as f32).floor() as usize;
|
let cx = (x as f32 / Chunk::SIZE as f32).floor() as usize;
|
||||||
let cy = (y as f32 / Chunk::SIZE as f32).floor() as usize;
|
let cy = (y as f32 / Chunk::SIZE as f32).floor() as usize;
|
||||||
@@ -145,6 +155,37 @@ impl BiomeChunk {
|
|||||||
pub fn get_biome_data(&self, x: usize, y: usize) -> &BiomeData {
|
pub fn get_biome_data(&self, x: usize, y: usize) -> &BiomeData {
|
||||||
return &self.data[x + y * Chunk::SIZE];
|
return &self.data[x + y * Chunk::SIZE];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_biome_id(&self, x: usize, y: usize) -> usize {
|
||||||
|
let b = self.get_biome(x, y);
|
||||||
|
let mut max = 0.;
|
||||||
|
let mut idx = 0;
|
||||||
|
for i in 0..b.len() {
|
||||||
|
let blend = b[i];
|
||||||
|
if blend > max {
|
||||||
|
max = blend;
|
||||||
|
idx = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_biome_id_dithered(&self, x: usize, y: usize, noise: &impl NoiseFn<f64, 2>, scale: f64) -> usize {
|
||||||
|
let cur_id = self.get_biome_id(x, y);
|
||||||
|
let b = self.get_biome(x, y);
|
||||||
|
let n = (noise.get([x as f64 / scale, y as f64 / scale]) as f32) * b[cur_id];
|
||||||
|
for i in 0..b.len() {
|
||||||
|
let blend = b[i];
|
||||||
|
if blend == 0. {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if n < blend {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return cur_id;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ pub struct Chunk {
|
|||||||
pub heights: [f32; Chunk::AREA],
|
pub heights: [f32; Chunk::AREA],
|
||||||
pub textures: [[u32; 2]; Chunk::AREA],
|
pub textures: [[u32; 2]; Chunk::AREA],
|
||||||
pub biome_data: [BiomeData; Chunk::AREA],
|
pub biome_data: [BiomeData; Chunk::AREA],
|
||||||
|
pub biome_id: [usize; Chunk::AREA],
|
||||||
pub chunk_offset: IVec2,
|
pub chunk_offset: IVec2,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -17,6 +18,7 @@ impl Default for Chunk {
|
|||||||
heights: [0.; Chunk::AREA],
|
heights: [0.; Chunk::AREA],
|
||||||
textures: [[0; 2]; Chunk::AREA],
|
textures: [[0; 2]; Chunk::AREA],
|
||||||
biome_data: [BiomeData::default(); Chunk::AREA],
|
biome_data: [BiomeData::default(); Chunk::AREA],
|
||||||
|
biome_id: [0; Chunk::AREA],
|
||||||
chunk_offset: Default::default(),
|
chunk_offset: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,9 +10,10 @@ pub struct GenerationConfig {
|
|||||||
pub sea_level: f64,
|
pub sea_level: f64,
|
||||||
pub border_size: f32,
|
pub border_size: f32,
|
||||||
pub biome_blend: usize,
|
pub biome_blend: usize,
|
||||||
pub moisture_layer: NoiseConfig,
|
pub biome_dither: f64,
|
||||||
pub temperature_layer: NoiseConfig,
|
pub moisture_noise: NoiseConfig,
|
||||||
pub continent_layer: NoiseConfig,
|
pub temperature_noise: NoiseConfig,
|
||||||
|
pub continent_noise: NoiseConfig,
|
||||||
pub size: UVec2,
|
pub size: UVec2,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Submodule game/main/assets updated: 2f1fb1ba3b...d7389cf5b1
@@ -207,8 +207,9 @@ fn create_heightmap(
|
|||||||
) {
|
) {
|
||||||
let config = GenerationConfig {
|
let config = GenerationConfig {
|
||||||
biome_blend: 16,
|
biome_blend: 16,
|
||||||
continent_layer: NoiseConfig {
|
biome_dither: 16.,
|
||||||
scale: 450.,
|
continent_noise: NoiseConfig {
|
||||||
|
scale: 500.,
|
||||||
layers: vec![GeneratorLayer {
|
layers: vec![GeneratorLayer {
|
||||||
base_roughness: 2.14,
|
base_roughness: 2.14,
|
||||||
roughness: 0.87,
|
roughness: 0.87,
|
||||||
@@ -222,8 +223,8 @@ fn create_heightmap(
|
|||||||
first_layer_mask: false,
|
first_layer_mask: false,
|
||||||
}],
|
}],
|
||||||
},
|
},
|
||||||
moisture_layer: NoiseConfig {
|
moisture_noise: NoiseConfig {
|
||||||
scale: 450.,
|
scale: 500.,
|
||||||
layers: vec![GeneratorLayer {
|
layers: vec![GeneratorLayer {
|
||||||
base_roughness: 2.14,
|
base_roughness: 2.14,
|
||||||
roughness: 0.87,
|
roughness: 0.87,
|
||||||
@@ -237,8 +238,8 @@ fn create_heightmap(
|
|||||||
first_layer_mask: false,
|
first_layer_mask: false,
|
||||||
}],
|
}],
|
||||||
},
|
},
|
||||||
temperature_layer: NoiseConfig {
|
temperature_noise: NoiseConfig {
|
||||||
scale: 450.,
|
scale: 500.,
|
||||||
layers: vec![GeneratorLayer {
|
layers: vec![GeneratorLayer {
|
||||||
base_roughness: 2.14,
|
base_roughness: 2.14,
|
||||||
roughness: 0.87,
|
roughness: 0.87,
|
||||||
|
|||||||
@@ -38,8 +38,8 @@ pub fn paint_chunk(
|
|||||||
for x in 0..Chunk::SIZE {
|
for x in 0..Chunk::SIZE {
|
||||||
let idx = x + z * Chunk::SIZE;
|
let idx = x + z * Chunk::SIZE;
|
||||||
let height = chunk.heights[idx];
|
let height = chunk.heights[idx];
|
||||||
let biome_data = &chunk.biome_data[idx];
|
let biome_id = chunk.biome_id[idx];
|
||||||
let biome = painter.sample_biome(biome_data);
|
let biome = &painter.biomes[biome_id];
|
||||||
let mapper = mappers.get(biome.tile_mapper.clone());
|
let mapper = mappers.get(biome.tile_mapper.clone());
|
||||||
let tile_handle = mapper.unwrap().sample_tile(height);
|
let tile_handle = mapper.unwrap().sample_tile(height);
|
||||||
let tile = tiles.get(tile_handle).unwrap();
|
let tile = tiles.get(tile_handle).unwrap();
|
||||||
|
|||||||
Reference in New Issue
Block a user