Index: shaders/ship.frag
===================================================================
--- shaders/ship.frag	(revision 683dd557486e52b2bdd589d98486346bd0314c76)
+++ shaders/ship.frag	(revision 8e02b6ba837700ee39877d03da5cd5112cf055d9)
@@ -8,5 +8,4 @@
 layout(location = 0) out vec4 outColor;
 
-/*
 // fixed point light properties
 vec3 Ls = vec3(1.0, 1.0, 1.0);
@@ -19,42 +18,39 @@
 vec3 Ka = vec3(0.2, 0.2, 0.2);
 float specular_exponent = 100.0; // specular 'power'
-*/
 
 void main() {
-  /*
-  // ambient intensity
-  vec3 Ia = La * Ka;
+   // ambient intensity
+   vec3 Ia = La * Ka;
 
-  // ambient intensity
-  vec3 Ia2 = La * Ka;
+   // ambient intensity
+   vec3 Ia2 = La * Ka;
 
-  vec3 direction_to_light_eye = normalize(light_position_eye - position_eye);
-  float dot_prod = max(dot(direction_to_light_eye, normal_eye), 0.0);
+   //vec3 direction_to_light_eye = normalize(light_position_eye - position_eye);
+   //float dot_prod = max(dot(direction_to_light_eye, normal_eye), 0.0);
 
-  // diffuse intensity
-  vec3 Id = Ld * color * dot_prod;
+   // diffuse intensity
+   //vec3 Id = Ld * color * dot_prod;
 
-  vec3 direction_to_light2_eye = normalize(light2_position_eye - position_eye);
-  float dot_prod2 = max(dot(direction_to_light2_eye, normal_eye), 0.0);
+   //vec3 direction_to_light2_eye = normalize(light2_position_eye - position_eye);
+   //float dot_prod2 = max(dot(direction_to_light2_eye, normal_eye), 0.0);
 
-  // diffuse intensity
-  vec3 Id2 = Ld * color * dot_prod2;
+   // diffuse intensity
+   //vec3 Id2 = Ld * color * dot_prod2;
 
-  vec3 surface_to_viewer_eye = normalize(-position_eye);
+   //vec3 surface_to_viewer_eye = normalize(-position_eye);
 
-  vec3 reflection_eye = reflect(-direction_to_light_eye, normal_eye);
-  float dot_prod_specular = max(dot(reflection_eye, surface_to_viewer_eye), 0.0);
-  float specular_factor = pow(dot_prod_specular, specular_exponent);
+   //vec3 reflection_eye = reflect(-direction_to_light_eye, normal_eye);
+   //float dot_prod_specular = max(dot(reflection_eye, surface_to_viewer_eye), 0.0);
+   //float specular_factor = pow(dot_prod_specular, specular_exponent);
 
-  vec3 reflection_eye2 = reflect(-direction_to_light2_eye, normal_eye);
-  float dot_prod_specular2 = max(dot(reflection_eye2, surface_to_viewer_eye), 0.0);
-  float specular_factor2 = pow(dot_prod_specular2, specular_exponent);
+   //vec3 reflection_eye2 = reflect(-direction_to_light2_eye, normal_eye);
+   //float dot_prod_specular2 = max(dot(reflection_eye2, surface_to_viewer_eye), 0.0);
+   //float specular_factor2 = pow(dot_prod_specular2, specular_exponent);
 
-  // specular intensity
-  vec3 Is = Ls * Ks * specular_factor;
-  vec3 Is2 = Ls * Ks * specular_factor2;
+   // specular intensity
+   //vec3 Is = Ls * Ks * specular_factor;
+   //vec3 Is2 = Ls * Ks * specular_factor2;
 
-  outColor = vec4((Is + Id + Ia + Is2 + Id2 + Ia2)/2, 1.0);
-  */
-  outColor = vec4(color, 1.0);
+   //frag_color = vec4((Is + Id + Ia + Is2 + Id2 + Ia2)/2, 1.0);
+   outColor = vec4(color, 1.0);
 }
Index: shaders/ship.vert
===================================================================
--- shaders/ship.vert	(revision 683dd557486e52b2bdd589d98486346bd0314c76)
+++ shaders/ship.vert	(revision 8e02b6ba837700ee39877d03da5cd5112cf055d9)
@@ -2,4 +2,5 @@
 #extension GL_ARB_separate_shader_objects : enable
 
+// TODO: Figure out if the UniformBufferObject label is necessary and, if not, remove it
 layout (binding = 0) uniform UniformBufferObject {
    mat4 model;
@@ -10,4 +11,6 @@
 layout(location = 0) in vec3 vertex_position;
 layout(location = 1) in vec3 vertex_color;
+//layout(location = 2) in vec3 vertex_normal;
+//layout(location = 3) in uint ubo_index;
 
 //out vec3 position_eye, normal_eye, color, light_position_eye, light2_position_eye;
@@ -20,11 +23,11 @@
 
 void main() {
-  // ORIG: position_eye = vec3(view * model_mats[ubo_index] * vec4(vertex_position, 1.0));
-  position_eye = vec3(ubo.view * ubo.model * vec4(vertex_position, 1.0));
-  //normal_eye = normalize(vec3(view * model_mats[ubo_index] * vec4(vertex_normal, 0.0)));
-  color = vertex_color;
-  //light_position_eye = vec3(view * vec4(light_position_world, 1.0));
-  //light2_position_eye = vec3(view * vec4(light2_position_world, 1.0));
+   //position_eye = vec3(view * model_mats[ubo_index] * vec4(vertex_position, 1.0));
+   position_eye = vec3(ubo.view * ubo.model * vec4(vertex_position, 1.0));
+   //normal_eye = normalize(vec3(view * model_mats[ubo_index] * vec4(vertex_normal, 0.0)));
+   color = vertex_color;
+   //light_position_eye = vec3(view * vec4(light_position_world, 1.0));
+   //light2_position_eye = vec3(view * vec4(light2_position_world, 1.0));
 
-  gl_Position = ubo.proj * vec4(position_eye, 1.0);
+   gl_Position = ubo.proj * vec4(position_eye, 1.0);
 }
Index: vulkan-game.cpp
===================================================================
--- vulkan-game.cpp	(revision 683dd557486e52b2bdd589d98486346bd0314c76)
+++ vulkan-game.cpp	(revision 8e02b6ba837700ee39877d03da5cd5112cf055d9)
@@ -26,5 +26,5 @@
    framebufferResized = false;
 
-   ubo = {};
+   modelMvpMats = {};
 }
 
@@ -266,8 +266,8 @@
    mat4 T = translate(mat4(1.0f), vec3(-cam_pos.x, -cam_pos.y, -cam_pos.z));
 
-   ubo.view = R * T;
-
-   ubo.proj = perspective(radians(FOV_ANGLE), (float)swapChainExtent.width / (float)swapChainExtent.height, NEAR_CLIP, FAR_CLIP);
-   ubo.proj[1][1] *= -1; // flip the y-axis so that +y is up
+   modelMvpMats.view = R * T;
+
+   modelMvpMats.proj = perspective(radians(FOV_ANGLE), (float)swapChainExtent.width / (float)swapChainExtent.height, NEAR_CLIP, FAR_CLIP);
+   modelMvpMats.proj[1][1] *= -1; // flip the y-axis so that +y is up
 }
 
@@ -342,4 +342,17 @@
 }
 
+void VulkanGame::updateScene(uint32_t currentImage) {
+   static auto startTime = chrono::high_resolution_clock::now();
+
+   auto currentTime = chrono::high_resolution_clock::now();
+   float time = chrono::duration<float, chrono::seconds::period>(currentTime - startTime).count();
+
+   modelMvpMats.model =
+      translate(mat4(1.0f), vec3(0.0f, -2.0f, -0.0f)) *
+      rotate(mat4(1.0f), time * radians(90.0f), vec3(0.0f, 0.0f, 1.0f));
+
+   VulkanUtils::copyDataToMemory(device, uniformBuffersMemory[currentImage], modelMvpMats);
+}
+
 void VulkanGame::renderUI() {
    SDL_SetRenderDrawColor(renderer, 0x00, 0x00, 0x00, 0x00);
@@ -380,5 +393,8 @@
    }
 
-   updateUniformBuffer(imageIndex);
+   // TODO: Figure out a more elegant way to only do updates and render the UI once per scene render
+   // Probably move some of the renderScene() code into a higher function that updates the UI, and renders
+   // the UI and scene
+   updateScene(imageIndex);
 
    VkSubmitInfo submitInfo = {};
@@ -880,5 +896,5 @@
 
 void VulkanGame::createUniformBuffers() {
-   VkDeviceSize bufferSize = sizeof(UniformBufferObject);
+   VkDeviceSize bufferSize = sizeof(UBO_MvpMat);
 
    uniformBuffers.resize(swapChainImages.size());
@@ -893,5 +909,5 @@
       uniformBufferInfoList[i].buffer = uniformBuffers[i];
       uniformBufferInfoList[i].offset = 0;
-      uniformBufferInfoList[i].range = sizeof(UniformBufferObject);
+      uniformBufferInfoList[i].range = sizeof(UBO_MvpMat);
    }
 }
@@ -1005,20 +1021,4 @@
 }
 
-void VulkanGame::updateUniformBuffer(uint32_t currentImage) {
-   static auto startTime = chrono::high_resolution_clock::now();
-
-   auto currentTime = chrono::high_resolution_clock::now();
-   float time = chrono::duration<float, chrono::seconds::period>(currentTime - startTime).count();
-
-   ubo.model =
-      translate(mat4(1.0f), vec3(0.0f, -2.0f, -0.0f)) * 
-      rotate(mat4(1.0f), time * radians(90.0f), vec3(0.0f, 0.0f, 1.0f));
-
-   void* data;
-   vkMapMemory(device, uniformBuffersMemory[currentImage], 0, sizeof(ubo), 0, &data);
-   memcpy(data, &ubo, sizeof(ubo));
-   vkUnmapMemory(device, uniformBuffersMemory[currentImage]);
-}
-
 void VulkanGame::cleanupSwapChain() {
    VulkanUtils::destroyVulkanImage(device, depthImage);
Index: vulkan-game.hpp
===================================================================
--- vulkan-game.hpp	(revision 683dd557486e52b2bdd589d98486346bd0314c76)
+++ vulkan-game.hpp	(revision 8e02b6ba837700ee39877d03da5cd5112cf055d9)
@@ -29,5 +29,5 @@
 };
 
-struct UniformBufferObject {
+struct UBO_MvpMat {
    alignas(16) mat4 model;
    alignas(16) mat4 view;
@@ -51,5 +51,5 @@
       vec3 cam_pos;
 
-      UniformBufferObject ubo;
+      UBO_MvpMat modelMvpMats;
 
       GameGui* gui;
@@ -120,4 +120,5 @@
       void initMatrices();
       void mainLoop();
+      void updateScene(uint32_t currentImage);
       void renderUI();
       void renderScene();
@@ -147,5 +148,4 @@
 
       void recreateSwapChain();
-      void updateUniformBuffer(uint32_t currentImage);
 
       void cleanupSwapChain();
Index: vulkan-utils.hpp
===================================================================
--- vulkan-utils.hpp	(revision 683dd557486e52b2bdd589d98486346bd0314c76)
+++ vulkan-utils.hpp	(revision 8e02b6ba837700ee39877d03da5cd5112cf055d9)
@@ -94,4 +94,7 @@
             VkDeviceSize srcOffset, VkDeviceSize dstOffset, VkDeviceSize size, VkQueue graphicsQueue);
 
+      template<class DataType>
+      static void copyDataToMemory(VkDevice device, VkDeviceMemory bufferMemory, const DataType& srcData);
+
       static bool hasStencilComponent(VkFormat format);
 
@@ -122,3 +125,11 @@
 }
 
+template<class DataType>
+void VulkanUtils::copyDataToMemory(VkDevice device, VkDeviceMemory bufferMemory, const DataType& srcData) {
+   void* data;
+   vkMapMemory(device, bufferMemory, 0, sizeof(DataType), 0, &data);
+   memcpy(data, &srcData, sizeof(DataType));
+   vkUnmapMemory(device, bufferMemory);
+}
+
 #endif // _VULKAN_UTILS_H
