From 0f2afbec8ffb926827cdf16f8cbdcb954bf664b7 Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Sun, 18 Jul 2021 23:15:21 +0100 Subject: [PATCH 01/20] Fixed clouds and fluids underground --- assets/voxygen/shaders/fluid-frag/cheap.glsl | 5 +++++ assets/voxygen/shaders/fluid-frag/shiny.glsl | 6 ++++++ assets/voxygen/shaders/include/cloud/regular.glsl | 9 +++++---- assets/voxygen/shaders/include/sky.glsl | 2 +- assets/voxygen/shaders/terrain-frag.glsl | 6 +++++- 5 files changed, 22 insertions(+), 6 deletions(-) diff --git a/assets/voxygen/shaders/fluid-frag/cheap.glsl b/assets/voxygen/shaders/fluid-frag/cheap.glsl index f405fdd039..922135e500 100644 --- a/assets/voxygen/shaders/fluid-frag/cheap.glsl +++ b/assets/voxygen/shaders/fluid-frag/cheap.glsl @@ -131,6 +131,9 @@ void main() { vec3 emitted_light, reflected_light; + // Prevent the sky affecting light when underground + float not_underground = clamp((f_pos.z - f_alt) / 128.0 + 1.0, 0.0, 1.0); + // float point_shadow = shadow_at(f_pos, f_norm); // vec3 cam_to_frag = normalize(f_pos - cam_pos.xyz); // vec3 emitted_light, reflected_light; @@ -143,6 +146,8 @@ void main() { // vec3 surf_color = /*srgb_to_linear*/(vec3(0.4, 0.7, 2.0)); float max_light = 0.0; max_light += get_sun_diffuse2(sun_info, moon_info, f_norm, /*time_of_day.x*//*-cam_to_frag*/sun_view_dir/*view_dir*/, f_pos, mu, cam_attenuation, fluid_alt, k_a/* * (shade_frac * 0.5 + light_frac * 0.5)*/, /*vec3(0.0)*/k_d, k_s, alpha, f_norm, 1.0, emitted_light, reflected_light); + emitted_light *= not_underground; + reflected_light *= not_underground; // reflected_light *= f_light * point_shadow * shade_frac; // emitted_light *= f_light * point_shadow * max(shade_frac, MIN_SHADOW); // max_light *= f_light * point_shadow * shade_frac; diff --git a/assets/voxygen/shaders/fluid-frag/shiny.glsl b/assets/voxygen/shaders/fluid-frag/shiny.glsl index 67aae23766..ad5f462774 100644 --- a/assets/voxygen/shaders/fluid-frag/shiny.glsl +++ b/assets/voxygen/shaders/fluid-frag/shiny.glsl @@ -179,6 +179,10 @@ void main() { vec3 reflect_color = get_sky_color(/*reflect_ray_dir*/beam_view_dir, time_of_day.x, f_pos, vec3(-100000), 0.125, true); reflect_color = get_cloud_color(reflect_color, reflect_ray_dir, cam_pos.xyz, time_of_day.x, 100000.0, 0.1); reflect_color *= f_light; + + // Prevent the sky affecting light when underground + float not_underground = clamp((f_pos.z - f_alt) / 128.0 + 1.0, 0.0, 1.0); + reflect_color *= not_underground; // /*const */vec3 water_color = srgb_to_linear(vec3(0.2, 0.5, 1.0)); // /*const */vec3 water_color = srgb_to_linear(vec3(0.8, 0.9, 1.0)); // NOTE: Linear RGB, attenuation coefficients for water at roughly R, G, B wavelengths. @@ -254,6 +258,8 @@ void main() { float max_light = 0.0; max_light += get_sun_diffuse2(sun_info, moon_info, norm, /*time_of_day.x*/sun_view_dir, f_pos, mu, cam_attenuation, fluid_alt, k_a/* * (shade_frac * 0.5 + light_frac * 0.5)*/, vec3(k_d), /*vec3(f_light * point_shadow)*//*reflect_color*/k_s, alpha, f_norm, 1.0, emitted_light, reflected_light); + emitted_light *= not_underground; + reflected_light *= not_underground; // Apply cloud layer to sky // reflected_light *= /*water_color_direct * */reflect_color * f_light * point_shadow * shade_frac; // emitted_light *= /*water_color_direct*//*ambient_attenuation * */f_light * point_shadow * max(shade_frac, MIN_SHADOW); diff --git a/assets/voxygen/shaders/include/cloud/regular.glsl b/assets/voxygen/shaders/include/cloud/regular.glsl index 85fee047c6..889147e9c2 100644 --- a/assets/voxygen/shaders/include/cloud/regular.glsl +++ b/assets/voxygen/shaders/include/cloud/regular.glsl @@ -16,7 +16,7 @@ float cloud_broad(vec3 pos) { } // Returns vec4(r, g, b, density) -vec4 cloud_at(vec3 pos, float dist, out vec3 emission) { +vec4 cloud_at(vec3 pos, float dist, out vec3 emission, out float not_underground) { // Natural attenuation of air (air naturally attenuates light that passes through it) // Simulate the atmosphere thinning as you get higher. Not physically accurate, but then // it can't be since Veloren's world is flat, not spherical. @@ -134,7 +134,7 @@ vec4 cloud_at(vec3 pos, float dist, out vec3 emission) { //moon_access *= suppress_mist; // Prevent clouds and mist appearing underground (but fade them out gently) - float not_underground = clamp(1.0 - (alt - (pos.z - focus_off.z)) / 80.0 + dist * 0.001, 0, 1); + not_underground = clamp(1.0 - (alt - (pos.z - focus_off.z)) / 80.0 + dist * 0.001, 0, 1); sun_access *= not_underground; moon_access *= not_underground; float vapor_density = (mist + cloud) * not_underground; @@ -220,8 +220,9 @@ vec3 get_cloud_color(vec3 surf_color, vec3 dir, vec3 origin, const float time_of cdist = step_to_dist(trunc(dist_to_step(cdist - 0.25, quality)), quality); vec3 emission; + float not_underground; // Used to prevent sunlight leaking underground // `sample` is a reserved keyword - vec4 sample_ = cloud_at(origin + dir * ldist * splay, ldist, emission); + vec4 sample_ = cloud_at(origin + dir * ldist * splay, ldist, emission, not_underground); vec2 density_integrals = max(sample_.zw, vec2(0)); @@ -239,7 +240,7 @@ vec3 get_cloud_color(vec3 surf_color, vec3 dir, vec3 origin, const float time_of // Add the directed light light scattered into the camera by the clouds and the atmosphere (global illumination) sun_color * sun_scatter * get_sun_brightness() * (sun_access * (1.0 - cloud_darken) /*+ sky_color * global_scatter_factor*/) + moon_color * moon_scatter * get_moon_brightness() * (moon_access * (1.0 - cloud_darken) /*+ sky_color * global_scatter_factor*/) + - sky_light * (1.0 - global_darken) + + sky_light * (1.0 - global_darken) * not_underground + emission * density_integrals.y; } diff --git a/assets/voxygen/shaders/include/sky.glsl b/assets/voxygen/shaders/include/sky.glsl index cd209c2a4f..d5dafb6253 100644 --- a/assets/voxygen/shaders/include/sky.glsl +++ b/assets/voxygen/shaders/include/sky.glsl @@ -57,7 +57,7 @@ vec3 glow_light(vec3 pos) { #if (SHADOW_MODE <= SHADOW_MODE_NONE) return GLOW_COLOR; #else - return GLOW_COLOR * (1.0 + (noise_3d(vec3(pos.xy * 0.005, tick.x * 0.5)) - 0.5) * 1.0); + return GLOW_COLOR * (1.0 + (noise_3d(vec3(pos.xy * 0.005, tick.x * 0.5)) - 0.5) * 0.5); #endif } diff --git a/assets/voxygen/shaders/terrain-frag.glsl b/assets/voxygen/shaders/terrain-frag.glsl index aa5b0e89a2..35c9691390 100644 --- a/assets/voxygen/shaders/terrain-frag.glsl +++ b/assets/voxygen/shaders/terrain-frag.glsl @@ -253,8 +253,12 @@ void main() { // Computing light attenuation from water. vec3 emitted_light, reflected_light; + + // Prevent the sky affecting light when underground + float not_underground = clamp((f_pos.z - f_alt) / 128.0 + 1.0, 0.0, 1.0); + // To account for prior saturation - /*float */f_light = faces_fluid ? 1.0 : f_light * sqrt(f_light); + /*float */f_light = faces_fluid ? not_underground : f_light * sqrt(f_light); emitted_light = vec3(1.0); reflected_light = vec3(1.0); From 1cfad833c74f7b7ab097812e49b7b226b6057c9a Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Sun, 18 Jul 2021 23:15:56 +0100 Subject: [PATCH 02/20] Added caverns, fixed chunk load performance issue --- common/net/src/msg/compression.rs | 5 + common/src/terrain/block.rs | 3 +- voxygen/Cargo.toml | 1 + voxygen/src/scene/terrain/watcher.rs | 21 ++-- world/src/layer/mod.rs | 173 ++++++++++++++++++++++++++- world/src/lib.rs | 1 + 6 files changed, 192 insertions(+), 12 deletions(-) diff --git a/common/net/src/msg/compression.rs b/common/net/src/msg/compression.rs index db2bd0c31d..fc7f9aaea0 100644 --- a/common/net/src/msg/compression.rs +++ b/common/net/src/msg/compression.rs @@ -644,6 +644,11 @@ impl VoxelImageDecoding for TriPngEncoding Rgb { + r: 50, + g: 250, + b: 250, + }, Misc => Rgb { r: 255, g: 0, diff --git a/common/src/terrain/block.rs b/common/src/terrain/block.rs index d6420ec348..9615a46ce5 100644 --- a/common/src/terrain/block.rs +++ b/common/src/terrain/block.rs @@ -48,7 +48,8 @@ make_case_elim!( // 0x32 <= x < 0x40 is reserved for future earths/muds/gravels/sands/etc. Wood = 0x40, Leaves = 0x41, - // 0x42 <= x < 0x50 is reserved for future tree parts + GlowingMushroom = 0x42, + // 0x43 <= x < 0x50 is reserved for future tree parts // Covers all other cases (we sometimes have bizarrely coloured misc blocks, and also we // often want to experiment with new kinds of block without allocating them a // dedicated block kind. diff --git a/voxygen/Cargo.toml b/voxygen/Cargo.toml index f34934e846..789ab89ecd 100644 --- a/voxygen/Cargo.toml +++ b/voxygen/Cargo.toml @@ -106,6 +106,7 @@ native-dialog = { version = "0.5.2", optional = true } num = "0.4" ordered-float = { version = "2.0.1", default-features = false } rand = "0.8" +rand_chacha = "0.3" rayon = "1.5" rodio = {version = "0.14", default-features = false, features = ["vorbis"]} ron = {version = "0.6", default-features = false} diff --git a/voxygen/src/scene/terrain/watcher.rs b/voxygen/src/scene/terrain/watcher.rs index 8becc3e3e4..e811c715fb 100644 --- a/voxygen/src/scene/terrain/watcher.rs +++ b/voxygen/src/scene/terrain/watcher.rs @@ -5,6 +5,7 @@ use common::{ }; use common_base::span; use rand::prelude::*; +use rand_chacha::ChaCha8Rng; use vek::*; #[derive(Copy, Clone, Debug)] @@ -60,6 +61,8 @@ impl BlocksOfInterest { let mut cricket3 = Vec::new(); let mut frogs = Vec::new(); + let mut rng = ChaCha8Rng::from_seed(thread_rng().gen()); + chunk .vol_iter( Vec3::new(0, 0, chunk.get_min_z()), @@ -71,13 +74,13 @@ impl BlocksOfInterest { ) .for_each(|(pos, block)| { match block.kind() { - BlockKind::Leaves if thread_rng().gen_range(0..16) == 0 => leaves.push(pos), - BlockKind::WeakRock if thread_rng().gen_range(0..6) == 0 => drip.push(pos), + BlockKind::Leaves if rng.gen_range(0..16) == 0 => leaves.push(pos), + BlockKind::WeakRock if rng.gen_range(0..6) == 0 => drip.push(pos), BlockKind::Grass => { - if thread_rng().gen_range(0..16) == 0 { + if rng.gen_range(0..16) == 0 { grass.push(pos); } - match thread_rng().gen_range(0..8192) { + match rng.gen_range(0..8192) { 1 => cricket1.push(pos), 2 => cricket2.push(pos), 3 => cricket3.push(pos), @@ -85,14 +88,12 @@ impl BlocksOfInterest { } }, BlockKind::Water - if chunk.meta().contains_river() && thread_rng().gen_range(0..16) == 0 => + if chunk.meta().contains_river() && rng.gen_range(0..16) == 0 => { river.push(pos) }, - BlockKind::Lava if thread_rng().gen_range(0..5) == 0 => { - fires.push(pos + Vec3::unit_z()) - }, - BlockKind::Snow if thread_rng().gen_range(0..16) == 0 => snow.push(pos), + BlockKind::Lava if rng.gen_range(0..5) == 0 => fires.push(pos + Vec3::unit_z()), + BlockKind::Snow if rng.gen_range(0..16) == 0 => snow.push(pos), _ => match block.get_sprite() { Some(SpriteKind::Ember) => { fires.push(pos); @@ -114,7 +115,7 @@ impl BlocksOfInterest { Some(SpriteKind::Reed) => { reeds.push(pos); fireflies.push(pos); - if thread_rng().gen_range(0..12) == 0 { + if rng.gen_range(0..12) == 0 { frogs.push(pos); } }, diff --git a/world/src/layer/mod.rs b/world/src/layer/mod.rs index 9d3148eb80..02f67bde05 100644 --- a/world/src/layer/mod.rs +++ b/world/src/layer/mod.rs @@ -10,7 +10,7 @@ pub use self::{ use crate::{ column::ColumnSample, - util::{FastNoise, RandomField, Sampler}, + util::{FastNoise, RandomField, Sampler, RandomPerm}, Canvas, IndexRef, }; use common::{ @@ -27,6 +27,7 @@ use std::{ f32, ops::{Mul, Range, Sub}, }; +use hashbrown::HashMap; use vek::*; #[derive(Deserialize)] @@ -570,3 +571,173 @@ pub fn apply_coral_to(canvas: &mut Canvas) { } }); } + +pub fn apply_caverns_to(canvas: &mut Canvas, dynamic_rng: &mut R) { + let info = canvas.info(); + + // Get cavern attributes at a position + let cavern_at = |wpos2d| { + let alt = info.land().get_alt_approx(wpos2d); + + // Horizontal average scale of caverns + let scale = 2048.0; + // How common should they be? (0.0 - 1.0) + let common = 0.15; + // Range of heights for the caverns + let height_range = 48.0..300.0; + // Minimum distance below the surface + let surface_clearance = 64.0; + + let cavern_avg_height = Lerp::lerp( + height_range.start, + height_range.end, + info.index().noise.cave_nz.get((wpos2d.map(|e| e as f64) / 128.0).into_array()) as f32 * 0.5 + 0.5, + ); + + let cavern_avg_alt = alt * 0.25 - height_range.end - surface_clearance; + + let cavern_nz = info.index().noise.cave_nz.get((wpos2d.map(|e| e as f64) / scale).into_array()) as f32; + let cavern_height = ((cavern_nz * 0.5 + 0.5 - (1.0 - common)).max(0.0) / common).powf(common * 2.0) * cavern_avg_height; + + // Stalagtites + let stalagtite = info.index().noise.cave_nz + .get(wpos2d.map(|e| e as f64 * 0.015).into_array()) + .sub(0.5) + .max(0.0) + .mul((cavern_height as f64 - 5.0).mul(0.15).clamped(0.0, 1.0)) + .mul(32.0 + cavern_avg_height as f64 * 0.85); + + let lake = info.index().noise.cave_nz + .get(wpos2d.map(|e| e as f64 * 0.01).into_array()) + .sub(0.5) + .max(0.0) + .mul(2.0) + .mul(80.0); + let lake = 0.0; + + let rugged = 0.25; // How bumpy should the floor be relative to the ceiling? + let cavern_bottom = (cavern_avg_alt - cavern_height * rugged) as i32; + let cavern_avg_bottom = (cavern_avg_alt - ((height_range.start + height_range.end) * 0.5) * rugged) as i32; + let cavern_top = (cavern_avg_alt + cavern_height) as i32; + let cavern_avg_top = (cavern_avg_alt + cavern_avg_height) as i32; + + // Stalagmites rise up to meet stalagtites + let stalagmite = stalagtite * 0.3; + + let floor = stalagmite as i32; + + (cavern_bottom, cavern_top, cavern_avg_bottom, cavern_avg_top, floor, lake, stalagtite) + }; + + let mut mushroom_cache = HashMap::new(); + + struct Mushroom { + pos: Vec3, + stalk: f32, + head_color: Rgb, + } + + // Get mushroom block, if any, at a position + let mut get_mushroom = |wpos: Vec3, dynamic_rng: &mut R| { + for (wpos2d, seed) in info.chunks().gen_ctx.structure_gen.get(wpos.xy()) { + let mushroom = if let Some(mushroom) = mushroom_cache + .entry(wpos2d) + .or_insert_with(|| { + let mut rng = RandomPerm::new(seed); + let (cavern_bottom, _, _, _, floor, _, _) = cavern_at(wpos2d); + if rng.gen_bool(0.1) { + Some(Mushroom { + pos: wpos2d.with_z(cavern_bottom + floor), + stalk: rng.gen_range(8.0..26.0), + head_color: Rgb::new(50, rng.gen_range(70..110), rng.gen_range(100..200)), + }) + } else { + None + } + }) + { + mushroom + } else { + continue + }; + + let wposf = wpos.map(|e| e as f64); + let warp_freq = 1.0 / 32.0; + let warp_amp = Vec3::new(8.0, 8.0, 12.0); + let wposf_warped = wposf.map(|e| e as f32) + Vec3::new( + FastNoise::new(seed + 0).get(wposf * warp_freq) as f32, + FastNoise::new(seed + 1).get(wposf * warp_freq) as f32, + FastNoise::new(seed + 2).get(wposf * warp_freq) as f32, + ) * warp_amp; + + let rpos = wposf_warped - mushroom.pos.map(|e| e as f32).map(|e| e as f32); + + let stalk_radius = 2.0f32; + let head_radius = 12.0f32; + let head_height = 10.0; + + let dist_sq = rpos.xy().magnitude_squared(); + if dist_sq < head_radius.powi(2) { + let dist = dist_sq.sqrt(); + // Head + if rpos.z > mushroom.stalk && rpos.z < mushroom.stalk + head_height && dist < head_radius * (1.0 - (rpos.z - mushroom.stalk) / head_height).powf(0.125) { + return Some(Block::new(BlockKind::GlowingMushroom, mushroom.head_color)); + } else if rpos.z <= mushroom.stalk && rpos.xy().magnitude_squared() < stalk_radius.powi(2) { // Stalk + return Some(Block::new(BlockKind::Wood, Rgb::new(50, 120, 180))); + } else if ((mushroom.stalk - 1.0)..mushroom.stalk).contains(&rpos.z) // Hanging orbs + && ((head_radius * 0.5)..(head_radius * 0.8)).contains(&dist) + && dynamic_rng.gen_bool(0.025) + { + return Some(Block::air(SpriteKind::Orb)); + } + } + } + + None + }; + + canvas.foreach_col(|canvas, wpos2d, _col| { + let (cavern_bottom, cavern_top, cavern_avg_bottom, cavern_avg_top, floor, lake, stalagtite) = cavern_at(wpos2d); + + let mini_stalagtite = info.index().noise.cave_nz + .get(wpos2d.map(|e| e as f64 * 0.08).into_array()) + .sub(0.5) + .max(0.0) + .mul(((cavern_top - cavern_bottom) as f64 - 5.0).mul(0.15).clamped(0.0, 1.0)) + .mul(24.0 + (cavern_avg_top - cavern_avg_bottom) as f64 * 0.2); + let stalagtite_height = (stalagtite + mini_stalagtite) as i32; + + let cavern_top = cavern_top as i32; + let lower_bound = cavern_bottom - lake as i32; + let mut on_ground = true; + for z in lower_bound..cavern_top { + use SpriteKind::*; + + let wpos = wpos2d.with_z(z); + + let block = if z < lower_bound + floor { + Block::new(BlockKind::WeakRock, Rgb::new(110, 120, 150)) + } else if z > cavern_top - stalagtite_height { + if dynamic_rng.gen_bool(0.0035) { // Glowing rock in stalagtites + Block::new(BlockKind::GlowingRock, Rgb::new(30, 150, 120)) + } else { + Block::new(BlockKind::WeakRock, Rgb::new(110, 120, 150)) + } + } else if let Some(mushroom_block) = get_mushroom(wpos, dynamic_rng) { + mushroom_block + } else if z < cavern_avg_bottom as i32 + 16 { + Block::water(SpriteKind::Empty) + } else if z == cavern_bottom + floor && dynamic_rng.gen_bool(0.005) && on_ground { + Block::air(*[CrystalLow, CaveMushroom].choose(dynamic_rng).unwrap()) + } else if z == cavern_top - 1 && dynamic_rng.gen_bool(0.01) { + Block::air(*[CrystalHigh, CeilingMushroom, Orb].choose(dynamic_rng).unwrap()) + } else { + Block::empty() + }; + + on_ground |= block.is_solid(); + + let _ = canvas.set(wpos, block); + } + }); +} diff --git a/world/src/lib.rs b/world/src/lib.rs index 72edb90318..57ebdcf10e 100644 --- a/world/src/lib.rs +++ b/world/src/lib.rs @@ -346,6 +346,7 @@ impl World { entities: Vec::new(), }; + layer::apply_caverns_to(&mut canvas, &mut dynamic_rng); layer::apply_caves_to(&mut canvas, &mut dynamic_rng); layer::apply_shrubs_to(&mut canvas, &mut dynamic_rng); layer::apply_trees_to(&mut canvas, &mut dynamic_rng); From 5c0026f4a70663ada78507906e7eed04eb2e1fe1 Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Mon, 19 Jul 2021 00:10:55 +0100 Subject: [PATCH 03/20] Performance improvements for terrain watcher --- Cargo.lock | 1 + common/src/terrain/chonk.rs | 16 ++++++++++++++++ voxygen/src/scene/terrain/watcher.rs | 14 ++------------ world/src/layer/mod.rs | 23 +++++++---------------- world/src/lib.rs | 6 ++++-- 5 files changed, 30 insertions(+), 30 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2dc5d8324d..e45c0a8754 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6275,6 +6275,7 @@ dependencies = [ "ordered-float 2.8.0", "profiling", "rand 0.8.4", + "rand_chacha 0.3.1", "rayon", "rodio", "ron", diff --git a/common/src/terrain/chonk.rs b/common/src/terrain/chonk.rs index 29240560de..a71c15f41f 100644 --- a/common/src/terrain/chonk.rs +++ b/common/src/terrain/chonk.rs @@ -69,6 +69,22 @@ impl Chonk { self.sub_chunks.iter().map(SubChunk::num_groups).sum() } + /// Iterate through the voxels in this chunk, attempting to avoid those that are unchanged (i.e: match the `below` + /// and `above` voxels). This is generally useful for performance reasons. + pub fn iter_changed(&self) -> impl Iterator, &V)> + '_ { + self.sub_chunks + .iter() + .enumerate() + .filter(|(_, sc)| sc.num_groups() > 0) + .map(move |(i, sc)| { + let z_offset = self.z_offset + i as i32 * SubChunkSize::::SIZE.z as i32; + sc + .vol_iter(Vec3::zero(), SubChunkSize::::SIZE.map(|e| e as i32)) + .map(move |(pos, vox)| (pos + Vec3::unit_z() * z_offset, vox)) + }) + .flatten() + } + // Returns the index (in self.sub_chunks) of the SubChunk that contains // layer z; note that this index changes when more SubChunks are prepended fn sub_chunk_idx(&self, z: i32) -> i32 { diff --git a/voxygen/src/scene/terrain/watcher.rs b/voxygen/src/scene/terrain/watcher.rs index e811c715fb..3f067730ed 100644 --- a/voxygen/src/scene/terrain/watcher.rs +++ b/voxygen/src/scene/terrain/watcher.rs @@ -1,8 +1,5 @@ use crate::hud::CraftingTab; -use common::{ - terrain::{BlockKind, SpriteKind, TerrainChunk}, - vol::{IntoVolIterator, RectRasterableVol}, -}; +use common::terrain::{BlockKind, SpriteKind, TerrainChunk}; use common_base::span; use rand::prelude::*; use rand_chacha::ChaCha8Rng; @@ -64,14 +61,7 @@ impl BlocksOfInterest { let mut rng = ChaCha8Rng::from_seed(thread_rng().gen()); chunk - .vol_iter( - Vec3::new(0, 0, chunk.get_min_z()), - Vec3::new( - TerrainChunk::RECT_SIZE.x as i32, - TerrainChunk::RECT_SIZE.y as i32, - chunk.get_max_z(), - ), - ) + .iter_changed() .for_each(|(pos, block)| { match block.kind() { BlockKind::Leaves if rng.gen_range(0..16) == 0 => leaves.push(pos), diff --git a/world/src/layer/mod.rs b/world/src/layer/mod.rs index 02f67bde05..7c1d44d4b2 100644 --- a/world/src/layer/mod.rs +++ b/world/src/layer/mod.rs @@ -607,14 +607,6 @@ pub fn apply_caverns_to(canvas: &mut Canvas, dynamic_rng: &mut R) { .mul((cavern_height as f64 - 5.0).mul(0.15).clamped(0.0, 1.0)) .mul(32.0 + cavern_avg_height as f64 * 0.85); - let lake = info.index().noise.cave_nz - .get(wpos2d.map(|e| e as f64 * 0.01).into_array()) - .sub(0.5) - .max(0.0) - .mul(2.0) - .mul(80.0); - let lake = 0.0; - let rugged = 0.25; // How bumpy should the floor be relative to the ceiling? let cavern_bottom = (cavern_avg_alt - cavern_height * rugged) as i32; let cavern_avg_bottom = (cavern_avg_alt - ((height_range.start + height_range.end) * 0.5) * rugged) as i32; @@ -626,7 +618,7 @@ pub fn apply_caverns_to(canvas: &mut Canvas, dynamic_rng: &mut R) { let floor = stalagmite as i32; - (cavern_bottom, cavern_top, cavern_avg_bottom, cavern_avg_top, floor, lake, stalagtite) + (cavern_bottom, cavern_top, cavern_avg_bottom, cavern_avg_top, floor, stalagtite) }; let mut mushroom_cache = HashMap::new(); @@ -644,8 +636,8 @@ pub fn apply_caverns_to(canvas: &mut Canvas, dynamic_rng: &mut R) { .entry(wpos2d) .or_insert_with(|| { let mut rng = RandomPerm::new(seed); - let (cavern_bottom, _, _, _, floor, _, _) = cavern_at(wpos2d); - if rng.gen_bool(0.1) { + let (cavern_bottom, cavern_top, _, _, floor, _) = cavern_at(wpos2d); + if rng.gen_bool(0.1) && cavern_top - cavern_bottom > 32 { Some(Mushroom { pos: wpos2d.with_z(cavern_bottom + floor), stalk: rng.gen_range(8.0..26.0), @@ -684,7 +676,7 @@ pub fn apply_caverns_to(canvas: &mut Canvas, dynamic_rng: &mut R) { return Some(Block::new(BlockKind::GlowingMushroom, mushroom.head_color)); } else if rpos.z <= mushroom.stalk && rpos.xy().magnitude_squared() < stalk_radius.powi(2) { // Stalk return Some(Block::new(BlockKind::Wood, Rgb::new(50, 120, 180))); - } else if ((mushroom.stalk - 1.0)..mushroom.stalk).contains(&rpos.z) // Hanging orbs + } else if ((mushroom.stalk - 0.5)..mushroom.stalk).contains(&rpos.z) // Hanging orbs && ((head_radius * 0.5)..(head_radius * 0.8)).contains(&dist) && dynamic_rng.gen_bool(0.025) { @@ -697,7 +689,7 @@ pub fn apply_caverns_to(canvas: &mut Canvas, dynamic_rng: &mut R) { }; canvas.foreach_col(|canvas, wpos2d, _col| { - let (cavern_bottom, cavern_top, cavern_avg_bottom, cavern_avg_top, floor, lake, stalagtite) = cavern_at(wpos2d); + let (cavern_bottom, cavern_top, cavern_avg_bottom, cavern_avg_top, floor, stalagtite) = cavern_at(wpos2d); let mini_stalagtite = info.index().noise.cave_nz .get(wpos2d.map(|e| e as f64 * 0.08).into_array()) @@ -708,14 +700,13 @@ pub fn apply_caverns_to(canvas: &mut Canvas, dynamic_rng: &mut R) { let stalagtite_height = (stalagtite + mini_stalagtite) as i32; let cavern_top = cavern_top as i32; - let lower_bound = cavern_bottom - lake as i32; let mut on_ground = true; - for z in lower_bound..cavern_top { + for z in cavern_bottom..cavern_top { use SpriteKind::*; let wpos = wpos2d.with_z(z); - let block = if z < lower_bound + floor { + let block = if z < cavern_bottom + floor { Block::new(BlockKind::WeakRock, Rgb::new(110, 120, 150)) } else if z > cavern_top - stalagtite_height { if dynamic_rng.gen_bool(0.0035) { // Glowing rock in stalagtites diff --git a/world/src/lib.rs b/world/src/lib.rs index 57ebdcf10e..2ceb854cfa 100644 --- a/world/src/lib.rs +++ b/world/src/lib.rs @@ -55,6 +55,8 @@ use common_net::msg::{world_msg, WorldMapMsg}; use rand::Rng; use serde::Deserialize; use std::time::Duration; +use rand_chacha::ChaCha8Rng; +use rand::prelude::*; use vek::*; #[derive(Debug)] @@ -329,7 +331,7 @@ impl World { }; // Only use for rng affecting dynamic elements like chests and entities! - let mut dynamic_rng = rand::thread_rng(); + let mut dynamic_rng = ChaCha8Rng::from_seed(thread_rng().gen()); // Apply layers (paths, caves, etc.) let mut canvas = Canvas { @@ -365,7 +367,7 @@ impl World { entities: canvas.entities, }; - let gen_entity_pos = |dynamic_rng: &mut rand::rngs::ThreadRng| { + let gen_entity_pos = |dynamic_rng: &mut ChaCha8Rng| { let lpos2d = TerrainChunkSize::RECT_SIZE .map(|sz| dynamic_rng.gen::().rem_euclid(sz) as i32); let mut lpos = Vec3::new( From f9c635c92868277b993029089a2ef4a7a6cee672 Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Mon, 19 Jul 2021 00:54:23 +0100 Subject: [PATCH 04/20] Silly GI for water in caves --- assets/voxygen/shaders/fluid-frag/cheap.glsl | 3 +++ assets/voxygen/shaders/fluid-frag/shiny.glsl | 3 +++ 2 files changed, 6 insertions(+) diff --git a/assets/voxygen/shaders/fluid-frag/cheap.glsl b/assets/voxygen/shaders/fluid-frag/cheap.glsl index 922135e500..6247522baa 100644 --- a/assets/voxygen/shaders/fluid-frag/cheap.glsl +++ b/assets/voxygen/shaders/fluid-frag/cheap.glsl @@ -148,6 +148,9 @@ void main() { max_light += get_sun_diffuse2(sun_info, moon_info, f_norm, /*time_of_day.x*//*-cam_to_frag*/sun_view_dir/*view_dir*/, f_pos, mu, cam_attenuation, fluid_alt, k_a/* * (shade_frac * 0.5 + light_frac * 0.5)*/, /*vec3(0.0)*/k_d, k_s, alpha, f_norm, 1.0, emitted_light, reflected_light); emitted_light *= not_underground; reflected_light *= not_underground; + + // Global illumination when underground (silly) + emitted_light += (1.0 - not_underground) * 0.05; // reflected_light *= f_light * point_shadow * shade_frac; // emitted_light *= f_light * point_shadow * max(shade_frac, MIN_SHADOW); // max_light *= f_light * point_shadow * shade_frac; diff --git a/assets/voxygen/shaders/fluid-frag/shiny.glsl b/assets/voxygen/shaders/fluid-frag/shiny.glsl index ad5f462774..aee8c55051 100644 --- a/assets/voxygen/shaders/fluid-frag/shiny.glsl +++ b/assets/voxygen/shaders/fluid-frag/shiny.glsl @@ -260,6 +260,9 @@ void main() { max_light += get_sun_diffuse2(sun_info, moon_info, norm, /*time_of_day.x*/sun_view_dir, f_pos, mu, cam_attenuation, fluid_alt, k_a/* * (shade_frac * 0.5 + light_frac * 0.5)*/, vec3(k_d), /*vec3(f_light * point_shadow)*//*reflect_color*/k_s, alpha, f_norm, 1.0, emitted_light, reflected_light); emitted_light *= not_underground; reflected_light *= not_underground; + + // Global illumination when underground (silly) + emitted_light += (1.0 - not_underground) * 0.05; // Apply cloud layer to sky // reflected_light *= /*water_color_direct * */reflect_color * f_light * point_shadow * shade_frac; // emitted_light *= /*water_color_direct*//*ambient_attenuation * */f_light * point_shadow * max(shade_frac, MIN_SHADOW); From ed40e92801277c0e75d1b61f234ebc98e3b51aa1 Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Mon, 19 Jul 2021 00:54:33 +0100 Subject: [PATCH 05/20] Better cave water --- world/src/layer/mod.rs | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/world/src/layer/mod.rs b/world/src/layer/mod.rs index 7c1d44d4b2..d7ba21b77c 100644 --- a/world/src/layer/mod.rs +++ b/world/src/layer/mod.rs @@ -11,6 +11,7 @@ pub use self::{ use crate::{ column::ColumnSample, util::{FastNoise, RandomField, Sampler, RandomPerm}, + config::CONFIG, Canvas, IndexRef, }; use common::{ @@ -584,20 +585,21 @@ pub fn apply_caverns_to(canvas: &mut Canvas, dynamic_rng: &mut R) { // How common should they be? (0.0 - 1.0) let common = 0.15; // Range of heights for the caverns - let height_range = 48.0..300.0; + let height_range = 16.0..250.0; // Minimum distance below the surface let surface_clearance = 64.0; let cavern_avg_height = Lerp::lerp( height_range.start, height_range.end, - info.index().noise.cave_nz.get((wpos2d.map(|e| e as f64) / 128.0).into_array()) as f32 * 0.5 + 0.5, + info.index().noise.cave_nz.get((wpos2d.map(|e| e as f64) / 300.0).into_array()) as f32 * 0.5 + 0.5, ); - let cavern_avg_alt = alt * 0.25 - height_range.end - surface_clearance; + let cavern_avg_alt = CONFIG.sea_level.min(alt * 0.25) - height_range.end - surface_clearance; let cavern_nz = info.index().noise.cave_nz.get((wpos2d.map(|e| e as f64) / scale).into_array()) as f32; - let cavern_height = ((cavern_nz * 0.5 + 0.5 - (1.0 - common)).max(0.0) / common).powf(common * 2.0) * cavern_avg_height; + let cavern = ((cavern_nz * 0.5 + 0.5 - (1.0 - common)).max(0.0) / common).powf(common * 2.0); + let cavern_height = cavern * cavern_avg_height; // Stalagtites let stalagtite = info.index().noise.cave_nz @@ -605,16 +607,17 @@ pub fn apply_caverns_to(canvas: &mut Canvas, dynamic_rng: &mut R) { .sub(0.5) .max(0.0) .mul((cavern_height as f64 - 5.0).mul(0.15).clamped(0.0, 1.0)) - .mul(32.0 + cavern_avg_height as f64 * 0.85); + .mul(32.0 + cavern_avg_height as f64); - let rugged = 0.25; // How bumpy should the floor be relative to the ceiling? - let cavern_bottom = (cavern_avg_alt - cavern_height * rugged) as i32; + let hill = info.index().noise.cave_nz.get((wpos2d.map(|e| e as f64) / 96.0).into_array()) as f32 * cavern * 24.0; + let rugged = 0.4; // How bumpy should the floor be relative to the ceiling? + let cavern_bottom = (cavern_avg_alt - cavern_height * rugged + hill) as i32; let cavern_avg_bottom = (cavern_avg_alt - ((height_range.start + height_range.end) * 0.5) * rugged) as i32; let cavern_top = (cavern_avg_alt + cavern_height) as i32; let cavern_avg_top = (cavern_avg_alt + cavern_avg_height) as i32; // Stalagmites rise up to meet stalagtites - let stalagmite = stalagtite * 0.3; + let stalagmite = stalagtite; let floor = stalagmite as i32; @@ -716,7 +719,7 @@ pub fn apply_caverns_to(canvas: &mut Canvas, dynamic_rng: &mut R) { } } else if let Some(mushroom_block) = get_mushroom(wpos, dynamic_rng) { mushroom_block - } else if z < cavern_avg_bottom as i32 + 16 { + } else if z < cavern_avg_bottom as i32 + 4 { Block::water(SpriteKind::Empty) } else if z == cavern_bottom + floor && dynamic_rng.gen_bool(0.005) && on_ground { Block::air(*[CrystalLow, CaveMushroom].choose(dynamic_rng).unwrap()) From bfc55d7b17adbd3bc0631728b2853ecad82f8c6f Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Mon, 19 Jul 2021 02:42:10 +0100 Subject: [PATCH 06/20] More cavern details --- common/src/terrain/block.rs | 3 +- common/src/terrain/chonk.rs | 8 +- voxygen/src/scene/terrain/watcher.rs | 83 ++++++++----- world/src/layer/mod.rs | 174 ++++++++++++++++++++------- world/src/lib.rs | 5 +- 5 files changed, 195 insertions(+), 78 deletions(-) diff --git a/common/src/terrain/block.rs b/common/src/terrain/block.rs index 9615a46ce5..9b91989557 100644 --- a/common/src/terrain/block.rs +++ b/common/src/terrain/block.rs @@ -178,7 +178,8 @@ impl Block { pub fn get_glow(&self) -> Option { match self.kind() { BlockKind::Lava => Some(24), - BlockKind::GlowingRock | BlockKind::GlowingWeakRock => Some(12), + BlockKind::GlowingRock | BlockKind::GlowingWeakRock => Some(15), + BlockKind::BlockKind::GlowingMushroom => Some(20), _ => match self.get_sprite()? { SpriteKind::StreetLamp | SpriteKind::StreetLampTall => Some(24), SpriteKind::Ember => Some(20), diff --git a/common/src/terrain/chonk.rs b/common/src/terrain/chonk.rs index a71c15f41f..60e157da1e 100644 --- a/common/src/terrain/chonk.rs +++ b/common/src/terrain/chonk.rs @@ -69,8 +69,9 @@ impl Chonk { self.sub_chunks.iter().map(SubChunk::num_groups).sum() } - /// Iterate through the voxels in this chunk, attempting to avoid those that are unchanged (i.e: match the `below` - /// and `above` voxels). This is generally useful for performance reasons. + /// Iterate through the voxels in this chunk, attempting to avoid those that + /// are unchanged (i.e: match the `below` and `above` voxels). This is + /// generally useful for performance reasons. pub fn iter_changed(&self) -> impl Iterator, &V)> + '_ { self.sub_chunks .iter() @@ -78,8 +79,7 @@ impl Chonk { .filter(|(_, sc)| sc.num_groups() > 0) .map(move |(i, sc)| { let z_offset = self.z_offset + i as i32 * SubChunkSize::::SIZE.z as i32; - sc - .vol_iter(Vec3::zero(), SubChunkSize::::SIZE.map(|e| e as i32)) + sc.vol_iter(Vec3::zero(), SubChunkSize::::SIZE.map(|e| e as i32)) .map(move |(pos, vox)| (pos + Vec3::unit_z() * z_offset, vox)) }) .flatten() diff --git a/voxygen/src/scene/terrain/watcher.rs b/voxygen/src/scene/terrain/watcher.rs index 3f067730ed..14acd1b2e6 100644 --- a/voxygen/src/scene/terrain/watcher.rs +++ b/voxygen/src/scene/terrain/watcher.rs @@ -60,27 +60,54 @@ impl BlocksOfInterest { let mut rng = ChaCha8Rng::from_seed(thread_rng().gen()); - chunk - .iter_changed() - .for_each(|(pos, block)| { - match block.kind() { - BlockKind::Leaves if rng.gen_range(0..16) == 0 => leaves.push(pos), - BlockKind::WeakRock if rng.gen_range(0..6) == 0 => drip.push(pos), - BlockKind::Grass => { - if rng.gen_range(0..16) == 0 { - grass.push(pos); - } - match rng.gen_range(0..8192) { - 1 => cricket1.push(pos), - 2 => cricket2.push(pos), - 3 => cricket3.push(pos), - _ => {}, + chunk.iter_changed().for_each(|(pos, block)| { + match block.kind() { + BlockKind::Leaves if rng.gen_range(0..16) == 0 => leaves.push(pos), + BlockKind::WeakRock if rng.gen_range(0..6) == 0 => drip.push(pos), + BlockKind::Grass => { + if rng.gen_range(0..16) == 0 { + grass.push(pos); + } + match rng.gen_range(0..8192) { + 1 => cricket1.push(pos), + 2 => cricket2.push(pos), + 3 => cricket3.push(pos), + _ => {}, + } + }, + BlockKind::Water if chunk.meta().contains_river() && rng.gen_range(0..16) == 0 => { + river.push(pos) + }, + BlockKind::Snow if rng.gen_range(0..16) == 0 => snow.push(pos), + _ => match block.get_sprite() { + Some(SpriteKind::Ember) => { + fires.push(pos); + smokers.push(pos); + }, + // Offset positions to account for block height. + // TODO: Is this a good idea? + Some(SpriteKind::StreetLamp) => fire_bowls.push(pos + Vec3::unit_z() * 2), + Some(SpriteKind::FireBowlGround) => fire_bowls.push(pos + Vec3::unit_z()), + Some(SpriteKind::StreetLampTall) => fire_bowls.push(pos + Vec3::unit_z() * 4), + Some(SpriteKind::WallSconce) => fire_bowls.push(pos + Vec3::unit_z()), + Some(SpriteKind::Beehive) => beehives.push(pos), + Some(SpriteKind::CrystalHigh) => fireflies.push(pos), + Some(SpriteKind::Reed) => { + reeds.push(pos); + fireflies.push(pos); + if rng.gen_range(0..12) == 0 { + frogs.push(pos); } }, - BlockKind::Water - if chunk.meta().contains_river() && rng.gen_range(0..16) == 0 => - { - river.push(pos) + Some(SpriteKind::CaveMushroom) => fireflies.push(pos), + Some(SpriteKind::PinkFlower) => flowers.push(pos), + Some(SpriteKind::PurpleFlower) => flowers.push(pos), + Some(SpriteKind::RedFlower) => flowers.push(pos), + Some(SpriteKind::WhiteFlower) => flowers.push(pos), + Some(SpriteKind::YellowFlower) => flowers.push(pos), + Some(SpriteKind::Sunflower) => flowers.push(pos), + Some(SpriteKind::CraftingBench) => { + interactables.push((pos, Interaction::Craft(CraftingTab::All))) }, BlockKind::Lava if rng.gen_range(0..5) == 0 => fires.push(pos + Vec3::unit_z()), BlockKind::Snow if rng.gen_range(0..16) == 0 => snow.push(pos), @@ -143,14 +170,16 @@ impl BlocksOfInterest { }, _ => {}, }, - } - if block.is_collectible() { - interactables.push((pos, Interaction::Collect)); - } - if let Some(glow) = block.get_glow() { - lights.push((pos, glow)); - } - }); + _ => {}, + }, + } + if block.is_collectible() { + interactables.push((pos, Interaction::Collect)); + } + if let Some(glow) = block.get_glow() { + lights.push((pos, glow)); + } + }); Self { leaves, diff --git a/world/src/layer/mod.rs b/world/src/layer/mod.rs index d7ba21b77c..e94ddc9a08 100644 --- a/world/src/layer/mod.rs +++ b/world/src/layer/mod.rs @@ -10,8 +10,8 @@ pub use self::{ use crate::{ column::ColumnSample, - util::{FastNoise, RandomField, Sampler, RandomPerm}, config::CONFIG, + util::{FastNoise, RandomField, RandomPerm, Sampler}, Canvas, IndexRef, }; use common::{ @@ -21,6 +21,7 @@ use common::{ terrain::{Block, BlockKind, SpriteKind}, vol::{BaseVol, ReadVol, RectSizedVol, WriteVol}, }; +use hashbrown::HashMap; use noise::NoiseFn; use rand::prelude::*; use serde::Deserialize; @@ -28,7 +29,6 @@ use std::{ f32, ops::{Mul, Range, Sub}, }; -use hashbrown::HashMap; use vek::*; #[derive(Deserialize)] @@ -592,27 +592,48 @@ pub fn apply_caverns_to(canvas: &mut Canvas, dynamic_rng: &mut R) { let cavern_avg_height = Lerp::lerp( height_range.start, height_range.end, - info.index().noise.cave_nz.get((wpos2d.map(|e| e as f64) / 300.0).into_array()) as f32 * 0.5 + 0.5, + info.index() + .noise + .cave_nz + .get((wpos2d.map(|e| e as f64) / 300.0).into_array()) as f32 + * 0.5 + + 0.5, ); - let cavern_avg_alt = CONFIG.sea_level.min(alt * 0.25) - height_range.end - surface_clearance; + let cavern_avg_alt = + CONFIG.sea_level.min(alt * 0.25) - height_range.end - surface_clearance; - let cavern_nz = info.index().noise.cave_nz.get((wpos2d.map(|e| e as f64) / scale).into_array()) as f32; - let cavern = ((cavern_nz * 0.5 + 0.5 - (1.0 - common)).max(0.0) / common).powf(common * 2.0); + let cavern_nz = info + .index() + .noise + .cave_nz + .get((wpos2d.map(|e| e as f64) / scale).into_array()) as f32; + let cavern = + ((cavern_nz * 0.5 + 0.5 - (1.0 - common)).max(0.0) / common).powf(common * 2.0); let cavern_height = cavern * cavern_avg_height; // Stalagtites - let stalagtite = info.index().noise.cave_nz + let stalagtite = info + .index() + .noise + .cave_nz .get(wpos2d.map(|e| e as f64 * 0.015).into_array()) .sub(0.5) .max(0.0) .mul((cavern_height as f64 - 5.0).mul(0.15).clamped(0.0, 1.0)) .mul(32.0 + cavern_avg_height as f64); - let hill = info.index().noise.cave_nz.get((wpos2d.map(|e| e as f64) / 96.0).into_array()) as f32 * cavern * 24.0; + let hill = info + .index() + .noise + .cave_nz + .get((wpos2d.map(|e| e as f64) / 96.0).into_array()) as f32 + * cavern + * 24.0; let rugged = 0.4; // How bumpy should the floor be relative to the ceiling? let cavern_bottom = (cavern_avg_alt - cavern_height * rugged + hill) as i32; - let cavern_avg_bottom = (cavern_avg_alt - ((height_range.start + height_range.end) * 0.5) * rugged) as i32; + let cavern_avg_bottom = + (cavern_avg_alt - ((height_range.start + height_range.end) * 0.5) * rugged) as i32; let cavern_top = (cavern_avg_alt + cavern_height) as i32; let cavern_avg_top = (cavern_avg_alt + cavern_avg_height) as i32; @@ -621,7 +642,14 @@ pub fn apply_caverns_to(canvas: &mut Canvas, dynamic_rng: &mut R) { let floor = stalagmite as i32; - (cavern_bottom, cavern_top, cavern_avg_bottom, cavern_avg_top, floor, stalagtite) + ( + cavern_bottom, + cavern_top, + cavern_avg_bottom, + cavern_avg_top, + floor, + stalagtite, + ) }; let mut mushroom_cache = HashMap::new(); @@ -635,53 +663,76 @@ pub fn apply_caverns_to(canvas: &mut Canvas, dynamic_rng: &mut R) { // Get mushroom block, if any, at a position let mut get_mushroom = |wpos: Vec3, dynamic_rng: &mut R| { for (wpos2d, seed) in info.chunks().gen_ctx.structure_gen.get(wpos.xy()) { - let mushroom = if let Some(mushroom) = mushroom_cache - .entry(wpos2d) - .or_insert_with(|| { + let mushroom = if let Some(mushroom) = + mushroom_cache.entry(wpos2d).or_insert_with(|| { let mut rng = RandomPerm::new(seed); let (cavern_bottom, cavern_top, _, _, floor, _) = cavern_at(wpos2d); if rng.gen_bool(0.1) && cavern_top - cavern_bottom > 32 { Some(Mushroom { pos: wpos2d.with_z(cavern_bottom + floor), - stalk: rng.gen_range(8.0..26.0), - head_color: Rgb::new(50, rng.gen_range(70..110), rng.gen_range(100..200)), + stalk: 12.0 + rng.gen::().powf(2.0) * 35.0, + head_color: Rgb::new( + 50, + rng.gen_range(70..110), + rng.gen_range(100..200), + ), }) } else { None } - }) - { + }) { mushroom } else { - continue + continue; }; let wposf = wpos.map(|e| e as f64); let warp_freq = 1.0 / 32.0; - let warp_amp = Vec3::new(8.0, 8.0, 12.0); - let wposf_warped = wposf.map(|e| e as f32) + Vec3::new( - FastNoise::new(seed + 0).get(wposf * warp_freq) as f32, - FastNoise::new(seed + 1).get(wposf * warp_freq) as f32, - FastNoise::new(seed + 2).get(wposf * warp_freq) as f32, - ) * warp_amp; + let warp_amp = Vec3::new(12.0, 12.0, 12.0); + let wposf_warped = wposf.map(|e| e as f32) + + Vec3::new( + FastNoise::new(seed + 0).get(wposf * warp_freq) as f32, + FastNoise::new(seed + 1).get(wposf * warp_freq) as f32, + FastNoise::new(seed + 2).get(wposf * warp_freq) as f32, + ) * warp_amp + * (wposf.z as f32 - mushroom.pos.z as f32) + .mul(0.1) + .clamped(0.0, 1.0); let rpos = wposf_warped - mushroom.pos.map(|e| e as f32).map(|e| e as f32); - let stalk_radius = 2.0f32; - let head_radius = 12.0f32; - let head_height = 10.0; + let stalk_radius = 2.5f32; + let head_radius = 18.0f32; + let head_height = 16.0; let dist_sq = rpos.xy().magnitude_squared(); if dist_sq < head_radius.powi(2) { let dist = dist_sq.sqrt(); + let head_dist = ((rpos - Vec3::unit_z() * mushroom.stalk) + / Vec2::broadcast(head_radius).with_z(head_height)) + .magnitude(); // Head - if rpos.z > mushroom.stalk && rpos.z < mushroom.stalk + head_height && dist < head_radius * (1.0 - (rpos.z - mushroom.stalk) / head_height).powf(0.125) { - return Some(Block::new(BlockKind::GlowingMushroom, mushroom.head_color)); - } else if rpos.z <= mushroom.stalk && rpos.xy().magnitude_squared() < stalk_radius.powi(2) { // Stalk - return Some(Block::new(BlockKind::Wood, Rgb::new(50, 120, 180))); + if rpos.z > mushroom.stalk + && rpos.z < mushroom.stalk + head_height + && dist + < head_radius * (1.0 - (rpos.z - mushroom.stalk) / head_height).powf(0.125) + { + if head_dist < 0.85 { + return Some(Block::new(BlockKind::GlowingMushroom, Rgb::new(90, 50, 0))); + } else if head_dist < 1.0 { + return Some(Block::new(BlockKind::Wood, mushroom.head_color)); + } + } + + if rpos.z <= mushroom.stalk + && dist_sq + < (stalk_radius * Lerp::lerp(1.5, 0.75, rpos.z / mushroom.stalk)).powi(2) + { + // Stalk + return Some(Block::new(BlockKind::Wood, Rgb::new(25, 60, 90))); } else if ((mushroom.stalk - 0.5)..mushroom.stalk).contains(&rpos.z) // Hanging orbs - && ((head_radius * 0.5)..(head_radius * 0.8)).contains(&dist) - && dynamic_rng.gen_bool(0.025) + && ((head_radius * 0.7)..(head_radius * 0.9)).contains(&dist) + && dynamic_rng.gen_bool(0.1) { return Some(Block::air(SpriteKind::Orb)); } @@ -692,39 +743,76 @@ pub fn apply_caverns_to(canvas: &mut Canvas, dynamic_rng: &mut R) { }; canvas.foreach_col(|canvas, wpos2d, _col| { - let (cavern_bottom, cavern_top, cavern_avg_bottom, cavern_avg_top, floor, stalagtite) = cavern_at(wpos2d); + let (cavern_bottom, cavern_top, cavern_avg_bottom, cavern_avg_top, floor, stalagtite) = + cavern_at(wpos2d); - let mini_stalagtite = info.index().noise.cave_nz + let mini_stalagtite = info + .index() + .noise + .cave_nz .get(wpos2d.map(|e| e as f64 * 0.08).into_array()) .sub(0.5) .max(0.0) - .mul(((cavern_top - cavern_bottom) as f64 - 5.0).mul(0.15).clamped(0.0, 1.0)) + .mul( + ((cavern_top - cavern_bottom) as f64 - 5.0) + .mul(0.15) + .clamped(0.0, 1.0), + ) .mul(24.0 + (cavern_avg_top - cavern_avg_bottom) as f64 * 0.2); let stalagtite_height = (stalagtite + mini_stalagtite) as i32; + let water_level = cavern_avg_bottom as i32 + 16; + let cavern_top = cavern_top as i32; let mut on_ground = true; - for z in cavern_bottom..cavern_top { + for z in cavern_bottom - 1..cavern_top { use SpriteKind::*; let wpos = wpos2d.with_z(z); - let block = if z < cavern_bottom + floor { + let block = if z < cavern_bottom { + if z > water_level + dynamic_rng.gen_range(4..16) { + Block::new(BlockKind::Leaves, Rgb::new(40, 85, 70)) + } else { + Block::new(BlockKind::Rock, Rgb::new(50, 40, 10)) + } + } else if z < cavern_bottom + floor { Block::new(BlockKind::WeakRock, Rgb::new(110, 120, 150)) } else if z > cavern_top - stalagtite_height { - if dynamic_rng.gen_bool(0.0035) { // Glowing rock in stalagtites + if dynamic_rng.gen_bool(0.0035) { + // Glowing rock in stalagtites Block::new(BlockKind::GlowingRock, Rgb::new(30, 150, 120)) } else { Block::new(BlockKind::WeakRock, Rgb::new(110, 120, 150)) } } else if let Some(mushroom_block) = get_mushroom(wpos, dynamic_rng) { mushroom_block - } else if z < cavern_avg_bottom as i32 + 4 { + } else if z < water_level { Block::water(SpriteKind::Empty) - } else if z == cavern_bottom + floor && dynamic_rng.gen_bool(0.005) && on_ground { - Block::air(*[CrystalLow, CaveMushroom].choose(dynamic_rng).unwrap()) + } else if z == cavern_bottom + floor && dynamic_rng.gen_bool(0.025) && on_ground { + Block::air( + *[ + CrystalLow, + CaveMushroom, + LeafyPlant, + Fern, + Reed, + Pyrebloom, + Moonbell, + Welwitch, + LongGrass, + MediumGrass, + ShortGrass, + ] + .choose(dynamic_rng) + .unwrap(), + ) } else if z == cavern_top - 1 && dynamic_rng.gen_bool(0.01) { - Block::air(*[CrystalHigh, CeilingMushroom, Orb].choose(dynamic_rng).unwrap()) + Block::air( + *[CrystalHigh, CeilingMushroom, Orb] + .choose(dynamic_rng) + .unwrap(), + ) } else { Block::empty() }; diff --git a/world/src/lib.rs b/world/src/lib.rs index 2ceb854cfa..0cd1c4f8d1 100644 --- a/world/src/lib.rs +++ b/world/src/lib.rs @@ -52,11 +52,10 @@ use common::{ vol::{ReadVol, RectVolSize, WriteVol}, }; use common_net::msg::{world_msg, WorldMapMsg}; -use rand::Rng; +use rand::{prelude::*, Rng}; +use rand_chacha::ChaCha8Rng; use serde::Deserialize; use std::time::Duration; -use rand_chacha::ChaCha8Rng; -use rand::prelude::*; use vek::*; #[derive(Debug)] From 46118acef3d5149555c852d2ed1f46ef443664d9 Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Mon, 19 Jul 2021 03:28:52 +0100 Subject: [PATCH 07/20] Added mushroom inner bevel --- world/src/layer/mod.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/world/src/layer/mod.rs b/world/src/layer/mod.rs index e94ddc9a08..eb7fc50ddb 100644 --- a/world/src/layer/mod.rs +++ b/world/src/layer/mod.rs @@ -711,9 +711,12 @@ pub fn apply_caverns_to(canvas: &mut Canvas, dynamic_rng: &mut R) { let head_dist = ((rpos - Vec3::unit_z() * mushroom.stalk) / Vec2::broadcast(head_radius).with_z(head_height)) .magnitude(); + + let stalk = mushroom.stalk + Lerp::lerp(head_height * 0.5, 0.0, dist / head_radius); + // Head - if rpos.z > mushroom.stalk - && rpos.z < mushroom.stalk + head_height + if rpos.z > stalk + && rpos.z <= mushroom.stalk + head_height && dist < head_radius * (1.0 - (rpos.z - mushroom.stalk) / head_height).powf(0.125) { @@ -724,7 +727,7 @@ pub fn apply_caverns_to(canvas: &mut Canvas, dynamic_rng: &mut R) { } } - if rpos.z <= mushroom.stalk + if rpos.z <= mushroom.stalk + head_height - 1.0 && dist_sq < (stalk_radius * Lerp::lerp(1.5, 0.75, rpos.z / mushroom.stalk)).powi(2) { From d785ecc1023927018e6940074dd3a0f5210c37f1 Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Mon, 19 Jul 2021 11:41:50 +0100 Subject: [PATCH 08/20] Added vines --- world/src/layer/mod.rs | 99 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 85 insertions(+), 14 deletions(-) diff --git a/world/src/layer/mod.rs b/world/src/layer/mod.rs index eb7fc50ddb..12ccdd2f8a 100644 --- a/world/src/layer/mod.rs +++ b/world/src/layer/mod.rs @@ -27,7 +27,7 @@ use rand::prelude::*; use serde::Deserialize; use std::{ f32, - ops::{Mul, Range, Sub}, + ops::{Add, Mul, Range, Sub}, }; use vek::*; @@ -576,14 +576,24 @@ pub fn apply_coral_to(canvas: &mut Canvas) { pub fn apply_caverns_to(canvas: &mut Canvas, dynamic_rng: &mut R) { let info = canvas.info(); - // Get cavern attributes at a position - let cavern_at = |wpos2d| { - let alt = info.land().get_alt_approx(wpos2d); - + let canvern_nz_at = |wpos2d: Vec2| { // Horizontal average scale of caverns let scale = 2048.0; // How common should they be? (0.0 - 1.0) let common = 0.15; + + let cavern_nz = info + .index() + .noise + .cave_nz + .get((wpos2d.map(|e| e as f64) / scale).into_array()) as f32; + ((cavern_nz * 0.5 + 0.5 - (1.0 - common)).max(0.0) / common).powf(common * 2.0) + }; + + // Get cavern attributes at a position + let cavern_at = |wpos2d| { + let alt = info.land().get_alt_approx(wpos2d); + // Range of heights for the caverns let height_range = 16.0..250.0; // Minimum distance below the surface @@ -603,13 +613,7 @@ pub fn apply_caverns_to(canvas: &mut Canvas, dynamic_rng: &mut R) { let cavern_avg_alt = CONFIG.sea_level.min(alt * 0.25) - height_range.end - surface_clearance; - let cavern_nz = info - .index() - .noise - .cave_nz - .get((wpos2d.map(|e| e as f64) / scale).into_array()) as f32; - let cavern = - ((cavern_nz * 0.5 + 0.5 - (1.0 - common)).max(0.0) / common).powf(common * 2.0); + let cavern = canvern_nz_at(wpos2d); let cavern_height = cavern * cavern_avg_height; // Stalagtites @@ -733,8 +737,8 @@ pub fn apply_caverns_to(canvas: &mut Canvas, dynamic_rng: &mut R) { { // Stalk return Some(Block::new(BlockKind::Wood, Rgb::new(25, 60, 90))); - } else if ((mushroom.stalk - 0.5)..mushroom.stalk).contains(&rpos.z) // Hanging orbs - && ((head_radius * 0.7)..(head_radius * 0.9)).contains(&dist) + } else if ((mushroom.stalk - 0.1)..(mushroom.stalk + 0.9)).contains(&rpos.z) // Hanging orbs + && dist > head_radius * 0.85 && dynamic_rng.gen_bool(0.1) { return Some(Block::air(SpriteKind::Orb)); @@ -746,6 +750,10 @@ pub fn apply_caverns_to(canvas: &mut Canvas, dynamic_rng: &mut R) { }; canvas.foreach_col(|canvas, wpos2d, _col| { + if canvern_nz_at(wpos2d) <= 0.0 { + return; + } + let (cavern_bottom, cavern_top, cavern_avg_bottom, cavern_avg_top, floor, stalagtite) = cavern_at(wpos2d); @@ -764,6 +772,57 @@ pub fn apply_caverns_to(canvas: &mut Canvas, dynamic_rng: &mut R) { .mul(24.0 + (cavern_avg_top - cavern_avg_bottom) as f64 * 0.2); let stalagtite_height = (stalagtite + mini_stalagtite) as i32; + let moss = info + .index() + .noise + .cave_nz + .get(wpos2d.map(|e| e as f64 * 0.05).into_array()) + .sub(0.85) + .max(0.0) + .mul( + ((cavern_top - cavern_bottom) as f64) + .mul(0.15) + .clamped(0.0, 1.0), + ) + .mul(64.0 + (cavern_avg_top - cavern_avg_bottom) as f64 * 5.0); + + let is_vine = |wpos: Vec3, dynamic_rng: &mut R| { + let wpos = wpos + wpos.xy().yx().with_z(0.0) * 0.2; // A little twist + let dims = Vec2::new(7.0, 256.0); // Long and thin + let vine_posf = (wpos + Vec2::new(0.0, (wpos.x / dims.x).floor() * 733.0)) / dims; // ~Random offset + let vine_pos = vine_posf.map(|e| e.floor() as i32); + let mut rng = RandomPerm::new(((vine_pos.x << 16) | vine_pos.y) as u32); // Rng for vine attributes + if rng.gen_bool(0.2) { + let vine_height = (cavern_avg_top - cavern_avg_bottom).max(64) as f32; + let vine_base = cavern_avg_bottom as f32 + rng.gen_range(48.0..vine_height); + let vine_y = (vine_posf.y.fract() - 0.5).abs() * 2.0 * dims.y; + let vine_reach = (vine_y * 0.05).powf(2.0).min(1024.0); + let vine_z = vine_base + vine_reach; + if Vec2::new(vine_posf.x.fract() * 2.0 - 1.0, (wpos.z - vine_z) / 5.0) + .magnitude_squared() + < 1.0f32 + { + let kind = if dynamic_rng.gen_bool(0.01) { + BlockKind::GlowingMushroom + } else { + BlockKind::Leaves + }; + Some(Block::new( + kind, + Rgb::new( + 0, + (vine_y + vine_reach).mul(0.05).sin().mul(35.0).add(85.0) as u8, + 90, + ), + )) + } else { + None + } + } else { + None + } + }; + let water_level = cavern_avg_bottom as i32 + 16; let cavern_top = cavern_top as i32; @@ -772,6 +831,7 @@ pub fn apply_caverns_to(canvas: &mut Canvas, dynamic_rng: &mut R) { use SpriteKind::*; let wpos = wpos2d.with_z(z); + let wposf = wpos.map(|e| e as f32); let block = if z < cavern_bottom { if z > water_level + dynamic_rng.gen_range(4..16) { @@ -816,6 +876,17 @@ pub fn apply_caverns_to(canvas: &mut Canvas, dynamic_rng: &mut R) { .choose(dynamic_rng) .unwrap(), ) + } else if let Some(vine) = is_vine(wposf, dynamic_rng) + .or_else(|| is_vine(wposf.xy().yx().with_z(wposf.z), dynamic_rng)) + { + vine + } else if z > cavern_top - moss as i32 { + let kind = if dynamic_rng.gen_bool(0.01) { + BlockKind::GlowingMushroom + } else { + BlockKind::Leaves + }; + Block::new(kind, Rgb::new(0, 85, 50)) } else { Block::empty() }; From b22029f87c500bcd4411175bf48b6fb2283dc30c Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Mon, 19 Jul 2021 18:05:57 +0100 Subject: [PATCH 09/20] More mushroom sprites --- world/src/layer/mod.rs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/world/src/layer/mod.rs b/world/src/layer/mod.rs index 12ccdd2f8a..a5da8ea33b 100644 --- a/world/src/layer/mod.rs +++ b/world/src/layer/mod.rs @@ -741,7 +741,13 @@ pub fn apply_caverns_to(canvas: &mut Canvas, dynamic_rng: &mut R) { && dist > head_radius * 0.85 && dynamic_rng.gen_bool(0.1) { - return Some(Block::air(SpriteKind::Orb)); + use SpriteKind::*; + let sprites = if dynamic_rng.gen_bool(0.1) { + &[Beehive, Lantern] + } else { + &[Orb, Liana] + }; + return Some(Block::air(*sprites.choose(dynamic_rng).unwrap())); } } } @@ -852,6 +858,11 @@ pub fn apply_caverns_to(canvas: &mut Canvas, dynamic_rng: &mut R) { mushroom_block } else if z < water_level { Block::water(SpriteKind::Empty) + .with_sprite(if z == cavern_bottom + floor && dynamic_rng.gen_bool(0.01) { + SpriteKind::CaveMushroom + } else { + SpriteKind::Empty + }) } else if z == cavern_bottom + floor && dynamic_rng.gen_bool(0.025) && on_ground { Block::air( *[ @@ -863,9 +874,11 @@ pub fn apply_caverns_to(canvas: &mut Canvas, dynamic_rng: &mut R) { Pyrebloom, Moonbell, Welwitch, + LargeGrass, LongGrass, MediumGrass, ShortGrass, + GrassBlue, ] .choose(dynamic_rng) .unwrap(), From 14ed73ec12a823a048368fc036dcf6f907cca127 Mon Sep 17 00:00:00 2001 From: Monty Marz Date: Tue, 20 Jul 2021 20:22:21 +0200 Subject: [PATCH 10/20] cavern sprites --- .../voxel/sprite/cavern/grass_long-0.vox | 3 + .../voxel/sprite/cavern/grass_long-1.vox | 3 + .../voxel/sprite/cavern/grass_long-2.vox | 3 + .../voxel/sprite/cavern/grass_long-3.vox | 3 + .../voxel/sprite/cavern/grass_long-4.vox | 3 + .../voxel/sprite/cavern/grass_long-5.vox | 3 + .../voxel/sprite/cavern/grass_long-6.vox | 3 + .../voxel/sprite/cavern/grass_long-7.vox | 3 + .../voxel/sprite/cavern/grass_med-0.vox | 3 + .../voxel/sprite/cavern/grass_med-1.vox | 3 + .../voxel/sprite/cavern/grass_med-2.vox | 3 + .../voxel/sprite/cavern/grass_med-3.vox | 3 + .../voxel/sprite/cavern/grass_short-0.vox | 3 + .../voxel/sprite/cavern/grass_short-1.vox | 3 + .../voxel/sprite/cavern/grass_short-2.vox | 3 + .../voxel/sprite/cavern/grass_short-3.vox | 3 + .../voxel/sprite/cavern/grass_short-4.vox | 3 + .../voxel/sprite/cavern/lillypad-0.vox | 3 + .../voxel/sprite/cavern/lillypad-1.vox | 3 + .../voxel/sprite/cavern/lillypad-2.vox | 3 + .../voxel/sprite/cavern/lillypad-3.vox | 3 + .../voxel/sprite/cavern/lillypad-4.vox | 3 + .../voxygen/voxel/sprite/cavern/mycel-0.vox | 3 + .../voxygen/voxel/sprite/cavern/mycel-1.vox | 3 + .../voxygen/voxel/sprite/cavern/mycel-2.vox | 3 + .../voxygen/voxel/sprite/cavern/mycel-3.vox | 3 + assets/voxygen/voxel/sprite_manifest.ron | 161 ++++++++++++++++++ common/src/terrain/block.rs | 2 +- common/src/terrain/sprite.rs | 5 + voxygen/src/scene/terrain/watcher.rs | 86 +++------- 30 files changed, 271 insertions(+), 61 deletions(-) create mode 100644 assets/voxygen/voxel/sprite/cavern/grass_long-0.vox create mode 100644 assets/voxygen/voxel/sprite/cavern/grass_long-1.vox create mode 100644 assets/voxygen/voxel/sprite/cavern/grass_long-2.vox create mode 100644 assets/voxygen/voxel/sprite/cavern/grass_long-3.vox create mode 100644 assets/voxygen/voxel/sprite/cavern/grass_long-4.vox create mode 100644 assets/voxygen/voxel/sprite/cavern/grass_long-5.vox create mode 100644 assets/voxygen/voxel/sprite/cavern/grass_long-6.vox create mode 100644 assets/voxygen/voxel/sprite/cavern/grass_long-7.vox create mode 100644 assets/voxygen/voxel/sprite/cavern/grass_med-0.vox create mode 100644 assets/voxygen/voxel/sprite/cavern/grass_med-1.vox create mode 100644 assets/voxygen/voxel/sprite/cavern/grass_med-2.vox create mode 100644 assets/voxygen/voxel/sprite/cavern/grass_med-3.vox create mode 100644 assets/voxygen/voxel/sprite/cavern/grass_short-0.vox create mode 100644 assets/voxygen/voxel/sprite/cavern/grass_short-1.vox create mode 100644 assets/voxygen/voxel/sprite/cavern/grass_short-2.vox create mode 100644 assets/voxygen/voxel/sprite/cavern/grass_short-3.vox create mode 100644 assets/voxygen/voxel/sprite/cavern/grass_short-4.vox create mode 100644 assets/voxygen/voxel/sprite/cavern/lillypad-0.vox create mode 100644 assets/voxygen/voxel/sprite/cavern/lillypad-1.vox create mode 100644 assets/voxygen/voxel/sprite/cavern/lillypad-2.vox create mode 100644 assets/voxygen/voxel/sprite/cavern/lillypad-3.vox create mode 100644 assets/voxygen/voxel/sprite/cavern/lillypad-4.vox create mode 100644 assets/voxygen/voxel/sprite/cavern/mycel-0.vox create mode 100644 assets/voxygen/voxel/sprite/cavern/mycel-1.vox create mode 100644 assets/voxygen/voxel/sprite/cavern/mycel-2.vox create mode 100644 assets/voxygen/voxel/sprite/cavern/mycel-3.vox diff --git a/assets/voxygen/voxel/sprite/cavern/grass_long-0.vox b/assets/voxygen/voxel/sprite/cavern/grass_long-0.vox new file mode 100644 index 0000000000..02a7af7f8c --- /dev/null +++ b/assets/voxygen/voxel/sprite/cavern/grass_long-0.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:144bb2be7627de61e951085c96038284ae28eed216c6b2c04eb0db596df2f738 +size 1428 diff --git a/assets/voxygen/voxel/sprite/cavern/grass_long-1.vox b/assets/voxygen/voxel/sprite/cavern/grass_long-1.vox new file mode 100644 index 0000000000..772cfe132a --- /dev/null +++ b/assets/voxygen/voxel/sprite/cavern/grass_long-1.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c76794542d91c94960373966c2b0232f57801d0a862a117090ba00a7ae934034 +size 1396 diff --git a/assets/voxygen/voxel/sprite/cavern/grass_long-2.vox b/assets/voxygen/voxel/sprite/cavern/grass_long-2.vox new file mode 100644 index 0000000000..e53115ea2a --- /dev/null +++ b/assets/voxygen/voxel/sprite/cavern/grass_long-2.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:44d27165b605d477f769123ef5d93de7ad357f0b937263ad37ebb8c1480c4324 +size 1444 diff --git a/assets/voxygen/voxel/sprite/cavern/grass_long-3.vox b/assets/voxygen/voxel/sprite/cavern/grass_long-3.vox new file mode 100644 index 0000000000..6157a2843f --- /dev/null +++ b/assets/voxygen/voxel/sprite/cavern/grass_long-3.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:44745ce1fef2c4cc1834e82abde5ef6ea3af113b3d3a4cf7df223b833ec07207 +size 1264 diff --git a/assets/voxygen/voxel/sprite/cavern/grass_long-4.vox b/assets/voxygen/voxel/sprite/cavern/grass_long-4.vox new file mode 100644 index 0000000000..d1b9ac74e1 --- /dev/null +++ b/assets/voxygen/voxel/sprite/cavern/grass_long-4.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9439482e006100f8219d27095e1929e15e4cfcd6303b8911a9ce638c30b76966 +size 1404 diff --git a/assets/voxygen/voxel/sprite/cavern/grass_long-5.vox b/assets/voxygen/voxel/sprite/cavern/grass_long-5.vox new file mode 100644 index 0000000000..3e0c01f98a --- /dev/null +++ b/assets/voxygen/voxel/sprite/cavern/grass_long-5.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7261c47bb5683e0a0cb1461dc84c5980e7cc1b25f8063b667fef86657e145a68 +size 1432 diff --git a/assets/voxygen/voxel/sprite/cavern/grass_long-6.vox b/assets/voxygen/voxel/sprite/cavern/grass_long-6.vox new file mode 100644 index 0000000000..b8e51f934e --- /dev/null +++ b/assets/voxygen/voxel/sprite/cavern/grass_long-6.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3bfe9db4fc6e624aa477b04dc6c681e390df65d8c488bf0eb61a86e7d8b7430d +size 1428 diff --git a/assets/voxygen/voxel/sprite/cavern/grass_long-7.vox b/assets/voxygen/voxel/sprite/cavern/grass_long-7.vox new file mode 100644 index 0000000000..5d7ffe064c --- /dev/null +++ b/assets/voxygen/voxel/sprite/cavern/grass_long-7.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:eec0a1b111d12f022e973e14afaf2e8f81fd7c6e4676a29cbc2f698f75a13e95 +size 1380 diff --git a/assets/voxygen/voxel/sprite/cavern/grass_med-0.vox b/assets/voxygen/voxel/sprite/cavern/grass_med-0.vox new file mode 100644 index 0000000000..452bd9f440 --- /dev/null +++ b/assets/voxygen/voxel/sprite/cavern/grass_med-0.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7496e27724e51a4129955a304cc10a15447845687e817140464da7f69be92386 +size 1244 diff --git a/assets/voxygen/voxel/sprite/cavern/grass_med-1.vox b/assets/voxygen/voxel/sprite/cavern/grass_med-1.vox new file mode 100644 index 0000000000..6f79383e6a --- /dev/null +++ b/assets/voxygen/voxel/sprite/cavern/grass_med-1.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7decc0743714a30208440e9437caaa77de79d730a9d7e060a4625c621ab30feb +size 1248 diff --git a/assets/voxygen/voxel/sprite/cavern/grass_med-2.vox b/assets/voxygen/voxel/sprite/cavern/grass_med-2.vox new file mode 100644 index 0000000000..2f2f65d819 --- /dev/null +++ b/assets/voxygen/voxel/sprite/cavern/grass_med-2.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:05c12e2e4d82b186c422f0da4617e17dd72f45b48071a3a7567fb186b581d4d2 +size 1288 diff --git a/assets/voxygen/voxel/sprite/cavern/grass_med-3.vox b/assets/voxygen/voxel/sprite/cavern/grass_med-3.vox new file mode 100644 index 0000000000..4e657e7fe8 --- /dev/null +++ b/assets/voxygen/voxel/sprite/cavern/grass_med-3.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:92fbd926d0e40ae777286c85d1cd56547717a0fc74f6d34611394113d063c74b +size 1232 diff --git a/assets/voxygen/voxel/sprite/cavern/grass_short-0.vox b/assets/voxygen/voxel/sprite/cavern/grass_short-0.vox new file mode 100644 index 0000000000..f89cffa1bb --- /dev/null +++ b/assets/voxygen/voxel/sprite/cavern/grass_short-0.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b0d4309ef5732adbfc46b47cf7aa29d78e3b7ae70d3184875b5e12fb0f8c043c +size 1132 diff --git a/assets/voxygen/voxel/sprite/cavern/grass_short-1.vox b/assets/voxygen/voxel/sprite/cavern/grass_short-1.vox new file mode 100644 index 0000000000..d5f92820eb --- /dev/null +++ b/assets/voxygen/voxel/sprite/cavern/grass_short-1.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1730532a21a1a804c19ca3fde55fdb6a9c84a8ea9b27f92ed63754aa185512b7 +size 1144 diff --git a/assets/voxygen/voxel/sprite/cavern/grass_short-2.vox b/assets/voxygen/voxel/sprite/cavern/grass_short-2.vox new file mode 100644 index 0000000000..bf342778c1 --- /dev/null +++ b/assets/voxygen/voxel/sprite/cavern/grass_short-2.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:681cc88f7c8744cd3983ae3fdf6350ef7791e9b115badb0eaaa1206177929f70 +size 1144 diff --git a/assets/voxygen/voxel/sprite/cavern/grass_short-3.vox b/assets/voxygen/voxel/sprite/cavern/grass_short-3.vox new file mode 100644 index 0000000000..60f15ad088 --- /dev/null +++ b/assets/voxygen/voxel/sprite/cavern/grass_short-3.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c9e0e7d61c9313aaf14602621fe438c43d8d9f6010adac49e67d59f2efbba17c +size 1140 diff --git a/assets/voxygen/voxel/sprite/cavern/grass_short-4.vox b/assets/voxygen/voxel/sprite/cavern/grass_short-4.vox new file mode 100644 index 0000000000..f384e765f2 --- /dev/null +++ b/assets/voxygen/voxel/sprite/cavern/grass_short-4.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c5ff5c224f0ea876895e22c3c57aabdef2e78b5a97b21b1fc13f4295122c7596 +size 1156 diff --git a/assets/voxygen/voxel/sprite/cavern/lillypad-0.vox b/assets/voxygen/voxel/sprite/cavern/lillypad-0.vox new file mode 100644 index 0000000000..7e6587b170 --- /dev/null +++ b/assets/voxygen/voxel/sprite/cavern/lillypad-0.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9210cb97a553956c72f72e920145e27fdabdb0e6addb0d5717f2c44d47c378b7 +size 1360 diff --git a/assets/voxygen/voxel/sprite/cavern/lillypad-1.vox b/assets/voxygen/voxel/sprite/cavern/lillypad-1.vox new file mode 100644 index 0000000000..c3f92c6c9e --- /dev/null +++ b/assets/voxygen/voxel/sprite/cavern/lillypad-1.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e1190ebbe1fcb9eeaaabf7e474eb2a10761e00e2027feb93392b533472c42666 +size 1512 diff --git a/assets/voxygen/voxel/sprite/cavern/lillypad-2.vox b/assets/voxygen/voxel/sprite/cavern/lillypad-2.vox new file mode 100644 index 0000000000..f7dc4f575b --- /dev/null +++ b/assets/voxygen/voxel/sprite/cavern/lillypad-2.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e606bb9b66630c56ec5a5d1151b2250983aba5b471fdd347dc3ab87b5dd153f1 +size 1612 diff --git a/assets/voxygen/voxel/sprite/cavern/lillypad-3.vox b/assets/voxygen/voxel/sprite/cavern/lillypad-3.vox new file mode 100644 index 0000000000..aaeef7f187 --- /dev/null +++ b/assets/voxygen/voxel/sprite/cavern/lillypad-3.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:468d154ec556f0bdaffe275a6b45164e7a53672a58b880cf1e189d6f8f6f4195 +size 1860 diff --git a/assets/voxygen/voxel/sprite/cavern/lillypad-4.vox b/assets/voxygen/voxel/sprite/cavern/lillypad-4.vox new file mode 100644 index 0000000000..0fa4ee525e --- /dev/null +++ b/assets/voxygen/voxel/sprite/cavern/lillypad-4.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ff8851998cc381be2d9dc3265fabc5c0e7e555329e4ebc20b490c7961b1a6fbd +size 1680 diff --git a/assets/voxygen/voxel/sprite/cavern/mycel-0.vox b/assets/voxygen/voxel/sprite/cavern/mycel-0.vox new file mode 100644 index 0000000000..4f3d86f73b --- /dev/null +++ b/assets/voxygen/voxel/sprite/cavern/mycel-0.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3d7180c8469565f8836b1e795c94faecab5fb97c1d3d9b3c1d50fd202bb23d6f +size 1180 diff --git a/assets/voxygen/voxel/sprite/cavern/mycel-1.vox b/assets/voxygen/voxel/sprite/cavern/mycel-1.vox new file mode 100644 index 0000000000..44ff474b6e --- /dev/null +++ b/assets/voxygen/voxel/sprite/cavern/mycel-1.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:10c3aa05a02e9431d2bf25fa473218c4c91ad62252ee3d8383e82a57cbcff1bb +size 1220 diff --git a/assets/voxygen/voxel/sprite/cavern/mycel-2.vox b/assets/voxygen/voxel/sprite/cavern/mycel-2.vox new file mode 100644 index 0000000000..a63c1a67af --- /dev/null +++ b/assets/voxygen/voxel/sprite/cavern/mycel-2.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0516877cbf4caa6370c2dbf3c957b294c12a93db8e805dd858e43c91d17ee36c +size 1152 diff --git a/assets/voxygen/voxel/sprite/cavern/mycel-3.vox b/assets/voxygen/voxel/sprite/cavern/mycel-3.vox new file mode 100644 index 0000000000..764d35b66e --- /dev/null +++ b/assets/voxygen/voxel/sprite/cavern/mycel-3.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6d3ceb2b40579d0b885280d80e8e52179d6696fe99ff4612ee2c9931ec0543bc +size 1256 diff --git a/assets/voxygen/voxel/sprite_manifest.ron b/assets/voxygen/voxel/sprite_manifest.ron index 79f99e2112..7672a1b9a5 100644 --- a/assets/voxygen/voxel/sprite_manifest.ron +++ b/assets/voxygen/voxel/sprite_manifest.ron @@ -3258,6 +3258,7 @@ CookingPot: Some(( ], wind_sway: 0.0, )), +// Ensnaring Vines EnsnaringVines: Some(( variations: [ ( @@ -3310,4 +3311,164 @@ Bones: Some(( ], wind_sway: 0.0, )), +// Short Cavern Grass Blue +CavernGrassBlueShort: Some(( + variations: [ + ( + model: "voxygen.voxel.sprite.cavern.grass_short-0", + offset: (-5.5, -5.5, 0.0), + lod_axes: (0.0, 0.0, 0.0), + ), + ( + model: "voxygen.voxel.sprite.cavern.grass_short-1", + offset: (-5.5, -5.5, 0.0), + lod_axes: (0.0, 0.0, 0.0), + ), + ( + model: "voxygen.voxel.sprite.cavern.grass_short-2", + offset: (-5.5, -5.5, 0.0), + lod_axes: (0.0, 0.0, 0.0), + ), + ( + model: "voxygen.voxel.sprite.cavern.grass_short-3", + offset: (-5.5, -5.5, 0.0), + lod_axes: (0.0, 0.0, 0.0), + ), + ( + model: "voxygen.voxel.sprite.cavern.grass_short-4", + offset: (-5.5, -5.5, 0.0), + lod_axes: (0.0, 0.0, 0.0), + ), + ], + wind_sway: 0.0, +)), +// Medium Cavern Grass Blue +CavernGrassBlueMedium: Some(( + variations: [ + ( + model: "voxygen.voxel.sprite.cavern.grass_med-0", + offset: (-5.5, -5.5, 0.0), + lod_axes: (0.0, 0.0, 0.0), + ), + ( + model: "voxygen.voxel.sprite.cavern.grass_med-1", + offset: (-5.5, -5.5, 0.0), + lod_axes: (0.0, 0.0, 0.0), + ), + ( + model: "voxygen.voxel.sprite.cavern.grass_med-2", + offset: (-5.5, -5.5, 0.0), + lod_axes: (0.0, 0.0, 0.0), + ), + ( + model: "voxygen.voxel.sprite.cavern.grass_med-3", + offset: (-5.5, -5.5, 0.0), + lod_axes: (0.0, 0.0, 0.0), + ), + ], + wind_sway: 0.0, +)), +// Long Cavern Grass Blue +CavernGrassBlueLong: Some(( + variations: [ + ( + model: "voxygen.voxel.sprite.cavern.grass_long-0", + offset: (-5.5, -5.5, 0.0), + lod_axes: (0.0, 0.0, 0.0), + ), + ( + model: "voxygen.voxel.sprite.cavern.grass_long-1", + offset: (-5.5, -5.5, 0.0), + lod_axes: (0.0, 0.0, 0.0), + ), + ( + model: "voxygen.voxel.sprite.cavern.grass_long-2", + offset: (-5.5, -5.5, 0.0), + lod_axes: (0.0, 0.0, 0.0), + ), + ( + model: "voxygen.voxel.sprite.cavern.grass_long-3", + offset: (-5.5, -5.5, 0.0), + lod_axes: (0.0, 0.0, 0.0), + ), + ( + model: "voxygen.voxel.sprite.cavern.grass_long-4", + offset: (-5.5, -5.5, 0.0), + lod_axes: (0.0, 0.0, 0.0), + ), + ( + model: "voxygen.voxel.sprite.cavern.grass_long-5", + offset: (-5.5, -5.5, 0.0), + lod_axes: (0.0, 0.0, 0.0), + ), + ( + model: "voxygen.voxel.sprite.cavern.grass_long-6", + offset: (-5.5, -5.5, 0.0), + lod_axes: (0.0, 0.0, 0.0), + ), + ( + model: "voxygen.voxel.sprite.cavern.grass_long-7", + offset: (-5.5, -5.5, 0.0), + lod_axes: (0.0, 0.0, 0.0), + ), + ], + wind_sway: 0.0, +)), +// Cavern Lillypads Blue +CavernLillypadBlue: Some(( + variations: [ + ( + model: "voxygen.voxel.sprite.cavern.lillypad-0", + offset: (-5.5, -5.5, -1.0), + lod_axes: (0.0, 0.0, 0.0), + ), + ( + model: "voxygen.voxel.sprite.cavern.lillypad-1", + offset: (-5.5, -5.5, -1.0), + lod_axes: (0.0, 0.0, 0.0), + ), + ( + model: "voxygen.voxel.sprite.cavern.lillypad-2", + offset: (-5.5, -5.5, -1.0), + lod_axes: (0.0, 0.0, 0.0), + ), + ( + model: "voxygen.voxel.sprite.cavern.lillypad-3", + offset: (-5.5, -5.5, -1.0), + lod_axes: (0.0, 0.0, 0.0), + ), + ( + model: "voxygen.voxel.sprite.cavern.lillypad-4", + offset: (-5.5, -5.5, -1.0), + lod_axes: (0.0, 0.0, 0.0), + ), + ], + wind_sway: 0.0, +)), +// Cavern Hanging Mycel Blue +CavernMycelBlue: Some(( + variations: [ + ( + model: "voxygen.voxel.sprite.cavern.mycel-0", + offset: (-0.5, -0.5, -21.0), + lod_axes: (0.0, 0.0, 0.0), + ), + ( + model: "voxygen.voxel.sprite.cavern.mycel-1", + offset: (-0.5, -0.5, -31.0), + lod_axes: (0.0, 0.0, 0.0), + ), + ( + model: "voxygen.voxel.sprite.cavern.mycel-2", + offset: (-0.5, -0.5, -14.0), + lod_axes: (0.0, 0.0, 0.0), + ), + ( + model: "voxygen.voxel.sprite.cavern.mycel-3", + offset: (-0.5, -0.5, -40.0), + lod_axes: (0.0, 0.0, 0.0), + ), + ], + wind_sway: 0.1, +)), ) diff --git a/common/src/terrain/block.rs b/common/src/terrain/block.rs index 9b91989557..5365566f96 100644 --- a/common/src/terrain/block.rs +++ b/common/src/terrain/block.rs @@ -179,7 +179,7 @@ impl Block { match self.kind() { BlockKind::Lava => Some(24), BlockKind::GlowingRock | BlockKind::GlowingWeakRock => Some(15), - BlockKind::BlockKind::GlowingMushroom => Some(20), + BlockKind::GlowingMushroom => Some(20), _ => match self.get_sprite()? { SpriteKind::StreetLamp | SpriteKind::StreetLampTall => Some(24), SpriteKind::Ember => Some(20), diff --git a/common/src/terrain/sprite.rs b/common/src/terrain/sprite.rs index cf67732a01..0a56b74d98 100644 --- a/common/src/terrain/sprite.rs +++ b/common/src/terrain/sprite.rs @@ -177,6 +177,11 @@ make_case_elim!( WitchWindow = 0x96, SmokeDummy = 0x97, Bones = 0x98, + CavernGrassBlueShort = 0x99, + CavernGrassBlueMedium = 0x9A, + CavernGrassBlueLong = 0x9B, + CavernLillypadBlue = 0x9C, + CavernMycelBlue = 0x9D, } ); diff --git a/voxygen/src/scene/terrain/watcher.rs b/voxygen/src/scene/terrain/watcher.rs index 14acd1b2e6..bcf3a952ff 100644 --- a/voxygen/src/scene/terrain/watcher.rs +++ b/voxygen/src/scene/terrain/watcher.rs @@ -79,6 +79,8 @@ impl BlocksOfInterest { river.push(pos) }, BlockKind::Snow if rng.gen_range(0..16) == 0 => snow.push(pos), + BlockKind::Lava if rng.gen_range(0..5) == 0 => fires.push(pos + Vec3::unit_z()), + BlockKind::Snow if rng.gen_range(0..16) == 0 => snow.push(pos), _ => match block.get_sprite() { Some(SpriteKind::Ember) => { fires.push(pos); @@ -109,66 +111,30 @@ impl BlocksOfInterest { Some(SpriteKind::CraftingBench) => { interactables.push((pos, Interaction::Craft(CraftingTab::All))) }, - BlockKind::Lava if rng.gen_range(0..5) == 0 => fires.push(pos + Vec3::unit_z()), - BlockKind::Snow if rng.gen_range(0..16) == 0 => snow.push(pos), - _ => match block.get_sprite() { - Some(SpriteKind::Ember) => { - fires.push(pos); - smokers.push(pos); - }, - Some(SpriteKind::SmokeDummy) => { - smokers.push(pos); - }, - // Offset positions to account for block height. - // TODO: Is this a good idea? - Some(SpriteKind::StreetLamp) => fire_bowls.push(pos + Vec3::unit_z() * 2), - Some(SpriteKind::FireBowlGround) => fire_bowls.push(pos + Vec3::unit_z()), - Some(SpriteKind::StreetLampTall) => { - fire_bowls.push(pos + Vec3::unit_z() * 3); - }, - Some(SpriteKind::WallSconce) => fire_bowls.push(pos + Vec3::unit_z()), - Some(SpriteKind::Beehive) => beehives.push(pos), - Some(SpriteKind::CrystalHigh) => fireflies.push(pos), - Some(SpriteKind::Reed) => { - reeds.push(pos); - fireflies.push(pos); - if rng.gen_range(0..12) == 0 { - frogs.push(pos); - } - }, - Some(SpriteKind::CaveMushroom) => fireflies.push(pos), - Some(SpriteKind::PinkFlower) => flowers.push(pos), - Some(SpriteKind::PurpleFlower) => flowers.push(pos), - Some(SpriteKind::RedFlower) => flowers.push(pos), - Some(SpriteKind::WhiteFlower) => flowers.push(pos), - Some(SpriteKind::YellowFlower) => flowers.push(pos), - Some(SpriteKind::Sunflower) => flowers.push(pos), - Some(SpriteKind::CraftingBench) => { - interactables.push((pos, Interaction::Craft(CraftingTab::All))) - }, - Some(SpriteKind::Forge) => { - interactables.push((pos, Interaction::Craft(CraftingTab::Dismantle))) - }, - Some(SpriteKind::TanningRack) => interactables - .push((pos, Interaction::Craft(CraftingTab::ProcessedMaterial))), - Some(SpriteKind::SpinningWheel) => { - interactables.push((pos, Interaction::Craft(CraftingTab::All))) - }, - Some(SpriteKind::Loom) => { - interactables.push((pos, Interaction::Craft(CraftingTab::All))) - }, - Some(SpriteKind::Cauldron) => { - fires.push(pos); - interactables.push((pos, Interaction::Craft(CraftingTab::Potion))) - }, - Some(SpriteKind::Anvil) => { - interactables.push((pos, Interaction::Craft(CraftingTab::Weapon))) - }, - Some(SpriteKind::CookingPot) => { - fires.push(pos); - interactables.push((pos, Interaction::Craft(CraftingTab::Food))) - }, - _ => {}, + Some(SpriteKind::SmokeDummy) => { + smokers.push(pos); + }, + Some(SpriteKind::Forge) => { + interactables.push((pos, Interaction::Craft(CraftingTab::Dismantle))) + }, + Some(SpriteKind::TanningRack) => interactables + .push((pos, Interaction::Craft(CraftingTab::ProcessedMaterial))), + Some(SpriteKind::SpinningWheel) => { + interactables.push((pos, Interaction::Craft(CraftingTab::All))) + }, + Some(SpriteKind::Loom) => { + interactables.push((pos, Interaction::Craft(CraftingTab::All))) + }, + Some(SpriteKind::Cauldron) => { + fires.push(pos); + interactables.push((pos, Interaction::Craft(CraftingTab::Potion))) + }, + Some(SpriteKind::Anvil) => { + interactables.push((pos, Interaction::Craft(CraftingTab::Weapon))) + }, + Some(SpriteKind::CookingPot) => { + fires.push(pos); + interactables.push((pos, Interaction::Craft(CraftingTab::Food))) }, _ => {}, }, From 7768a22f7fba960cd5650e5b9e4376f55f2308a4 Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Tue, 20 Jul 2021 19:31:02 +0100 Subject: [PATCH 11/20] Better moss --- world/src/layer/mod.rs | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/world/src/layer/mod.rs b/world/src/layer/mod.rs index a5da8ea33b..0bd51d5efb 100644 --- a/world/src/layer/mod.rs +++ b/world/src/layer/mod.rs @@ -778,19 +778,22 @@ pub fn apply_caverns_to(canvas: &mut Canvas, dynamic_rng: &mut R) { .mul(24.0 + (cavern_avg_top - cavern_avg_bottom) as f64 * 0.2); let stalagtite_height = (stalagtite + mini_stalagtite) as i32; + let moss_common = 1.5; let moss = info .index() .noise .cave_nz - .get(wpos2d.map(|e| e as f64 * 0.05).into_array()) - .sub(0.85) + .get(wpos2d.map(|e| e as f64 * 0.035).into_array()) + .sub(1.0 - moss_common) .max(0.0) + .mul(1.0 / moss_common) + .powf(8.0 * moss_common) .mul( ((cavern_top - cavern_bottom) as f64) .mul(0.15) .clamped(0.0, 1.0), ) - .mul(64.0 + (cavern_avg_top - cavern_avg_bottom) as f64 * 5.0); + .mul(16.0 + (cavern_avg_top - cavern_avg_bottom) as f64 * 0.35); let is_vine = |wpos: Vec3, dynamic_rng: &mut R| { let wpos = wpos + wpos.xy().yx().with_z(0.0) * 0.2; // A little twist @@ -809,7 +812,7 @@ pub fn apply_caverns_to(canvas: &mut Canvas, dynamic_rng: &mut R) { < 1.0f32 { let kind = if dynamic_rng.gen_bool(0.01) { - BlockKind::GlowingMushroom + BlockKind::GlowingRock } else { BlockKind::Leaves }; @@ -856,6 +859,13 @@ pub fn apply_caverns_to(canvas: &mut Canvas, dynamic_rng: &mut R) { } } else if let Some(mushroom_block) = get_mushroom(wpos, dynamic_rng) { mushroom_block + } else if z > cavern_top - moss as i32 { + let kind = if dynamic_rng.gen_bool(0.05 / (1.0 + ((cavern_top - z).max(0) as f64).mul(0.1))) { + BlockKind::GlowingMushroom + } else { + BlockKind::Leaves + }; + Block::new(kind, Rgb::new(50, 120, 160)) } else if z < water_level { Block::water(SpriteKind::Empty) .with_sprite(if z == cavern_bottom + floor && dynamic_rng.gen_bool(0.01) { @@ -883,7 +893,7 @@ pub fn apply_caverns_to(canvas: &mut Canvas, dynamic_rng: &mut R) { .choose(dynamic_rng) .unwrap(), ) - } else if z == cavern_top - 1 && dynamic_rng.gen_bool(0.01) { + } else if z == cavern_top - 1 && dynamic_rng.gen_bool(0.001) { Block::air( *[CrystalHigh, CeilingMushroom, Orb] .choose(dynamic_rng) @@ -893,13 +903,6 @@ pub fn apply_caverns_to(canvas: &mut Canvas, dynamic_rng: &mut R) { .or_else(|| is_vine(wposf.xy().yx().with_z(wposf.z), dynamic_rng)) { vine - } else if z > cavern_top - moss as i32 { - let kind = if dynamic_rng.gen_bool(0.01) { - BlockKind::GlowingMushroom - } else { - BlockKind::Leaves - }; - Block::new(kind, Rgb::new(0, 85, 50)) } else { Block::empty() }; From 353ccc5bcecca1d9cf8898b58262f09032d19d00 Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Tue, 20 Jul 2021 19:47:30 +0100 Subject: [PATCH 12/20] Added new cavern sprites to caverns --- common/src/terrain/block.rs | 6 +++- common/src/terrain/sprite.rs | 2 +- world/src/layer/mod.rs | 58 ++++++++++++++++++++++-------------- 3 files changed, 41 insertions(+), 25 deletions(-) diff --git a/common/src/terrain/block.rs b/common/src/terrain/block.rs index 5365566f96..6ab58c9e1d 100644 --- a/common/src/terrain/block.rs +++ b/common/src/terrain/block.rs @@ -190,7 +190,11 @@ impl Block { | SpriteKind::Orb => Some(16), SpriteKind::Velorite | SpriteKind::VeloriteFrag - | SpriteKind::Cauldron + | SpriteKind::CavernGrassBlueShort + | SpriteKind::CavernGrassBlueMedium + | SpriteKind::CavernGrassBlueLong + | SpriteKind::CavernLillypadBlue + | SpriteKind::CavernMycelBlue | SpriteKind::CeilingMushroom => Some(6), SpriteKind::CaveMushroom | SpriteKind::CookingPot diff --git a/common/src/terrain/sprite.rs b/common/src/terrain/sprite.rs index 0a56b74d98..f8033004d1 100644 --- a/common/src/terrain/sprite.rs +++ b/common/src/terrain/sprite.rs @@ -267,7 +267,7 @@ impl SpriteKind { | SpriteKind::Tin | SpriteKind::Silver | SpriteKind::Gold => 0.6, - SpriteKind::EnsnaringVines => 0.1, + SpriteKind::EnsnaringVines | SpriteKind::CavernLillypadBlue => 0.1, _ => return None, }) } diff --git a/world/src/layer/mod.rs b/world/src/layer/mod.rs index 0bd51d5efb..4d73d36424 100644 --- a/world/src/layer/mod.rs +++ b/world/src/layer/mod.rs @@ -743,9 +743,9 @@ pub fn apply_caverns_to(canvas: &mut Canvas, dynamic_rng: &mut R) { { use SpriteKind::*; let sprites = if dynamic_rng.gen_bool(0.1) { - &[Beehive, Lantern] + &[Beehive, Lantern] as &[_] } else { - &[Orb, Liana] + &[Orb, CavernMycelBlue, CavernMycelBlue] as &[_] }; return Some(Block::air(*sprites.choose(dynamic_rng).unwrap())); } @@ -860,42 +860,54 @@ pub fn apply_caverns_to(canvas: &mut Canvas, dynamic_rng: &mut R) { } else if let Some(mushroom_block) = get_mushroom(wpos, dynamic_rng) { mushroom_block } else if z > cavern_top - moss as i32 { - let kind = if dynamic_rng.gen_bool(0.05 / (1.0 + ((cavern_top - z).max(0) as f64).mul(0.1))) { + let kind = if dynamic_rng + .gen_bool(0.05 / (1.0 + ((cavern_top - z).max(0) as f64).mul(0.1))) + { BlockKind::GlowingMushroom } else { BlockKind::Leaves }; Block::new(kind, Rgb::new(50, 120, 160)) } else if z < water_level { - Block::water(SpriteKind::Empty) - .with_sprite(if z == cavern_bottom + floor && dynamic_rng.gen_bool(0.01) { + Block::water(SpriteKind::Empty).with_sprite( + if z == cavern_bottom + floor && dynamic_rng.gen_bool(0.01) { SpriteKind::CaveMushroom } else { SpriteKind::Empty - }) - } else if z == cavern_bottom + floor && dynamic_rng.gen_bool(0.025) && on_ground { + }, + ) + } else if z == water_level && dynamic_rng.gen_bool(0.01) && !on_ground { + Block::air(SpriteKind::CavernLillypadBlue) + } else if z == cavern_bottom + floor && dynamic_rng.gen_bool(0.1) && on_ground { Block::air( - *[ - CrystalLow, - CaveMushroom, - LeafyPlant, - Fern, - Reed, - Pyrebloom, - Moonbell, - Welwitch, - LargeGrass, - LongGrass, - MediumGrass, - ShortGrass, - GrassBlue, - ] + *if dynamic_rng.gen_bool(0.9) { + &[ + CavernGrassBlueShort, + CavernGrassBlueMedium, + CavernGrassBlueLong, + ] as &[_] + } else { + &[ + CaveMushroom, + LeafyPlant, + Fern, + Reed, + Pyrebloom, + Moonbell, + Welwitch, + LargeGrass, + LongGrass, + MediumGrass, + ShortGrass, + GrassBlue, + ] as &[_] + } .choose(dynamic_rng) .unwrap(), ) } else if z == cavern_top - 1 && dynamic_rng.gen_bool(0.001) { Block::air( - *[CrystalHigh, CeilingMushroom, Orb] + *[CrystalHigh, CeilingMushroom, Orb, CavernMycelBlue] .choose(dynamic_rng) .unwrap(), ) From 2ce88ac398fad30d20b32da3b34fdf2422e3bd27 Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Tue, 20 Jul 2021 20:48:50 +0100 Subject: [PATCH 13/20] Better grass and lily distribution --- world/src/layer/mod.rs | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/world/src/layer/mod.rs b/world/src/layer/mod.rs index 4d73d36424..2157945b33 100644 --- a/world/src/layer/mod.rs +++ b/world/src/layer/mod.rs @@ -795,6 +795,15 @@ pub fn apply_caverns_to(canvas: &mut Canvas, dynamic_rng: &mut R) { ) .mul(16.0 + (cavern_avg_top - cavern_avg_bottom) as f64 * 0.35); + let plant_factor = info + .index() + .noise + .cave_nz + .get(wpos2d.map(|e| e as f64 * 0.015).into_array()) + .add(1.0) + .mul(0.5) + .powf(2.0); + let is_vine = |wpos: Vec3, dynamic_rng: &mut R| { let wpos = wpos + wpos.xy().yx().with_z(0.0) * 0.2; // A little twist let dims = Vec2::new(7.0, 256.0); // Long and thin @@ -835,7 +844,7 @@ pub fn apply_caverns_to(canvas: &mut Canvas, dynamic_rng: &mut R) { let water_level = cavern_avg_bottom as i32 + 16; let cavern_top = cavern_top as i32; - let mut on_ground = true; + let mut last_kind = BlockKind::Rock; for z in cavern_bottom - 1..cavern_top { use SpriteKind::*; @@ -844,7 +853,7 @@ pub fn apply_caverns_to(canvas: &mut Canvas, dynamic_rng: &mut R) { let block = if z < cavern_bottom { if z > water_level + dynamic_rng.gen_range(4..16) { - Block::new(BlockKind::Leaves, Rgb::new(40, 85, 70)) + Block::new(BlockKind::Grass, Rgb::new(10, 75, 90)) } else { Block::new(BlockKind::Rock, Rgb::new(50, 40, 10)) } @@ -871,14 +880,19 @@ pub fn apply_caverns_to(canvas: &mut Canvas, dynamic_rng: &mut R) { } else if z < water_level { Block::water(SpriteKind::Empty).with_sprite( if z == cavern_bottom + floor && dynamic_rng.gen_bool(0.01) { - SpriteKind::CaveMushroom + *[ + SpriteKind::Seagrass, + SpriteKind::SeaGrapes, + SpriteKind::SeaweedTemperate, + SpriteKind::StonyCoral, + ].choose(dynamic_rng).unwrap() } else { SpriteKind::Empty }, ) - } else if z == water_level && dynamic_rng.gen_bool(0.01) && !on_ground { + } else if z == water_level && dynamic_rng.gen_bool(Lerp::lerp(0.0, 0.05, plant_factor)) && last_kind == BlockKind::Water { Block::air(SpriteKind::CavernLillypadBlue) - } else if z == cavern_bottom + floor && dynamic_rng.gen_bool(0.1) && on_ground { + } else if z == cavern_bottom + floor && dynamic_rng.gen_bool(Lerp::lerp(0.0, 0.5, plant_factor)) && last_kind == BlockKind::Grass { Block::air( *if dynamic_rng.gen_bool(0.9) { &[ @@ -919,7 +933,7 @@ pub fn apply_caverns_to(canvas: &mut Canvas, dynamic_rng: &mut R) { Block::empty() }; - on_ground |= block.is_solid(); + last_kind = block.kind(); let _ = canvas.set(wpos, block); } From a5309e1036f9fe7d31398c6303d1760fc208521c Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Tue, 20 Jul 2021 21:22:42 +0100 Subject: [PATCH 14/20] Prevented shrooms spawning in water --- world/src/layer/mod.rs | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/world/src/layer/mod.rs b/world/src/layer/mod.rs index 2157945b33..9b2536d7ac 100644 --- a/world/src/layer/mod.rs +++ b/world/src/layer/mod.rs @@ -653,6 +653,7 @@ pub fn apply_caverns_to(canvas: &mut Canvas, dynamic_rng: &mut R) { cavern_avg_top, floor, stalagtite, + cavern_avg_bottom as i32 + 16, // Water level ) }; @@ -670,10 +671,11 @@ pub fn apply_caverns_to(canvas: &mut Canvas, dynamic_rng: &mut R) { let mushroom = if let Some(mushroom) = mushroom_cache.entry(wpos2d).or_insert_with(|| { let mut rng = RandomPerm::new(seed); - let (cavern_bottom, cavern_top, _, _, floor, _) = cavern_at(wpos2d); - if rng.gen_bool(0.1) && cavern_top - cavern_bottom > 32 { + let (cavern_bottom, cavern_top, _, _, floor, _, water_level) = cavern_at(wpos2d); + let pos = wpos2d.with_z(cavern_bottom + floor); + if rng.gen_bool(0.15) && cavern_top - cavern_bottom > 32 && pos.z as i32 > water_level - 2 { Some(Mushroom { - pos: wpos2d.with_z(cavern_bottom + floor), + pos, stalk: 12.0 + rng.gen::().powf(2.0) * 35.0, head_color: Rgb::new( 50, @@ -760,7 +762,7 @@ pub fn apply_caverns_to(canvas: &mut Canvas, dynamic_rng: &mut R) { return; } - let (cavern_bottom, cavern_top, cavern_avg_bottom, cavern_avg_top, floor, stalagtite) = + let (cavern_bottom, cavern_top, cavern_avg_bottom, cavern_avg_top, floor, stalagtite, water_level) = cavern_at(wpos2d); let mini_stalagtite = info @@ -841,8 +843,6 @@ pub fn apply_caverns_to(canvas: &mut Canvas, dynamic_rng: &mut R) { } }; - let water_level = cavern_avg_bottom as i32 + 16; - let cavern_top = cavern_top as i32; let mut last_kind = BlockKind::Rock; for z in cavern_bottom - 1..cavern_top { @@ -894,25 +894,23 @@ pub fn apply_caverns_to(canvas: &mut Canvas, dynamic_rng: &mut R) { Block::air(SpriteKind::CavernLillypadBlue) } else if z == cavern_bottom + floor && dynamic_rng.gen_bool(Lerp::lerp(0.0, 0.5, plant_factor)) && last_kind == BlockKind::Grass { Block::air( - *if dynamic_rng.gen_bool(0.9) { + *if dynamic_rng.gen_bool(0.9) { // High density &[ CavernGrassBlueShort, CavernGrassBlueMedium, CavernGrassBlueLong, ] as &[_] - } else { + } else if dynamic_rng.gen_bool(0.5) { // Medium density &[ CaveMushroom, + ] as &[_] + } else { // Low density + &[ LeafyPlant, Fern, - Reed, Pyrebloom, Moonbell, Welwitch, - LargeGrass, - LongGrass, - MediumGrass, - ShortGrass, GrassBlue, ] as &[_] } From 086097cd56a1959c07d2c4765c0ec0a2a836bd70 Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Tue, 20 Jul 2021 23:25:49 +0100 Subject: [PATCH 15/20] Better vines and lighting --- assets/voxygen/shaders/terrain-frag.glsl | 2 +- common/src/terrain/block.rs | 2 +- world/src/layer/mod.rs | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/assets/voxygen/shaders/terrain-frag.glsl b/assets/voxygen/shaders/terrain-frag.glsl index 35c9691390..474f9ddca4 100644 --- a/assets/voxygen/shaders/terrain-frag.glsl +++ b/assets/voxygen/shaders/terrain-frag.glsl @@ -272,7 +272,7 @@ void main() { max_light *= f_light; // TODO: Apply AO after this - vec3 glow = glow_light(f_pos) * (pow(f_glow, 6) * 5 + pow(f_glow, 1.5) * 2); + vec3 glow = glow_light(f_pos) * (pow(f_glow, 3) * 5 + pow(f_glow, 2.0) * 2); reflected_light += glow; max_light += lights_at(f_pos, f_norm, view_dir, mu, cam_attenuation, fluid_alt, k_a, k_d, k_s, alpha, f_norm, 1.0, emitted_light, reflected_light); diff --git a/common/src/terrain/block.rs b/common/src/terrain/block.rs index 6ab58c9e1d..8665c20ed2 100644 --- a/common/src/terrain/block.rs +++ b/common/src/terrain/block.rs @@ -178,7 +178,7 @@ impl Block { pub fn get_glow(&self) -> Option { match self.kind() { BlockKind::Lava => Some(24), - BlockKind::GlowingRock | BlockKind::GlowingWeakRock => Some(15), + BlockKind::GlowingRock | BlockKind::GlowingWeakRock => Some(10), BlockKind::GlowingMushroom => Some(20), _ => match self.get_sprite()? { SpriteKind::StreetLamp | SpriteKind::StreetLampTall => Some(24), diff --git a/world/src/layer/mod.rs b/world/src/layer/mod.rs index 9b2536d7ac..0f023bb6bf 100644 --- a/world/src/layer/mod.rs +++ b/world/src/layer/mod.rs @@ -822,7 +822,7 @@ pub fn apply_caverns_to(canvas: &mut Canvas, dynamic_rng: &mut R) { .magnitude_squared() < 1.0f32 { - let kind = if dynamic_rng.gen_bool(0.01) { + let kind = if dynamic_rng.gen_bool(0.025) { BlockKind::GlowingRock } else { BlockKind::Leaves @@ -830,9 +830,9 @@ pub fn apply_caverns_to(canvas: &mut Canvas, dynamic_rng: &mut R) { Some(Block::new( kind, Rgb::new( - 0, + 85, (vine_y + vine_reach).mul(0.05).sin().mul(35.0).add(85.0) as u8, - 90, + 20, ), )) } else { From d09f1e1c4a392e0e591ad39ffa02317604a52cb8 Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Wed, 21 Jul 2021 10:52:02 +0100 Subject: [PATCH 16/20] Added noise to blocks --- world/src/layer/mod.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/world/src/layer/mod.rs b/world/src/layer/mod.rs index 0f023bb6bf..af671ba611 100644 --- a/world/src/layer/mod.rs +++ b/world/src/layer/mod.rs @@ -933,6 +933,15 @@ pub fn apply_caverns_to(canvas: &mut Canvas, dynamic_rng: &mut R) { last_kind = block.kind(); + let block = if block.is_filled() { + Block::new(block.kind(), block + .get_color() + .unwrap_or_default() + .map(|e| (e as f32 * dynamic_rng.gen_range(0.95..1.05)).clamped(0.0, 255.0) as u8)) + } else { + block + }; + let _ = canvas.set(wpos, block); } }); From bee922156e2a5fd0db88246007de533f0c28db07 Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Sun, 29 Aug 2021 10:44:46 +0100 Subject: [PATCH 17/20] Added radial pattern to shrooms --- world/src/layer/mod.rs | 71 ++++++++++++++++++++++++++---------------- 1 file changed, 45 insertions(+), 26 deletions(-) diff --git a/world/src/layer/mod.rs b/world/src/layer/mod.rs index af671ba611..b026959b28 100644 --- a/world/src/layer/mod.rs +++ b/world/src/layer/mod.rs @@ -671,9 +671,13 @@ pub fn apply_caverns_to(canvas: &mut Canvas, dynamic_rng: &mut R) { let mushroom = if let Some(mushroom) = mushroom_cache.entry(wpos2d).or_insert_with(|| { let mut rng = RandomPerm::new(seed); - let (cavern_bottom, cavern_top, _, _, floor, _, water_level) = cavern_at(wpos2d); + let (cavern_bottom, cavern_top, _, _, floor, _, water_level) = + cavern_at(wpos2d); let pos = wpos2d.with_z(cavern_bottom + floor); - if rng.gen_bool(0.15) && cavern_top - cavern_bottom > 32 && pos.z as i32 > water_level - 2 { + if rng.gen_bool(0.15) + && cavern_top - cavern_bottom > 32 + && pos.z as i32 > water_level - 2 + { Some(Mushroom { pos, stalk: 12.0 + rng.gen::().powf(2.0) * 35.0, @@ -727,7 +731,11 @@ pub fn apply_caverns_to(canvas: &mut Canvas, dynamic_rng: &mut R) { < head_radius * (1.0 - (rpos.z - mushroom.stalk) / head_height).powf(0.125) { if head_dist < 0.85 { - return Some(Block::new(BlockKind::GlowingMushroom, Rgb::new(90, 50, 0))); + let radial = (rpos.x.atan2(rpos.y) * 10.0).sin() * 0.5 + 0.5; + return Some(Block::new( + BlockKind::GlowingMushroom, + Rgb::new(30, 50 + (radial * 100.0) as u8, 100 - (radial * 50.0) as u8), + )); } else if head_dist < 1.0 { return Some(Block::new(BlockKind::Wood, mushroom.head_color)); } @@ -762,8 +770,15 @@ pub fn apply_caverns_to(canvas: &mut Canvas, dynamic_rng: &mut R) { return; } - let (cavern_bottom, cavern_top, cavern_avg_bottom, cavern_avg_top, floor, stalagtite, water_level) = - cavern_at(wpos2d); + let ( + cavern_bottom, + cavern_top, + cavern_avg_bottom, + cavern_avg_top, + floor, + stalagtite, + water_level, + ) = cavern_at(wpos2d); let mini_stalagtite = info .index() @@ -885,34 +900,36 @@ pub fn apply_caverns_to(canvas: &mut Canvas, dynamic_rng: &mut R) { SpriteKind::SeaGrapes, SpriteKind::SeaweedTemperate, SpriteKind::StonyCoral, - ].choose(dynamic_rng).unwrap() + ] + .choose(dynamic_rng) + .unwrap() } else { SpriteKind::Empty }, ) - } else if z == water_level && dynamic_rng.gen_bool(Lerp::lerp(0.0, 0.05, plant_factor)) && last_kind == BlockKind::Water { + } else if z == water_level + && dynamic_rng.gen_bool(Lerp::lerp(0.0, 0.05, plant_factor)) + && last_kind == BlockKind::Water + { Block::air(SpriteKind::CavernLillypadBlue) - } else if z == cavern_bottom + floor && dynamic_rng.gen_bool(Lerp::lerp(0.0, 0.5, plant_factor)) && last_kind == BlockKind::Grass { + } else if z == cavern_bottom + floor + && dynamic_rng.gen_bool(Lerp::lerp(0.0, 0.5, plant_factor)) + && last_kind == BlockKind::Grass + { Block::air( - *if dynamic_rng.gen_bool(0.9) { // High density + *if dynamic_rng.gen_bool(0.9) { + // High density &[ CavernGrassBlueShort, CavernGrassBlueMedium, CavernGrassBlueLong, ] as &[_] - } else if dynamic_rng.gen_bool(0.5) { // Medium density - &[ - CaveMushroom, - ] as &[_] - } else { // Low density - &[ - LeafyPlant, - Fern, - Pyrebloom, - Moonbell, - Welwitch, - GrassBlue, - ] as &[_] + } else if dynamic_rng.gen_bool(0.5) { + // Medium density + &[CaveMushroom] as &[_] + } else { + // Low density + &[LeafyPlant, Fern, Pyrebloom, Moonbell, Welwitch, GrassBlue] as &[_] } .choose(dynamic_rng) .unwrap(), @@ -934,10 +951,12 @@ pub fn apply_caverns_to(canvas: &mut Canvas, dynamic_rng: &mut R) { last_kind = block.kind(); let block = if block.is_filled() { - Block::new(block.kind(), block - .get_color() - .unwrap_or_default() - .map(|e| (e as f32 * dynamic_rng.gen_range(0.95..1.05)).clamped(0.0, 255.0) as u8)) + Block::new( + block.kind(), + block.get_color().unwrap_or_default().map(|e| { + (e as f32 * dynamic_rng.gen_range(0.95..1.05)).clamped(0.0, 255.0) as u8 + }), + ) } else { block }; From 1473029204743bdc2be9b1878e4d91acf15060ef Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Fri, 8 Oct 2021 13:55:26 +0100 Subject: [PATCH 18/20] Added ability to toggle world features --- assets/world/features.ron | 12 ++++++++++++ server/src/lib.rs | 2 +- world/src/config.rs | 20 ++++++++++++++++++++ world/src/index.rs | 22 +++++++++++++++------- world/src/lib.rs | 30 ++++++++++++++++++++++-------- 5 files changed, 70 insertions(+), 16 deletions(-) create mode 100644 assets/world/features.ron diff --git a/assets/world/features.ron b/assets/world/features.ron new file mode 100644 index 0000000000..05c703d615 --- /dev/null +++ b/assets/world/features.ron @@ -0,0 +1,12 @@ +#![enable(unwrap_newtypes)] +#![enable(implicit_some)] + +( + caverns: false, // TODO: Disabled by default until cave overhaul + caves: true, + shrubs: true, + trees: true, + scatter: true, + paths: true, + spots: true, +) diff --git a/server/src/lib.rs b/server/src/lib.rs index be13805968..fb69658408 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -851,7 +851,7 @@ impl Server { let ecs = self.state.ecs_mut(); let slow_jobs = ecs.write_resource::(); - index.reload_colors_if_changed(|index| { + index.reload_if_changed(|index| { let mut chunk_generator = ecs.write_resource::(); let client = ecs.read_storage::(); let mut terrain = ecs.write_resource::(); diff --git a/world/src/config.rs b/world/src/config.rs index e6db31e6f2..b666c82c24 100644 --- a/world/src/config.rs +++ b/world/src/config.rs @@ -1,3 +1,6 @@ +use common::assets; +use serde::Deserialize; + pub struct Config { pub sea_level: f32, pub mountain_scale: f32, @@ -69,3 +72,20 @@ pub const CONFIG: Config = Config { river_min_height: 0.25, river_width_to_depth: 8.0, }; + +#[derive(Deserialize)] +pub struct Features { + pub caverns: bool, + pub caves: bool, + pub shrubs: bool, + pub trees: bool, + pub scatter: bool, + pub paths: bool, + pub spots: bool, +} + +impl assets::Asset for Features { + type Loader = assets::RonLoader; + + const EXTENSION: &'static str = "ron"; +} diff --git a/world/src/index.rs b/world/src/index.rs index 7d5d6e4685..0edef3eaf7 100644 --- a/world/src/index.rs +++ b/world/src/index.rs @@ -1,7 +1,7 @@ use crate::{ layer::wildlife::{self, DensityFn, SpawnEntry}, site::{economy::TradeInformation, Site}, - Colors, + Colors, Features, }; use common::{ assets::{AssetExt, AssetHandle}, @@ -13,6 +13,7 @@ use noise::{Seedable, SuperSimplex}; use std::sync::Arc; const WORLD_COLORS_MANIFEST: &str = "world.style.colors"; +const WORLD_FEATURES_MANIFEST: &str = "world.features"; pub struct Index { pub seed: u32, @@ -22,6 +23,7 @@ pub struct Index { pub trade: TradeInformation, pub wildlife_spawns: Vec<(AssetHandle, DensityFn)>, colors: AssetHandle>, + features: AssetHandle>, } /// An owned reference to indexed data. @@ -32,6 +34,7 @@ pub struct Index { #[derive(Clone)] pub struct IndexOwned { colors: Arc, + features: Arc, index: Arc, } @@ -47,6 +50,7 @@ impl Deref for IndexOwned { #[derive(Clone, Copy)] pub struct IndexRef<'a> { pub colors: &'a Colors, + pub features: &'a Features, pub index: &'a Index, } @@ -60,6 +64,7 @@ impl Index { /// NOTE: Panics if the color manifest cannot be loaded. pub fn new(seed: u32) -> Self { let colors = Arc::::load_expect(WORLD_COLORS_MANIFEST); + let features = Arc::::load_expect(WORLD_FEATURES_MANIFEST); let wildlife_spawns = wildlife::spawn_manifest() .into_iter() .map(|(e, f)| (SpawnEntry::load_expect(e), f)) @@ -73,6 +78,7 @@ impl Index { trade: Default::default(), wildlife_spawns, colors, + features, } } @@ -89,10 +95,12 @@ impl Index { impl IndexOwned { pub fn new(index: Index) -> Self { let colors = index.colors.cloned(); + let features = index.features.cloned(); Self { index: Arc::new(index), colors, + features, } } @@ -103,13 +111,12 @@ impl IndexOwned { /// solution. /// /// Ideally, this should be called about once per tick. - pub fn reload_colors_if_changed( - &mut self, - reload: impl FnOnce(&mut Self) -> R, - ) -> Option { - self.index.colors.reloaded_global().then(move || { - // Reload the color from the asset handle, which is updated automatically + pub fn reload_if_changed(&mut self, reload: impl FnOnce(&mut Self) -> R) -> Option { + let reloaded = self.index.colors.reloaded_global() || self.index.features.reloaded_global(); + reloaded.then(move || { + // Reload the fields from the asset handle, which is updated automatically self.colors = self.index.colors.cloned(); + self.features = self.index.features.cloned(); reload(self) }) } @@ -117,6 +124,7 @@ impl IndexOwned { pub fn as_index_ref(&self) -> IndexRef { IndexRef { colors: &self.colors, + features: &self.features, index: &self.index, } } diff --git a/world/src/lib.rs b/world/src/lib.rs index 0cd1c4f8d1..182c2a94d4 100644 --- a/world/src/lib.rs +++ b/world/src/lib.rs @@ -28,7 +28,7 @@ pub mod util; // Reexports pub use crate::{ canvas::{Canvas, CanvasInfo}, - config::CONFIG, + config::{Features, CONFIG}, land::Land, }; pub use block::BlockGen; @@ -347,13 +347,27 @@ impl World { entities: Vec::new(), }; - layer::apply_caverns_to(&mut canvas, &mut dynamic_rng); - layer::apply_caves_to(&mut canvas, &mut dynamic_rng); - layer::apply_shrubs_to(&mut canvas, &mut dynamic_rng); - layer::apply_trees_to(&mut canvas, &mut dynamic_rng); - layer::apply_scatter_to(&mut canvas, &mut dynamic_rng); - layer::apply_paths_to(&mut canvas); - layer::apply_spots_to(&mut canvas, &mut dynamic_rng); + if index.features.caverns { + layer::apply_caverns_to(&mut canvas, &mut dynamic_rng); + } + if index.features.caves { + layer::apply_caves_to(&mut canvas, &mut dynamic_rng); + } + if index.features.shrubs { + layer::apply_shrubs_to(&mut canvas, &mut dynamic_rng); + } + if index.features.trees { + layer::apply_trees_to(&mut canvas, &mut dynamic_rng); + } + if index.features.scatter { + layer::apply_scatter_to(&mut canvas, &mut dynamic_rng); + } + if index.features.paths { + layer::apply_paths_to(&mut canvas); + } + if index.features.spots { + layer::apply_spots_to(&mut canvas, &mut dynamic_rng); + } // layer::apply_coral_to(&mut canvas); // Apply site generation From e660aafed309e0803dbb8cc7882acd380c91567b Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Sat, 9 Oct 2021 13:19:28 +0100 Subject: [PATCH 19/20] Nicer lake borders --- world/examples/settlement_viewer.rs | 7 ++- world/src/column/mod.rs | 93 ++++++++++++++++++++++------- world/src/index.rs | 2 + world/src/layer/mod.rs | 2 +- 4 files changed, 81 insertions(+), 23 deletions(-) diff --git a/world/examples/settlement_viewer.rs b/world/examples/settlement_viewer.rs index d2c311827b..d397a2dd06 100644 --- a/world/examples/settlement_viewer.rs +++ b/world/examples/settlement_viewer.rs @@ -17,7 +17,12 @@ fn main() { let mut focus = Vec2::::zero(); let mut zoom = 1.0; let colors = &**index.colors().read(); - let index = IndexRef { colors, index }; + let features = &**index.features().read(); + let index = IndexRef { + colors, + features, + index, + }; while win.is_open() { let mut buf = vec![0; W * H]; diff --git a/world/src/column/mod.rs b/world/src/column/mod.rs index 4fa873f159..2d77fb8cf8 100644 --- a/world/src/column/mod.rs +++ b/world/src/column/mod.rs @@ -414,7 +414,7 @@ impl<'a> Sampler<'a> for ColumnGen<'a> { downhill_chunk.river.river_kind, Some(RiverKind::Lake { .. }) )) - && (river_chunk.water_alt > downhill_chunk.water_alt + 8.0) + && (river_chunk.water_alt > downhill_chunk.water_alt + 0.0) } /// Determine the altitude of a river based on the altitude of the @@ -452,7 +452,14 @@ impl<'a> Sampler<'a> for ColumnGen<'a> { // they do not result in artifacts, even in edge cases. The exact configuration // of this code is the product of hundreds of hours of testing and // refinement and I ask that you do not take that effort lightly. - let (river_water_level, in_river, lake_water_level, lake_dist, water_dist, unbounded_water_level) = neighbor_river_data.iter().copied().fold( + let ( + river_water_level, + in_river, + lake_water_level, + lake_dist, + water_dist, + unbounded_water_level, + ) = neighbor_river_data.iter().copied().fold( ( WeightedSum::default().with_max(base_sea_level), false, @@ -461,7 +468,18 @@ impl<'a> Sampler<'a> for ColumnGen<'a> { None, WeightedSum::default().with_max(base_sea_level), ), - |(mut river_water_level, mut in_river, mut lake_water_level, mut lake_dist, water_dist, mut unbounded_water_level), (river_chunk_idx, river_chunk, river, dist_info)| match (river.river_kind, dist_info) { + |( + mut river_water_level, + mut in_river, + lake_water_level, + mut lake_dist, + water_dist, + mut unbounded_water_level, + ), + (river_chunk_idx, river_chunk, river, dist_info)| match ( + river.river_kind, + dist_info, + ) { ( Some(kind), Some((_, _, river_width, (river_t, (river_pos, _), downhill_chunk))), @@ -480,7 +498,8 @@ impl<'a> Sampler<'a> for ColumnGen<'a> { match kind { RiverKind::River { .. } => { - // Alt of river water *is* the alt of land (ignoring gorge, which gets applied later) + // Alt of river water *is* the alt of land (ignoring gorge, which gets + // applied later) let river_water_alt = river_water_alt( river_chunk.alt.max(river_chunk.water_alt), downhill_chunk.alt.max(downhill_chunk.water_alt), @@ -488,14 +507,15 @@ impl<'a> Sampler<'a> for ColumnGen<'a> { is_waterfall(river_chunk_idx, river_chunk, downhill_chunk), ); - river_water_level = river_water_level - .with(river_water_alt, near_center); + river_water_level = + river_water_level.with(river_water_alt, near_center); if river_edge_dist <= 0.0 { in_river = true; } }, - // Slightly wider threshold is chosen in case the lake bounds are a bit wrong + // Slightly wider threshold is chosen in case the lake bounds are a bit + // wrong RiverKind::Lake { .. } | RiverKind::Ocean => { let lake_water_alt = if matches!(kind, RiverKind::Ocean) { base_sea_level @@ -509,32 +529,63 @@ impl<'a> Sampler<'a> for ColumnGen<'a> { }; if river_edge_dist > 0.0 && river_width > lake_width * 0.99 { - let unbounded_water_alt = lake_water_alt - ((river_edge_dist - 8.0).max(0.0) / 5.0).powf(2.0); + let unbounded_water_alt = lake_water_alt + - ((river_edge_dist - 8.0).max(0.0) / 5.0).powf(2.0); unbounded_water_level = unbounded_water_level - .with(unbounded_water_alt, 1.0 / (1.0 + river_edge_dist * 5.0)) - .with_max(unbounded_water_alt); + .with(unbounded_water_alt, 1.0 / (1.0 + river_edge_dist * 5.0)); + //.with_max(unbounded_water_alt); } - river_water_level = river_water_level - .with(lake_water_alt, near_center); + river_water_level = river_water_level.with(lake_water_alt, near_center); lake_dist = lake_dist.min(river_edge_dist); - // Lake border prevents a lake failing to propagate its altitude to nearby rivers - if river_edge_dist <= 0.0 { - lake_water_level = lake_water_level - // Make sure the closest lake is prioritised - .with(lake_water_alt, near_center + 0.1 / (1.0 + river_edge_dist)); + // Lake border prevents a lake failing to propagate its altitude to + // nearby rivers + let off = 0.0; + let len = 3.0; + if river_edge_dist <= off { + // lake_water_level = lake_water_level + // // Make sure the closest lake is prioritised + // .with(lake_water_alt, near_center + 0.1 / (1.0 + + // river_edge_dist)); // .with_min(lake_water_alt); + // + river_water_level = river_water_level.with_min( + lake_water_alt + + ((((river_dist - river_width * 0.5) as f32 + len - off) + .max(0.0)) + / len) + .powf(1.5) + * 32.0, + ); } }, }; let river_edge_dist_unclamped = (river_dist - river_width * 0.5) as f32; - let water_dist = Some(water_dist.unwrap_or(river_edge_dist_unclamped).min(river_edge_dist_unclamped)); + let water_dist = Some( + water_dist + .unwrap_or(river_edge_dist_unclamped) + .min(river_edge_dist_unclamped), + ); - (river_water_level, in_river, lake_water_level, lake_dist, water_dist, unbounded_water_level) + ( + river_water_level, + in_river, + lake_water_level, + lake_dist, + water_dist, + unbounded_water_level, + ) }, - (_, _) => (river_water_level, in_river, lake_water_level, lake_dist, water_dist, unbounded_water_level), + (_, _) => ( + river_water_level, + in_river, + lake_water_level, + lake_dist, + water_dist, + unbounded_water_level, + ), }, ); let unbounded_water_level = unbounded_water_level.eval_or(base_sea_level); @@ -679,7 +730,7 @@ impl<'a> Sampler<'a> for ColumnGen<'a> { ) .with_min(min_alt.unwrap_or(riverbed_alt).min(riverbed_alt)) } else { - const GORGE: f32 = 0.5; + const GORGE: f32 = 0.25; const BANK_SCALE: f32 = 24.0; // Weighting of this riverbank on nearby terrain (higher when closer to // the river). This 'pulls' the riverbank diff --git a/world/src/index.rs b/world/src/index.rs index 0edef3eaf7..1e69f6f310 100644 --- a/world/src/index.rs +++ b/world/src/index.rs @@ -84,6 +84,8 @@ impl Index { pub fn colors(&self) -> AssetHandle> { self.colors } + pub fn features(&self) -> AssetHandle> { self.features } + pub fn get_site_prices(&self, site_id: SiteId) -> Option { self.sites .recreate_id(site_id) diff --git a/world/src/layer/mod.rs b/world/src/layer/mod.rs index b026959b28..8cb9f87efd 100644 --- a/world/src/layer/mod.rs +++ b/world/src/layer/mod.rs @@ -701,7 +701,7 @@ pub fn apply_caverns_to(canvas: &mut Canvas, dynamic_rng: &mut R) { let warp_amp = Vec3::new(12.0, 12.0, 12.0); let wposf_warped = wposf.map(|e| e as f32) + Vec3::new( - FastNoise::new(seed + 0).get(wposf * warp_freq) as f32, + FastNoise::new(seed).get(wposf * warp_freq) as f32, FastNoise::new(seed + 1).get(wposf * warp_freq) as f32, FastNoise::new(seed + 2).get(wposf * warp_freq) as f32, ) * warp_amp From f9b661fc617d3cfe6fb9cc640cc1e81348c72444 Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Fri, 15 Oct 2021 22:47:43 +0100 Subject: [PATCH 20/20] Corrected historical typo --- assets/world/style/colors.ron | 2 +- world/src/layer/mod.rs | 32 ++++++++++++++++---------------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/assets/world/style/colors.ron b/assets/world/style/colors.ron index c01b322e19..ce0f153bcc 100644 --- a/assets/world/style/colors.ron +++ b/assets/world/style/colors.ron @@ -67,7 +67,7 @@ deep_stone_color: (125, 120, 130), layer: ( bridge: (80, 80, 100), - stalagtite: (90, 71, 112), + stalactite: (90, 71, 112), cave_floor: (42, 39, 82), cave_roof: (38, 21, 79), dirt: (69, 48, 15), diff --git a/world/src/layer/mod.rs b/world/src/layer/mod.rs index 8cb9f87efd..7bf1aac864 100644 --- a/world/src/layer/mod.rs +++ b/world/src/layer/mod.rs @@ -34,7 +34,7 @@ use vek::*; #[derive(Deserialize)] pub struct Colors { pub bridge: (u8, u8, u8), - pub stalagtite: (u8, u8, u8), + pub stalactite: (u8, u8, u8), pub cave_floor: (u8, u8, u8), pub cave_roof: (u8, u8, u8), pub dirt: (u8, u8, u8), @@ -172,11 +172,11 @@ pub fn apply_caves_to(canvas: &mut Canvas, rng: &mut impl Rng) { let floor_dist = pit_condition as i32 * pit_depth as i32; let vein_condition = cave_depth % 12.0 > 11.5 && cave_x > 0.1 && cave_x < 0.6 && cave_depth > 200.0; - let stalagtite_condition = cave_depth > 150.0; + let stalactite_condition = cave_depth > 150.0; let vein_depth = 3; let vein_floor = cave_base - vein_depth; // Stalagtites - let stalagtites = info + let stalactites = info .index() .noise .cave_nz @@ -190,18 +190,18 @@ pub fn apply_caves_to(canvas: &mut Canvas, rng: &mut impl Rng) { ) .mul(45.0) as i32; - // Generate stalagtites if there's something for them to hold on to + // Generate stalactites if there's something for them to hold on to if canvas .get(Vec3::new(wpos2d.x, wpos2d.y, cave_roof)) .is_filled() - && stalagtite_condition + && stalactite_condition { - for z in cave_roof - stalagtites..cave_roof { + for z in cave_roof - stalactites..cave_roof { canvas.set( Vec3::new(wpos2d.x, wpos2d.y, z), Block::new( BlockKind::WeakRock, - noisy_color(info.index().colors.layer.stalagtite.into(), 8), + noisy_color(info.index().colors.layer.stalactite.into(), 8), ), ); } @@ -617,7 +617,7 @@ pub fn apply_caverns_to(canvas: &mut Canvas, dynamic_rng: &mut R) { let cavern_height = cavern * cavern_avg_height; // Stalagtites - let stalagtite = info + let stalactite = info .index() .noise .cave_nz @@ -641,8 +641,8 @@ pub fn apply_caverns_to(canvas: &mut Canvas, dynamic_rng: &mut R) { let cavern_top = (cavern_avg_alt + cavern_height) as i32; let cavern_avg_top = (cavern_avg_alt + cavern_avg_height) as i32; - // Stalagmites rise up to meet stalagtites - let stalagmite = stalagtite; + // Stalagmites rise up to meet stalactites + let stalagmite = stalactite; let floor = stalagmite as i32; @@ -652,7 +652,7 @@ pub fn apply_caverns_to(canvas: &mut Canvas, dynamic_rng: &mut R) { cavern_avg_bottom, cavern_avg_top, floor, - stalagtite, + stalactite, cavern_avg_bottom as i32 + 16, // Water level ) }; @@ -776,11 +776,11 @@ pub fn apply_caverns_to(canvas: &mut Canvas, dynamic_rng: &mut R) { cavern_avg_bottom, cavern_avg_top, floor, - stalagtite, + stalactite, water_level, ) = cavern_at(wpos2d); - let mini_stalagtite = info + let mini_stalactite = info .index() .noise .cave_nz @@ -793,7 +793,7 @@ pub fn apply_caverns_to(canvas: &mut Canvas, dynamic_rng: &mut R) { .clamped(0.0, 1.0), ) .mul(24.0 + (cavern_avg_top - cavern_avg_bottom) as f64 * 0.2); - let stalagtite_height = (stalagtite + mini_stalagtite) as i32; + let stalactite_height = (stalactite + mini_stalactite) as i32; let moss_common = 1.5; let moss = info @@ -874,9 +874,9 @@ pub fn apply_caverns_to(canvas: &mut Canvas, dynamic_rng: &mut R) { } } else if z < cavern_bottom + floor { Block::new(BlockKind::WeakRock, Rgb::new(110, 120, 150)) - } else if z > cavern_top - stalagtite_height { + } else if z > cavern_top - stalactite_height { if dynamic_rng.gen_bool(0.0035) { - // Glowing rock in stalagtites + // Glowing rock in stalactites Block::new(BlockKind::GlowingRock, Rgb::new(30, 150, 120)) } else { Block::new(BlockKind::WeakRock, Rgb::new(110, 120, 150))