diff --git a/client/src/lib.rs b/client/src/lib.rs index f6e2fa5d29..41c9ac5ab4 100644 --- a/client/src/lib.rs +++ b/client/src/lib.rs @@ -46,6 +46,7 @@ pub struct Client { state: State, entity: EcsEntity, view_distance: Option, + loaded_distance: Option, pending_chunks: HashMap, Instant>, } @@ -96,6 +97,7 @@ impl Client { state, entity, view_distance, + loaded_distance: None, pending_chunks: HashMap::new(), }) @@ -144,6 +146,10 @@ impl Client { self.view_distance } + pub fn loaded_distance(&self) -> Option { + self.loaded_distance + } + /// Send a chat message to the server. #[allow(dead_code)] pub fn send_chat(&mut self, msg: String) { @@ -253,7 +259,7 @@ impl Client { if (Vec2::from(chunk_pos) - Vec2::from(key)) .map(|e: i32| e.abs() as u32) .reduce_max() - > view_distance + > view_distance + 1 { chunks_to_remove.push(key); } @@ -264,23 +270,30 @@ impl Client { // Request chunks from the server. // TODO: This is really inefficient. + let mut all_loaded = true; 'outer: for dist in 0..=view_distance as i32 { - for i in chunk_pos.x - dist..=chunk_pos.x + dist { - for j in chunk_pos.y - dist..=chunk_pos.y + dist { + for i in chunk_pos.x - dist..=chunk_pos.x + 1 + dist { + for j in chunk_pos.y - dist..=chunk_pos.y + 1 + dist { let key = Vec2::new(i, j); - if self.state.terrain().get_key(key).is_none() - && !self.pending_chunks.contains_key(&key) - { - if self.pending_chunks.len() < 4 { - self.postbox - .send_message(ClientMsg::TerrainChunkRequest { key }); - self.pending_chunks.insert(key, Instant::now()); - } else { - break 'outer; + if self.state.terrain().get_key(key).is_none() { + if !self.pending_chunks.contains_key(&key) { + if self.pending_chunks.len() < 4 { + self.postbox + .send_message(ClientMsg::TerrainChunkRequest { key }); + self.pending_chunks.insert(key, Instant::now()); + } else { + break 'outer; + } } + + all_loaded = false; } } } + + if all_loaded { + self.loaded_distance = Some((dist - 1).max(0) as u32); + } } // If chunks are taking too long, assume they're no longer pending. diff --git a/server/src/lib.rs b/server/src/lib.rs index d680fe79a4..d6dd165f46 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -312,7 +312,7 @@ impl Server { .map(|e: i32| e.abs()) .reduce_max() as u32; - if dist <= view_distance { + if dist <= view_distance + 1 { self.clients.notify( entity, ServerMsg::TerrainChunkUpdate { @@ -344,7 +344,11 @@ impl Server { .map(|e: i32| e.abs() as u32) .reduce_max(); - if player.view_distance.map(|vd| dist <= vd).unwrap_or(false) { + if player + .view_distance + .map(|vd| dist <= vd + 1) + .unwrap_or(false) + { should_drop = false; break; } diff --git a/voxygen/shaders/include/sky.glsl b/voxygen/shaders/include/sky.glsl index e17e5288d3..ef280ca283 100644 --- a/voxygen/shaders/include/sky.glsl +++ b/voxygen/shaders/include/sky.glsl @@ -22,7 +22,7 @@ vec3 get_sky_color(vec3 dir, float time_of_day) { float fog(vec2 f_pos, vec2 cam_pos) { float dist = distance(f_pos, cam_pos) / view_distance.x; float min_fog = 0.5; - float max_fog = 0.95; + float max_fog = 1.0; return clamp((dist - min_fog) / (max_fog - min_fog), 0.0, 1.0); } diff --git a/voxygen/src/scene/mod.rs b/voxygen/src/scene/mod.rs index f768afa6c6..a76f3a2c9f 100644 --- a/voxygen/src/scene/mod.rs +++ b/voxygen/src/scene/mod.rs @@ -40,6 +40,7 @@ pub struct Scene { skybox: Skybox, postprocess: PostProcess, terrain: Terrain, + loaded_distance: f32, figure_mgr: FigureMgr, } @@ -64,6 +65,7 @@ impl Scene { .unwrap(), }, terrain: Terrain::new(), + loaded_distance: 0.0, figure_mgr: FigureMgr::new(), } } @@ -127,6 +129,10 @@ impl Scene { // Compute camera matrices. 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(1) as f32 * 32.0; + self.loaded_distance = 0.98 * self.loaded_distance + 0.02 * loaded_distance; + // Update global constants. renderer .update_consts( @@ -136,7 +142,7 @@ impl Scene { proj_mat, cam_pos, self.camera.get_focus_pos(), - client.view_distance().unwrap_or(0) as f32 * 32.0, // TODO: No magic numbers + self.loaded_distance, client.state().get_time_of_day(), client.state().get_time(), renderer.get_resolution(),