diff --git a/homework/homework1/homework1.cpp b/homework/homework1/homework1.cpp index 4012170..f3c7d3b 100644 --- a/homework/homework1/homework1.cpp +++ b/homework/homework1/homework1.cpp @@ -21,27 +21,6 @@ #include "homework1.h" -VulkanglTFModel::~VulkanglTFModel() - { - for (auto node : nodes) { - delete node; - } - // Release all Vulkan resources allocated for the model - vkDestroyBuffer(vulkanDevice->logicalDevice, vertices.buffer, nullptr); - vkFreeMemory(vulkanDevice->logicalDevice, vertices.memory, nullptr); - vkDestroyBuffer(vulkanDevice->logicalDevice, indices.buffer, nullptr); - vkFreeMemory(vulkanDevice->logicalDevice, indices.memory, nullptr); - for (Image image : images) { - vkDestroyImageView(vulkanDevice->logicalDevice, image.texture.view, nullptr); - vkDestroyImage(vulkanDevice->logicalDevice, image.texture.image, nullptr); - vkDestroySampler(vulkanDevice->logicalDevice, image.texture.sampler, nullptr); - vkFreeMemory(vulkanDevice->logicalDevice, image.texture.deviceMemory, nullptr); - } - for (Skin skin : skins) - { - skin.ssbo.destroy(); - } - } /* glTF loading functions @@ -206,44 +185,48 @@ VulkanglTFModel::~VulkanglTFModel() { skins.resize(input.skins.size()); - - for (size_t i = 0; i < input.skins.size(); i++) + if (skins.size() > 0) { - tinygltf::Skin glTFSkin = input.skins[i]; - - skins[i].name = glTFSkin.name; - //follow the tree structure,find the root node of skeleton by index - skins[i].skeletonRoot = nodeFromIndex(glTFSkin.skeleton); - - //join nodes - for (int jointIndex : glTFSkin.joints) - { - Node* node = nodeFromIndex(jointIndex); - if (node) + for (size_t i = 0; i < input.skins.size(); i++) { - skins[i].joints.push_back(node); - } - } - //get the inverse bind matrices - if (glTFSkin.inverseBindMatrices > -1) - { - const tinygltf::Accessor& accessor = input.accessors[glTFSkin.inverseBindMatrices]; - const tinygltf::BufferView& bufferview = input.bufferViews[accessor.bufferView]; - const tinygltf::Buffer& buffer = input.buffers[bufferview.buffer]; - skins[i].inverseBindMatrices.resize(accessor.count); - memcpy(skins[i].inverseBindMatrices.data(), &buffer.data[accessor.byteOffset + bufferview.byteOffset], accessor.count * sizeof(glm::mat4)); + tinygltf::Skin glTFSkin = input.skins[i]; + + skins[i].name = glTFSkin.name; + //follow the tree structure,find the root node of skeleton by index + skins[i].skeletonRoot = nodeFromIndex(glTFSkin.skeleton); + + //join nodes + for (int jointIndex : glTFSkin.joints) + { + Node* node = nodeFromIndex(jointIndex); + if (node) + { + skins[i].joints.push_back(node); + } + } + //get the inverse bind matrices + if (glTFSkin.inverseBindMatrices > -1) + { + const tinygltf::Accessor& accessor = input.accessors[glTFSkin.inverseBindMatrices]; + const tinygltf::BufferView& bufferview = input.bufferViews[accessor.bufferView]; + const tinygltf::Buffer& buffer = input.buffers[bufferview.buffer]; + skins[i].inverseBindMatrices.resize(accessor.count); + memcpy(skins[i].inverseBindMatrices.data(), &buffer.data[accessor.byteOffset + bufferview.byteOffset], accessor.count * sizeof(glm::mat4)); + + //create a host visible shader buffer to store inverse bind matrices for this skin + VK_CHECK_RESULT( + vulkanDevice->createBuffer( + VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, + &skins[i].ssbo, + sizeof(glm::mat4) * skins[i].inverseBindMatrices.size(), + skins[i].inverseBindMatrices.data())); + VK_CHECK_RESULT(skins[i].ssbo.map()); + } + } - //create a host visible shader buffer to store inverse bind matrices for this skin - VK_CHECK_RESULT( - vulkanDevice->createBuffer( - VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &skins[i].ssbo, - sizeof(glm::mat4) * skins[i].inverseBindMatrices.size(), - skins[i].inverseBindMatrices.data())); - VK_CHECK_RESULT(skins[i].ssbo.map()); - } } + } @@ -542,6 +525,7 @@ VulkanglTFModel::~VulkanglTFModel() if (channel.path == "translation") { channel.node->translation = glm::mix(sampler.outputsVec4[i], sampler.outputsVec4[i + 1], ratio); + channel.node->bAnimateNode = true; } if (channel.path == "rotation") { @@ -596,7 +580,7 @@ VulkanglTFModel::~VulkanglTFModel() } // Pass the final matrix to the vertex shader using push constants vkCmdPushConstants(commandBuffer, pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(glm::mat4), &nodeMatrix); - if (skins.size() != 0) + if (skins.size() > 0) { vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 1, 1, &skins[node.skin].descriptorSet, 0, nullptr); } @@ -645,24 +629,7 @@ VulkanExample::VulkanExample(): camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 256.0f); } -VulkanExample::~VulkanExample() - { - // Clean up used Vulkan resources - // Note : Inherited destructor cleans up resources stored in base class - vkDestroyPipeline(device, pipelines.solid, nullptr); - if (pipelines.wireframe != VK_NULL_HANDLE) { - vkDestroyPipeline(device, pipelines.wireframe, nullptr); - } - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayouts.matrices, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayouts.textures, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayouts.jointMatrices, nullptr); - - - shaderData.buffer.destroy(); - - } void VulkanExample::getEnabledFeatures() { @@ -747,6 +714,7 @@ void VulkanExample::getEnabledFeatures() glTFModel.loadAnimations(glTFInput); // update joint in nodes + for (auto node : glTFModel.nodes) { glTFModel.updateJoints(node); @@ -1014,7 +982,7 @@ void VulkanExample::getEnabledFeatures() } if (!paused) { - glTFModel.updateAnimation(frameTimer,shaderData.buffer); + glTFModel.updateAnimation(frameTimer,shaderData.skinSSBO); } } diff --git a/homework/homework1/homework1.h b/homework/homework1/homework1.h index 5198a25..9c6c08a 100644 --- a/homework/homework1/homework1.h +++ b/homework/homework1/homework1.h @@ -91,7 +91,7 @@ public: } glm::mat4 matrix; bool bAnimateNode = false; - /* + ~Node() { for (auto& child : children) { delete child; @@ -99,15 +99,28 @@ public: } - */ - }; + // material data for pbr + struct MaterialData + { + vks::Buffer buffer; + VkDescriptorSet descriptorSet; + struct Values + { + glm::vec3 emissiveFactor; + glm::vec4 baseColorFactor; + }values; + }; // A glTF material stores information in e.g. the texture that is attached to it and colors struct Material { glm::vec4 baseColorFactor = glm::vec4(1.0f); uint32_t baseColorTextureIndex; + uint32_t normalMapTextureIndex; + uint32_t matalicRoughTextureIndex; + int32_t emissiveTextureIndex = -1; + MaterialData materialData; }; // Contains the texture for a single glTF image @@ -177,7 +190,27 @@ public: //VulkanglTFModel(); - ~VulkanglTFModel(); + ~VulkanglTFModel() + { + for (auto node : nodes) { + delete node; + } + // Release all Vulkan resources allocated for the model + vkDestroyBuffer(vulkanDevice->logicalDevice, vertices.buffer, nullptr); + vkFreeMemory(vulkanDevice->logicalDevice, vertices.memory, nullptr); + vkDestroyBuffer(vulkanDevice->logicalDevice, indices.buffer, nullptr); + vkFreeMemory(vulkanDevice->logicalDevice, indices.memory, nullptr); + for (auto& material : materials) + { + material.materialData.buffer.destroy(); + } + for (Image image : images) { + vkDestroyImageView(vulkanDevice->logicalDevice, image.texture.view, nullptr); + vkDestroyImage(vulkanDevice->logicalDevice, image.texture.image, nullptr); + vkDestroySampler(vulkanDevice->logicalDevice, image.texture.sampler, nullptr); + vkFreeMemory(vulkanDevice->logicalDevice, image.texture.deviceMemory, nullptr); + } + } void loadImages(tinygltf::Model& input); void loadTextures(tinygltf::Model& input); void loadMaterials(tinygltf::Model& input); @@ -198,6 +231,9 @@ class VulkanExample : public VulkanExampleBase { public: bool wireframe = false; + bool normalMapping = true; + bool ToneMapping = true; + bool pbrEnabled = true; VulkanglTFModel glTFModel; @@ -208,28 +244,117 @@ public: glm::mat4 model; glm::vec4 lightPos = glm::vec4(5.0f, 5.0f, 5.0f, 1.0f); glm::vec4 viewPos; + glm::vec4 bFlagSet = glm::vec4(0.0f, 0.0f, 0.0f, 0.0f); } values; - vks::Buffer animationBuffer; + vks::Buffer skinSSBO; } shaderData; struct Pipelines { VkPipeline solid; VkPipeline wireframe = VK_NULL_HANDLE; + VkPipeline toneMapping = VK_NULL_HANDLE; } pipelines; - VkPipelineLayout pipelineLayout; + struct PipelineLayouts + { + VkPipelineLayout pbrLayout; + VkPipelineLayout tonemappingLayout; + } pipelineLayouts; + VkPipelineLayout pipelineLayout; + + VkDescriptorSet descriptorSet; + VkDescriptorSet skinDescriptorSet; + VkDescriptorSet tonemappingDescriptorSet = VK_NULL_HANDLE; + + struct FrameBufferAttachment + { + VkImage image; + VkDeviceMemory deviceMemory; + VkImageView imageView; + VkFormat format; + + void destroy(VkDevice device) + { + vkDestroyImage(device, image, nullptr); + vkDestroyImageView(device, imageView,nullptr); + vkFreeMemory(device, deviceMemory, nullptr); + + } + }; + + struct FrameBuffer + { + int32_t width, height; + VkFramebuffer frameBuffer; + VkRenderPass renderPass; + void setSize(int32_t w, int32_t h) + { + this->width = w; + this->height = h; + } + void destroy(VkDevice device) + { + vkDestroyFramebuffer(device, frameBuffer, nullptr); + vkDestroyRenderPass(device, renderPass, nullptr); + } + }; + + struct PBRFrameBuffer { + FrameBufferAttachment color, depth; + FrameBuffer fbo; + bool bCreate = false; + } pbrFrameBuffer; + + VkSampler colorSampler; struct DescriptorSetLayouts { VkDescriptorSetLayout matrices; VkDescriptorSetLayout textures; + VkDescriptorSetLayout materialUniform; + VkDescriptorSetLayout ssbo; VkDescriptorSetLayout jointMatrices; } descriptorSetLayouts; - VkDescriptorSet descriptorSet; + struct IBLTextures + { + vks::TextureCubeMap skyboxCube; + vks::TextureCubeMap irradianceCube; + vks::TextureCubeMap prefilteredCube; + vks::Texture2D lutBrdf; + } ibltextures; + + VulkanglTFModel skyboxModel; VulkanExample(); - ~VulkanExample(); + ~VulkanExample() + { + // Clean up used Vulkan resources + // Note : Inherited destructor cleans up resources stored in base class + vkDestroyPipeline(device, pipelines.solid, nullptr); + vkDestroyPipeline(device, pipelines.toneMapping, nullptr); + if (pipelines.wireframe != VK_NULL_HANDLE) { + vkDestroyPipeline(device, pipelines.wireframe, nullptr); + } + + vkDestroyPipelineLayout(device, pipelineLayouts.pbrLayout, nullptr); + vkDestroyPipelineLayout(device, pipelineLayouts.tonemappingLayout, nullptr); + vkDestroyDescriptorSetLayout(device, descriptorSetLayouts.matrices, nullptr); + vkDestroyDescriptorSetLayout(device, descriptorSetLayouts.textures, nullptr); + vkDestroyDescriptorSetLayout(device, descriptorSetLayouts.materialUniform, nullptr); + vkDestroyDescriptorSetLayout(device, descriptorSetLayouts.ssbo, nullptr); + ibltextures.irradianceCube.destroy(); + ibltextures.skyboxCube.destroy(); + ibltextures.prefilteredCube.destroy(); + ibltextures.lutBrdf.destroy(); + pbrFrameBuffer.color.destroy(device); + pbrFrameBuffer.depth.destroy(device); + pbrFrameBuffer.fbo.destroy(device); + vkDestroySampler(device, colorSampler, nullptr); + + shaderData.buffer.destroy(); + shaderData.skinSSBO.destroy(); + } void loadglTFFile(std::string filename); virtual void getEnabledFeatures(); void buildCommandBuffers();