Changeset 4a777d2 in opengl-game
- Timestamp:
- Apr 11, 2021, 12:09:58 AM (4 years ago)
- Branches:
- feature/imgui-sdl
- Children:
- cb6fabb, e8445f0
- Parents:
- b8efa56
- git-author:
- Dmitry Portnoy <dportnoy@…> (04/11/21 00:09:49)
- git-committer:
- Dmitry Portnoy <dportnoy@…> (04/11/21 00:09:58)
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
sdl-game.cpp
rb8efa56 r4a777d2 8 8 9 9 #include "logger.hpp" 10 #include "utils.hpp" 10 11 11 12 #include "gui/imgui/button-imgui.hpp" … … 89 90 initImGuiOverlay(); 90 91 92 // TODO: Figure out how much of ubo creation and associated variables should be in the pipeline class 93 // Maybe combine the ubo-related objects into a new class 94 95 initGraphicsPipelines(); 96 97 initMatrices(); 98 99 modelPipeline.addAttribute(VK_FORMAT_R32G32B32_SFLOAT, offset_of(&ModelVertex::pos)); 100 modelPipeline.addAttribute(VK_FORMAT_R32G32B32_SFLOAT, offset_of(&ModelVertex::color)); 101 modelPipeline.addAttribute(VK_FORMAT_R32G32_SFLOAT, offset_of(&ModelVertex::texCoord)); 102 modelPipeline.addAttribute(VK_FORMAT_R32G32B32_SFLOAT, offset_of(&ModelVertex::normal)); 103 modelPipeline.addAttribute(VK_FORMAT_R32_UINT, offset_of(&ModelVertex::objIndex)); 104 105 createBufferSet(sizeof(UBO_VP_mats), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, 106 uniformBuffers_modelPipeline, uniformBuffersMemory_modelPipeline, uniformBufferInfoList_modelPipeline); 107 108 modelPipeline.addDescriptorInfo(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 109 VK_SHADER_STAGE_VERTEX_BIT, &uniformBufferInfoList_modelPipeline); 110 modelPipeline.addStorageDescriptor(VK_SHADER_STAGE_VERTEX_BIT); 111 modelPipeline.addDescriptorInfo(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 112 VK_SHADER_STAGE_FRAGMENT_BIT, &floorTextureImageDescriptor); 113 114 SceneObject<ModelVertex, SSBO_ModelObject>* texturedSquare = nullptr; 115 116 texturedSquare = &addObject(modelObjects, modelPipeline, 117 addObjectIndex<ModelVertex>(modelObjects.size(), 118 addVertexNormals<ModelVertex>({ 119 {{-0.5f, -0.5f, 0.0f}, {1.0f, 0.0f, 0.0f}, {0.0f, 1.0f}, {1.0f, 0.0f, 0.0f}, 0}, 120 {{ 0.5f, -0.5f, 0.0f}, {0.0f, 1.0f, 0.0f}, {1.0f, 1.0f}, {1.0f, 0.0f, 0.0f}, 0}, 121 {{ 0.5f, 0.5f, 0.0f}, {0.0f, 0.0f, 1.0f}, {1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0}, 122 {{ 0.5f, 0.5f, 0.0f}, {0.0f, 0.0f, 1.0f}, {1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0}, 123 {{-0.5f, 0.5f, 0.0f}, {1.0f, 1.0f, 1.0f}, {0.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0}, 124 {{-0.5f, -0.5f, 0.0f}, {1.0f, 0.0f, 0.0f}, {0.0f, 1.0f}, {1.0f, 0.0f, 0.0f}, 0} 125 })), { 126 0, 1, 2, 3, 4, 5 127 }, { 128 mat4(1.0f) 129 }, false); 130 131 texturedSquare->model_base = 132 translate(mat4(1.0f), vec3(0.0f, 0.0f, -2.0f)); 133 texturedSquare->modified = true; 134 135 texturedSquare = &addObject(modelObjects, modelPipeline, 136 addObjectIndex<ModelVertex>(modelObjects.size(), 137 addVertexNormals<ModelVertex>({ 138 {{-0.5f, -0.5f, 0.0f}, {1.0f, 0.0f, 0.0f}, {0.0f, 1.0f}}, 139 {{ 0.5f, -0.5f, 0.0f}, {0.0f, 1.0f, 0.0f}, {1.0f, 1.0f}}, 140 {{ 0.5f, 0.5f, 0.0f}, {0.0f, 0.0f, 1.0f}, {1.0f, 0.0f}}, 141 {{ 0.5f, 0.5f, 0.0f}, {0.0f, 0.0f, 1.0f}, {1.0f, 0.0f}}, 142 {{-0.5f, 0.5f, 0.0f}, {1.0f, 1.0f, 1.0f}, {0.0f, 0.0f}}, 143 {{-0.5f, -0.5f, 0.0f}, {1.0f, 0.0f, 0.0f}, {0.0f, 1.0f}} 144 })), { 145 0, 1, 2, 3, 4, 5 146 }, { 147 mat4(1.0f) 148 }, false); 149 150 texturedSquare->model_base = 151 translate(mat4(1.0f), vec3(0.0f, 0.0f, -1.5f)); 152 texturedSquare->modified = true; 153 154 modelPipeline.createDescriptorSetLayout(); 155 modelPipeline.createPipeline("shaders/model-vert.spv", "shaders/model-frag.spv"); 156 modelPipeline.createDescriptorPool(swapChainImages); 157 modelPipeline.createDescriptorSets(swapChainImages); 158 91 159 currentRenderScreenFn = &VulkanGame::renderMainScreen; 92 160 … … 182 250 createCommandBuffers(); 183 251 createSyncObjects(); 252 } 253 254 void VulkanGame::initGraphicsPipelines() { 255 modelPipeline = GraphicsPipeline_Vulkan<ModelVertex, SSBO_ModelObject>( 256 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, physicalDevice, device, renderPass, 257 { 0, 0, (int)swapChainExtent.width, (int)swapChainExtent.height }, swapChainImages, 16, 24, 10); 258 } 259 260 // TODO: Maybe change the name to initScene() or something similar 261 void VulkanGame::initMatrices() { 262 cam_pos = vec3(0.0f, 0.0f, 2.0f); 263 264 float cam_yaw = 0.0f; 265 float cam_pitch = -50.0f; 266 267 mat4 yaw_mat = rotate(mat4(1.0f), radians(-cam_yaw), vec3(0.0f, 1.0f, 0.0f)); 268 mat4 pitch_mat = rotate(mat4(1.0f), radians(-cam_pitch), vec3(1.0f, 0.0f, 0.0f)); 269 270 mat4 R_view = pitch_mat * yaw_mat; 271 mat4 T_view = translate(mat4(1.0f), vec3(-cam_pos.x, -cam_pos.y, -cam_pos.z)); 272 viewMat = R_view * T_view; 273 274 projMat = perspective(radians(FOV_ANGLE), (float)swapChainExtent.width / (float)swapChainExtent.height, NEAR_CLIP, FAR_CLIP); 275 projMat[1][1] *= -1; // flip the y-axis so that +y is up 276 277 object_VP_mats.view = viewMat; 278 object_VP_mats.proj = projMat; 184 279 } 185 280 … … 241 336 cout << "Window resize event detected" << endl; 242 337 shouldRecreateSwapChain = true; 338 break; 339 case UI_EVENT_KEYDOWN: 340 if (e.key.repeat) { 341 break; 342 } 343 344 if (e.key.keycode == SDL_SCANCODE_ESCAPE) { 345 done = true; 346 } else if (e.key.keycode == SDL_SCANCODE_SPACE) { 347 cout << "Adding a plane" << endl; 348 float zOffset = -2.0f + (0.5f * modelObjects.size()); 349 350 SceneObject<ModelVertex, SSBO_ModelObject>& texturedSquare = 351 addObject(modelObjects, modelPipeline, 352 addObjectIndex<ModelVertex>(modelObjects.size(), 353 addVertexNormals<ModelVertex>({ 354 {{-0.5f, -0.5f, 0.0f}, {1.0f, 0.0f, 0.0f}, {0.0f, 1.0f}, {1.0f, 0.0f, 0.0f}, 0}, 355 {{ 0.5f, -0.5f, 0.0f}, {0.0f, 1.0f, 0.0f}, {1.0f, 1.0f}, {1.0f, 0.0f, 0.0f}, 0}, 356 {{ 0.5f, 0.5f, 0.0f}, {0.0f, 0.0f, 1.0f}, {1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0}, 357 {{ 0.5f, 0.5f, 0.0f}, {0.0f, 0.0f, 1.0f}, {1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0}, 358 {{-0.5f, 0.5f, 0.0f}, {1.0f, 1.0f, 1.0f}, {0.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0}, 359 {{-0.5f, -0.5f, 0.0f}, {1.0f, 0.0f, 0.0f}, {0.0f, 1.0f}, {1.0f, 0.0f, 0.0f}, 0} 360 })), { 361 0, 1, 2, 3, 4, 5 362 }, { 363 mat4(1.0f) 364 }, true); 365 366 texturedSquare.model_base = 367 translate(mat4(1.0f), vec3(0.0f, 0.0f, zOffset)); 368 texturedSquare.modified = true; 369 // START UNREVIEWED SECTION 370 // END UNREVIEWED SECTION 371 } else { 372 cout << "Key event detected" << endl; 373 } 243 374 break; 244 375 case UI_EVENT_KEYUP: … … 277 408 } 278 409 410 updateScene(); 411 279 412 // TODO: Move this into a renderImGuiOverlay() function 280 413 ImGui_ImplVulkan_NewFrame(); … … 296 429 } 297 430 431 // TODO: The only updates that need to happen once per Vulkan image are the SSBO ones, 432 // which are already handled by updateObject(). Move this code to a different place, 433 // where it will run just once per frame 434 void VulkanGame::updateScene() { 435 for (SceneObject<ModelVertex, SSBO_ModelObject>& model : this->modelObjects) { 436 model.model_transform = 437 translate(mat4(1.0f), vec3(0.0f, -2.0f, -0.0f)) * 438 rotate(mat4(1.0f), curTime * radians(90.0f), vec3(0.0f, 0.0f, 1.0f)); 439 model.modified = true; 440 } 441 442 for (size_t i = 0; i < modelObjects.size(); i++) { 443 if (modelObjects[i].modified) { 444 updateObject(modelObjects, modelPipeline, i); 445 } 446 } 447 448 VulkanUtils::copyDataToMemory(device, uniformBuffersMemory_modelPipeline[imageIndex], 0, object_VP_mats); 449 } 450 298 451 void VulkanGame::cleanup() { 299 452 // FIXME: We could wait on the Queue if we had the queue in wd-> (otherwise VulkanH functions can't use globals) … … 304 457 305 458 cleanupSwapChain(); 459 460 VulkanUtils::destroyVulkanImage(device, floorTextureImage); 461 // START UNREVIEWED SECTION 462 463 vkDestroySampler(device, textureSampler, nullptr); 464 465 modelPipeline.cleanupBuffers(); 466 467 // END UNREVIEWED SECTION 306 468 307 469 vkDestroyCommandPool(device, resourceCommandPool, nullptr); … … 638 800 VulkanUtils::createDepthImage(device, physicalDevice, resourceCommandPool, findDepthFormat(), swapChainExtent, 639 801 depthImage, graphicsQueue); 802 803 createTextureSampler(); 804 805 // TODO: Move all images/textures somewhere into the assets folder 806 807 VulkanUtils::createVulkanImageFromFile(device, physicalDevice, resourceCommandPool, "textures/texture.jpg", 808 floorTextureImage, graphicsQueue); 809 810 floorTextureImageDescriptor = {}; 811 floorTextureImageDescriptor.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; 812 floorTextureImageDescriptor.imageView = floorTextureImage.imageView; 813 floorTextureImageDescriptor.sampler = textureSampler; 640 814 } 641 815 … … 726 900 } 727 901 } 902 } 903 904 void VulkanGame::createTextureSampler() { 905 VkSamplerCreateInfo samplerInfo = {}; 906 samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; 907 samplerInfo.magFilter = VK_FILTER_LINEAR; 908 samplerInfo.minFilter = VK_FILTER_LINEAR; 909 910 samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT; 911 samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT; 912 samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT; 913 914 samplerInfo.anisotropyEnable = VK_TRUE; 915 samplerInfo.maxAnisotropy = 16; 916 samplerInfo.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK; 917 samplerInfo.unnormalizedCoordinates = VK_FALSE; 918 samplerInfo.compareEnable = VK_FALSE; 919 samplerInfo.compareOp = VK_COMPARE_OP_ALWAYS; 920 samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; 921 samplerInfo.mipLodBias = 0.0f; 922 samplerInfo.minLod = 0.0f; 923 samplerInfo.maxLod = 0.0f; 924 925 VKUTIL_CHECK_RESULT(vkCreateSampler(device, &samplerInfo, nullptr, &textureSampler), 926 "failed to create texture sampler!"); 728 927 } 729 928 … … 881 1080 } 882 1081 1082 void VulkanGame::createBufferSet(VkDeviceSize bufferSize, VkBufferUsageFlags flags, 1083 vector<VkBuffer>& buffers, vector<VkDeviceMemory>& buffersMemory, 1084 vector<VkDescriptorBufferInfo>& bufferInfoList) { 1085 buffers.resize(swapChainImageCount); 1086 buffersMemory.resize(swapChainImageCount); 1087 bufferInfoList.resize(swapChainImageCount); 1088 1089 for (size_t i = 0; i < swapChainImageCount; i++) { 1090 VulkanUtils::createBuffer(device, physicalDevice, bufferSize, flags, 1091 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, 1092 buffers[i], buffersMemory[i]); 1093 1094 bufferInfoList[i].buffer = buffers[i]; 1095 bufferInfoList[i].offset = 0; // This is the offset from the start of the buffer, so always 0 for now 1096 bufferInfoList[i].range = bufferSize; // Size of the update starting from offset, or VK_WHOLE_SIZE 1097 } 1098 } 1099 883 1100 void VulkanGame::renderFrame(ImDrawData* draw_data) { 884 1101 VkResult result = vkAcquireNextImageKHR(device, swapChain, numeric_limits<uint64_t>::max(), … … 926 1143 927 1144 vkCmdBeginRenderPass(commandBuffers[imageIndex], &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE); 1145 1146 // TODO: Find a more elegant, per-screen solution for this 1147 if (currentRenderScreenFn == &VulkanGame::renderGameScreen) { 1148 modelPipeline.createRenderCommands(commandBuffers[imageIndex], imageIndex); 1149 1150 1151 1152 1153 } 928 1154 929 1155 ImGui_ImplVulkan_RenderDrawData(draw_data, commandBuffers[imageIndex]); … … 999 1225 createSyncObjects(); 1000 1226 1001 // TODO: Update pipelines here 1227 // TODO: Move UBO creation/management into GraphicsPipeline_Vulkan, like I did with SSBOs 1228 // TODO: Check if the shader stages and maybe some other properties of the pipeline can be re-used 1229 // instead of recreated every time 1230 1231 createBufferSet(sizeof(UBO_VP_mats), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, 1232 uniformBuffers_modelPipeline, uniformBuffersMemory_modelPipeline, uniformBufferInfoList_modelPipeline); 1233 1234 modelPipeline.updateRenderPass(renderPass); 1235 modelPipeline.createPipeline("shaders/model-vert.spv", "shaders/model-frag.spv"); 1236 modelPipeline.createDescriptorPool(swapChainImages); 1237 modelPipeline.createDescriptorSets(swapChainImages); 1002 1238 1003 1239 imageIndex = 0; … … 1014 1250 vkFreeCommandBuffers(device, commandPools[i], 1, &commandBuffers[i]); 1015 1251 vkDestroyCommandPool(device, commandPools[i], nullptr); 1252 } 1253 1254 modelPipeline.cleanup(); 1255 1256 for (size_t i = 0; i < uniformBuffers_modelPipeline.size(); i++) { 1257 vkDestroyBuffer(device, uniformBuffers_modelPipeline[i], nullptr); 1258 vkFreeMemory(device, uniformBuffersMemory_modelPipeline[i], nullptr); 1016 1259 } 1017 1260 -
sdl-game.hpp
rb8efa56 r4a777d2 10 10 #include <SDL2/SDL.h> 11 11 12 #define GLM_FORCE_RADIANS 13 #define GLM_FORCE_DEPTH_ZERO_TO_ONE // Since, in Vulkan, the depth range is 0 to 1 instead of -1 to 1 14 #define GLM_FORCE_RIGHT_HANDED 15 16 #include <glm/glm.hpp> 17 #include <glm/gtc/matrix_transform.hpp> 18 12 19 #include "IMGUI/imgui_impl_vulkan.h" 13 20 14 21 #include "consts.hpp" 15 22 #include "vulkan-utils.hpp" 16 23 #include "graphics-pipeline_vulkan.hpp" 17 24 #include "game-gui-sdl.hpp" 18 25 26 using namespace glm; 19 27 using namespace std; 20 28 using namespace std::chrono; … … 28 36 #endif 29 37 38 // TODO: Consider if there is a better way of dealing with all the vertex types and ssbo types, maybe 39 // by consolidating some and trying to keep new ones to a minimum 40 41 struct ModelVertex { 42 vec3 pos; 43 vec3 color; 44 vec2 texCoord; 45 vec3 normal; 46 unsigned int objIndex; 47 }; 48 49 struct LaserVertex { 50 vec3 pos; 51 vec2 texCoord; 52 unsigned int objIndex; 53 }; 54 55 struct ExplosionVertex { 56 vec3 particleStartVelocity; 57 float particleStartTime; 58 unsigned int objIndex; 59 }; 60 61 struct SSBO_ModelObject { 62 alignas(16) mat4 model; 63 }; 64 65 struct SSBO_Asteroid { 66 alignas(16) mat4 model; 67 alignas(4) float hp; 68 alignas(4) unsigned int deleted; 69 }; 70 71 struct UBO_VP_mats { 72 alignas(16) mat4 view; 73 alignas(16) mat4 proj; 74 }; 75 76 // TODO: Change the index type to uint32_t and check the Vulkan Tutorial loading model section as a reference 77 // TODO: Create a typedef for index type so I can easily change uin16_t to something else later 78 // TODO: Maybe create a typedef for each of the templated SceneObject types 79 template<class VertexType, class SSBOType> 80 struct SceneObject { 81 vector<VertexType> vertices; 82 vector<uint16_t> indices; 83 SSBOType ssbo; 84 85 mat4 model_base; 86 mat4 model_transform; 87 88 bool modified; 89 90 // TODO: Figure out if I should make child classes that have these fields instead of putting them in the 91 // parent class 92 vec3 center; // currently only matters for asteroids 93 float radius; // currently only matters for asteroids 94 SceneObject<ModelVertex, SSBO_Asteroid>* targetAsteroid; // currently only used for lasers 95 }; 96 97 // TODO: Have to figure out how to include an optional ssbo parameter for each object 98 // Could probably use the same approach to make indices optional 99 // Figure out if there are sufficient use cases to make either of these optional or is it fine to make 100 // them mamdatory 101 102 103 // TODO: Look into using dynamic_cast to check types of SceneObject and EffectOverTime 104 30 105 // TODO: Maybe move this to a different header 31 106 … … 60 135 void* pUserData); 61 136 137 // TODO: Maybe pass these in as parameters to some Camera class 138 const float NEAR_CLIP = 0.1f; 139 const float FAR_CLIP = 100.0f; 140 const float FOV_ANGLE = 67.0f; // means the camera lens goes from -33 deg to 33 deg 141 62 142 bool done; 143 144 vec3 cam_pos; 63 145 64 146 // TODO: Good place to start using smart pointers … … 110 192 bool shouldRecreateSwapChain; 111 193 194 VkSampler textureSampler; 195 196 VulkanImage floorTextureImage; 197 VkDescriptorImageInfo floorTextureImageDescriptor; 198 199 mat4 viewMat, projMat; 200 112 201 // Maybe at some point create an imgui pipeline class, but I don't think it makes sense right now 113 202 VkDescriptorPool imguiDescriptorPool; 203 204 // TODO: Probably restructure the GraphicsPipeline_Vulkan class based on what I learned about descriptors and textures 205 // while working on graphics-library. Double-check exactly what this was and note it down here. 206 // Basically, I think the point was that if I have several models that all use the same shaders and, therefore, 207 // the same pipeline, but use different textures, the approach I took when initially creating GraphicsPipeline_Vulkan 208 // wouldn't work since the whole pipeline couldn't have a common set of descriptors for the textures 209 GraphicsPipeline_Vulkan<ModelVertex, SSBO_ModelObject> modelPipeline; 210 211 // TODO: Maybe make the ubo objects part of the pipeline class since there's only one ubo 212 // per pipeline. 213 // Or maybe create a higher level wrapper around GraphicsPipeline_Vulkan to hold things like 214 // the objects vector, the ubo, and the ssbo 215 216 // TODO: Rename *_VP_mats to *_uniforms and possibly use different types for each one 217 // if there is a need to add other uniform variables to one or more of the shaders 218 219 vector<SceneObject<ModelVertex, SSBO_ModelObject>> modelObjects; 220 221 vector<VkBuffer> uniformBuffers_modelPipeline; 222 vector<VkDeviceMemory> uniformBuffersMemory_modelPipeline; 223 vector<VkDescriptorBufferInfo> uniformBufferInfoList_modelPipeline; 224 225 UBO_VP_mats object_VP_mats; 114 226 115 227 /*** High-level vars ***/ … … 133 245 bool initUI(int width, int height, unsigned char guiFlags); 134 246 void initVulkan(); 247 void initGraphicsPipelines(); 248 void initMatrices(); 135 249 void renderLoop(); 250 void updateScene(); 136 251 void cleanup(); 137 252 … … 156 271 void createSyncObjects(); 157 272 273 void createTextureSampler(); 274 158 275 void initImGuiOverlay(); 159 276 void cleanupImGuiOverlay(); 160 277 278 void createBufferSet(VkDeviceSize bufferSize, VkBufferUsageFlags flags, 279 vector<VkBuffer>& buffers, vector<VkDeviceMemory>& buffersMemory, 280 vector<VkDescriptorBufferInfo>& bufferInfoList); 281 282 // TODO: Since addObject() returns a reference to the new object now, 283 // stop using objects.back() to access the object that was just created 284 template<class VertexType, class SSBOType> 285 SceneObject<VertexType, SSBOType>& addObject( 286 vector<SceneObject<VertexType, SSBOType>>& objects, 287 GraphicsPipeline_Vulkan<VertexType, SSBOType>& pipeline, 288 const vector<VertexType>& vertices, vector<uint16_t> indices, SSBOType ssbo, 289 bool pipelinesCreated); 290 291 template<class VertexType> 292 vector<VertexType> addObjectIndex(unsigned int objIndex, vector<VertexType> vertices); 293 294 template<class VertexType> 295 vector<VertexType> addVertexNormals(vector<VertexType> vertices); 296 297 template<class VertexType, class SSBOType> 298 void centerObject(SceneObject<VertexType, SSBOType>& object); 299 300 template<class VertexType, class SSBOType> 301 void updateObject(vector<SceneObject<VertexType, SSBOType>>& objects, 302 GraphicsPipeline_Vulkan<VertexType, SSBOType>& pipeline, size_t index); 303 161 304 void renderFrame(ImDrawData* draw_data); 162 305 void presentFrame(); … … 178 321 }; 179 322 323 // TODO: Right now, it's basically necessary to pass the identity matrix in for ssbo.model 324 // and to change the model matrix later by setting model_transform and then calling updateObject() 325 // Figure out a better way to allow the model matrix to be set during objecting creation 326 327 // TODO: Maybe return a reference to the object from this method if I decide that updating it 328 // immediately after creation is a good idea (such as setting model_base) 329 // Currently, model_base is set like this in a few places and the radius is set for asteroids 330 // to account for scaling 331 template<class VertexType, class SSBOType> 332 SceneObject<VertexType, SSBOType>& VulkanGame::addObject( 333 vector<SceneObject<VertexType, SSBOType>>& objects, 334 GraphicsPipeline_Vulkan<VertexType, SSBOType>& pipeline, 335 const vector<VertexType>& vertices, vector<uint16_t> indices, SSBOType ssbo, 336 bool pipelinesCreated) { 337 // TODO: Use the model field of ssbo to set the object's model_base 338 // currently, the passed in model is useless since it gets overridden in updateObject() anyway 339 size_t numVertices = pipeline.getNumVertices(); 340 341 for (uint16_t& idx : indices) { 342 idx += numVertices; 343 } 344 345 objects.push_back({ vertices, indices, ssbo, mat4(1.0f), mat4(1.0f), false }); 346 347 SceneObject<VertexType, SSBOType>& obj = objects.back(); 348 349 // TODO: Specify whether to center the object outside of this function or, worst case, maybe 350 // with a boolean being passed in here, so that I don't have to rely on checking the specific object 351 // type 352 if (!is_same_v<VertexType, LaserVertex> && !is_same_v<VertexType, ExplosionVertex>) { 353 centerObject(obj); 354 } 355 356 bool storageBufferResized = pipeline.addObject(obj.vertices, obj.indices, obj.ssbo, 357 resourceCommandPool, graphicsQueue); 358 359 if (pipelinesCreated) { 360 vkDeviceWaitIdle(device); 361 362 for (uint32_t i = 0; i < swapChainImageCount; i++) { 363 vkFreeCommandBuffers(device, commandPools[i], 1, &commandBuffers[i]); 364 } 365 366 // TODO: The pipeline recreation only has to be done once per frame where at least 367 // one SSBO is resized. 368 // Refactor the logic to check for any resized SSBOs after all objects for the frame 369 // are created and then recreate each of the corresponding pipelines only once per frame 370 if (storageBufferResized) { 371 pipeline.createPipeline(pipeline.vertShaderFile, pipeline.fragShaderFile); 372 pipeline.createDescriptorPool(swapChainImages); 373 pipeline.createDescriptorSets(swapChainImages); 374 } 375 376 createCommandBuffers(); 377 } 378 379 return obj; 380 } 381 382 template<class VertexType> 383 vector<VertexType> VulkanGame::addObjectIndex(unsigned int objIndex, vector<VertexType> vertices) { 384 for (VertexType& vertex : vertices) { 385 vertex.objIndex = objIndex; 386 } 387 388 return vertices; 389 } 390 391 template<class VertexType> 392 vector<VertexType> VulkanGame::addVertexNormals(vector<VertexType> vertices) { 393 for (unsigned int i = 0; i < vertices.size(); i += 3) { 394 vec3 p1 = vertices[i].pos; 395 vec3 p2 = vertices[i + 1].pos; 396 vec3 p3 = vertices[i + 2].pos; 397 398 vec3 normal = normalize(cross(p2 - p1, p3 - p1)); 399 400 // Add the same normal for all 3 vertices 401 vertices[i].normal = normal; 402 vertices[i + 1].normal = normal; 403 vertices[i + 2].normal = normal; 404 } 405 406 return vertices; 407 } 408 409 template<class VertexType, class SSBOType> 410 void VulkanGame::centerObject(SceneObject<VertexType, SSBOType>& object) { 411 vector<VertexType>& vertices = object.vertices; 412 413 float min_x = vertices[0].pos.x; 414 float max_x = vertices[0].pos.x; 415 float min_y = vertices[0].pos.y; 416 float max_y = vertices[0].pos.y; 417 float min_z = vertices[0].pos.z; 418 float max_z = vertices[0].pos.z; 419 420 // start from the second point 421 for (unsigned int i = 1; i < vertices.size(); i++) { 422 vec3& pos = vertices[i].pos; 423 424 if (min_x > pos.x) { 425 min_x = pos.x; 426 } 427 else if (max_x < pos.x) { 428 max_x = pos.x; 429 } 430 431 if (min_y > pos.y) { 432 min_y = pos.y; 433 } 434 else if (max_y < pos.y) { 435 max_y = pos.y; 436 } 437 438 if (min_z > pos.z) { 439 min_z = pos.z; 440 } 441 else if (max_z < pos.z) { 442 max_z = pos.z; 443 } 444 } 445 446 vec3 center = vec3(min_x + max_x, min_y + max_y, min_z + max_z) / 2.0f; 447 448 for (unsigned int i = 0; i < vertices.size(); i++) { 449 vertices[i].pos -= center; 450 } 451 452 object.radius = std::max(max_x - center.x, max_y - center.y); 453 object.radius = std::max(object.radius, max_z - center.z); 454 455 object.center = vec3(0.0f, 0.0f, 0.0f); 456 } 457 458 // TODO: Just pass in the single object instead of a list of all of them 459 template<class VertexType, class SSBOType> 460 void VulkanGame::updateObject(vector<SceneObject<VertexType, SSBOType>>& objects, 461 GraphicsPipeline_Vulkan<VertexType, SSBOType>& pipeline, size_t index) { 462 SceneObject<VertexType, SSBOType>& obj = objects[index]; 463 464 obj.ssbo.model = obj.model_transform * obj.model_base; 465 obj.center = vec3(obj.ssbo.model * vec4(0.0f, 0.0f, 0.0f, 1.0f)); 466 467 pipeline.updateObject(index, obj.ssbo); 468 469 obj.modified = false; 470 } 471 180 472 #endif // _SDL_GAME_H
Note:
See TracChangeset
for help on using the changeset viewer.