Index: shaders/asteroid.frag
===================================================================
--- shaders/asteroid.frag	(revision 3e8cc8b7aef266654d80c142b7d4436950ceba1f)
+++ shaders/asteroid.frag	(revision 3e8cc8b7aef266654d80c142b7d4436950ceba1f)
@@ -0,0 +1,57 @@
+#version 450
+#extension GL_ARB_separate_shader_objects : enable
+
+layout(location = 0) in vec3 position_eye;
+layout(location = 1) in vec3 color;
+layout(location = 2) in vec3 normal_eye;
+layout(location = 3) in vec3 light_position_eye;
+layout(location = 4) in vec3 light2_position_eye;
+
+layout(location = 0) out vec4 frag_color;
+
+// fixed point light properties
+vec3 Ls = vec3(1.0, 1.0, 1.0);
+vec3 Ld = vec3(1.0, 1.0, 1.0);
+vec3 La = vec3(0.2, 0.2, 0.2);
+
+// surface reflectance
+vec3 Ks = vec3(1.0, 1.0, 1.0);
+vec3 Kd = vec3(1.0, 1.5, 1.0);
+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 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);
+
+  // 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);
+
+  // diffuse intensity
+  vec3 Id2 = Ld * color * dot_prod2;
+
+  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_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;
+
+  frag_color = vec4((Is + Id + Ia + Is2 + Id2 + Ia2)/2, 1.0);
+}
Index: shaders/asteroid.vert
===================================================================
--- shaders/asteroid.vert	(revision 3e8cc8b7aef266654d80c142b7d4436950ceba1f)
+++ shaders/asteroid.vert	(revision 3e8cc8b7aef266654d80c142b7d4436950ceba1f)
@@ -0,0 +1,45 @@
+#version 450
+#extension GL_ARB_separate_shader_objects : enable
+
+struct Object {
+   mat4 model;
+   float hp;
+};
+
+layout (binding = 0) uniform UniformBufferObject {
+   mat4 view;
+   mat4 proj;
+} ubo;
+
+layout(binding = 1) readonly buffer StorageBufferObject {
+    Object objects[];
+} sbo;
+
+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 obj_index;
+
+layout(location = 0) out vec3 position_eye;
+layout(location = 1) out vec3 color;
+layout(location = 2) out vec3 normal_eye;
+layout(location = 3) out vec3 light_position_eye;
+layout(location = 4) out vec3 light2_position_eye;
+
+// fixed point light position
+vec3 light_position_world = vec3(0.0, 0.0, 2.0);
+vec3 light2_position_world = vec3(0.0, 1.5, -0.1);
+
+void main() {
+  position_eye = vec3(ubo.view * sbo.objects[obj_index].model * vec4(vertex_position, 1.0));
+  normal_eye = normalize(vec3(ubo.view * sbo.objects[obj_index].model * vec4(vertex_normal, 0.0)));
+
+  float hp_percent = sbo.objects[obj_index].hp / 10.0;
+  vec3 damage_color = vec3(1.0, 0.0, 0.0);
+  color = (vertex_color * hp_percent) + (damage_color * (1.0 - hp_percent));
+
+  light_position_eye = vec3(ubo.view * vec4(light_position_world, 1.0));
+  light2_position_eye = vec3(ubo.view * vec4(light2_position_world, 1.0));
+
+  gl_Position = ubo.proj * vec4(position_eye, 1.0);
+}
Index: vulkan-game.cpp
===================================================================
--- vulkan-game.cpp	(revision 0fe84333f0e448837677f6a2bd0c3f62b0a1d8c8)
+++ vulkan-game.cpp	(revision 3e8cc8b7aef266654d80c142b7d4436950ceba1f)
@@ -25,4 +25,5 @@
    object_VP_mats = {};
    ship_VP_mats = {};
+   asteroid_VP_mats = {};
 }
 
@@ -196,4 +197,5 @@
    createBufferSet(sizeof(UBO_VP_mats), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
       uniformBuffers_scenePipeline, uniformBuffersMemory_scenePipeline, uniformBufferInfoList_scenePipeline);
+   // TODO: Calculate the size of this buffer (and all the other SSBOs) based on the number of objects
    createBufferSet(10 * sizeof(SBO_SceneObject), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
       storageBuffers_scenePipeline, storageBuffersMemory_scenePipeline, storageBufferInfoList_scenePipeline);
@@ -274,4 +276,5 @@
       addObjectIndex<ShipVertex>(shipObjects.size(),
       addVertexNormals<ShipVertex>({
+
          //back
          {{ -0.5f,   0.3f,   0.0f}, {0.0f, 0.0f, 0.3f}},
@@ -506,4 +509,85 @@
    shipPipeline.createDescriptorSets(swapChainImages);
 
+   asteroidPipeline.addAttribute(VK_FORMAT_R32G32B32_SFLOAT, offset_of(&AsteroidVertex::pos));
+   asteroidPipeline.addAttribute(VK_FORMAT_R32G32B32_SFLOAT, offset_of(&AsteroidVertex::color));
+   asteroidPipeline.addAttribute(VK_FORMAT_R32G32B32_SFLOAT, offset_of(&AsteroidVertex::normal));
+   asteroidPipeline.addAttribute(VK_FORMAT_R32_UINT, offset_of(&AsteroidVertex::objIndex));
+
+   createBufferSet(sizeof(UBO_VP_mats), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
+      uniformBuffers_asteroidPipeline, uniformBuffersMemory_asteroidPipeline, uniformBufferInfoList_asteroidPipeline);
+   createBufferSet(10 * sizeof(SBO_Asteroid), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
+      storageBuffers_asteroidPipeline, storageBuffersMemory_asteroidPipeline, storageBufferInfoList_asteroidPipeline);
+
+   asteroidPipeline.addDescriptorInfo(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
+      VK_SHADER_STAGE_VERTEX_BIT, &uniformBufferInfoList_asteroidPipeline);
+   asteroidPipeline.addDescriptorInfo(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
+      VK_SHADER_STAGE_VERTEX_BIT, &storageBufferInfoList_asteroidPipeline);
+
+   addObject(asteroidObjects, asteroidPipeline,
+      centerObject<AsteroidVertex>(
+      addObjectIndex<AsteroidVertex>(asteroidObjects.size(),
+      addVertexNormals<AsteroidVertex>({
+
+         // front
+         {{ 1.0f,  1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
+         {{-1.0f,  1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
+         {{-1.0f, -1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
+         {{ 1.0f,  1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
+         {{-1.0f, -1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
+         {{ 1.0f, -1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
+
+         // top
+         {{ 1.0f,  1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
+         {{-1.0f,  1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
+         {{-1.0f,  1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
+         {{ 1.0f,  1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
+         {{-1.0f,  1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
+         {{ 1.0f,  1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
+
+         // bottom
+         {{ 1.0f, -1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
+         {{-1.0f, -1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
+         {{-1.0f, -1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
+         {{ 1.0f, -1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
+         {{-1.0f, -1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
+         {{ 1.0f, -1.0f, -1.0}, {0.4f, 0.4f, 0.4f}},
+
+         // back
+         {{ 1.0f,  1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
+         {{-1.0f, -1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
+         {{-1.0f,  1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
+         {{ 1.0f,  1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
+         {{ 1.0f, -1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
+         {{-1.0f, -1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
+
+         // right
+         {{ 1.0f,  1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
+         {{ 1.0f,  1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
+         {{ 1.0f, -1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
+         {{ 1.0f,  1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
+         {{ 1.0f, -1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
+         {{ 1.0f, -1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
+
+         // left
+         {{-1.0f,  1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
+         {{-1.0f,  1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
+         {{-1.0f, -1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
+         {{-1.0f,  1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
+         {{-1.0f, -1.0f, -1.0f}, {0.4f, 0.4f, 0.4f}},
+         {{-1.0f, -1.0f,  1.0f}, {0.4f, 0.4f, 0.4f}},
+      }))), {
+          0,  1,  2,  3,  4,  5,
+          6,  7,  8,  9, 10, 11,
+         12, 13, 14, 15, 16, 17,
+         18, 19, 20, 21, 22, 23,
+         24, 25, 26, 27, 28, 29,
+         30, 31, 32, 33, 34, 35,
+      });
+
+   asteroidPipeline.createDescriptorSetLayout();
+   asteroidPipeline.createPipeline("shaders/asteroid-vert.spv", "shaders/asteroid-frag.spv");
+   asteroidPipeline.createDescriptorPool(swapChainImages);
+   asteroidPipeline.createDescriptorSets(swapChainImages);
+
    cout << "Created all the graphics pipelines" << endl;
 
@@ -515,4 +599,13 @@
       translate(mat4(1.0f), vec3(0.0f, -1.2f, 1.65f)) *
       scale(mat4(1.0f), vec3(0.1f, 0.1f, 0.1f));
+
+   //vec3 pos = vec3(getRandomNum(-1.3f, 1.3f), -1.2f, getRandomNum(-5.5f, -4.5f));
+   vec3 pos = vec3(getRandomNum(-1.3f, 1.3f), -1.2f, -2.0f);
+
+   asteroidObjects[0].model_base =
+      translate(mat4(1.0f), pos) *
+      rotate(mat4(1.0f), radians(60.0f), vec3(1.0f, 1.0f, -1.0f)) *
+      scale(mat4(1.0f), vec3(0.1f, 0.1f, 0.1f));
+   asteroidObjects[0].model_transform = mat4(1.0); // Might not be needed
 }
 
@@ -526,4 +619,7 @@
    shipPipeline = GraphicsPipeline_Vulkan<ShipVertex>(physicalDevice, device, renderPass,
       { 0, 0, (int)swapChainExtent.width, (int)swapChainExtent.height }, 138, 138);
+
+   asteroidPipeline = GraphicsPipeline_Vulkan<AsteroidVertex>(physicalDevice, device, renderPass,
+      { 0, 0, (int)swapChainExtent.width, (int)swapChainExtent.height }, 24, 36);
 }
 
@@ -550,4 +646,7 @@
    ship_VP_mats.view = view;
    ship_VP_mats.proj = proj;
+
+   asteroid_VP_mats.view = view;
+   asteroid_VP_mats.proj = proj;
 }
 
@@ -624,4 +723,7 @@
       }
 
+      // this code moves the asteroids
+      transformObject(asteroidObjects[0], translate(mat4(1.0f), vec3(0.0f, 0.0f, 0.04f)));
+
       renderUI();
       renderScene();
@@ -647,4 +749,7 @@
    so_Ship.model = shipObjects[0].model_transform * shipObjects[0].model_base;
 
+   so_Asteroid.model = asteroidObjects[0].model_transform * asteroidObjects[0].model_base;
+   so_Asteroid.hp = 10.0;
+
    VulkanUtils::copyDataToMemory(device, uniformBuffersMemory_scenePipeline[currentImage], object_VP_mats);
 
@@ -654,4 +759,8 @@
 
    VulkanUtils::copyDataToMemory(device, storageBuffersMemory_shipPipeline[currentImage], so_Ship);
+
+   VulkanUtils::copyDataToMemory(device, uniformBuffersMemory_asteroidPipeline[currentImage], asteroid_VP_mats);
+
+   VulkanUtils::copyDataToMemory(device, storageBuffersMemory_asteroidPipeline[currentImage], so_Asteroid);
 }
 
@@ -757,4 +866,5 @@
    overlayPipeline.cleanupBuffers();
    shipPipeline.cleanupBuffers();
+   asteroidPipeline.cleanupBuffers();
 
    for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
@@ -1237,4 +1347,5 @@
       modelPipeline.createRenderCommands(commandBuffers[i], i);
       shipPipeline.createRenderCommands(commandBuffers[i], i);
+      asteroidPipeline.createRenderCommands(commandBuffers[i], i);
 
       // Always render this pipeline last
@@ -1335,4 +1446,14 @@
    shipPipeline.createDescriptorSets(swapChainImages);
 
+   createBufferSet(sizeof(UBO_VP_mats), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
+      uniformBuffers_asteroidPipeline, uniformBuffersMemory_asteroidPipeline, uniformBufferInfoList_asteroidPipeline);
+   createBufferSet(10 * sizeof(SBO_Asteroid), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
+      storageBuffers_asteroidPipeline, storageBuffersMemory_asteroidPipeline, storageBufferInfoList_asteroidPipeline);
+
+   asteroidPipeline.updateRenderPass(renderPass);
+   asteroidPipeline.createPipeline("shaders/asteroid-vert.spv", "shaders/asteroid-frag.spv");
+   asteroidPipeline.createDescriptorPool(swapChainImages);
+   asteroidPipeline.createDescriptorSets(swapChainImages);
+
    createCommandBuffers();
 }
@@ -1350,4 +1471,5 @@
    overlayPipeline.cleanup();
    shipPipeline.cleanup();
+   asteroidPipeline.cleanup();
 
    vkDestroyRenderPass(device, renderPass, nullptr);
@@ -1378,3 +1500,13 @@
       vkFreeMemory(device, storageBuffersMemory_shipPipeline[i], nullptr);
    }
-}
+
+   for (size_t i = 0; i < uniformBuffers_asteroidPipeline.size(); i++) {
+      vkDestroyBuffer(device, uniformBuffers_asteroidPipeline[i], nullptr);
+      vkFreeMemory(device, uniformBuffersMemory_asteroidPipeline[i], nullptr);
+   }
+
+   for (size_t i = 0; i < storageBuffers_asteroidPipeline.size(); i++) {
+      vkDestroyBuffer(device, storageBuffers_asteroidPipeline[i], nullptr);
+      vkFreeMemory(device, storageBuffersMemory_asteroidPipeline[i], nullptr);
+   }
+}
Index: vulkan-game.hpp
===================================================================
--- vulkan-game.hpp	(revision 0fe84333f0e448837677f6a2bd0c3f62b0a1d8c8)
+++ vulkan-game.hpp	(revision 3e8cc8b7aef266654d80c142b7d4436950ceba1f)
@@ -40,4 +40,11 @@
 };
 
+struct AsteroidVertex {
+   vec3 pos;
+   vec3 color;
+   vec3 normal;
+   unsigned int objIndex;
+};
+
 // TODO: Change the index type to uint32_t and check the Vulkan Tutorial loading model section as a reference
 // TODO: Create a typedef for index type so I can easily change uin16_t to something else later
@@ -58,4 +65,9 @@
 struct SBO_SceneObject {
    alignas(16) mat4 model;
+};
+
+struct SBO_Asteroid {
+   alignas(16) mat4 model;
+   alignas(4) float hp;
 };
 
@@ -130,4 +142,6 @@
       // variables to better reflect the data they hold
 
+      // TODO: Create a struct that holds the buffers, memory, and info objects (Probably in VulkanUtils)
+
       GraphicsPipeline_Vulkan<OverlayVertex> overlayPipeline;
 
@@ -142,10 +156,8 @@
       vector<VkBuffer> uniformBuffers_scenePipeline;
       vector<VkDeviceMemory> uniformBuffersMemory_scenePipeline;
-
       vector<VkDescriptorBufferInfo> uniformBufferInfoList_scenePipeline;
 
       vector<VkBuffer> storageBuffers_scenePipeline;
       vector<VkDeviceMemory> storageBuffersMemory_scenePipeline;
-
       vector<VkDescriptorBufferInfo> storageBufferInfoList_scenePipeline;
 
@@ -159,14 +171,27 @@
       vector<VkBuffer> uniformBuffers_shipPipeline;
       vector<VkDeviceMemory> uniformBuffersMemory_shipPipeline;
-
       vector<VkDescriptorBufferInfo> uniformBufferInfoList_shipPipeline;
 
       vector<VkBuffer> storageBuffers_shipPipeline;
       vector<VkDeviceMemory> storageBuffersMemory_shipPipeline;
-
       vector<VkDescriptorBufferInfo> storageBufferInfoList_shipPipeline;
 
       UBO_VP_mats ship_VP_mats;
       SBO_SceneObject so_Ship;
+
+      GraphicsPipeline_Vulkan<AsteroidVertex> asteroidPipeline;
+
+      vector<SceneObject<AsteroidVertex>> asteroidObjects;
+
+      vector<VkBuffer> uniformBuffers_asteroidPipeline;
+      vector<VkDeviceMemory> uniformBuffersMemory_asteroidPipeline;
+      vector<VkDescriptorBufferInfo> uniformBufferInfoList_asteroidPipeline;
+
+      vector<VkBuffer> storageBuffers_asteroidPipeline;
+      vector<VkDeviceMemory> storageBuffersMemory_asteroidPipeline;
+      vector<VkDescriptorBufferInfo> storageBufferInfoList_asteroidPipeline;
+
+      UBO_VP_mats asteroid_VP_mats;
+      SBO_Asteroid so_Asteroid;
 
       bool initWindow(int width, int height, unsigned char guiFlags);
