From 308cbbb998cfd03a7ae7101a2995818dc8370b25 Mon Sep 17 00:00:00 2001
From: Imbris <imbrisf@gmail.com>
Date: Thu, 13 May 2021 01:25:28 -0400
Subject: [PATCH] Address various TODOs introduced in wgpu transition

---
 assets/voxygen/shaders/skybox-vert.glsl  | 10 +++-
 assets/voxygen/shaders/terrain-vert.glsl |  1 +
 voxygen/src/mesh/greedy.rs               | 10 ++--
 voxygen/src/render/pipelines/mod.rs      |  8 +--
 voxygen/src/render/pipelines/shadow.rs   |  4 +-
 voxygen/src/render/pipelines/terrain.rs  | 14 ++++-
 voxygen/src/render/renderer.rs           |  7 ++-
 voxygen/src/render/renderer/drawer.rs    |  4 --
 voxygen/src/scene/terrain.rs             | 73 ++++++++++--------------
 9 files changed, 66 insertions(+), 65 deletions(-)

diff --git a/assets/voxygen/shaders/skybox-vert.glsl b/assets/voxygen/shaders/skybox-vert.glsl
index e3eaf45546..9f362fedb7 100644
--- a/assets/voxygen/shaders/skybox-vert.glsl
+++ b/assets/voxygen/shaders/skybox-vert.glsl
@@ -25,8 +25,16 @@ layout(location = 0) out vec3 f_pos;
 void main() {
     f_pos = v_pos;
 
-    // TODO: is this todo below still valid? is cam_pos jittery
     // TODO: Make this position-independent to avoid rounding error jittering
+    // NOTE: we may or may not want to use an infinite projection here
+    //
+    // Essentially: using any finite projection is likely wrong here if we want
+    // to project out to infinity, but since we want to perturb the skybox as we
+    // move and we have stars now, the "right" answer is heavily dependent on
+    // how we compute cloud position and stuff.
+    //
+    // Infinite projections of cubemaps are nice because they can be oriented
+    // but still extend infinitely far.
     gl_Position =
         all_mat *
         vec4(v_pos + cam_pos.xyz, 1);
diff --git a/assets/voxygen/shaders/terrain-vert.glsl b/assets/voxygen/shaders/terrain-vert.glsl
index a1b04c2946..7fac4a0d2e 100644
--- a/assets/voxygen/shaders/terrain-vert.glsl
+++ b/assets/voxygen/shaders/terrain-vert.glsl
@@ -32,6 +32,7 @@ layout (std140, set = 2, binding = 0)
 uniform u_locals {
     vec3 model_offs;
     float load_time;
+    // TODO: consider whether these need to be signed
     ivec4 atlas_offs;
 };
 
diff --git a/voxygen/src/mesh/greedy.rs b/voxygen/src/mesh/greedy.rs
index 839d443cd1..ef8f4f5014 100644
--- a/voxygen/src/mesh/greedy.rs
+++ b/voxygen/src/mesh/greedy.rs
@@ -82,7 +82,7 @@ pub type SuspendedMesh<'a> = dyn for<'r> FnOnce(&'r mut ColLightInfo) + 'a;
 /// For an explanation of why we want this, see `SuspendedMesh`.
 pub struct GreedyMesh<'a> {
     atlas: guillotiere::SimpleAtlasAllocator,
-    col_lights_size: Vec2<u32>,
+    col_lights_size: Vec2<u16>,
     max_size: guillotiere::Size,
     suspended: Vec<Box<SuspendedMesh<'a>>>,
 }
@@ -190,7 +190,7 @@ impl<'a> GreedyMesh<'a> {
 
 fn greedy_mesh<'a, M: PartialEq, D: 'a, FL, FG, FO, FS, FP, FT>(
     atlas: &mut guillotiere::SimpleAtlasAllocator,
-    col_lights_size: &mut Vec2<u32>,
+    col_lights_size: &mut Vec2<u16>,
     max_size: guillotiere::Size,
     GreedyConfig {
         mut data,
@@ -428,7 +428,7 @@ fn add_to_atlas(
     norm: Vec3<i16>,
     faces_forward: bool,
     max_size: guillotiere::Size,
-    cur_size: &mut Vec2<u32>,
+    cur_size: &mut Vec2<u16>,
 ) -> guillotiere::Rectangle {
     // TODO: Check this conversion.
     let atlas_rect;
@@ -473,8 +473,8 @@ fn add_to_atlas(
     // a u16 and we never grew the atlas, meaning all valid coordinates within the
     // atlas also fit into a u16.
     *cur_size = Vec2::new(
-        cur_size.x.max(atlas_rect.max.x as u32),
-        cur_size.y.max(atlas_rect.max.y as u32),
+        cur_size.x.max(atlas_rect.max.x as u16),
+        cur_size.y.max(atlas_rect.max.y as u16),
     );
 
     // NOTE: pos can be converted safely from usize to i32 because all legal block
diff --git a/voxygen/src/render/pipelines/mod.rs b/voxygen/src/render/pipelines/mod.rs
index bb55a288a0..846a4d7339 100644
--- a/voxygen/src/render/pipelines/mod.rs
+++ b/voxygen/src/render/pipelines/mod.rs
@@ -124,11 +124,11 @@ impl Globals {
                 shadow_planes.x,
                 shadow_planes.y,
             ],
+            // TODO: why do we accept values greater than the max?
             light_shadow_count: [
-                // TODO: why do we accept values greater than the max?
-                (light_count % (MAX_POINT_LIGHT_COUNT + 1)) as u32,
-                (shadow_count % (MAX_FIGURE_SHADOW_COUNT + 1)) as u32,
-                (directed_light_count % (MAX_DIRECTED_LIGHT_COUNT + 1)) as u32,
+                usize::min(light_count, MAX_POINT_LIGHT_COUNT) as u32,
+                usize::min(shadow_count, MAX_FIGURE_SHADOW_COUNT) as u32,
+                usize::min(directed_light_count, MAX_DIRECTED_LIGHT_COUNT) as u32,
                 0,
             ],
             shadow_proj_factors: [
diff --git a/voxygen/src/render/pipelines/shadow.rs b/voxygen/src/render/pipelines/shadow.rs
index cc3262b4d7..e51069c28d 100644
--- a/voxygen/src/render/pipelines/shadow.rs
+++ b/voxygen/src/render/pipelines/shadow.rs
@@ -82,8 +82,8 @@ pub fn create_col_lights(
     let texture_info = wgpu::TextureDescriptor {
         label: None,
         size: wgpu::Extent3d {
-            width: col_lights_size.x,
-            height: col_lights_size.y,
+            width: u32::from(col_lights_size.x),
+            height: u32::from(col_lights_size.y),
             depth_or_array_layers: 1,
         },
         mip_level_count: 1,
diff --git a/voxygen/src/render/pipelines/terrain.rs b/voxygen/src/render/pipelines/terrain.rs
index 6fc245e7d8..8a379f589d 100644
--- a/voxygen/src/render/pipelines/terrain.rs
+++ b/voxygen/src/render/pipelines/terrain.rs
@@ -141,12 +141,20 @@ impl VertexTrait for Vertex {
 #[derive(Copy, Clone, Debug, Zeroable, Pod)]
 // TODO: new function and private fields??
 pub struct Locals {
-    pub model_offs: [f32; 3],
-    pub load_time: f32,
-    pub atlas_offs: [i32; 4],
+    model_offs: [f32; 3],
+    load_time: f32,
+    atlas_offs: [i32; 4],
 }
 
 impl Locals {
+    pub fn new(model_offs: Vec3<f32>, atlas_offs: Vec2<u32>, load_time: f32) -> Self {
+        Self {
+            model_offs: model_offs.into_array(),
+            load_time,
+            atlas_offs: Vec4::new(atlas_offs.x as i32, atlas_offs.y as i32, 0, 0).into_array(),
+        }
+    }
+
     pub fn default() -> Self {
         Self {
             model_offs: [0.0; 3],
diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs
index 4602da5e1b..bc77931326 100644
--- a/voxygen/src/render/renderer.rs
+++ b/voxygen/src/render/renderer.rs
@@ -38,7 +38,7 @@ use vek::*;
 /// A type representing data that can be converted to an immutable texture map
 /// of ColLight data (used for texture atlases created during greedy meshing).
 // TODO: revert to u16
-pub type ColLightInfo = (Vec<[u8; 4]>, Vec2<u32>);
+pub type ColLightInfo = (Vec<[u8; 4]>, Vec2<u16>);
 
 const QUAD_INDEX_BUFFER_U16_START_VERT_LEN: u16 = 3000;
 const QUAD_INDEX_BUFFER_U32_START_VERT_LEN: u32 = 3000;
@@ -678,7 +678,10 @@ impl Renderer {
         .unwrap_or_else(|| (Vec2::new(1, 1), Vec2::new(1, 1)))
     }
 
-    // TODO: @Sharp what should this look like with wgpu?
+    // TODO: Seamless is potentially the default with wgpu but we need further
+    // investigation into whether this is actually turned on for the OpenGL
+    // backend
+    //
     /// NOTE: Supported by Vulkan (by default), DirectX 10+ (it seems--it's hard
     /// to find proof of this, but Direct3D 10 apparently does it by
     /// default, and 11 definitely does, so I assume it's natively supported
diff --git a/voxygen/src/render/renderer/drawer.rs b/voxygen/src/render/renderer/drawer.rs
index 4e45488e13..ca8bb7e824 100644
--- a/voxygen/src/render/renderer/drawer.rs
+++ b/voxygen/src/render/renderer/drawer.rs
@@ -839,10 +839,6 @@ impl<'pass_ref, 'pass: 'pass_ref> PreparedUiDrawer<'pass_ref, 'pass> {
 
     pub fn set_scissor(&mut self, scissor: Aabr<u16>) {
         let Aabr { min, max } = scissor;
-        // TODO: Got an invalid scissor panic from wgpu,
-        // use this if you can reproduce
-        // Note: might have been from changing monitors
-        // dbg!(&scissor)
         self.render_pass.set_scissor_rect(
             min.x as u32,
             min.y as u32,
diff --git a/voxygen/src/scene/terrain.rs b/voxygen/src/scene/terrain.rs
index 1aa6022f75..6c09250fad 100644
--- a/voxygen/src/scene/terrain.rs
+++ b/voxygen/src/scene/terrain.rs
@@ -1088,40 +1088,32 @@ impl<V: RectRasterableVol> Terrain<V> {
                         let atlas = &mut self.atlas;
                         let chunks = &mut self.chunks;
                         let col_lights = &mut self.col_lights;
-                        let allocation = atlas
-                            .allocate(guillotiere::Size::new(
-                                tex_size.x as i32, /* TODO: adjust ColLightInfo to avoid the
-                                                    * cast here? */
-                                tex_size.y as i32,
-                            ))
-                            .unwrap_or_else(|| {
-                                // Atlas allocation failure: try allocating a new texture and atlas.
-                                let (new_atlas, new_col_lights) = Self::make_atlas(renderer)
-                                    .expect("Failed to create atlas texture");
+                        let alloc_size =
+                            guillotiere::Size::new(i32::from(tex_size.x), i32::from(tex_size.y));
 
-                                // We reset the atlas and clear allocations from existing chunks,
-                                // even though we haven't yet
-                                // checked whether the new allocation can fit in
-                                // the texture.  This is reasonable because we don't have a fallback
-                                // if a single chunk can't fit in an empty atlas of maximum size.
-                                //
-                                // TODO: Consider attempting defragmentation first rather than just
-                                // always moving everything into the new chunk.
-                                chunks.iter_mut().for_each(|(_, chunk)| {
-                                    chunk.col_lights_alloc = None;
-                                });
-                                *atlas = new_atlas;
-                                *col_lights = Arc::new(new_col_lights);
+                        let allocation = atlas.allocate(alloc_size).unwrap_or_else(|| {
+                            // Atlas allocation failure: try allocating a new texture and atlas.
+                            let (new_atlas, new_col_lights) =
+                                Self::make_atlas(renderer).expect("Failed to create atlas texture");
 
-                                atlas
-                                    .allocate(guillotiere::Size::new(
-                                        tex_size.x as i32, /* TODO: adjust ColLightInfo to avoid
-                                                            * the
-                                                            * cast here? */
-                                        tex_size.y as i32,
-                                    ))
-                                    .expect("Chunk data does not fit in a texture of maximum size.")
+                            // We reset the atlas and clear allocations from existing chunks,
+                            // even though we haven't yet
+                            // checked whether the new allocation can fit in
+                            // the texture.  This is reasonable because we don't have a fallback
+                            // if a single chunk can't fit in an empty atlas of maximum size.
+                            //
+                            // TODO: Consider attempting defragmentation first rather than just
+                            // always moving everything into the new chunk.
+                            chunks.iter_mut().for_each(|(_, chunk)| {
+                                chunk.col_lights_alloc = None;
                             });
+                            *atlas = new_atlas;
+                            *col_lights = Arc::new(new_col_lights);
+
+                            atlas
+                                .allocate(alloc_size)
+                                .expect("Chunk data does not fit in a texture of maximum size.")
+                        });
 
                         // NOTE: Cast is safe since the origin was a u16.
                         let atlas_offs = Vec2::new(
@@ -1131,7 +1123,7 @@ impl<V: RectRasterableVol> Terrain<V> {
                         renderer.update_texture(
                             &col_lights.texture,
                             atlas_offs.into_array(),
-                            tex_size.into_array(),
+                            tex_size.map(|e| u32::from(e)).into_array(),
                             &tex,
                         );
 
@@ -1144,22 +1136,15 @@ impl<V: RectRasterableVol> Terrain<V> {
                             light_map: mesh.light_map,
                             glow_map: mesh.glow_map,
                             sprite_instances,
-                            locals: renderer.create_terrain_bound_locals(&[TerrainLocals {
-                                model_offs: Vec3::from(
+                            locals: renderer.create_terrain_bound_locals(&[TerrainLocals::new(
+                                Vec3::from(
                                     response.pos.map2(VolGrid2d::<V>::chunk_size(), |e, sz| {
                                         e as f32 * sz as f32
                                     }),
-                                )
-                                .into_array(),
-                                atlas_offs: Vec4::new(
-                                    atlas_offs.x as i32,
-                                    atlas_offs.y as i32,
-                                    0,
-                                    0,
-                                )
-                                .into_array(),
+                                ),
+                                atlas_offs,
                                 load_time,
-                            }]),
+                            )]),
                             visible: Visibility {
                                 in_range: false,
                                 in_frustum: false,