diff --git a/assets/voxygen/shaders/particle-vert.glsl b/assets/voxygen/shaders/particle-vert.glsl index a78551a935..7170fbc6f8 100644 --- a/assets/voxygen/shaders/particle-vert.glsl +++ b/assets/voxygen/shaders/particle-vert.glsl @@ -78,17 +78,17 @@ float start_end(float from, float to) { return mix(from, to, lifetime / inst_lifespan); } -mat4 rotationMatrix(vec3 axis, float angle) +mat4 spin_in_axis(vec3 axis, float angle) { - axis = normalize(axis); - float s = sin(angle); - float c = cos(angle); - float oc = 1.0 - c; + axis = normalize(axis); + float s = sin(angle); + float c = cos(angle); + float oc = 1.0 - c; - return mat4(oc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s, 0, - oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s, 0, - oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c, 0, - 0, 0, 0, 1); + return mat4(oc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s, 0, + oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s, 0, + oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c, 0, + 0, 0, 0, 1); } void main() { @@ -113,7 +113,7 @@ void main() { ), linear_scale(0.5), vec4(1, 1, 1, start_end(1.0, 0.0)), - rotationMatrix(vec3(rand6, rand7, rand8), rand9 * 3 + lifetime * 0.5) + spin_in_axis(vec3(rand6, rand7, rand8), rand9 * 3 + lifetime * 0.5) ); } else if (inst_mode == FIRE) { attr = Attr( @@ -123,7 +123,7 @@ void main() { ), 1.0, vec4(2, 0.8 + rand5 * 0.3, 0, 1), - rotationMatrix(vec3(rand6, rand7, rand8), rand9 * 3) + spin_in_axis(vec3(rand6, rand7, rand8), rand9 * 3) ); } else if (inst_mode == GUN_POWDER_SPARK) { attr = Attr( @@ -133,7 +133,7 @@ void main() { ), 1.0, vec4(3.5, 3 + rand7, 0, 1), - rotationMatrix(vec3(1,0,0),0) + spin_in_axis(vec3(1,0,0),0) ); } else if (inst_mode == SHRAPNEL) { attr = Attr( @@ -143,7 +143,7 @@ void main() { ), 3.0 + rand0, vec4(vec3(0.6 + rand7 * 0.4), 1), - rotationMatrix(vec3(1,0,0),0) + spin_in_axis(vec3(1,0,0),0) ); } else if (inst_mode == FIREWORK_BLUE) { attr = Attr( @@ -153,7 +153,7 @@ void main() { ), 3.0 + rand0, vec4(vec3(0.6 + rand7 * 0.4), 0.3), - rotationMatrix(vec3(1,0,0),0) + spin_in_axis(vec3(1,0,0),0) ); } else if (inst_mode == FIREWORK_GREEN) { attr = Attr( @@ -163,7 +163,7 @@ void main() { ), 3.0 + rand0, vec4(vec3(0.6 + rand7 * 0.4), 0.3), - rotationMatrix(vec3(1,0,0),0) + spin_in_axis(vec3(1,0,0),0) ); } else if (inst_mode == FIREWORK_PURPLE) { attr = Attr( @@ -173,7 +173,7 @@ void main() { ), 3.0 + rand0, vec4(vec3(0.6 + rand7 * 0.4), 0.3), - rotationMatrix(vec3(1,0,0),0) + spin_in_axis(vec3(1,0,0),0) ); } else if (inst_mode == FIREWORK_RED) { attr = Attr( @@ -183,7 +183,7 @@ void main() { ), 3.0 + rand0, vec4(vec3(0.6 + rand7 * 0.4), 0.3), - rotationMatrix(vec3(1,0,0),0) + spin_in_axis(vec3(1,0,0),0) ); } else if (inst_mode == FIREWORK_YELLOW) { attr = Attr( @@ -193,7 +193,7 @@ void main() { ), 3.0 + rand0, vec4(vec3(0.6 + rand7 * 0.4), 0.3), - rotationMatrix(vec3(1,0,0),0) + spin_in_axis(vec3(1,0,0),0) ); } else if (inst_mode == LEAF) { attr = Attr( @@ -203,7 +203,7 @@ void main() { ) + vec3(sin(lifetime), sin(lifetime + 0.7), sin(lifetime * 0.5)) * 2.0, 4, vec4(vec3(0.2 + rand7 * 0.2, 0.2 + (0.5 + rand6 * 0.5) * 0.6, 0), 1), - rotationMatrix(vec3(rand6, rand7, rand8), rand9 * 3 + lifetime * 5) + spin_in_axis(vec3(rand6, rand7, rand8), rand9 * 3 + lifetime * 5) ); } else { attr = Attr( @@ -213,7 +213,7 @@ void main() { ), exp_scale(-0.2), vec4(1), - rotationMatrix(vec3(1,0,0),0) + spin_in_axis(vec3(1,0,0),0) ); } diff --git a/voxygen/src/scene/particle.rs b/voxygen/src/scene/particle.rs index 2586d335a7..be555c1468 100644 --- a/voxygen/src/scene/particle.rs +++ b/voxygen/src/scene/particle.rs @@ -273,12 +273,22 @@ impl ParticleMgr { type BoiFn<'a> = fn(&'a BlocksOfInterest) -> &'a [Vec3]; // blocks, chunk range, emission density, lifetime, particle mode + // + // - blocks: the function to select the blocks of interest that we should emit + // from + // - chunk range: the range, in chunks, that the particles should be generated + // in from the player + // - emission density: the density, per block per second, of the generated + // particles + // - lifetime: the number of seconds that each particle should live for + // - particle mode: the visual mode of the generated particle let particles: &[(BoiFn, usize, f32, f32, ParticleMode)] = &[ (|boi| &boi.leaves, 4, 0.001, 30.0, ParticleMode::Leaf), (|boi| &boi.embers, 2, 20.0, 0.25, ParticleMode::CampfireFire), (|boi| &boi.embers, 8, 3.0, 40.0, ParticleMode::CampfireSmoke), ]; + let mut rng = thread_rng(); for (get_blocks, range, rate, dur, mode) in particles.iter() { for offset in Spiral2d::new().take((*range * 2 + 1).pow(2)) { let chunk_pos = player_chunk + offset; @@ -288,20 +298,21 @@ impl ParticleMgr { let avg_particles = dt * blocks.len() as f32 * *rate; let particle_count = avg_particles.trunc() as usize - + (thread_rng().gen::() < avg_particles.fract()) as usize; + + (rng.gen::() < avg_particles.fract()) as usize; - for _ in 0..particle_count { - let block_pos = - Vec3::from(chunk_pos * TerrainChunk::RECT_SIZE.map(|e| e as i32)) - + blocks.choose(&mut thread_rng()).copied().unwrap(); // Can't fail + self.particles + .resize_with(self.particles.len() + particle_count, || { + let block_pos = + Vec3::from(chunk_pos * TerrainChunk::RECT_SIZE.map(|e| e as i32)) + + blocks.choose(&mut rng).copied().unwrap(); // Can't fail - self.particles.push(Particle::new( - Duration::from_secs_f32(*dur), - time, - *mode, - block_pos.map(|e: i32| e as f32 + thread_rng().gen::()), - )); - } + Particle::new( + Duration::from_secs_f32(*dur), + time, + *mode, + block_pos.map(|e: i32| e as f32 + rng.gen::()), + ) + }) }); } }