diff --git a/engine/xe_descriptors.cpp b/engine/xe_descriptors.cpp index 4840c9e..367b26e 100644 --- a/engine/xe_descriptors.cpp +++ b/engine/xe_descriptors.cpp @@ -2,6 +2,7 @@ #include #include +#include namespace xe { diff --git a/engine/xe_engine.cpp b/engine/xe_engine.cpp index 7a6df71..a4ddaea 100644 --- a/engine/xe_engine.cpp +++ b/engine/xe_engine.cpp @@ -35,16 +35,17 @@ std::shared_ptr Engine::loadModelFromFile(const std::string &filename) { return Model::createModelFromFile(xeDevice, filename); } -std::shared_ptr Engine::loadModelFromData(std::vector vertices, std::vector indices) { +std::shared_ptr Engine::loadModelFromData(std::vector vertexData, uint32_t vertexSize, std::vector indices) { Model::Builder builder{}; - builder.vertices = vertices; + builder.vertexData = vertexData; + builder.vertexSize = vertexSize; if(indices.size() > 0) { builder.indices = indices; } return std::make_shared(xeDevice, builder); } -std::shared_ptr Engine::loadImage(const std::string &filename) { +std::shared_ptr Engine::loadImageFromFile(const std::string &filename) { return std::make_shared(xeDevice, filename); } diff --git a/engine/xe_engine.hpp b/engine/xe_engine.hpp index 7f78239..aa1c774 100644 --- a/engine/xe_engine.hpp +++ b/engine/xe_engine.hpp @@ -26,8 +26,8 @@ class Engine { Camera& getCamera() {return xeCamera;} std::shared_ptr loadModelFromFile(const std::string &filename); - std::shared_ptr loadModelFromData(std::vector vertices, std::vector indices); - std::shared_ptr loadImage(const std::string &filename); + std::shared_ptr loadModelFromData(std::vector vertexData, uint32_t vertexSize, std::vector indices); + std::shared_ptr loadImageFromFile(const std::string &filename); bool beginFrame() { return xeRenderer.beginFrame(); } void endFrame() { xeRenderer.endFrame(); } diff --git a/engine/xe_model.cpp b/engine/xe_model.cpp index df210d8..48f9ad2 100644 --- a/engine/xe_model.cpp +++ b/engine/xe_model.cpp @@ -1,5 +1,4 @@ #include "xe_model.hpp" -#include "xe_utils.hpp" #define TINYOBJLOADER_IMPLEMENTATION #include "xe_obj_loader.hpp" @@ -10,22 +9,12 @@ #include #include #include - -namespace std { -template<> -struct hash { - size_t operator()(xe::Model::Vertex const &vertex) const { - size_t seed = 0; - xe::hashCombine(seed, vertex.position, vertex.normal, vertex.uv); - return seed; - } -}; -} +#include namespace xe { Model::Model(Device &device, const Model::Builder &builder) : xeDevice{device} { - createVertexBuffers(builder.vertices); + createVertexBuffers(builder.vertexData, builder.vertexSize); createIndexBuffers(builder.indices); } @@ -37,11 +26,10 @@ std::unique_ptr Model::createModelFromFile(Device &device, const std::str return std::make_unique(device, builder); } -void Model::createVertexBuffers(const std::vector &vertices) { - vertexCount = static_cast(vertices.size()); +void Model::createVertexBuffers(const std::vector &vertexData, uint32_t vertexSize) { + vertexCount = static_cast(vertexData.size()) / (vertexSize / 4); assert(vertexCount >= 3 && "Vertex count must be atleast 3"); - VkDeviceSize bufferSize = sizeof(vertices[0]) * vertexCount; - uint32_t vertexSize = sizeof(vertices[0]); + VkDeviceSize bufferSize = vertexData.size() * 4; Buffer stagingBuffer { xeDevice, @@ -52,7 +40,7 @@ void Model::createVertexBuffers(const std::vector &vertices) { }; stagingBuffer.map(); - stagingBuffer.writeToBuffer((void *)vertices.data()); + stagingBuffer.writeToBuffer((void *)vertexData.data()); vertexBuffer = std::make_unique( xeDevice, @@ -65,16 +53,16 @@ void Model::createVertexBuffers(const std::vector &vertices) { xeDevice.copyBuffer(stagingBuffer.getBuffer(), vertexBuffer->getBuffer(), bufferSize); } -void Model::createIndexBuffers(const std::vector &indices) { - indexCount = static_cast(indices.size()); +void Model::createIndexBuffers(const std::vector &indexData) { + indexCount = static_cast(indexData.size()); hasIndexBuffer = indexCount > 0; if (!hasIndexBuffer) { return; } - VkDeviceSize bufferSize = sizeof(indices[0]) * indexCount; - uint32_t indexSize = sizeof(indices[0]); + VkDeviceSize bufferSize = sizeof(indexData[0]) * indexCount; + uint32_t indexSize = sizeof(indexData[0]); Buffer stagingBuffer { xeDevice, @@ -85,7 +73,7 @@ void Model::createIndexBuffers(const std::vector &indices) { }; stagingBuffer.map(); - stagingBuffer.writeToBuffer((void *)indices.data()); + stagingBuffer.writeToBuffer((void *)indexData.data()); indexBuffer = std::make_unique( xeDevice, @@ -116,25 +104,6 @@ void Model::draw(VkCommandBuffer commandBuffer) { } } -std::vector Model::Vertex::getBindingDescriptions() { - std::vector bindingDescriptions(1); - bindingDescriptions[0].binding = 0; - bindingDescriptions[0].stride = sizeof(Vertex); - bindingDescriptions[0].inputRate = VK_VERTEX_INPUT_RATE_VERTEX; - return bindingDescriptions; -} - -std::vector Model::Vertex::getAttributeDescriptions() { - std::vector attributeDescptions{}; - - attributeDescptions.push_back({0, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(Vertex, position)}); - attributeDescptions.push_back({1, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(Vertex, color)}); - attributeDescptions.push_back({2, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(Vertex, normal)}); - attributeDescptions.push_back({3, 0, VK_FORMAT_R32G32_SFLOAT, offsetof(Vertex, uv)}); - - return attributeDescptions; -} - void Model::Builder::loadModel(const std::string &filepath) { tinyobj::attrib_t attrib; std::vector shapes; @@ -144,50 +113,52 @@ void Model::Builder::loadModel(const std::string &filepath) { throw std::runtime_error(warn + err); } - vertices.clear(); + vertexData.clear(); indices.clear(); + vertexSize = 0; + + bool vertex, color, normal, uvs; - std::unordered_map uniqueVertices{}; for (const auto &shape : shapes) { for (const auto &index : shape.mesh.indices) { - Vertex vertex{}; if(index.vertex_index >= 0) { - vertex.position = { - attrib.vertices[3 * index.vertex_index + 0], - attrib.vertices[3 * index.vertex_index + 1], - attrib.vertices[3 * index.vertex_index + 2] - }; + vertexData.push_back(attrib.vertices[3 * index.vertex_index + 0]); + vertexData.push_back(attrib.vertices[3 * index.vertex_index + 1]); + vertexData.push_back(attrib.vertices[3 * index.vertex_index + 2]); + vertex = true; - vertex.color = { - attrib.colors[3 * index.vertex_index + 0], - attrib.colors[3 * index.vertex_index + 1], - attrib.colors[3 * index.vertex_index + 2] - }; + vertexData.push_back(attrib.colors[3 * index.vertex_index + 0]); + vertexData.push_back(attrib.colors[3 * index.vertex_index + 1]); + vertexData.push_back(attrib.colors[3 * index.vertex_index + 2]); + color = true; } if(index.normal_index >= 0) { - vertex.normal = { - attrib.normals[3 * index.normal_index + 0], - attrib.normals[3 * index.normal_index + 1], - attrib.normals[3 * index.normal_index + 2] - }; + vertexData.push_back(attrib.normals[3 * index.normal_index + 0]); + vertexData.push_back(attrib.normals[3 * index.normal_index + 1]); + vertexData.push_back(attrib.normals[3 * index.normal_index + 2]); + normal = true; } if(index.texcoord_index >= 0) { - vertex.uv = { - attrib.texcoords[2 * index.texcoord_index + 0], - attrib.texcoords[2 * index.texcoord_index + 1], - }; + vertexData.push_back(attrib.texcoords[2 * index.texcoord_index + 0]); + vertexData.push_back(attrib.texcoords[2 * index.texcoord_index + 1]); + uvs = true; } - if (uniqueVertices.count(vertex) == 0) { - uniqueVertices[vertex] = static_cast(vertices.size()); - vertices.push_back(vertex); - } - indices.push_back(uniqueVertices[vertex]); } } + + if(vertex) + vertexSize += 12; + if(color) + vertexSize += 12; + if(normal) + vertexSize += 12; + if(uvs) + vertexSize += 8; + } } \ No newline at end of file diff --git a/engine/xe_model.hpp b/engine/xe_model.hpp index fec572f..09c5913 100644 --- a/engine/xe_model.hpp +++ b/engine/xe_model.hpp @@ -14,22 +14,10 @@ namespace xe { class Model { public: - struct Vertex { - glm::vec3 position; - glm::vec3 color; - glm::vec3 normal; - glm::vec2 uv; - - static std::vector getBindingDescriptions(); - static std::vector getAttributeDescriptions(); - - bool operator==(const Vertex &other) const { - return position == other.position && color == other.color && normal == other.normal && uv == other.uv; - } - }; - struct Builder { - std::vector vertices{}; + std::vector vertexData{}; + uint32_t vertexSize; + std::vector indices{}; void loadModel(const std::string &filepath); @@ -47,8 +35,8 @@ class Model { void draw(VkCommandBuffer commandBuffer); private: - void createVertexBuffers(const std::vector &vertices); - void createIndexBuffers(const std::vector &indices); + void createVertexBuffers(const std::vector &vertexData, uint32_t vertexSize); + void createIndexBuffers(const std::vector &indexData); Device &xeDevice; diff --git a/engine/xe_pipeline.cpp b/engine/xe_pipeline.cpp index 3f407ec..633548f 100755 --- a/engine/xe_pipeline.cpp +++ b/engine/xe_pipeline.cpp @@ -16,9 +16,11 @@ namespace xe { Device &device, const std::string& vertFilepath, const std::string& fragFilepath, - const PipelineConfigInfo& configInfo) - : xeDevice{device} { - createGraphicsPipeline(vertFilepath, fragFilepath, configInfo); + const PipelineConfigInfo& configInfo, + std::vector &attributeDescptions, + uint32_t vertexSize + ) : xeDevice{device} { + createGraphicsPipeline(vertFilepath, fragFilepath, configInfo, attributeDescptions, vertexSize); } Pipeline::~Pipeline() { @@ -48,7 +50,10 @@ namespace xe { void Pipeline::createGraphicsPipeline( const std::string& vertFilePath, const std::string& fragFilepath, - const PipelineConfigInfo& configInfo) { + const PipelineConfigInfo& configInfo, + std::vector &attributeDescptions, + uint32_t vertexSize + ) { assert( configInfo.pipelineLayout != VK_NULL_HANDLE && @@ -78,8 +83,13 @@ namespace xe { shaderStages[1].pNext = nullptr; shaderStages[1].pSpecializationInfo = nullptr; - auto bindingDescriptions = Model::Vertex::getBindingDescriptions(); - auto attributeDescptions = Model::Vertex::getAttributeDescriptions(); + VkVertexInputBindingDescription bindingDescription; + bindingDescription.binding = 0; + bindingDescription.stride = vertexSize; + bindingDescription.inputRate = VK_VERTEX_INPUT_RATE_VERTEX; + + std::vector bindingDescriptions{bindingDescription}; + VkPipelineVertexInputStateCreateInfo vertexInputInfo{}; vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; vertexInputInfo.vertexAttributeDescriptionCount = static_cast(attributeDescptions.size()); diff --git a/engine/xe_pipeline.hpp b/engine/xe_pipeline.hpp index cb601e0..14df508 100755 --- a/engine/xe_pipeline.hpp +++ b/engine/xe_pipeline.hpp @@ -33,7 +33,10 @@ class Pipeline { Device &device, const std::string& vertFilepath, const std::string& fragFilepath, - const PipelineConfigInfo& configInfo); + const PipelineConfigInfo& configInfo, + std::vector &attributeDescptions, + uint32_t vertexSize + ); ~Pipeline(); Pipeline(const Pipeline&) = delete; @@ -48,7 +51,10 @@ class Pipeline { void createGraphicsPipeline( const std::string& vertFilePath, const std::string& fragFilepath, - const PipelineConfigInfo& configInfo); + const PipelineConfigInfo& configInfo, + std::vector &attributeDescptions, + uint32_t vertexSize + ); void createShaderModule(const std::vector& code, VkShaderModule* shaderModule); diff --git a/engine/xe_render_system.cpp b/engine/xe_render_system.cpp index 4f2aadd..cf30f24 100644 --- a/engine/xe_render_system.cpp +++ b/engine/xe_render_system.cpp @@ -23,7 +23,9 @@ RenderSystem::RenderSystem( std::map uniformBindings, std::map imageBindings, uint32_t pushCunstantDataSize, - bool cullingEnabled + bool cullingEnabled, + std::vector attributeDescptions, + uint32_t vertexSize ) : xeDevice{xeEngine.xeDevice}, xeRenderer{xeEngine.xeRenderer}, xeDescriptorPool{xeEngine.xeDescriptorPool}, @@ -35,10 +37,9 @@ RenderSystem::RenderSystem( createUniformBuffers(); createDescriptorSets(); createPipelineLayout(); - createPipeline(xeRenderer.getSwapChainRenderPass(), vert, frag, cullingEnabled); + createPipeline(xeRenderer.getSwapChainRenderPass(), vert, frag, cullingEnabled, attributeDescptions, vertexSize); } - RenderSystem::~RenderSystem() { vkDestroyPipelineLayout(xeDevice.device(), pipelineLayout, nullptr); vkDestroySampler(xeDevice.device(), textureSampler, nullptr); @@ -164,7 +165,7 @@ void RenderSystem::createPipelineLayout() { } -void RenderSystem::createPipeline(VkRenderPass renderPass, std::string vert, std::string frag, bool cullingEnabled) { +void RenderSystem::createPipeline(VkRenderPass renderPass, std::string vert, std::string frag, bool cullingEnabled, std::vector attributeDescptions, uint32_t vertexSize) { assert(pipelineLayout != nullptr && "Cannot create pipeline before pipeline layout"); PipelineConfigInfo pipelineConfig{}; @@ -178,7 +179,9 @@ void RenderSystem::createPipeline(VkRenderPass renderPass, std::string vert, std xeDevice, vert, frag, - pipelineConfig + pipelineConfig, + attributeDescptions, + vertexSize ); } diff --git a/engine/xe_render_system.hpp b/engine/xe_render_system.hpp index 2b29642..fd5043f 100644 --- a/engine/xe_render_system.hpp +++ b/engine/xe_render_system.hpp @@ -11,6 +11,7 @@ #include #include +#include namespace xe { @@ -21,6 +22,21 @@ class RenderSystem { public: Builder(Engine &xeEngine, std::string vert, std::string frag) : xeEngine{xeEngine}, vert{vert}, frag{frag} {} + Builder& addVertexBinding(uint32_t binding, uint32_t dimension, uint32_t offset){ + if(dimension == 1) + attributeDescptions.push_back({binding, 0, VK_FORMAT_R32_SFLOAT, offset}); + if(dimension == 2) + attributeDescptions.push_back({binding, 0, VK_FORMAT_R32G32_SFLOAT, offset}); + if(dimension == 3) + attributeDescptions.push_back({binding, 0, VK_FORMAT_R32G32B32_SFLOAT, offset}); + return *this; + } + + Builder& setVertexSize(uint32_t size) { + vertexSize = size; + return *this; + } + Builder& addPushConstant(uint32_t size) { pushCunstantDataSize = size; return *this; @@ -42,7 +58,7 @@ class RenderSystem { } std::unique_ptr build() { - return std::make_unique(xeEngine, std::move(vert), std::move(frag), std::move(uniformBindings), std::move(imageBindings), std::move(pushCunstantDataSize), std::move(cullingEnabled)); + return std::make_unique(xeEngine, std::move(vert), std::move(frag), std::move(uniformBindings), std::move(imageBindings), std::move(pushCunstantDataSize), std::move(cullingEnabled), std::move(attributeDescptions), std::move(vertexSize)); } private: @@ -51,6 +67,9 @@ class RenderSystem { std::map imageBindings{}; uint32_t pushCunstantDataSize{0}; + std::vector attributeDescptions{}; + uint32_t vertexSize; + std::string vert; std::string frag; @@ -66,7 +85,9 @@ class RenderSystem { std::map uniformBindings, std::map imageBindings, uint32_t pushCunstantDataSize, - bool cullingEnabled + bool cullingEnabled, + std::vector attributeDescptions, + uint32_t vertexSize ); ~RenderSystem(); @@ -89,7 +110,7 @@ class RenderSystem { void createDescriptorSets(); void updateDescriptorSet(int frameIndex, bool allocate); void createPipelineLayout(); - void createPipeline(VkRenderPass renderPass, std::string vert, std::string frag, bool cullingEnabled); + void createPipeline(VkRenderPass renderPass, std::string vert, std::string frag, bool cullingEnabled, std::vector attributeDescptions, uint32_t vertexSize); bool boundPipeline{false}; bool boundDescriptor{false}; diff --git a/engine/xe_utils.hpp b/engine/xe_utils.hpp deleted file mode 100644 index 4ec88cf..0000000 --- a/engine/xe_utils.hpp +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -namespace xe { - -template -void hashCombine(std::size_t& seed, const T& v, const Rest&... rest) { - seed ^= std::hash{}(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2); - (hashCombine(seed, rest), ...); -}; - -} \ No newline at end of file diff --git a/res/shaders/simple_shader.frag b/res/shaders/simple_shader.frag index 4eaaafc..a4e2b7e 100755 --- a/res/shaders/simple_shader.frag +++ b/res/shaders/simple_shader.frag @@ -10,6 +10,11 @@ layout (binding = 0) uniform GlobalUbo { vec3 directionToLight; } ubo; +layout (binding = 2) uniform Deez { + mat4 projectionViewMatrix; + vec3 directionToLight; +} deez; + layout (binding = 1) uniform sampler2D texSampler; layout(push_constant) uniform Push { diff --git a/res/shaders/simple_shader.vert b/res/shaders/simple_shader.vert index a61fa0b..04b603e 100755 --- a/res/shaders/simple_shader.vert +++ b/res/shaders/simple_shader.vert @@ -13,6 +13,11 @@ layout (binding = 0) uniform GlobalUbo { vec3 directionToLight; } ubo; +layout (binding = 2) uniform Deez { + mat4 projectionViewMatrix; + vec3 directionToLight; +} deez; + layout (push_constant) uniform Push { mat4 modelMatrix; mat4 normalMatrix; diff --git a/src/first_app.cpp b/src/first_app.cpp index 5b2d23d..3de0a0b 100755 --- a/src/first_app.cpp +++ b/src/first_app.cpp @@ -27,8 +27,8 @@ FirstApp::~FirstApp() {} void FirstApp::run() { - std::shared_ptr image = xeEngine.loadImage("res/image/texture.png"); - std::shared_ptr image2 = xeEngine.loadImage("res/image/ltt."); + std::shared_ptr image = xeEngine.loadImageFromFile("res/image/texture.png"); + std::shared_ptr image2 = xeEngine.loadImageFromFile("res/image/scaly.png"); SimpleRenderer renderer{xeEngine, image.get()}; diff --git a/src/simple_renderer.cpp b/src/simple_renderer.cpp index 43c933d..82acb46 100644 --- a/src/simple_renderer.cpp +++ b/src/simple_renderer.cpp @@ -7,6 +7,11 @@ namespace app { SimpleRenderer::SimpleRenderer(xe::Engine &xeEngine, xe::Image *xeImage) { xeRenderSystem = xe::RenderSystem::Builder(xeEngine, "res/shaders/simple_shader.vert.spv", "res/shaders/simple_shader.frag.spv") + .addVertexBinding(0, 3, 0) + .addVertexBinding(1, 3, 12) + .addVertexBinding(2, 3, 24) + .addVertexBinding(3, 2, 36) + .setVertexSize(sizeof(Vertex)) .addPushConstant(sizeof(PushConstant)) .addUniformBinding(0, sizeof(UniformBuffer)) .addTextureBinding(1, xeImage) diff --git a/src/simple_renderer.hpp b/src/simple_renderer.hpp index 59c1e60..e0e9a93 100644 --- a/src/simple_renderer.hpp +++ b/src/simple_renderer.hpp @@ -15,6 +15,13 @@ struct PushConstant { alignas(16) glm::mat4 normalMatrix{1.f}; }; +struct Vertex { + glm::vec3 position; + glm::vec3 color; + glm::vec3 normal; + glm::vec2 uv; +}; + class SimpleRenderer { public: