Changeset 4a777d2 in opengl-game for sdl-game.hpp


Ignore:
Timestamp:
Apr 11, 2021, 12:09:58 AM (4 years ago)
Author:
Dmitry Portnoy <dportnoy@…>
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)
Message:

Add the model pipeline and the spinning, textured squares to SDLGame

File:
1 edited

Legend:

Unmodified
Added
Removed
  • sdl-game.hpp

    rb8efa56 r4a777d2  
    1010#include <SDL2/SDL.h>
    1111
     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
    1219#include "IMGUI/imgui_impl_vulkan.h"
    1320
    1421#include "consts.hpp"
    1522#include "vulkan-utils.hpp"
    16 
     23#include "graphics-pipeline_vulkan.hpp"
    1724#include "game-gui-sdl.hpp"
    1825
     26using namespace glm;
    1927using namespace std;
    2028using namespace std::chrono;
     
    2836#endif
    2937
     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
     41struct ModelVertex {
     42   vec3 pos;
     43   vec3 color;
     44   vec2 texCoord;
     45   vec3 normal;
     46   unsigned int objIndex;
     47};
     48
     49struct LaserVertex {
     50   vec3 pos;
     51   vec2 texCoord;
     52   unsigned int objIndex;
     53};
     54
     55struct ExplosionVertex {
     56   vec3 particleStartVelocity;
     57   float particleStartTime;
     58   unsigned int objIndex;
     59};
     60
     61struct SSBO_ModelObject {
     62   alignas(16) mat4 model;
     63};
     64
     65struct SSBO_Asteroid {
     66   alignas(16) mat4 model;
     67   alignas(4) float hp;
     68   alignas(4) unsigned int deleted;
     69};
     70
     71struct 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
     79template<class VertexType, class SSBOType>
     80struct 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
    30105// TODO: Maybe move this to a different header
    31106
     
    60135         void* pUserData);
    61136
     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
    62142      bool done;
     143
     144      vec3 cam_pos;
    63145
    64146      // TODO: Good place to start using smart pointers
     
    110192      bool shouldRecreateSwapChain;
    111193
     194      VkSampler textureSampler;
     195
     196      VulkanImage floorTextureImage;
     197      VkDescriptorImageInfo floorTextureImageDescriptor;
     198
     199      mat4 viewMat, projMat;
     200
    112201      // Maybe at some point create an imgui pipeline class, but I don't think it makes sense right now
    113202      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;
    114226
    115227      /*** High-level vars ***/
     
    133245      bool initUI(int width, int height, unsigned char guiFlags);
    134246      void initVulkan();
     247      void initGraphicsPipelines();
     248      void initMatrices();
    135249      void renderLoop();
     250      void updateScene();
    136251      void cleanup();
    137252
     
    156271      void createSyncObjects();
    157272
     273      void createTextureSampler();
     274
    158275      void initImGuiOverlay();
    159276      void cleanupImGuiOverlay();
    160277
     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
    161304      void renderFrame(ImDrawData* draw_data);
    162305      void presentFrame();
     
    178321};
    179322
     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
     331template<class VertexType, class SSBOType>
     332SceneObject<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
     382template<class VertexType>
     383vector<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
     391template<class VertexType>
     392vector<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
     409template<class VertexType, class SSBOType>
     410void 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
     459template<class VertexType, class SSBOType>
     460void 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
    180472#endif // _SDL_GAME_H
Note: See TracChangeset for help on using the changeset viewer.