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, 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; vec3 wpos = cam_pos.xyz + dir * wpos_dist;
float density = rain_density * rain_occlusion_at(wpos); 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 (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) { 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 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 rain = rain_density_at(pos.xy) * pow(h, 0.1);
float sun = sun_access * get_sun_brightness(); float sun = sun_access * get_sun_brightness();
float energy = pow(rain * sun * min(cdist / 500.0, 1.0), 2.0) * 0.4; 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; uvec4 medium;
ivec4 select_pos; ivec4 select_pos;
vec4 gamma_exposure; vec4 gamma_exposure;
vec4 last_lightning;
float ambiance; float ambiance;
// 0 - FirstPerson // 0 - FirstPerson
// 1 - ThirdPerson // 1 - ThirdPerson

View File

@ -431,13 +431,31 @@ float get_sun_diffuse2(DirectionalLight sun_info, DirectionalLight moon_info, ve
} }
#endif #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 * ( 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) /*+ (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) +
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) + (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 emission
); ) + lightning;
/* light = sun_chroma + moon_chroma + PERSISTENT_AMBIANCE; /* light = sun_chroma + moon_chroma + PERSISTENT_AMBIANCE;
diffuse_light = diffuse_light =

View File

@ -27,6 +27,9 @@ pub enum Outcome {
is_attack: bool, is_attack: bool,
reagent: Option<Reagent>, // How can we better define this? reagent: Option<Reagent>, // How can we better define this?
}, },
Lightning {
pos: Vec3<f32>,
},
ProjectileShot { ProjectileShot {
pos: Vec3<f32>, pos: Vec3<f32>,
body: comp::Body, body: comp::Body,
@ -99,6 +102,8 @@ impl Outcome {
pub fn get_pos(&self) -> Option<Vec3<f32>> { pub fn get_pos(&self) -> Option<Vec3<f32>> {
match self { match self {
Outcome::Explosion { pos, .. } 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::ProjectileShot { pos, .. }
| Outcome::ProjectileHit { pos, .. } | Outcome::ProjectileHit { pos, .. }
| Outcome::Beam { pos, .. } | Outcome::Beam { pos, .. }
@ -113,6 +118,7 @@ impl Outcome {
Outcome::BreakBlock { pos, .. } => Some(pos.map(|e| e as f32 + 0.5)), Outcome::BreakBlock { pos, .. } => Some(pos.map(|e| e as f32 + 0.5)),
Outcome::ExpChange { .. } Outcome::ExpChange { .. }
| Outcome::ComboChange { .. } | Outcome::ComboChange { .. }
| Outcome::Lightning { .. }
| Outcome::SkillPointGain { .. } => None, | Outcome::SkillPointGain { .. } => None,
} }
} }

View File

@ -1,9 +1,12 @@
use common::{ use common::{
event::EventBus,
grid::Grid, grid::Grid,
outcome::Outcome,
resources::TimeOfDay, resources::TimeOfDay,
weather::{Weather, WeatherGrid, CELL_SIZE, CHUNKS_PER_CELL}, weather::{Weather, WeatherGrid, CELL_SIZE, CHUNKS_PER_CELL},
}; };
use noise::{NoiseFn, SuperSimplex, Turbulence}; use noise::{NoiseFn, SuperSimplex, Turbulence};
use rand::prelude::*;
use vek::*; use vek::*;
use world::World; use world::World;
@ -20,6 +23,7 @@ struct WeatherZone {
struct CellConsts { struct CellConsts {
humidity: f32, humidity: f32,
alt: f32,
} }
pub struct WeatherSim { pub struct WeatherSim {
@ -49,8 +53,13 @@ impl WeatherSim {
} }
} }
let average_humid = humid_sum / (CHUNKS_PER_CELL * CHUNKS_PER_CELL) as f32; let average_humid = humid_sum / (CHUNKS_PER_CELL * CHUNKS_PER_CELL) as f32;
let humidity = average_humid.powf(0.2).min(1.0); CellConsts {
CellConsts { humidity } 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<_>>(), .collect::<Vec<_>>(),
), ),
@ -82,7 +91,12 @@ impl WeatherSim {
} }
// Time step is cell size / maximum wind speed // 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 time = time_of_day.0;
let base_nz = Turbulence::new( let base_nz = Turbulence::new(
@ -125,6 +139,12 @@ impl WeatherSim {
rain_nz.get((spos + 1.0).into_array()).powi(3) as f32, rain_nz.get((spos + 1.0).into_array()).powi(3) as f32,
) * 200.0 ) * 200.0
* (1.0 - pressure); * (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 common_ecs::{Origin, Phase, System};
use specs::{Read, Write, WriteExpect}; use specs::{Read, ReadExpect, Write, WriteExpect};
use crate::sys::SysScheduler; use crate::sys::SysScheduler;
@ -15,6 +15,7 @@ impl<'a> System<'a> for Sys {
WriteExpect<'a, WeatherSim>, WriteExpect<'a, WeatherSim>,
WriteExpect<'a, WeatherGrid>, WriteExpect<'a, WeatherGrid>,
Write<'a, SysScheduler<Self>>, Write<'a, SysScheduler<Self>>,
ReadExpect<'a, EventBus<Outcome>>,
); );
const NAME: &'static str = "weather::tick"; const NAME: &'static str = "weather::tick";
@ -23,13 +24,13 @@ impl<'a> System<'a> for Sys {
fn run( fn run(
_job: &mut common_ecs::Job<Self>, _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 scheduler.should_run() {
if grid.size() != sim.size() { if grid.size() != sim.size() {
*grid = WeatherGrid::new(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), PoiseChange(PoiseState),
GroundSlam, GroundSlam,
Utterance(UtteranceKind, VoiceKind), Utterance(UtteranceKind, VoiceKind),
Lightning,
} }
#[derive(Copy, Clone, Debug, PartialEq, Deserialize, Hash, Eq)] #[derive(Copy, Clone, Debug, PartialEq, Deserialize, Hash, Eq)]
@ -432,6 +433,16 @@ impl SfxMgr {
underwater, 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, .. } => { Outcome::GroundSlam { pos, .. } => {
let sfx_trigger_item = triggers.get_key_value(&SfxEvent::GroundSlam); let sfx_trigger_item = triggers.get_key_value(&SfxEvent::GroundSlam);
audio.emit_sfx(sfx_trigger_item, *pos, Some(2.0), underwater); audio.emit_sfx(sfx_trigger_item, *pos, Some(2.0), underwater);

View File

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

View File

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

View File

@ -62,6 +62,17 @@ impl ParticleMgr {
let mut rng = rand::thread_rng(); let mut rng = rand::thread_rng();
match outcome { 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 { Outcome::Explosion {
pos, pos,
power, power,

View File

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