Made particle code more rugged

This commit is contained in:
Joshua Barretto 2020-09-03 21:47:34 +01:00
parent 282291c9dc
commit 0adc57e487
3 changed files with 74 additions and 71 deletions

View File

@ -140,15 +140,14 @@ float lights_at(vec3 wpos, vec3 wnorm, vec3 /*cam_to_frag*/view_dir, vec3 mu, ve
float distance_2 = dot(difference, difference);
// float strength = attenuation_strength(difference);// pow(attenuation_strength(difference), 0.6);
// // NOTE: This normalizes strength to 1.0 at the center of the point source.
// float strength = 1.0 / (1.0 + distance_2);
// NOTE: This normalizes strength to 0.25 at the center of the point source.
float strength = 1.0 / (4 + distance_2);
// Multiply the vec3 only once
const float PI = 3.1415926535897932384626433832795;
const float PI_2 = 2 * PI;
float square_factor = /*2.0 * PI_2 * *//*2.0 * */L.light_col.a;
vec3 color = /*srgb_to_linear*/L.light_col.rgb * vec3(1, 1, 1);
vec3 color = /*srgb_to_linear*/L.light_col.rgb;
// // Only access the array once
// Shadow S = shadows[i];

View File

@ -71,6 +71,7 @@ void main() {
max_light += lights_at(f_pos, f_norm, view_dir, k_a, k_d, k_s, alpha, emitted_light, reflected_light);
// Allow particles to glow at night
// TODO: Not this
emitted_light += max(f_col.rgb - 1.0, vec3(0));

View File

@ -282,82 +282,85 @@ impl ParticleMgr {
(e.floor() as i32).div_euclid(sz as i32)
});
type BoiFn<'a> = fn(&'a BlocksOfInterest) -> &'a [Vec3<i32>];
// blocks, chunk range, emission density, lifetime, particle mode, condition
//
// - 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
// - Condition required for emissions
let particles: &[(BoiFn, usize, f32, f32, ParticleMode, fn(&SceneData) -> bool)] = &[
(
|boi| &boi.leaves,
4,
0.001,
30.0,
ParticleMode::Leaf,
|_| true,
),
(
|boi| &boi.embers,
2,
20.0,
0.25,
ParticleMode::CampfireFire,
|_| true,
),
(
|boi| &boi.embers,
8,
3.0,
40.0,
ParticleMode::CampfireSmoke,
|_| true,
),
(
|boi| &boi.reeds,
6,
0.004,
40.0,
ParticleMode::Firefly,
|sd| sd.state.get_day_period().is_dark(),
),
(
|boi| &boi.flowers,
5,
0.002,
40.0,
ParticleMode::Firefly,
|sd| sd.state.get_day_period().is_dark(),
),
(
|boi| &boi.beehives,
3,
0.5,
30.0,
ParticleMode::Bee,
|sd| sd.state.get_day_period().is_light(),
),
struct BlockParticles<'a> {
// The function to select the blocks of interest that we should emit from
blocks: fn(&'a BlocksOfInterest) -> &'a [Vec3<i32>],
// The range, in chunks, that the particles should be generated in from the player
range: usize,
// The emission rate, per block per second, of the generated particles
rate: f32,
// The number of seconds that each particle should live for
lifetime: f32,
// The visual mode of the generated particle
mode: ParticleMode,
// Condition that must be true
cond: fn(&SceneData) -> bool,
}
let particles: &[BlockParticles] = &[
BlockParticles {
blocks: |boi| &boi.leaves,
range: 4,
rate: 0.001,
lifetime: 30.0,
mode: ParticleMode::Leaf,
cond: |_| true,
},
BlockParticles {
blocks: |boi| &boi.embers,
range: 2,
rate: 20.0,
lifetime: 0.25,
mode: ParticleMode::CampfireFire,
cond: |_| true,
},
BlockParticles {
blocks: |boi| &boi.embers,
range: 8,
rate: 3.0,
lifetime: 40.0,
mode: ParticleMode::CampfireSmoke,
cond: |_| true,
},
BlockParticles {
blocks: |boi| &boi.reeds,
range: 6,
rate: 0.004,
lifetime: 40.0,
mode: ParticleMode::Firefly,
cond: |sd| sd.state.get_day_period().is_dark(),
},
BlockParticles {
blocks: |boi| &boi.flowers,
range: 5,
rate: 0.002,
lifetime: 40.0,
mode: ParticleMode::Firefly,
cond: |sd| sd.state.get_day_period().is_dark(),
},
BlockParticles {
blocks: |boi| &boi.beehives,
range: 3,
rate: 0.5,
lifetime: 30.0,
mode: ParticleMode::Bee,
cond: |sd| sd.state.get_day_period().is_light(),
},
];
let mut rng = thread_rng();
for (get_blocks, range, rate, dur, mode, cond) in particles.iter() {
if !cond(scene_data) {
for particles in particles.iter() {
if !(particles.cond)(scene_data) {
continue;
}
for offset in Spiral2d::new().take((*range * 2 + 1).pow(2)) {
for offset in Spiral2d::new().take((particles.range * 2 + 1).pow(2)) {
let chunk_pos = player_chunk + offset;
terrain.get(chunk_pos).map(|chunk_data| {
let blocks = get_blocks(&chunk_data.blocks_of_interest);
let blocks = (particles.blocks)(&chunk_data.blocks_of_interest);
let avg_particles = dt * blocks.len() as f32 * *rate;
let avg_particles = dt * blocks.len() as f32 * particles.rate;
let particle_count = avg_particles.trunc() as usize
+ (rng.gen::<f32>() < avg_particles.fract()) as usize;
@ -368,9 +371,9 @@ impl ParticleMgr {
+ blocks.choose(&mut rng).copied().unwrap(); // Can't fail
Particle::new(
Duration::from_secs_f32(*dur),
Duration::from_secs_f32(particles.lifetime),
time,
*mode,
particles.mode,
block_pos.map(|e: i32| e as f32 + rng.gen::<f32>()),
)
})