From 8bdbedc10960b3c74607f534f6a34eef9e3ec625 Mon Sep 17 00:00:00 2001 From: Pfauenauge90 <44173739+Pfauenauge90@users.noreply.github.com> Date: Sun, 21 Jul 2019 01:39:47 +0200 Subject: [PATCH 1/8] added bomb, chest and scarecrow models --- assets/voxygen/voxel/object/bomb.vox | Bin 0 -> 58586 bytes assets/voxygen/voxel/object/chest_vines.vox | Bin 0 -> 59380 bytes assets/voxygen/voxel/object/scarecrow.vox | Bin 0 -> 57691 bytes 3 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 assets/voxygen/voxel/object/bomb.vox create mode 100644 assets/voxygen/voxel/object/chest_vines.vox create mode 100644 assets/voxygen/voxel/object/scarecrow.vox diff --git a/assets/voxygen/voxel/object/bomb.vox b/assets/voxygen/voxel/object/bomb.vox new file mode 100644 index 0000000000000000000000000000000000000000..f44d7c1c66e0f30379d98938f9405b10bd6e9ca7 GIT binary patch literal 58586 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 literal 0 HcmV?d00001 diff --git a/assets/voxygen/voxel/object/chest_vines.vox b/assets/voxygen/voxel/object/chest_vines.vox new file mode 100644 index 0000000000000000000000000000000000000000..3827ab54500b18b0d10f9f73c49943798ed9cf5f GIT binary patch literal 59380 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 eSYLC%S$}m_9)B<7but literal 0 HcmV?d00001 diff --git a/assets/voxygen/voxel/object/scarecrow.vox b/assets/voxygen/voxel/object/scarecrow.vox new file mode 100644 index 0000000000000000000000000000000000000000..fa5aa43d121352294e9fd9b1321555dce82210fb GIT binary patch literal 57691 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�NfgZ=h@$zjD4MT`qWP*Q zny-nXc~%t7*G17B5=HY3Q8dqqqWPvMn&(B)d`lF~3!-SgEsEwvQ8a%jisp|*(Yz#z z=8r|uyex|5PejqYB8uiuMbR78-xWpk=b~u7CyM4TMA7`ED4Oq! zqWLRPG_Q%G`D;-$uZyDj8&NcGh@$yhQ8YggMe}!}XnrV)=I=$(yeW$2A4JjoqbQnx z5=HaRqGjz)kJ_?34BnFXC6s%+sPy*Vyq zzA#brYjwXEqIBniTsDsu28;ReV9#+A$L`fN*vb!wpT-CVL*>!2U{KsPQQ-jD;Lt7Q z(y`hU28xr%@+lR@7^l0dn{jTyke?GG2ff)mTB(c$!N$tl!UBX%n;a;NhIcr4%?kXU zg)b6!IA0s~i<85Z(V(bVKI7uxgp+Puu(yPlcziH8ZlE$+@fkkXo9@Y^yZeHphmXFo zL7*j5fw-R2W#H8En@h)noN{3=nA*mk)7!$L4VH?>Hu6*^jsJqFt>wYm)b}N*)Gbp{ z*z3e7CBJ+e!*rCOlamvLf%16JjPSD+gbll&3A>NCb7HixJ?IdZ>#nJTc>nZ4VX$JY vhG55)F6emR#7P`$c@bd8tj(qTzzJ3%uma4Wn;ZeJcsl%$4ira6*&+K2#fv=y literal 0 HcmV?d00001 From 1a23ab5ba87cec836a560c09acf2f1bae6bcabdd Mon Sep 17 00:00:00 2001 From: Pfauenauge90 <44173739+Pfauenauge90@users.noreply.github.com> Date: Sun, 21 Jul 2019 12:57:21 +0200 Subject: [PATCH 2/8] pumpkin model --- assets/voxygen/voxel/object/pumpkin.vox | Bin 0 -> 57041 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 assets/voxygen/voxel/object/pumpkin.vox diff --git a/assets/voxygen/voxel/object/pumpkin.vox b/assets/voxygen/voxel/object/pumpkin.vox new file mode 100644 index 0000000000000000000000000000000000000000..89ca4c074b24a03f26514f45ba9f6aa2c75443ed GIT binary patch literal 57041 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 ixEbuQwKNs4KgvoN%V3(5WQAxkei*6xWG2H7(f Date: Sun, 21 Jul 2019 13:42:45 +0100 Subject: [PATCH 3/8] Added object entities --- client/src/lib.rs | 4 +- common/src/comp/body.rs | 2 + common/src/comp/body/object.rs | 18 +++++ common/src/comp/mod.rs | 2 +- common/src/msg/server.rs | 2 +- common/src/sys/action_state.rs | 2 +- common/src/sys/mod.rs | 3 + common/src/sys/movement.rs | 138 ++++++++++++++++++++++++++++++++ common/src/sys/phys.rs | 91 +-------------------- server/src/cmd.rs | 29 ++++++- server/src/lib.rs | 30 +++++-- voxygen/src/anim/fixture/mod.rs | 1 + voxygen/src/anim/mod.rs | 1 + voxygen/src/anim/object/mod.rs | 39 +++++++++ voxygen/src/scene/figure.rs | 78 ++++++++++++++++-- voxygen/src/scene/mod.rs | 5 +- 16 files changed, 335 insertions(+), 110 deletions(-) create mode 100644 common/src/comp/body/object.rs create mode 100644 common/src/sys/movement.rs create mode 100644 voxygen/src/anim/object/mod.rs diff --git a/client/src/lib.rs b/client/src/lib.rs index a75a4a34fe..a4985eebd5 100644 --- a/client/src/lib.rs +++ b/client/src/lib.rs @@ -403,7 +403,9 @@ impl Client { self.state.write_component(entity, pos); self.state.write_component(entity, vel); self.state.write_component(entity, ori); - self.state.write_component(entity, action_state); + if let Some(a_s) = action_state { + self.state.write_component(entity, a_s); + } } } ServerMsg::TerrainChunkUpdate { key, chunk } => { diff --git a/common/src/comp/body.rs b/common/src/comp/body.rs index 0febc1e799..4c9ae82124 100644 --- a/common/src/comp/body.rs +++ b/common/src/comp/body.rs @@ -1,4 +1,5 @@ pub mod humanoid; +pub mod object; pub mod quadruped; pub mod quadruped_medium; @@ -9,6 +10,7 @@ pub enum Body { Humanoid(humanoid::Body), Quadruped(quadruped::Body), QuadrupedMedium(quadruped_medium::Body), + Object(object::Body), } impl Component for Body { diff --git a/common/src/comp/body/object.rs b/common/src/comp/body/object.rs new file mode 100644 index 0000000000..54133c9f0a --- /dev/null +++ b/common/src/comp/body/object.rs @@ -0,0 +1,18 @@ +use rand::{seq::SliceRandom, thread_rng}; + +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] +pub enum Body { + Bomb, + Scarecrow, + Chest, + Pumpkin, +} + +impl Body { + pub fn random() -> Self { + let mut rng = thread_rng(); + *(&ALL_OBJECTS).choose(&mut rng).unwrap() + } +} + +const ALL_OBJECTS: [Body; 4] = [Body::Bomb, Body::Scarecrow, Body::Chest, Body::Pumpkin]; diff --git a/common/src/comp/mod.rs b/common/src/comp/mod.rs index d7d5c211dd..655177b0ee 100644 --- a/common/src/comp/mod.rs +++ b/common/src/comp/mod.rs @@ -13,7 +13,7 @@ mod stats; pub use action_state::ActionState; pub use agent::Agent; pub use animation::{Animation, AnimationInfo}; -pub use body::{humanoid, quadruped, quadruped_medium, Body}; +pub use body::{humanoid, object, quadruped, quadruped_medium, Body}; pub use controller::Controller; pub use inputs::{ Attacking, CanBuild, Gliding, Jumping, MoveDir, OnGround, Respawning, Rolling, Wielding, diff --git a/common/src/msg/server.rs b/common/src/msg/server.rs index 06c53af40f..636a33326a 100644 --- a/common/src/msg/server.rs +++ b/common/src/msg/server.rs @@ -40,7 +40,7 @@ pub enum ServerMsg { pos: comp::Pos, vel: comp::Vel, ori: comp::Ori, - action_state: comp::ActionState, + action_state: Option, }, TerrainChunkUpdate { key: Vec2, diff --git a/common/src/sys/action_state.rs b/common/src/sys/action_state.rs index d5852bf648..fd8d1ee11a 100644 --- a/common/src/sys/action_state.rs +++ b/common/src/sys/action_state.rs @@ -1,6 +1,6 @@ use crate::{ comp::{ActionState, Attacking, Controller, Gliding, OnGround, Rolling, Vel, Wielding}, - sys::phys::MOVEMENT_THRESHOLD_VEL, + sys::movement::MOVEMENT_THRESHOLD_VEL, }; use specs::{Entities, Join, ReadStorage, System, WriteStorage}; diff --git a/common/src/sys/mod.rs b/common/src/sys/mod.rs index 6507c09f7e..7664b4af8a 100644 --- a/common/src/sys/mod.rs +++ b/common/src/sys/mod.rs @@ -3,6 +3,7 @@ pub mod agent; pub mod animation; pub mod combat; pub mod controller; +pub mod movement; pub mod phys; mod stats; @@ -14,6 +15,7 @@ const AGENT_SYS: &str = "agent_sys"; const CONTROLLER_SYS: &str = "controller_sys"; const ACTION_STATE_SYS: &str = "action_state_sys"; const PHYS_SYS: &str = "phys_sys"; +const MOVEMENT_SYS: &str = "movement_sys"; const COMBAT_SYS: &str = "combat_sys"; const ANIMATION_SYS: &str = "animation_sys"; const STATS_SYS: &str = "stats_sys"; @@ -22,6 +24,7 @@ pub fn add_local_systems(dispatch_builder: &mut DispatcherBuilder) { dispatch_builder.add(agent::Sys, AGENT_SYS, &[]); dispatch_builder.add(controller::Sys, CONTROLLER_SYS, &[AGENT_SYS]); dispatch_builder.add(phys::Sys, PHYS_SYS, &[CONTROLLER_SYS]); + dispatch_builder.add(movement::Sys, MOVEMENT_SYS, &[PHYS_SYS]); dispatch_builder.add( action_state::Sys, ACTION_STATE_SYS, diff --git a/common/src/sys/movement.rs b/common/src/sys/movement.rs new file mode 100644 index 0000000000..a1744d9fa6 --- /dev/null +++ b/common/src/sys/movement.rs @@ -0,0 +1,138 @@ +use crate::{ + comp::{ActionState, Jumping, MoveDir, OnGround, Ori, Pos, Rolling, Stats, Vel, Wielding}, + state::DeltaTime, + terrain::TerrainMap, + vol::{ReadVol, Vox}, +}; +use specs::{Entities, Join, Read, ReadExpect, ReadStorage, System, WriteStorage}; +use vek::*; + +const HUMANOID_ACCEL: f32 = 70.0; +const HUMANOID_SPEED: f32 = 120.0; +const HUMANOID_AIR_ACCEL: f32 = 10.0; +const HUMANOID_AIR_SPEED: f32 = 100.0; +const HUMANOID_JUMP_ACCEL: f32 = 16.5; +const ROLL_ACCEL: f32 = 120.0; +const ROLL_SPEED: f32 = 550.0; +const GLIDE_ACCEL: f32 = 15.0; +const GLIDE_SPEED: f32 = 45.0; +// Gravity is 9.81 * 4, so this makes gravity equal to .15 +const GLIDE_ANTIGRAV: f32 = 9.81 * 3.95; + +pub const MOVEMENT_THRESHOLD_VEL: f32 = 3.0; + +/// This system applies forces and calculates new positions and velocities. +pub struct Sys; +impl<'a> System<'a> for Sys { + type SystemData = ( + Entities<'a>, + ReadExpect<'a, TerrainMap>, + Read<'a, DeltaTime>, + ReadStorage<'a, MoveDir>, + ReadStorage<'a, Stats>, + ReadStorage<'a, ActionState>, + WriteStorage<'a, Jumping>, + WriteStorage<'a, Wielding>, + WriteStorage<'a, Rolling>, + WriteStorage<'a, OnGround>, + WriteStorage<'a, Pos>, + WriteStorage<'a, Vel>, + WriteStorage<'a, Ori>, + ); + + fn run( + &mut self, + ( + entities, + terrain, + dt, + move_dirs, + stats, + action_states, + mut jumpings, + mut wieldings, + mut rollings, + mut on_grounds, + mut positions, + mut velocities, + mut orientations, + ): Self::SystemData, + ) { + // Apply movement inputs + for (entity, stats, a, move_dir, mut pos, mut vel, mut ori) in ( + &entities, + &stats, + &action_states, + move_dirs.maybe(), + &mut positions, + &mut velocities, + &mut orientations, + ) + .join() + { + // Disable while dead TODO: Replace with client states? + if stats.is_dead { + continue; + } + + // Move player according to move_dir + if let Some(move_dir) = move_dir { + vel.0 += Vec2::broadcast(dt.0) + * move_dir.0 + * match (a.on_ground, a.gliding, a.rolling) { + (true, false, false) + if vel.0.magnitude_squared() < HUMANOID_SPEED.powf(2.0) => + { + HUMANOID_ACCEL + } + (false, true, false) + if vel.0.magnitude_squared() < GLIDE_SPEED.powf(2.0) => + { + GLIDE_ACCEL + } + (false, false, false) + if vel.0.magnitude_squared() < HUMANOID_AIR_SPEED.powf(2.0) => + { + HUMANOID_AIR_ACCEL + } + (true, false, true) if vel.0.magnitude_squared() < ROLL_SPEED.powf(2.0) => { + ROLL_ACCEL + } + + _ => 0.0, + }; + } + + // Jump + if jumpings.get(entity).is_some() { + vel.0.z = HUMANOID_JUMP_ACCEL; + jumpings.remove(entity); + } + + // Glide + if a.gliding && vel.0.magnitude_squared() < GLIDE_SPEED.powf(2.0) && vel.0.z < 0.0 { + let _ = wieldings.remove(entity); + let lift = GLIDE_ANTIGRAV + vel.0.z.powf(2.0) * 0.2; + vel.0.z += dt.0 * lift * Vec2::::from(vel.0 * 0.15).magnitude().min(1.0); + } + + // Roll + if let Some(time) = rollings.get_mut(entity).map(|r| &mut r.time) { + let _ = wieldings.remove(entity); + *time += dt.0; + if *time > 0.55 || !a.moving { + rollings.remove(entity); + } + } + + // Set direction based on velocity when on the ground + if Vec2::::from(vel.0).magnitude_squared() > 0.1 { + ori.0 = Lerp::lerp( + ori.0, + vel.0.normalized() * Vec3::new(1.0, 1.0, 0.0), + 10.0 * dt.0, + ); + } + } + } +} diff --git a/common/src/sys/phys.rs b/common/src/sys/phys.rs index e1c0a8b91d..f196a29f9c 100644 --- a/common/src/sys/phys.rs +++ b/common/src/sys/phys.rs @@ -10,19 +10,6 @@ use vek::*; const GRAVITY: f32 = 9.81 * 4.0; const FRIC_GROUND: f32 = 0.15; const FRIC_AIR: f32 = 0.015; -const HUMANOID_ACCEL: f32 = 70.0; -const HUMANOID_SPEED: f32 = 120.0; -const HUMANOID_AIR_ACCEL: f32 = 10.0; -const HUMANOID_AIR_SPEED: f32 = 100.0; -const HUMANOID_JUMP_ACCEL: f32 = 16.5; -const ROLL_ACCEL: f32 = 120.0; -const ROLL_SPEED: f32 = 550.0; -const GLIDE_ACCEL: f32 = 15.0; -const GLIDE_SPEED: f32 = 45.0; -// Gravity is 9.81 * 4, so this makes gravity equal to .15 -const GLIDE_ANTIGRAV: f32 = 9.81 * 3.95; - -pub const MOVEMENT_THRESHOLD_VEL: f32 = 3.0; // Integrates forces, calculates the new velocity based off of the old velocity // dt = delta time @@ -44,12 +31,7 @@ impl<'a> System<'a> for Sys { Entities<'a>, ReadExpect<'a, TerrainMap>, Read<'a, DeltaTime>, - ReadStorage<'a, MoveDir>, - ReadStorage<'a, Stats>, ReadStorage<'a, ActionState>, - WriteStorage<'a, Jumping>, - WriteStorage<'a, Wielding>, - WriteStorage<'a, Rolling>, WriteStorage<'a, OnGround>, WriteStorage<'a, Pos>, WriteStorage<'a, Vel>, @@ -62,12 +44,7 @@ impl<'a> System<'a> for Sys { entities, terrain, dt, - move_dirs, - stats, action_states, - mut jumpings, - mut wieldings, - mut rollings, mut on_grounds, mut positions, mut velocities, @@ -75,81 +52,15 @@ impl<'a> System<'a> for Sys { ): Self::SystemData, ) { // Apply movement inputs - for (entity, stats, a, move_dir, mut pos, mut vel, mut ori) in ( + for (entity, a, mut pos, mut vel, mut ori) in ( &entities, - &stats, &action_states, - move_dirs.maybe(), &mut positions, &mut velocities, &mut orientations, ) .join() { - // Disable while dead TODO: Replace with client states? - if stats.is_dead { - continue; - } - - // Move player according to move_dir - if let Some(move_dir) = move_dir { - vel.0 += Vec2::broadcast(dt.0) - * move_dir.0 - * match (a.on_ground, a.gliding, a.rolling) { - (true, false, false) - if vel.0.magnitude_squared() < HUMANOID_SPEED.powf(2.0) => - { - HUMANOID_ACCEL - } - (false, true, false) - if vel.0.magnitude_squared() < GLIDE_SPEED.powf(2.0) => - { - GLIDE_ACCEL - } - (false, false, false) - if vel.0.magnitude_squared() < HUMANOID_AIR_SPEED.powf(2.0) => - { - HUMANOID_AIR_ACCEL - } - (true, false, true) if vel.0.magnitude_squared() < ROLL_SPEED.powf(2.0) => { - ROLL_ACCEL - } - - _ => 0.0, - }; - } - - // Jump - if jumpings.get(entity).is_some() { - vel.0.z = HUMANOID_JUMP_ACCEL; - jumpings.remove(entity); - } - - // Glide - if a.gliding && vel.0.magnitude_squared() < GLIDE_SPEED.powf(2.0) && vel.0.z < 0.0 { - let _ = wieldings.remove(entity); - let lift = GLIDE_ANTIGRAV + vel.0.z.powf(2.0) * 0.2; - vel.0.z += dt.0 * lift * Vec2::::from(vel.0 * 0.15).magnitude().min(1.0); - } - - // Roll - if let Some(time) = rollings.get_mut(entity).map(|r| &mut r.time) { - let _ = wieldings.remove(entity); - *time += dt.0; - if *time > 0.55 || !a.moving { - rollings.remove(entity); - } - } - - // Set direction based on velocity when on the ground - if Vec2::::from(vel.0).magnitude_squared() > 0.1 { - ori.0 = Lerp::lerp( - ori.0, - vel.0.normalized() * Vec3::new(1.0, 1.0, 0.0), - 10.0 * dt.0, - ); - } - // Integrate forces // Friction is assumed to be a constant dependent on location let friction = 50.0 * if a.on_ground { FRIC_GROUND } else { FRIC_AIR }; diff --git a/server/src/cmd.rs b/server/src/cmd.rs index e5a2bd9f4b..d5723bf2d1 100644 --- a/server/src/cmd.rs +++ b/server/src/cmd.rs @@ -130,7 +130,13 @@ lazy_static! { "{}", "/killnpcs : Kill the NPCs", handle_killnpcs, - ), + ), + ChatCommand::new( + "object", + "{}", + "/object : Spawn a random object", + handle_object, + ), ]; } @@ -444,6 +450,27 @@ fn handle_killnpcs(server: &mut Server, entity: EcsEntity, _args: String, _actio server.clients.notify(entity, ServerMsg::Chat(text)); } +fn handle_object(server: &mut Server, entity: EcsEntity, _args: String, _action: &ChatCommand) { + let pos = server + .state + .ecs() + .read_storage::() + .get(entity) + .copied(); + if let Some(pos) = pos { + server + .create_object(pos, comp::object::Body::random()) + .build(); + server + .clients + .notify(entity, ServerMsg::Chat(format!("Spawned object."))); + } else { + server + .clients + .notify(entity, ServerMsg::Chat(format!("You have no position!"))); + } +} + fn handle_tell(server: &mut Server, entity: EcsEntity, args: String, action: &ChatCommand) { let opt_alias = scan_fmt!(&args, action.arg_fmt, String); match opt_alias { diff --git a/server/src/lib.rs b/server/src/lib.rs index 6958c62b7e..db753cb97f 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -158,6 +158,24 @@ impl Server { .with(comp::ForceUpdate) } + /// Build a static object entity + #[allow(dead_code)] + pub fn create_object( + &mut self, + pos: comp::Pos, + object: comp::object::Body, + ) -> EcsEntityBuilder { + self.state + .ecs_mut() + .create_entity_synced() + .with(pos) + .with(comp::Vel(Vec3::zero())) + .with(comp::Ori(Vec3::unit_y())) + .with(comp::Body::Object(object)) + .with(comp::ActionState::default()) + .with(comp::ForceUpdate) + } + pub fn create_player_character( state: &mut State, entity: EcsEntity, @@ -645,12 +663,12 @@ impl Server { state.write_component(entity, player); // Sync physics - for (&uid, &pos, &vel, &ori, &action_state) in ( + for (&uid, &pos, &vel, &ori, action_state) in ( &state.ecs().read_storage::(), &state.ecs().read_storage::(), &state.ecs().read_storage::(), &state.ecs().read_storage::(), - &state.ecs().read_storage::(), + state.ecs().read_storage::().maybe(), ) .join() { @@ -659,7 +677,7 @@ impl Server { pos, vel, ori, - action_state, + action_state: action_state.copied(), }); } @@ -743,13 +761,13 @@ impl Server { } // Sync physics - for (entity, &uid, &pos, &vel, &ori, &action_state, force_update) in ( + for (entity, &uid, &pos, &vel, &ori, action_state, force_update) in ( &self.state.ecs().entities(), &self.state.ecs().read_storage::(), &self.state.ecs().read_storage::(), &self.state.ecs().read_storage::(), &self.state.ecs().read_storage::(), - &self.state.ecs().read_storage::(), + self.state.ecs().read_storage::().maybe(), self.state.ecs().read_storage::().maybe(), ) .join() @@ -759,7 +777,7 @@ impl Server { pos, vel, ori, - action_state, + action_state: action_state.copied(), }; let state = &self.state; diff --git a/voxygen/src/anim/fixture/mod.rs b/voxygen/src/anim/fixture/mod.rs index 8238f69073..22a2ba2686 100644 --- a/voxygen/src/anim/fixture/mod.rs +++ b/voxygen/src/anim/fixture/mod.rs @@ -1,6 +1,7 @@ use super::Skeleton; use crate::render::FigureBoneData; +#[derive(Clone)] pub struct FixtureSkeleton; impl FixtureSkeleton { diff --git a/voxygen/src/anim/mod.rs b/voxygen/src/anim/mod.rs index cb756fea9e..96df4e6cb7 100644 --- a/voxygen/src/anim/mod.rs +++ b/voxygen/src/anim/mod.rs @@ -1,5 +1,6 @@ pub mod character; pub mod fixture; +pub mod object; pub mod quadruped; pub mod quadrupedmedium; diff --git a/voxygen/src/anim/object/mod.rs b/voxygen/src/anim/object/mod.rs new file mode 100644 index 0000000000..5ff3f185f5 --- /dev/null +++ b/voxygen/src/anim/object/mod.rs @@ -0,0 +1,39 @@ +use super::Skeleton; +use crate::render::FigureBoneData; +use vek::*; + +#[derive(Clone)] +pub struct ObjectSkeleton; + +impl ObjectSkeleton { + pub fn new() -> Self { + Self {} + } +} + +const SCALE: f32 = 1.0 / 11.0; + +impl Skeleton for ObjectSkeleton { + fn compute_matrices(&self) -> [FigureBoneData; 16] { + [ + FigureBoneData::new(Mat4::scaling_3d(Vec3::broadcast(SCALE))), + FigureBoneData::new(Mat4::scaling_3d(Vec3::broadcast(SCALE))), + FigureBoneData::new(Mat4::scaling_3d(Vec3::broadcast(SCALE))), + FigureBoneData::new(Mat4::scaling_3d(Vec3::broadcast(SCALE))), + FigureBoneData::new(Mat4::scaling_3d(Vec3::broadcast(SCALE))), + FigureBoneData::new(Mat4::scaling_3d(Vec3::broadcast(SCALE))), + FigureBoneData::new(Mat4::scaling_3d(Vec3::broadcast(SCALE))), + FigureBoneData::new(Mat4::scaling_3d(Vec3::broadcast(SCALE))), + FigureBoneData::new(Mat4::scaling_3d(Vec3::broadcast(SCALE))), + FigureBoneData::new(Mat4::scaling_3d(Vec3::broadcast(SCALE))), + FigureBoneData::new(Mat4::scaling_3d(Vec3::broadcast(SCALE))), + FigureBoneData::new(Mat4::scaling_3d(Vec3::broadcast(SCALE))), + FigureBoneData::new(Mat4::scaling_3d(Vec3::broadcast(SCALE))), + FigureBoneData::new(Mat4::scaling_3d(Vec3::broadcast(SCALE))), + FigureBoneData::new(Mat4::scaling_3d(Vec3::broadcast(SCALE))), + FigureBoneData::new(Mat4::scaling_3d(Vec3::broadcast(SCALE))), + ] + } + + fn interpolate(&mut self, _target: &Self, _dt: f32) {} +} diff --git a/voxygen/src/scene/figure.rs b/voxygen/src/scene/figure.rs index 3107744615..13d1849c0e 100644 --- a/voxygen/src/scene/figure.rs +++ b/voxygen/src/scene/figure.rs @@ -1,6 +1,6 @@ use crate::{ anim::{ - self, character::CharacterSkeleton, quadruped::QuadrupedSkeleton, + self, character::CharacterSkeleton, object::ObjectSkeleton, quadruped::QuadrupedSkeleton, quadrupedmedium::QuadrupedMediumSkeleton, Animation, Skeleton, SkeletonAttr, }, mesh::Meshable, @@ -11,7 +11,7 @@ use crate::{ use client::Client; use common::{ assets, - comp::{self, humanoid, item::Weapon, quadruped, quadruped_medium, Body}, + comp::{self, humanoid, item::Weapon, object, quadruped, quadruped_medium, Body}, figure::Segment, terrain::TerrainChunkSize, vol::VolSize, @@ -105,6 +105,24 @@ impl FigureModelCache { None, None, ], + Body::Object(object) => [ + Some(Self::load_object(object)), + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + ], }; let skeleton_attr = match body { @@ -493,6 +511,18 @@ impl FigureModelCache { Vec3::new(-2.5, -4.0, -2.5), ) } + + fn load_object(obj: object::Body) -> Mesh { + Self::load_mesh( + match obj { + object::Body::Bomb => "object/bomb.vox", + object::Body::Scarecrow => "object/scarecrow.vox", + object::Body::Chest => "object/chest_vines.vox", + object::Body::Pumpkin => "object/pumpkin.vox", + }, + Vec3::new(-3.5, -3.5, 0.0), + ) + } } pub struct FigureMgr { @@ -500,6 +530,7 @@ pub struct FigureMgr { character_states: HashMap>, quadruped_states: HashMap>, quadruped_medium_states: HashMap>, + object_states: HashMap>, } impl FigureMgr { @@ -509,6 +540,7 @@ impl FigureMgr { character_states: HashMap::new(), quadruped_states: HashMap::new(), quadruped_medium_states: HashMap::new(), + object_states: HashMap::new(), } } @@ -534,7 +566,7 @@ impl FigureMgr { &ecs.read_storage::(), &ecs.read_storage::(), &ecs.read_storage::(), - &ecs.read_storage::(), + ecs.read_storage::().maybe(), ecs.read_storage::().maybe(), ) .join() @@ -556,6 +588,9 @@ impl FigureMgr { Body::QuadrupedMedium(_) => { self.quadruped_medium_states.remove(&entity); } + Body::Object(_) => { + self.object_states.remove(&entity); + } } continue; } else if vd_frac > 1.0 { @@ -584,6 +619,11 @@ impl FigureMgr { .entry(entity) .or_insert_with(|| FigureState::new(renderer, CharacterSkeleton::new())); + let animation_info = match animation_info { + Some(a_i) => a_i, + None => continue, + }; + let target_skeleton = match animation_info.animation { comp::Animation::Idle => anim::character::IdleAnimation::update_skeleton( state.skeleton_mut(), @@ -654,6 +694,11 @@ impl FigureMgr { .entry(entity) .or_insert_with(|| FigureState::new(renderer, QuadrupedSkeleton::new())); + let animation_info = match animation_info { + Some(a_i) => a_i, + None => continue, + }; + let target_skeleton = match animation_info.animation { comp::Animation::Run => anim::quadruped::RunAnimation::update_skeleton( state.skeleton_mut(), @@ -689,6 +734,11 @@ impl FigureMgr { FigureState::new(renderer, QuadrupedMediumSkeleton::new()) }); + let animation_info = match animation_info { + Some(a_i) => a_i, + None => continue, + }; + let target_skeleton = match animation_info.animation { comp::Animation::Run => { anim::quadrupedmedium::RunAnimation::update_skeleton( @@ -722,6 +772,15 @@ impl FigureMgr { state.skeleton.interpolate(&target_skeleton, dt); state.update(renderer, pos.0, ori.0, col, dt); } + Body::Object(_) => { + let state = self + .object_states + .entry(entity) + .or_insert_with(|| FigureState::new(renderer, ObjectSkeleton::new())); + + state.skeleton = state.skeleton_mut().clone(); + state.update(renderer, pos.0, ori.0, col, dt); + } } } @@ -732,6 +791,8 @@ impl FigureMgr { .retain(|entity, _| ecs.entities().is_alive(*entity)); self.quadruped_medium_states .retain(|entity, _| ecs.entities().is_alive(*entity)); + self.object_states + .retain(|entity, _| ecs.entities().is_alive(*entity)); } pub fn render( @@ -752,25 +813,24 @@ impl FigureMgr { .get(client.entity()) .map_or(Vec3::zero(), |pos| pos.0); - for (entity, _, _, _, body, _, _) in ( + for (entity, _, _, _, body, _) in ( &ecs.entities(), &ecs.read_storage::(), &ecs.read_storage::(), &ecs.read_storage::(), &ecs.read_storage::(), - &ecs.read_storage::(), ecs.read_storage::().maybe(), ) .join() // Don't render figures outside the vd - .filter(|(_, pos, _, _, _, _, _)| { + .filter(|(_, pos, _, _, _, _)| { (pos.0 - player_pos) .map2(TerrainChunkSize::SIZE, |d, sz| d.abs() as f32 / sz as f32) .magnitude() < view_distance as f32 }) // Don't render dead entities - .filter(|(_, _, _, _, _, _, stats)| stats.map_or(true, |s| !s.is_dead)) + .filter(|(_, _, _, _, _, stats)| stats.map_or(true, |s| !s.is_dead)) { if let Some((locals, bone_consts)) = match body { Body::Humanoid(_) => self @@ -785,6 +845,10 @@ impl FigureMgr { .quadruped_medium_states .get(&entity) .map(|state| (state.locals(), state.bone_consts())), + Body::Object(_) => self + .object_states + .get(&entity) + .map(|state| (state.locals(), state.bone_consts())), } { let model = &self .model_cache diff --git a/voxygen/src/scene/mod.rs b/voxygen/src/scene/mod.rs index 04c1d1cc25..f8c27ba70b 100644 --- a/voxygen/src/scene/mod.rs +++ b/voxygen/src/scene/mod.rs @@ -117,8 +117,9 @@ impl Scene { // Alter camera position to match player. let tilt = self.camera.get_orientation().y; let dist = self.camera.get_distance(); - self.camera - .set_focus_pos(player_pos + Vec3::unit_z() * (3.0 - tilt.min(0.0) * dist * 0.75)); + self.camera.set_focus_pos( + player_pos + Vec3::unit_z() * (1.2 + dist * 0.15 - tilt.min(0.0) * dist * 0.75), + ); // Tick camera for interpolation. self.camera.update(client.state().get_time()); From 1333ffa7a49e884d27de457454ef9c1950941adf Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Sun, 21 Jul 2019 16:04:36 +0100 Subject: [PATCH 4/8] Added point lights --- voxygen/shaders/figure.frag | 16 ++++++- voxygen/shaders/figure.vert | 10 +++++ voxygen/shaders/include/globals.glsl | 1 + voxygen/shaders/include/light.glsl | 22 ++++++++++ voxygen/shaders/terrain.frag | 16 ++++++- voxygen/shaders/terrain.vert | 10 +++++ voxygen/src/menu/char_selection/scene.rs | 7 +++- voxygen/src/render/mod.rs | 2 +- voxygen/src/render/pipelines/figure.rs | 3 +- voxygen/src/render/pipelines/mod.rs | 53 +++++++++++++++++------- voxygen/src/render/pipelines/terrain.rs | 3 +- voxygen/src/render/renderer.rs | 11 ++++- voxygen/src/scene/figure.rs | 5 ++- voxygen/src/scene/mod.rs | 33 +++++++++++++-- voxygen/src/scene/terrain.rs | 11 +++-- 15 files changed, 171 insertions(+), 32 deletions(-) create mode 100644 voxygen/shaders/include/light.glsl diff --git a/voxygen/shaders/figure.frag b/voxygen/shaders/figure.frag index 20781c3a33..57e776e56e 100644 --- a/voxygen/shaders/figure.frag +++ b/voxygen/shaders/figure.frag @@ -1,7 +1,6 @@ #version 330 core #include -#include in vec3 f_pos; in vec3 f_norm; @@ -23,6 +22,19 @@ uniform u_bones { BoneData bones[16]; }; +struct Light { + vec4 light_pos; + vec4 light_col; +}; + +layout (std140) +uniform u_lights { + Light lights[32]; +}; + +#include +#include + out vec4 tgt_color; void main() { @@ -32,7 +44,7 @@ void main() { vec4(f_norm, 0.0) ).xyz; - vec3 light = get_sun_diffuse(world_norm, time_of_day.x); + vec3 light = get_sun_diffuse(world_norm, time_of_day.x) + light_at(f_pos, f_norm); vec3 surf_color = model_col.rgb * f_col * 2.0 * light; float fog_level = fog(f_pos.xy, focus_pos.xy); diff --git a/voxygen/shaders/figure.vert b/voxygen/shaders/figure.vert index a33dc8004c..9bc98b1a4c 100644 --- a/voxygen/shaders/figure.vert +++ b/voxygen/shaders/figure.vert @@ -22,6 +22,16 @@ uniform u_bones { BoneData bones[16]; }; +struct Light { + vec4 light_pos; + vec4 light_col; +}; + +layout (std140) +uniform u_lights { + Light lights[32]; +}; + out vec3 f_pos; out vec3 f_norm; out vec3 f_col; diff --git a/voxygen/shaders/include/globals.glsl b/voxygen/shaders/include/globals.glsl index a01aa0a71e..cbd7e2e739 100644 --- a/voxygen/shaders/include/globals.glsl +++ b/voxygen/shaders/include/globals.glsl @@ -8,4 +8,5 @@ uniform u_globals { vec4 time_of_day; vec4 tick; vec4 screen_res; + uvec4 light_count; }; diff --git a/voxygen/shaders/include/light.glsl b/voxygen/shaders/include/light.glsl new file mode 100644 index 0000000000..ff7c4089a7 --- /dev/null +++ b/voxygen/shaders/include/light.glsl @@ -0,0 +1,22 @@ +float attenuation_strength(vec3 rpos) { + return 1.0 / (rpos.x * rpos.x + rpos.y * rpos.y + rpos.z * rpos.z); +} + +vec3 light_at(vec3 wpos, vec3 wnorm) { + const float LIGHT_AMBIENCE = 0.1; + + vec3 light = vec3(0); + for (uint i = 0u; i < light_count.x; i ++) { + vec3 light_pos = lights[i].light_pos.xyz; + float strength = attenuation_strength(wpos - light_pos); + + if (strength < 0.001) { + continue; + } + + light += strength + * lights[i].light_col.rgb + * clamp(dot(normalize(light_pos - wpos), wnorm), LIGHT_AMBIENCE, 1.0); + } + return light; +} diff --git a/voxygen/shaders/terrain.frag b/voxygen/shaders/terrain.frag index bb27693733..f7dc38bd98 100644 --- a/voxygen/shaders/terrain.frag +++ b/voxygen/shaders/terrain.frag @@ -1,7 +1,6 @@ #version 330 core #include -#include in vec3 f_pos; flat in uint f_pos_norm; @@ -13,8 +12,21 @@ uniform u_locals { vec3 model_offs; }; +struct Light { + vec4 light_pos; + vec4 light_col; +}; + +layout (std140) +uniform u_lights { + Light lights[32]; +}; + out vec4 tgt_color; +#include +#include + void main() { // Calculate normal from packed data vec3 f_norm; @@ -28,7 +40,7 @@ void main() { f_norm = vec3(0.0, 0.0, 1.0) * norm_dir; } - vec3 light = get_sun_diffuse(f_norm, time_of_day.x) * f_light; + vec3 light = get_sun_diffuse(f_norm, time_of_day.x) * f_light + light_at(f_pos, f_norm); vec3 surf_color = f_col * light; float fog_level = fog(f_pos.xy, focus_pos.xy); diff --git a/voxygen/shaders/terrain.vert b/voxygen/shaders/terrain.vert index 7b1d416925..c07432567b 100644 --- a/voxygen/shaders/terrain.vert +++ b/voxygen/shaders/terrain.vert @@ -10,6 +10,16 @@ uniform u_locals { vec3 model_offs; }; +struct Light { + vec4 light_pos; + vec4 light_col; +}; + +layout (std140) +uniform u_lights { + Light lights[32]; +}; + out vec3 f_pos; flat out uint f_pos_norm; out vec3 f_col; diff --git a/voxygen/src/menu/char_selection/scene.rs b/voxygen/src/menu/char_selection/scene.rs index 739d3dd750..6ec3570cd4 100644 --- a/voxygen/src/menu/char_selection/scene.rs +++ b/voxygen/src/menu/char_selection/scene.rs @@ -5,7 +5,7 @@ use crate::{ Animation, Skeleton, SkeletonAttr, }, render::{ - create_pp_mesh, create_skybox_mesh, Consts, FigurePipeline, Globals, Model, + create_pp_mesh, create_skybox_mesh, Consts, FigurePipeline, Globals, Light, Model, PostProcessLocals, PostProcessPipeline, Renderer, SkyboxLocals, SkyboxPipeline, }, scene::{ @@ -33,6 +33,7 @@ struct PostProcess { pub struct Scene { globals: Consts, + lights: Consts, camera: Camera, skybox: Skybox, @@ -50,6 +51,7 @@ impl Scene { Self { globals: renderer.create_consts(&[Globals::default()]).unwrap(), + lights: renderer.create_consts(&[Light::default(); 32]).unwrap(), camera: Camera::new(resolution.x / resolution.y), skybox: Skybox { @@ -99,6 +101,7 @@ impl Scene { 55800.0, client.state().get_time(), renderer.get_resolution(), + 0, )], ) { error!("Renderer failed to update: {:?}", err); @@ -139,6 +142,7 @@ impl Scene { &self.globals, self.figure_state.locals(), self.figure_state.bone_consts(), + &self.lights, ); renderer.render_figure( @@ -146,6 +150,7 @@ impl Scene { &self.globals, self.backdrop_state.locals(), self.backdrop_state.bone_consts(), + &self.lights, ); renderer.render_post_process( diff --git a/voxygen/src/render/mod.rs b/voxygen/src/render/mod.rs index d9f53e04ae..8a5859c91c 100644 --- a/voxygen/src/render/mod.rs +++ b/voxygen/src/render/mod.rs @@ -22,7 +22,7 @@ pub use self::{ create_quad as create_ui_quad, create_tri as create_ui_tri, Locals as UiLocals, Mode as UiMode, UiPipeline, }, - Globals, + Globals, Light, }, renderer::{Renderer, TgtColorFmt, TgtDepthFmt, WinColorFmt, WinDepthFmt}, texture::Texture, diff --git a/voxygen/src/render/pipelines/figure.rs b/voxygen/src/render/pipelines/figure.rs index 29d4fe8626..6dbd0f2640 100644 --- a/voxygen/src/render/pipelines/figure.rs +++ b/voxygen/src/render/pipelines/figure.rs @@ -1,6 +1,6 @@ use super::{ super::{util::arr_to_mat, Pipeline, TgtColorFmt, TgtDepthFmt}, - Globals, + Globals, Light, }; use gfx::{ self, @@ -37,6 +37,7 @@ gfx_defines! { locals: gfx::ConstantBuffer = "u_locals", globals: gfx::ConstantBuffer = "u_globals", bones: gfx::ConstantBuffer = "u_bones", + lights: gfx::ConstantBuffer = "u_lights", tgt_color: gfx::RenderTarget = "tgt_color", tgt_depth: gfx::DepthTarget = gfx::preset::depth::LESS_EQUAL_WRITE, diff --git a/voxygen/src/render/pipelines/mod.rs b/voxygen/src/render/pipelines/mod.rs index a1f77ffcf8..c5ee05aaf5 100644 --- a/voxygen/src/render/pipelines/mod.rs +++ b/voxygen/src/render/pipelines/mod.rs @@ -25,24 +25,16 @@ gfx_defines! { time_of_day: [f32; 4] = "time_of_day", // TODO: Make this f64. tick: [f32; 4] = "tick", screen_res: [f32; 4] = "screen_res", + light_count: [u32; 4] = "light_count", + } + + constant Light { + pos: [f32; 4] = "light_pos", + col: [f32; 4] = "light_col", } } impl Globals { - /// Create global consts with default values. - pub fn default() -> Self { - Self { - view_mat: arr_to_mat(Mat4::identity().into_col_array()), - proj_mat: arr_to_mat(Mat4::identity().into_col_array()), - cam_pos: [0.0; 4], - focus_pos: [0.0; 4], - view_distance: [0.0; 4], - time_of_day: [0.0; 4], - tick: [0.0; 4], - screen_res: [800.0, 500.0, 0.0, 0.0], - } - } - /// Create global consts from the provided parameters. pub fn new( view_mat: Mat4, @@ -53,6 +45,7 @@ impl Globals { time_of_day: f64, tick: f64, screen_res: Vec2, + light_count: usize, ) -> Self { Self { view_mat: arr_to_mat(view_mat.into_col_array()), @@ -63,6 +56,38 @@ impl Globals { time_of_day: [time_of_day as f32; 4], tick: [tick as f32; 4], screen_res: Vec4::from(screen_res.map(|e| e as f32)).into_array(), + light_count: [light_count as u32; 4], } } } + +impl Default for Globals { + fn default() -> Self { + Self::new( + Mat4::identity(), + Mat4::identity(), + Vec3::zero(), + Vec3::zero(), + 0.0, + 0.0, + 0.0, + Vec2::new(800, 500), + 0, + ) + } +} + +impl Light { + pub fn new(pos: Vec3, col: Rgb, strength: f32) -> Self { + Self { + pos: Vec4::from(pos).into_array(), + col: Rgba::new(col.r, col.g, col.b, strength).into_array(), + } + } +} + +impl Default for Light { + fn default() -> Self { + Self::new(Vec3::zero(), Rgb::zero(), 0.0) + } +} diff --git a/voxygen/src/render/pipelines/terrain.rs b/voxygen/src/render/pipelines/terrain.rs index e3cfaf1900..03372d6461 100644 --- a/voxygen/src/render/pipelines/terrain.rs +++ b/voxygen/src/render/pipelines/terrain.rs @@ -1,6 +1,6 @@ use super::{ super::{Pipeline, TgtColorFmt, TgtDepthFmt}, - Globals, + Globals, Light, }; use gfx::{ self, @@ -30,6 +30,7 @@ gfx_defines! { locals: gfx::ConstantBuffer = "u_locals", globals: gfx::ConstantBuffer = "u_globals", + lights: gfx::ConstantBuffer = "u_lights", tgt_color: gfx::RenderTarget = "tgt_color", tgt_depth: gfx::DepthTarget = gfx::preset::depth::LESS_EQUAL_WRITE, diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs index 94fb819d5d..9151a66fb3 100644 --- a/voxygen/src/render/renderer.rs +++ b/voxygen/src/render/renderer.rs @@ -3,7 +3,7 @@ use super::{ gfx_backend, mesh::Mesh, model::{DynamicModel, Model}, - pipelines::{figure, postprocess, skybox, terrain, ui, Globals}, + pipelines::{figure, postprocess, skybox, terrain, ui, Globals, Light}, texture::Texture, Pipeline, RenderError, }; @@ -82,10 +82,15 @@ impl Renderer { env!("CARGO_MANIFEST_DIR"), "/shaders/include/sky.glsl" )); + let light = include_str!(concat!( + env!("CARGO_MANIFEST_DIR"), + "/shaders/include/light.glsl" + )); let mut include_ctx = IncludeContext::new(); include_ctx.include("globals.glsl", globals); include_ctx.include("sky.glsl", sky); + include_ctx.include("light.glsl", light); // Construct a pipeline for rendering skyboxes let skybox_pipeline = create_pipeline( @@ -389,6 +394,7 @@ impl Renderer { globals: &Consts, locals: &Consts, bones: &Consts, + lights: &Consts, ) { self.encoder.draw( &model.slice, @@ -398,6 +404,7 @@ impl Renderer { locals: locals.buf.clone(), globals: globals.buf.clone(), bones: bones.buf.clone(), + lights: lights.buf.clone(), tgt_color: self.tgt_color_view.clone(), tgt_depth: self.tgt_depth_view.clone(), }, @@ -410,6 +417,7 @@ impl Renderer { model: &Model, globals: &Consts, locals: &Consts, + lights: &Consts, ) { self.encoder.draw( &model.slice, @@ -418,6 +426,7 @@ impl Renderer { vbuf: model.vbuf.clone(), locals: locals.buf.clone(), globals: globals.buf.clone(), + lights: lights.buf.clone(), tgt_color: self.tgt_color_view.clone(), tgt_depth: self.tgt_depth_view.clone(), }, diff --git a/voxygen/src/scene/figure.rs b/voxygen/src/scene/figure.rs index 13d1849c0e..182b40fe1d 100644 --- a/voxygen/src/scene/figure.rs +++ b/voxygen/src/scene/figure.rs @@ -5,7 +5,7 @@ use crate::{ }, mesh::Meshable, render::{ - Consts, FigureBoneData, FigureLocals, FigurePipeline, Globals, Mesh, Model, Renderer, + Consts, FigureBoneData, FigureLocals, FigurePipeline, Globals, Light, Mesh, Model, Renderer, }, }; use client::Client; @@ -800,6 +800,7 @@ impl FigureMgr { renderer: &mut Renderer, client: &mut Client, globals: &Consts, + lights: &Consts, ) { let tick = client.get_tick(); let ecs = client.state().ecs(); @@ -855,7 +856,7 @@ impl FigureMgr { .get_or_create_model(renderer, *body, tick) .0; - renderer.render_figure(model, globals, locals, bone_consts); + renderer.render_figure(model, globals, locals, bone_consts, lights); } else { warn!("Body has no saved figure"); } diff --git a/voxygen/src/scene/mod.rs b/voxygen/src/scene/mod.rs index f8c27ba70b..68b5d5a4e9 100644 --- a/voxygen/src/scene/mod.rs +++ b/voxygen/src/scene/mod.rs @@ -5,18 +5,21 @@ pub mod terrain; use self::{camera::Camera, figure::FigureMgr, terrain::Terrain}; use crate::{ render::{ - create_pp_mesh, create_skybox_mesh, Consts, Globals, Model, PostProcessLocals, + create_pp_mesh, create_skybox_mesh, Consts, Globals, Light, Model, PostProcessLocals, PostProcessPipeline, Renderer, SkyboxLocals, SkyboxPipeline, }, window::Event, }; use client::Client; use common::comp; +use specs::Join; use vek::*; // TODO: Don't hard-code this. const CURSOR_PAN_SCALE: f32 = 0.005; +const LIGHT_DIST_RADIUS: f32 = 64.0; // The distance beyond which lights may not be visible + struct Skybox { model: Model, locals: Consts, @@ -29,6 +32,7 @@ struct PostProcess { pub struct Scene { globals: Consts, + lights: Consts, camera: Camera, skybox: Skybox, @@ -46,6 +50,7 @@ impl Scene { Self { globals: renderer.create_consts(&[Globals::default()]).unwrap(), + lights: renderer.create_consts(&[Light::default(); 32]).unwrap(), camera: Camera::new(resolution.x / resolution.y), skybox: Skybox { @@ -128,9 +133,27 @@ impl Scene { let (view_mat, proj_mat, cam_pos) = self.camera.compute_dependents(client); // Update chunk loaded distance smoothly for nice shader fog - let loaded_distance = client.loaded_distance().unwrap_or(0) as f32 * 32.0; + let loaded_distance = client.loaded_distance().unwrap_or(0) as f32 * 32.0; // TODO: No magic! self.loaded_distance = (0.98 * self.loaded_distance + 0.02 * loaded_distance).max(0.01); + // Update light constants + let mut lights = (&client.state().ecs().read_storage::(),) + .join() + .filter(|(pos,)| { + (pos.0.distance_squared(player_pos) as f32) + < self.loaded_distance.powf(2.0) + LIGHT_DIST_RADIUS + }) + .map(|(pos,)| pos.0) + .map(|pos| Light::new(pos + Vec3::unit_z(), Rgb::broadcast(1.0), 100.0)) // TODO: Don't add 1 to z! + .take(32) + .collect::>(); + lights.sort_by_key(|light| { + Vec3::from(Vec4::from(light.pos)).distance_squared(player_pos) as i32 + }); + renderer + .update_consts(&mut self.lights, &lights) + .expect("Failed to update light constants"); + // Update global constants. renderer .update_consts( @@ -144,6 +167,7 @@ impl Scene { client.state().get_time_of_day(), client.state().get_time(), renderer.get_resolution(), + lights.len(), )], ) .expect("Failed to update global constants"); @@ -171,8 +195,9 @@ impl Scene { renderer.render_skybox(&self.skybox.model, &self.globals, &self.skybox.locals); // Render terrain and figures. - self.terrain.render(renderer, &self.globals); - self.figure_mgr.render(renderer, client, &self.globals); + self.terrain.render(renderer, &self.globals, &self.lights); + self.figure_mgr + .render(renderer, client, &self.globals, &self.lights); renderer.render_post_process( &self.postprocess.model, diff --git a/voxygen/src/scene/terrain.rs b/voxygen/src/scene/terrain.rs index 09cbbbe97e..f1e70c4541 100644 --- a/voxygen/src/scene/terrain.rs +++ b/voxygen/src/scene/terrain.rs @@ -1,6 +1,6 @@ use crate::{ mesh::Meshable, - render::{Consts, Globals, Mesh, Model, Renderer, TerrainLocals, TerrainPipeline}, + render::{Consts, Globals, Light, Mesh, Model, Renderer, TerrainLocals, TerrainPipeline}, }; use client::Client; use common::{ @@ -327,10 +327,15 @@ impl Terrain { } } - pub fn render(&self, renderer: &mut Renderer, globals: &Consts) { + pub fn render( + &self, + renderer: &mut Renderer, + globals: &Consts, + lights: &Consts, + ) { for (_pos, chunk) in &self.chunks { if chunk.visible { - renderer.render_terrain_chunk(&chunk.model, globals, &chunk.locals); + renderer.render_terrain_chunk(&chunk.model, globals, &chunk.locals, lights); } } } From 8df07da2e420f9b786170048a4533ed61efbdcd7 Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Sun, 21 Jul 2019 16:37:41 +0100 Subject: [PATCH 5/8] Fixed light cap --- server/src/lib.rs | 1 + voxygen/src/scene/mod.rs | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/server/src/lib.rs b/server/src/lib.rs index db753cb97f..b7c2389c68 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -172,6 +172,7 @@ impl Server { .with(comp::Vel(Vec3::zero())) .with(comp::Ori(Vec3::unit_y())) .with(comp::Body::Object(object)) + //.with(comp::Stats::new("Objecty McObjectface".to_string())) .with(comp::ActionState::default()) .with(comp::ForceUpdate) } diff --git a/voxygen/src/scene/mod.rs b/voxygen/src/scene/mod.rs index 68b5d5a4e9..68e2460b6b 100644 --- a/voxygen/src/scene/mod.rs +++ b/voxygen/src/scene/mod.rs @@ -18,6 +18,7 @@ use vek::*; // TODO: Don't hard-code this. const CURSOR_PAN_SCALE: f32 = 0.005; +const MAX_LIGHT_COUNT: usize = 32; const LIGHT_DIST_RADIUS: f32 = 64.0; // The distance beyond which lights may not be visible struct Skybox { @@ -145,11 +146,11 @@ impl Scene { }) .map(|(pos,)| pos.0) .map(|pos| Light::new(pos + Vec3::unit_z(), Rgb::broadcast(1.0), 100.0)) // TODO: Don't add 1 to z! - .take(32) .collect::>(); lights.sort_by_key(|light| { Vec3::from(Vec4::from(light.pos)).distance_squared(player_pos) as i32 }); + lights.truncate(MAX_LIGHT_COUNT); renderer .update_consts(&mut self.lights, &lights) .expect("Failed to update light constants"); From b387d14e10acde2f72c43b36d4544e5be7cacea0 Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Sun, 21 Jul 2019 17:15:31 +0100 Subject: [PATCH 6/8] Fixed infinite NPC jumping --- common/src/sys/controller.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/common/src/sys/controller.rs b/common/src/sys/controller.rs index c87436b295..a4f6fcc357 100644 --- a/common/src/sys/controller.rs +++ b/common/src/sys/controller.rs @@ -113,6 +113,9 @@ impl<'a> System<'a> for Sys { let _ = jumpings.insert(entity, Jumping); a.on_ground = false; } + + // Reset the controller ready for the next tick + *controller = Controller::default(); } } } From 044c4d4a2c180c3b32e735ec4758a0fa053be92e Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Sun, 21 Jul 2019 17:50:13 +0100 Subject: [PATCH 7/8] Added LightEmitter component --- common/src/comp/mod.rs | 2 ++ common/src/comp/visual.rs | 21 +++++++++++++++++++++ common/src/msg/ecs_packet.rs | 2 ++ common/src/state.rs | 1 + common/src/sys/controller.rs | 6 +++--- server/src/lib.rs | 2 +- voxygen/src/scene/mod.rs | 16 ++++++++++++---- 7 files changed, 42 insertions(+), 8 deletions(-) create mode 100644 common/src/comp/visual.rs diff --git a/common/src/comp/mod.rs b/common/src/comp/mod.rs index 655177b0ee..25321f555d 100644 --- a/common/src/comp/mod.rs +++ b/common/src/comp/mod.rs @@ -8,6 +8,7 @@ mod inventory; mod phys; mod player; mod stats; +mod visual; // Reexports pub use action_state::ActionState; @@ -22,3 +23,4 @@ pub use inventory::{item, Inventory}; pub use phys::{ForceUpdate, Ori, Pos, Vel}; pub use player::Player; pub use stats::{Dying, HealthSource, Stats}; +pub use visual::LightEmitter; diff --git a/common/src/comp/visual.rs b/common/src/comp/visual.rs new file mode 100644 index 0000000000..df0102b46d --- /dev/null +++ b/common/src/comp/visual.rs @@ -0,0 +1,21 @@ +use specs::{Component, FlaggedStorage, VecStorage}; +use vek::*; + +#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct LightEmitter { + pub col: Rgb, + pub strength: f32, +} + +impl Default for LightEmitter { + fn default() -> Self { + Self { + col: Rgb::one(), + strength: 250.0, + } + } +} + +impl Component for LightEmitter { + type Storage = FlaggedStorage>; +} diff --git a/common/src/msg/ecs_packet.rs b/common/src/msg/ecs_packet.rs index d1d7d25dae..b2f3d8bbbe 100644 --- a/common/src/msg/ecs_packet.rs +++ b/common/src/msg/ecs_packet.rs @@ -24,6 +24,7 @@ sphynx::sum_type! { Player(comp::Player), CanBuild(comp::CanBuild), Stats(comp::Stats), + LightEmitter(comp::LightEmitter), } } // Automatically derive From for EcsCompPhantom @@ -38,6 +39,7 @@ sphynx::sum_type! { Player(PhantomData), CanBuild(PhantomData), Stats(PhantomData), + LightEmitter(PhantomData), } } impl sphynx::CompPacket for EcsCompPacket { diff --git a/common/src/state.rs b/common/src/state.rs index 103c70cb5e..06c6d49fe4 100644 --- a/common/src/state.rs +++ b/common/src/state.rs @@ -130,6 +130,7 @@ impl State { ecs.register_synced::(); ecs.register_synced::(); ecs.register_synced::(); + ecs.register_synced::(); // Register components synced by other means ecs.register::(); diff --git a/common/src/sys/controller.rs b/common/src/sys/controller.rs index a4f6fcc357..e9ae987024 100644 --- a/common/src/sys/controller.rs +++ b/common/src/sys/controller.rs @@ -9,7 +9,7 @@ pub struct Sys; impl<'a> System<'a> for Sys { type SystemData = ( Entities<'a>, - ReadStorage<'a, Controller>, + WriteStorage<'a, Controller>, ReadStorage<'a, Stats>, ReadStorage<'a, Vel>, WriteStorage<'a, ActionState>, @@ -26,7 +26,7 @@ impl<'a> System<'a> for Sys { &mut self, ( entities, - controllers, + mut controllers, stats, velocities, mut action_states, @@ -41,7 +41,7 @@ impl<'a> System<'a> for Sys { ) { for (entity, controller, stats, vel, mut a) in ( &entities, - &controllers, + &mut controllers, &stats, &velocities, // Although this is changed, it is only kept for this system diff --git a/server/src/lib.rs b/server/src/lib.rs index b7c2389c68..e9e6bb5909 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -172,7 +172,7 @@ impl Server { .with(comp::Vel(Vec3::zero())) .with(comp::Ori(Vec3::unit_y())) .with(comp::Body::Object(object)) - //.with(comp::Stats::new("Objecty McObjectface".to_string())) + .with(comp::LightEmitter::default()) .with(comp::ActionState::default()) .with(comp::ForceUpdate) } diff --git a/voxygen/src/scene/mod.rs b/voxygen/src/scene/mod.rs index 68e2460b6b..9aee0f750e 100644 --- a/voxygen/src/scene/mod.rs +++ b/voxygen/src/scene/mod.rs @@ -138,14 +138,22 @@ impl Scene { self.loaded_distance = (0.98 * self.loaded_distance + 0.02 * loaded_distance).max(0.01); // Update light constants - let mut lights = (&client.state().ecs().read_storage::(),) + let mut lights = ( + &client.state().ecs().read_storage::(), + &client.state().ecs().read_storage::(), + ) .join() - .filter(|(pos,)| { + .filter(|(pos, _)| { (pos.0.distance_squared(player_pos) as f32) < self.loaded_distance.powf(2.0) + LIGHT_DIST_RADIUS }) - .map(|(pos,)| pos.0) - .map(|pos| Light::new(pos + Vec3::unit_z(), Rgb::broadcast(1.0), 100.0)) // TODO: Don't add 1 to z! + .map(|(pos, light_emitter)| { + Light::new( + pos.0 + Vec3::unit_z(), + light_emitter.col, + light_emitter.strength, + ) + }) // TODO: Don't add 1 to z! .collect::>(); lights.sort_by_key(|light| { Vec3::from(Vec4::from(light.pos)).distance_squared(player_pos) as i32 From 41fefb7ebceaf18236181257e05671383266ecb3 Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Sun, 21 Jul 2019 18:57:25 +0100 Subject: [PATCH 8/8] Moved lighting uniforms into light.glsl --- voxygen/shaders/figure.frag | 10 ---------- voxygen/shaders/figure.vert | 10 ---------- voxygen/shaders/include/light.glsl | 10 ++++++++++ voxygen/shaders/terrain.frag | 10 ---------- voxygen/shaders/terrain.vert | 10 ---------- 5 files changed, 10 insertions(+), 40 deletions(-) diff --git a/voxygen/shaders/figure.frag b/voxygen/shaders/figure.frag index 57e776e56e..d797e12032 100644 --- a/voxygen/shaders/figure.frag +++ b/voxygen/shaders/figure.frag @@ -22,16 +22,6 @@ uniform u_bones { BoneData bones[16]; }; -struct Light { - vec4 light_pos; - vec4 light_col; -}; - -layout (std140) -uniform u_lights { - Light lights[32]; -}; - #include #include diff --git a/voxygen/shaders/figure.vert b/voxygen/shaders/figure.vert index 9bc98b1a4c..a33dc8004c 100644 --- a/voxygen/shaders/figure.vert +++ b/voxygen/shaders/figure.vert @@ -22,16 +22,6 @@ uniform u_bones { BoneData bones[16]; }; -struct Light { - vec4 light_pos; - vec4 light_col; -}; - -layout (std140) -uniform u_lights { - Light lights[32]; -}; - out vec3 f_pos; out vec3 f_norm; out vec3 f_col; diff --git a/voxygen/shaders/include/light.glsl b/voxygen/shaders/include/light.glsl index ff7c4089a7..43380077fe 100644 --- a/voxygen/shaders/include/light.glsl +++ b/voxygen/shaders/include/light.glsl @@ -1,3 +1,13 @@ +struct Light { + vec4 light_pos; + vec4 light_col; +}; + +layout (std140) +uniform u_lights { + Light lights[32]; +}; + float attenuation_strength(vec3 rpos) { return 1.0 / (rpos.x * rpos.x + rpos.y * rpos.y + rpos.z * rpos.z); } diff --git a/voxygen/shaders/terrain.frag b/voxygen/shaders/terrain.frag index f7dc38bd98..75bc338d6f 100644 --- a/voxygen/shaders/terrain.frag +++ b/voxygen/shaders/terrain.frag @@ -12,16 +12,6 @@ uniform u_locals { vec3 model_offs; }; -struct Light { - vec4 light_pos; - vec4 light_col; -}; - -layout (std140) -uniform u_lights { - Light lights[32]; -}; - out vec4 tgt_color; #include diff --git a/voxygen/shaders/terrain.vert b/voxygen/shaders/terrain.vert index c07432567b..7b1d416925 100644 --- a/voxygen/shaders/terrain.vert +++ b/voxygen/shaders/terrain.vert @@ -10,16 +10,6 @@ uniform u_locals { vec3 model_offs; }; -struct Light { - vec4 light_pos; - vec4 light_col; -}; - -layout (std140) -uniform u_lights { - Light lights[32]; -}; - out vec3 f_pos; flat out uint f_pos_norm; out vec3 f_col;