Added lightning

This commit is contained in:
Joshua Barretto 2022-07-08 23:26:33 +01:00
parent 622b67d24e
commit 4531a4e3f9
14 changed files with 101 additions and 10 deletions

View File

@ -1169,5 +1169,11 @@
],
threshold: 1.0,
),
Lightning: (
files: [
"voxygen.audio.sfx.ambient.lightning_1",
],
threshold: 1.0,
),
}
)

BIN
assets/voxygen/audio/sfx/ambient/lightning_1.ogg (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -110,7 +110,7 @@ void main() {
vec3 wpos = cam_pos.xyz + dir * wpos_dist;
float density = rain_density * rain_occlusion_at(wpos);
if (fract(hash(vec4(floor(wall_pos.xyz), 0))) > density) { continue; }
if (fract(hash(vec4(floor(wall_pos.xyz), 0))) >= density) { continue; }
if (wpos_dist > dist) { break; }
if (length((fract(wall_pos.xz) - 0.5)) < 0.1 + pow(max(0.0, wpos_dist - (dist - 0.25)) / 0.25, 4.0) * 0.2) {

View File

@ -300,7 +300,7 @@ vec3 get_cloud_color(vec3 surf_color, vec3 dir, vec3 origin, const float time_of
};
float h = max(0.0, min(pos.z, 900.0 - pos.z) / 450.0);
float rain = rain_density_at(pos.xy) * pow(h, 0.1);
float sun = sun_access * get_sun_brightness();
float energy = pow(rain * sun * min(cdist / 500.0, 1.0), 2.0) * 0.4;

View File

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

View File

@ -431,13 +431,31 @@ float get_sun_diffuse2(DirectionalLight sun_info, DirectionalLight moon_info, ve
}
#endif
float time_since_lightning = tick.x - last_lightning.w;
vec3 lightning = vec3(0.0);
if (time_since_lightning < 5.0) {
vec3 diff = wpos + focus_off.xyz - (last_lightning.xyz + vec3(0, 0, 250));
float dist = length(diff);
lightning = vec3(0.5, 0.8, 1.0)
// Strength
* 1000000
// Flash
* max(0.0, 1.0 - time_since_lightning * 1.0)
// Reverb
* max(sin(time_of_day.x * 0.4), 0.0)
// Direction
* (dot(norm, diff / dist) + 1.0)
// Attenuation
/ pow(50.0 + dist, 2);
}
reflected_light = R_t_r * (
(1.0 - SUN_AMBIANCE) * sun_chroma * sun_shadow * (light_reflection_factor(norm, dir, sun_dir, k_d, k_s, alpha, voxel_norm, voxel_lighting) /*+
light_reflection_factor(norm, dir, normalize(sun_dir + vec3(0.0, 0.1, 0.0)), k_d, k_s, alpha) +
light_reflection_factor(norm, dir, normalize(sun_dir - vec3(0.0, 0.1, 0.0)), k_d, k_s, alpha)*/) +
(1.0 - MOON_AMBIANCE) * moon_chroma * moon_shadow * 1.0 * /*4.0 * */light_reflection_factor(norm, dir, moon_dir, k_d, k_s, alpha, voxel_norm, voxel_lighting) +
emission
);
) + lightning;
/* light = sun_chroma + moon_chroma + PERSISTENT_AMBIANCE;
diffuse_light =

View File

@ -27,6 +27,9 @@ pub enum Outcome {
is_attack: bool,
reagent: Option<Reagent>, // How can we better define this?
},
Lightning {
pos: Vec3<f32>,
},
ProjectileShot {
pos: Vec3<f32>,
body: comp::Body,
@ -99,6 +102,8 @@ impl Outcome {
pub fn get_pos(&self) -> Option<Vec3<f32>> {
match self {
Outcome::Explosion { pos, .. }
// TODO: Include this, but allow it to be sent to clients when outside of the VD
// | Outcome::Lightning { pos }
| Outcome::ProjectileShot { pos, .. }
| Outcome::ProjectileHit { pos, .. }
| Outcome::Beam { pos, .. }
@ -113,6 +118,7 @@ impl Outcome {
Outcome::BreakBlock { pos, .. } => Some(pos.map(|e| e as f32 + 0.5)),
Outcome::ExpChange { .. }
| Outcome::ComboChange { .. }
| Outcome::Lightning { .. }
| Outcome::SkillPointGain { .. } => None,
}
}

View File

@ -1,9 +1,12 @@
use common::{
event::EventBus,
grid::Grid,
outcome::Outcome,
resources::TimeOfDay,
weather::{Weather, WeatherGrid, CELL_SIZE, CHUNKS_PER_CELL},
};
use noise::{NoiseFn, SuperSimplex, Turbulence};
use rand::prelude::*;
use vek::*;
use world::World;
@ -20,6 +23,7 @@ struct WeatherZone {
struct CellConsts {
humidity: f32,
alt: f32,
}
pub struct WeatherSim {
@ -49,8 +53,13 @@ impl WeatherSim {
}
}
let average_humid = humid_sum / (CHUNKS_PER_CELL * CHUNKS_PER_CELL) as f32;
let humidity = average_humid.powf(0.2).min(1.0);
CellConsts { humidity }
CellConsts {
humidity: average_humid.powf(0.2).min(1.0),
alt: world
.sim()
.get_alt_approx(cell_to_wpos_center(p.map(|e| e as i32)))
.unwrap_or(world::CONFIG.sea_level),
}
})
.collect::<Vec<_>>(),
),
@ -82,7 +91,12 @@ impl WeatherSim {
}
// Time step is cell size / maximum wind speed
pub fn tick(&mut self, time_of_day: &TimeOfDay, out: &mut WeatherGrid) {
pub fn tick(
&mut self,
time_of_day: &TimeOfDay,
outcomes: &EventBus<Outcome>,
out: &mut WeatherGrid,
) {
let time = time_of_day.0;
let base_nz = Turbulence::new(
@ -125,6 +139,12 @@ impl WeatherSim {
rain_nz.get((spos + 1.0).into_array()).powi(3) as f32,
) * 200.0
* (1.0 - pressure);
if cell.rain > 0.02 && cell.cloud > 0.05 && thread_rng().gen_bool(0.01) {
outcomes.emit_now(Outcome::Lightning {
pos: wpos.map(|e| e as f32).with_z(self.consts[point].alt),
});
}
}
}
}

View File

@ -1,6 +1,6 @@
use common::{resources::TimeOfDay, weather::WeatherGrid};
use common::{event::EventBus, outcome::Outcome, resources::TimeOfDay, weather::WeatherGrid};
use common_ecs::{Origin, Phase, System};
use specs::{Read, Write, WriteExpect};
use specs::{Read, ReadExpect, Write, WriteExpect};
use crate::sys::SysScheduler;
@ -15,6 +15,7 @@ impl<'a> System<'a> for Sys {
WriteExpect<'a, WeatherSim>,
WriteExpect<'a, WeatherGrid>,
Write<'a, SysScheduler<Self>>,
ReadExpect<'a, EventBus<Outcome>>,
);
const NAME: &'static str = "weather::tick";
@ -23,13 +24,13 @@ impl<'a> System<'a> for Sys {
fn run(
_job: &mut common_ecs::Job<Self>,
(game_time, mut sim, mut grid, mut scheduler): Self::SystemData,
(game_time, mut sim, mut grid, mut scheduler, outcomes): Self::SystemData,
) {
if scheduler.should_run() {
if grid.size() != sim.size() {
*grid = WeatherGrid::new(sim.size());
}
sim.tick(&game_time, &mut grid);
sim.tick(&game_time, &outcomes, &mut grid);
}
}
}

View File

@ -190,6 +190,7 @@ pub enum SfxEvent {
PoiseChange(PoiseState),
GroundSlam,
Utterance(UtteranceKind, VoiceKind),
Lightning,
}
#[derive(Copy, Clone, Debug, PartialEq, Deserialize, Hash, Eq)]
@ -432,6 +433,16 @@ impl SfxMgr {
underwater,
);
},
Outcome::Lightning { pos } => {
let sfx_trigger_item = triggers.get_key_value(&SfxEvent::Lightning);
// TODO: Don't use UI sfx, add a way to control position falloff
audio.emit_ui_sfx(
sfx_trigger_item,
Some(
(1.0 - pos.distance(audio.listener.pos) / 10_000.0).clamped(0.0, 1.0) * 3.0,
),
);
},
Outcome::GroundSlam { pos, .. } => {
let sfx_trigger_item = triggers.get_key_value(&SfxEvent::GroundSlam);
audio.emit_sfx(sfx_trigger_item, *pos, Some(2.0), underwater);

View File

@ -64,6 +64,7 @@ pub struct Globals {
medium: [u32; 4],
select_pos: [i32; 4],
gamma_exposure: [f32; 4],
last_lightning: [f32; 4],
ambiance: f32,
cam_mode: u32,
sprite_render_distance: f32,
@ -108,6 +109,7 @@ impl Globals {
select_pos: Option<Vec3<i32>>,
gamma: f32,
exposure: f32,
last_lightning: (Vec3<f32>, f64),
ambiance: f32,
cam_mode: CameraMode,
sprite_render_distance: f32,
@ -156,6 +158,10 @@ impl Globals {
.unwrap_or_else(Vec4::zero)
.into_array(),
gamma_exposure: [gamma, exposure, 0.0, 0.0],
last_lightning: last_lightning
.0
.with_w(last_lightning.1 as f32)
.into_array(),
ambiance: ambiance.clamped(0.0, 1.0),
cam_mode: cam_mode as u32,
sprite_render_distance,
@ -202,6 +208,7 @@ impl Default for Globals {
None,
1.0,
1.0,
(Vec3::zero(), -1000.0),
1.0,
CameraMode::ThirdPerson,
250.0,

View File

@ -108,6 +108,7 @@ pub struct Scene {
ambient_mgr: AmbientMgr,
integrated_rain_vel: f32,
last_lightning: Option<(Vec3<f32>, f64)>,
}
pub struct SceneData<'a> {
@ -325,6 +326,7 @@ impl Scene {
ambience: ambient::load_ambience_items(),
},
integrated_rain_vel: 0.0,
last_lightning: None,
}
}
@ -426,6 +428,9 @@ impl Scene {
.handle_outcome(outcome, audio, scene_data.client, underwater);
match outcome {
Outcome::Lightning { pos } => {
self.last_lightning = Some((*pos, scene_data.state.get_time()));
},
Outcome::Explosion {
pos,
power,
@ -689,6 +694,7 @@ impl Scene {
self.select_pos.map(|e| e - focus_off.map(|e| e as i32)),
scene_data.gamma,
scene_data.exposure,
self.last_lightning.unwrap_or((Vec3::zero(), -1000.0)),
scene_data.ambiance,
self.camera.get_mode(),
scene_data.sprite_render_distance as f32 - 20.0,

View File

@ -62,6 +62,17 @@ impl ParticleMgr {
let mut rng = rand::thread_rng();
match outcome {
Outcome::Lightning { pos } => {
self.particles.resize_with(self.particles.len() + 400, || {
Particle::new_directed(
Duration::from_secs_f32(rng.gen_range(2.0..3.0)),
time,
ParticleMode::GunPowderSpark,
*pos + Vec3::new(0.0, 0.0, rng.gen_range(250.0..1500.0)),
*pos,
)
});
},
Outcome::Explosion {
pos,
power,

View File

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