Index: vulkan-game.cpp
===================================================================
--- vulkan-game.cpp	(revision aa7e5f02d65eda57e6410dbfc26d5ef3e252bcc6)
+++ vulkan-game.cpp	(revision cefdf232d863ae4c6dd39962d3c681551bb062e9)
@@ -52,5 +52,5 @@
 VulkanGame::VulkanGame()
                      : swapChainImageCount(0)
-                      , swapChainMinImageCount(0)
+                     , swapChainMinImageCount(0)
                      , swapChainSurfaceFormat({})
                      , swapChainPresentMode(VK_PRESENT_MODE_MAX_ENUM_KHR)
@@ -70,5 +70,5 @@
                      , shouldRecreateSwapChain(false)
                      , frameCount(0)
-                     , currentFrame()
+                     , currentFrame(0)
                      , imageIndex(0)
                      , fpsStartTime(0.0f)
@@ -91,6 +91,4 @@
 
 void VulkanGame::run(int width, int height, unsigned char guiFlags) {
-   // TODO: Maybe call the init code in the constructor instead of in run()
-   // Research this
    seedRandomNums();
 
@@ -99,5 +97,4 @@
    cout << "Vulkan Game" << endl;
 
-   // TODO: Move IMGUI initialization in here
    if (initUI(width, height, guiFlags) == RTWO_ERROR) {
       return;
@@ -106,7 +103,379 @@
    initVulkan();
 
+   initImGuiOverlay();
+
+   // TODO: Figure out how much of ubo creation and associated variables should be in the pipeline class
+   // Maybe combine the ubo-related objects into a new class
+
+   initGraphicsPipelines();
+
+   initMatrices();
+
+   cout << "INITIALIZING OBJECTS" << endl;
+
+   modelPipeline.addAttribute(VK_FORMAT_R32G32B32_SFLOAT, offset_of(&ModelVertex::pos));
+   modelPipeline.addAttribute(VK_FORMAT_R32G32B32_SFLOAT, offset_of(&ModelVertex::color));
+   modelPipeline.addAttribute(VK_FORMAT_R32G32_SFLOAT, offset_of(&ModelVertex::texCoord));
+   modelPipeline.addAttribute(VK_FORMAT_R32_UINT, offset_of(&ModelVertex::objIndex));
+
+   createBufferSet(sizeof(UBO_VP_mats), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
+      uniformBuffers_modelPipeline, uniformBuffersMemory_modelPipeline, uniformBufferInfoList_modelPipeline);
+
+   modelPipeline.addDescriptorInfo(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
+      VK_SHADER_STAGE_VERTEX_BIT, &uniformBufferInfoList_modelPipeline);
+   modelPipeline.addStorageDescriptor(VK_SHADER_STAGE_VERTEX_BIT);
+   modelPipeline.addDescriptorInfo(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
+      VK_SHADER_STAGE_FRAGMENT_BIT, &floorTextureImageDescriptor);
+
+   SceneObject<ModelVertex, SSBO_ModelObject>* texturedSquare = nullptr;
+
+   texturedSquare = &addObject(modelObjects, modelPipeline,
+      addObjectIndex<ModelVertex>(modelObjects.size(), {
+         {{-0.5f, -0.5f,  0.0f}, {1.0f, 0.0f, 0.0f}, {0.0f, 1.0f}},
+         {{ 0.5f, -0.5f,  0.0f}, {0.0f, 1.0f, 0.0f}, {1.0f, 1.0f}},
+         {{ 0.5f,  0.5f,  0.0f}, {0.0f, 0.0f, 1.0f}, {1.0f, 0.0f}},
+         {{-0.5f,  0.5f,  0.0f}, {1.0f, 1.0f, 1.0f}, {0.0f, 0.0f}}
+         }), {
+            0, 1, 2, 2, 3, 0
+      }, {
+         mat4(1.0f)
+      }, false);
+
+   texturedSquare->model_base =
+      translate(mat4(1.0f), vec3(0.0f, 0.0f, -2.0f));
+   texturedSquare->modified = true;
+
+   texturedSquare = &addObject(modelObjects, modelPipeline,
+      addObjectIndex<ModelVertex>(modelObjects.size(), {
+         {{-0.5f, -0.5f,  0.0f}, {1.0f, 0.0f, 0.0f}, {0.0f, 1.0f}},
+         {{ 0.5f, -0.5f,  0.0f}, {0.0f, 1.0f, 0.0f}, {1.0f, 1.0f}},
+         {{ 0.5f,  0.5f,  0.0f}, {0.0f, 0.0f, 1.0f}, {1.0f, 0.0f}},
+         {{-0.5f,  0.5f,  0.0f}, {1.0f, 1.0f, 1.0f}, {0.0f, 0.0f}}
+         }), {
+            0, 1, 2, 2, 3, 0
+      }, {
+         mat4(1.0f)
+      }, false);
+
+   texturedSquare->model_base =
+      translate(mat4(1.0f), vec3(0.0f, 0.0f, -1.5f));
+   texturedSquare->modified = true;
+
+   modelPipeline.createDescriptorSetLayout();
+   modelPipeline.createPipeline("shaders/model-vert.spv", "shaders/model-frag.spv");
+   modelPipeline.createDescriptorPool(swapChainImages);
+   modelPipeline.createDescriptorSets(swapChainImages);
+
+   shipPipeline.addAttribute(VK_FORMAT_R32G32B32_SFLOAT, offset_of(&ShipVertex::pos));
+   shipPipeline.addAttribute(VK_FORMAT_R32G32B32_SFLOAT, offset_of(&ShipVertex::color));
+   shipPipeline.addAttribute(VK_FORMAT_R32G32B32_SFLOAT, offset_of(&ShipVertex::normal));
+   shipPipeline.addAttribute(VK_FORMAT_R32_UINT, offset_of(&ShipVertex::objIndex));
+
+   createBufferSet(sizeof(UBO_VP_mats), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
+      uniformBuffers_shipPipeline, uniformBuffersMemory_shipPipeline, uniformBufferInfoList_shipPipeline);
+
+   shipPipeline.addDescriptorInfo(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
+      VK_SHADER_STAGE_VERTEX_BIT, &uniformBufferInfoList_shipPipeline);
+   shipPipeline.addStorageDescriptor(VK_SHADER_STAGE_VERTEX_BIT);
+
+   // TODO: With the normals, indexing basically becomes pointless since no vertices will have exactly
+   // the same data. Add an option to make some pipelines not use indexing
+   SceneObject<ShipVertex, SSBO_ModelObject>& ship = addObject(shipObjects, shipPipeline,
+      addObjectIndex<ShipVertex>(shipObjects.size(),
+         addVertexNormals<ShipVertex>({
+
+            //back
+            {{ -0.5f,   0.3f,   0.0f}, {0.0f, 0.0f, 0.3f}},
+            {{ -0.5f,   0.0f,   0.0f}, {0.0f, 0.0f, 0.3f}},
+            {{  0.5f,   0.0f,   0.0f}, {0.0f, 0.0f, 0.3f}},
+            {{ -0.5f,   0.3f,   0.0f}, {0.0f, 0.0f, 0.3f}},
+            {{  0.5f,   0.0f,   0.0f}, {0.0f, 0.0f, 0.3f}},
+            {{  0.5f,   0.3f,   0.0f}, {0.0f, 0.0f, 0.3f}},
+
+            // left back
+            {{ -0.5f,   0.3f,  -2.0f}, {0.0f, 0.0f, 0.3f}},
+            {{ -0.5f,   0.0f,  -2.0f}, {0.0f, 0.0f, 0.3f}},
+            {{ -0.5f,   0.0f,   0.0f}, {0.0f, 0.0f, 0.3f}},
+            {{ -0.5f,   0.3f,  -2.0f}, {0.0f, 0.0f, 0.3f}},
+            {{ -0.5f,   0.0f,   0.0f}, {0.0f, 0.0f, 0.3f}},
+            {{ -0.5f,   0.3f,   0.0f}, {0.0f, 0.0f, 0.3f}},
+
+            // right back
+            {{  0.5f,   0.3f,   0.0f}, {0.0f, 0.0f, 0.3f}},
+            {{  0.5f,   0.0f,   0.0f}, {0.0f, 0.0f, 0.3f}},
+            {{  0.5f,   0.0f,  -2.0f}, {0.0f, 0.0f, 0.3f}},
+            {{  0.5f,   0.3f,   0.0f}, {0.0f, 0.0f, 0.3f}},
+            {{  0.5f,   0.0f,  -2.0f}, {0.0f, 0.0f, 0.3f}},
+            {{  0.5f,   0.3f,  -2.0f}, {0.0f, 0.0f, 0.3f}},
+
+            // left mid
+            {{-0.25f,   0.3f,  -3.0f}, {0.0f, 0.0f, 0.3f}},
+            {{-0.25f,   0.0f,  -3.0f}, {0.0f, 0.0f, 0.3f}},
+            {{ -0.5f,   0.0f,  -2.0f}, {0.0f, 0.0f, 0.3f}},
+            {{-0.25f,   0.3f,  -3.0f}, {0.0f, 0.0f, 0.3f}},
+            {{ -0.5f,   0.0f,  -2.0f}, {0.0f, 0.0f, 0.3f}},
+            {{ -0.5f,   0.3f,  -2.0f}, {0.0f, 0.0f, 0.3f}},
+
+            // right mid
+            {{  0.5f,   0.3f,  -2.0f}, {0.0f, 0.0f, 0.3f}},
+            {{  0.5f,   0.0f,  -2.0f}, {0.0f, 0.0f, 0.3f}},
+            {{ 0.25f,   0.0f,  -3.0f}, {0.0f, 0.0f, 0.3f}},
+            {{  0.5f,   0.3f,  -2.0f}, {0.0f, 0.0f, 0.3f}},
+            {{ 0.25f,   0.0f,  -3.0f}, {0.0f, 0.0f, 0.3f}},
+            {{ 0.25f,   0.3f,  -3.0f}, {0.0f, 0.0f, 0.3f}},
+
+            // left front
+            {{  0.0f,   0.0f,  -3.5f}, {0.0f, 0.0f, 1.0f}},
+            {{-0.25f,   0.0f,  -3.0f}, {0.0f, 0.0f, 1.0f}},
+            {{-0.25f,   0.3f,  -3.0f}, {0.0f, 0.0f, 1.0f}},
+
+            // right front
+            {{ 0.25f,   0.3f,  -3.0f}, {0.0f, 0.0f, 1.0f}},
+            {{ 0.25f,   0.0f,  -3.0f}, {0.0f, 0.0f, 1.0f}},
+            {{  0.0f,   0.0f,  -3.5f}, {0.0f, 0.0f, 1.0f}},
+
+            // top back
+            {{ -0.5f,   0.3f,  -2.0f}, {0.0f, 0.0f, 1.0f}},
+            {{ -0.5f,   0.3f,   0.0f}, {0.0f, 0.0f, 1.0f}},
+            {{  0.5f,   0.3f,   0.0f}, {0.0f, 0.0f, 1.0f}},
+            {{ -0.5f,   0.3f,  -2.0f}, {0.0f, 0.0f, 1.0f}},
+            {{  0.5f,   0.3f,   0.0f}, {0.0f, 0.0f, 1.0f}},
+            {{  0.5f,   0.3f,  -2.0f}, {0.0f, 0.0f, 1.0f}},
+
+            // bottom back
+            {{ -0.5f,   0.0f,   0.0f}, {0.0f, 0.0f, 1.0f}},
+            {{ -0.5f,   0.0f,  -2.0f}, {0.0f, 0.0f, 1.0f}},
+            {{  0.5f,   0.0f,   0.0f}, {0.0f, 0.0f, 1.0f}},
+            {{  0.5f,   0.0f,   0.0f}, {0.0f, 0.0f, 1.0f}},
+            {{ -0.5f,   0.0f,  -2.0f}, {0.0f, 0.0f, 1.0f}},
+            {{  0.5f,   0.0f,  -2.0f}, {0.0f, 0.0f, 1.0f}},
+
+            // top mid
+            {{-0.25f,   0.3f, -3.0f}, {0.0f, 0.0f, 1.0f}},
+            {{ -0.5f,   0.3f, -2.0f}, {0.0f, 0.0f, 1.0f}},
+            {{  0.5f,   0.3f, -2.0f}, {0.0f, 0.0f, 1.0f}},
+            {{ -0.25f,  0.3f, -3.0f}, {0.0f, 0.0f, 1.0f}},
+            {{  0.5f,   0.3f, -2.0f}, {0.0f, 0.0f, 1.0f}},
+            {{ 0.25f,   0.3f, -3.0f}, {0.0f, 0.0f, 1.0f}},
+
+            // bottom mid
+            {{ -0.5f,   0.0f,  -2.0f}, {0.0f, 0.0f, 1.0f}},
+            {{-0.25f,   0.0f,  -3.0f}, {0.0f, 0.0f, 1.0f}},
+            {{  0.5f,   0.0f,  -2.0f}, {0.0f, 0.0f, 1.0f}},
+            {{  0.5f,   0.0f,  -2.0f}, {0.0f, 0.0f, 1.0f}},
+            {{-0.25f,   0.0f,  -3.0f}, {0.0f, 0.0f, 1.0f}},
+            {{ 0.25f,   0.0f,  -3.0f}, {0.0f, 0.0f, 1.0f}},
+
+            // top front
+            {{-0.25f,   0.3f,  -3.0f}, {0.0f, 0.0f, 0.3f}},
+            {{ 0.25f,   0.3f,  -3.0f}, {0.0f, 0.0f, 0.3f}},
+            {{  0.0f,   0.0f,  -3.5f}, {0.0f, 0.0f, 0.3f}},
+
+            // bottom front
+            {{ 0.25f,   0.0f,  -3.0f}, {0.0f, 0.0f, 0.3f}},
+            {{-0.25f,   0.0f,  -3.0f}, {0.0f, 0.0f, 0.3f}},
+            {{  0.0f,   0.0f,  -3.5f}, {0.0f, 0.0f, 0.3f}},
+
+            // left wing start back
+            {{ -1.5f,   0.3f,   0.0f}, {0.0f, 0.0f, 0.3f}},
+            {{ -1.5f,   0.0f,   0.0f}, {0.0f, 0.0f, 0.3f}},
+            {{ -0.5f,   0.0f,   0.0f}, {0.0f, 0.0f, 0.3f}},
+            {{ -1.5f,   0.3f,   0.0f}, {0.0f, 0.0f, 0.3f}},
+            {{ -0.5f,   0.0f,   0.0f}, {0.0f, 0.0f, 0.3f}},
+            {{ -0.5f,   0.3f,   0.0f}, {0.0f, 0.0f, 0.3f}},
+
+            // left wing start top
+            {{ -0.5f,   0.3f,  -0.3f}, {0.0f, 0.0f, 0.3f}},
+            {{ -1.3f,   0.3f,  -0.3f}, {0.0f, 0.0f, 0.3f}},
+            {{ -1.5f,   0.3f,   0.0f}, {0.0f, 0.0f, 0.3f}},
+            {{ -0.5f,   0.3f,  -0.3f}, {0.0f, 0.0f, 0.3f}},
+            {{ -1.5f,   0.3f,   0.0f}, {0.0f, 0.0f, 0.3f}},
+            {{ -0.5f,   0.3f,   0.0f}, {0.0f, 0.0f, 0.3f}},
+
+            // left wing start front
+            {{ -0.5f,   0.3f,  -0.3f}, {0.0f, 0.0f, 0.3f}},
+            {{ -0.5f,   0.0f,  -0.3f}, {0.0f, 0.0f, 0.3f}},
+            {{ -1.3f,   0.0f,  -0.3f}, {0.0f, 0.0f, 0.3f}},
+            {{ -0.5f,   0.3f,  -0.3f}, {0.0f, 0.0f, 0.3f}},
+            {{ -1.3f,   0.0f,  -0.3f}, {0.0f, 0.0f, 0.3f}},
+            {{ -1.3f,   0.3f,  -0.3f}, {0.0f, 0.0f, 0.3f}},
+
+            // left wing start bottom
+            {{ -0.5f,   0.0f,   0.0f}, {0.0f, 0.0f, 0.3f}},
+            {{ -1.5f,   0.0f,   0.0f}, {0.0f, 0.0f, 0.3f}},
+            {{ -1.3f,   0.0f,  -0.3f}, {0.0f, 0.0f, 0.3f}},
+            {{ -0.5f,   0.0f,   0.0f}, {0.0f, 0.0f, 0.3f}},
+            {{ -1.3f,   0.0f,  -0.3f}, {0.0f, 0.0f, 0.3f}},
+            {{ -0.5f,   0.0f,  -0.3f}, {0.0f, 0.0f, 0.3f}},
+
+            // left wing end outside
+            {{ -1.5f,   0.3f,   0.0f}, {0.0f, 0.0f, 0.3f}},
+            {{ -2.2f,   0.15f, -0.8f}, {0.0f, 0.0f, 0.3f}},
+            {{ -1.5f,   0.0f,   0.0f}, {0.0f, 0.0f, 0.3f}},
+
+            // left wing end top
+            {{ -1.3f,   0.3f,  -0.3f}, {0.0f, 0.0f, 0.3f}},
+            {{ -2.2f,   0.15f, -0.8f}, {0.0f, 0.0f, 0.3f}},
+            {{ -1.5f,   0.3f,   0.0f}, {0.0f, 0.0f, 0.3f}},
+
+            // left wing end front
+            {{ -1.3f,   0.0f,  -0.3f}, {0.0f, 0.0f, 0.3f}},
+            {{ -2.2f,  0.15f,  -0.8f}, {0.0f, 0.0f, 0.3f}},
+            {{ -1.3f,   0.3f,  -0.3f}, {0.0f, 0.0f, 0.3f}},
+
+            // left wing end bottom
+            {{ -1.5f,   0.0f,   0.0f}, {0.0f, 0.0f, 0.3f}},
+            {{ -2.2f,  0.15f,  -0.8f}, {0.0f, 0.0f, 0.3f}},
+            {{ -1.3f,   0.0f,  -0.3f}, {0.0f, 0.0f, 0.3f}},
+
+            // right wing start back
+            {{  1.5f,   0.0f,   0.0f}, {0.0f, 0.0f, 0.3f}},
+            {{  1.5f,   0.3f,   0.0f}, {0.0f, 0.0f, 0.3f}},
+            {{  0.5f,   0.0f,   0.0f}, {0.0f, 0.0f, 0.3f}},
+            {{  0.5f,   0.0f,   0.0f}, {0.0f, 0.0f, 0.3f}},
+            {{  1.5f,   0.3f,   0.0f}, {0.0f, 0.0f, 0.3f}},
+            {{  0.5f,   0.3f,   0.0f}, {0.0f, 0.0f, 0.3f}},
+
+            // right wing start top
+            {{  1.3f,   0.3f,  -0.3f}, {0.0f, 0.0f, 0.3f}},
+            {{  0.5f,   0.3f,  -0.3f}, {0.0f, 0.0f, 0.3f}},
+            {{  1.5f,   0.3f,   0.0f}, {0.0f, 0.0f, 0.3f}},
+            {{  1.5f,   0.3f,   0.0f}, {0.0f, 0.0f, 0.3f}},
+            {{  0.5f,   0.3f,  -0.3f}, {0.0f, 0.0f, 0.3f}},
+            {{  0.5f,   0.3f,   0.0f}, {0.0f, 0.0f, 0.3f}},
+
+            // right wing start front
+            {{  0.5f,   0.0f,  -0.3f}, {0.0f, 0.0f, 0.3f}},
+            {{  0.5f,   0.3f,  -0.3f}, {0.0f, 0.0f, 0.3f}},
+            {{  1.3f,   0.0f,  -0.3f}, {0.0f, 0.0f, 0.3f}},
+            {{  1.3f,   0.0f,  -0.3f}, {0.0f, 0.0f, 0.3f}},
+            {{  0.5f,   0.3f,  -0.3f}, {0.0f, 0.0f, 0.3f}},
+            {{  1.3f,   0.3f,  -0.3f}, {0.0f, 0.0f, 0.3f}},
+
+            // right wing start bottom
+            {{  1.5f,   0.0f,   0.0f}, {0.0f, 0.0f, 0.3f}},
+            {{  0.5f,   0.0f,   0.0f}, {0.0f, 0.0f, 0.3f}},
+            {{ 1.3f,    0.0f,  -0.3f}, {0.0f, 0.0f, 0.3f}},
+            {{ 1.3f,    0.0f,  -0.3f}, {0.0f, 0.0f, 0.3f}},
+            {{ 0.5f,    0.0f,   0.0f}, {0.0f, 0.0f, 0.3f}},
+            {{ 0.5f,    0.0f,  -0.3f}, {0.0f, 0.0f, 0.3f}},
+
+            // right wing end outside
+            {{  2.2f,   0.15f, -0.8f}, {0.0f, 0.0f, 0.3f}},
+            {{  1.5f,   0.3f,   0.0f}, {0.0f, 0.0f, 0.3f}},
+            {{  1.5f,   0.0f,   0.0f}, {0.0f, 0.0f, 0.3f}},
+
+            // right wing end top
+            {{  2.2f,  0.15f,  -0.8f}, {0.0f, 0.0f, 0.3f}},
+            {{  1.3f,   0.3f,  -0.3f}, {0.0f, 0.0f, 0.3f}},
+            {{  1.5f,   0.3f,   0.0f}, {0.0f, 0.0f, 0.3f}},
+
+            // right wing end front
+            {{  2.2f,   0.15f,  -0.8f}, {0.0f, 0.0f, 0.3f}},
+            {{  1.3f,   0.0f,   -0.3f}, {0.0f, 0.0f, 0.3f}},
+            {{  1.3f,   0.3f,   -0.3f}, {0.0f, 0.0f, 0.3f}},
+
+            // right wing end bottom
+            {{  2.2f,  0.15f,  -0.8f}, {0.0f, 0.0f, 0.3f}},
+            {{  1.5f,   0.0f,   0.0f}, {0.0f, 0.0f, 0.3f}},
+            {{  1.3f,   0.0f,  -0.3f}, {0.0f, 0.0f, 0.3f}},
+         })), {
+              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,
+             36,  37,  38,  39,  40,  41,
+             42,  43,  44,  45,  46,  47,
+             48,  49,  50,  51,  52,  53,
+             54,  55,  56,  57,  58,  59,
+             60,  61,  62,
+             63,  64,  65,
+             66,  67,  68,  69,  70,  71,
+             72,  73,  74,  75,  76,  77,
+             78,  79,  80,  81,  82,  83,
+             84,  85,  86,  87,  88,  89,
+             90,  91,  92,
+             93,  94,  95,
+             96,  97,  98,
+             99, 100, 101,
+            102, 103, 104, 105, 106, 107,
+            108, 109, 110, 111, 112, 113,
+            114, 115, 116, 117, 118, 119,
+            120, 121, 122, 123, 124, 125,
+            126, 127, 128,
+            129, 130, 131,
+            132, 133, 134,
+            135, 136, 137,
+      }, {
+         mat4(1.0f)
+      }, false);
+
+   ship.model_base =
+      translate(mat4(1.0f), vec3(0.0f, -1.2f, 1.65f)) *
+      scale(mat4(1.0f), vec3(0.1f, 0.1f, 0.1f));
+   ship.modified = true;
+
+   shipPipeline.createDescriptorSetLayout();
+   shipPipeline.createPipeline("shaders/ship-vert.spv", "shaders/ship-frag.spv");
+   shipPipeline.createDescriptorPool(swapChainImages);
+   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);
+
+   asteroidPipeline.addDescriptorInfo(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
+      VK_SHADER_STAGE_VERTEX_BIT, &uniformBufferInfoList_asteroidPipeline);
+   asteroidPipeline.addStorageDescriptor(VK_SHADER_STAGE_VERTEX_BIT);
+
+   asteroidPipeline.createDescriptorSetLayout();
+   asteroidPipeline.createPipeline("shaders/asteroid-vert.spv", "shaders/asteroid-frag.spv");
+   asteroidPipeline.createDescriptorPool(swapChainImages);
+   asteroidPipeline.createDescriptorSets(swapChainImages);
+
+   laserPipeline.addAttribute(VK_FORMAT_R32G32B32_SFLOAT, offset_of(&LaserVertex::pos));
+   laserPipeline.addAttribute(VK_FORMAT_R32G32B32_SFLOAT, offset_of(&LaserVertex::texCoord));
+   laserPipeline.addAttribute(VK_FORMAT_R32_UINT, offset_of(&LaserVertex::objIndex));
+
+   createBufferSet(sizeof(UBO_VP_mats), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
+      uniformBuffers_laserPipeline, uniformBuffersMemory_laserPipeline, uniformBufferInfoList_laserPipeline);
+
+   laserPipeline.addDescriptorInfo(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
+      VK_SHADER_STAGE_VERTEX_BIT, &uniformBufferInfoList_laserPipeline);
+   laserPipeline.addStorageDescriptor(VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT);
+   laserPipeline.addDescriptorInfo(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
+      VK_SHADER_STAGE_FRAGMENT_BIT, &laserTextureImageDescriptor);
+
+   laserPipeline.createDescriptorSetLayout();
+   laserPipeline.createPipeline("shaders/laser-vert.spv", "shaders/laser-frag.spv");
+   laserPipeline.createDescriptorPool(swapChainImages);
+   laserPipeline.createDescriptorSets(swapChainImages);
+
+   explosionPipeline.addAttribute(VK_FORMAT_R32G32B32_SFLOAT, offset_of(&ExplosionVertex::particleStartVelocity));
+   explosionPipeline.addAttribute(VK_FORMAT_R32_SFLOAT, offset_of(&ExplosionVertex::particleStartTime));
+   explosionPipeline.addAttribute(VK_FORMAT_R32_UINT, offset_of(&ExplosionVertex::objIndex));
+
+   createBufferSet(sizeof(UBO_Explosion), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
+      uniformBuffers_explosionPipeline, uniformBuffersMemory_explosionPipeline, uniformBufferInfoList_explosionPipeline);
+
+   explosionPipeline.addDescriptorInfo(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
+      VK_SHADER_STAGE_VERTEX_BIT, &uniformBufferInfoList_explosionPipeline);
+   explosionPipeline.addStorageDescriptor(VK_SHADER_STAGE_VERTEX_BIT);
+
+   explosionPipeline.createDescriptorSetLayout();
+   explosionPipeline.createPipeline("shaders/explosion-vert.spv", "shaders/explosion-frag.spv");
+   explosionPipeline.createDescriptorPool(swapChainImages);
+   explosionPipeline.createDescriptorSets(swapChainImages);
+
+   currentRenderScreenFn = &VulkanGame::renderMainScreen;
+
    ImGuiIO& io = ImGui::GetIO();
-
-   currentRenderScreenFn = &VulkanGame::renderMainScreen;
 
    initGuiValueLists(valueLists);
@@ -190,475 +559,13 @@
    createSwapChain();
    createImageViews();
+
+   createResourceCommandPool();
+   createImageResources();
+
    createRenderPass();
-
-   createResourceCommandPool();
    createCommandPools();
-
-   createImageResources();
    createFramebuffers();
-
-   // TODO: I think I can start setting up IMGUI here
-   // ImGui_ImplVulkan_Init will create the Vulkan pipeline for ImGui for me
-   // imgui_impl_vulkan keeps track of the imgui pipeline internally
-   // TODO: Check how the example recreates the pipeline and what code I need
-   // to copy over to do that
-
-   createImguiDescriptorPool();
-
-   IMGUI_CHECKVERSION();
-   ImGui::CreateContext();
-   ImGuiIO& io = ImGui::GetIO(); (void)io;
-   //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;     // Enable Keyboard Controls
-   //io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad;      // Enable Gamepad Controls
-
-   // Setup Dear ImGui style
-   ImGui::StyleColorsDark();
-   //ImGui::StyleColorsClassic();
-
-   // TODO: Maybe call this once and save the results since it's also called when creating the logical device
-   QueueFamilyIndices indices = VulkanUtils::findQueueFamilies(physicalDevice, vulkanSurface);
-
-   ImGui_ImplSDL2_InitForVulkan(window);
-   ImGui_ImplVulkan_InitInfo init_info = {};
-   init_info.Instance = this->instance;
-   init_info.PhysicalDevice = this->physicalDevice;
-   init_info.Device = this->device;
-   init_info.QueueFamily = indices.graphicsFamily.value();
-   init_info.Queue = graphicsQueue;
-   init_info.DescriptorPool = this->imguiDescriptorPool; // TODO: Create a descriptor pool for IMGUI
-   init_info.Allocator = nullptr;
-   init_info.MinImageCount = this->swapChainMinImageCount;
-   init_info.ImageCount = this->swapChainImageCount;
-   init_info.CheckVkResultFn = check_imgui_vk_result;
-   ImGui_ImplVulkan_Init(&init_info, this->renderPass);
-
-   cout << "Got here" << endl;
-
-   // TODO: I think I have code in VkUtil for creating VkImages, which uses command buffers
-   // Maybe check how that code works
-
-   // Upload Fonts
-   {
-      VkCommandBuffer command_buffer;
-
-      // Create the command buffer to load 
-      VkCommandBufferAllocateInfo info = {};
-      info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
-      info.commandPool = resourceCommandPool;
-      info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
-      info.commandBufferCount = 1;
-
-      VKUTIL_CHECK_RESULT(vkAllocateCommandBuffers(this->device, &info, &command_buffer),
-         "failed to allocate command buffers!");
-
-      //err = vkResetCommandPool(this->device, command_pool, 0); // Probably not really needed here since the command pool is never used before this
-      //check_vk_result(err);
-      VkCommandBufferBeginInfo begin_info = {};
-      begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
-      begin_info.flags |= VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
-      VKUTIL_CHECK_RESULT(vkBeginCommandBuffer(command_buffer, &begin_info),
-         "failed to begin recording command buffer!");
-
-      ImGui_ImplVulkan_CreateFontsTexture(command_buffer);
-
-      VkSubmitInfo end_info = {};
-      end_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
-      end_info.commandBufferCount = 1;
-      end_info.pCommandBuffers = &command_buffer;
-
-      VKUTIL_CHECK_RESULT(vkEndCommandBuffer(command_buffer),
-         "failed to record command buffer!");
-
-      VKUTIL_CHECK_RESULT(vkQueueSubmit(this->graphicsQueue, 1, &end_info, VK_NULL_HANDLE),
-         "failed to submit draw command buffer!");
-
-      if (vkDeviceWaitIdle(this->device) != VK_SUCCESS) {
-         throw runtime_error("failed to wait for device!");
-      }
-
-      ImGui_ImplVulkan_DestroyFontUploadObjects();
-
-      // This should make the command pool reusable for later
-      VKUTIL_CHECK_RESULT(vkResetCommandPool(this->device, resourceCommandPool, 0),
-         "failed to reset command pool!");
-   }
-
-   cout << "And now here" << endl;
-
-   initMatrices();
-
-   // TODO: Figure out how much of ubo creation and associated variables should be in the pipeline class
-   // Maybe combine the ubo-related objects into a new class
-
-   initGraphicsPipelines();
-
-   modelPipeline.addAttribute(VK_FORMAT_R32G32B32_SFLOAT, offset_of(&ModelVertex::pos));
-   modelPipeline.addAttribute(VK_FORMAT_R32G32B32_SFLOAT, offset_of(&ModelVertex::color));
-   modelPipeline.addAttribute(VK_FORMAT_R32G32_SFLOAT, offset_of(&ModelVertex::texCoord));
-   modelPipeline.addAttribute(VK_FORMAT_R32_UINT, offset_of(&ModelVertex::objIndex));
-
-   createBufferSet(sizeof(UBO_VP_mats), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
-      uniformBuffers_modelPipeline, uniformBuffersMemory_modelPipeline, uniformBufferInfoList_modelPipeline);
-
-   modelPipeline.addDescriptorInfo(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
-      VK_SHADER_STAGE_VERTEX_BIT, &uniformBufferInfoList_modelPipeline);
-   modelPipeline.addStorageDescriptor(VK_SHADER_STAGE_VERTEX_BIT);
-   modelPipeline.addDescriptorInfo(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
-      VK_SHADER_STAGE_FRAGMENT_BIT, &floorTextureImageDescriptor);
-
-   SceneObject<ModelVertex, SSBO_ModelObject>* texturedSquare = nullptr;
-
-   texturedSquare = &addObject(modelObjects, modelPipeline,
-      addObjectIndex<ModelVertex>(modelObjects.size(), {
-         {{-0.5f, -0.5f,  0.0f}, {1.0f, 0.0f, 0.0f}, {0.0f, 1.0f}},
-         {{ 0.5f, -0.5f,  0.0f}, {0.0f, 1.0f, 0.0f}, {1.0f, 1.0f}},
-         {{ 0.5f,  0.5f,  0.0f}, {0.0f, 0.0f, 1.0f}, {1.0f, 0.0f}},
-         {{-0.5f,  0.5f,  0.0f}, {1.0f, 1.0f, 1.0f}, {0.0f, 0.0f}}
-      }), {
-         0, 1, 2, 2, 3, 0
-      }, {
-         mat4(1.0f)
-      }, false);
-
-   texturedSquare->model_base =
-      translate(mat4(1.0f), vec3(0.0f, 0.0f, -2.0f));
-   texturedSquare->modified = true;
-
-   texturedSquare = &addObject(modelObjects, modelPipeline,
-      addObjectIndex<ModelVertex>(modelObjects.size(), {
-         {{-0.5f, -0.5f,  0.0f}, {1.0f, 0.0f, 0.0f}, {0.0f, 1.0f}},
-         {{ 0.5f, -0.5f,  0.0f}, {0.0f, 1.0f, 0.0f}, {1.0f, 1.0f}},
-         {{ 0.5f,  0.5f,  0.0f}, {0.0f, 0.0f, 1.0f}, {1.0f, 0.0f}},
-         {{-0.5f,  0.5f,  0.0f}, {1.0f, 1.0f, 1.0f}, {0.0f, 0.0f}}
-      }), {
-         0, 1, 2, 2, 3, 0
-      }, {
-         mat4(1.0f)
-      }, false);
-
-   texturedSquare->model_base =
-      translate(mat4(1.0f), vec3(0.0f, 0.0f, -1.5f));
-   texturedSquare->modified = true;
-
-   modelPipeline.createDescriptorSetLayout();
-   modelPipeline.createPipeline("shaders/model-vert.spv", "shaders/model-frag.spv");
-   modelPipeline.createDescriptorPool(swapChainImages);
-   modelPipeline.createDescriptorSets(swapChainImages);
-
-   shipPipeline.addAttribute(VK_FORMAT_R32G32B32_SFLOAT, offset_of(&ShipVertex::pos));
-   shipPipeline.addAttribute(VK_FORMAT_R32G32B32_SFLOAT, offset_of(&ShipVertex::color));
-   shipPipeline.addAttribute(VK_FORMAT_R32G32B32_SFLOAT, offset_of(&ShipVertex::normal));
-   shipPipeline.addAttribute(VK_FORMAT_R32_UINT, offset_of(&ShipVertex::objIndex));
-
-   createBufferSet(sizeof(UBO_VP_mats), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
-      uniformBuffers_shipPipeline, uniformBuffersMemory_shipPipeline, uniformBufferInfoList_shipPipeline);
-
-   shipPipeline.addDescriptorInfo(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
-      VK_SHADER_STAGE_VERTEX_BIT, &uniformBufferInfoList_shipPipeline);
-   shipPipeline.addStorageDescriptor(VK_SHADER_STAGE_VERTEX_BIT);
-
-   // TODO: With the normals, indexing basically becomes pointless since no vertices will have exactly
-   // the same data. Add an option to make some pipelines not use indexing
-   SceneObject<ShipVertex, SSBO_ModelObject>& ship = addObject(shipObjects, shipPipeline,
-      addObjectIndex<ShipVertex>(shipObjects.size(),
-      addVertexNormals<ShipVertex>({
-
-         //back
-         {{ -0.5f,   0.3f,   0.0f}, {0.0f, 0.0f, 0.3f}},
-         {{ -0.5f,   0.0f,   0.0f}, {0.0f, 0.0f, 0.3f}},
-         {{  0.5f,   0.0f,   0.0f}, {0.0f, 0.0f, 0.3f}},
-         {{ -0.5f,   0.3f,   0.0f}, {0.0f, 0.0f, 0.3f}},
-         {{  0.5f,   0.0f,   0.0f}, {0.0f, 0.0f, 0.3f}},
-         {{  0.5f,   0.3f,   0.0f}, {0.0f, 0.0f, 0.3f}},
-
-         // left back
-         {{ -0.5f,   0.3f,  -2.0f}, {0.0f, 0.0f, 0.3f}},
-         {{ -0.5f,   0.0f,  -2.0f}, {0.0f, 0.0f, 0.3f}},
-         {{ -0.5f,   0.0f,   0.0f}, {0.0f, 0.0f, 0.3f}},
-         {{ -0.5f,   0.3f,  -2.0f}, {0.0f, 0.0f, 0.3f}},
-         {{ -0.5f,   0.0f,   0.0f}, {0.0f, 0.0f, 0.3f}},
-         {{ -0.5f,   0.3f,   0.0f}, {0.0f, 0.0f, 0.3f}},
-
-         // right back
-         {{  0.5f,   0.3f,   0.0f}, {0.0f, 0.0f, 0.3f}},
-         {{  0.5f,   0.0f,   0.0f}, {0.0f, 0.0f, 0.3f}},
-         {{  0.5f,   0.0f,  -2.0f}, {0.0f, 0.0f, 0.3f}},
-         {{  0.5f,   0.3f,   0.0f}, {0.0f, 0.0f, 0.3f}},
-         {{  0.5f,   0.0f,  -2.0f}, {0.0f, 0.0f, 0.3f}},
-         {{  0.5f,   0.3f,  -2.0f}, {0.0f, 0.0f, 0.3f}},
-
-         // left mid
-         {{-0.25f,   0.3f,  -3.0f}, {0.0f, 0.0f, 0.3f}},
-         {{-0.25f,   0.0f,  -3.0f}, {0.0f, 0.0f, 0.3f}},
-         {{ -0.5f,   0.0f,  -2.0f}, {0.0f, 0.0f, 0.3f}},
-         {{-0.25f,   0.3f,  -3.0f}, {0.0f, 0.0f, 0.3f}},
-         {{ -0.5f,   0.0f,  -2.0f}, {0.0f, 0.0f, 0.3f}},
-         {{ -0.5f,   0.3f,  -2.0f}, {0.0f, 0.0f, 0.3f}},
-
-         // right mid
-         {{  0.5f,   0.3f,  -2.0f}, {0.0f, 0.0f, 0.3f}},
-         {{  0.5f,   0.0f,  -2.0f}, {0.0f, 0.0f, 0.3f}},
-         {{ 0.25f,   0.0f,  -3.0f}, {0.0f, 0.0f, 0.3f}},
-         {{  0.5f,   0.3f,  -2.0f}, {0.0f, 0.0f, 0.3f}},
-         {{ 0.25f,   0.0f,  -3.0f}, {0.0f, 0.0f, 0.3f}},
-         {{ 0.25f,   0.3f,  -3.0f}, {0.0f, 0.0f, 0.3f}},
-
-         // left front
-         {{  0.0f,   0.0f,  -3.5f}, {0.0f, 0.0f, 1.0f}},
-         {{-0.25f,   0.0f,  -3.0f}, {0.0f, 0.0f, 1.0f}},
-         {{-0.25f,   0.3f,  -3.0f}, {0.0f, 0.0f, 1.0f}},
-
-         // right front
-         {{ 0.25f,   0.3f,  -3.0f}, {0.0f, 0.0f, 1.0f}},
-         {{ 0.25f,   0.0f,  -3.0f}, {0.0f, 0.0f, 1.0f}},
-         {{  0.0f,   0.0f,  -3.5f}, {0.0f, 0.0f, 1.0f}},
-
-         // top back
-         {{ -0.5f,   0.3f,  -2.0f}, {0.0f, 0.0f, 1.0f}},
-         {{ -0.5f,   0.3f,   0.0f}, {0.0f, 0.0f, 1.0f}},
-         {{  0.5f,   0.3f,   0.0f}, {0.0f, 0.0f, 1.0f}},
-         {{ -0.5f,   0.3f,  -2.0f}, {0.0f, 0.0f, 1.0f}},
-         {{  0.5f,   0.3f,   0.0f}, {0.0f, 0.0f, 1.0f}},
-         {{  0.5f,   0.3f,  -2.0f}, {0.0f, 0.0f, 1.0f}},
-
-         // bottom back
-         {{ -0.5f,   0.0f,   0.0f}, {0.0f, 0.0f, 1.0f}},
-         {{ -0.5f,   0.0f,  -2.0f}, {0.0f, 0.0f, 1.0f}},
-         {{  0.5f,   0.0f,   0.0f}, {0.0f, 0.0f, 1.0f}},
-         {{  0.5f,   0.0f,   0.0f}, {0.0f, 0.0f, 1.0f}},
-         {{ -0.5f,   0.0f,  -2.0f}, {0.0f, 0.0f, 1.0f}},
-         {{  0.5f,   0.0f,  -2.0f}, {0.0f, 0.0f, 1.0f}},
-
-         // top mid
-         {{-0.25f,   0.3f, -3.0f}, {0.0f, 0.0f, 1.0f}},
-         {{ -0.5f,   0.3f, -2.0f}, {0.0f, 0.0f, 1.0f}},
-         {{  0.5f,   0.3f, -2.0f}, {0.0f, 0.0f, 1.0f}},
-         {{ -0.25f,  0.3f, -3.0f}, {0.0f, 0.0f, 1.0f}},
-         {{  0.5f,   0.3f, -2.0f}, {0.0f, 0.0f, 1.0f}},
-         {{ 0.25f,   0.3f, -3.0f}, {0.0f, 0.0f, 1.0f}},
-
-         // bottom mid
-         {{ -0.5f,   0.0f,  -2.0f}, {0.0f, 0.0f, 1.0f}},
-         {{-0.25f,   0.0f,  -3.0f}, {0.0f, 0.0f, 1.0f}},
-         {{  0.5f,   0.0f,  -2.0f}, {0.0f, 0.0f, 1.0f}},
-         {{  0.5f,   0.0f,  -2.0f}, {0.0f, 0.0f, 1.0f}},
-         {{-0.25f,   0.0f,  -3.0f}, {0.0f, 0.0f, 1.0f}},
-         {{ 0.25f,   0.0f,  -3.0f}, {0.0f, 0.0f, 1.0f}},
-
-         // top front
-         {{-0.25f,   0.3f,  -3.0f}, {0.0f, 0.0f, 0.3f}},
-         {{ 0.25f,   0.3f,  -3.0f}, {0.0f, 0.0f, 0.3f}},
-         {{  0.0f,   0.0f,  -3.5f}, {0.0f, 0.0f, 0.3f}},
-
-         // bottom front
-         {{ 0.25f,   0.0f,  -3.0f}, {0.0f, 0.0f, 0.3f}},
-         {{-0.25f,   0.0f,  -3.0f}, {0.0f, 0.0f, 0.3f}},
-         {{  0.0f,   0.0f,  -3.5f}, {0.0f, 0.0f, 0.3f}},
-
-         // left wing start back
-         {{ -1.5f,   0.3f,   0.0f}, {0.0f, 0.0f, 0.3f}},
-         {{ -1.5f,   0.0f,   0.0f}, {0.0f, 0.0f, 0.3f}},
-         {{ -0.5f,   0.0f,   0.0f}, {0.0f, 0.0f, 0.3f}},
-         {{ -1.5f,   0.3f,   0.0f}, {0.0f, 0.0f, 0.3f}},
-         {{ -0.5f,   0.0f,   0.0f}, {0.0f, 0.0f, 0.3f}},
-         {{ -0.5f,   0.3f,   0.0f}, {0.0f, 0.0f, 0.3f}},
-
-         // left wing start top
-         {{ -0.5f,   0.3f,  -0.3f}, {0.0f, 0.0f, 0.3f}},
-         {{ -1.3f,   0.3f,  -0.3f}, {0.0f, 0.0f, 0.3f}},
-         {{ -1.5f,   0.3f,   0.0f}, {0.0f, 0.0f, 0.3f}},
-         {{ -0.5f,   0.3f,  -0.3f}, {0.0f, 0.0f, 0.3f}},
-         {{ -1.5f,   0.3f,   0.0f}, {0.0f, 0.0f, 0.3f}},
-         {{ -0.5f,   0.3f,   0.0f}, {0.0f, 0.0f, 0.3f}},
-
-         // left wing start front
-         {{ -0.5f,   0.3f,  -0.3f}, {0.0f, 0.0f, 0.3f}},
-         {{ -0.5f,   0.0f,  -0.3f}, {0.0f, 0.0f, 0.3f}},
-         {{ -1.3f,   0.0f,  -0.3f}, {0.0f, 0.0f, 0.3f}},
-         {{ -0.5f,   0.3f,  -0.3f}, {0.0f, 0.0f, 0.3f}},
-         {{ -1.3f,   0.0f,  -0.3f}, {0.0f, 0.0f, 0.3f}},
-         {{ -1.3f,   0.3f,  -0.3f}, {0.0f, 0.0f, 0.3f}},
-
-         // left wing start bottom
-         {{ -0.5f,   0.0f,   0.0f}, {0.0f, 0.0f, 0.3f}},
-         {{ -1.5f,   0.0f,   0.0f}, {0.0f, 0.0f, 0.3f}},
-         {{ -1.3f,   0.0f,  -0.3f}, {0.0f, 0.0f, 0.3f}},
-         {{ -0.5f,   0.0f,   0.0f}, {0.0f, 0.0f, 0.3f}},
-         {{ -1.3f,   0.0f,  -0.3f}, {0.0f, 0.0f, 0.3f}},
-         {{ -0.5f,   0.0f,  -0.3f}, {0.0f, 0.0f, 0.3f}},
-
-         // left wing end outside
-         {{ -1.5f,   0.3f,   0.0f}, {0.0f, 0.0f, 0.3f}},
-         {{ -2.2f,   0.15f, -0.8f}, {0.0f, 0.0f, 0.3f}},
-         {{ -1.5f,   0.0f,   0.0f}, {0.0f, 0.0f, 0.3f}},
-
-         // left wing end top
-         {{ -1.3f,   0.3f,  -0.3f}, {0.0f, 0.0f, 0.3f}},
-         {{ -2.2f,   0.15f, -0.8f}, {0.0f, 0.0f, 0.3f}},
-         {{ -1.5f,   0.3f,   0.0f}, {0.0f, 0.0f, 0.3f}},
-
-         // left wing end front
-         {{ -1.3f,   0.0f,  -0.3f}, {0.0f, 0.0f, 0.3f}},
-         {{ -2.2f,  0.15f,  -0.8f}, {0.0f, 0.0f, 0.3f}},
-         {{ -1.3f,   0.3f,  -0.3f}, {0.0f, 0.0f, 0.3f}},
-
-         // left wing end bottom
-         {{ -1.5f,   0.0f,   0.0f}, {0.0f, 0.0f, 0.3f}},
-         {{ -2.2f,  0.15f,  -0.8f}, {0.0f, 0.0f, 0.3f}},
-         {{ -1.3f,   0.0f,  -0.3f}, {0.0f, 0.0f, 0.3f}},
-
-         // right wing start back
-         {{  1.5f,   0.0f,   0.0f}, {0.0f, 0.0f, 0.3f}},
-         {{  1.5f,   0.3f,   0.0f}, {0.0f, 0.0f, 0.3f}},
-         {{  0.5f,   0.0f,   0.0f}, {0.0f, 0.0f, 0.3f}},
-         {{  0.5f,   0.0f,   0.0f}, {0.0f, 0.0f, 0.3f}},
-         {{  1.5f,   0.3f,   0.0f}, {0.0f, 0.0f, 0.3f}},
-         {{  0.5f,   0.3f,   0.0f}, {0.0f, 0.0f, 0.3f}},
-
-         // right wing start top
-         {{  1.3f,   0.3f,  -0.3f}, {0.0f, 0.0f, 0.3f}},
-         {{  0.5f,   0.3f,  -0.3f}, {0.0f, 0.0f, 0.3f}},
-         {{  1.5f,   0.3f,   0.0f}, {0.0f, 0.0f, 0.3f}},
-         {{  1.5f,   0.3f,   0.0f}, {0.0f, 0.0f, 0.3f}},
-         {{  0.5f,   0.3f,  -0.3f}, {0.0f, 0.0f, 0.3f}},
-         {{  0.5f,   0.3f,   0.0f}, {0.0f, 0.0f, 0.3f}},
-
-         // right wing start front
-         {{  0.5f,   0.0f,  -0.3f}, {0.0f, 0.0f, 0.3f}},
-         {{  0.5f,   0.3f,  -0.3f}, {0.0f, 0.0f, 0.3f}},
-         {{  1.3f,   0.0f,  -0.3f}, {0.0f, 0.0f, 0.3f}},
-         {{  1.3f,   0.0f,  -0.3f}, {0.0f, 0.0f, 0.3f}},
-         {{  0.5f,   0.3f,  -0.3f}, {0.0f, 0.0f, 0.3f}},
-         {{  1.3f,   0.3f,  -0.3f}, {0.0f, 0.0f, 0.3f}},
-
-         // right wing start bottom
-         {{  1.5f,   0.0f,   0.0f}, {0.0f, 0.0f, 0.3f}},
-         {{  0.5f,   0.0f,   0.0f}, {0.0f, 0.0f, 0.3f}},
-         {{ 1.3f,    0.0f,  -0.3f}, {0.0f, 0.0f, 0.3f}},
-         {{ 1.3f,    0.0f,  -0.3f}, {0.0f, 0.0f, 0.3f}},
-         {{ 0.5f,    0.0f,   0.0f}, {0.0f, 0.0f, 0.3f}},
-         {{ 0.5f,    0.0f,  -0.3f}, {0.0f, 0.0f, 0.3f}},
-
-         // right wing end outside
-         {{  2.2f,   0.15f, -0.8f}, {0.0f, 0.0f, 0.3f}},
-         {{  1.5f,   0.3f,   0.0f}, {0.0f, 0.0f, 0.3f}},
-         {{  1.5f,   0.0f,   0.0f}, {0.0f, 0.0f, 0.3f}},
-
-         // right wing end top
-         {{  2.2f,  0.15f,  -0.8f}, {0.0f, 0.0f, 0.3f}},
-         {{  1.3f,   0.3f,  -0.3f}, {0.0f, 0.0f, 0.3f}},
-         {{  1.5f,   0.3f,   0.0f}, {0.0f, 0.0f, 0.3f}},
-
-         // right wing end front
-         {{  2.2f,   0.15f,  -0.8f}, {0.0f, 0.0f, 0.3f}},
-         {{  1.3f,   0.0f,   -0.3f}, {0.0f, 0.0f, 0.3f}},
-         {{  1.3f,   0.3f,   -0.3f}, {0.0f, 0.0f, 0.3f}},
-
-         // right wing end bottom
-         {{  2.2f,  0.15f,  -0.8f}, {0.0f, 0.0f, 0.3f}},
-         {{  1.5f,   0.0f,   0.0f}, {0.0f, 0.0f, 0.3f}},
-         {{  1.3f,   0.0f,  -0.3f}, {0.0f, 0.0f, 0.3f}},
-      })), {
-           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,
-          36,  37,  38,  39,  40,  41,
-          42,  43,  44,  45,  46,  47,
-          48,  49,  50,  51,  52,  53,
-          54,  55,  56,  57,  58,  59,
-          60,  61,  62,
-          63,  64,  65,
-          66,  67,  68,  69,  70,  71,
-          72,  73,  74,  75,  76,  77,
-          78,  79,  80,  81,  82,  83,
-          84,  85,  86,  87,  88,  89,
-          90,  91,  92,
-          93,  94,  95,
-          96,  97,  98,
-          99, 100, 101,
-         102, 103, 104, 105, 106, 107,
-         108, 109, 110, 111, 112, 113,
-         114, 115, 116, 117, 118, 119,
-         120, 121, 122, 123, 124, 125,
-         126, 127, 128,
-         129, 130, 131,
-         132, 133, 134,
-         135, 136, 137,
-      }, {
-         mat4(1.0f)
-      }, false);
-
-   ship.model_base =
-      translate(mat4(1.0f), vec3(0.0f, -1.2f, 1.65f)) *
-      scale(mat4(1.0f), vec3(0.1f, 0.1f, 0.1f));
-   ship.modified = true;
-
-   shipPipeline.createDescriptorSetLayout();
-   shipPipeline.createPipeline("shaders/ship-vert.spv", "shaders/ship-frag.spv");
-   shipPipeline.createDescriptorPool(swapChainImages);
-   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);
-
-   asteroidPipeline.addDescriptorInfo(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
-      VK_SHADER_STAGE_VERTEX_BIT, &uniformBufferInfoList_asteroidPipeline);
-   asteroidPipeline.addStorageDescriptor(VK_SHADER_STAGE_VERTEX_BIT);
-
-   asteroidPipeline.createDescriptorSetLayout();
-   asteroidPipeline.createPipeline("shaders/asteroid-vert.spv", "shaders/asteroid-frag.spv");
-   asteroidPipeline.createDescriptorPool(swapChainImages);
-   asteroidPipeline.createDescriptorSets(swapChainImages);
-
-   laserPipeline.addAttribute(VK_FORMAT_R32G32B32_SFLOAT, offset_of(&LaserVertex::pos));
-   laserPipeline.addAttribute(VK_FORMAT_R32G32B32_SFLOAT, offset_of(&LaserVertex::texCoord));
-   laserPipeline.addAttribute(VK_FORMAT_R32_UINT, offset_of(&LaserVertex::objIndex));
-
-   createBufferSet(sizeof(UBO_VP_mats), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
-      uniformBuffers_laserPipeline, uniformBuffersMemory_laserPipeline, uniformBufferInfoList_laserPipeline);
-
-   laserPipeline.addDescriptorInfo(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
-      VK_SHADER_STAGE_VERTEX_BIT, &uniformBufferInfoList_laserPipeline);
-   laserPipeline.addStorageDescriptor(VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT);
-   laserPipeline.addDescriptorInfo(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
-      VK_SHADER_STAGE_FRAGMENT_BIT, &laserTextureImageDescriptor);
-
-   laserPipeline.createDescriptorSetLayout();
-   laserPipeline.createPipeline("shaders/laser-vert.spv", "shaders/laser-frag.spv");
-   laserPipeline.createDescriptorPool(swapChainImages);
-   laserPipeline.createDescriptorSets(swapChainImages);
-
-   explosionPipeline.addAttribute(VK_FORMAT_R32G32B32_SFLOAT, offset_of(&ExplosionVertex::particleStartVelocity));
-   explosionPipeline.addAttribute(VK_FORMAT_R32_SFLOAT, offset_of(&ExplosionVertex::particleStartTime));
-   explosionPipeline.addAttribute(VK_FORMAT_R32_UINT, offset_of(&ExplosionVertex::objIndex));
-
-   createBufferSet(sizeof(UBO_Explosion), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
-      uniformBuffers_explosionPipeline, uniformBuffersMemory_explosionPipeline, uniformBufferInfoList_explosionPipeline);
-
-   explosionPipeline.addDescriptorInfo(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
-      VK_SHADER_STAGE_VERTEX_BIT, &uniformBufferInfoList_explosionPipeline);
-   explosionPipeline.addStorageDescriptor(VK_SHADER_STAGE_VERTEX_BIT);
-
-   explosionPipeline.createDescriptorSetLayout();
-   explosionPipeline.createPipeline("shaders/explosion-vert.spv", "shaders/explosion-frag.spv");
-   explosionPipeline.createDescriptorPool(swapChainImages);
-   explosionPipeline.createDescriptorSets(swapChainImages);
-
-   cout << "Created all the graphics pipelines" << endl;
-
    createCommandBuffers();
-
    createSyncObjects();
-
-   cout << "Finished init function" << endl;
 }
 
@@ -688,5 +595,5 @@
 // TODO: Maybe changes the name to initScene() or something similar
 void VulkanGame::initMatrices() {
-   this->cam_pos = vec3(0.0f, 0.0f, 2.0f);
+   cam_pos = vec3(0.0f, 0.0f, 2.0f);
 
    float cam_yaw = 0.0f;
@@ -697,5 +604,5 @@
 
    mat4 R_view = pitch_mat * yaw_mat;
-   mat4 T_view = translate(mat4(1.0f), vec3(-this->cam_pos.x, -this->cam_pos.y, -this->cam_pos.z));
+   mat4 T_view = translate(mat4(1.0f), vec3(-cam_pos.x, -cam_pos.y, -cam_pos.z));
    viewMat = R_view * T_view;
 
@@ -733,16 +640,16 @@
    while (!done) {
 
-      this->prevTime = curTime;
-      curTime = duration<float, seconds::period>(steady_clock::now() - this->startTime).count();
-      this->elapsedTime = curTime - this->prevTime;
-
-      if (curTime - this->fpsStartTime >= 1.0f) {
-         this->fps = (float)frameCount / (curTime - this->fpsStartTime);
-
-         this->frameCount = 0;
-         this->fpsStartTime = curTime;
-      }
-
-      this->frameCount++;
+      prevTime = curTime;
+      curTime = duration<float, seconds::period>(steady_clock::now() - startTime).count();
+      elapsedTime = curTime - prevTime;
+
+      if (curTime - fpsStartTime >= 1.0f) {
+         fps = (float)frameCount / (curTime - fpsStartTime);
+
+         frameCount = 0;
+         fpsStartTime = curTime;
+      }
+
+      frameCount++;
 
       gui->processEvents();
@@ -924,4 +831,5 @@
       updateScene();
 
+      // TODO: Move this into a renderImGuiOverlay() function
       ImGui_ImplVulkan_NewFrame();
       ImGui_ImplSDL2_NewFrame(window);
@@ -1136,12 +1044,9 @@
 
 void VulkanGame::cleanup() {
+   // FIXME: We could wait on the Queue if we had the queue in wd-> (otherwise VulkanH functions can't use globals)
+   //vkQueueWaitIdle(g_Queue);
    VKUTIL_CHECK_RESULT(vkDeviceWaitIdle(device), "failed to wait for device!");
 
-   ImGui_ImplVulkan_Shutdown();
-   ImGui_ImplSDL2_Shutdown();
-   ImGui::DestroyContext();
-
-   // TODO: Probably move this into cleanupSwapChain once I finish the integration
-   destroyImguiDescriptorPool();
+   cleanupImGuiOverlay();
 
    cleanupSwapChain();
@@ -1467,4 +1372,51 @@
          VK_IMAGE_ASPECT_COLOR_BIT);
    }
+}
+
+void VulkanGame::createResourceCommandPool() {
+   QueueFamilyIndices indices = VulkanUtils::findQueueFamilies(physicalDevice, vulkanSurface);
+
+   VkCommandPoolCreateInfo poolInfo = {};
+   poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
+   poolInfo.queueFamilyIndex = indices.graphicsFamily.value();
+   poolInfo.flags = 0;
+
+   if (vkCreateCommandPool(device, &poolInfo, nullptr, &resourceCommandPool) != VK_SUCCESS) {
+      throw runtime_error("failed to create resource command pool!");
+   }
+}
+
+void VulkanGame::createImageResources() {
+   VulkanUtils::createDepthImage(device, physicalDevice, resourceCommandPool, findDepthFormat(), swapChainExtent,
+      depthImage, graphicsQueue);
+
+   createTextureSampler();
+
+   // TODO: Move all images/textures somewhere into the assets folder
+
+   VulkanUtils::createVulkanImageFromFile(device, physicalDevice, resourceCommandPool, "textures/texture.jpg",
+      floorTextureImage, graphicsQueue);
+
+   floorTextureImageDescriptor = {};
+   floorTextureImageDescriptor.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
+   floorTextureImageDescriptor.imageView = floorTextureImage.imageView;
+   floorTextureImageDescriptor.sampler = textureSampler;
+
+   VulkanUtils::createVulkanImageFromFile(device, physicalDevice, resourceCommandPool, "textures/laser.png",
+      laserTextureImage, graphicsQueue);
+
+   laserTextureImageDescriptor = {};
+   laserTextureImageDescriptor.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
+   laserTextureImageDescriptor.imageView = laserTextureImage.imageView;
+   laserTextureImageDescriptor.sampler = textureSampler;
+}
+
+VkFormat VulkanGame::findDepthFormat() {
+   return VulkanUtils::findSupportedFormat(
+      physicalDevice,
+      { VK_FORMAT_D32_SFLOAT, VK_FORMAT_D32_SFLOAT_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT },
+      VK_IMAGE_TILING_OPTIMAL,
+      VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT
+   );
 }
 
@@ -1527,26 +1479,4 @@
 }
 
-VkFormat VulkanGame::findDepthFormat() {
-   return VulkanUtils::findSupportedFormat(
-      physicalDevice,
-      { VK_FORMAT_D32_SFLOAT, VK_FORMAT_D32_SFLOAT_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT },
-      VK_IMAGE_TILING_OPTIMAL,
-      VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT
-   );
-}
-
-void VulkanGame::createResourceCommandPool() {
-   QueueFamilyIndices indices = VulkanUtils::findQueueFamilies(physicalDevice, vulkanSurface);
-
-   VkCommandPoolCreateInfo poolInfo = {};
-   poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
-   poolInfo.queueFamilyIndex = indices.graphicsFamily.value();
-   poolInfo.flags = 0;
-
-   if (vkCreateCommandPool(device, &poolInfo, nullptr, &resourceCommandPool) != VK_SUCCESS) {
-      throw runtime_error("failed to create resource command pool!");
-   }
-}
-
 void VulkanGame::createCommandPools() {
    commandPools.resize(swapChainImageCount);
@@ -1563,29 +1493,4 @@
          "failed to create graphics command pool!");
    }
-}
-
-void VulkanGame::createImageResources() {
-   VulkanUtils::createDepthImage(device, physicalDevice, resourceCommandPool, findDepthFormat(), swapChainExtent,
-      depthImage, graphicsQueue);
-
-   createTextureSampler();
-
-   // TODO: Move all images/textures somewhere into the assets folder
-
-   VulkanUtils::createVulkanImageFromFile(device, physicalDevice, resourceCommandPool, "textures/texture.jpg",
-      floorTextureImage, graphicsQueue);
-
-   floorTextureImageDescriptor = {};
-   floorTextureImageDescriptor.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
-   floorTextureImageDescriptor.imageView = floorTextureImage.imageView;
-   floorTextureImageDescriptor.sampler = textureSampler;
-
-   VulkanUtils::createVulkanImageFromFile(device, physicalDevice, resourceCommandPool, "textures/laser.png",
-      laserTextureImage, graphicsQueue);
-
-   laserTextureImageDescriptor = {};
-   laserTextureImageDescriptor.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
-   laserTextureImageDescriptor.imageView = laserTextureImage.imageView;
-   laserTextureImageDescriptor.sampler = textureSampler;
 }
 
@@ -1611,7 +1516,6 @@
    samplerInfo.maxLod = 0.0f;
 
-   if (vkCreateSampler(device, &samplerInfo, nullptr, &textureSampler) != VK_SUCCESS) {
-      throw runtime_error("failed to create texture sampler!");
-   }
+   VKUTIL_CHECK_RESULT(vkCreateSampler(device, &samplerInfo, nullptr, &textureSampler),
+      "failed to create texture sampler!");
 }
 
@@ -1653,4 +1557,31 @@
       if (vkAllocateCommandBuffers(device, &allocInfo, &commandBuffers[i]) != VK_SUCCESS) {
          throw runtime_error("failed to allocate command buffer!");
+      }
+   }
+}
+
+void VulkanGame::createSyncObjects() {
+   imageAcquiredSemaphores.resize(swapChainImageCount);
+   renderCompleteSemaphores.resize(swapChainImageCount);
+   inFlightFences.resize(swapChainImageCount);
+
+   VkSemaphoreCreateInfo semaphoreInfo = {};
+   semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
+
+   VkFenceCreateInfo fenceInfo = {};
+   fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
+   fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
+
+   for (size_t i = 0; i < swapChainImageCount; i++) {
+      if (vkCreateSemaphore(device, &semaphoreInfo, nullptr, &imageAcquiredSemaphores[i]) != VK_SUCCESS) {
+         throw runtime_error("failed to create image acquired sempahore for a frame!");
+      }
+
+      if (vkCreateSemaphore(device, &semaphoreInfo, nullptr, &renderCompleteSemaphores[i]) != VK_SUCCESS) {
+         throw runtime_error("failed to create render complete sempahore for a frame!");
+      }
+
+      if (vkCreateFence(device, &fenceInfo, nullptr, &inFlightFences[i]) != VK_SUCCESS) {
+         throw runtime_error("failed to create fence for a frame!");
       }
    }
@@ -1763,32 +1694,5 @@
 }
 
-void VulkanGame::createSyncObjects() {
-   imageAcquiredSemaphores.resize(swapChainImageCount);
-   renderCompleteSemaphores.resize(swapChainImageCount);
-   inFlightFences.resize(swapChainImageCount);
-
-   VkSemaphoreCreateInfo semaphoreInfo = {};
-   semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
-
-   VkFenceCreateInfo fenceInfo = {};
-   fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
-   fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
-
-   for (size_t i = 0; i < swapChainImageCount; i++) {
-      if (vkCreateSemaphore(device, &semaphoreInfo, nullptr, &imageAcquiredSemaphores[i]) != VK_SUCCESS) {
-         throw runtime_error("failed to create image acquired sempahore for a frame!");
-      }
-
-      if (vkCreateSemaphore(device, &semaphoreInfo, nullptr, &renderCompleteSemaphores[i]) != VK_SUCCESS) {
-         throw runtime_error("failed to create render complete sempahore for a frame!");
-      }
-
-      if (vkCreateFence(device, &fenceInfo, nullptr, &inFlightFences[i]) != VK_SUCCESS) {
-         throw runtime_error("failed to create fence for a frame!");
-      }
-   }
-}
-
-void VulkanGame::createImguiDescriptorPool() {
+void VulkanGame::initImGuiOverlay() {
    vector<VkDescriptorPoolSize> pool_sizes{
        { VK_DESCRIPTOR_TYPE_SAMPLER, 1000 },
@@ -1811,11 +1715,87 @@
    pool_info.poolSizeCount = static_cast<uint32_t>(pool_sizes.size());
    pool_info.pPoolSizes = pool_sizes.data();
-   if (vkCreateDescriptorPool(device, &pool_info, nullptr, &imguiDescriptorPool) != VK_SUCCESS) {
-      throw runtime_error("failed to create IMGUI descriptor pool!");
-   }
-}
-
-void VulkanGame::destroyImguiDescriptorPool() {
+
+   VKUTIL_CHECK_RESULT(vkCreateDescriptorPool(device, &pool_info, nullptr, &imguiDescriptorPool),
+      "failed to create IMGUI descriptor pool!");
+
+   // TODO: Do this in one place and save it instead of redoing it every time I need a queue family index
+   QueueFamilyIndices indices = VulkanUtils::findQueueFamilies(physicalDevice, vulkanSurface);
+
+   // Setup Dear ImGui context
+   IMGUI_CHECKVERSION();
+   ImGui::CreateContext();
+   ImGuiIO& io = ImGui::GetIO();
+   //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;     // Enable Keyboard Controls
+   //io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad;      // Enable Gamepad Controls
+
+   // Setup Dear ImGui style
+   ImGui::StyleColorsDark();
+   //ImGui::StyleColorsClassic();
+
+   // Setup Platform/Renderer bindings
+   ImGui_ImplSDL2_InitForVulkan(window);
+   ImGui_ImplVulkan_InitInfo init_info = {};
+   init_info.Instance = instance;
+   init_info.PhysicalDevice = physicalDevice;
+   init_info.Device = device;
+   init_info.QueueFamily = indices.graphicsFamily.value();
+   init_info.Queue = graphicsQueue;
+   init_info.DescriptorPool = imguiDescriptorPool;
+   init_info.Allocator = nullptr;
+   init_info.MinImageCount = swapChainMinImageCount;
+   init_info.ImageCount = swapChainImageCount;
+   init_info.CheckVkResultFn = check_imgui_vk_result;
+   ImGui_ImplVulkan_Init(&init_info, renderPass);
+
+   // Load Fonts
+   // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
+   // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
+   // - If the file cannot be loaded, the function will return NULL. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
+   // - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call.
+   // - Read 'docs/FONTS.md' for more instructions and details.
+   // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
+   //io.Fonts->AddFontDefault();
+   //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f);
+   //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f);
+   //io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf", 16.0f);
+   //io.Fonts->AddFontFromFileTTF("../../misc/fonts/ProggyTiny.ttf", 10.0f);
+   //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
+   //assert(font != NULL);
+
+   // Upload Fonts
+   {
+      VkCommandBuffer commandBuffer = VulkanUtils::beginSingleTimeCommands(device, resourceCommandPool);
+
+      ImGui_ImplVulkan_CreateFontsTexture(commandBuffer);
+
+      VulkanUtils::endSingleTimeCommands(device, resourceCommandPool, commandBuffer, graphicsQueue);
+
+      ImGui_ImplVulkan_DestroyFontUploadObjects();
+   }
+}
+
+void VulkanGame::cleanupImGuiOverlay() {
+   ImGui_ImplVulkan_Shutdown();
+   ImGui_ImplSDL2_Shutdown();
+   ImGui::DestroyContext();
+
    vkDestroyDescriptorPool(device, imguiDescriptorPool, nullptr);
+}
+
+void VulkanGame::createBufferSet(VkDeviceSize bufferSize, VkBufferUsageFlags flags,
+   vector<VkBuffer>& buffers, vector<VkDeviceMemory>& buffersMemory, vector<VkDescriptorBufferInfo>& bufferInfoList) {
+   buffers.resize(swapChainImageCount);
+   buffersMemory.resize(swapChainImageCount);
+   bufferInfoList.resize(swapChainImageCount);
+
+   for (size_t i = 0; i < swapChainImageCount; i++) {
+      VulkanUtils::createBuffer(device, physicalDevice, bufferSize, flags,
+         VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
+         buffers[i], buffersMemory[i]);
+
+      bufferInfoList[i].buffer = buffers[i];
+      bufferInfoList[i].offset = 0; // This is the offset from the start of the buffer, so always 0 for now
+      bufferInfoList[i].range = bufferSize; // Size of the update starting from offset, or VK_WHOLE_SIZE
+   }
 }
 
@@ -2024,21 +2004,4 @@
 }
 
-void VulkanGame::createBufferSet(VkDeviceSize bufferSize, VkBufferUsageFlags flags,
-      vector<VkBuffer>& buffers, vector<VkDeviceMemory>& buffersMemory, vector<VkDescriptorBufferInfo>& bufferInfoList) {
-   buffers.resize(swapChainImageCount);
-   buffersMemory.resize(swapChainImageCount);
-   bufferInfoList.resize(swapChainImageCount);
-
-   for (size_t i = 0; i < swapChainImageCount; i++) {
-      VulkanUtils::createBuffer(device, physicalDevice, bufferSize, flags,
-         VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
-         buffers[i], buffersMemory[i]);
-
-      bufferInfoList[i].buffer = buffers[i];
-      bufferInfoList[i].offset = 0; // This is the offset from the start of the buffer, so always 0 for now
-      bufferInfoList[i].range = bufferSize; // Size of the update starting from offset, or VK_WHOLE_SIZE
-   }
-}
-
 void VulkanGame::addExplosion(mat4 model_mat, float duration, float cur_time) {
    vector<ExplosionVertex> vertices;
@@ -2087,7 +2050,4 @@
    createSwapChain();
    createImageViews();
-   createRenderPass();
-
-   createCommandPools();
 
    // The depth buffer does need to be recreated with the swap chain since its dimensions depend on the window size
@@ -2095,7 +2055,14 @@
    VulkanUtils::createDepthImage(device, physicalDevice, resourceCommandPool, findDepthFormat(), swapChainExtent,
       depthImage, graphicsQueue);
+
+   createRenderPass();
+   createCommandPools();
    createFramebuffers();
+   createCommandBuffers();
+   createSyncObjects();
 
    // TODO: Move UBO creation/management into GraphicsPipeline_Vulkan, like I did with SSBOs
+   // TODO: Check if the shader stages and maybe some other properties of the pipeline can be re-used
+   // instead of recreated every time
 
    createBufferSet(sizeof(UBO_VP_mats), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
@@ -2138,8 +2105,4 @@
    explosionPipeline.createDescriptorPool(swapChainImages);
    explosionPipeline.createDescriptorSets(swapChainImages);
-
-   createCommandBuffers();
-
-   createSyncObjects();
 
    imageIndex = 0;
Index: vulkan-game.hpp
===================================================================
--- vulkan-game.hpp	(revision aa7e5f02d65eda57e6410dbfc26d5ef3e252bcc6)
+++ vulkan-game.hpp	(revision cefdf232d863ae4c6dd39962d3c681551bb062e9)
@@ -34,4 +34,7 @@
    const bool ENABLE_VALIDATION_LAYERS = true;
 #endif
+
+// TODO: Consider if there is a better way of dealing with all the vertex types and ssbo types, maybe
+// by consolidating some and trying to keep new ones to a minimum
 
 struct OverlayVertex {
@@ -193,4 +196,6 @@
 };
 
+// TODO: Maybe move this to a different header
+
 enum UIValueType {
    UIVALUE_INT,
@@ -208,4 +213,5 @@
 class VulkanGame {
    public:
+
       VulkanGame();
       ~VulkanGame();
@@ -213,11 +219,6 @@
       void run(int width, int height, unsigned char guiFlags);
 
-      GraphicsPipeline_Vulkan<ModelVertex, SSBO_ModelObject> modelPipeline;
-      GraphicsPipeline_Vulkan<ShipVertex, SSBO_ModelObject> shipPipeline;
-      GraphicsPipeline_Vulkan<AsteroidVertex, SSBO_Asteroid> asteroidPipeline;
-      GraphicsPipeline_Vulkan<LaserVertex, SSBO_Laser> laserPipeline;
-      GraphicsPipeline_Vulkan<ExplosionVertex, SSBO_Explosion> explosionPipeline;
-
    private:
+
       static VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback(
          VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
@@ -226,7 +227,8 @@
          void* pUserData);
 
+      // TODO: Maybe pass these in as parameters to some Camera class
       const float NEAR_CLIP = 0.1f;
       const float FAR_CLIP = 100.0f;
-      const float FOV_ANGLE = 67.0f; // means the camera lens goes from -33 deg to 33 def
+      const float FOV_ANGLE = 67.0f; // means the camera lens goes from -33 deg to 33 deg
 
       const int EXPLOSION_PARTICLE_COUNT = 300;
@@ -286,6 +288,4 @@
       bool shouldRecreateSwapChain;
 
-      VkDescriptorPool imguiDescriptorPool;
-
       VkSampler textureSampler;
 
@@ -297,4 +297,18 @@
 
       mat4 viewMat, projMat;
+
+      // Maybe at some point create an imgui pipeline class, but I don't think it makes sense right now
+      VkDescriptorPool imguiDescriptorPool;
+
+      // TODO: Probably restructure the GraphicsPipeline_Vulkan class based on what I learned about descriptors and textures
+      // while working on graphics-library. Double-check exactly what this was and note it down here.
+      // Basically, I think the point was that if I have several modesl that all use the same shaders and, therefore,
+      // the same pipeline, but use different textures, the approach I took when initially creating GraphicsPipeline_Vulkan
+      // wouldn't work since the whole pipeline couldn't have a common set of descriptors for the textures
+      GraphicsPipeline_Vulkan<ModelVertex, SSBO_ModelObject> modelPipeline;
+      GraphicsPipeline_Vulkan<ShipVertex, SSBO_ModelObject> shipPipeline;
+      GraphicsPipeline_Vulkan<AsteroidVertex, SSBO_Asteroid> asteroidPipeline;
+      GraphicsPipeline_Vulkan<LaserVertex, SSBO_Laser> laserPipeline;
+      GraphicsPipeline_Vulkan<ExplosionVertex, SSBO_Explosion> explosionPipeline;
 
       // TODO: Maybe make the ubo objects part of the pipeline class since there's only one ubo
@@ -371,5 +385,4 @@
 
       // TODO: Make a separate TImer class
-      // It could also deal with the steady_clock vs high_resolution_clock issue
       time_point<steady_clock> startTime;
       float fpsStartTime, curTime, prevTime, elapsedTime;
@@ -398,9 +411,9 @@
       void createSwapChain();
       void createImageViews();
+      void createResourceCommandPool();
+      void createImageResources();
+      VkFormat findDepthFormat(); // TODO: Declare/define (in the cpp file) this function in some util functions section
       void createRenderPass();
-      VkFormat findDepthFormat(); // TODO: Declare/define (in the cpp file) this function in some util functions section
-      void createResourceCommandPool();
       void createCommandPools();
-      void createImageResources();
       void createFramebuffers();
       void createCommandBuffers();
@@ -409,6 +422,10 @@
       void createTextureSampler();
 
-      void createImguiDescriptorPool();
-      void destroyImguiDescriptorPool();
+      void initImGuiOverlay();
+      void cleanupImGuiOverlay();
+
+      void createBufferSet(VkDeviceSize bufferSize, VkBufferUsageFlags flags,
+         vector<VkBuffer>& buffers, vector<VkDeviceMemory>& buffersMemory,
+         vector<VkDescriptorBufferInfo>& bufferInfoList);
 
       // TODO: Since addObject() returns a reference to the new object now,
@@ -421,4 +438,13 @@
             bool pipelinesCreated);
 
+      template<class VertexType>
+      vector<VertexType> addObjectIndex(unsigned int objIndex, vector<VertexType> vertices);
+
+      template<class VertexType>
+      vector<VertexType> addVertexNormals(vector<VertexType> vertices);
+
+      template<class VertexType, class SSBOType>
+      void centerObject(SceneObject<VertexType, SSBOType>& object);
+
       template<class VertexType, class SSBOType>
       void updateObject(vector<SceneObject<VertexType, SSBOType>>& objects,
@@ -428,13 +454,4 @@
       void updateObjectVertices(GraphicsPipeline_Vulkan<VertexType, SSBOType>& pipeline,
             SceneObject<VertexType, SSBOType>& obj, size_t index);
-
-      template<class VertexType>
-      vector<VertexType> addVertexNormals(vector<VertexType> vertices);
-
-      template<class VertexType>
-      vector<VertexType> addObjectIndex(unsigned int objIndex, vector<VertexType> vertices);
-
-      template<class VertexType, class SSBOType>
-      void centerObject(SceneObject<VertexType, SSBOType>& object);
 
       void addLaser(vec3 start, vec3 end, vec3 color, float width);
@@ -445,8 +462,4 @@
 
       void addExplosion(mat4 model_mat, float duration, float cur_time);
-
-      void createBufferSet(VkDeviceSize bufferSize, VkBufferUsageFlags flags,
-            vector<VkBuffer>& buffers, vector<VkDeviceMemory>& buffersMemory,
-            vector<VkDescriptorBufferInfo>& bufferInfoList);
 
       void renderFrame(ImDrawData* draw_data);
@@ -503,4 +516,7 @@
    SceneObject<VertexType, SSBOType>& obj = objects.back();
 
+   // TODO: Specify whether to center the object outside of this function or, worst case, maybe
+   // with a boolean being passed in here, so that I don't have to rely on checking the specific object
+   // type
    if (!is_same_v<VertexType, LaserVertex> && !is_same_v<VertexType, ExplosionVertex>) {
       centerObject(obj);
@@ -533,22 +549,11 @@
 }
 
-// TODO: Just pass in the single object instead of a list of all of them
-template<class VertexType, class SSBOType>
-void VulkanGame::updateObject(vector<SceneObject<VertexType, SSBOType>>& objects,
-      GraphicsPipeline_Vulkan<VertexType, SSBOType>& pipeline, size_t index) {
-   SceneObject<VertexType, SSBOType>& obj = objects[index];
-
-   obj.ssbo.model = obj.model_transform * obj.model_base;
-   obj.center = vec3(obj.ssbo.model * vec4(0.0f, 0.0f, 0.0f, 1.0f));
-
-   pipeline.updateObject(index, obj.ssbo);
-
-   obj.modified = false;
-}
-
-template<class VertexType, class SSBOType>
-void VulkanGame::updateObjectVertices(GraphicsPipeline_Vulkan<VertexType, SSBOType>& pipeline,
-      SceneObject<VertexType, SSBOType>& obj, size_t index) {
-   pipeline.updateObjectVertices(index, obj.vertices, resourceCommandPool, graphicsQueue);
+template<class VertexType>
+vector<VertexType> VulkanGame::addObjectIndex(unsigned int objIndex, vector<VertexType> vertices) {
+   for (VertexType& vertex : vertices) {
+      vertex.objIndex = objIndex;
+   }
+
+   return vertices;
 }
 
@@ -557,6 +562,6 @@
    for (unsigned int i = 0; i < vertices.size(); i += 3) {
       vec3 p1 = vertices[i].pos;
-      vec3 p2 = vertices[i+1].pos;
-      vec3 p3 = vertices[i+2].pos;
+      vec3 p2 = vertices[i + 1].pos;
+      vec3 p3 = vertices[i + 2].pos;
 
       vec3 normal = normalize(cross(p2 - p1, p3 - p1));
@@ -564,15 +569,6 @@
       // Add the same normal for all 3 vertices
       vertices[i].normal = normal;
-      vertices[i+1].normal = normal;
-      vertices[i+2].normal = normal;
-   }
-
-   return vertices;
-}
-
-template<class VertexType>
-vector<VertexType> VulkanGame::addObjectIndex(unsigned int objIndex, vector<VertexType> vertices) {
-   for (VertexType& vertex : vertices) {
-      vertex.objIndex = objIndex;
+      vertices[i + 1].normal = normal;
+      vertices[i + 2].normal = normal;
    }
 
@@ -626,3 +622,23 @@
 }
 
+// TODO: Just pass in the single object instead of a list of all of them
+template<class VertexType, class SSBOType>
+void VulkanGame::updateObject(vector<SceneObject<VertexType, SSBOType>>& objects,
+      GraphicsPipeline_Vulkan<VertexType, SSBOType>& pipeline, size_t index) {
+   SceneObject<VertexType, SSBOType>& obj = objects[index];
+
+   obj.ssbo.model = obj.model_transform * obj.model_base;
+   obj.center = vec3(obj.ssbo.model * vec4(0.0f, 0.0f, 0.0f, 1.0f));
+
+   pipeline.updateObject(index, obj.ssbo);
+
+   obj.modified = false;
+}
+
+template<class VertexType, class SSBOType>
+void VulkanGame::updateObjectVertices(GraphicsPipeline_Vulkan<VertexType, SSBOType>& pipeline,
+      SceneObject<VertexType, SSBOType>& obj, size_t index) {
+   pipeline.updateObjectVertices(index, obj.vertices, resourceCommandPool, graphicsQueue);
+}
+
 #endif // _VULKAN_GAME_H
