Temporary noise solution

This commit is contained in:
IsseW 2022-02-20 18:23:37 +01:00
parent 67683f315f
commit 273c5ed2f0
7 changed files with 108 additions and 48 deletions

1
Cargo.lock generated
View File

@ -6635,6 +6635,7 @@ dependencies = [
"humantime", "humantime",
"itertools", "itertools",
"lazy_static", "lazy_static",
"noise",
"num_cpus", "num_cpus",
"portpicker", "portpicker",
"prometheus", "prometheus",

View File

@ -102,7 +102,7 @@ void main() {
#ifdef EXPERIMENTAL_RAIN #ifdef EXPERIMENTAL_RAIN
vec3 old_color = color.rgb; vec3 old_color = color.rgb;
float fall_rate = 20.0; float fall_rate = 40.0;
dir.xy += wind_vel * dir.z / fall_rate; dir.xy += wind_vel * dir.z / fall_rate;
dir = normalize(dir); dir = normalize(dir);
@ -126,7 +126,7 @@ void main() {
} }
float drop_density = 3; 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); vec2 rain_pos = (view_pos * rain_dist);
rain_pos += vec2(0, tick.x * fall_rate + cam_wpos.z); rain_pos += vec2(0, tick.x * fall_rate + cam_wpos.z);

View File

@ -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); //vec2 cloud_attr = get_cloud_heights(wind_pos.xy);
float sun_access = 0.0; float sun_access = 0.0;
float moon_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_moon_access = 0.0;
float cloud_broad_a = 0.0; float cloud_broad_a = 0.0;
float cloud_broad_b = 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 // 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)) { if ((pos.z < CLOUD_AVG_ALT + 15000.0 && cloud_tendency > 0.0)) {
// Turbulence (small variations in clouds/mist) // 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_DENSITY = 10000.0;
const float CLOUD_ALT_VARI_WIDTH = 100000.0; const float CLOUD_ALT_VARI_WIDTH = 100000.0;
const float CLOUD_ALT_VARI_SCALE = 5000.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_a = cloud_broad(wind_pos + sun_dir.xyz * 250);
cloud_broad_b = 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 + 24 * (cloud_broad_a + cloud_broad_b) * 0.5
#if (CLOUD_MODE >= CLOUD_MODE_MINIMAL) #if (CLOUD_MODE >= CLOUD_MODE_MINIMAL)
+ 4 * (noise_3d((wind_pos + turb_offset) / 2000.0 / cloud_scale) - 0.5) + 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) #if (CLOUD_MODE >= CLOUD_MODE_HIGH)
+ 0.75 * (noise_3d(wind_pos / 500.0 / cloud_scale) - 0.5) + 0.75 * (noise_3d(wind_pos / 500.0 / cloud_scale) - 0.5)
#endif #endif
) * 0.01; ) * 0.1;
cloud = pow(max(cloud, 0), 3) * sign(cloud); 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) // 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 // 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 // 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))) 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) #if (CLOUD_MODE >= CLOUD_MODE_HIGH)
// More noise // More noise
+ 0.01 * (noise_3d(wind_pos / 500) / cloud_scale - 0.5) + 0.01 * (noise_3d(wind_pos / 500) / cloud_scale - 0.5)
#endif #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 // 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; 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 // Keeping this because it's something I'm likely to reenable later
/* /*
#if (CLOUD_MODE >= CLOUD_MODE_HIGH) #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); float min_dist = clamp(max_dist / 4, 0.25, 24);
int i; int i;
// TODO: Make it a double rainbow #if (CLOUD_MODE >= CLOUD_MODE_MEDIUM)
float rainbow_t = (0.7 - dot(sun_dir.xyz, dir)) * 8 / 0.05; // TODO: Make it a double rainbow
int rainbow_c = int(floor(rainbow_t)); float rainbow_t = (0.7 - dot(sun_dir.xyz, dir)) * 8 / 0.05;
rainbow_t = fract(rainbow_t); int rainbow_c = int(floor(rainbow_t));
rainbow_t = fract(rainbow_t);
#endif
for (i = 0; cdist > min_dist && i < 250; i ++) { for (i = 0; cdist > min_dist && i < 250; i ++) {
ldist = cdist; 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; emission * density_integrals.y * step;
// Rainbow // Rainbow
if (rainbow_c >= 0 && rainbow_c < 8) { #if (CLOUD_MODE >= CLOUD_MODE_MEDIUM)
float rain = rain_density_at(pos.xy); if (rainbow_c >= 0 && rainbow_c < 8) {
vec3 colors[9] = { float rain = rain_density_at(pos.xy);
surf_color, vec3 colors[9] = {
vec3(0.9, 0.5, 0.9), surf_color,
vec3(0.25, 0.0, 0.5), vec3(0.9, 0.5, 0.9),
vec3(0.0, 0.0, 1.0), vec3(0.25, 0.0, 0.5),
vec3(0.0, 0.5, 0.0), vec3(0.0, 0.0, 1.0),
vec3(1.0, 1.0, 0.0), vec3(0.0, 0.5, 0.0),
vec3(1.0, 0.6, 0.0), vec3(1.0, 1.0, 0.0),
vec3(1.0, 0.0, 0.0), vec3(1.0, 0.6, 0.0),
surf_color, 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)); };
} 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 #ifdef IS_POSTPROCESS
} }

View File

@ -58,6 +58,7 @@ authc = { git = "https://gitlab.com/veloren/auth.git", rev = "fb3dcbc4962b367253
slab = "0.4" slab = "0.4"
rand_distr = "0.4.0" rand_distr = "0.4.0"
enumset = "1.0.8" enumset = "1.0.8"
noise = { version = "0.7", default-features = false }
rusqlite = { version = "0.24.2", features = ["array", "vtab", "bundled", "trace"] } rusqlite = { version = "0.24.2", features = ["array", "vtab", "bundled", "trace"] }
refinery = { git = "https://gitlab.com/veloren/refinery.git", rev = "8ecf4b4772d791e6c8c0a3f9b66a7530fad1af3e", features = ["rusqlite"] } refinery = { git = "https://gitlab.com/veloren/refinery.git", rev = "8ecf4b4772d791e6c8c0a3f9b66a7530fad1af3e", features = ["rusqlite"] }

View File

@ -6,6 +6,7 @@ use common::{
weather::{Weather, CHUNKS_PER_CELL}, weather::{Weather, CHUNKS_PER_CELL},
}; };
use itertools::Itertools; use itertools::Itertools;
use noise::{NoiseFn, SuperSimplex, Turbulence};
use vek::*; use vek::*;
use world::World; use world::World;
@ -46,10 +47,13 @@ pub struct WeatherSim {
info: Grid<WeatherInfo>, info: Grid<WeatherInfo>,
} }
const WATER_BOILING_POINT: f32 = 2.5; /*
const MAX_WIND_SPEED: f32 = 128.0; 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<f32>]) -> Option<Vec3<f32>> { fn sample_plane_normal(points: &[Vec3<f32>]) -> Option<Vec3<f32>> {
if points.len() < 3 { if points.len() < 3 {
@ -88,6 +92,8 @@ fn sample_plane_normal(points: &[Vec3<f32>]) -> Option<Vec3<f32>> {
} }
} }
fn cell_to_wpos(p: Vec2<i32>) -> Vec2<i32> { p * CELL_SIZE as i32 }
impl WeatherSim { impl WeatherSim {
pub fn new(size: Vec2<u32>, world: &World) -> Self { pub fn new(size: Vec2<u32>, world: &World) -> Self {
let size = size.as_(); let size = size.as_();
@ -146,14 +152,44 @@ impl WeatherSim {
pub fn get_weather(&self) -> &Grid<Weather> { &self.weather } pub fn get_weather(&self) -> &Grid<Weather> { &self.weather }
/*
fn get_cell(&self, p: Vec2<i32>, time: f64) -> Cell { fn get_cell(&self, p: Vec2<i32>, time: f64) -> Cell {
*self.cells.get(p).unwrap_or(&sample_cell(p, time)) *self.cells.get(p).unwrap_or(&sample_cell(p, time))
} }
*/
// https://minds.wisconsin.edu/bitstream/handle/1793/66950/LitzauSpr2013.pdf // https://minds.wisconsin.edu/bitstream/handle/1793/66950/LitzauSpr2013.pdf
// Time step is cell size / maximum wind speed // Time step is cell size / maximum wind speed
pub fn tick(&mut self, time_of_day: &TimeOfDay) { pub fn tick(&mut self, time_of_day: &TimeOfDay) {
let time = time_of_day.0; 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_::<f64>() / 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()); let mut swap = Grid::new(self.cells.size(), Cell::default());
// Dissipate wind, humidty and pressure // Dissipate wind, humidty and pressure
// Dissipation is represented by the target cell expanding into the 8 adjacent // 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) * (self.weather[point].rain * 0.9 + 0.1)
* temp_part; * temp_part;
} }
*/
// Maybe moisture condenses to clouds, which if they have a certain
// amount they will release rain.
} }
} }

View File

@ -152,9 +152,9 @@ impl LodData {
let sampler_info = wgpu::SamplerDescriptor { let sampler_info = wgpu::SamplerDescriptor {
label: None, label: None,
address_mode_u: wgpu::AddressMode::ClampToEdge, address_mode_u: wgpu::AddressMode::ClampToBorder,
address_mode_v: wgpu::AddressMode::ClampToEdge, address_mode_v: wgpu::AddressMode::ClampToBorder,
address_mode_w: wgpu::AddressMode::ClampToEdge, address_mode_w: wgpu::AddressMode::ClampToBorder,
mag_filter: wgpu::FilterMode::Linear, mag_filter: wgpu::FilterMode::Linear,
min_filter: wgpu::FilterMode::Linear, min_filter: wgpu::FilterMode::Linear,
mipmap_filter: wgpu::FilterMode::Nearest, mipmap_filter: wgpu::FilterMode::Nearest,

View File

@ -1,4 +1,4 @@
use noise::{Seedable, SuperSimplex}; use noise::{NoiseFn, Seedable, SuperSimplex, Turbulence};
use vek::*; use vek::*;
@ -8,32 +8,40 @@ const H: usize = 640;
fn main() { fn main() {
let mut win = minifb::Window::new("Turb", W, H, minifb::WindowOptions::default()).unwrap(); 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_x = SuperSimplex::new().set_seed(0);
let _nz_y = SuperSimplex::new().set_seed(1); let _nz_y = SuperSimplex::new().set_seed(1);
let mut _time = 0.0f64; let mut _time = 0.0f64;
let mut scale = 50.0;
while win.is_open() { while win.is_open() {
let mut buf = vec![0; W * H]; let mut buf = vec![0; W * H];
for i in 0..W { for i in 0..W {
for j in 0..H { 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 val = nz.get(pos.into_array());
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
};
buf[j * W + i] = u32::from_le_bytes([(val.max(0.0).min(1.0) * 255.0) as u8; 4]); 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(); win.update_with_buffer(&buf, W, H).unwrap();
_time += 1.0 / 60.0; _time += 1.0 / 60.0;