Fix light animations so they are removed when the light turns off.

This commit is contained in:
Joshua Yanovski 2020-07-30 13:22:42 +02:00
parent 7e0f4bcbf0
commit ba54307540
5 changed files with 51 additions and 14 deletions

View File

@ -170,6 +170,7 @@ widget_ids! {
time,
entity_count,
num_chunks,
num_lights,
num_figures,
// Game Version
@ -235,6 +236,7 @@ pub struct DebugInfo {
pub velocity: Option<comp::Vel>,
pub ori: Option<comp::Ori>,
pub num_chunks: u32,
pub num_lights: u32,
pub num_visible_chunks: u32,
pub num_shadow_chunks: u32,
pub num_figures: u32,
@ -1404,13 +1406,21 @@ impl Hud {
.font_size(self.fonts.cyri.scale(14))
.set(self.ids.num_chunks, ui_widgets);
// Number of lights
Text::new(&format!("Lights: {}", debug_info.num_lights,))
.color(TEXT_COLOR)
.down_from(self.ids.num_chunks, 5.0)
.font_id(self.fonts.cyri.conrod_id)
.font_size(self.fonts.cyri.scale(14))
.set(self.ids.num_lights, ui_widgets);
// Number of figures
Text::new(&format!(
"Figures: {} ({} visible)",
debug_info.num_figures, debug_info.num_figures_visible,
))
.color(TEXT_COLOR)
.down_from(self.ids.num_chunks, 5.0)
.down_from(self.ids.num_lights, 5.0)
.font_id(self.fonts.cyri.conrod_id)
.font_size(self.fonts.cyri.scale(14))
.set(self.ids.num_figures, ui_widgets);

View File

@ -34,8 +34,12 @@ impl<T: Copy + gfx::traits::Pod> Consts<T> {
vals: &[T],
offset: usize,
) -> Result<(), RenderError> {
encoder
.update_buffer(&self.buf, vals, offset)
.map_err(RenderError::UpdateError)
if vals.len() > 0 {
encoder
.update_buffer(&self.buf, vals, offset)
.map_err(RenderError::UpdateError)
} else {
Ok(())
}
}
}

View File

@ -41,7 +41,7 @@ use core::{
};
use guillotiere::AtlasAllocator;
use hashbrown::HashMap;
use specs::{Entity as EcsEntity, Join, WorldExt};
use specs::{Entity as EcsEntity, Join, LazyUpdate, WorldExt};
use treeculler::{BVol, BoundingSphere};
use vek::*;
@ -365,6 +365,7 @@ impl FigureMgr {
}
}
let dt = ecs.fetch::<DeltaTime>().0;
let updater = ecs.read_resource::<LazyUpdate>();
for (entity, waypoint, light_emitter_opt, light_anim) in (
&ecs.entities(),
ecs.read_storage::<common::comp::Waypoint>().maybe(),
@ -377,7 +378,7 @@ impl FigureMgr {
if let Some(emitter) = light_emitter_opt {
(
emitter.col,
if emitter.strength.is_finite() {
if emitter.strength.is_normal() {
emitter.strength
} else {
0.0
@ -394,7 +395,7 @@ impl FigureMgr {
if let Some(state) = self.states.character_states.get(&entity) {
light_anim.offset = state.lantern_offset;
}
if !light_anim.strength.is_finite() {
if !light_anim.strength.is_normal() {
light_anim.strength = 0.0;
}
if animated {
@ -408,6 +409,18 @@ impl FigureMgr {
light_anim.strength = target_strength;
light_anim.col = target_col;
}
// NOTE: We add `LIGHT_EPSILON` because if we wait for numbers to become
// equal to target (or even within a subnormal), it will take a minimum
// of 30 seconds for a light to fully turn off (for initial
// strength ≥ 1), which prevents optimizations (particularly those that
// can kick in with zero lights).
const LIGHT_EPSILON: f32 = 0.0001;
if (light_anim.strength - target_strength).abs() < LIGHT_EPSILON {
light_anim.strength = target_strength;
if light_anim.strength == 0.0 {
updater.remove::<LightAnimation>(entity);
}
}
}
}

View File

@ -304,6 +304,9 @@ impl Scene {
/// Get a reference to the scene's terrain.
pub fn terrain(&self) -> &Terrain<TerrainChunk> { &self.terrain }
/// Get a reference to the scene's lights.
pub fn lights(&self) -> &Vec<Light> { &self.light_data }
/// Get a reference to the scene's figure manager.
pub fn figure_mgr(&self) -> &FigureMgr { &self.figure_mgr }
@ -466,9 +469,11 @@ impl Scene {
.read_storage::<comp::LightAnimation>(),
)
.join()
.filter(|(pos, _, _, _)| {
(pos.0.distance_squared(player_pos) as f32)
< loaded_distance.powf(2.0) + LIGHT_DIST_RADIUS
.filter(|(pos, _, _, light_anim)| {
light_anim.col != Rgb::zero()
&& light_anim.strength > 0.0
&& (pos.0.distance_squared(player_pos) as f32)
< loaded_distance.powf(2.0) + LIGHT_DIST_RADIUS
})
.map(|(pos, ori, interpolated, light_anim)| {
// Use interpolated values if they are available
@ -1435,8 +1440,10 @@ impl Scene {
// would instead have this as an extension.
if renderer.render_mode().shadow.is_map() && (is_daylight || self.light_data.len() > 0) {
// Set up shadow mapping.
renderer.start_shadows();
if is_daylight {
// Set up shadow mapping.
renderer.start_shadows();
}
// Render terrain shadows.
self.terrain.render_shadows(
@ -1462,8 +1469,10 @@ impl Scene {
scene_data.figure_lod_render_distance,
);
// Flush shadows.
renderer.flush_shadows();
if is_daylight {
// Flush shadows.
renderer.flush_shadows();
}
}
let lod = self.lod.get_data();

View File

@ -697,6 +697,7 @@ impl PlayState for SessionState {
.get(self.client.borrow().entity())
.cloned(),
num_chunks: self.scene.terrain().chunk_count() as u32,
num_lights: self.scene.lights().len() as u32,
num_visible_chunks: self.scene.terrain().visible_chunk_count() as u32,
num_shadow_chunks: self.scene.terrain().shadow_chunk_count() as u32,
num_figures: self.scene.figure_mgr().figure_count() as u32,