diff --git a/assets/voxygen/shaders/particle-vert.glsl b/assets/voxygen/shaders/particle-vert.glsl index a2c8a89ee4..72aecd1758 100644 --- a/assets/voxygen/shaders/particle-vert.glsl +++ b/assets/voxygen/shaders/particle-vert.glsl @@ -64,6 +64,7 @@ const int LIFESTEAL_BEAM = 22; const int CULTIST_FLAME = 23; const int STATIC_SMOKE = 24; const int BLOOD = 25; +const int DUST = 26; // meters per second squared (acceleration) const float earth_gravity = 9.807; @@ -421,6 +422,16 @@ void main() { vec4(1, 0, 0, 1), spin_in_axis(vec3(1,0,0),0) ); + } else if (inst_mode == DUST) { + attr = Attr( + linear_motion( + vec3(0), + vec3(rand2 * 0.1, rand3 * 0.1, 0.25 + rand4 * 0.5) + ), + vec3(pow(1.0 - abs(percent() - 0.5) * 2.0, 0.25) * 1.5), + vec4(/*inst_dir*/ vec3(0.5, 0.4, 0.1), 1), + spin_in_axis(vec3(1,0,0),0) + ); } else { attr = Attr( linear_motion( diff --git a/voxygen/src/lib.rs b/voxygen/src/lib.rs index 81df2ba090..6e93215f2a 100644 --- a/voxygen/src/lib.rs +++ b/voxygen/src/lib.rs @@ -8,7 +8,8 @@ const_generics, drain_filter, once_cell, - or_patterns + or_patterns, + option_zip, )] #![recursion_limit = "2048"] diff --git a/voxygen/src/render/pipelines/particle.rs b/voxygen/src/render/pipelines/particle.rs index 32a73abfde..ed041c11cd 100644 --- a/voxygen/src/render/pipelines/particle.rs +++ b/voxygen/src/render/pipelines/particle.rs @@ -122,6 +122,7 @@ pub enum ParticleMode { CultistFlame = 23, StaticSmoke = 24, Blood = 25, + Dust = 26, } impl ParticleMode { @@ -163,6 +164,23 @@ impl Instance { inst_dir: (inst_pos2 - inst_pos).into_array(), } } + + pub fn new_dust( + inst_time: f64, + lifespan: f32, + inst_pos: Vec3, + inst_color: Rgb, + ) -> Self { + use rand::Rng; + Self { + inst_time: inst_time as f32, + inst_lifespan: lifespan, + inst_entropy: rand::thread_rng().gen(), + inst_mode: ParticleMode::Dust as i32, + inst_pos: inst_pos.into_array(), + inst_dir: inst_color.into_array(), + } + } } impl Default for Instance { diff --git a/voxygen/src/scene/particle.rs b/voxygen/src/scene/particle.rs index b58bbff27f..ee8fb29893 100644 --- a/voxygen/src/scene/particle.rs +++ b/voxygen/src/scene/particle.rs @@ -10,7 +10,7 @@ use common::{ assets::{AssetExt, DotVoxAsset}, comp::{ self, aura, beam, body, buff, item::Reagent, object, BeamSegment, Body, CharacterState, - Ori, Pos, Shockwave, Vel, + Ori, Pos, Shockwave, Vel, PhysicsState, }, figure::Segment, outcome::Outcome, @@ -254,10 +254,11 @@ impl ParticleMgr { "ParticleMgr::maintain_body_particles" ); let ecs = scene_data.state.ecs(); - for (body, pos, vel) in ( + for (body, pos, vel, physics_state) in ( &ecs.read_storage::(), &ecs.read_storage::(), ecs.read_storage::().maybe(), + ecs.read_storage::().maybe(), ) .join() { @@ -289,6 +290,7 @@ impl ParticleMgr { | object::Body::FireworkWhite | object::Body::FireworkYellow, ) => self.maintain_bomb_particles(scene_data, pos, vel), + Body::Humanoid(_) => self.maintain_dust_particles(scene_data, pos, vel, physics_state), _ => {}, } } @@ -484,6 +486,30 @@ impl ParticleMgr { } } + fn maintain_dust_particles(&mut self, scene_data: &SceneData, pos: &Pos, vel: Option<&Vel>, physics_state: Option<&PhysicsState>) { + span!( + _guard, + "dust_particles", + "ParticleMgr::maintain_dust_particles" + ); + let time = scene_data.state.get_time(); + let dt = scene_data.state.get_delta_time(); + let mut rng = thread_rng(); + + if let Some(vel) = vel.zip_with(physics_state.filter(|ps| ps.on_ground), |vel, ps| vel.0 - ps.ground_vel) { + for _ in 0..self.scheduler.heartbeats(Duration::from_millis((750.0 / (vel.magnitude() + 0.1)).clamped(10.0, 10000.0) as u64)) { + // Dust + self.particles.push(Particle::new_dust( + Duration::from_millis(500), + time, + pos.0 + Vec2::::zero().map(|_| rng.gen_range(-0.4..0.4)).with_z(0.0) + - vel * dt * rng.gen::(), + Rgb::new(150.0, 125.0, 75.0), + )); + } + } + } + fn maintain_char_state_particles(&mut self, scene_data: &SceneData) { span!( _guard, @@ -1239,4 +1265,21 @@ impl Particle { ), } } + + fn new_dust( + lifespan: Duration, + time: f64, + pos: Vec3, + color: Rgb, + ) -> Self { + Particle { + alive_until: time + lifespan.as_secs_f64(), + instance: ParticleInstance::new_dust( + time, + lifespan.as_secs_f32(), + pos, + color, + ), + } + } }