Make wind sway change according to weather wind velocity

This commit is contained in:
Joshua Barretto 2022-12-31 17:40:40 +00:00
parent 873d3fb7a4
commit f48e1ca951
10 changed files with 59 additions and 22 deletions

View File

@ -20,6 +20,7 @@ layout(std140, set = 0, binding = 0) uniform u_globals {
ivec4 select_pos; ivec4 select_pos;
vec4 gamma_exposure; vec4 gamma_exposure;
vec4 last_lightning; vec4 last_lightning;
vec2 wind_vel;
float ambiance; float ambiance;
// 0 - FirstPerson // 0 - FirstPerson
// 1 - ThirdPerson // 1 - ThirdPerson

View File

@ -53,6 +53,7 @@ const float SCALE = 1.0 / 11.0;
const float SCALE_FACTOR = pow(SCALE, 1.3) * 0.2; const float SCALE_FACTOR = pow(SCALE, 1.3) * 0.2;
const float EXTRA_NEG_Z = 32768.0; const float EXTRA_NEG_Z = 32768.0;
const float VERT_EXTRA_NEG_XY = 128.0;
const float VERT_EXTRA_NEG_Z = 128.0; const float VERT_EXTRA_NEG_Z = 128.0;
const uint VERT_PAGE_SIZE = 256; const uint VERT_PAGE_SIZE = 256;
@ -74,6 +75,19 @@ vec4 nearest_entity(in vec3 sprite_pos, const float entity_radius_factor) {
return closest; return closest;
} }
float wind_wave(float off, float scaling, float speed, float strength) {
float aspeed = abs(speed);
// TODO: Right now, the wind model is pretty simplistic. This means that there is frequently no wind at all, which
// looks bad. For now, we add a lower bound on the wind speed to keep things looking nice.
strength = max(strength, 3.0);
aspeed = max(aspeed, 3.0);
return (sin(tick.x * 0.75 * scaling * floor(aspeed) + off) * (1.0 - fract(aspeed))
+ sin(tick.x * 0.75 * scaling * ceil(aspeed) + off) * fract(aspeed)) * abs(strength) * 0.5;
//return sin(tick.x * 1.5 * scaling + off) + sin(tick.x * 0.35 * scaling + off);
}
void main() { void main() {
// Matrix to transform this sprite instance from model space to chunk space // Matrix to transform this sprite instance from model space to chunk space
mat4 inst_mat; mat4 inst_mat;
@ -94,7 +108,11 @@ void main() {
uint v_atlas_pos = pos_atlas_pos_norm_ao.y; uint v_atlas_pos = pos_atlas_pos_norm_ao.y;
// Expand the model vertex position bits into float values // Expand the model vertex position bits into float values
vec3 v_pos = vec3(v_pos_norm & 0xFFu, (v_pos_norm >> 8) & 0xFFu, float((v_pos_norm >> 16) & 0x0FFFu) - VERT_EXTRA_NEG_Z); vec3 v_pos = vec3(
float(v_pos_norm & 0xFFu) - VERT_EXTRA_NEG_XY,
float((v_pos_norm >> 8) & 0xFFu) - VERT_EXTRA_NEG_XY,
float((v_pos_norm >> 16) & 0x0FFFu) - VERT_EXTRA_NEG_Z
);
// Position of the sprite block in the chunk // Position of the sprite block in the chunk
// Used for highlighting the selected sprite, and for opening doors // Used for highlighting the selected sprite, and for opening doors
@ -142,15 +160,16 @@ void main() {
#endif #endif
#ifndef EXPERIMENTAL_BAREMINIMUM #ifndef EXPERIMENTAL_BAREMINIMUM
// TODO: take wind_vel into account
// Wind sway effect // Wind sway effect
f_pos += model_wind_sway * vec3( f_pos.xy += (wind_vel * 0.1 + vec2(
sin(tick.x * 1.5 + f_pos.y * 0.1) * sin(tick.x * 0.35), wind_wave(f_pos.y * 0.1, 0.9, wind_vel.x, wind_vel.y),
sin(tick.x * 1.5 + f_pos.x * 0.1) * sin(tick.x * 0.25), wind_wave(f_pos.x * 0.1, 1.1, wind_vel.y, wind_vel.x)
0.0 ))
// NOTE: could potentially replace `v_pos.z * model_z_scale` with a calculation using `inst_chunk_pos` from below * model_wind_sway
//) * pow(abs(v_pos.z * model_z_scale), 1.3) * SCALE_FACTOR; //* mix(10.0, abs(v_pos.z), 1.0 / (1.0 + abs(v_pos.z) * 0.1))
) * v_pos.z * model_z_scale * SCALE_FACTOR; * v_pos.z
* model_z_scale
* SCALE_FACTOR;
if (model_wind_sway > 0.0) { if (model_wind_sway > 0.0) {
vec2 center = sprite_pos.xy + 0.5; vec2 center = sprite_pos.xy + 0.5;

View File

@ -700,16 +700,16 @@ Liana: Some((
variations: [ variations: [
( (
model: "voxygen.voxel.sprite.lianas.liana-0", model: "voxygen.voxel.sprite.lianas.liana-0",
offset: (-4.0, -4.0, -88.0), offset: (-4.0, -4.0, -115.0),
lod_axes: (0.0, 0.0, 0.5), lod_axes: (0.0, 0.0, 0.5),
), ),
( (
model: "voxygen.voxel.sprite.lianas.liana-1", model: "voxygen.voxel.sprite.lianas.liana-1",
offset: (-4.0, -4.0, -55.0), offset: (-4.0, -4.0, -72.0),
lod_axes: (0.0, 0.0, 0.5), lod_axes: (0.0, 0.0, 0.5),
), ),
], ],
wind_sway: 0.0, wind_sway: 0.5,
)), )),
// Velorite // Velorite
Velorite: Some(( Velorite: Some((
@ -1403,7 +1403,7 @@ SavannaBush: Some((
lod_axes: (1.0, 1.0, 1.0), lod_axes: (1.0, 1.0, 1.0),
), ),
], ],
wind_sway: 0.1, wind_sway: 0.2,
)), )),
// Dead Bush // Dead Bush
DeadBush: Some(( DeadBush: Some((
@ -1429,7 +1429,7 @@ DeadBush: Some((
lod_axes: (1.0, 1.0, 1.0), lod_axes: (1.0, 1.0, 1.0),
), ),
], ],
wind_sway: 0.1, wind_sway: 0.2,
)), )),
// Blueberries // Blueberries
// NOTE: Why are these commented out? // NOTE: Why are these commented out?

View File

@ -43,7 +43,12 @@ impl Weather {
// Get the rain velocity for this weather // Get the rain velocity for this weather
pub fn rain_vel(&self) -> Vec3<f32> { pub fn rain_vel(&self) -> Vec3<f32> {
const FALL_RATE: f32 = 30.0; const FALL_RATE: f32 = 30.0;
Vec3::new(self.wind.x, self.wind.y, -FALL_RATE) self.wind.with_z(-FALL_RATE)
}
// Get the wind velocity for this weather
pub fn wind_vel(&self) -> Vec2<f32> {
self.wind
} }
} }

View File

@ -122,6 +122,7 @@ pub fn generate_mesh_base_vol_sprite<'a: 'b, 'b, V: 'a>(
&'b mut Mesh<SpriteVertex>, &'b mut Mesh<SpriteVertex>,
bool, bool,
), ),
offset: Vec3<f32>,
) -> MeshGen<SpriteVertex, SpriteVertex, TerrainVertex, ()> ) -> MeshGen<SpriteVertex, SpriteVertex, TerrainVertex, ()>
where where
V: BaseVol<Vox = Cell> + ReadVol + SizedVol, V: BaseVol<Vox = Cell> + ReadVol + SizedVol,
@ -211,7 +212,7 @@ where
// position, pos + mesh_delta, is guaranteed to fit in an f32). // position, pos + mesh_delta, is guaranteed to fit in an f32).
let mesh_delta = lower_bound.as_::<f32>(); let mesh_delta = lower_bound.as_::<f32>();
let create_opaque = |atlas_pos, pos: Vec3<f32>, norm, _meta| { let create_opaque = |atlas_pos, pos: Vec3<f32>, norm, _meta| {
SpriteVertex::new(atlas_pos, pos + mesh_delta, norm) SpriteVertex::new(atlas_pos, pos + offset + mesh_delta, norm)
}; };
greedy.push(GreedyConfig { greedy.push(GreedyConfig {

View File

@ -65,11 +65,12 @@ pub struct Globals {
select_pos: [i32; 4], select_pos: [i32; 4],
gamma_exposure: [f32; 4], gamma_exposure: [f32; 4],
last_lightning: [f32; 4], last_lightning: [f32; 4],
wind_vel: [f32; 2],
ambiance: f32, ambiance: f32,
cam_mode: u32, cam_mode: u32,
sprite_render_distance: f32, sprite_render_distance: f32,
// To keep 16-byte-aligned. // To keep 16-byte-aligned.
globals_dummy: [f32; 1], globals_dummy: [f32; 3],
} }
/// Make sure Globals is 16-byte-aligned. /// Make sure Globals is 16-byte-aligned.
const _: () = assert!(core::mem::size_of::<Globals>() % 16 == 0); const _: () = assert!(core::mem::size_of::<Globals>() % 16 == 0);
@ -110,6 +111,7 @@ impl Globals {
gamma: f32, gamma: f32,
exposure: f32, exposure: f32,
last_lightning: (Vec3<f32>, f64), last_lightning: (Vec3<f32>, f64),
wind_vel: Vec2<f32>,
ambiance: f32, ambiance: f32,
cam_mode: CameraMode, cam_mode: CameraMode,
sprite_render_distance: f32, sprite_render_distance: f32,
@ -162,10 +164,11 @@ impl Globals {
.0 .0
.with_w(last_lightning.1 as f32) .with_w(last_lightning.1 as f32)
.into_array(), .into_array(),
wind_vel: wind_vel.into_array(),
ambiance: ambiance.clamped(0.0, 1.0), ambiance: ambiance.clamped(0.0, 1.0),
cam_mode: cam_mode as u32, cam_mode: cam_mode as u32,
sprite_render_distance, sprite_render_distance,
globals_dummy: [0.0; 1], globals_dummy: [0.0; 3],
} }
} }
@ -209,6 +212,7 @@ impl Default for Globals {
1.0, 1.0,
1.0, 1.0,
(Vec3::zero(), -1000.0), (Vec3::zero(), -1000.0),
Vec2::zero(),
1.0, 1.0,
CameraMode::ThirdPerson, CameraMode::ThirdPerson,
250.0, 250.0,

View File

@ -42,6 +42,7 @@ impl Vertex {
// NOTE: Limit to 16 (x) × 16 (y) × 32 (z). // NOTE: Limit to 16 (x) × 16 (y) × 32 (z).
#[allow(clippy::collapsible_else_if)] #[allow(clippy::collapsible_else_if)]
pub fn new(atlas_pos: Vec2<u16>, pos: Vec3<f32>, norm: Vec3<f32>) -> Self { pub fn new(atlas_pos: Vec2<u16>, pos: Vec3<f32>, norm: Vec3<f32>) -> Self {
const VERT_EXTRA_NEG_XY: i32 = 128;
const VERT_EXTRA_NEG_Z: i32 = 128; // NOTE: change if number of bits changes below, also we might not need this if meshing always produces positives values for sprites (I have no idea) const VERT_EXTRA_NEG_Z: i32 = 128; // NOTE: change if number of bits changes below, also we might not need this if meshing always produces positives values for sprites (I have no idea)
#[allow(clippy::bool_to_int_with_if)] #[allow(clippy::bool_to_int_with_if)]
@ -59,8 +60,8 @@ impl Vertex {
// | (((pos + EXTRA_NEG_Z).z.max(0.0).min((1 << 16) as f32) as u32) & 0xFFFF) << 12 // | (((pos + EXTRA_NEG_Z).z.max(0.0).min((1 << 16) as f32) as u32) & 0xFFFF) << 12
// | if meta { 1 } else { 0 } << 28 // | if meta { 1 } else { 0 } << 28
// | (norm_bits & 0x7) << 29, // | (norm_bits & 0x7) << 29,
pos_norm: ((pos.x as u32) & 0x00FF) // NOTE: temp hack, this doesn't need 8 bits pos_norm: (((pos.x as i32 + VERT_EXTRA_NEG_XY) & 0x00FF) as u32) // NOTE: temp hack, this doesn't need 8 bits
| ((pos.y as u32) & 0x00FF) << 8 | (((pos.y as i32 + VERT_EXTRA_NEG_XY) & 0x00FF) as u32) << 8
| (((pos.z as i32 + VERT_EXTRA_NEG_Z).clamp(0, 1 << 12) as u32) & 0x0FFF) << 16 | (((pos.z as i32 + VERT_EXTRA_NEG_Z).clamp(0, 1 << 12) as u32) & 0x0FFF) << 16
| (norm_bits & 0x7) << 29, | (norm_bits & 0x7) << 29,
atlas_pos: ((atlas_pos.x as u32) & 0xFFFF) | ((atlas_pos.y as u32) & 0xFFFF) << 16, atlas_pos: ((atlas_pos.x as u32) & 0xFFFF) | ((atlas_pos.y as u32) & 0xFFFF) << 16,

View File

@ -111,6 +111,7 @@ pub struct Scene {
ambient_mgr: AmbientMgr, ambient_mgr: AmbientMgr,
integrated_rain_vel: f32, integrated_rain_vel: f32,
wind_vel: Vec2<f32>,
pub interpolated_time_of_day: Option<f64>, pub interpolated_time_of_day: Option<f64>,
last_lightning: Option<(Vec3<f32>, f64)>, last_lightning: Option<(Vec3<f32>, f64)>,
} }
@ -345,6 +346,7 @@ impl Scene {
ambience: ambient::load_ambience_items(), ambience: ambient::load_ambience_items(),
}, },
integrated_rain_vel: 0.0, integrated_rain_vel: 0.0,
wind_vel: Vec2::zero(),
interpolated_time_of_day: None, interpolated_time_of_day: None,
last_lightning: None, last_lightning: None,
} }
@ -783,6 +785,7 @@ impl Scene {
scene_data.gamma, scene_data.gamma,
scene_data.exposure, scene_data.exposure,
self.last_lightning.unwrap_or((Vec3::zero(), -1000.0)), self.last_lightning.unwrap_or((Vec3::zero(), -1000.0)),
self.wind_vel,
scene_data.ambiance, scene_data.ambiance,
self.camera.get_mode(), self.camera.get_mode(),
scene_data.sprite_render_distance - 20.0, scene_data.sprite_render_distance - 20.0,
@ -1101,6 +1104,7 @@ impl Scene {
let weather = client let weather = client
.state() .state()
.max_weather_near(focus_off.xy() + cam_pos.xy()); .max_weather_near(focus_off.xy() + cam_pos.xy());
self.wind_vel = weather.wind_vel();
if weather.rain > RAIN_THRESHOLD { if weather.rain > RAIN_THRESHOLD {
let weather = client.state().weather_at(focus_off.xy() + cam_pos.xy()); let weather = client.state().weather_at(focus_off.xy() + cam_pos.xy());
let rain_vel = weather.rain_vel(); let rain_vel = weather.rain_vel();

View File

@ -274,6 +274,7 @@ impl Scene {
scene_data.gamma, scene_data.gamma,
scene_data.exposure, scene_data.exposure,
(Vec3::zero(), -1000.0), (Vec3::zero(), -1000.0),
Vec2::zero(),
scene_data.ambiance, scene_data.ambiance,
self.camera.get_mode(), self.camera.get_mode(),
250.0, 250.0,

View File

@ -515,6 +515,7 @@ impl SpriteRenderContext {
generate_mesh_base_vol_sprite( generate_mesh_base_vol_sprite(
Segment::from(&model.read().0).scaled_by(lod_scale), Segment::from(&model.read().0).scaled_by(lod_scale),
(greedy, sprite_mesh, false), (greedy, sprite_mesh, false),
offset.map(|e: f32| e.floor()) * lod_scale,
); );
// Get the number of pages after the model was meshed // Get the number of pages after the model was meshed
let end_page_num = (sprite_mesh.vertices().len() let end_page_num = (sprite_mesh.vertices().len()
@ -532,7 +533,7 @@ impl SpriteRenderContext {
SpriteData { SpriteData {
vert_pages: start_page_num as u32..end_page_num as u32, vert_pages: start_page_num as u32..end_page_num as u32,
scale: sprite_scale, scale: sprite_scale,
offset, offset: offset.map(|e| e.rem_euclid(1.0)),
} }
}); });