mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Added lightning
This commit is contained in:
parent
622b67d24e
commit
4531a4e3f9
@ -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
BIN
assets/voxygen/audio/sfx/ambient/lightning_1.ogg
(Stored with Git LFS)
Normal file
Binary file not shown.
@ -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) {
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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 =
|
||||||
|
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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),
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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,
|
||||||
|
@ -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,
|
||||||
|
@ -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,
|
||||||
|
@ -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,
|
||||||
|
Loading…
Reference in New Issue
Block a user