From 5acfe44cbb266dc7b860beb407e10bdef3403e42 Mon Sep 17 00:00:00 2001 From: scott-c Date: Sat, 25 Jul 2020 23:46:45 +0800 Subject: [PATCH] Add toggle particles graphics setting --- assets/voxygen/i18n/en.ron | 1 + assets/voxygen/shaders/include/globals.glsl | 1 - assets/voxygen/shaders/particle-frag.glsl | 2 +- voxygen/src/hud/mod.rs | 5 +- voxygen/src/hud/settings_window.rs | 31 +++++- voxygen/src/render/pipelines/mod.rs | 6 +- voxygen/src/scene/mod.rs | 4 +- voxygen/src/scene/particle.rs | 115 ++++++-------------- voxygen/src/scene/simple.rs | 1 - voxygen/src/session.rs | 17 +-- voxygen/src/settings.rs | 4 +- 11 files changed, 79 insertions(+), 108 deletions(-) diff --git a/assets/voxygen/i18n/en.ron b/assets/voxygen/i18n/en.ron index e57424b780..b3a2004539 100644 --- a/assets/voxygen/i18n/en.ron +++ b/assets/voxygen/i18n/en.ron @@ -297,6 +297,7 @@ magically infused items?"#, "hud.settings.fluid_rendering_mode.cheap": "Cheap", "hud.settings.fluid_rendering_mode.shiny": "Shiny", "hud.settings.cloud_rendering_mode.regular": "Regular", + "hud.settings.particles": "Particles", "hud.settings.fullscreen": "Fullscreen", "hud.settings.save_window_size": "Save window size", diff --git a/assets/voxygen/shaders/include/globals.glsl b/assets/voxygen/shaders/include/globals.glsl index 7436e5c036..895492a23a 100644 --- a/assets/voxygen/shaders/include/globals.glsl +++ b/assets/voxygen/shaders/include/globals.glsl @@ -17,7 +17,6 @@ uniform u_globals { // 1 - ThirdPerson uint cam_mode; float sprite_render_distance; - float particle_render_distance; }; // Specifies the pattern used in the player dithering diff --git a/assets/voxygen/shaders/particle-frag.glsl b/assets/voxygen/shaders/particle-frag.glsl index 3e2ef6b9e6..3d730f7a50 100644 --- a/assets/voxygen/shaders/particle-frag.glsl +++ b/assets/voxygen/shaders/particle-frag.glsl @@ -34,5 +34,5 @@ void main() { vec3 fog_color = get_sky_color(normalize(f_pos - cam_pos.xyz), time_of_day.x, cam_pos.xyz, f_pos, 0.5, true, clouds); vec3 color = mix(mix(surf_color, fog_color, fog_level), clouds.rgb, clouds.a); - tgt_color = vec4(color, 1.0 - clamp((distance(focus_pos.xy, f_pos.xy) - (particle_render_distance - FADE_DIST)) / FADE_DIST, 0, 1)); + tgt_color = vec4(color, 1.0 - clamp((distance(focus_pos.xy, f_pos.xy) - (1000.0 - FADE_DIST)) / FADE_DIST, 0, 1)); } diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs index de2ac1649c..20a48df35e 100644 --- a/voxygen/src/hud/mod.rs +++ b/voxygen/src/hud/mod.rs @@ -269,7 +269,6 @@ pub enum Event { ToggleSmoothPan(bool), AdjustViewDistance(u32), AdjustSpriteRenderDistance(u32), - AdjustParticleRenderDistance(u32), AdjustFigureLoDRenderDistance(u32), AdjustMusicVolume(f32), AdjustSfxVolume(f32), @@ -279,6 +278,7 @@ pub enum Event { ChangeGamma(f32), MapZoom(f64), AdjustWindowSize([u16; 2]), + ToggleParticlesEnabled(bool), ToggleFullscreen, ChangeAaMode(AaMode), ChangeCloudMode(CloudMode), @@ -1911,6 +1911,9 @@ impl Hud { settings_window::Event::ChangeLanguage(language) => { events.push(Event::ChangeLanguage(language)); }, + settings_window::Event::ToggleParticlesEnabled(particles_enabled) => { + events.push(Event::ToggleParticlesEnabled(particles_enabled)); + }, settings_window::Event::ToggleFullscreen => { events.push(Event::ToggleFullscreen); }, diff --git a/voxygen/src/hud/settings_window.rs b/voxygen/src/hud/settings_window.rs index c0b8e42fff..f9e6b7d17b 100644 --- a/voxygen/src/hud/settings_window.rs +++ b/voxygen/src/hud/settings_window.rs @@ -111,6 +111,8 @@ widget_ids! { cloud_mode_list, fluid_mode_text, fluid_mode_list, + particles_button, + particles_label, fullscreen_button, fullscreen_label, save_window_size_button, @@ -232,6 +234,7 @@ pub enum Event { AdjustFOV(u16), AdjustGamma(f32), AdjustWindowSize([u16; 2]), + ToggleParticlesEnabled(bool), ToggleFullscreen, ChangeAaMode(AaMode), ChangeCloudMode(CloudMode), @@ -1845,7 +1848,6 @@ impl<'a> Widget for SettingsWindow<'a> { .color(TEXT_COLOR) .set(state.ids.sprite_dist_text, ui); - Text::new(&format!( "{}", self.global_state.settings.graphics.sprite_render_distance @@ -1899,8 +1901,6 @@ impl<'a> Widget for SettingsWindow<'a> { .color(TEXT_COLOR) .set(state.ids.figure_dist_value, ui); - // TODO: Particle View Distance slider. - // AaMode Text::new(&self.localized_strings.get("hud.settings.antialiasing_mode")) .down_from(state.ids.gamma_slider, 8.0) @@ -2016,11 +2016,34 @@ impl<'a> Widget for SettingsWindow<'a> { events.push(Event::ChangeFluidMode(mode_list[clicked])); } + // Particles + Text::new(&self.localized_strings.get("hud.settings.particles")) + .font_size(self.fonts.cyri.scale(14)) + .font_id(self.fonts.cyri.conrod_id) + .down_from(state.ids.fluid_mode_list, 8.0) + .color(TEXT_COLOR) + .set(state.ids.particles_label, ui); + + let particles_enabled = ToggleButton::new( + self.global_state.settings.graphics.particles_enabled, + self.imgs.checkbox, + self.imgs.checkbox_checked, + ) + .w_h(18.0, 18.0) + .right_from(state.ids.particles_label, 10.0) + .hover_images(self.imgs.checkbox_mo, self.imgs.checkbox_checked_mo) + .press_images(self.imgs.checkbox_press, self.imgs.checkbox_checked) + .set(state.ids.particles_button, ui); + + if self.global_state.settings.graphics.particles_enabled != particles_enabled { + events.push(Event::ToggleParticlesEnabled(particles_enabled)); + } + // Fullscreen Text::new(&self.localized_strings.get("hud.settings.fullscreen")) .font_size(self.fonts.cyri.scale(14)) .font_id(self.fonts.cyri.conrod_id) - .down_from(state.ids.fluid_mode_list, 8.0) + .down_from(state.ids.particles_label, 8.0) .color(TEXT_COLOR) .set(state.ids.fullscreen_label, ui); diff --git a/voxygen/src/render/pipelines/mod.rs b/voxygen/src/render/pipelines/mod.rs index a3e978a70c..f97890626d 100644 --- a/voxygen/src/render/pipelines/mod.rs +++ b/voxygen/src/render/pipelines/mod.rs @@ -1,9 +1,9 @@ pub mod figure; pub mod fluid; +pub mod particle; pub mod postprocess; pub mod skybox; pub mod sprite; -pub mod particle; pub mod terrain; pub mod ui; @@ -30,7 +30,6 @@ gfx_defines! { gamma: [f32; 4] = "gamma", cam_mode: u32 = "cam_mode", sprite_render_distance: f32 = "sprite_render_distance", - particle_render_distance: f32 = "particle_render_distance", } constant Light { @@ -63,7 +62,6 @@ impl Globals { gamma: f32, cam_mode: CameraMode, sprite_render_distance: f32, - particle_render_distance: f32, ) -> Self { Self { view_mat: view_mat.into_col_arrays(), @@ -84,7 +82,6 @@ impl Globals { gamma: [gamma; 4], cam_mode: cam_mode as u32, sprite_render_distance, - particle_render_distance, } } } @@ -107,7 +104,6 @@ impl Default for Globals { 1.0, CameraMode::ThirdPerson, 250.0, - 250.0, ) } } diff --git a/voxygen/src/scene/mod.rs b/voxygen/src/scene/mod.rs index d242239e94..af59657488 100644 --- a/voxygen/src/scene/mod.rs +++ b/voxygen/src/scene/mod.rs @@ -81,7 +81,7 @@ pub struct SceneData<'a> { pub gamma: f32, pub mouse_smoothing: bool, pub sprite_render_distance: f32, - pub particle_render_distance: f32, + pub particles_enabled: bool, pub figure_lod_render_distance: f32, pub is_aiming: bool, } @@ -377,7 +377,6 @@ impl Scene { scene_data.gamma, self.camera.get_mode(), scene_data.sprite_render_distance as f32 - 20.0, - scene_data.particle_render_distance as f32 - 20.0, )]) .expect("Failed to update global constants"); @@ -437,6 +436,7 @@ impl Scene { self.particle_mgr.render( renderer, + scene_data, &self.globals, &self.lights, &self.shadows, diff --git a/voxygen/src/scene/particle.rs b/voxygen/src/scene/particle.rs index 92ef68607e..3a72f92b94 100644 --- a/voxygen/src/scene/particle.rs +++ b/voxygen/src/scene/particle.rs @@ -48,11 +48,9 @@ impl ParticleMgr { ) .0; - let model = renderer + renderer .create_model(mesh) .expect("Failed to create particle model"); - - model }); let insts = Vec::new(); @@ -73,31 +71,37 @@ impl ParticleMgr { pub fn particle_count_visible(&self) -> usize { self.instances.count() } pub fn maintain(&mut self, renderer: &mut Renderer, scene_data: &SceneData) { - let now = Instant::now(); + if scene_data.particles_enabled { + let now = Instant::now(); - // remove dead particles - self.particles.retain(|p| p.alive_until > now); + // remove dead particles + self.particles.retain(|p| p.alive_until > now); - // let zxc = scene_data.particle_render_distance; + self.maintain_body_particles(scene_data); + self.maintain_boost_particles(scene_data); - self.maintain_body_particles(renderer, scene_data); - - self.maintain_boost_particles(renderer, scene_data); + self.upload_particles(renderer); + } else { + self.particles.clear(); + } + } + fn upload_particles(&mut self, renderer: &mut Renderer) { let all_cpu_instances = self .particles .iter() .map(|p| p.instance) .collect::>(); - // TODO: upload just the ones that were created and added to queue, not all of - // them. - self.instances = renderer + // TODO: optimise buffer writes + let gpu_instances = renderer .create_instances(&all_cpu_instances) .expect("Failed to upload particle instances to the GPU!"); + + self.instances = gpu_instances; } - fn maintain_body_particles(&mut self, renderer: &mut Renderer, scene_data: &SceneData) { + fn maintain_body_particles(&mut self, scene_data: &SceneData) { let ecs = scene_data.state.ecs(); for (_i, (_entity, body, pos)) in ( &ecs.entities(), @@ -109,31 +113,21 @@ impl ParticleMgr { { match body { Body::Object(object::Body::CampfireLit) => { - self.maintain_campfirelit_particles(renderer, scene_data, pos) + self.maintain_campfirelit_particles(scene_data, pos) }, Body::Object(object::Body::BoltFire) => { - self.maintain_boltfire_particles(renderer, scene_data, pos) + self.maintain_boltfire_particles(scene_data, pos) }, Body::Object(object::Body::BoltFireBig) => { - self.maintain_boltfirebig_particles(renderer, scene_data, pos) + self.maintain_boltfirebig_particles(scene_data, pos) }, - Body::Object(object::Body::Bomb) => { - self.maintain_bomb_particles(renderer, scene_data, pos) - }, - // Body::Object(object::Body::Pouch) => { - // self.maintain_pouch_particles(renderer, scene_data, pos) - // }, + Body::Object(object::Body::Bomb) => self.maintain_bomb_particles(scene_data, pos), _ => {}, } } } - fn maintain_campfirelit_particles( - &mut self, - renderer: &mut Renderer, - scene_data: &SceneData, - pos: &Pos, - ) { + fn maintain_campfirelit_particles(&mut self, scene_data: &SceneData, pos: &Pos) { let time = scene_data.state.get_time(); let now = Instant::now(); let mut rng = rand::thread_rng(); @@ -149,12 +143,7 @@ impl ParticleMgr { }); } - fn maintain_boltfire_particles( - &mut self, - renderer: &mut Renderer, - scene_data: &SceneData, - pos: &Pos, - ) { + fn maintain_boltfire_particles(&mut self, scene_data: &SceneData, pos: &Pos) { let time = scene_data.state.get_time(); let now = Instant::now(); let mut rng = rand::thread_rng(); @@ -170,12 +159,7 @@ impl ParticleMgr { }); } - fn maintain_boltfirebig_particles( - &mut self, - renderer: &mut Renderer, - scene_data: &SceneData, - pos: &Pos, - ) { + fn maintain_boltfirebig_particles(&mut self, scene_data: &SceneData, pos: &Pos) { let time = scene_data.state.get_time(); let now = Instant::now(); let mut rng = rand::thread_rng(); @@ -205,12 +189,7 @@ impl ParticleMgr { }); } - fn maintain_bomb_particles( - &mut self, - renderer: &mut Renderer, - scene_data: &SceneData, - pos: &Pos, - ) { + fn maintain_bomb_particles(&mut self, scene_data: &SceneData, pos: &Pos) { let time = scene_data.state.get_time(); let now = Instant::now(); let mut rng = rand::thread_rng(); @@ -244,34 +223,7 @@ impl ParticleMgr { }); } - // fn maintain_pouch_particles( - // &mut self, - // renderer: &mut Renderer, - // scene_data: &SceneData, - // pos: &Pos, - // ) { - // let time = scene_data.state.get_time(); - // let now = Instant::now(); - // let mut rng = rand::thread_rng(); - - // let smoke_cpu_insts = vec![ParticleInstance::new( - // time, - // rng.gen(), - // ParticleMode::CampfireSmoke, - // pos.0, - // )]; - - // let smoke_cpu_insts = renderer - // .create_instances(&smoke_cpu_insts) - // .expect("Failed to upload particle instances to the GPU!"); - - // self.particles.push(Particles { - // alive_until: now + Duration::from_secs(1), - // instances: smoke_cpu_insts, - // }); - // } - - fn maintain_boost_particles(&mut self, renderer: &mut Renderer, scene_data: &SceneData) { + fn maintain_boost_particles(&mut self, scene_data: &SceneData) { let state = scene_data.state; let ecs = state.ecs(); let time = state.get_time(); @@ -303,15 +255,18 @@ impl ParticleMgr { pub fn render( &self, renderer: &mut Renderer, + scene_data: &SceneData, globals: &Consts, lights: &Consts, shadows: &Consts, ) { - let model = &self - .model_cache - .get(MODEL_KEY) - .expect("Expected particle model in cache"); + if scene_data.particles_enabled { + let model = &self + .model_cache + .get(MODEL_KEY) + .expect("Expected particle model in cache"); - renderer.render_particles(model, globals, &self.instances, lights, shadows); + renderer.render_particles(model, globals, &self.instances, lights, shadows); + } } } diff --git a/voxygen/src/scene/simple.rs b/voxygen/src/scene/simple.rs index fb620aa0f1..c89ebc6511 100644 --- a/voxygen/src/scene/simple.rs +++ b/voxygen/src/scene/simple.rs @@ -190,7 +190,6 @@ impl Scene { scene_data.gamma, self.camera.get_mode(), 250.0, - 250.0, )]) { error!(?e, "Renderer failed to update"); } diff --git a/voxygen/src/session.rs b/voxygen/src/session.rs index 86ea35b27a..9c5122cee8 100644 --- a/voxygen/src/session.rs +++ b/voxygen/src/session.rs @@ -788,11 +788,6 @@ impl PlayState for SessionState { sprite_render_distance; global_state.settings.save_to_file_warn(); }, - HudEvent::AdjustParticleRenderDistance(particle_render_distance) => { - global_state.settings.graphics.particle_render_distance = - particle_render_distance; - global_state.settings.save_to_file_warn(); - }, HudEvent::AdjustFigureLoDRenderDistance(figure_lod_render_distance) => { global_state.settings.graphics.figure_lod_render_distance = figure_lod_render_distance; @@ -942,6 +937,10 @@ impl PlayState for SessionState { self.voxygen_i18n.log_missing_entries(); self.hud.update_language(self.voxygen_i18n.clone()); }, + HudEvent::ToggleParticlesEnabled(particles_enabled) => { + global_state.settings.graphics.particles_enabled = particles_enabled; + global_state.settings.save_to_file_warn(); + }, HudEvent::ToggleFullscreen => { global_state .window @@ -1006,11 +1005,7 @@ impl PlayState for SessionState { mouse_smoothing: global_state.settings.gameplay.smooth_pan_enable, sprite_render_distance: global_state.settings.graphics.sprite_render_distance as f32, - particle_render_distance: global_state - .settings - .graphics - .particle_render_distance - as f32, + particles_enabled: global_state.settings.graphics.particles_enabled, figure_lod_render_distance: global_state .settings .graphics @@ -1066,7 +1061,7 @@ impl PlayState for SessionState { mouse_smoothing: settings.gameplay.smooth_pan_enable, sprite_render_distance: settings.graphics.sprite_render_distance as f32, figure_lod_render_distance: settings.graphics.figure_lod_render_distance as f32, - particle_render_distance: settings.graphics.particle_render_distance as f32, + particles_enabled: settings.graphics.particles_enabled, is_aiming: self.is_aiming, }; self.scene.render( diff --git a/voxygen/src/settings.rs b/voxygen/src/settings.rs index ef1184c8ee..722b077ae7 100644 --- a/voxygen/src/settings.rs +++ b/voxygen/src/settings.rs @@ -603,7 +603,7 @@ impl Default for Log { pub struct GraphicsSettings { pub view_distance: u32, pub sprite_render_distance: u32, - pub particle_render_distance: u32, + pub particles_enabled: bool, pub figure_lod_render_distance: u32, pub max_fps: u32, pub fov: u16, @@ -620,7 +620,7 @@ impl Default for GraphicsSettings { Self { view_distance: 10, sprite_render_distance: 150, - particle_render_distance: 150, + particles_enabled: true, figure_lod_render_distance: 250, max_fps: 60, fov: 50,