More accurate weather sim

This commit is contained in:
IsseW 2022-02-20 17:04:58 +01:00
parent 6585ef1513
commit 78c1de19cf
14 changed files with 294 additions and 173 deletions

View File

@ -19,6 +19,7 @@ layout(std140, set = 0, binding = 0) uniform u_globals {
uvec4 medium;
ivec4 select_pos;
vec4 gamma_exposure;
vec2 wind_vel;
float ambiance;
// 0 - FirstPerson
// 1 - ThirdPerson
@ -37,6 +38,4 @@ mat4 threshold_matrix = mat4(
float distance_divider = 2;
float shadow_dithering = 0.5;
vec2 wind_vel = vec2(0.0);
#endif

View File

@ -5,8 +5,6 @@
#include <sky.glsl>
#include <srgb.glsl>
layout(set = 0, binding = 5) uniform texture2D t_alt;
layout(set = 0, binding = 6) uniform sampler s_alt;
layout(set = 0, binding = 7) uniform texture2D t_horizon;
layout(set = 0, binding = 8) uniform sampler s_horizon;

View File

@ -97,6 +97,9 @@ vec2 wind_offset = vec2(time_of_day.x * wind_speed);
float cloud_scale = view_distance.z / 150.0;
layout(set = 0, binding = 5) uniform texture2D t_alt;
layout(set = 0, binding = 6) uniform sampler s_alt;
vec2 pos_to_uv(texture2D tex, sampler s, vec2 pos) {
// Want: (pixel + 0.5) / W
vec2 texSize = textureSize(sampler2D(tex, s), 0);
@ -105,19 +108,22 @@ vec2 pos_to_uv(texture2D tex, sampler s, vec2 pos) {
}
// Weather texture
layout(set = 0, binding = 12) uniform texture2D t_clouds;
layout(set = 0, binding = 13) uniform sampler s_clouds;
layout(set = 0, binding = 12) uniform texture2D t_weather;
layout(set = 0, binding = 13) uniform sampler s_weather;
vec4 sample_weather(vec2 wpos) {
return textureLod(sampler2D(t_weather, s_weather), pos_to_uv(t_alt, s_alt, wpos - focus_off.xy), 0); // TODO: make this work for any world size
}
float cloud_tendency_at(vec2 pos) {
float nz = textureLod/*textureBicubic16*/(sampler2D(t_clouds, s_clouds), pos / 33500 , 0).r;
//float nz = textureLod(sampler2D(t_noise, s_noise), (pos + wind_offset) / 60000.0 / cloud_scale, 0).x - 0.3;
nz = pow(nz, 3);
return nz;
return sample_weather(pos).r;
}
const float RAIN_CLOUD = 0.05;
float rain_density_at(vec2 pos) {
return clamp((cloud_tendency_at(pos) - RAIN_CLOUD) * 10, 0, 1);
return sample_weather(pos).g;
//return clamp((cloud_tendency_at(pos) - RAIN_CLOUD) * 10, 0, 1);
}
float cloud_shadow(vec3 pos, vec3 light_dir) {

View File

@ -92,6 +92,7 @@ void main() {
#endif
#ifndef EXPERIMENTAL_BAREMINIMUM
// TODO: take wind_vel into account
// Wind sway effect
f_pos += model_wind_sway * vec3(
sin(tick.x * 1.5 + f_pos.y * 0.1) * sin(tick.x * 0.35),

View File

@ -1430,6 +1430,12 @@ impl Client {
}
}
pub fn current_weather_wpos(&self, wpos: Vec2<f32>) -> Weather {
let cell_pos =
(wpos / ((TerrainChunkSize::RECT_SIZE * weather::CHUNKS_PER_CELL).as_())).as_();
*self.weather.get(cell_pos).unwrap_or(&Weather::default())
}
pub fn current_chunk(&self) -> Option<Arc<TerrainChunk>> {
let chunk_pos = Vec2::from(self.position()?)
.map2(TerrainChunkSize::RECT_SIZE, |e: f32, sz| {

View File

@ -1,3 +1,5 @@
use std::fmt;
use serde::{Deserialize, Serialize};
use vek::Vec2;
@ -5,8 +7,11 @@ pub const CHUNKS_PER_CELL: u32 = 16;
// Weather::default is Clear, 0 degrees C and no wind
#[derive(Debug, Clone, Copy, Serialize, Deserialize, Default)]
pub struct Weather {
/// Clouds currently in the area between 0 and 1
pub cloud: f32,
/// Rain per time, between 0 and 1
pub rain: f32,
// Wind direction in block / second
pub wind: Vec2<f32>,
}
@ -35,3 +40,14 @@ pub enum WeatherKind {
Rain,
Storm,
}
impl fmt::Display for WeatherKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
WeatherKind::Clear => write!(f, "Clear"),
WeatherKind::Cloudy => write!(f, "Cloudy"),
WeatherKind::Rain => write!(f, "Rain"),
WeatherKind::Storm => write!(f, "Storm"),
}
}
}

View File

@ -24,11 +24,11 @@ pub fn init(state: &mut State, world: &world::World) {
state
.ecs_mut()
.insert(SysScheduler::<tick::Sys>::every(Duration::from_secs_f32(
0.1,
sim::DT / 100.0,
)));
state
.ecs_mut()
.insert(SysScheduler::<sync::Sys>::every(Duration::from_secs_f32(
0.1,
sim::DT / 100.0,
)));
}

View File

@ -1,12 +1,8 @@
use std::{
ops::{Add, Deref, DerefMut, Div, Mul},
sync::Arc,
};
use common::{
grid::Grid,
resources::TimeOfDay,
terrain::{BiomeKind, TerrainChunkSize},
time::DayPeriod,
vol::RectVolSize,
weather::{Weather, CHUNKS_PER_CELL},
};
@ -19,10 +15,10 @@ use world::{
#[derive(Default)]
pub struct Constants {
drag: f32, // How much drag therfe is on wind. Caused by slopes.
humidity: Option<f32>,
temperature_day: Option<f32>,
temperature_night: Option<f32>,
altitude: f32,
water: f32,
temperature_day: f32,
temperature_night: f32,
}
#[derive(Clone, Copy, Default)]
@ -30,83 +26,173 @@ struct Cell {
wind: Vec2<f32>,
temperature: f32,
moisture: f32,
rain: f32,
cloud: f32,
}
/// Used to sample weather that isn't simulated
fn sample_cell(p: Vec2<i32>, time: f64) -> Cell {
let noise = FastNoise::new(0b10110_101_1100_1111_10010_101_1110);
/*let noise = FastNoise::new(0b10110_101_1100_1111_10010_101_1110);
// Feeding sensible values into the simulation
Cell {
wind: Vec2::new(noise.get(p.with_z(0).as_()), noise.get(p.with_z(100).as_()))
* ((noise.get(p.with_z(200).as_()) + 1.0) * 0.5).powf(4.0)
* 30.0,
temperature: noise.get(p.with_z(300).as_()).powf(3.0) * 10.0 + 20.0, // 10 -> 30
moisture: BASE_HUMIDITY,
rain: ((noise.get(p.with_z(400).as_()) + 1.0) * 0.5).powf(4.0) * MAX_RAIN,
wind: Vec2::new(
noise.get(p.as_().with_z(time / 1000.0)),
noise.get(p.as_().with_z(-time / 1000.0)),
) * ((noise.get(p.as_().with_z(time / 1000.0 + 200.0)) + 1.0) * 0.5).powf(2.0)
* 30.0
+ 5.0,
temperature: noise.get(p.as_().with_z(time / 1000.0 + 300.0)).powf(3.0) * 10.0
+ BASE_TEMPERATURE
+ 273.3, /* 10 -> 30 C */
moisture: BASE_MOISTURE + noise.get(p.as_().with_z(time / 100.0 + 400.0)).powf(3.0) * 0.2,
cloud: noise
.get((p.as_() / 2.0).with_z(time / 100.0 + 400.0))
.powf(2.0)
* 1.0,
} */
Cell {
wind: Vec2::new(10.0, 0.0),
temperature: 20.0,
moisture: 0.0,
cloud: 0.0,
}
}
pub struct WeatherSim {
cells: Grid<Cell>,
constants: Grid<Constants>,
weather: Grid<Weather>, // The current weather.
cells: Grid<Cell>, // The variables used for simulation
constants: Grid<Constants>, // The constants from the world used for simulation
weather: Grid<Weather>, // The current weather.
}
const BASE_HUMIDITY: f32 = 1.6652;
const BASE_MOISTURE: f32 = 1.0;
const BASE_TEMPERATURE: f32 = 20.0;
const MAX_RAIN: f32 = 100.0;
const WATER_BOILING_POINT: f32 = 373.3;
const MAX_WIND_SPEED: f32 = 60.0;
const CELL_SIZE: f32 = (CHUNKS_PER_CELL * TerrainChunkSize::RECT_SIZE.x) as f32;
pub(crate) const DT: f32 = CELL_SIZE / MAX_WIND_SPEED;
impl WeatherSim {
pub fn new(size: Vec2<u32>, world: &World) -> Self {
let size = size.as_();
Self {
let mut this = Self {
cells: Grid::new(size, Cell::default()),
constants: Grid::from_raw(
size,
(0..size.x * size.y)
.map(|i| Vec2::new(i as i32 % size.x, i as i32 / size.x))
.map(|p| {
let mut c = Constants::default();
let add = |member: &mut f32, v| {
*member += v;
*member /= 2.0;
};
let mut temperature_night_r = 0.0;
let mut temperature_night = |v| {
add(&mut temperature_night_r, v);
};
let mut temperature_day_r = 0.0;
let mut temperature_day = |v| {
add(&mut temperature_day_r, v);
};
let mut altitude_r = 0.0;
let mut altitude = |v| {
add(&mut altitude_r, v);
};
let mut water_r = 0.0;
for y in 0..CHUNKS_PER_CELL as i32 {
for x in 0..CHUNKS_PER_CELL as i32 {
let chunk_pos = p * CHUNKS_PER_CELL as i32 + Vec2::new(x, y);
if let Some(chunk) = world.sim().get(chunk_pos) {
c.drag +=
let a =
world.sim().get_gradient_approx(chunk_pos).unwrap_or(0.0);
if chunk.is_underwater() {
c.humidity =
Some(c.humidity.unwrap_or(0.0) + BASE_HUMIDITY);
c.temperature_night =
Some(c.temperature_night.unwrap_or(0.0) + 0.01);
} else {
c.temperature_day =
Some(c.temperature_day.unwrap_or(0.0) + 0.01);
}
altitude(a);
let height_p = 1.0
- world.sim().get_alt_approx(chunk_pos).unwrap_or(0.0)
/ world.sim().max_height;
let mut water = |v| {
add(&mut water_r, v * height_p);
};
match chunk.get_biome() {
BiomeKind::Desert => {
c.temperature_day =
Some(c.temperature_day.unwrap_or(0.0) + 0.01);
c.humidity = Some(
c.humidity.unwrap_or(0.0) - 10.0 * BASE_HUMIDITY,
);
water(0.0);
temperature_night(11.0);
temperature_day(30.0);
},
BiomeKind::Savannah => {
water(0.02);
temperature_night(13.0);
temperature_day(26.0);
},
BiomeKind::Swamp => {
c.humidity = Some(
c.humidity.unwrap_or(0.0) + 2.0 * BASE_HUMIDITY,
);
water(0.8);
temperature_night(16.0);
temperature_day(24.0);
},
BiomeKind::Mountain => {
water(0.01);
temperature_night(13.0);
temperature_day(14.0);
},
BiomeKind::Grassland => {
water(0.05);
temperature_night(15.0);
temperature_day(20.0);
},
BiomeKind::Snowland => {
water(0.005);
temperature_night(-8.0);
temperature_day(-1.0);
},
BiomeKind::Jungle => {
water(0.4);
temperature_night(20.0);
temperature_day(27.0);
},
BiomeKind::Forest => {
water(0.1);
temperature_night(16.0);
temperature_day(19.0);
},
BiomeKind::Taiga => {
water(0.02);
temperature_night(1.0);
temperature_day(10.0);
},
BiomeKind::Lake => {
water(1.0);
temperature_night(20.0);
temperature_day(18.0);
},
BiomeKind::Ocean => {
water(0.98);
temperature_night(19.0);
temperature_day(17.0);
},
BiomeKind::Void => {
water(0.0);
temperature_night(20.0);
temperature_day(20.0);
},
_ => {},
}
}
}
}
c
Constants {
altitude: altitude_r,
water: water_r,
temperature_day: temperature_day_r,
temperature_night: temperature_day_r,
}
})
.collect_vec(),
),
weather: Grid::new(size, Weather::default()),
}
};
this.cells.iter_mut().for_each(|(point, cell)| {
let time = 0.0;
*cell = sample_cell(point, time);
});
this
}
pub fn get_weather(&self) -> &Grid<Weather> { &self.weather }
@ -121,61 +207,67 @@ impl WeatherSim {
// https://minds.wisconsin.edu/bitstream/handle/1793/66950/LitzauSpr2013.pdf
// Time step is cell size / maximum wind speed
pub fn tick(&mut self, world: &World, time_of_day: &TimeOfDay, dt: f32) {
const MAX_WIND_SPEED: f32 = 127.0;
let cell_size: Vec2<f32> = (CHUNKS_PER_CELL * TerrainChunkSize::RECT_SIZE).as_();
let dt = cell_size.x / MAX_WIND_SPEED;
pub fn tick(&mut self, time_of_day: &TimeOfDay, dt: f32) {
let time = time_of_day.0;
let mut swap = Grid::new(self.cells.size(), Cell::default());
// Dissipate wind, humidty and pressure
//Dispersion is represented by the target cell expanding into the 8 adjacent
// Dissipation is represented by the target cell expanding into the 8 adjacent
// cells. The target cells contents are then distributed based the
// percentage that overlaps the surrounding cell.
for (point, cell) in self.cells.iter() {
swap[point] = {
let spread = [
(*cell, 1. / 4.),
(
self.get_cell(point + Vec2::new(1, 0), time_of_day.0),
1. / 8.,
),
(
self.get_cell(point + Vec2::new(-1, 0), time_of_day.0),
1. / 8.,
),
(
self.get_cell(point + Vec2::new(0, 1), time_of_day.0),
1. / 8.,
),
(
self.get_cell(point + Vec2::new(0, -1), time_of_day.0),
1. / 8.,
),
(*cell, 0),
(self.get_cell(point + Vec2::new(1, 0), time), 1),
(self.get_cell(point + Vec2::new(-1, 0), time), 1),
(self.get_cell(point + Vec2::new(0, 1), time), 1),
(self.get_cell(point + Vec2::new(0, -1), time), 1),
// Diagonal so less overlap
(
self.get_cell(point + Vec2::new(1, 1), time_of_day.0),
1. / 16.,
),
(
self.get_cell(point + Vec2::new(1, -1), time_of_day.0),
1. / 16.,
),
(
self.get_cell(point + Vec2::new(-1, 1), time_of_day.0),
1. / 16.,
),
(
self.get_cell(point + Vec2::new(-1, -1), time_of_day.0),
1. / 16.,
),
(self.get_cell(point + Vec2::new(1, 1), time), 2),
(self.get_cell(point + Vec2::new(1, -1), time), 2),
(self.get_cell(point + Vec2::new(-1, 1), time), 2),
(self.get_cell(point + Vec2::new(-1, -1), time), 2),
];
let mut cell = Cell::default();
for (c, factor) in spread {
cell.wind += c.wind * factor;
cell.temperature += c.temperature * factor;
cell.moisture += c.moisture * factor;
}
for (c, p) in spread {
let factor = |rate: f32| {
let rate = (1.0 + rate).powf(DT);
// 1.0
// ___________________
// / \
// +---+-------------------+---+
// | 2 | 1 | 2 |
// +---+-------------------+---+
// | | | |
// | | | |
// | | | |
// | 1 | 0 | 1 |
// | | | |
// | | | |
// | | | |
// +---+-------------------+---+ \
// | 2 | 1 | 2 | | rate
// +---+-------------------+---+ /
// \___________________________/
// 2.0 * rate + 1.0
// area_0 = 1.0 * 1.0
// area_1 = rate * 1.0
// area_2 = rate * rate
let area = (1.0 + 2.0 * rate).powf(2.0);
match p {
0 => 1.0 * 1.0 / area, // area_0 / area
1 => rate * 1.0 / area, // area_1 / area
_ => rate * rate / area, // area_2/ area
}
};
// 0.0 <= dissipation rate <= 1.0 because we only spread to direct neighbours.
cell.wind += c.wind * factor(0.0055);
cell.temperature += c.temperature * factor(0.007);
cell.moisture += c.moisture * factor(0.003);
cell.cloud += c.cloud * factor(0.001);
}
cell
}
}
@ -194,23 +286,23 @@ impl WeatherSim {
for y in -1..=self.cells.size().y {
for x in -1..=self.cells.size().x {
let point = Vec2::new(x, y);
let cell = self.get_cell(point, time_of_day.0);
let a = cell_size.x - cell.wind.x.abs();
let b = cell_size.y - cell.wind.y.abs();
let cell = self.get_cell(point, time);
let a = CELL_SIZE - cell.wind.x.abs() * DT;
let b = CELL_SIZE - cell.wind.y.abs() * DT;
let wind_dir = Vec2::new(cell.wind.x.signum(), cell.wind.y.signum()).as_();
let spread = [
(point, a * b / (cell_size.x * cell_size.y)),
(point, a * b / (CELL_SIZE * CELL_SIZE)),
(
point + wind_dir.with_y(0),
(cell_size.x - a) * b / (cell_size.x * cell_size.y),
(CELL_SIZE - a) * b / (CELL_SIZE * CELL_SIZE),
),
(
point + wind_dir.with_x(0),
a * (cell_size.y - b) / (cell_size.x * cell_size.y),
a * (CELL_SIZE - b) / (CELL_SIZE * CELL_SIZE),
),
(
point + wind_dir,
(cell_size.x - a) * (cell_size.y - b) / (cell_size.x * cell_size.y),
(CELL_SIZE - a) * (CELL_SIZE - b) / (CELL_SIZE * CELL_SIZE),
),
];
for (p, factor) in spread {
@ -218,79 +310,58 @@ impl WeatherSim {
c.wind += cell.wind * factor;
c.temperature += cell.temperature * factor;
c.moisture += cell.moisture * factor;
c.rain += cell.rain * factor;
c.cloud += cell.cloud * factor;
}
}
}
}
self.cells = swap.clone();
// TODO: wind curl, rain condesnsing from moisture. And interacting with world
// elements.
// TODO: wind curl
// Evaporate moisture and condense clouds
for (point, cell) in self.cells.iter_mut() {
// r = rain, m = moisture
// ∆r = Rcond Rrain.
// ∆m = Rcond + V.
// Rcond = δ(T0(m) T)H(T0(m) T) γ(T T0(m))H(T T0(m)).
// T0(m) = (100m) / 5
let dt = 1.0 - 0.96f32.powf(DT);
let day_light = (1.0 - (1.0 - time_of_day.0 as f32 / 12.0 * 60.0 * 60.0).abs())
* self.weather[point].cloud;
// V = B(T Tv(h))H(T Tv(h))
// γ = 0.5, δ = 0.25, B = 0.5 and Tv(h) = 20◦C
cell.temperature = cell.temperature * (1.0 - dt)
+ dt * (self.constants[point].temperature_day * day_light
+ self.constants[point].temperature_night * (1.0 - day_light));
// TODO: make these parameters depend on the world.
// TODO: figure out what these variables mean.
let gamma = 0.5;
let delta = 0.25;
let b = 0.5;
let h = 1.0;
let t_v = BASE_TEMPERATURE;
// Evaporate from ground.
let temp_part = (cell.temperature / WATER_BOILING_POINT)
//.powf(2.0)
.clamp(0.0, 1.0);
cell.moisture += (self.constants[point].water / 10.0) * temp_part * DT;
let rain_fall_max = 0.05;
let evaporation = b * (cell.temperature - t_v) * h * (cell.temperature - t_v);
let dew_point = (100.0 - cell.moisture) / 5.0;
let condensation =
delta * (dew_point - cell.temperature) * h * (dew_point - cell.temperature)
- gamma * (cell.temperature - dew_point) * h * (cell.temperature - dew_point);
cell.rain += condensation;
if cell.rain > rain_fall_max {
cell.rain -= rain_fall_max;
self.weather[point].rain = 1.0;
// If positive condense moisture to clouds, if negative evaporate clouds into
// moisture.
let condensation = if cell.moisture > 1.0 {
cell.moisture.powf(2.0 / 3.0)
} else {
self.weather[point].rain = 0.5;
}
cell.moisture += evaporation - condensation;
cell.moisture
} * temp_part
* DT;
self.weather[point].cloud = (cell.rain / MAX_RAIN).clamp(0.0, 1.0);
cell.moisture -= condensation;
cell.cloud += condensation;
const CLOUD_MAX: f32 = 15.0;
const RAIN_P: f32 = 0.96;
let rain_cloud = temp_part * CLOUD_MAX;
let rain_p_t = ((cell.cloud - rain_cloud) / (CLOUD_MAX - rain_cloud)).max(0.0);
let rain = rain_p_t * (1.0 - RAIN_P.powf(DT));
cell.cloud -= rain;
cell.cloud = cell.cloud.max(0.0);
self.weather[point].cloud = (cell.cloud / CLOUD_MAX).clamp(0.0, 1.0);
self.weather[point].rain = rain_p_t;
self.weather[point].wind = cell.wind;
}
// Maybe moisture condenses to clouds, which if they have a certain
// amount they will release rain.
}
fn update_info(&mut self) {
let w = self
.cells
.iter()
.map(|(p, c)| {
(
p,
Weather::new(
//if p.x % 2 == p.y % 2 { 1.0 } else { 0.0 },
(self.constants[p].humidity.unwrap_or(0.0) * 100.0).clamp(0.0, 1.0),
0.0,
c.wind,
),
)
})
.collect_vec();
w.iter().for_each(|&(p, w)| {
self.weather[p] = w;
});
}
}

View File

@ -14,7 +14,6 @@ pub struct Sys;
impl<'a> System<'a> for Sys {
type SystemData = (
Read<'a, TimeOfDay>,
ReadExpect<'a, Arc<world::World>>,
WriteExpect<'a, WeatherSim>,
Write<'a, SysScheduler<Self>>,
);
@ -23,12 +22,9 @@ impl<'a> System<'a> for Sys {
const ORIGIN: Origin = Origin::Server;
const PHASE: Phase = Phase::Create;
fn run(
job: &mut common_ecs::Job<Self>,
(game_time, world, mut sim, mut scheduler): Self::SystemData,
) {
fn run(job: &mut common_ecs::Job<Self>, (game_time, mut sim, mut scheduler): Self::SystemData) {
if scheduler.should_run() {
sim.tick(&*world, &*game_time, 1.0);
sim.tick(&*game_time, 1.0);
}
}
}

View File

@ -101,6 +101,7 @@ use common::{
uid::Uid,
util::{srgba_to_linear, Dir},
vol::RectRasterableVol,
weather::Weather,
};
use common_base::{prof_span, span};
use common_net::{
@ -264,6 +265,7 @@ widget_ids! {
current_site,
graphics_backend,
gpu_timings[],
weather,
// Game Version
version,
@ -492,6 +494,7 @@ pub struct DebugInfo {
pub num_figures_visible: u32,
pub num_particles: u32,
pub num_particles_visible: u32,
pub weather: Weather,
}
pub struct HudInfo {
@ -2386,11 +2389,27 @@ impl Hud {
.font_size(self.fonts.cyri.scale(14))
.set(self.ids.time, ui_widgets);
let weather = client.current_weather();
Text::new(&format!(
"Weather({kind:.5}): {{cloud: {cloud:.5}, rain: {rain:.5}, wind: <{wind_x:.5}, \
{wind_y:.2}>}}",
kind = weather.get_kind(),
cloud = weather.cloud,
rain = weather.rain,
wind_x = weather.wind.x,
wind_y = weather.wind.y
))
.color(TEXT_COLOR)
.down_from(self.ids.time, V_PAD)
.font_id(self.fonts.cyri.conrod_id)
.font_size(self.fonts.cyri.scale(14))
.set(self.ids.weather, ui_widgets);
// Number of entities
let entity_count = client.state().ecs().entities().join().count();
Text::new(&format!("Entity count: {}", entity_count))
.color(TEXT_COLOR)
.down_from(self.ids.time, V_PAD)
.down_from(self.ids.weather, V_PAD)
.font_id(self.fonts.cyri.conrod_id)
.font_size(self.fonts.cyri.scale(14))
.set(self.ids.entity_count, ui_widgets);
@ -2503,6 +2522,7 @@ impl Hud {
// Set debug box dimensions, only timings height is dynamic
// TODO: Make the background box size fully dynamic
let debug_bg_size = [320.0, 370.0 + timings_height];
Rectangle::fill(debug_bg_size)

View File

@ -63,6 +63,7 @@ pub struct Globals {
medium: [u32; 4],
select_pos: [i32; 4],
gamma_exposure: [f32; 4],
wind_vel: [f32; 2],
ambiance: f32,
cam_mode: u32,
sprite_render_distance: f32,
@ -108,6 +109,7 @@ impl Globals {
ambiance: f32,
cam_mode: CameraMode,
sprite_render_distance: f32,
wind_vel: Vec2<f32>,
) -> Self {
Self {
view_mat: view_mat.into_col_arrays(),
@ -153,6 +155,7 @@ impl Globals {
.unwrap_or_else(Vec4::zero)
.into_array(),
gamma_exposure: [gamma, exposure, 0.0, 0.0],
wind_vel: [wind_vel.x, wind_vel.y],
ambiance: ambiance.clamped(0.0, 1.0),
cam_mode: cam_mode as u32,
sprite_render_distance,
@ -202,6 +205,7 @@ impl Default for Globals {
1.0,
CameraMode::ThirdPerson,
250.0,
Vec2::zero(),
)
}
}
@ -401,7 +405,7 @@ impl GlobalsLayouts {
},
count: None,
},
// clouds t_clouds
// clouds t_weather
wgpu::BindGroupLayoutEntry {
binding: 12,
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,

View File

@ -677,6 +677,7 @@ impl Scene {
scene_data.ambiance,
self.camera.get_mode(),
scene_data.sprite_render_distance as f32 - 20.0,
client.current_weather_wpos(cam_pos.xy()).wind,
)]);
renderer.update_clouds_locals(CloudsLocals::new(proj_mat_inv, view_mat_inv));
renderer.update_postprocess_locals(PostProcessLocals::new(proj_mat_inv, view_mat_inv));

View File

@ -274,6 +274,7 @@ impl Scene {
scene_data.ambiance,
self.camera.get_mode(),
250.0,
Vec2::zero(),
)]);
self.figure_model_cache

View File

@ -338,9 +338,10 @@ impl SessionState {
.get_weather()
.iter()
.map(|(_, w)| {
//println!("{}, ", w.cloud);
[
(w.cloud * 255.0) as u8,
(w.rain + 128.0).clamp(0.0, 255.0) as u8,
(w.rain * 255.0) as u8,
(w.wind.x + 128.0).clamp(0.0, 255.0) as u8,
(w.wind.y + 128.0).clamp(0.0, 255.0) as u8,
]
@ -1126,6 +1127,7 @@ impl PlayState for SessionState {
num_particles: self.scene.particle_mgr().particle_count() as u32,
num_particles_visible: self.scene.particle_mgr().particle_count_visible()
as u32,
weather: client.current_weather(),
}
});