From ca4a0e7bc127febbb89bdba2302c0b8b0245e80e Mon Sep 17 00:00:00 2001
From: Joshua Barretto <joshua.s.barretto@gmail.com>
Date: Wed, 5 Jun 2019 16:22:06 +0100
Subject: [PATCH] Added proper VD fog

---
 Cargo.lock                                  |  1 +
 common/Cargo.toml                           |  1 +
 common/src/terrain/chonk.rs                 | 39 +++++++++++++++++++--
 common/src/vol.rs                           |  8 ++++-
 common/src/volumes/chunk.rs                 | 12 +++++++
 common/src/volumes/dyna.rs                  | 13 +++++++
 common/src/volumes/vol_map_2d.rs            | 21 +++++++----
 common/src/volumes/vol_map_3d.rs            | 10 +++---
 voxygen/shaders/figure.frag                 |  9 ++++-
 voxygen/shaders/figure.vert                 | 11 +++---
 voxygen/shaders/include/sky.glsl            | 27 ++++++++++++++
 voxygen/shaders/postprocess.frag            |  2 +-
 voxygen/shaders/skybox.frag                 | 22 +-----------
 voxygen/shaders/terrain.frag                | 14 ++++----
 voxygen/src/anim/character/run.rs           |  4 +--
 voxygen/src/menu/main/start_singleplayer.rs |  2 +-
 voxygen/src/mesh/terrain.rs                 | 20 +++++------
 voxygen/src/render/renderer.rs              |  2 +-
 voxygen/src/scene/camera.rs                 |  2 +-
 voxygen/src/singleplayer.rs                 |  5 ++-
 20 files changed, 153 insertions(+), 72 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 8bc98412fb..6c16661e04 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2582,6 +2582,7 @@ version = "0.2.0"
 dependencies = [
  "bincode 1.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "dot_vox 4.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "image 0.21.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
diff --git a/common/Cargo.toml b/common/Cargo.toml
index ddb7f68de2..92245e75b3 100644
--- a/common/Cargo.toml
+++ b/common/Cargo.toml
@@ -23,3 +23,4 @@ rand = "0.6.5"
 rayon = "1.0"
 lazy_static = "1.3"
 lz4-compress = "0.1"
+fxhash = "0.2"
diff --git a/common/src/terrain/chonk.rs b/common/src/terrain/chonk.rs
index 4373d378c5..919a97c94d 100644
--- a/common/src/terrain/chonk.rs
+++ b/common/src/terrain/chonk.rs
@@ -3,6 +3,7 @@ use crate::{
     vol::{BaseVol, ReadVol, VolSize, WriteVol},
     volumes::chunk::{Chunk, ChunkErr},
 };
+use fxhash::FxHashMap;
 use serde_derive::{Deserialize, Serialize};
 use std::{collections::HashMap, ops::Add};
 use vek::*;
@@ -117,6 +118,40 @@ impl ReadVol for Chonk {
             }
         }
     }
+
+    #[inline(always)]
+    unsafe fn get_unchecked(&self, pos: Vec3<i32>) -> &Block {
+        if pos.z < self.z_offset {
+            // Below the terrain
+            &self.below
+        } else if pos.z >= self.z_offset + SUB_CHUNK_HEIGHT as i32 * self.sub_chunks.len() as i32 {
+            // Above the terrain
+            &self.above
+        } else {
+            // Within the terrain
+
+            let sub_chunk_idx = self.sub_chunk_idx(pos.z);
+
+            match &self.sub_chunks[sub_chunk_idx] {
+                // Can't fail
+                SubChunk::Homogeneous(block) => block,
+                SubChunk::Hash(cblock, map) => {
+                    let rpos = pos
+                        - Vec3::unit_z()
+                            * (self.z_offset + sub_chunk_idx as i32 * SUB_CHUNK_HEIGHT as i32);
+
+                    map.get(&rpos.map(|e| e as u8)).unwrap_or(cblock)
+                }
+                SubChunk::Heterogeneous(chunk) => {
+                    let rpos = pos
+                        - Vec3::unit_z()
+                            * (self.z_offset + sub_chunk_idx as i32 * SUB_CHUNK_HEIGHT as i32);
+
+                    chunk.get_unchecked(rpos)
+                }
+            }
+        }
+    }
 }
 
 impl WriteVol for Chonk {
@@ -140,7 +175,7 @@ impl WriteVol for Chonk {
             // Can't fail
             SubChunk::Homogeneous(cblock) if block == *cblock => Ok(()),
             SubChunk::Homogeneous(cblock) => {
-                let mut map = HashMap::new();
+                let mut map = FxHashMap::default();
                 map.insert(rpos.map(|e| e as u8), block);
 
                 self.sub_chunks[sub_chunk_idx] = SubChunk::Hash(*cblock, map);
@@ -186,7 +221,7 @@ impl WriteVol for Chonk {
 #[derive(Debug, Clone, Serialize, Deserialize)]
 pub enum SubChunk {
     Homogeneous(Block),
-    Hash(Block, HashMap<Vec3<u8>, Block>),
+    Hash(Block, FxHashMap<Vec3<u8>, Block>),
     Heterogeneous(Chunk<Block, TerrainChunkSize, ()>),
 }
 
diff --git a/common/src/vol.rs b/common/src/vol.rs
index 3a063a6de5..6b800d8793 100644
--- a/common/src/vol.rs
+++ b/common/src/vol.rs
@@ -1,4 +1,5 @@
 use crate::ray::{Ray, RayUntil};
+use std::fmt::Debug;
 use vek::*;
 
 /// A voxel.
@@ -18,7 +19,7 @@ pub trait Vox: Sized {
 /// A volume that contains voxel data.
 pub trait BaseVol {
     type Vox: Vox;
-    type Err;
+    type Err: Debug;
 }
 
 // Utility types
@@ -73,6 +74,11 @@ pub trait ReadVol: BaseVol {
     #[inline(always)]
     fn get(&self, pos: Vec3<i32>) -> Result<&Self::Vox, Self::Err>;
 
+    #[inline(always)]
+    unsafe fn get_unchecked(&self, pos: Vec3<i32>) -> &Self::Vox {
+        self.get(pos).unwrap()
+    }
+
     fn ray(&self, from: Vec3<f32>, to: Vec3<f32>) -> Ray<Self, fn(&Self::Vox) -> bool>
     where
         Self: Sized,
diff --git a/common/src/volumes/chunk.rs b/common/src/volumes/chunk.rs
index 4e61190b9c..e395a762ef 100644
--- a/common/src/volumes/chunk.rs
+++ b/common/src/volumes/chunk.rs
@@ -40,6 +40,13 @@ impl<V: Vox, S: VolSize, M> Chunk<V, S, M> {
             None
         }
     }
+
+    /// Used to transform a voxel position in the volume into its corresponding index
+    /// in the voxel array.
+    #[inline(always)]
+    fn idx_for_unchecked(pos: Vec3<i32>) -> usize {
+        (pos.x * S::SIZE.y as i32 * S::SIZE.z as i32 + pos.y * S::SIZE.z as i32 + pos.z) as usize
+    }
 }
 
 impl<V: Vox, S: VolSize, M> BaseVol for Chunk<V, S, M> {
@@ -61,6 +68,11 @@ impl<V: Vox, S: VolSize, M> ReadVol for Chunk<V, S, M> {
             .and_then(|idx| self.vox.get(idx))
             .ok_or(ChunkErr::OutOfBounds)
     }
+
+    #[inline(always)]
+    unsafe fn get_unchecked(&self, pos: Vec3<i32>) -> &V {
+        self.vox.get_unchecked(Self::idx_for_unchecked(pos))
+    }
 }
 
 impl<V: Vox, S: VolSize, M> WriteVol for Chunk<V, S, M> {
diff --git a/common/src/volumes/dyna.rs b/common/src/volumes/dyna.rs
index 9c0968dbc7..51d6d111d8 100644
--- a/common/src/volumes/dyna.rs
+++ b/common/src/volumes/dyna.rs
@@ -32,6 +32,13 @@ impl<V: Vox, M> Dyna<V, M> {
             None
         }
     }
+
+    /// Used to transform a voxel position in the volume into its corresponding index
+    /// in the voxel array.
+    #[inline(always)]
+    fn idx_for_unchecked(sz: Vec3<u32>, pos: Vec3<i32>) -> usize {
+        (pos.x * sz.y as i32 * sz.z as i32 + pos.y * sz.z as i32 + pos.z) as usize
+    }
 }
 
 impl<V: Vox, M> BaseVol for Dyna<V, M> {
@@ -53,6 +60,12 @@ impl<V: Vox, M> ReadVol for Dyna<V, M> {
             .and_then(|idx| self.vox.get(idx))
             .ok_or(DynaErr::OutOfBounds)
     }
+
+    #[inline(always)]
+    unsafe fn get_unchecked(&self, pos: Vec3<i32>) -> &V {
+        self.vox
+            .get_unchecked(Self::idx_for_unchecked(self.sz, pos))
+    }
 }
 
 impl<V: Vox, M> WriteVol for Dyna<V, M> {
diff --git a/common/src/volumes/vol_map_2d.rs b/common/src/volumes/vol_map_2d.rs
index b552778a04..de35ceb3f3 100644
--- a/common/src/volumes/vol_map_2d.rs
+++ b/common/src/volumes/vol_map_2d.rs
@@ -6,8 +6,10 @@ use crate::{
         dyna::{Dyna, DynaErr},
     },
 };
+use fxhash::FxHashMap;
 use std::{
     collections::{hash_map, HashMap},
+    fmt::Debug,
     marker::PhantomData,
     sync::Arc,
 };
@@ -26,7 +28,7 @@ pub enum VolMap2dErr<V: BaseVol> {
 // M = Chunk metadata
 #[derive(Clone)]
 pub struct VolMap2d<V: BaseVol, S: VolSize> {
-    chunks: HashMap<Vec2<i32>, Arc<V>>,
+    chunks: FxHashMap<Vec2<i32>, Arc<V>>,
     phantom: PhantomData<S>,
 }
 
@@ -50,12 +52,12 @@ impl<V: BaseVol, S: VolSize> VolMap2d<V, S> {
     }
 }
 
-impl<V: BaseVol, S: VolSize> BaseVol for VolMap2d<V, S> {
+impl<V: BaseVol + Debug, S: VolSize> BaseVol for VolMap2d<V, S> {
     type Vox = V::Vox;
     type Err = VolMap2dErr<V>;
 }
 
-impl<V: BaseVol + ReadVol, S: VolSize> ReadVol for VolMap2d<V, S> {
+impl<V: BaseVol + ReadVol + Debug, S: VolSize> ReadVol for VolMap2d<V, S> {
     #[inline(always)]
     fn get(&self, pos: Vec3<i32>) -> Result<&V::Vox, VolMap2dErr<V>> {
         let ck = Self::chunk_key(pos);
@@ -67,11 +69,18 @@ impl<V: BaseVol + ReadVol, S: VolSize> ReadVol for VolMap2d<V, S> {
                 chunk.get(co).map_err(|err| VolMap2dErr::ChunkErr(err))
             })
     }
+
+    #[inline(always)]
+    unsafe fn get_unchecked(&self, pos: Vec3<i32>) -> &V::Vox {
+        let ck = Self::chunk_key(pos);
+        let co = Self::chunk_offs(pos);
+        self.chunks.get(&ck).unwrap().get_unchecked(co)
+    }
 }
 
 // TODO: This actually breaks the API: samples are supposed to have an offset of zero!
 // TODO: Should this be changed, perhaps?
-impl<I: Into<Aabr<i32>>, V: BaseVol + ReadVol, S: VolSize> SampleVol<I> for VolMap2d<V, S> {
+impl<I: Into<Aabr<i32>>, V: BaseVol + ReadVol + Debug, S: VolSize> SampleVol<I> for VolMap2d<V, S> {
     type Sample = VolMap2d<V, S>;
 
     /// Take a sample of the terrain by cloning the voxels within the provided range.
@@ -99,7 +108,7 @@ impl<I: Into<Aabr<i32>>, V: BaseVol + ReadVol, S: VolSize> SampleVol<I> for VolM
     }
 }
 
-impl<V: BaseVol + WriteVol + Clone, S: VolSize + Clone> WriteVol for VolMap2d<V, S> {
+impl<V: BaseVol + WriteVol + Clone + Debug, S: VolSize + Clone> WriteVol for VolMap2d<V, S> {
     #[inline(always)]
     fn set(&mut self, pos: Vec3<i32>, vox: V::Vox) -> Result<(), VolMap2dErr<V>> {
         let ck = Self::chunk_key(pos);
@@ -122,7 +131,7 @@ impl<V: BaseVol, S: VolSize> VolMap2d<V, S> {
             .reduce_and()
         {
             Ok(Self {
-                chunks: HashMap::new(),
+                chunks: FxHashMap::default(),
                 phantom: PhantomData,
             })
         } else {
diff --git a/common/src/volumes/vol_map_3d.rs b/common/src/volumes/vol_map_3d.rs
index 3d8f2b0ba0..8d03b1f487 100644
--- a/common/src/volumes/vol_map_3d.rs
+++ b/common/src/volumes/vol_map_3d.rs
@@ -6,7 +6,7 @@ use crate::{
         dyna::{Dyna, DynaErr},
     },
 };
-use std::{collections::HashMap, marker::PhantomData, sync::Arc};
+use std::{collections::HashMap, fmt::Debug, marker::PhantomData, sync::Arc};
 use vek::*;
 
 #[derive(Debug)]
@@ -45,12 +45,12 @@ impl<V: BaseVol, S: VolSize> VolMap3d<V, S> {
     }
 }
 
-impl<V: BaseVol, S: VolSize> BaseVol for VolMap3d<V, S> {
+impl<V: BaseVol + Debug, S: VolSize> BaseVol for VolMap3d<V, S> {
     type Vox = V::Vox;
     type Err = VolMap3dErr<V>;
 }
 
-impl<V: BaseVol + ReadVol, S: VolSize> ReadVol for VolMap3d<V, S> {
+impl<V: BaseVol + ReadVol + Debug, S: VolSize> ReadVol for VolMap3d<V, S> {
     #[inline(always)]
     fn get(&self, pos: Vec3<i32>) -> Result<&V::Vox, VolMap3dErr<V>> {
         let ck = Self::chunk_key(pos);
@@ -66,7 +66,7 @@ impl<V: BaseVol + ReadVol, S: VolSize> ReadVol for VolMap3d<V, S> {
 
 // TODO: This actually breaks the API: samples are supposed to have an offset of zero!
 // TODO: Should this be changed, perhaps?
-impl<I: Into<Aabb<i32>>, V: BaseVol + ReadVol, S: VolSize> SampleVol<I> for VolMap3d<V, S> {
+impl<I: Into<Aabb<i32>>, V: BaseVol + ReadVol + Debug, S: VolSize> SampleVol<I> for VolMap3d<V, S> {
     type Sample = VolMap3d<V, S>;
 
     /// Take a sample of the terrain by cloning the voxels within the provided range.
@@ -95,7 +95,7 @@ impl<I: Into<Aabb<i32>>, V: BaseVol + ReadVol, S: VolSize> SampleVol<I> for VolM
     }
 }
 
-impl<V: BaseVol + WriteVol + Clone, S: VolSize + Clone> WriteVol for VolMap3d<V, S> {
+impl<V: BaseVol + WriteVol + Clone + Debug, S: VolSize + Clone> WriteVol for VolMap3d<V, S> {
     #[inline(always)]
     fn set(&mut self, pos: Vec3<i32>, vox: V::Vox) -> Result<(), VolMap3dErr<V>> {
         let ck = Self::chunk_key(pos);
diff --git a/voxygen/shaders/figure.frag b/voxygen/shaders/figure.frag
index 9f35b6b04a..e68dbb4e5d 100644
--- a/voxygen/shaders/figure.frag
+++ b/voxygen/shaders/figure.frag
@@ -1,6 +1,7 @@
 #version 330 core
 
 #include <globals.glsl>
+#include <sky.glsl>
 
 in vec3 f_pos;
 in vec3 f_norm;
@@ -37,5 +38,11 @@ void main() {
 
 	float sun_diffuse = dot(sun_dir, world_norm) * 0.5;
 
-	tgt_color = model_col * vec4(f_col * (ambient + sun_diffuse), 1.0);
+	vec3 surf_color = model_col.rgb * f_col * (ambient + sun_diffuse);
+
+	float fog_level = fog(f_pos.xy, cam_pos.xy);
+	vec3 fog_color = get_sky_color(normalize(f_pos - cam_pos.xyz), time_of_day.x);
+	vec3 color = mix(surf_color, fog_color, fog_level);
+
+	tgt_color = vec4(color, 1.0);
 }
diff --git a/voxygen/shaders/figure.vert b/voxygen/shaders/figure.vert
index 4db80ee7c4..a33dc8004c 100644
--- a/voxygen/shaders/figure.vert
+++ b/voxygen/shaders/figure.vert
@@ -28,15 +28,12 @@ out vec3 f_col;
 flat out uint f_bone_idx;
 
 void main() {
-	f_pos = v_pos;
+	f_pos = (model_mat *
+		bones[v_bone_idx].bone_mat *
+		vec4(v_pos, 1)).xyz;
 	f_norm = v_norm;
 	f_col = v_col;
 	f_bone_idx = v_bone_idx;
 
-	gl_Position =
-		proj_mat *
-		view_mat *
-		model_mat *
-		bones[v_bone_idx].bone_mat *
-		vec4(v_pos, 1);
+	gl_Position = proj_mat * view_mat * vec4(f_pos, 1);
 }
diff --git a/voxygen/shaders/include/sky.glsl b/voxygen/shaders/include/sky.glsl
index 8b13789179..e17e5288d3 100644
--- a/voxygen/shaders/include/sky.glsl
+++ b/voxygen/shaders/include/sky.glsl
@@ -1 +1,28 @@
+const float PI = 3.141592;
 
+vec3 get_sky_color(vec3 dir, float time_of_day) {
+	const float TIME_FACTOR = (PI * 2.0) / (3600.0 * 24.0);
+
+	const vec3 SKY_TOP    = vec3(0.1, 0.5, 1.0);
+	const vec3 SKY_BOTTOM = vec3(0.025, 0.08, 0.2);
+
+	const vec3 SUN_HALO_COLOR = vec3(1.0, 0.7, 0.5);
+	const vec3 SUN_SURF_COLOR = vec3(1.0, 0.9, 0.35) * 200.0;
+
+	float sun_angle_rad = time_of_day * TIME_FACTOR;
+	vec3 sun_dir = vec3(sin(sun_angle_rad), 0.0, cos(sun_angle_rad));
+
+	vec3 sun_halo = pow(max(dot(dir, sun_dir), 0.0), 8.0) * SUN_HALO_COLOR;
+	vec3 sun_surf = pow(max(dot(dir, sun_dir) - 0.0045, 0.0), 1000.0) * SUN_SURF_COLOR;
+	vec3 sun_light = sun_halo + sun_surf;
+
+	return mix(SKY_BOTTOM, SKY_TOP, (dir.z + 1.0) / 2.0) + sun_light;
+}
+
+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;
+
+	return clamp((dist - min_fog) / (max_fog - min_fog), 0.0, 1.0);
+}
diff --git a/voxygen/shaders/postprocess.frag b/voxygen/shaders/postprocess.frag
index 8eda152c57..62bd919f91 100644
--- a/voxygen/shaders/postprocess.frag
+++ b/voxygen/shaders/postprocess.frag
@@ -171,5 +171,5 @@ void main() {
 	//hsva_color.z = 1.0 - 1.0 / (1.0 * hsva_color.z + 1.0);
 	vec4 final_color = vec4(hsv2rgb(hsva_color.rgb), hsva_color.a);
 
-	tgt_color = vec4(final_color.rgb, 0.5);
+	tgt_color = vec4(final_color.rgb, 1);
 }
diff --git a/voxygen/shaders/skybox.frag b/voxygen/shaders/skybox.frag
index 986a3434fb..7cabdd09ec 100644
--- a/voxygen/shaders/skybox.frag
+++ b/voxygen/shaders/skybox.frag
@@ -1,6 +1,7 @@
 #version 330 core
 
 #include <globals.glsl>
+#include <sky.glsl>
 
 in vec3 f_pos;
 
@@ -11,27 +12,6 @@ uniform u_locals {
 
 out vec4 tgt_color;
 
-const float PI = 3.141592;
-
-vec3 get_sky_color(vec3 dir, float time_of_day) {
-	const float TIME_FACTOR = (PI * 2.0) / (3600.0 * 24.0);
-
-	const vec3 SKY_TOP    = vec3(0.1, 0.5, 1.0);
-	const vec3 SKY_BOTTOM = vec3(0.025, 0.08, 0.2);
-
-	const vec3 SUN_HALO_COLOR = vec3(1.0, 0.7, 0.5);
-	const vec3 SUN_SURF_COLOR = vec3(1.0, 0.9, 0.35) * 200.0;
-
-	float sun_angle_rad = time_of_day * TIME_FACTOR;
-	vec3 sun_dir = vec3(sin(sun_angle_rad), 0.0, cos(sun_angle_rad));
-
-	vec3 sun_halo = pow(max(dot(dir, sun_dir), 0.0), 8.0) * SUN_HALO_COLOR;
-	vec3 sun_surf = pow(max(dot(dir, sun_dir) - 0.0045, 0.0), 1000.0) * SUN_SURF_COLOR;
-	vec3 sun_light = sun_halo + sun_surf;
-
-	return mix(SKY_BOTTOM, SKY_TOP, (dir.z + 1.0) / 2.0) + sun_light;
-}
-
 void main() {
 	tgt_color = vec4(get_sky_color(normalize(f_pos), time_of_day.x), 1.0);
 }
diff --git a/voxygen/shaders/terrain.frag b/voxygen/shaders/terrain.frag
index ac07bd0ef9..93a08fe02b 100644
--- a/voxygen/shaders/terrain.frag
+++ b/voxygen/shaders/terrain.frag
@@ -1,6 +1,7 @@
 #version 330 core
 
 #include <globals.glsl>
+#include <sky.glsl>
 
 in vec3 f_pos;
 flat in uint f_pos_norm;
@@ -14,11 +15,6 @@ uniform u_locals {
 
 out vec4 tgt_color;
 
-float fog() {
-	float half_vd = 0.95 * view_distance.x / 2.0;
-	return clamp(distance(f_pos, cam_pos.xyz) / half_vd - 1.0, 0.0, 1.0);
-}
-
 void main() {
 	// Calculate normal from packed data
 	vec3 f_norm;
@@ -45,9 +41,11 @@ void main() {
 
 	vec3 light = vec3(static_light);
 
-	vec3 frag_color = f_col * light;
+	vec3 surf_color = f_col * light;
 
-	vec3 fog_color = vec3(0.0, 0.25, 0.55);
+	float fog_level = fog(f_pos.xy, cam_pos.xy);
+	vec3 fog_color = get_sky_color(normalize(f_pos - cam_pos.xyz), time_of_day.x);
+	vec3 color = mix(surf_color, fog_color, fog_level);
 
-	tgt_color = vec4(mix(frag_color, fog_color, fog()), 1.0);
+	tgt_color = vec4(color, 1.0);
 }
diff --git a/voxygen/src/anim/character/run.rs b/voxygen/src/anim/character/run.rs
index 53845caeec..173caca70a 100644
--- a/voxygen/src/anim/character/run.rs
+++ b/voxygen/src/anim/character/run.rs
@@ -37,8 +37,8 @@ impl Animation for RunAnimation {
         );
 
         next.head.offset = Vec3::new(0.0, 3.0, 12.0 + wave_cos * 1.3);
-        next.head.ori =
-            Quaternion::rotation_z(head_look.x + wave * 0.1) * Quaternion::rotation_x(head_look.y + 0.35);
+        next.head.ori = Quaternion::rotation_z(head_look.x + wave * 0.1)
+            * Quaternion::rotation_x(head_look.y + 0.35);
         next.head.scale = Vec3::one();
 
         next.chest.offset = Vec3::new(0.0, 0.0, 7.0 + wave_cos * 1.1);
diff --git a/voxygen/src/menu/main/start_singleplayer.rs b/voxygen/src/menu/main/start_singleplayer.rs
index 9ab08b138a..8dc9a575a8 100644
--- a/voxygen/src/menu/main/start_singleplayer.rs
+++ b/voxygen/src/menu/main/start_singleplayer.rs
@@ -3,8 +3,8 @@ use crate::{
     menu::char_selection::CharSelectionState, singleplayer::Singleplayer, Direction, GlobalState,
     PlayState, PlayStateResult,
 };
-use common::comp;
 use client::Client;
+use common::comp;
 use log::warn;
 use std::net::SocketAddr;
 
diff --git a/voxygen/src/mesh/terrain.rs b/voxygen/src/mesh/terrain.rs
index e85e216d7e..d3619b615b 100644
--- a/voxygen/src/mesh/terrain.rs
+++ b/voxygen/src/mesh/terrain.rs
@@ -1,18 +1,14 @@
-// Library
-use vek::*;
-
-// Project
+use crate::{
+    mesh::{vol, Meshable},
+    render::{self, Mesh, Quad, TerrainPipeline},
+};
 use common::{
     terrain::Block,
     vol::{BaseVol, ReadVol, SizedVol, VolSize, Vox},
     volumes::{dyna::Dyna, vol_map_2d::VolMap2d, vol_map_3d::VolMap3d},
 };
-
-// Crate
-use crate::{
-    mesh::{vol, Meshable},
-    render::{self, Mesh, Quad, TerrainPipeline},
-};
+use std::fmt::Debug;
+use vek::*;
 
 type TerrainVertex = <TerrainPipeline as render::Pipeline>::Vertex;
 
@@ -46,7 +42,7 @@ impl<M> Meshable for Dyna<Block, M> {
 }
 */
 
-impl<V: BaseVol<Vox = Block> + ReadVol, S: VolSize + Clone> Meshable for VolMap2d<V, S> {
+impl<V: BaseVol<Vox = Block> + ReadVol + Debug, S: VolSize + Clone> Meshable for VolMap2d<V, S> {
     type Pipeline = TerrainPipeline;
     type Supplement = Aabb<i32>;
 
@@ -107,7 +103,7 @@ impl<V: BaseVol<Vox = Block> + ReadVol, S: VolSize + Clone> Meshable for VolMap2
 }
 
 /*
-impl<V: BaseVol<Vox = Block> + ReadVol, S: VolSize + Clone> Meshable for VolMap3d<V, S> {
+impl<V: BaseVol<Vox = Block> + ReadVol + Debug, S: VolSize + Clone> Meshable for VolMap3d<V, S> {
     type Pipeline = TerrainPipeline;
     type Supplement = Aabb<i32>;
 
diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs
index 794b59ca4b..f82e11faba 100644
--- a/voxygen/src/render/renderer.rs
+++ b/voxygen/src/render/renderer.rs
@@ -85,7 +85,7 @@ impl Renderer {
 
         let mut include_ctx = IncludeContext::new();
         include_ctx.include("globals.glsl", globals);
-        include_ctx.include("sky.glsl", globals);
+        include_ctx.include("sky.glsl", sky);
 
         // Construct a pipeline for rendering skyboxes
         let skybox_pipeline = create_pipeline(
diff --git a/voxygen/src/scene/camera.rs b/voxygen/src/scene/camera.rs
index ef747ab3df..08393f909c 100644
--- a/voxygen/src/scene/camera.rs
+++ b/voxygen/src/scene/camera.rs
@@ -11,7 +11,7 @@ use vek::*;
 const NEAR_PLANE: f32 = 0.1;
 const FAR_PLANE: f32 = 10000.0;
 
-const INTERP_TIME: f32 = 0.1;
+const INTERP_TIME: f32 = 0.05;
 
 pub struct Camera {
     tgt_focus: Vec3<f32>,
diff --git a/voxygen/src/singleplayer.rs b/voxygen/src/singleplayer.rs
index 27bb198596..eea93f8928 100644
--- a/voxygen/src/singleplayer.rs
+++ b/voxygen/src/singleplayer.rs
@@ -1,5 +1,5 @@
-use common::clock::Clock;
 use client::Client;
+use common::clock::Clock;
 use log::info;
 use portpicker::pick_unused_port;
 use server::{Event, Input, Server};
@@ -33,8 +33,7 @@ impl Singleplayer {
         ));
 
         // Create server
-        let server = Server::bind(sock.clone())
-            .expect("Failed to create server instance!");
+        let server = Server::bind(sock.clone()).expect("Failed to create server instance!");
 
         let server = match client {
             Some(client) => server.with_thread_pool(client.thread_pool().clone()),