Added particle explanation, more efficient particle pushing

This commit is contained in:
Joshua Barretto 2020-08-21 09:53:09 +01:00
parent 1b80f05e82
commit db183e607f
2 changed files with 43 additions and 32 deletions

View File

@ -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)
);
}

View File

@ -273,12 +273,22 @@ impl ParticleMgr {
type BoiFn<'a> = fn(&'a BlocksOfInterest) -> &'a [Vec3<i32>];
// 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::<f32>() < avg_particles.fract()) as usize;
+ (rng.gen::<f32>() < 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::<f32>()),
));
}
Particle::new(
Duration::from_secs_f32(*dur),
time,
*mode,
block_pos.map(|e: i32| e as f32 + rng.gen::<f32>()),
)
})
});
}
}