Interpolate weather in voxygen

This commit is contained in:
IsseW 2022-03-15 09:34:01 +01:00
parent e37f2be820
commit 4fa2644507
5 changed files with 89 additions and 31 deletions

View File

@ -1,7 +1,7 @@
use std::fmt;
use serde::{Deserialize, Serialize};
use vek::Vec2;
use vek::{Lerp, Vec2};
pub const CHUNKS_PER_CELL: u32 = 16;
// Weather::default is Clear, 0 degrees C and no wind
@ -31,6 +31,14 @@ impl Weather {
_ => WeatherKind::Clear,
}
}
pub fn lerp(from: &Self, to: &Self, t: f32) -> Self {
Self {
cloud: f32::lerp(from.cloud, to.cloud, t),
rain: f32::lerp(from.rain, to.rain, t),
wind: Vec2::<f32>::lerp(from.wind, to.wind, t),
}
}
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]

View File

@ -1,6 +1,7 @@
use super::super::{AaMode, GlobalsLayouts, Renderer, Texture, Vertex as VertexTrait};
use bytemuck::{Pod, Zeroable};
use std::mem;
use common::{grid::Grid, weather::Weather};
use std::{mem, time::Instant};
use vek::*;
#[repr(C)]
@ -31,12 +32,77 @@ impl VertexTrait for Vertex {
const STRIDE: wgpu::BufferAddress = mem::size_of::<Self>() as wgpu::BufferAddress;
}
pub struct WeatherTexture {
a: (Grid<Weather>, Instant),
b: (Grid<Weather>, Instant),
pub tex: Texture,
}
impl WeatherTexture {
fn new(tex: Texture) -> Self {
Self {
a: (Grid::new(Vec2::zero(), Default::default()), Instant::now()),
b: (Grid::new(Vec2::zero(), Default::default()), Instant::now()),
tex,
}
}
pub fn update_weather(&mut self, weather: Grid<Weather>) {
self.a = mem::replace(&mut self.b, (weather, Instant::now()));
}
pub fn update_texture(&self, renderer: &mut Renderer) {
let a = &self.a.0;
let b = &self.b.0;
let size = self.b.0.size().as_::<u32>();
if a.size() != b.size() {
renderer.update_texture(
&self.tex,
[0, 0],
[size.x, size.y],
&b.iter()
.map(|(_, w)| {
[
(w.cloud * 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,
]
})
.collect::<Vec<_>>(),
);
} else {
// Assume updates are regular
let t = (self.b.1.elapsed().as_secs_f32()
/ self.b.1.duration_since(self.a.1).as_secs_f32())
.clamp(0.0, 1.0);
renderer.update_texture(
&self.tex,
[0, 0],
[size.x, size.y],
&a.iter()
.zip(b.iter())
.map(|((_, a), (_, b))| {
let w = Weather::lerp(a, b, t);
[
(w.cloud * 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,
]
})
.collect::<Vec<_>>(),
);
}
}
}
pub struct LodData {
pub map: Texture,
pub alt: Texture,
pub horizon: Texture,
pub tgt_detail: u32,
pub clouds: Texture,
pub weather: WeatherTexture,
}
impl LodData {
@ -135,7 +201,7 @@ impl LodData {
);
// SamplerInfo {
// border: [1.0, 0.0, 1.0, 0.0].into(),
let clouds = {
let weather = {
let texture_info = wgpu::TextureDescriptor {
label: None,
size: wgpu::Extent3d {
@ -185,7 +251,7 @@ impl LodData {
alt,
horizon,
tgt_detail,
clouds,
weather: WeatherTexture::new(weather),
}
}
}

View File

@ -578,11 +578,11 @@ impl GlobalsLayouts {
},
wgpu::BindGroupEntry {
binding: 12,
resource: wgpu::BindingResource::TextureView(&lod_data.clouds.view),
resource: wgpu::BindingResource::TextureView(&lod_data.weather.tex.view),
},
wgpu::BindGroupEntry {
binding: 13,
resource: wgpu::BindingResource::Sampler(&lod_data.clouds.sampler),
resource: wgpu::BindingResource::Sampler(&lod_data.weather.tex.sampler),
},
]
}

View File

@ -10,9 +10,11 @@ use crate::{
use client::Client;
use common::{
assets::{AssetExt, ObjAsset},
grid::Grid,
lod,
spiral::Spiral2d,
util::srgba_to_linear,
weather::Weather,
};
use hashbrown::HashMap;
use std::ops::Range;
@ -77,6 +79,10 @@ impl Lod {
pub fn get_data(&self) -> &LodData { &self.data }
pub fn update_weather(&mut self, weather: Grid<Weather>) {
self.data.weather.update_weather(weather);
}
pub fn set_detail(&mut self, detail: u32) {
// Make sure the recorded detail is even.
self.data.tgt_detail = (detail - detail % 2).max(100).min(2500);
@ -89,6 +95,7 @@ impl Lod {
focus_pos: Vec3<f32>,
camera: &Camera,
) {
self.data.weather.update_texture(renderer);
// Update LoD terrain mesh according to detail
if self
.model

View File

@ -4,7 +4,6 @@ mod target;
use std::{cell::RefCell, collections::HashSet, rc::Rc, result::Result, time::Duration};
use itertools::Itertools;
#[cfg(not(target_os = "macos"))]
use mumble_link::SharedLink;
use ordered_float::OrderedFloat;
@ -326,29 +325,7 @@ impl SessionState {
self.hud.show.update_map_markers(event);
},
client::Event::WeatherUpdate => {
//weather
// .iter_mut()
// .for_each(|(p, c)| *c = if (p.x + p.y) % 2 == 0 { 1.0 } else { 0.0 });
let size = client.get_weather().size();
global_state.window.renderer_mut().update_texture(
&self.scene.lod.get_data().clouds,
[0, 0],
[size.x as u32, size.y as u32],
client
.get_weather()
.iter()
.map(|(_, w)| {
//println!("{}, ", w.cloud);
[
(w.cloud * 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,
]
})
.collect_vec()
.as_slice(),
);
self.scene.lod.update_weather(client.get_weather().clone());
},
}
}