From 273c5ed2f084acc7de077f6e79eb65c47ba90cac Mon Sep 17 00:00:00 2001 From: IsseW Date: Sun, 20 Feb 2022 18:23:37 +0100 Subject: [PATCH] Temporary noise solution --- Cargo.lock | 1 + assets/voxygen/shaders/clouds-frag.glsl | 4 +- .../shaders/include/cloud/regular.glsl | 68 ++++++++++++------- server/Cargo.toml | 1 + server/src/weather/sim.rs | 46 +++++++++++-- voxygen/src/render/pipelines/lod_terrain.rs | 6 +- world/examples/turb.rs | 30 +++++--- 7 files changed, 108 insertions(+), 48 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e3b3ec9978..52dfcad198 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6635,6 +6635,7 @@ dependencies = [ "humantime", "itertools", "lazy_static", + "noise", "num_cpus", "portpicker", "prometheus", diff --git a/assets/voxygen/shaders/clouds-frag.glsl b/assets/voxygen/shaders/clouds-frag.glsl index c6aada235d..69ca56e5c3 100644 --- a/assets/voxygen/shaders/clouds-frag.glsl +++ b/assets/voxygen/shaders/clouds-frag.glsl @@ -102,7 +102,7 @@ void main() { #ifdef EXPERIMENTAL_RAIN vec3 old_color = color.rgb; - float fall_rate = 20.0; + float fall_rate = 40.0; dir.xy += wind_vel * dir.z / fall_rate; dir = normalize(dir); @@ -126,7 +126,7 @@ void main() { } float drop_density = 3; - vec2 drop_size = vec2(0.0025, 0.17); + vec2 drop_size = vec2(0.0015, 0.17); vec2 rain_pos = (view_pos * rain_dist); rain_pos += vec2(0, tick.x * fall_rate + cam_wpos.z); diff --git a/assets/voxygen/shaders/include/cloud/regular.glsl b/assets/voxygen/shaders/include/cloud/regular.glsl index 9fb365fb23..0430878a42 100644 --- a/assets/voxygen/shaders/include/cloud/regular.glsl +++ b/assets/voxygen/shaders/include/cloud/regular.glsl @@ -61,13 +61,16 @@ vec4 cloud_at(vec3 pos, float dist, out vec3 emission, out float not_underground ; } + float cloud_alt = CLOUD_AVG_ALT + alt * 0.5; + //vec2 cloud_attr = get_cloud_heights(wind_pos.xy); float sun_access = 0.0; float moon_access = 0.0; - float cloud_sun_access = 0.0; + float cloud_sun_access = clamp((pos.z - cloud_alt) / 1500 + 0.5, 0, 1); float cloud_moon_access = 0.0; float cloud_broad_a = 0.0; float cloud_broad_b = 0.0; + // This is a silly optimisation but it actually nets us a fair few fps by skipping quite a few expensive calcs if ((pos.z < CLOUD_AVG_ALT + 15000.0 && cloud_tendency > 0.0)) { // Turbulence (small variations in clouds/mist) @@ -78,11 +81,10 @@ vec4 cloud_at(vec3 pos, float dist, out vec3 emission, out float not_underground const float CLOUD_DENSITY = 10000.0; const float CLOUD_ALT_VARI_WIDTH = 100000.0; const float CLOUD_ALT_VARI_SCALE = 5000.0; - float cloud_alt = CLOUD_AVG_ALT + alt * 0.5; cloud_broad_a = cloud_broad(wind_pos + sun_dir.xyz * 250); cloud_broad_b = cloud_broad(wind_pos - sun_dir.xyz * 250); - cloud = cloud_tendency + (0.0 + cloud = cloud_tendency + cloud_tendency * (0.0 + 24 * (cloud_broad_a + cloud_broad_b) * 0.5 #if (CLOUD_MODE >= CLOUD_MODE_MINIMAL) + 4 * (noise_3d((wind_pos + turb_offset) / 2000.0 / cloud_scale) - 0.5) @@ -93,24 +95,30 @@ vec4 cloud_at(vec3 pos, float dist, out vec3 emission, out float not_underground #if (CLOUD_MODE >= CLOUD_MODE_HIGH) + 0.75 * (noise_3d(wind_pos / 500.0 / cloud_scale) - 0.5) #endif - ) * 0.01; + ) * 0.1; cloud = pow(max(cloud, 0), 3) * sign(cloud); - cloud *= CLOUD_DENSITY * sqrt(cloud_tendency) * falloff(abs(pos.z - cloud_alt) / CLOUD_DEPTH); + cloud *= CLOUD_DENSITY * sqrt(cloud_tendency + 0.001) * falloff(abs(pos.z - cloud_alt) / CLOUD_DEPTH); // What proportion of sunlight is *not* being blocked by nearby cloud? (approximation) // Basically, just throw together a few values that roughly approximate this term and come up with an average - cloud_sun_access = exp(( + cloud_sun_access = mix(cloud_sun_access, exp(( // Cloud density gradient 0.25 * (cloud_broad_a - cloud_broad_b + (0.25 * (noise_3d(wind_pos / 4000 / cloud_scale) - 0.5) + 0.1 * (noise_3d(wind_pos / 1000 / cloud_scale) - 0.5))) #if (CLOUD_MODE >= CLOUD_MODE_HIGH) // More noise + 0.01 * (noise_3d(wind_pos / 500) / cloud_scale - 0.5) #endif - ) * 15.0 - 1.5) * 1.5; + ) * 15.0 - 1.5) * 1.5, min(cloud_tendency * 10, 1)); // Since we're assuming the sun/moon is always above (not always correct) it's the same for the moon cloud_moon_access = 1.0 - cloud_sun_access; } + #if (CLOUD_MODE >= CLOUD_MODE_LOW) + cloud += max(noise_3d((wind_pos) / 25000.0 / cloud_scale) - 0.75 + noise_3d((wind_pos) / 2500.0 / cloud_scale) * 0.1, 0) + * 0.1 + / (abs(pos.z - cloud_alt) / 500.0 + 0.1); + #endif + // Keeping this because it's something I'm likely to reenable later /* #if (CLOUD_MODE >= CLOUD_MODE_HIGH) @@ -238,10 +246,12 @@ vec3 get_cloud_color(vec3 surf_color, vec3 dir, vec3 origin, const float time_of float min_dist = clamp(max_dist / 4, 0.25, 24); int i; - // TODO: Make it a double rainbow - float rainbow_t = (0.7 - dot(sun_dir.xyz, dir)) * 8 / 0.05; - int rainbow_c = int(floor(rainbow_t)); - rainbow_t = fract(rainbow_t); + #if (CLOUD_MODE >= CLOUD_MODE_MEDIUM) + // TODO: Make it a double rainbow + float rainbow_t = (0.7 - dot(sun_dir.xyz, dir)) * 8 / 0.05; + int rainbow_c = int(floor(rainbow_t)); + rainbow_t = fract(rainbow_t); + #endif for (i = 0; cdist > min_dist && i < 250; i ++) { ldist = cdist; @@ -276,21 +286,27 @@ vec3 get_cloud_color(vec3 surf_color, vec3 dir, vec3 origin, const float time_of emission * density_integrals.y * step; // Rainbow - if (rainbow_c >= 0 && rainbow_c < 8) { - float rain = rain_density_at(pos.xy); - vec3 colors[9] = { - surf_color, - vec3(0.9, 0.5, 0.9), - vec3(0.25, 0.0, 0.5), - vec3(0.0, 0.0, 1.0), - vec3(0.0, 0.5, 0.0), - vec3(1.0, 1.0, 0.0), - vec3(1.0, 0.6, 0.0), - vec3(1.0, 0.0, 0.0), - surf_color, - }; - surf_color = mix(surf_color, mix(colors[rainbow_c], colors[rainbow_c + 1], rainbow_t), rain * sun_access * sun_access * get_sun_brightness() * pow(min(cdist / 500.0, 1.0), 2.0)); - } + #if (CLOUD_MODE >= CLOUD_MODE_MEDIUM) + if (rainbow_c >= 0 && rainbow_c < 8) { + float rain = rain_density_at(pos.xy); + vec3 colors[9] = { + surf_color, + vec3(0.9, 0.5, 0.9), + vec3(0.25, 0.0, 0.5), + vec3(0.0, 0.0, 1.0), + vec3(0.0, 0.5, 0.0), + vec3(1.0, 1.0, 0.0), + vec3(1.0, 0.6, 0.0), + vec3(1.0, 0.0, 0.0), + surf_color, + }; + surf_color = mix( + surf_color, + mix(colors[rainbow_c], colors[rainbow_c + 1], rainbow_t), + rain * sun_access * sun_access * get_sun_brightness() * pow(min(cdist / 500.0, 1.0), 2.0), + ); + } + #endif } #ifdef IS_POSTPROCESS } diff --git a/server/Cargo.toml b/server/Cargo.toml index 0ccd17c0aa..b24acdf414 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -58,6 +58,7 @@ authc = { git = "https://gitlab.com/veloren/auth.git", rev = "fb3dcbc4962b367253 slab = "0.4" rand_distr = "0.4.0" enumset = "1.0.8" +noise = { version = "0.7", default-features = false } rusqlite = { version = "0.24.2", features = ["array", "vtab", "bundled", "trace"] } refinery = { git = "https://gitlab.com/veloren/refinery.git", rev = "8ecf4b4772d791e6c8c0a3f9b66a7530fad1af3e", features = ["rusqlite"] } diff --git a/server/src/weather/sim.rs b/server/src/weather/sim.rs index 2fa6951149..8c916371f6 100644 --- a/server/src/weather/sim.rs +++ b/server/src/weather/sim.rs @@ -6,6 +6,7 @@ use common::{ weather::{Weather, CHUNKS_PER_CELL}, }; use itertools::Itertools; +use noise::{NoiseFn, SuperSimplex, Turbulence}; use vek::*; use world::World; @@ -46,10 +47,13 @@ pub struct WeatherSim { info: Grid, } -const WATER_BOILING_POINT: f32 = 2.5; +/* const MAX_WIND_SPEED: f32 = 128.0; -pub(crate) const CELL_SIZE: f32 = (CHUNKS_PER_CELL * TerrainChunkSize::RECT_SIZE.x) as f32; -pub(crate) const DT: f32 = CELL_SIZE / MAX_WIND_SPEED; +*/ +pub(crate) const CELL_SIZE: u32 = CHUNKS_PER_CELL * TerrainChunkSize::RECT_SIZE.x; + +/// How often the weather is updated, in seconds +pub(crate) const DT: f32 = 5.0; // CELL_SIZE as f32 / MAX_WIND_SPEED; fn sample_plane_normal(points: &[Vec3]) -> Option> { if points.len() < 3 { @@ -88,6 +92,8 @@ fn sample_plane_normal(points: &[Vec3]) -> Option> { } } +fn cell_to_wpos(p: Vec2) -> Vec2 { p * CELL_SIZE as i32 } + impl WeatherSim { pub fn new(size: Vec2, world: &World) -> Self { let size = size.as_(); @@ -146,14 +152,44 @@ impl WeatherSim { pub fn get_weather(&self) -> &Grid { &self.weather } + /* fn get_cell(&self, p: Vec2, time: f64) -> Cell { *self.cells.get(p).unwrap_or(&sample_cell(p, time)) } + */ // https://minds.wisconsin.edu/bitstream/handle/1793/66950/LitzauSpr2013.pdf // Time step is cell size / maximum wind speed pub fn tick(&mut self, time_of_day: &TimeOfDay) { let time = time_of_day.0; + + let base_nz = Turbulence::new( + Turbulence::new(SuperSimplex::new()) + .set_frequency(0.2) + .set_power(1.5), + ) + .set_frequency(2.0) + .set_power(0.2); + + let rain_nz = SuperSimplex::new(); + + for (point, cell) in self.weather.iter_mut() { + let wpos = cell_to_wpos(point); + + let space_scale = 7500.0; + let time_scale = 25000.0; + let spos = (wpos.as_::() / space_scale).with_z(time as f64 / time_scale); + + let pressure = (base_nz.get(spos.into_array()) * 0.5 + 1.0).clamped(0.0, 1.0) as f32; + + cell.cloud = 1.0 - pressure; + cell.rain = (1.0 - pressure - 0.2).max(0.0).powf(1.5); + cell.wind = Vec2::new( + rain_nz.get(spos.into_array()) as f32, + rain_nz.get((spos + 1.0).into_array()) as f32, + ) * 250.0 * (1.0 - pressure); + } + /* let mut swap = Grid::new(self.cells.size(), Cell::default()); // Dissipate wind, humidty and pressure // Dissipation is represented by the target cell expanding into the 8 adjacent @@ -349,8 +385,6 @@ impl WeatherSim { * (self.weather[point].rain * 0.9 + 0.1) * temp_part; } - - // Maybe moisture condenses to clouds, which if they have a certain - // amount they will release rain. + */ } } diff --git a/voxygen/src/render/pipelines/lod_terrain.rs b/voxygen/src/render/pipelines/lod_terrain.rs index 7d53baa89a..437ea73f11 100644 --- a/voxygen/src/render/pipelines/lod_terrain.rs +++ b/voxygen/src/render/pipelines/lod_terrain.rs @@ -152,9 +152,9 @@ impl LodData { let sampler_info = wgpu::SamplerDescriptor { label: None, - address_mode_u: wgpu::AddressMode::ClampToEdge, - address_mode_v: wgpu::AddressMode::ClampToEdge, - address_mode_w: wgpu::AddressMode::ClampToEdge, + address_mode_u: wgpu::AddressMode::ClampToBorder, + address_mode_v: wgpu::AddressMode::ClampToBorder, + address_mode_w: wgpu::AddressMode::ClampToBorder, mag_filter: wgpu::FilterMode::Linear, min_filter: wgpu::FilterMode::Linear, mipmap_filter: wgpu::FilterMode::Nearest, diff --git a/world/examples/turb.rs b/world/examples/turb.rs index 1eae349bc9..fe3d8924c5 100644 --- a/world/examples/turb.rs +++ b/world/examples/turb.rs @@ -1,4 +1,4 @@ -use noise::{Seedable, SuperSimplex}; +use noise::{NoiseFn, Seedable, SuperSimplex, Turbulence}; use vek::*; @@ -8,32 +8,40 @@ const H: usize = 640; fn main() { let mut win = minifb::Window::new("Turb", W, H, minifb::WindowOptions::default()).unwrap(); + let nz = Turbulence::new( + Turbulence::new(SuperSimplex::new()) + .set_frequency(0.2) + .set_power(1.5), + ) + .set_frequency(2.0) + .set_power(0.2); + let _nz_x = SuperSimplex::new().set_seed(0); let _nz_y = SuperSimplex::new().set_seed(1); let mut _time = 0.0f64; + let mut scale = 50.0; + while win.is_open() { let mut buf = vec![0; W * H]; for i in 0..W { for j in 0..H { - let pos = Vec2::new(i as f64 / W as f64, j as f64 / H as f64) * 0.5 - 0.25; + let pos = Vec2::new(i as f64, j as f64) / scale; - let pos = pos * 10.0; - - let pos = (0..10).fold(pos, |pos, _| pos.map(|e| e.powi(3) - 1.0)); - - let val = if pos.map(|e| e.abs() < 0.5).reduce_and() { - 1.0f32 - } else { - 0.0 - }; + let val = nz.get(pos.into_array()); buf[j * W + i] = u32::from_le_bytes([(val.max(0.0).min(1.0) * 255.0) as u8; 4]); } } + if win.is_key_pressed(minifb::Key::Right, minifb::KeyRepeat::No) { + scale *= 1.5; + } else if win.is_key_pressed(minifb::Key::Left, minifb::KeyRepeat::No) { + scale /= 1.5; + } + win.update_with_buffer(&buf, W, H).unwrap(); _time += 1.0 / 60.0;