diff --git a/engine/world_generation/src/heightmap.rs b/engine/world_generation/src/heightmap.rs index 4160dce..f2f198d 100644 --- a/engine/world_generation/src/heightmap.rs +++ b/engine/world_generation/src/heightmap.rs @@ -3,12 +3,12 @@ use core::f32; use bevy::math::{IVec2, UVec2}; use bevy::prelude::{FloatExt, Vec2}; use bevy::utils::default; -use noise::{NoiseFn, SuperSimplex}; +use noise::{NoiseFn, Simplex, SuperSimplex}; use rayon::iter::{IntoParallelIterator, ParallelIterator}; use crate::biome_painter::BiomePainter; use crate::map::biome_map::{BiomeChunk, BiomeData, BiomeMap}; -use crate::prelude::*; +use crate::{map, prelude::*}; pub fn generate_heightmap(cfg: &GenerationConfig, seed: u32, painter: &BiomePainter) -> (Map, BiomeMap) { let biomes = generate_biomes(cfg, seed, painter); @@ -74,9 +74,9 @@ pub fn generate_biome_chunk( data: [BiomeData::default(); Chunk::AREA], tiles: Vec::with_capacity(Chunk::AREA), }; - let noise_m = SuperSimplex::new(seed + 1); - let noise_t = SuperSimplex::new(seed + 2); - let noise_c = SuperSimplex::new(seed + 3); + let noise_m = Simplex::new(seed + 1); + let noise_t = Simplex::new(seed + 2); + let noise_c = Simplex::new(seed + 3); for z in 0..Chunk::SIZE { for x in 0..Chunk::SIZE { @@ -86,7 +86,8 @@ pub fn generate_biome_chunk( &cfg.moisture_noise, &noise_m, cfg.size.as_vec2(), - 0.0, + cfg.border_size, + 100.0, ); let temperature = sample_point( x as f64 + chunk_x as f64 * Chunk::SIZE as f64, @@ -94,7 +95,8 @@ pub fn generate_biome_chunk( &cfg.temperature_noise, &noise_t, cfg.size.as_vec2(), - 0.0, + cfg.border_size, + 50.0, ); let continentality = sample_point( x as f64 + chunk_x as f64 * Chunk::SIZE as f64, @@ -102,6 +104,7 @@ pub fn generate_biome_chunk( &cfg.continent_noise, &noise_c, cfg.size.as_vec2(), + cfg.border_size, 0.0, ); let data = BiomeData { @@ -135,6 +138,7 @@ pub fn generate_noise_map(size: UVec2, seed: u32, cfg: &NoiseConfig, border_size &noise, size.as_vec2(), border_size, + 0.0, )); } return row; @@ -154,7 +158,7 @@ pub fn generate_chunk( let mut result: [f32; Chunk::SIZE * Chunk::SIZE] = [0.; Chunk::AREA]; let mut data = [BiomeData::default(); Chunk::AREA]; let mut biome_ids = [0; Chunk::AREA]; - let noise = SuperSimplex::new(seed); + let noise = Simplex::new(seed); let mut min = f32::MAX; let mut max = f32::MIN; for z in 0..Chunk::SIZE { @@ -175,6 +179,7 @@ pub fn generate_chunk( &noise, cfg.size.as_vec2(), cfg.border_size, + 0.0, ) * blend; } let idx = x + z * Chunk::SIZE; @@ -199,7 +204,15 @@ pub fn generate_chunk( }; } -fn sample_point(x: f64, z: f64, cfg: &NoiseConfig, noise: &impl NoiseFn, size: Vec2, border_size: f32) -> f32 { +fn sample_point( + x: f64, + z: f64, + cfg: &NoiseConfig, + noise: &impl NoiseFn, + size: Vec2, + border_size: f32, + border_value: f32, +) -> f32 { let x_s = x / cfg.scale; let z_s = z / cfg.scale; @@ -221,7 +234,7 @@ fn sample_point(x: f64, z: f64, cfg: &NoiseConfig, noise: &impl NoiseFn, } else { elevation += value; } - } + } if border_size == 0.0 { return elevation as f32; @@ -235,7 +248,7 @@ fn sample_point(x: f64, z: f64, cfg: &NoiseConfig, noise: &impl NoiseFn, let d2 = od.x.min(od.y); let d = d1.min(d2).min(border_size).remap(0., border_size, 0., 1.); - return (elevation as f32) * d; + return border_value.lerp(elevation as f32, d); } fn mask(mask: f64, value: f64) -> f64 { diff --git a/engine/world_generation/src/map/map_utils.rs b/engine/world_generation/src/map/map_utils.rs index f401d7e..d98d184 100644 --- a/engine/world_generation/src/map/map_utils.rs +++ b/engine/world_generation/src/map/map_utils.rs @@ -106,20 +106,20 @@ fn get_height_color_blend(base_color: Hsla, height: f32, height2: f32, smooth: f return color; } -pub fn render_biome_noise_map(map: &BiomeMap) -> ImageBuffer, Vec> { +pub fn render_biome_noise_map(map: &BiomeMap, multi: Vec3) -> ImageBuffer, Vec> { let mut image = ImageBuffer::new(map.width as u32, map.height as u32); - update_biome_noise_map(map, &mut image); + update_biome_noise_map(map, multi, &mut image); return image; } -pub fn update_biome_noise_map(map: &BiomeMap, image: &mut ImageBuffer, Vec>) { +pub fn update_biome_noise_map(map: &BiomeMap, multi: Vec3, image: &mut ImageBuffer, Vec>) { image.par_enumerate_pixels_mut().for_each(|(x, y, pixel)| { let tile = map.get_biome_data(x as usize, y as usize); let color = LinearRgba::rgb( - tile.temperature / 100.0, - tile.continentality / 100.0, - tile.moisture / 100.0, + (tile.temperature / 100.0) * multi.x, + (tile.continentality / 100.0) * multi.y, + (tile.moisture / 100.0) * multi.z, ); *pixel = to_pixel(&color); }); diff --git a/game/main/src/map_rendering/map_init.rs b/game/main/src/map_rendering/map_init.rs index 65ad04d..7698342 100644 --- a/game/main/src/map_rendering/map_init.rs +++ b/game/main/src/map_rendering/map_init.rs @@ -162,10 +162,10 @@ fn create_heightmap( biome_painter: Res, ) { let config = GenerationConfig { - biome_blend: 16, + biome_blend: 32, biome_dither: 16., continent_noise: NoiseConfig { - scale: 1000., + scale: 800., layers: vec![GeneratorLayer { base_roughness: 2.14, roughness: 0.87, @@ -180,7 +180,7 @@ fn create_heightmap( }], }, moisture_noise: NoiseConfig { - scale: 500., + scale: 900., layers: vec![GeneratorLayer { base_roughness: 2.14, roughness: 0.87, @@ -195,7 +195,7 @@ fn create_heightmap( }], }, temperature_noise: NoiseConfig { - scale: 900., + scale: 700., layers: vec![GeneratorLayer { base_roughness: 2.14, roughness: 0.87, diff --git a/game/main/src/utlis/editor_plugin.rs b/game/main/src/utlis/editor_plugin.rs index b5b7a21..1a5a242 100644 --- a/game/main/src/utlis/editor_plugin.rs +++ b/game/main/src/utlis/editor_plugin.rs @@ -2,6 +2,7 @@ use bevy::{prelude::*, render::render_asset::RenderAssetUsages}; use bevy_inspector_egui::bevy_egui::EguiContexts; use bevy_inspector_egui::egui::{self}; use bevy_rapier3d::rapier::crossbeam::deque::Steal; +use image::{ImageBuffer, Rgba}; use world_generation::map::biome_map::{self, BiomeMap}; use world_generation::map::map_utils::{render_biome_map, render_biome_noise_map, update_map}; use world_generation::{map::map_utils::render_map, prelude::Map, states::GeneratorState}; @@ -53,9 +54,12 @@ enum MapDisplayType { HeightMap, Biomes, BiomeNoise, + BiomeNoiseTemp, + BiomeNoiseContinent, + BiomeNoiseMoisture, } -fn render_map_ui(image: Res, mut contexts: EguiContexts, mut state: ResMut) { +fn render_map_ui(image: Res, heightmap: Res, biome_map: Res, mut contexts: EguiContexts, mut state: ResMut) { let id = contexts.add_image(image.0.clone_weak()); let mut map_type = state.target_map_type; @@ -68,12 +72,32 @@ fn render_map_ui(image: Res, mut contexts: EguiContexts, mut state: Re ui.selectable_value(&mut map_type, MapDisplayType::HeightMap, "Heightmap"); ui.selectable_value(&mut map_type, MapDisplayType::Biomes, "Biomes"); ui.selectable_value(&mut map_type, MapDisplayType::BiomeNoise, "Biome Noise"); + ui.selectable_value( + &mut map_type, + MapDisplayType::BiomeNoiseTemp, + "Biome Noise: Tempurature", + ); + ui.selectable_value( + &mut map_type, + MapDisplayType::BiomeNoiseContinent, + "Biome Noise: Continent", + ); + ui.selectable_value( + &mut map_type, + MapDisplayType::BiomeNoiseMoisture, + "Biome Noise: Moisture", + ); }); ui.add(egui::widgets::Image::new(egui::load::SizedTexture::new( id, [512.0, 512.0], ))); + + if ui.button("Save Image").clicked() { + let img = get_map_image(&heightmap, &biome_map, map_type); + _ = img.save(format!("{:?}.png", map_type)); + } }); state.target_map_type = map_type; @@ -90,11 +114,7 @@ fn update_map_render( return; } - let result = match state.target_map_type { - MapDisplayType::HeightMap => render_map(&heightmap, 0.1), - MapDisplayType::Biomes => render_biome_map(&heightmap, &biome_map), - MapDisplayType::BiomeNoise => render_biome_noise_map(&biome_map), - }; + let result = get_map_image(&heightmap, &biome_map, state.target_map_type); images.insert( image.0.id(), Image::from_dynamic(result.into(), true, RenderAssetUsages::RENDER_WORLD), @@ -102,3 +122,14 @@ fn update_map_render( state.cur_map_type = state.target_map_type; } + +fn get_map_image(heightmap: &Map, biome_map: &BiomeMap, map_type: MapDisplayType) -> ImageBuffer, Vec> { + return match map_type { + MapDisplayType::HeightMap => render_map(&heightmap, 0.1), + MapDisplayType::Biomes => render_biome_map(&heightmap, &biome_map), + MapDisplayType::BiomeNoise => render_biome_noise_map(&biome_map, Vec3::ONE), + MapDisplayType::BiomeNoiseTemp => render_biome_noise_map(&biome_map, Vec3::X), + MapDisplayType::BiomeNoiseContinent => render_biome_noise_map(&biome_map, Vec3::Y), + MapDisplayType::BiomeNoiseMoisture => render_biome_noise_map(&biome_map, Vec3::Z), + }; +}