diff --git a/assets/voxygen/shaders/include/globals.glsl b/assets/voxygen/shaders/include/globals.glsl index b35fab1228..895492a23a 100644 --- a/assets/voxygen/shaders/include/globals.glsl +++ b/assets/voxygen/shaders/include/globals.glsl @@ -16,6 +16,7 @@ uniform u_globals { // 0 - FirstPerson // 1 - ThirdPerson uint cam_mode; + float sprite_render_distance; }; // Specifies the pattern used in the player dithering @@ -26,4 +27,4 @@ mat4 threshold_matrix = mat4( vec4(16.0 / 17.0, 8.0 / 17.0, 14.0 / 17.0, 6.0 / 17.0) ); float distance_divider = 2; -float shadow_dithering = 0.5; \ No newline at end of file +float shadow_dithering = 0.5; diff --git a/assets/voxygen/shaders/sprite-frag.glsl b/assets/voxygen/shaders/sprite-frag.glsl index 0c08431d52..4b983e5ae7 100644 --- a/assets/voxygen/shaders/sprite-frag.glsl +++ b/assets/voxygen/shaders/sprite-frag.glsl @@ -13,7 +13,6 @@ out vec4 tgt_color; #include #include -const float RENDER_DIST = 180.0; const float FADE_DIST = 32.0; void main() { @@ -35,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) - (RENDER_DIST - FADE_DIST)) / FADE_DIST, 0, 1)); + tgt_color = vec4(color, 1.0 - clamp((distance(focus_pos.xy, f_pos.xy) - (sprite_render_distance - FADE_DIST)) / FADE_DIST, 0, 1)); } diff --git a/assets/voxygen/shaders/sprite-vert.glsl b/assets/voxygen/shaders/sprite-vert.glsl index 45b3d60dea..214b66a460 100644 --- a/assets/voxygen/shaders/sprite-vert.glsl +++ b/assets/voxygen/shaders/sprite-vert.glsl @@ -32,6 +32,7 @@ void main() { vec3 sprite_pos = (inst_mat * vec4(0, 0, 0, 1)).xyz; f_pos = (inst_mat * vec4(v_pos * SCALE, 1)).xyz; + f_pos.z -= 25.0 * pow(distance(focus_pos.xy, f_pos.xy) / view_distance.x, 20.0); // Wind waving f_pos += inst_wind_sway * vec3( diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs index cf1b4a174a..8f59fef80f 100644 --- a/voxygen/src/hud/mod.rs +++ b/voxygen/src/hud/mod.rs @@ -210,6 +210,7 @@ pub enum Event { ToggleMouseYInvert(bool), ToggleSmoothPan(bool), AdjustViewDistance(u32), + AdjustSpriteRenderDistance(u32), AdjustMusicVolume(f32), AdjustSfxVolume(f32), ChangeAudioDevice(String), @@ -1801,6 +1802,9 @@ impl Hud { settings_window::Event::AdjustViewDistance(view_distance) => { events.push(Event::AdjustViewDistance(view_distance)); }, + settings_window::Event::AdjustSpriteRenderDistance(view_distance) => { + events.push(Event::AdjustSpriteRenderDistance(view_distance)); + }, settings_window::Event::CrosshairTransp(crosshair_transp) => { events.push(Event::CrosshairTransp(crosshair_transp)); }, diff --git a/voxygen/src/hud/settings_window.rs b/voxygen/src/hud/settings_window.rs index fac506bc54..d37a053b7f 100644 --- a/voxygen/src/hud/settings_window.rs +++ b/voxygen/src/hud/settings_window.rs @@ -212,6 +212,7 @@ pub enum Event { ToggleMouseYInvert(bool), ToggleSmoothPan(bool), AdjustViewDistance(u32), + AdjustSpriteRenderDistance(u32), AdjustFOV(u16), AdjustGamma(f32), AdjustWindowSize([u16; 2]), @@ -1617,9 +1618,9 @@ impl<'a> Widget for SettingsWindow<'a> { .set(state.ids.gamma_value, ui); // Sprites VD if let Some(new_val) = ImageSlider::discrete( - self.global_state.settings.graphics.view_distance, - 1, - 65, + self.global_state.settings.graphics.sprite_render_distance, + 50, + 500, self.imgs.slider_indicator, self.imgs.slider, ) @@ -1630,7 +1631,7 @@ impl<'a> Widget for SettingsWindow<'a> { .pad_track((5.0, 5.0)) .set(state.ids.sprite_dist_slider, ui) { - events.push(Event::AdjustViewDistance(new_val)); + events.push(Event::AdjustSpriteRenderDistance(new_val)); } Text::new( &self @@ -1645,7 +1646,7 @@ impl<'a> Widget for SettingsWindow<'a> { Text::new(&format!( "{}", - self.global_state.settings.graphics.view_distance + self.global_state.settings.graphics.sprite_render_distance )) .right_from(state.ids.sprite_dist_slider, 8.0) .font_size(self.fonts.cyri.scale(14)) diff --git a/voxygen/src/render/pipelines/mod.rs b/voxygen/src/render/pipelines/mod.rs index a4edd0e598..5ca7182521 100644 --- a/voxygen/src/render/pipelines/mod.rs +++ b/voxygen/src/render/pipelines/mod.rs @@ -29,6 +29,7 @@ gfx_defines! { select_pos: [i32; 4] = "select_pos", gamma: [f32; 4] = "gamma", cam_mode: u32 = "cam_mode", + sprite_render_distance: f32 = "sprite_render_distance", } constant Light { @@ -58,6 +59,7 @@ impl Globals { select_pos: Option>, gamma: f32, cam_mode: CameraMode, + sprite_render_distance: f32, ) -> Self { Self { view_mat: arr_to_mat(view_mat.into_col_array()), @@ -77,6 +79,7 @@ impl Globals { .into_array(), gamma: [gamma; 4], cam_mode: cam_mode as u32, + sprite_render_distance, } } } @@ -98,6 +101,7 @@ impl Default for Globals { None, 1.0, CameraMode::ThirdPerson, + 250.0, ) } } diff --git a/voxygen/src/scene/mod.rs b/voxygen/src/scene/mod.rs index f3b7771e2d..44c55e2617 100644 --- a/voxygen/src/scene/mod.rs +++ b/voxygen/src/scene/mod.rs @@ -76,6 +76,7 @@ pub struct SceneData<'a> { pub thread_pool: &'a uvth::ThreadPool, pub gamma: f32, pub mouse_smoothing: bool, + pub sprite_render_distance: f32, } impl Scene { @@ -353,6 +354,7 @@ impl Scene { self.select_pos, scene_data.gamma, self.camera.get_mode(), + scene_data.sprite_render_distance as f32 - 20.0, )]) .expect("Failed to update global constants"); @@ -385,6 +387,7 @@ impl Scene { state: &State, player_entity: EcsEntity, tick: u64, + scene_data: &SceneData, ) { // Render terrain and figures. self.terrain.render( @@ -425,6 +428,7 @@ impl Scene { &self.lights, &self.shadows, self.camera.get_focus_pos(), + scene_data.sprite_render_distance, ); renderer.render_post_process( diff --git a/voxygen/src/scene/simple.rs b/voxygen/src/scene/simple.rs index 8abf6be9a7..2f53408569 100644 --- a/voxygen/src/scene/simple.rs +++ b/voxygen/src/scene/simple.rs @@ -183,6 +183,7 @@ impl Scene { None, scene_data.gamma, self.camera.get_mode(), + 250.0, )]) { error!("Renderer failed to update: {:?}", err); } diff --git a/voxygen/src/scene/terrain.rs b/voxygen/src/scene/terrain.rs index 5b33dd2cc2..6598fde00b 100644 --- a/voxygen/src/scene/terrain.rs +++ b/voxygen/src/scene/terrain.rs @@ -330,10 +330,12 @@ impl Terrain { let scaled = [1.0, 0.6, 0.4, 0.2]; scaled .iter() - .map(|lod_scale| if *lod_scale == 1.0 { - Vec3::broadcast(1.0) - } else { - lod_axes * *lod_scale + lod_axes.map(|e| if e == 0.0 { 1.0 } else { 0.0 }) + .map(|lod_scale| { + if *lod_scale == 1.0 { + Vec3::broadcast(1.0) + } else { + lod_axes * *lod_scale + lod_axes.map(|e| if e == 0.0 { 1.0 } else { 0.0 }) + } }) .map(|lod_scale| { renderer @@ -2229,6 +2231,7 @@ impl Terrain { lights: &Consts, shadows: &Consts, focus_pos: Vec3, + sprite_render_distance: f32, ) { let focus_chunk = Vec2::from(focus_pos).map2(TerrainChunk::RECT_SIZE, |e: f32, sz| { (e as i32).div_euclid(sz as i32) @@ -2252,22 +2255,21 @@ impl Terrain { // Terrain sprites for (pos, chunk) in chunk_iter.clone() { if chunk.visible { - const SPRITE_RENDER_DISTANCE: f32 = 200.0; - const SPRITE_DETAIL_LOW_DISTANCE: f32 = SPRITE_RENDER_DISTANCE * 0.65; - const SPRITE_DETAIL_MID_DISTANCE: f32 = SPRITE_RENDER_DISTANCE * 0.4; - const SPRITE_DETAIL_HIGH_DISTANCE: f32 = SPRITE_RENDER_DISTANCE * 0.25; + let sprite_detail_low_distance = sprite_render_distance * 0.65; + let sprite_detail_mid_distance = sprite_render_distance * 0.4; + let sprite_detail_high_distance = sprite_render_distance * 0.25; let chunk_center = pos.map2(V::RECT_SIZE, |e, sz: u32| (e as f32 + 0.5) * sz as f32); let dist_sqrd = Vec2::from(focus_pos).distance_squared(chunk_center); - if dist_sqrd < SPRITE_RENDER_DISTANCE.powf(2.0) { + if dist_sqrd < sprite_render_distance.powf(2.0) { for (kind, instances) in &chunk.sprite_instances { renderer.render_sprites( - if dist_sqrd < SPRITE_DETAIL_HIGH_DISTANCE.powf(2.0) { + if dist_sqrd < sprite_detail_high_distance.powf(2.0) { &self.sprite_models[&kind][0] - } else if dist_sqrd < SPRITE_DETAIL_MID_DISTANCE.powf(2.0) { + } else if dist_sqrd < sprite_detail_mid_distance.powf(2.0) { &self.sprite_models[&kind][1] - } else if dist_sqrd < SPRITE_DETAIL_LOW_DISTANCE.powf(2.0) { + } else if dist_sqrd < sprite_detail_low_distance.powf(2.0) { &self.sprite_models[&kind][2] } else { &self.sprite_models[&kind][3] diff --git a/voxygen/src/session.rs b/voxygen/src/session.rs index 25b8f7e1df..9c63cf3895 100644 --- a/voxygen/src/session.rs +++ b/voxygen/src/session.rs @@ -4,7 +4,6 @@ use crate::{ i18n::{i18n_asset_key, VoxygenLocalization}, key_state::KeyState, menu::char_selection::CharSelectionState, - render::Renderer, scene::{camera, Scene, SceneData}, settings::AudioOutput, window::{AnalogGameInput, Event, GameInput}, @@ -111,26 +110,6 @@ impl SessionState { /// Clean up the session (and the client attached to it) after a tick. pub fn cleanup(&mut self) { self.client.borrow_mut().cleanup(); } - - /// Render the session to the screen. - /// - /// This method should be called once per frame. - pub fn render(&mut self, renderer: &mut Renderer) { - // Clear the screen - renderer.clear(); - - // Render the screen using the global renderer - { - let client = self.client.borrow(); - self.scene - .render(renderer, client.state(), client.entity(), client.get_tick()); - } - // Draw the UI to the screen - self.hud.render(renderer, self.scene.globals()); - - // Finish the frame - renderer.flush(); - } } impl PlayState for SessionState { @@ -589,6 +568,10 @@ impl PlayState for SessionState { global_state.settings.graphics.view_distance = view_distance; global_state.settings.save_to_file_warn(); }, + HudEvent::AdjustSpriteRenderDistance(sprite_render_distance) => { + global_state.settings.graphics.sprite_render_distance = sprite_render_distance; + global_state.settings.save_to_file_warn(); + }, HudEvent::CrosshairTransp(crosshair_transp) => { global_state.settings.gameplay.crosshair_transp = crosshair_transp; global_state.settings.save_to_file_warn(); @@ -720,9 +703,6 @@ impl PlayState for SessionState { } } - // Runs if either in a multiplayer server or the singleplayer server is unpaused - if global_state.singleplayer.is_none() - || !global_state.singleplayer.as_ref().unwrap().is_paused() { let client = self.client.borrow(); let scene_data = SceneData { @@ -734,16 +714,30 @@ impl PlayState for SessionState { thread_pool: client.thread_pool(), gamma: global_state.settings.graphics.gamma, mouse_smoothing: global_state.settings.gameplay.smooth_pan_enable, + sprite_render_distance: global_state.settings.graphics.sprite_render_distance as f32, }; - self.scene.maintain( - global_state.window.renderer_mut(), - &mut global_state.audio, - &scene_data, - ); - } - // Render the session. - self.render(global_state.window.renderer_mut()); + // Runs if either in a multiplayer server or the singleplayer server is unpaused + if global_state.singleplayer.is_none() + || !global_state.singleplayer.as_ref().unwrap().is_paused() + { + self.scene.maintain( + global_state.window.renderer_mut(), + &mut global_state.audio, + &scene_data, + ); + } + + let renderer = global_state.window.renderer_mut(); + // Clear the screen + renderer.clear(); + // Render the screen using the global renderer + self.scene.render(renderer, client.state(), client.entity(), client.get_tick(), &scene_data); + // Draw the UI to the screen + self.hud.render(renderer, self.scene.globals()); + // Finish the frame + renderer.flush(); + } // Display the frame on the window. global_state diff --git a/voxygen/src/settings.rs b/voxygen/src/settings.rs index 11ac56aa6c..3c4f44c19a 100644 --- a/voxygen/src/settings.rs +++ b/voxygen/src/settings.rs @@ -548,6 +548,7 @@ impl Default for Log { #[serde(default)] pub struct GraphicsSettings { pub view_distance: u32, + pub sprite_render_distance: u32, pub max_fps: u32, pub fov: u16, pub gamma: f32, @@ -562,6 +563,7 @@ impl Default for GraphicsSettings { fn default() -> Self { Self { view_distance: 10, + sprite_render_distance: 250, max_fps: 60, fov: 50, gamma: 1.0, diff --git a/world/src/civ/mod.rs b/world/src/civ/mod.rs index 49954a02df..1d1515159a 100644 --- a/world/src/civ/mod.rs +++ b/world/src/civ/mod.rs @@ -142,16 +142,12 @@ impl Civs { let mut rng = ctx.reseed().rng; let world_site = match &site.kind { - SiteKind::Settlement => WorldSite::from(Settlement::generate( - wpos, - Some(ctx.sim), - &mut rng, - )), - SiteKind::Dungeon => WorldSite::from(Dungeon::generate( - wpos, - Some(ctx.sim), - &mut rng, - )), + SiteKind::Settlement => { + WorldSite::from(Settlement::generate(wpos, Some(ctx.sim), &mut rng)) + }, + SiteKind::Dungeon => { + WorldSite::from(Dungeon::generate(wpos, Some(ctx.sim), &mut rng)) + }, }; let radius_chunks =