From 3532369f08f1322cdf92431aa3364e2a0e09052e Mon Sep 17 00:00:00 2001 From: ink-soul Date: Wed, 17 May 2023 16:50:09 +0800 Subject: [PATCH 01/22] bug fix --- CMakeSettings.json | 27 +++++++ homework/homework1/homework1.cpp | 120 +++++++++++++++---------------- 2 files changed, 84 insertions(+), 63 deletions(-) create mode 100644 CMakeSettings.json diff --git a/CMakeSettings.json b/CMakeSettings.json new file mode 100644 index 0000000..7313f2b --- /dev/null +++ b/CMakeSettings.json @@ -0,0 +1,27 @@ +{ + "configurations": [ + { + "name": "x64-Debug", + "generator": "Ninja", + "configurationType": "Debug", + "inheritEnvironments": [ "msvc_x64_x64" ], + "buildRoot": "${projectDir}\\out\\build\\${name}", + "installRoot": "${projectDir}\\out\\install\\${name}", + "cmakeCommandArgs": "", + "buildCommandArgs": "", + "ctestCommandArgs": "" + }, + { + "name": "x64-Clang-Debug", + "generator": "Ninja", + "configurationType": "Debug", + "buildRoot": "${projectDir}\\out\\build\\${name}", + "installRoot": "${projectDir}\\out\\install\\${name}", + "cmakeCommandArgs": "", + "buildCommandArgs": "", + "ctestCommandArgs": "", + "inheritEnvironments": [ "clang_cl_x64_x64" ], + "variables": [] + } + ] +} \ No newline at end of file diff --git a/homework/homework1/homework1.cpp b/homework/homework1/homework1.cpp index ccae6cd..cc23f34 100644 --- a/homework/homework1/homework1.cpp +++ b/homework/homework1/homework1.cpp @@ -157,26 +157,26 @@ VulkanglTFModel::~VulkanglTFModel() tinygltf::Animation glTFAnimation = input.animations[i]; animations[i].name = glTFAnimation.name; + // Samplers animations[i].samplers.resize(glTFAnimation.samplers.size()); for (size_t j = 0; j < glTFAnimation.samplers.size(); j++) { tinygltf::AnimationSampler glTFSampler = glTFAnimation.samplers[j]; AnimationSampler& dstSampler = animations[i].samplers[j]; dstSampler.interpolation = glTFSampler.interpolation; - //sample keyframes to input + + // Read sampler keyframe input time values { const tinygltf::Accessor& accessor = input.accessors[glTFSampler.input]; const tinygltf::BufferView& bufferView = input.bufferViews[accessor.bufferView]; const tinygltf::Buffer& buffer = input.buffers[bufferView.buffer]; - //data pointer - const void* dataptr = &buffer.data[accessor.byteOffset + bufferView.byteOffset]; - const float* buf = static_cast(dataptr); - + const void* dataPtr = &buffer.data[accessor.byteOffset + bufferView.byteOffset]; + const float* buf = static_cast(dataPtr); for (size_t index = 0; index < accessor.count; index++) { dstSampler.inputs.push_back(buf[index]); } - //switch value for correct start and end time + // Adjust animation's start and end times for (auto input : animations[i].samplers[j].inputs) { if (input < animations[i].start) @@ -189,43 +189,40 @@ VulkanglTFModel::~VulkanglTFModel() } } } - //identify accessor type for keyframes to output translate/rotate/scale values + + // Read sampler keyframe output translate/rotate/scale values { - const tinygltf::Accessor& accessor = input.accessors[glTFSampler.input]; + const tinygltf::Accessor& accessor = input.accessors[glTFSampler.output]; const tinygltf::BufferView& bufferView = input.bufferViews[accessor.bufferView]; const tinygltf::Buffer& buffer = input.buffers[bufferView.buffer]; - //data pointer - const void* dataptr = &buffer.data[accessor.byteOffset + bufferView.byteOffset]; - + const void* dataPtr = &buffer.data[accessor.byteOffset + bufferView.byteOffset]; switch (accessor.type) { - case TINYGLTF_TYPE_VEC3: - { - const glm::vec3* buf = static_cast (dataptr); + case TINYGLTF_TYPE_VEC3: { + const glm::vec3* buf = static_cast(dataPtr); for (size_t index = 0; index < accessor.count; index++) { dstSampler.outputsVec4.push_back(glm::vec4(buf[index], 0.0f)); - } break; } - case TINYGLTF_TYPE_VEC4: - { - const glm::vec4* buf = static_cast(dataptr); + case TINYGLTF_TYPE_VEC4: { + const glm::vec4* buf = static_cast(dataPtr); for (size_t index = 0; index < accessor.count; index++) { dstSampler.outputsVec4.push_back(buf[index]); } break; } - default: - { - std::cout << "unknown type in accessor" << std::endl; + default: { + std::cout << "unknown type" << std::endl; + break; } - break; } } } + + // Channels animations[i].channels.resize(glTFAnimation.channels.size()); for (size_t j = 0; j < glTFAnimation.channels.size(); j++) { @@ -235,7 +232,6 @@ VulkanglTFModel::~VulkanglTFModel() dstChannel.samplerIndex = glTFChannel.sampler; dstChannel.node = nodeFromIndex(glTFChannel.target_node); } - } @@ -273,7 +269,7 @@ VulkanglTFModel::~VulkanglTFModel() { for (size_t i = 0; i < inputNode.children.size(); i++) { - VulkanglTFModel::loadNode(input.nodes[inputNode.children[i]], input, node, inputNode.children[i], indexBuffer, vertexBuffer); + loadNode(input.nodes[inputNode.children[i]], input, node, inputNode.children[i], indexBuffer, vertexBuffer); } } @@ -484,9 +480,9 @@ VulkanglTFModel::~VulkanglTFModel() void VulkanglTFModel::updateAnimation(float deltaTime) { - if (activeAnimation > static_cast(animations.size())-1) + if (activeAnimation > static_cast(animations.size()) - 1) { - std::cout << "no animation with index" << activeAnimation << std::endl; + std::cout << "No animation with index " << activeAnimation << std::endl; return; } Animation& animation = animations[activeAnimation]; @@ -495,17 +491,19 @@ VulkanglTFModel::~VulkanglTFModel() { animation.currentTime -= animation.end; } + for (auto& channel : animation.channels) { - AnimationSampler& sampler = animation.samplers[channel.samplerIndex]; for (size_t i = 0; i < sampler.inputs.size() - 1; i++) { if (sampler.interpolation != "LINEAR") { - std::cout << "sample only supports linear interpolaton" << std::endl; + std::cout << "This sample only supports linear interpolations\n"; continue; } + + // Get the input keyframe values for the current time stamp if ((animation.currentTime >= sampler.inputs[i]) && (animation.currentTime <= sampler.inputs[i + 1])) { float a = (animation.currentTime - sampler.inputs[i]) / (sampler.inputs[i + 1] - sampler.inputs[i]); @@ -515,7 +513,6 @@ VulkanglTFModel::~VulkanglTFModel() } if (channel.path == "rotation") { - //quaternion glm::quat q1; q1.x = sampler.outputsVec4[i].x; q1.y = sampler.outputsVec4[i].y; @@ -523,13 +520,12 @@ VulkanglTFModel::~VulkanglTFModel() q1.w = sampler.outputsVec4[i].w; glm::quat q2; - q2.x = sampler.outputsVec4[i].x; - q2.y = sampler.outputsVec4[i].y; - q2.z = sampler.outputsVec4[i].z; - q2.w = sampler.outputsVec4[i].w; + q2.x = sampler.outputsVec4[i + 1].x; + q2.y = sampler.outputsVec4[i + 1].y; + q2.z = sampler.outputsVec4[i + 1].z; + q2.w = sampler.outputsVec4[i + 1].w; channel.node->rotation = glm::normalize(glm::slerp(q1, q2, a)); - } if (channel.path == "scale") { @@ -563,8 +559,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); - //vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 1, 1, &skins[node.skin].descriptorSet, 0, nullptr); - + vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 1, 1, &skins[node.skin].descriptorSet, 0, nullptr); for (VulkanglTFModel::Primitive& primitive : node.mesh.primitives) { @@ -806,15 +801,14 @@ void VulkanExample::getEnabledFeatures() */ std::vector poolSizes = { - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1), - // One combined image sampler per model image/texture - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, static_cast(glTFModel.images.size())), - //initialize descriptor pool size for skin - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,static_cast(glTFModel.skins.size())), + vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1), + // One combined image sampler per material image/texture + vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, static_cast(glTFModel.images.size())), + // One ssbo per skin + vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, static_cast(glTFModel.skins.size())), }; - - // One set for matrices and one per model image/texture - const uint32_t maxSetCount = static_cast(glTFModel.images.size()) + static_cast(glTFModel.skins.size())+1; + // Number of descriptor sets = One for the scene ubo + one per image + one per skin + const uint32_t maxSetCount = static_cast(glTFModel.images.size()) + static_cast(glTFModel.skins.size()) + 1; VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, maxSetCount); VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); @@ -830,22 +824,22 @@ void VulkanExample::getEnabledFeatures() setLayoutBinding = vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 0); VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorSetLayoutCI, nullptr, &descriptorSetLayouts.textures)); - //Descriptor set layout for passing skin joint matrices + // Descriptor set layout for passing skin joint matrices setLayoutBinding = vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0); VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorSetLayoutCI, nullptr, &descriptorSetLayouts.jointMatrices)); - // Pipeline layout using three descriptor sets (set 0 = matrices, set 1 = joint matrices, set 3 = material) - std::array setLayouts = - { + // The pipeline layout uses three sets: + // Set 0 = Scene matrices (VS) + // Set 1 = Joint matrices (VS) + // Set 2 = Material texture (FS) + std::array setLayouts = { descriptorSetLayouts.matrices, descriptorSetLayouts.jointMatrices, - descriptorSetLayouts.textures - }; - VkPipelineLayoutCreateInfo pipelineLayoutCI= vks::initializers::pipelineLayoutCreateInfo(setLayouts.data(), static_cast(setLayouts.size())); + descriptorSetLayouts.textures }; + VkPipelineLayoutCreateInfo pipelineLayoutCI = vks::initializers::pipelineLayoutCreateInfo(setLayouts.data(), static_cast(setLayouts.size())); // We will use push constants to push the local matrices of a primitive to the vertex shader VkPushConstantRange pushConstantRange = vks::initializers::pushConstantRange(VK_SHADER_STAGE_VERTEX_BIT, sizeof(glm::mat4), 0); - // Push constant ranges are part of the pipeline layout pipelineLayoutCI.pushConstantRangeCount = 1; pipelineLayoutCI.pPushConstantRanges = &pushConstantRange; @@ -857,7 +851,7 @@ void VulkanExample::getEnabledFeatures() VkWriteDescriptorSet writeDescriptorSet = vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &shaderData.buffer.descriptor); vkUpdateDescriptorSets(device, 1, &writeDescriptorSet, 0, nullptr); - //Descriptor sets for skin joint matrices + // Descriptor set for glTF model skin joint matrices for (auto& skin : glTFModel.skins) { const VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayouts.jointMatrices, 1); @@ -866,14 +860,14 @@ void VulkanExample::getEnabledFeatures() vkUpdateDescriptorSets(device, 1, &writeDescriptorSet, 0, nullptr); } - // Descriptor sets for materials - for (auto& image : glTFModel.images) { + // Descriptor sets for glTF model materials + for (auto& image : glTFModel.images) + { const VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayouts.textures, 1); VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &image.descriptorSet)); VkWriteDescriptorSet writeDescriptorSet = vks::initializers::writeDescriptorSet(image.descriptorSet, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 0, &image.texture.descriptor); vkUpdateDescriptorSets(device, 1, &writeDescriptorSet, 0, nullptr); } - } @@ -893,13 +887,13 @@ void VulkanExample::getEnabledFeatures() vks::initializers::vertexInputBindingDescription(0, sizeof(VulkanglTFModel::Vertex), VK_VERTEX_INPUT_RATE_VERTEX), }; const std::vector vertexInputAttributes = { - vks::initializers::vertexInputAttributeDescription(0, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(VulkanglTFModel::Vertex, pos)), // Location 0: Position - vks::initializers::vertexInputAttributeDescription(0, 1, VK_FORMAT_R32G32B32_SFLOAT, offsetof(VulkanglTFModel::Vertex, normal)),// Location 1: Normal - vks::initializers::vertexInputAttributeDescription(0, 2, VK_FORMAT_R32G32B32_SFLOAT, offsetof(VulkanglTFModel::Vertex, uv)), // Location 2: Texture coordinates - vks::initializers::vertexInputAttributeDescription(0, 3, VK_FORMAT_R32G32B32_SFLOAT, offsetof(VulkanglTFModel::Vertex, color)), // Location 3: Color - vks::initializers::vertexInputAttributeDescription(0, 4, VK_FORMAT_R32G32B32_SFLOAT, offsetof(VulkanglTFModel::Vertex,jointIndices)), // Location 4 : jointIndices - vks::initializers::vertexInputAttributeDescription(0, 5, VK_FORMAT_R32G32B32_SFLOAT, offsetof(VulkanglTFModel::Vertex,jointWeights)), //Location 5 : jointWeights - + {0, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(VulkanglTFModel::Vertex, pos)}, + {1, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(VulkanglTFModel::Vertex, normal)}, + {2, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(VulkanglTFModel::Vertex, uv)}, + {3, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(VulkanglTFModel::Vertex, color)}, + // POI: Per-Vertex Joint indices and weights are passed to the vertex shader + {4, 0, VK_FORMAT_R32G32B32A32_SFLOAT, offsetof(VulkanglTFModel::Vertex, jointIndices)}, + {5, 0, VK_FORMAT_R32G32B32A32_SFLOAT, offsetof(VulkanglTFModel::Vertex, jointWeights)}, }; VkPipelineVertexInputStateCreateInfo vertexInputStateCI = vks::initializers::pipelineVertexInputStateCreateInfo(); vertexInputStateCI.vertexBindingDescriptionCount = static_cast(vertexInputBindings.size()); From c08f144680204cccca65fc3d96be46206411738b Mon Sep 17 00:00:00 2001 From: ink-soul Date: Thu, 18 May 2023 11:49:09 +0800 Subject: [PATCH 02/22] complete animation --- CMakeLists.txt | 1 + homework/homework1/homework1.cpp | 205 ++++++++++++++++++------------- homework/homework1/homework1.h | 21 +++- 3 files changed, 137 insertions(+), 90 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f78ddd2..751a347 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -149,4 +149,5 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin/") add_subdirectory(base) add_subdirectory(homework) + # add_subdirectory(examples) diff --git a/homework/homework1/homework1.cpp b/homework/homework1/homework1.cpp index cc23f34..498f666 100644 --- a/homework/homework1/homework1.cpp +++ b/homework/homework1/homework1.cpp @@ -20,10 +20,6 @@ #include "homework1.h" -glm::mat4 VulkanglTFModel::Node::getLocalMatrix() -{ - return glm::translate(glm::mat4(1.0f), translation) * glm::mat4(rotation) * glm::scale(glm::mat4(1.0f), scale) * matrix; -} VulkanglTFModel::~VulkanglTFModel() { @@ -113,39 +109,7 @@ VulkanglTFModel::~VulkanglTFModel() } } } - //glTF nodes loading helper function - //rewrite node loader,simplify logic - //Search node from parent to children by index - VulkanglTFModel::Node* VulkanglTFModel::findNode(Node* parent, uint32_t index) - { - Node* nodeFound = nullptr; - if (parent->index == index) - { - return parent; - } - for (auto &child : parent->children) - { - nodeFound = findNode(child, index); - if (nodeFound) - { - break; - } - } - return nodeFound; -} //iterate vector of nodes to check weather nodes exist or not - VulkanglTFModel::Node* VulkanglTFModel::nodeFromIndex(uint32_t index) - { - Node* nodeFound = nullptr; - for (auto& node : nodes) - { - nodeFound = findNode(node, index); - if (nodeFound) - { - break; - } - } - return nodeFound; - } + //animation loader void VulkanglTFModel::loadAnimations(tinygltf::Model& input) @@ -236,6 +200,86 @@ VulkanglTFModel::~VulkanglTFModel() } + + // load skins from glTF model + void VulkanglTFModel::loadSkins(tinygltf::Model& input) + { + + skins.resize(input.skins.size()); + + for (size_t i = 0; i < input.skins.size(); i++) + { + 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()); + } + } + + + } + + //glTF nodes loading helper function + //rewrite node loader,simplify logic + //Search node from parent to children by index + VulkanglTFModel::Node* VulkanglTFModel::findNode(Node* parent, uint32_t index) + { + Node* nodeFound = nullptr; + if (parent->index == index) + { + return parent; + } + for (auto& child : parent->children) + { + nodeFound = findNode(child, index); + if (nodeFound) + { + break; + } + } + return nodeFound; + } //iterate vector of nodes to check weather nodes exist or not + VulkanglTFModel::Node* VulkanglTFModel::nodeFromIndex(uint32_t index) + { + Node* nodeFound = nullptr; + for (auto& node : nodes) + { + nodeFound = findNode(node, index); + if (nodeFound) + { + break; + } + } + return nodeFound; + } + + //node loader void VulkanglTFModel::loadNode(const tinygltf::Node& inputNode, const tinygltf::Model& input, VulkanglTFModel::Node* parent, uint32_t nodeIndex, std::vector& indexBuffer, std::vector& vertexBuffer) { @@ -399,49 +443,7 @@ VulkanglTFModel::~VulkanglTFModel() } } - // load skins from glTF model - void VulkanglTFModel::loadSkins(tinygltf::Model& input) - { - skins.resize(input.skins.size()); - std::cout << input.skins.size() << std::endl; - for (size_t i = 0; i < input.skins.size(); i++) - { - 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()); - } - } - - - } /* vertex skinning functions */ @@ -456,6 +458,19 @@ VulkanglTFModel::~VulkanglTFModel() } return nodeMatrix; } + + void VulkanglTFModel::updateNodeMatrix(Node* node, std::vector& nodeMatrics) + { + if (node->skin <= -1) + { + nodeMatrics[node->index] = getNodeMatrix(node); + for (auto& child : node->children) + { + updateNodeMatrix(child, nodeMatrics); + } + } + + } void VulkanglTFModel::updateJoints(VulkanglTFModel::Node* node) { @@ -478,7 +493,7 @@ VulkanglTFModel::~VulkanglTFModel() } } - void VulkanglTFModel::updateAnimation(float deltaTime) + void VulkanglTFModel::updateAnimation(float deltaTime,vks::Buffer buffer) { if (activeAnimation > static_cast(animations.size()) - 1) { @@ -495,7 +510,7 @@ VulkanglTFModel::~VulkanglTFModel() for (auto& channel : animation.channels) { AnimationSampler& sampler = animation.samplers[channel.samplerIndex]; - for (size_t i = 0; i < sampler.inputs.size() - 1; i++) + for (size_t i = 0; i < sampler.inputs.size() - 1; ++i) { if (sampler.interpolation != "LINEAR") { @@ -506,10 +521,10 @@ VulkanglTFModel::~VulkanglTFModel() // Get the input keyframe values for the current time stamp if ((animation.currentTime >= sampler.inputs[i]) && (animation.currentTime <= sampler.inputs[i + 1])) { - float a = (animation.currentTime - sampler.inputs[i]) / (sampler.inputs[i + 1] - sampler.inputs[i]); + float ratio = (animation.currentTime - sampler.inputs[i]) / (sampler.inputs[i + 1] - sampler.inputs[i]); if (channel.path == "translation") { - channel.node->translation = glm::mix(sampler.outputsVec4[i], sampler.outputsVec4[i + 1], a); + channel.node->translation = glm::mix(sampler.outputsVec4[i], sampler.outputsVec4[i + 1], ratio); } if (channel.path == "rotation") { @@ -525,19 +540,25 @@ VulkanglTFModel::~VulkanglTFModel() q2.z = sampler.outputsVec4[i + 1].z; q2.w = sampler.outputsVec4[i + 1].w; - channel.node->rotation = glm::normalize(glm::slerp(q1, q2, a)); + channel.node->rotation = glm::normalize(glm::slerp(q1, q2, ratio)); + channel.node->bAnimateNode = true; } if (channel.path == "scale") { - channel.node->scale = glm::mix(sampler.outputsVec4[i], sampler.outputsVec4[i + 1], a); + channel.node->scale = glm::mix(sampler.outputsVec4[i], sampler.outputsVec4[i + 1], ratio); + channel.node->bAnimateNode = true; } } } } + //if no skin in model , update node matrix to update animation stage + std::vector nodeMatrics(nodeCount); for (auto& node : nodes) { updateJoints(node); + updateNodeMatrix(node, nodeMatrics); } + buffer.copyTo(nodeMatrics.data(), nodeCount * sizeof(glm::mat4)); } /* @@ -558,8 +579,11 @@ 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) + { + vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 1, 1, &skins[node.skin].descriptorSet, 0, nullptr); + } - vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 1, 1, &skins[node.skin].descriptorSet, 0, nullptr); for (VulkanglTFModel::Primitive& primitive : node.mesh.primitives) { @@ -693,6 +717,7 @@ void VulkanExample::getEnabledFeatures() if (fileLoaded) { + glTFModel.nodeCount = static_cast(glTFInput.nodes.size()); glTFModel.loadImages(glTFInput); glTFModel.loadMaterials(glTFInput); glTFModel.loadTextures(glTFInput); @@ -791,7 +816,7 @@ void VulkanExample::getEnabledFeatures() void VulkanExample::loadAssets() { - loadglTFFile(getAssetPath() + "models/CesiumMan/glTF/CesiumMan.gltf"); + loadglTFFile(getAssetPath() + "buster_drone/busterDrone.gltf"); } void VulkanExample::setupDescriptors() @@ -972,7 +997,7 @@ void VulkanExample::getEnabledFeatures() } if (!paused) { - glTFModel.updateAnimation(frameTimer); + glTFModel.updateAnimation(frameTimer,shaderData.buffer); } } @@ -988,6 +1013,10 @@ void VulkanExample::getEnabledFeatures() buildCommandBuffers(); } } + if (overlay->header("Animation")) + { + overlay->checkBox("pause", &paused); + } } diff --git a/homework/homework1/homework1.h b/homework/homework1/homework1.h index ff53750..a4b30be 100644 --- a/homework/homework1/homework1.h +++ b/homework/homework1/homework1.h @@ -33,6 +33,7 @@ public: // The class requires some Vulkan objects so it can create it's own resources vks::VulkanDevice* vulkanDevice; VkQueue copyQueue; + uint32_t nodeCount; // The vertex layout for the samples' model struct Vertex { @@ -83,8 +84,22 @@ public: glm::vec3 scale{ 1.0f }; glm::quat rotation{}; int32_t skin = -1; - glm::mat4 getLocalMatrix(); + glm::mat4 getLocalMatrix() + { + return bAnimateNode ? glm::translate(glm::mat4(1.0f), translation) * glm::mat4(rotation) * glm::scale(glm::mat4(1.0f), scale) : matrix; + } glm::mat4 matrix; + bool bAnimateNode = false; + /* + ~Node() { + for (auto& child : children) { + delete child; + }; + } + + + */ + }; @@ -116,6 +131,7 @@ public: std::vector joints; vks::Buffer ssbo; VkDescriptorSet descriptorSet; + }; struct AnimationSampler @@ -170,8 +186,9 @@ public: void loadAnimations(tinygltf::Model& input); void loadNode(const tinygltf::Node& inputNode, const tinygltf::Model& input, VulkanglTFModel::Node* parent, uint32_t nodeIndex, std::vector& indexBuffer, std::vector& vertexBuffer); glm::mat4 getNodeMatrix(VulkanglTFModel::Node* node); + void updateNodeMatrix(Node* node, std::vector& nodeMatrics); void updateJoints(VulkanglTFModel::Node* node); - void updateAnimation(float deltaTime); + void updateAnimation(float deltaTime,vks::Buffer buffer); void drawNode(VkCommandBuffer commandBuffer, VkPipelineLayout pipelineLayout, VulkanglTFModel::Node node); void draw(VkCommandBuffer commandBuffer, VkPipelineLayout pipelineLayout); }; From bdd9405f88b812045bdb18a9ee17cf23ef9c5e46 Mon Sep 17 00:00:00 2001 From: ink-soul Date: Thu, 18 May 2023 15:42:04 +0800 Subject: [PATCH 03/22] fix shading error (no complete yet) --- homework/homework1/homework1.cpp | 13 ++++++++----- homework/homework1/homework1.h | 1 + 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/homework/homework1/homework1.cpp b/homework/homework1/homework1.cpp index 498f666..30d11d1 100644 --- a/homework/homework1/homework1.cpp +++ b/homework/homework1/homework1.cpp @@ -838,17 +838,20 @@ void VulkanExample::getEnabledFeatures() VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); // Descriptor set layouts - VkDescriptorSetLayoutBinding setLayoutBinding{}; - VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCI = vks::initializers::descriptorSetLayoutCreateInfo(&setLayoutBinding, 1); + + VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCI = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBinding); // Descriptor set layout for passing matrices + setLayoutBinding = vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0); VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorSetLayoutCI, nullptr, &descriptorSetLayouts.matrices)); // Descriptor set layout for passing material textures - setLayoutBinding = vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 0); + VkDescriptorSetLayoutBinding setLayoutBinding = vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 0); + descriptorSetLayoutCI = vks::initializers::descriptorSetLayoutCreateInfo(&setLayoutBinding, 1); VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorSetLayoutCI, nullptr, &descriptorSetLayouts.textures)); + // Descriptor set layout for passing skin joint matrices setLayoutBinding = vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0); VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorSetLayoutCI, nullptr, &descriptorSetLayouts.jointMatrices)); @@ -974,7 +977,7 @@ void VulkanExample::getEnabledFeatures() { shaderData.values.projection = camera.matrices.perspective; shaderData.values.model = camera.matrices.view; - + shaderData.values.viewPos = camera.viewPos; memcpy(shaderData.buffer.mapped, &shaderData.values, sizeof(shaderData.values)); } @@ -997,7 +1000,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 a4b30be..2a97b4d 100644 --- a/homework/homework1/homework1.h +++ b/homework/homework1/homework1.h @@ -208,6 +208,7 @@ public: glm::vec4 lightPos = glm::vec4(5.0f, 5.0f, 5.0f, 1.0f); glm::vec4 viewPos; } values; + vks::Buffer skinSSBO; } shaderData; struct Pipelines { From d589afb3bb2762cb18ad10a41769fb2cbab05ec1 Mon Sep 17 00:00:00 2001 From: InkSoul Date: Thu, 18 May 2023 17:17:52 +0800 Subject: [PATCH 04/22] commit for revert --- homework/homework1/homework1.cpp | 21 ++++++++++++--------- homework/homework1/homework1.h | 2 ++ 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/homework/homework1/homework1.cpp b/homework/homework1/homework1.cpp index 30d11d1..2b18aa4 100644 --- a/homework/homework1/homework1.cpp +++ b/homework/homework1/homework1.cpp @@ -660,7 +660,7 @@ void VulkanExample::getEnabledFeatures() VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); VkClearValue clearValues[2]; - + clearValues[0].color = defaultClearColor; clearValues[0].color = { { 0.25f, 0.25f, 0.25f, 1.0f } };; clearValues[1].depthStencil = { 1.0f, 0 }; @@ -837,13 +837,16 @@ void VulkanExample::getEnabledFeatures() VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, maxSetCount); VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); - // Descriptor set layouts - - VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCI = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBinding); + std::vector setLayoutBindings = + { + vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0), + vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 0), + vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0), + }; + // Descriptor set layout for passing matrices - - setLayoutBinding = vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0); + VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCI = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorSetLayoutCI, nullptr, &descriptorSetLayouts.matrices)); // Descriptor set layout for passing material textures @@ -853,7 +856,7 @@ void VulkanExample::getEnabledFeatures() // Descriptor set layout for passing skin joint matrices - setLayoutBinding = vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0); + VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorSetLayoutCI, nullptr, &descriptorSetLayouts.jointMatrices)); // The pipeline layout uses three sets: @@ -969,7 +972,7 @@ void VulkanExample::getEnabledFeatures() // Map persistent VK_CHECK_RESULT(shaderData.buffer.map()); - + updateUniformBuffers(); } @@ -1000,7 +1003,7 @@ void VulkanExample::getEnabledFeatures() } if (!paused) { - glTFModel.updateAnimation(frameTimer,shaderData.skinSSBO); + glTFModel.updateAnimation(frameTimer,shaderData.buffer); } } diff --git a/homework/homework1/homework1.h b/homework/homework1/homework1.h index 2a97b4d..8404967 100644 --- a/homework/homework1/homework1.h +++ b/homework/homework1/homework1.h @@ -223,12 +223,14 @@ public: VkDescriptorSetLayout matrices; VkDescriptorSetLayout textures; VkDescriptorSetLayout jointMatrices; + VkDescriptorSetLayout ssbo; } descriptorSetLayouts; VkDescriptorSet descriptorSet; VulkanExample(); ~VulkanExample(); + void loadglTFFile(std::string filename); virtual void getEnabledFeatures(); void buildCommandBuffers(); From 1a69774a711624cdd4d51a7c55847bad920a2801 Mon Sep 17 00:00:00 2001 From: InkSoul Date: Thu, 18 May 2023 17:17:57 +0800 Subject: [PATCH 05/22] Revert "commit for revert" This reverts commit d589afb3bb2762cb18ad10a41769fb2cbab05ec1. --- homework/homework1/homework1.cpp | 21 +++++++++------------ homework/homework1/homework1.h | 2 -- 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/homework/homework1/homework1.cpp b/homework/homework1/homework1.cpp index 2b18aa4..30d11d1 100644 --- a/homework/homework1/homework1.cpp +++ b/homework/homework1/homework1.cpp @@ -660,7 +660,7 @@ void VulkanExample::getEnabledFeatures() VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); VkClearValue clearValues[2]; - clearValues[0].color = defaultClearColor; + clearValues[0].color = { { 0.25f, 0.25f, 0.25f, 1.0f } };; clearValues[1].depthStencil = { 1.0f, 0 }; @@ -837,16 +837,13 @@ void VulkanExample::getEnabledFeatures() VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, maxSetCount); VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); - std::vector setLayoutBindings = - { - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0), - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 0), - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0), - }; - + // Descriptor set layouts + + VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCI = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBinding); // Descriptor set layout for passing matrices - VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCI = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); + + setLayoutBinding = vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0); VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorSetLayoutCI, nullptr, &descriptorSetLayouts.matrices)); // Descriptor set layout for passing material textures @@ -856,7 +853,7 @@ void VulkanExample::getEnabledFeatures() // Descriptor set layout for passing skin joint matrices - + setLayoutBinding = vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0); VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorSetLayoutCI, nullptr, &descriptorSetLayouts.jointMatrices)); // The pipeline layout uses three sets: @@ -972,7 +969,7 @@ void VulkanExample::getEnabledFeatures() // Map persistent VK_CHECK_RESULT(shaderData.buffer.map()); - + updateUniformBuffers(); } @@ -1003,7 +1000,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 8404967..2a97b4d 100644 --- a/homework/homework1/homework1.h +++ b/homework/homework1/homework1.h @@ -223,14 +223,12 @@ public: VkDescriptorSetLayout matrices; VkDescriptorSetLayout textures; VkDescriptorSetLayout jointMatrices; - VkDescriptorSetLayout ssbo; } descriptorSetLayouts; VkDescriptorSet descriptorSet; VulkanExample(); ~VulkanExample(); - void loadglTFFile(std::string filename); virtual void getEnabledFeatures(); void buildCommandBuffers(); From 2eda8f24935b7ac17c4eb4bf10fe7670430adf0e Mon Sep 17 00:00:00 2001 From: InkSoul Date: Thu, 18 May 2023 17:19:54 +0800 Subject: [PATCH 06/22] Revert "fix shading error (no complete yet)" This reverts commit bdd9405f88b812045bdb18a9ee17cf23ef9c5e46. --- homework/homework1/homework1.cpp | 13 +++++-------- homework/homework1/homework1.h | 1 - 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/homework/homework1/homework1.cpp b/homework/homework1/homework1.cpp index 30d11d1..498f666 100644 --- a/homework/homework1/homework1.cpp +++ b/homework/homework1/homework1.cpp @@ -838,20 +838,17 @@ void VulkanExample::getEnabledFeatures() VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); // Descriptor set layouts - - VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCI = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBinding); + VkDescriptorSetLayoutBinding setLayoutBinding{}; + VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCI = vks::initializers::descriptorSetLayoutCreateInfo(&setLayoutBinding, 1); // Descriptor set layout for passing matrices - setLayoutBinding = vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0); VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorSetLayoutCI, nullptr, &descriptorSetLayouts.matrices)); // Descriptor set layout for passing material textures - VkDescriptorSetLayoutBinding setLayoutBinding = vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 0); - descriptorSetLayoutCI = vks::initializers::descriptorSetLayoutCreateInfo(&setLayoutBinding, 1); + setLayoutBinding = vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 0); VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorSetLayoutCI, nullptr, &descriptorSetLayouts.textures)); - // Descriptor set layout for passing skin joint matrices setLayoutBinding = vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0); VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorSetLayoutCI, nullptr, &descriptorSetLayouts.jointMatrices)); @@ -977,7 +974,7 @@ void VulkanExample::getEnabledFeatures() { shaderData.values.projection = camera.matrices.perspective; shaderData.values.model = camera.matrices.view; - shaderData.values.viewPos = camera.viewPos; + memcpy(shaderData.buffer.mapped, &shaderData.values, sizeof(shaderData.values)); } @@ -1000,7 +997,7 @@ void VulkanExample::getEnabledFeatures() } if (!paused) { - glTFModel.updateAnimation(frameTimer,shaderData.skinSSBO); + glTFModel.updateAnimation(frameTimer,shaderData.buffer); } } diff --git a/homework/homework1/homework1.h b/homework/homework1/homework1.h index 2a97b4d..a4b30be 100644 --- a/homework/homework1/homework1.h +++ b/homework/homework1/homework1.h @@ -208,7 +208,6 @@ public: glm::vec4 lightPos = glm::vec4(5.0f, 5.0f, 5.0f, 1.0f); glm::vec4 viewPos; } values; - vks::Buffer skinSSBO; } shaderData; struct Pipelines { From 104ebaa0a75ed59da6474e16e85c6b5a92344f11 Mon Sep 17 00:00:00 2001 From: InkSoul Date: Fri, 19 May 2023 00:08:15 +0800 Subject: [PATCH 07/22] update --- .gitignore | 1 + homework/homework1/homework1.cpp | 17 ++++++++++++----- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index 44fb2b6..78bbeaf 100644 --- a/.gitignore +++ b/.gitignore @@ -37,3 +37,4 @@ data/ # vs compile file out/ .vs/ +*.zip diff --git a/homework/homework1/homework1.cpp b/homework/homework1/homework1.cpp index 498f666..4705722 100644 --- a/homework/homework1/homework1.cpp +++ b/homework/homework1/homework1.cpp @@ -234,7 +234,10 @@ VulkanglTFModel::~VulkanglTFModel() 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, + 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())); @@ -327,9 +330,12 @@ VulkanglTFModel::~VulkanglTFModel() uint32_t firstIndex = static_cast(indexBuffer.size()); uint32_t vertexStart = static_cast(vertexBuffer.size()); uint32_t indexCount = 0; + //vertices const float* positionBuffer = nullptr; const float* normalsBuffer = nullptr; const float* texcoordsBuffer = nullptr; + const float* tangentsBuffer = nullptr; + //skin joints const float* jointWeightsBuffer = nullptr; const uint16_t * jointIndicesBuffer = nullptr; size_t vertexCount = 0; @@ -377,9 +383,9 @@ VulkanglTFModel::~VulkanglTFModel() { Vertex vert{}; vert.pos = glm::vec4(glm::make_vec3(&positionBuffer[v * 3]), 1.0f); - vert.uv = texcoordsBuffer ? glm::make_vec2(&texcoordsBuffer[v*2]):glm::vec4(0.0f); + vert.uv = texcoordsBuffer ? glm::make_vec2(&texcoordsBuffer[v*2]) : glm::vec3(0.0f); vert.normal = glm::normalize(glm::vec3(normalsBuffer ? glm::make_vec3(&normalsBuffer[v * 3]) : glm::vec3(0.0f))); - vert.color = glm::vec3(1.0f); + vert.color = glm::vec3(1.0f,1.0f,nodeIndex); vert.jointIndices = hasSkin ? glm::vec4(glm::make_vec4(&jointIndicesBuffer[v * 4])) : glm::vec4(0.0f); vert.jointWeights = hasSkin ? glm::make_vec4(&jointWeightsBuffer[v * 4]) : glm::vec4(0.0f); vertexBuffer.push_back(vert); @@ -597,7 +603,7 @@ VulkanglTFModel::~VulkanglTFModel() } } } - for (auto& child : node.children) { + for (auto &child : node.children) { drawNode(commandBuffer, pipelineLayout, *child); } } @@ -645,6 +651,7 @@ VulkanExample::~VulkanExample() shaderData.buffer.destroy(); + } void VulkanExample::getEnabledFeatures() @@ -660,7 +667,7 @@ void VulkanExample::getEnabledFeatures() VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); VkClearValue clearValues[2]; - + clearValues[0].color = defaultClearColor; clearValues[0].color = { { 0.25f, 0.25f, 0.25f, 1.0f } };; clearValues[1].depthStencil = { 1.0f, 0 }; From 39ba805802fd8b8404e2fa104b27e1cb71f41f80 Mon Sep 17 00:00:00 2001 From: ink-soul Date: Sat, 20 May 2023 15:09:51 +0800 Subject: [PATCH 08/22] bug fix --- homework/homework1/homework1.cpp | 24 +++++++++++++++++------- homework/homework1/homework1.h | 2 ++ 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/homework/homework1/homework1.cpp b/homework/homework1/homework1.cpp index 4705722..4012170 100644 --- a/homework/homework1/homework1.cpp +++ b/homework/homework1/homework1.cpp @@ -295,16 +295,16 @@ VulkanglTFModel::~VulkanglTFModel() //get distributions of node if (inputNode.translation.size() == 3) { - node->translation = glm::make_vec3(inputNode.translation.data()); + node->matrix =glm::translate(node->matrix,glm::vec3(glm::make_vec3(inputNode.translation.data()))); } if (inputNode.scale.size() == 3) { - node->scale = glm::make_vec3(inputNode.scale.data()); + node->matrix =glm::scale(node->matrix,glm::vec3(glm::make_vec3(inputNode.scale.data()))); } if (inputNode.rotation.size() == 4) { //rotation is given by quaternion glm::quat q = glm::make_quat(inputNode.rotation.data()); - node->rotation = glm::mat4(q); + node->matrix = glm::mat4(q); } if (inputNode.matrix.size() == 16) { @@ -345,7 +345,7 @@ VulkanglTFModel::~VulkanglTFModel() if (glTFPrimmitive.attributes.find("POSITION") != glTFPrimmitive.attributes.end()) { const tinygltf::Accessor& accessor = input.accessors[glTFPrimmitive.attributes.find("POSITION")->second]; - const tinygltf::BufferView view = input.bufferViews[accessor.bufferView]; + const tinygltf::BufferView &view = input.bufferViews[accessor.bufferView]; positionBuffer = reinterpret_cast (&(input.buffers[view.buffer].data[accessor.byteOffset + view.byteOffset])); vertexCount = accessor.count; } @@ -356,6 +356,7 @@ VulkanglTFModel::~VulkanglTFModel() normalsBuffer = reinterpret_cast (&(input.buffers[view.buffer].data[accessor.byteOffset + view.byteOffset])); } + //texture and tangent data if (glTFPrimmitive.attributes.find("TEXCOORD_0") != glTFPrimmitive.attributes.end()) { const tinygltf::Accessor& accessor = input.accessors[glTFPrimmitive.attributes.find("TEXCOORD_0")->second]; @@ -363,6 +364,14 @@ VulkanglTFModel::~VulkanglTFModel() texcoordsBuffer = reinterpret_cast (&(input.buffers[view.buffer].data[accessor.byteOffset + view.byteOffset])); } + if (glTFPrimmitive.attributes.find("TANGENT") != glTFPrimmitive.attributes.end()) + { + const tinygltf::Accessor& accessor = input.accessors[glTFPrimmitive.attributes.find("TANGENT")->second]; + const tinygltf::BufferView& view = input.bufferViews[accessor.bufferView]; + tangentsBuffer = reinterpret_cast (&(input.buffers[view.buffer].data[accessor.byteOffset + view.byteOffset])); + + } + //skin joints and weights data if (glTFPrimmitive.attributes.find("JOINTS_0") != glTFPrimmitive.attributes.end()) { const tinygltf::Accessor& accessor = input.accessors[glTFPrimmitive.attributes.find("JOINTS_0")->second]; @@ -377,6 +386,7 @@ VulkanglTFModel::~VulkanglTFModel() jointWeightsBuffer = reinterpret_cast (&(input.buffers[view.buffer].data[accessor.byteOffset + view.byteOffset])); } + hasSkin = (jointIndicesBuffer && jointWeightsBuffer); for (size_t v = 0; v < vertexCount; v++) @@ -386,6 +396,7 @@ VulkanglTFModel::~VulkanglTFModel() vert.uv = texcoordsBuffer ? glm::make_vec2(&texcoordsBuffer[v*2]) : glm::vec3(0.0f); vert.normal = glm::normalize(glm::vec3(normalsBuffer ? glm::make_vec3(&normalsBuffer[v * 3]) : glm::vec3(0.0f))); vert.color = glm::vec3(1.0f,1.0f,nodeIndex); + vert.tangent = tangentsBuffer ? glm::normalize(glm::make_vec3(&tangentsBuffer[v * 4])) : glm::vec3(0.0f); vert.jointIndices = hasSkin ? glm::vec4(glm::make_vec4(&jointIndicesBuffer[v * 4])) : glm::vec4(0.0f); vert.jointWeights = hasSkin ? glm::make_vec4(&jointWeightsBuffer[v * 4]) : glm::vec4(0.0f); vertexBuffer.push_back(vert); @@ -472,7 +483,7 @@ VulkanglTFModel::~VulkanglTFModel() nodeMatrics[node->index] = getNodeMatrix(node); for (auto& child : node->children) { - updateNodeMatrix(child, nodeMatrics); + updateNodeMatrix(child, nodeMatrics); } } @@ -590,11 +601,10 @@ VulkanglTFModel::~VulkanglTFModel() vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 1, 1, &skins[node.skin].descriptorSet, 0, nullptr); } - - for (VulkanglTFModel::Primitive& primitive : node.mesh.primitives) { if (primitive.indexCount > 0) { + // Get the texture index for this primitive VulkanglTFModel::Texture texture = textures[materials[primitive.materialIndex].baseColorTextureIndex]; // Bind the descriptor for the current primitive's texture diff --git a/homework/homework1/homework1.h b/homework/homework1/homework1.h index a4b30be..5198a25 100644 --- a/homework/homework1/homework1.h +++ b/homework/homework1/homework1.h @@ -41,6 +41,7 @@ public: glm::vec3 normal; glm::vec2 uv; glm::vec3 color; + glm::vec3 tangent; glm::vec3 jointIndices; glm::vec3 jointWeights; }; @@ -208,6 +209,7 @@ public: glm::vec4 lightPos = glm::vec4(5.0f, 5.0f, 5.0f, 1.0f); glm::vec4 viewPos; } values; + vks::Buffer animationBuffer; } shaderData; struct Pipelines { From 077d91916f6e9b57ea38665f368302eec9591ff0 Mon Sep 17 00:00:00 2001 From: InkSoul Date: Mon, 22 May 2023 11:21:13 +0800 Subject: [PATCH 09/22] ready for pbr and tonemapping --- homework/homework1/homework1.cpp | 116 +++++++++---------------- homework/homework1/homework1.h | 141 +++++++++++++++++++++++++++++-- 2 files changed, 175 insertions(+), 82 deletions(-) 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(); From 7733ba49ee745ced4877d74b76bcd59564f61115 Mon Sep 17 00:00:00 2001 From: InkSoul Date: Mon, 22 May 2023 22:52:27 +0800 Subject: [PATCH 10/22] update materials loader --- homework/homework1/homework1.cpp | 67 +++++++++++++++++++++++--------- 1 file changed, 49 insertions(+), 18 deletions(-) diff --git a/homework/homework1/homework1.cpp b/homework/homework1/homework1.cpp index f3c7d3b..95b6bd4 100644 --- a/homework/homework1/homework1.cpp +++ b/homework/homework1/homework1.cpp @@ -86,6 +86,26 @@ if (glTFMaterial.values.find("baseColorTexture") != glTFMaterial.values.end()) { materials[i].baseColorTextureIndex = glTFMaterial.values["baseColorTexture"].TextureIndex(); } + if (glTFMaterial.values.find("metallicRoughnessTexture") != glTFMaterial.values.end()) { + materials[i].matalicRoughTextureIndex = glTFMaterial.values["metallicRoughnessTexture"].TextureIndex(); + } + if (glTFMaterial.additionalValues.find("normalTexture") != glTFMaterial.additionalValues.end()) + { + materials[i].normalMapTextureIndex = glTFMaterial.additionalValues["normalTexture"].TextureIndex(); + } + if (glTFMaterial.emissiveTexture.index != -1) + { + materials[i].emissiveTextureIndex = glTFMaterial.emissiveTexture.index; + } + if (glTFMaterial.emissiveFactor.size() == 3) + { + materials[i].materialData.values.emissiveFactor = glm::make_vec3(glTFMaterial.emissiveFactor.data()); + } + + if (glTFMaterial.values.find("baseColorFactor") != glTFMaterial.values.end()) + { + materials[i].materialData.values.baseColorFactor = glm::make_vec4(glTFMaterial.values["baseColorFactor"].ColorFactor().data()); + } } } @@ -280,15 +300,18 @@ { node->matrix =glm::translate(node->matrix,glm::vec3(glm::make_vec3(inputNode.translation.data()))); } - if (inputNode.scale.size() == 3) - { - node->matrix =glm::scale(node->matrix,glm::vec3(glm::make_vec3(inputNode.scale.data()))); - } + if (inputNode.rotation.size() == 4) { //rotation is given by quaternion glm::quat q = glm::make_quat(inputNode.rotation.data()); node->matrix = glm::mat4(q); } + + if (inputNode.scale.size() == 3) + { + node->matrix =glm::scale(node->matrix,glm::vec3(glm::make_vec3(inputNode.scale.data()))); + } + if (inputNode.matrix.size() == 16) { node->matrix = glm::make_mat4x4(inputNode.matrix.data()); @@ -318,10 +341,11 @@ const float* normalsBuffer = nullptr; const float* texcoordsBuffer = nullptr; const float* tangentsBuffer = nullptr; + size_t vertexCount = 0; //skin joints const float* jointWeightsBuffer = nullptr; const uint16_t * jointIndicesBuffer = nullptr; - size_t vertexCount = 0; + bool hasSkin = false; //get buffer by index in primmitive.attributes { @@ -556,7 +580,7 @@ std::vector nodeMatrics(nodeCount); for (auto& node : nodes) { - updateJoints(node); + //updateJoints(node); updateNodeMatrix(node, nodeMatrics); } buffer.copyTo(nodeMatrics.data(), nodeCount * sizeof(glm::mat4)); @@ -578,21 +602,28 @@ nodeMatrix = currentParent->matrix * nodeMatrix; currentParent = currentParent->parent; } - // 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) - { - vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 1, 1, &skins[node.skin].descriptorSet, 0, nullptr); - } for (VulkanglTFModel::Primitive& primitive : node.mesh.primitives) { - if (primitive.indexCount > 0) - { - + if (primitive.indexCount > 0) { // Get the texture index for this primitive - VulkanglTFModel::Texture texture = textures[materials[primitive.materialIndex].baseColorTextureIndex]; - // Bind the descriptor for the current primitive's texture - vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 2, 1, &images[texture.imageIndex].descriptorSet, 0, nullptr); + if (textures.size() > 0) + { + VulkanglTFModel::Texture texture = textures[materials[primitive.materialIndex].baseColorTextureIndex]; + auto normalMap = textures[materials[primitive.materialIndex].normalMapTextureIndex]; + auto roughMetalMap = textures[materials[primitive.materialIndex].matalicRoughTextureIndex]; + + if (materials[primitive.materialIndex].emissiveTextureIndex >= 0) + { + auto emissiveMap = textures[materials[primitive.materialIndex].emissiveTextureIndex]; + vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 4, 1, &images[emissiveMap.imageIndex].descriptorSet, 0, nullptr); + } + + // Bind the descriptor for the current primitive's texture + vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 1, 1, &images[texture.imageIndex].descriptorSet, 0, nullptr); + vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 2, 1, &images[normalMap.imageIndex].descriptorSet, 0, nullptr); + vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 3, 1, &images[roughMetalMap.imageIndex].descriptorSet, 0, nullptr); + vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 5, 1, &materials[primitive.materialIndex].materialData.descriptorSet, 0, nullptr); + } vkCmdDrawIndexed(commandBuffer, primitive.indexCount, 1, primitive.firstIndex, 0, 0); } } From 1629bbdcf53adb67df7ed1d9fb96cd7f73a0db38 Mon Sep 17 00:00:00 2001 From: ink-soul Date: Tue, 23 May 2023 11:30:21 +0800 Subject: [PATCH 11/22] update framebuffer setup --- homework/homework1/homework1.cpp | 82 ++++++++++++++++++++++++++++++++ homework/homework1/homework1.h | 2 + 2 files changed, 84 insertions(+) diff --git a/homework/homework1/homework1.cpp b/homework/homework1/homework1.cpp index 95b6bd4..eb3f27d 100644 --- a/homework/homework1/homework1.cpp +++ b/homework/homework1/homework1.cpp @@ -660,7 +660,23 @@ VulkanExample::VulkanExample(): camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 256.0f); } +void VulkanExample::setupFrameBuffer() +{ + if (pbrFrameBuffer.bCreate && (pbrFrameBuffer.fbo.width != width || pbrFrameBuffer.fbo.height != height)) + { + pbrFrameBuffer.color.destroy(device); + pbrFrameBuffer.depth.destroy(device); + pbrFrameBuffer.fbo.destroy(device); + vkDestroySampler(device, colorSampler, nullptr); + } + pbrFrameBuffer.fbo.setSize(width, height); + VkFormat attachDepthFormat; + VkBool32 validDepthFormat = vks::tools::getSupportedDepthFormat(physicalDevice, &attachDepthFormat); + assert(validDepthFormat); + + +} void VulkanExample::getEnabledFeatures() { @@ -994,6 +1010,72 @@ void VulkanExample::getEnabledFeatures() memcpy(shaderData.buffer.mapped, &shaderData.values, sizeof(shaderData.values)); } + //-------------------------- pbr precompute start ---------------------------------- + +#pragma region pbr render pass setting + + void VulkanExample::createAttachment(VkFormat format, VkImageUsageFlagBits usage, VulkanExample::FrameBufferAttachment* attachment, uint32_t width, uint32_t height) + { + VkImageAspectFlags aspectMask = 0; + VkImageUsageFlags imageUsage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT; + attachment->format = format; + if (usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) + { + aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + imageUsage |= VK_IMAGE_USAGE_SAMPLED_BIT; + } + if (usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) + { + aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; + if (format >= VK_FORMAT_D16_UNORM_S8_UINT) + aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT; + } + + assert(aspectMask > 0); + + VkImageCreateInfo image = vks::initializers::imageCreateInfo(); + image.imageType = VK_IMAGE_TYPE_2D; + image.format = format; + image.extent.width = width; + image.extent.height = height; + image.extent.depth = 1; + image.mipLevels = 1; + image.arrayLayers = 1; + image.samples = VK_SAMPLE_COUNT_1_BIT; + image.tiling = VK_IMAGE_TILING_OPTIMAL; + image.usage = imageUsage | usage; + + VkMemoryAllocateInfo memAlloc = vks::initializers::memoryAllocateInfo(); + VkMemoryRequirements memReqs; + + VK_CHECK_RESULT(vkCreateImage(device, &image, nullptr, &attachment->image)); + vkGetImageMemoryRequirements(device, attachment->image, &memReqs); + memAlloc.allocationSize = memReqs.size; + memAlloc.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &attachment->deviceMemory)); + VK_CHECK_RESULT(vkBindImageMemory(device, attachment->image, attachment->deviceMemory, 0)); + + VkImageViewCreateInfo imageView = vks::initializers::imageViewCreateInfo(); + imageView.viewType = VK_IMAGE_VIEW_TYPE_2D; + imageView.format = format; + imageView.subresourceRange = {}; + imageView.subresourceRange.aspectMask = aspectMask; + imageView.subresourceRange.baseMipLevel = 0; + imageView.subresourceRange.levelCount = 1; + imageView.subresourceRange.baseArrayLayer = 0; + imageView.subresourceRange.layerCount = 1; + imageView.image = attachment->image; + VK_CHECK_RESULT(vkCreateImageView(device, &imageView, nullptr, &attachment->imageView)); + } + + +#pragma endregion + + + + + + // ----------------------- pbr precompute end --------------------------------------- void VulkanExample::prepare() { VulkanExampleBase::prepare(); diff --git a/homework/homework1/homework1.h b/homework/homework1/homework1.h index 9c6c08a..1c7d3f3 100644 --- a/homework/homework1/homework1.h +++ b/homework/homework1/homework1.h @@ -357,6 +357,8 @@ public: } void loadglTFFile(std::string filename); virtual void getEnabledFeatures(); + void createAttachment(VkFormat format, VkImageUsageFlagBits usage, FrameBufferAttachment* attachment, uint32_t width, uint32_t height); + virtual void setupFrameBuffer(); void buildCommandBuffers(); void loadAssets(); void setupDescriptors(); From 4e175e863b53dfbeb9e95ae97fc4724f9624df96 Mon Sep 17 00:00:00 2001 From: ink-soul Date: Tue, 23 May 2023 15:52:04 +0800 Subject: [PATCH 12/22] update framebuffer setter --- homework/homework1/homework1.cpp | 76 ++++++++++++++++++++++++++++++-- homework/homework1/homework1.h | 1 + 2 files changed, 74 insertions(+), 3 deletions(-) diff --git a/homework/homework1/homework1.cpp b/homework/homework1/homework1.cpp index eb3f27d..e4c7d34 100644 --- a/homework/homework1/homework1.cpp +++ b/homework/homework1/homework1.cpp @@ -609,12 +609,12 @@ if (textures.size() > 0) { VulkanglTFModel::Texture texture = textures[materials[primitive.materialIndex].baseColorTextureIndex]; - auto normalMap = textures[materials[primitive.materialIndex].normalMapTextureIndex]; - auto roughMetalMap = textures[materials[primitive.materialIndex].matalicRoughTextureIndex]; + VulkanglTFModel::Texture normalMap = textures[materials[primitive.materialIndex].normalMapTextureIndex]; + VulkanglTFModel::Texture roughMetalMap = textures[materials[primitive.materialIndex].matalicRoughTextureIndex]; if (materials[primitive.materialIndex].emissiveTextureIndex >= 0) { - auto emissiveMap = textures[materials[primitive.materialIndex].emissiveTextureIndex]; + VulkanglTFModel::Texture emissiveMap = textures[materials[primitive.materialIndex].emissiveTextureIndex]; vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 4, 1, &images[emissiveMap.imageIndex].descriptorSet, 0, nullptr); } @@ -674,8 +674,78 @@ void VulkanExample::setupFrameBuffer() VkFormat attachDepthFormat; VkBool32 validDepthFormat = vks::tools::getSupportedDepthFormat(physicalDevice, &attachDepthFormat); assert(validDepthFormat); + VulkanExample::createAttachment(VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, &pbrFrameBuffer.color, width, height); + VulkanExample::createAttachment(attachDepthFormat, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, &pbrFrameBuffer.depth, width, height); + + std::array attachs = {}; + for (uint32_t i = 0; i < static_cast(attachs.size()); i++) + { + attachs[i].samples = VK_SAMPLE_COUNT_1_BIT; + attachs[i].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; + attachs[i].storeOp = VK_ATTACHMENT_STORE_OP_STORE; + attachs[i].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + attachs[i].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + attachs[i].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + attachs[i].finalLayout = 1 ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL; + } + attachs[0].format = pbrFrameBuffer.color.format; + attachs[1].format = pbrFrameBuffer.depth.format; + + VkAttachmentReference colorRefference = {}; + colorRefference.attachment = 0; + colorRefference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + + VkAttachmentReference depthRefference = {}; + colorRefference.attachment = 1; + colorRefference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + + VkSubpassDescription subpass = {}; + subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; + subpass.pColorAttachments = &colorRefference; + subpass.colorAttachmentCount = 1; + subpass.pDepthStencilAttachment = &depthRefference; + + std::array dependencies; + //To test src 0 + dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL; + dependencies[0].dstSubpass = 0; + dependencies[0].srcStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + dependencies[0].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + dependencies[0].srcAccessMask = VK_ACCESS_SHADER_READ_BIT; + dependencies[0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + dependencies[0].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; + + dependencies[1].srcSubpass = 0; + dependencies[1].dstSubpass = VK_SUBPASS_EXTERNAL; + dependencies[1].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + dependencies[1].dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + dependencies[1].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + dependencies[1].dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + dependencies[1].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; + + VkRenderPassCreateInfo renderPassCI = {}; + renderPassCI.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; + renderPassCI.pAttachments = attachs.data(); + renderPassCI.attachmentCount = static_cast(attachs.size()); + renderPassCI.pSubpasses = &subpass; + renderPassCI.pDependencies = dependencies.data(); + renderPassCI.dependencyCount = 2; + VK_CHECK_RESULT(vkCreateRenderPass(device, &renderPassCI, nullptr, &pbrFrameBuffer.fbo.renderPass)); + // FBO + VkImageView attachments[2] = { pbrFrameBuffer.color.imageView,pbrFrameBuffer.depth.imageView }; + VkFramebufferCreateInfo frameBufferCreateInfo = vks::initializers::framebufferCreateInfo(); + frameBufferCreateInfo.renderPass = pbrFrameBuffer.fbo.renderPass; + frameBufferCreateInfo.pAttachments = attachments; + frameBufferCreateInfo.attachmentCount = 2; + frameBufferCreateInfo.width = pbrFrameBuffer.fbo.width; + frameBufferCreateInfo.height = pbrFrameBuffer.fbo.height; + frameBufferCreateInfo.layers = 1; + VK_CHECK_RESULT(vkCreateFramebuffer(device, &frameBufferCreateInfo, nullptr, &pbrFrameBuffer.fbo.frameBuffer)); + + VkSamplerCreateInfo samplerCI = vks::initializers::samplerCreateInfo(); + samplerCI.magFilter = VK_FILTER_NEAREST; } void VulkanExample::getEnabledFeatures() diff --git a/homework/homework1/homework1.h b/homework/homework1/homework1.h index 1c7d3f3..3fd0791 100644 --- a/homework/homework1/homework1.h +++ b/homework/homework1/homework1.h @@ -273,6 +273,7 @@ public: VkDeviceMemory deviceMemory; VkImageView imageView; VkFormat format; + void destroy(VkDevice device) { From d6542ac2f100dec49c79ba5f5e4b6ce60a78da9b Mon Sep 17 00:00:00 2001 From: ink-soul Date: Tue, 23 May 2023 17:32:20 +0800 Subject: [PATCH 13/22] Update homework1.cpp --- homework/homework1/homework1.cpp | 51 ++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/homework/homework1/homework1.cpp b/homework/homework1/homework1.cpp index e4c7d34..22972fa 100644 --- a/homework/homework1/homework1.cpp +++ b/homework/homework1/homework1.cpp @@ -746,6 +746,24 @@ void VulkanExample::setupFrameBuffer() VkSamplerCreateInfo samplerCI = vks::initializers::samplerCreateInfo(); samplerCI.magFilter = VK_FILTER_NEAREST; + samplerCI.minFilter = VK_FILTER_NEAREST; + samplerCI.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; + samplerCI.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + samplerCI.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + samplerCI.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + + samplerCI.minLod = 0.0f; + samplerCI.maxLod = 1.0f; + samplerCI.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE; + + if (tonemappingDescriptorSet != VK_NULL_HANDLE) + { + auto imageInfo = vks::initializers::descriptorImageInfo(colorSampler, pbrFrameBuffer.color.imageView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + VkWriteDescriptorSet writeDescriptorSet = vks::initializers::writeDescriptorSet(tonemappingDescriptorSet, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 0, &imageInfo); + vkUpdateDescriptorSets(device, 1, &writeDescriptorSet, 0, nullptr); + + } + pbrFrameBuffer.bCreate = true; } void VulkanExample::getEnabledFeatures() @@ -791,6 +809,24 @@ void VulkanExample::getEnabledFeatures() drawUI(drawCmdBuffers[i]); vkCmdEndRenderPass(drawCmdBuffers[i]); VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); + + //tonemapping render pass + VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); + renderPassBeginInfo.renderPass = renderPass; + renderPassBeginInfo.framebuffer = VulkanExampleBase::frameBuffers[i]; + renderPassBeginInfo.renderArea.extent.width = width; + renderPassBeginInfo.renderArea.extent.height = height; + renderPassBeginInfo.clearValueCount = 2; + renderPassBeginInfo.pClearValues = clearValues; + + vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); + vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); + vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); + vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayouts.tonemappingLayout, 0, 1, &tonemappingDescriptorSet, 0, NULL); + vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.toneMapping); + vkCmdDraw(drawCmdBuffers[i], 3, 1, 0, 0); + drawUI(drawCmdBuffers[i]); + vkCmdEndRenderPass(drawCmdBuffers[i]); } } @@ -831,10 +867,24 @@ void VulkanExample::getEnabledFeatures() glTFModel.loadAnimations(glTFInput); // update joint in nodes + /* for (auto node : glTFModel.nodes) { + glTFModel.updateJoints(node); + }*/ + + for (size_t i = 0; i < glTFModel.nodes.size(); i++) + { + if (glTFModel.nodes[i]->skin > -1) + { + glTFModel.updateJoints(glTFModel.nodes[i]); + } + else + { + continue; + } } } else { @@ -879,6 +929,7 @@ void VulkanExample::getEnabledFeatures() vertexBufferSize, &glTFModel.vertices.buffer, &glTFModel.vertices.memory)); + VK_CHECK_RESULT(vulkanDevice->createBuffer( VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, From 441aca4df4cba65eb572f294e6d0c66bd544d763 Mon Sep 17 00:00:00 2001 From: ink-soul Date: Wed, 24 May 2023 11:12:54 +0800 Subject: [PATCH 14/22] update setupDescriptor for pbr and tonemapping --- homework/homework1/homework1.cpp | 179 ++++++++++++++++++++++++++----- homework/homework1/homework1.h | 1 + 2 files changed, 153 insertions(+), 27 deletions(-) diff --git a/homework/homework1/homework1.cpp b/homework/homework1/homework1.cpp index 22972fa..6083a9c 100644 --- a/homework/homework1/homework1.cpp +++ b/homework/homework1/homework1.cpp @@ -979,11 +979,16 @@ void VulkanExample::getEnabledFeatures() */ std::vector poolSizes = { - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1), + vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 4), // One combined image sampler per material image/texture vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, static_cast(glTFModel.images.size())), // One ssbo per skin vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, static_cast(glTFModel.skins.size())), + // sampler descriptor + vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,4), + //animation storage buffer + vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,1) + }; // Number of descriptor sets = One for the scene ubo + one per image + one per skin const uint32_t maxSetCount = static_cast(glTFModel.images.size()) + static_cast(glTFModel.skins.size()) + 1; @@ -991,18 +996,29 @@ void VulkanExample::getEnabledFeatures() VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); // Descriptor set layouts - VkDescriptorSetLayoutBinding setLayoutBinding{}; - VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCI = vks::initializers::descriptorSetLayoutCreateInfo(&setLayoutBinding, 1); - + std::vector setLayoutBindings = + { + vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0), + vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 1), + vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 2), + vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 3), + }; + VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCI = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); // Descriptor set layout for passing matrices - setLayoutBinding = vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0); VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorSetLayoutCI, nullptr, &descriptorSetLayouts.matrices)); - + // Descriptor set layout for material uniform buffer + VkDescriptorSetLayoutBinding materialBufferLayoutBinding = vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT, 0); + descriptorSetLayoutCI = vks::initializers::descriptorSetLayoutCreateInfo(&materialBufferLayoutBinding, 1); + VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorSetLayoutCI, nullptr, &descriptorSetLayouts.materialUniform)); // Descriptor set layout for passing material textures - setLayoutBinding = vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 0); + VkDescriptorSetLayoutBinding setLayoutBinding = vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 0); + descriptorSetLayoutCI = vks::initializers::descriptorSetLayoutCreateInfo(&setLayoutBinding, 1); VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorSetLayoutCI, nullptr, &descriptorSetLayouts.textures)); - + // Descriptor set layout for ssbo + setLayoutBinding = vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0); + VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorSetLayoutCI, nullptr, &descriptorSetLayouts.ssbo)); // Descriptor set layout for passing skin joint matrices + setLayoutBinding = vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0); VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorSetLayoutCI, nullptr, &descriptorSetLayouts.jointMatrices)); @@ -1010,31 +1026,66 @@ void VulkanExample::getEnabledFeatures() // Set 0 = Scene matrices (VS) // Set 1 = Joint matrices (VS) // Set 2 = Material texture (FS) - std::array setLayouts = { + std::array setLayouts = { descriptorSetLayouts.matrices, descriptorSetLayouts.jointMatrices, - descriptorSetLayouts.textures }; + descriptorSetLayouts.textures, + descriptorSetLayouts.textures, + descriptorSetLayouts.textures, + descriptorSetLayouts.textures, + descriptorSetLayouts.materialUniform, + descriptorSetLayouts.ssbo, + }; VkPipelineLayoutCreateInfo pipelineLayoutCI = vks::initializers::pipelineLayoutCreateInfo(setLayouts.data(), static_cast(setLayouts.size())); - + VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCI, nullptr, &pipelineLayout)); + /* + // We will use push constants to push the local matrices of a primitive to the vertex shader VkPushConstantRange pushConstantRange = vks::initializers::pushConstantRange(VK_SHADER_STAGE_VERTEX_BIT, sizeof(glm::mat4), 0); // Push constant ranges are part of the pipeline layout pipelineLayoutCI.pushConstantRangeCount = 1; pipelineLayoutCI.pPushConstantRanges = &pushConstantRange; - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCI, nullptr, &pipelineLayout)); - + + */ // Descriptor set for scene matrices VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayouts.matrices, 1); VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet)); - VkWriteDescriptorSet writeDescriptorSet = vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &shaderData.buffer.descriptor); - vkUpdateDescriptorSets(device, 1, &writeDescriptorSet, 0, nullptr); + std::vector writeDescriptorSets = + { + vks::initializers::writeDescriptorSet(descriptorSet,VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,0,&shaderData.buffer.descriptor), + vks::initializers::writeDescriptorSet(descriptorSet,VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,1,&ibltextures.irradianceCube.descriptor), + vks::initializers::writeDescriptorSet(descriptorSet,VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,2,&ibltextures.lutBrdf.descriptor), + vks::initializers::writeDescriptorSet(descriptorSet,VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,3,&ibltextures.prefilteredCube.descriptor), + + }; + + vkUpdateDescriptorSets(device, 4, writeDescriptorSets.data(), 0, nullptr); // Descriptor set for glTF model skin joint matrices - for (auto& skin : glTFModel.skins) + if (glTFModel.skins.size() > 0) { - const VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayouts.jointMatrices, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &skin.descriptorSet)); - VkWriteDescriptorSet writeDescriptorSet = vks::initializers::writeDescriptorSet(skin.descriptorSet, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 0, &skin.ssbo.descriptor); + for (auto& skin : glTFModel.skins) + { + const VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayouts.jointMatrices, 1); + VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &skin.descriptorSet)); + VkWriteDescriptorSet writeDescriptorSet = vks::initializers::writeDescriptorSet(skin.descriptorSet, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 0, &skin.ssbo.descriptor); + vkUpdateDescriptorSets(device, 1, &writeDescriptorSet, 0, nullptr); + } + } + else + { + const VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayouts.ssbo, 1); + VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &skinDescriptorSet)); + VkWriteDescriptorSet writeDescriptorSet = vks::initializers::writeDescriptorSet(skinDescriptorSet, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 0, &shaderData.skinSSBO.descriptor); + vkUpdateDescriptorSets(device, 1, &writeDescriptorSet, 0, nullptr); + } + + + for (auto& material : glTFModel.materials) + { + const VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayouts.materialUniform, 1); + VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &material.materialData.descriptorSet)); + VkWriteDescriptorSet writeDescriptorSet = vks::initializers::writeDescriptorSet(material.materialData.descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &material.materialData.buffer.descriptor); vkUpdateDescriptorSets(device, 1, &writeDescriptorSet, 0, nullptr); } @@ -1046,6 +1097,19 @@ void VulkanExample::getEnabledFeatures() VkWriteDescriptorSet writeDescriptorSet = vks::initializers::writeDescriptorSet(image.descriptorSet, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 0, &image.texture.descriptor); vkUpdateDescriptorSets(device, 1, &writeDescriptorSet, 0, nullptr); } + + //tonemapping pipline layout + { + VkPipelineLayoutCreateInfo piplineLayoutCI = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayouts.textures, 1); + VK_CHECK_RESULT(vkCreatePipelineLayout(device, &piplineLayoutCI, nullptr, &pipelineLayouts.tonemappingLayout)); + + const VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayouts.textures, 1); + VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &tonemappingDescriptorSet)); + + VkDescriptorImageInfo imageInfo = vks::initializers::descriptorImageInfo(colorSampler, pbrFrameBuffer.color.imageView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + VkWriteDescriptorSet writeDescriptorSet = vks::initializers::writeDescriptorSet(tonemappingDescriptorSet, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 0, &imageInfo); + vkUpdateDescriptorSets(device, 1, &writeDescriptorSet, 0, nullptr); + } } @@ -1069,9 +1133,10 @@ void VulkanExample::getEnabledFeatures() {1, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(VulkanglTFModel::Vertex, normal)}, {2, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(VulkanglTFModel::Vertex, uv)}, {3, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(VulkanglTFModel::Vertex, color)}, + {4, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(VulkanglTFModel::Vertex, tangent)}, // POI: Per-Vertex Joint indices and weights are passed to the vertex shader - {4, 0, VK_FORMAT_R32G32B32A32_SFLOAT, offsetof(VulkanglTFModel::Vertex, jointIndices)}, - {5, 0, VK_FORMAT_R32G32B32A32_SFLOAT, offsetof(VulkanglTFModel::Vertex, jointWeights)}, + {5, 0, VK_FORMAT_R32G32B32A32_SFLOAT, offsetof(VulkanglTFModel::Vertex, jointIndices)}, + {6, 0, VK_FORMAT_R32G32B32A32_SFLOAT, offsetof(VulkanglTFModel::Vertex, jointWeights)}, }; VkPipelineVertexInputStateCreateInfo vertexInputStateCI = vks::initializers::pipelineVertexInputStateCreateInfo(); vertexInputStateCI.vertexBindingDescriptionCount = static_cast(vertexInputBindings.size()); @@ -1106,6 +1171,44 @@ void VulkanExample::getEnabledFeatures() VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.wireframe)); } } + void VulkanExample::prepareToneMappingPipeline() + { + if (pipelines.toneMapping != VK_NULL_HANDLE) + { + vkDestroyPipeline(device, pipelines.toneMapping, nullptr); + pipelines.toneMapping = VK_NULL_HANDLE; + } + VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCI = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); + VkPipelineRasterizationStateCreateInfo rasterizationStateCI = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_BACK_BIT, VK_FRONT_FACE_COUNTER_CLOCKWISE, 0); + VkPipelineColorBlendAttachmentState blendAttachmentStateCI = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); + VkPipelineColorBlendStateCreateInfo colorBlendStateCI = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentStateCI); + VkPipelineDepthStencilStateCreateInfo depthStencilStateCI = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL); + VkPipelineViewportStateCreateInfo viewportStateCI = vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); + VkPipelineMultisampleStateCreateInfo multisampleStateCI = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT, 0); + const std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; + VkPipelineDynamicStateCreateInfo dynamicStateCI = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables.data(), static_cast(dynamicStateEnables.size()), 0); + VkPipelineVertexInputStateCreateInfo emptyInputState = vks::initializers::pipelineVertexInputStateCreateInfo(); + + const std::string fragPath = ToneMapping ? "homework1/tonemapping_enable.frag.spv" : "homework1/tonemapping_disable.frag.spv"; + std::array shaderStages = { + loadShader(getHomeworkShadersPath() + "homework1/genbrdflut.vert.spv", VK_SHADER_STAGE_VERTEX_BIT), + loadShader(getHomeworkShadersPath() + fragPath, VK_SHADER_STAGE_FRAGMENT_BIT) + }; + + VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(pipelineLayouts.tonemappingLayout, renderPass, 0); + pipelineCI.pVertexInputState = &emptyInputState; + pipelineCI.pInputAssemblyState = &inputAssemblyStateCI; + pipelineCI.pRasterizationState = &rasterizationStateCI; + pipelineCI.pColorBlendState = &colorBlendStateCI; + pipelineCI.pMultisampleState = &multisampleStateCI; + pipelineCI.pViewportState = &viewportStateCI; + pipelineCI.pDepthStencilState = &depthStencilStateCI; + pipelineCI.pDynamicState = &dynamicStateCI; + pipelineCI.stageCount = static_cast(shaderStages.size()); + pipelineCI.pStages = shaderStages.data(); + + VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.toneMapping)); + } // Prepare and initialize uniform buffer containing shader uniforms void VulkanExample::prepareUniformBuffers() @@ -1117,9 +1220,28 @@ void VulkanExample::getEnabledFeatures() &shaderData.buffer, sizeof(shaderData.values))); + VK_CHECK_RESULT(vulkanDevice->createBuffer( + VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, + &shaderData.skinSSBO, + sizeof(glm::mat4) * glTFModel.nodeCount)); + + for (auto& material : glTFModel.materials) + { + VK_CHECK_RESULT(vulkanDevice->createBuffer( + VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, + &material.materialData.buffer, + sizeof(VulkanglTFModel::MaterialData::Values), + &material.materialData.values + )); + + } + // Map persistent VK_CHECK_RESULT(shaderData.buffer.map()); - + VK_CHECK_RESULT(shaderData.skinSSBO.map()); + updateUniformBuffers(); } @@ -1127,7 +1249,10 @@ void VulkanExample::getEnabledFeatures() { shaderData.values.projection = camera.matrices.perspective; shaderData.values.model = camera.matrices.view; - + shaderData.values.viewPos = camera.viewPos; + shaderData.values.bFlagSet.x = normalMapping; + shaderData.values.bFlagSet.y = pbrEnabled; + memcpy(shaderData.buffer.mapped, &shaderData.values, sizeof(shaderData.values)); } @@ -1192,11 +1317,11 @@ void VulkanExample::getEnabledFeatures() #pragma endregion +// ----------------------- pbr precompute end --------------------------------------- + + + - - - - // ----------------------- pbr precompute end --------------------------------------- void VulkanExample::prepare() { VulkanExampleBase::prepare(); diff --git a/homework/homework1/homework1.h b/homework/homework1/homework1.h index 3fd0791..5b6bcf3 100644 --- a/homework/homework1/homework1.h +++ b/homework/homework1/homework1.h @@ -364,6 +364,7 @@ public: void loadAssets(); void setupDescriptors(); void preparePipelines(); + void prepareToneMappingPipeline(); void prepareUniformBuffers(); void updateUniformBuffers(); void prepare(); From 463ac6fe590a6866b468d7c3220e35d544fc47b5 Mon Sep 17 00:00:00 2001 From: ink-soul Date: Wed, 24 May 2023 16:10:36 +0800 Subject: [PATCH 15/22] update irradiance caculation --- CMakeSettings.json | 11 + homework/homework1/homework1.cpp | 965 ++++++++++++++++++++++++++++++- homework/homework1/homework1.h | 32 +- 3 files changed, 999 insertions(+), 9 deletions(-) diff --git a/CMakeSettings.json b/CMakeSettings.json index 7313f2b..c9b700d 100644 --- a/CMakeSettings.json +++ b/CMakeSettings.json @@ -20,6 +20,17 @@ "cmakeCommandArgs": "", "buildCommandArgs": "", "ctestCommandArgs": "", + "inheritEnvironments": [ "clang_cl_x64_x64" ] + }, + { + "name": "x64-Clang-Release", + "generator": "Ninja", + "configurationType": "RelWithDebInfo", + "buildRoot": "${projectDir}\\out\\build\\${name}", + "installRoot": "${projectDir}\\out\\install\\${name}", + "cmakeCommandArgs": "", + "buildCommandArgs": "", + "ctestCommandArgs": "", "inheritEnvironments": [ "clang_cl_x64_x64" ], "variables": [] } diff --git a/homework/homework1/homework1.cpp b/homework/homework1/homework1.cpp index 6083a9c..4b498c1 100644 --- a/homework/homework1/homework1.cpp +++ b/homework/homework1/homework1.cpp @@ -830,7 +830,7 @@ void VulkanExample::getEnabledFeatures() } } - void VulkanExample::loadglTFFile(std::string filename) + void VulkanExample::loadglTFFile(std::string filename, VulkanglTFModel& model, bool bSkyboxFlag = false) { tinygltf::Model glTFInput; tinygltf::TinyGLTF gltfContext; @@ -900,10 +900,7 @@ void VulkanExample::getEnabledFeatures() size_t indexBufferSize = indexBuffer.size() * sizeof(uint32_t); glTFModel.indices.count = static_cast(indexBuffer.size()); - struct StagingBuffer { - VkBuffer buffer; - VkDeviceMemory memory; - } vertexStaging, indexStaging; + // Create host visible staging buffers (source) VK_CHECK_RESULT(vulkanDevice->createBuffer( @@ -969,7 +966,9 @@ void VulkanExample::getEnabledFeatures() void VulkanExample::loadAssets() { - loadglTFFile(getAssetPath() + "buster_drone/busterDrone.gltf"); + loadglTFFile(getAssetPath() + "buster_drone/busterDrone.gltf",glTFModel); + loadglTFFile(getAssetPath() + "models/cube.gltf", skyboxModel, true); + ibltextures.skyboxCube.loadFromFile(getAssetPath() + "textures/hdr/pisa_cube.ktx", VK_FORMAT_R16G16B16A16_SFLOAT, vulkanDevice, queue); } void VulkanExample::setupDescriptors() @@ -1056,7 +1055,6 @@ void VulkanExample::getEnabledFeatures() vks::initializers::writeDescriptorSet(descriptorSet,VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,1,&ibltextures.irradianceCube.descriptor), vks::initializers::writeDescriptorSet(descriptorSet,VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,2,&ibltextures.lutBrdf.descriptor), vks::initializers::writeDescriptorSet(descriptorSet,VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,3,&ibltextures.prefilteredCube.descriptor), - }; vkUpdateDescriptorSets(device, 4, writeDescriptorSets.data(), 0, nullptr); @@ -1256,7 +1254,955 @@ void VulkanExample::getEnabledFeatures() memcpy(shaderData.buffer.mapped, &shaderData.values, sizeof(shaderData.values)); } - //-------------------------- pbr precompute start ---------------------------------- +// --------- BRDF LUT precompute preparation ---------------- + void VulkanExample::generateIrradianceCubemap() + { + auto tStart = std::chrono::high_resolution_clock::now(); + + constexpr VkFormat format = VK_FORMAT_R32G32B32A32_SFLOAT; + constexpr int32_t dim = 64; + const uint32_t numMips = static_cast(floor(log2(dim))) + 1; + + VkImageCreateInfo imageCI = vks::initializers::imageCreateInfo(); + imageCI.imageType = VK_IMAGE_TYPE_2D; + imageCI.format = format; + imageCI.extent.width = dim; + imageCI.extent.height = dim; + imageCI.extent.depth = 1; + imageCI.mipLevels = numMips; + imageCI.arrayLayers = 6; + imageCI.samples = VK_SAMPLE_COUNT_1_BIT; + imageCI.tiling = VK_IMAGE_TILING_OPTIMAL; + imageCI.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; + imageCI.flags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; + VK_CHECK_RESULT(vkCreateImage(device, &imageCI, nullptr, &ibltextures.irradianceCube.image)) + + // allocate memory for irradiance cube map + VkMemoryAllocateInfo memAlloc = vks::initializers::memoryAllocateInfo(); + VkMemoryRequirements memReqs; + vkGetImageMemoryRequirements(device, ibltextures.irradianceCube.image, &memReqs); + memAlloc.allocationSize = memReqs.size; + memAlloc.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &ibltextures.irradianceCube.deviceMemory)) + VK_CHECK_RESULT(vkBindImageMemory(device, ibltextures.irradianceCube.image, ibltextures.irradianceCube.deviceMemory, 0)) + + + VkImageViewCreateInfo viewCI = vks::initializers::imageViewCreateInfo(); + viewCI.viewType = VK_IMAGE_VIEW_TYPE_CUBE; + viewCI.format = format; + viewCI.subresourceRange = {}; + viewCI.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + viewCI.subresourceRange.levelCount = numMips; + viewCI.subresourceRange.layerCount = 6; + viewCI.image = ibltextures.irradianceCube.image; + VK_CHECK_RESULT(vkCreateImageView(device, &viewCI, nullptr, &ibltextures.irradianceCube.view)) + + // set up sampler and image view + VkSamplerCreateInfo samplerCI = vks::initializers::samplerCreateInfo(); + samplerCI.magFilter = VK_FILTER_LINEAR; + samplerCI.minFilter = VK_FILTER_LINEAR; + samplerCI.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; + samplerCI.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + samplerCI.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + samplerCI.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + samplerCI.minLod = 0.0f; + samplerCI.maxLod = static_cast(numMips); + samplerCI.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE; + VK_CHECK_RESULT(vkCreateSampler(device, &samplerCI, nullptr, &ibltextures.irradianceCube.sampler)) + + ibltextures.irradianceCube.descriptor.imageView = ibltextures.irradianceCube.view; + ibltextures.irradianceCube.descriptor.sampler = ibltextures.irradianceCube.sampler; + ibltextures.irradianceCube.descriptor.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + ibltextures.irradianceCube.device = vulkanDevice; + + + //Setup Framebuffer and so on + VkAttachmentDescription attachDescription = {}; + attachDescription.format = format; + attachDescription.samples = VK_SAMPLE_COUNT_1_BIT; + attachDescription.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; + attachDescription.storeOp = VK_ATTACHMENT_STORE_OP_STORE; + attachDescription.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + attachDescription.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + attachDescription.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + attachDescription.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + + VkAttachmentReference colorReference = { 0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL }; + VkSubpassDescription subpassDescription = {}; + subpassDescription.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; + subpassDescription.colorAttachmentCount = 1; + subpassDescription.pColorAttachments = &colorReference; + + std::array dependencies; + dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL; + dependencies[0].dstSubpass = 0; + dependencies[0].srcStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; + dependencies[0].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + dependencies[0].srcAccessMask = VK_ACCESS_MEMORY_READ_BIT; + dependencies[0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + dependencies[0].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; + dependencies[1].srcSubpass = 0; + dependencies[1].dstSubpass = VK_SUBPASS_EXTERNAL; + dependencies[1].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + dependencies[1].dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; + dependencies[1].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + dependencies[1].dstAccessMask = VK_ACCESS_MEMORY_READ_BIT; + dependencies[1].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; + //set up render pass + VkRenderPassCreateInfo renderPassCI = vks::initializers::renderPassCreateInfo(); + renderPassCI.attachmentCount = 1; + renderPassCI.pAttachments = &attachDescription; + renderPassCI.subpassCount = 1; + renderPassCI.pSubpasses = &subpassDescription; + renderPassCI.dependencyCount = 2; + renderPassCI.pDependencies = dependencies.data(); + VkRenderPass renderpass; + VK_CHECK_RESULT(vkCreateRenderPass(device, &renderPassCI, nullptr, &renderpass)); + + // create offscreen image + VkImageCreateInfo imageCreateInfo = vks::initializers::imageCreateInfo(); + imageCreateInfo.imageType = VK_IMAGE_TYPE_2D; + imageCreateInfo.format = format; + imageCreateInfo.extent.width = dim; + imageCreateInfo.extent.height = dim; + imageCreateInfo.extent.depth = 1; + imageCreateInfo.mipLevels = 1; + imageCreateInfo.arrayLayers = 1; + imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT; + imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL; + imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + imageCreateInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT; + imageCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + VK_CHECK_RESULT(vkCreateImage(device, &imageCreateInfo, nullptr, &offscreen.image)) + + // allocate memory + VkMemoryAllocateInfo imageCIMemAlloc = vks::initializers::memoryAllocateInfo(); + VkMemoryRequirements imageCIMemReqs; + vkGetImageMemoryRequirements(device, offscreen.image, &imageCIMemReqs); + imageCIMemAlloc.allocationSize = imageCIMemReqs.size; + imageCIMemAlloc.memoryTypeIndex = vulkanDevice->getMemoryType(imageCIMemReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + VK_CHECK_RESULT(vkAllocateMemory(device, &imageCIMemAlloc, nullptr, &offscreen.memory)) + VK_CHECK_RESULT(vkBindImageMemory(device, offscreen.image, offscreen.memory, 0)) + + // create color image view + VkImageViewCreateInfo colorImageView = vks::initializers::imageViewCreateInfo(); + colorImageView.viewType = VK_IMAGE_VIEW_TYPE_2D; + colorImageView.format = format; + colorImageView.flags = 0; + colorImageView.subresourceRange = {}; + colorImageView.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + colorImageView.subresourceRange.baseMipLevel = 0; + colorImageView.subresourceRange.levelCount = 1; + colorImageView.subresourceRange.baseArrayLayer = 0; + colorImageView.subresourceRange.layerCount = 1; + colorImageView.image = offscreen.image; + VK_CHECK_RESULT(vkCreateImageView(device, &colorImageView, nullptr, &offscreen.view)) + + // set up framebuffer for offscreen image + VkFramebufferCreateInfo fbufCreateInfo = vks::initializers::framebufferCreateInfo(); + fbufCreateInfo.renderPass = renderpass; + fbufCreateInfo.attachmentCount = 1; + fbufCreateInfo.pAttachments = &offscreen.view; + fbufCreateInfo.width = dim; + fbufCreateInfo.height = dim; + fbufCreateInfo.layers = 1; + VK_CHECK_RESULT(vkCreateFramebuffer(device, &fbufCreateInfo, nullptr, &offscreen.framebuffer)) + + VkCommandBuffer layoutCmd = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); + vks::tools::setImageLayout( + layoutCmd, + offscreen.image, + VK_IMAGE_ASPECT_COLOR_BIT, + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + vulkanDevice->flushCommandBuffer(layoutCmd, queue, true); + + // create descriptor set layout + VkDescriptorSetLayout descriptorsetlayout; + std::vector setLayoutBindings = + { + vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 0), + }; + VkDescriptorSetLayoutCreateInfo descriptorsetlayoutCI = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); + VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorsetlayoutCI, nullptr, &descriptorsetlayout)); + // allocate pool + std::vector poolSizes = { vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1) }; + VkDescriptorPoolCreateInfo descriptorPoolCI = vks::initializers::descriptorPoolCreateInfo(poolSizes, 2); + VkDescriptorPool descriptorpool; + VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolCI, nullptr, &descriptorpool)); + //write to poos + VkDescriptorSet descriptorset; + VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorpool, &descriptorsetlayout, 1); + VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorset)); + VkWriteDescriptorSet writeDescriptorSet = vks::initializers::writeDescriptorSet(descriptorset, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 0, &ibltextures.skyboxCube.descriptor); + vkUpdateDescriptorSets(device, 1, &writeDescriptorSet, 0, nullptr); + // push matrix + VkPipelineLayout pipelinelayout; + std::vector pushConstantRanges = + { + vks::initializers::pushConstantRange(VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, sizeof(IrradiancePushBlock), 0) + }; + VkPipelineLayoutCreateInfo pipelineLayoutCI = vks::initializers::pipelineLayoutCreateInfo(&descriptorsetlayout, 1); + pipelineLayoutCI.pushConstantRangeCount = 1; + pipelineLayoutCI.pPushConstantRanges = pushConstantRanges.data(); + VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCI, nullptr, &pipelinelayout)); + + //Pipeline Setting + VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); + VkPipelineRasterizationStateCreateInfo rasterizationState = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_NONE, VK_FRONT_FACE_COUNTER_CLOCKWISE); + VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); + VkPipelineColorBlendStateCreateInfo colorBlendState = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); + VkPipelineDepthStencilStateCreateInfo depthStencilState = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_FALSE, VK_FALSE, VK_COMPARE_OP_LESS_OR_EQUAL); + VkPipelineViewportStateCreateInfo viewportState = vks::initializers::pipelineViewportStateCreateInfo(1, 1); + VkPipelineMultisampleStateCreateInfo multisampleState = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT); + std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; + VkPipelineDynamicStateCreateInfo dynamicState = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); + std::array shaderStages; + + const std::vector vertexInputBindings = + { + vks::initializers::vertexInputBindingDescription(0, sizeof(VulkanglTFModel::Vertex), VK_VERTEX_INPUT_RATE_VERTEX), + }; + + const std::vector vertexInputAttributes = { + vks::initializers::vertexInputAttributeDescription(0, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(VulkanglTFModel::Vertex, pos)), // Location 0: Position + }; + VkPipelineVertexInputStateCreateInfo vertexInputStateCI = vks::initializers::pipelineVertexInputStateCreateInfo(); + vertexInputStateCI.vertexBindingDescriptionCount = static_cast(vertexInputBindings.size()); + vertexInputStateCI.pVertexBindingDescriptions = vertexInputBindings.data(); + vertexInputStateCI.vertexAttributeDescriptionCount = static_cast(vertexInputAttributes.size()); + vertexInputStateCI.pVertexAttributeDescriptions = vertexInputAttributes.data(); + + VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(pipelinelayout, renderpass); + pipelineCI.pInputAssemblyState = &inputAssemblyState; + pipelineCI.pRasterizationState = &rasterizationState; + pipelineCI.pColorBlendState = &colorBlendState; + pipelineCI.pMultisampleState = &multisampleState; + pipelineCI.pViewportState = &viewportState; + pipelineCI.pDepthStencilState = &depthStencilState; + pipelineCI.pDynamicState = &dynamicState; + pipelineCI.stageCount = 2; + pipelineCI.pStages = shaderStages.data(); + pipelineCI.renderPass = renderpass; + + pipelineCI.pVertexInputState = &vertexInputStateCI; + shaderStages[0] = loadShader(getHomeworkShadersPath() + "homework1/filtercube.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); + shaderStages[1] = loadShader(getHomeworkShadersPath() + "homework1/irradiancecube.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); + VkPipeline pipeline; + VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipeline)); + + // offscreen Render pass begin + VkClearValue clearValues[1]; + clearValues[0].color = { { 0.0f, 0.0f, 0.2f, 0.0f } }; + VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); + renderPassBeginInfo.renderPass = renderpass; + renderPassBeginInfo.framebuffer = offscreen.framebuffer; + renderPassBeginInfo.renderArea.extent.width = dim; + renderPassBeginInfo.renderArea.extent.height = dim; + renderPassBeginInfo.clearValueCount = 1; + renderPassBeginInfo.pClearValues = clearValues; + + //six face in cube map + std::vector matrices = { + // POSITIVE_X + glm::rotate(glm::rotate(glm::mat4(1.0f), glm::radians(90.0f), glm::vec3(0.0f, 1.0f, 0.0f)), glm::radians(180.0f), glm::vec3(1.0f, 0.0f, 0.0f)), + // NEGATIVE_X + glm::rotate(glm::rotate(glm::mat4(1.0f), glm::radians(-90.0f), glm::vec3(0.0f, 1.0f, 0.0f)), glm::radians(180.0f), glm::vec3(1.0f, 0.0f, 0.0f)), + // POSITIVE_Y + glm::rotate(glm::mat4(1.0f), glm::radians(-90.0f), glm::vec3(1.0f, 0.0f, 0.0f)), + // NEGATIVE_Y + glm::rotate(glm::mat4(1.0f), glm::radians(90.0f), glm::vec3(1.0f, 0.0f, 0.0f)), + // POSITIVE_Z + glm::rotate(glm::mat4(1.0f), glm::radians(180.0f), glm::vec3(1.0f, 0.0f, 0.0f)), + // NEGATIVE_Z + glm::rotate(glm::mat4(1.0f), glm::radians(180.0f), glm::vec3(0.0f, 0.0f, 1.0f)), + }; + VkCommandBuffer cmdBuf = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); + VkViewport viewport = vks::initializers::viewport((float)dim, (float)dim, 0.0f, 1.0f); + VkRect2D scissor = vks::initializers::rect2D(dim, dim, 0, 0); + + vkCmdSetViewport(cmdBuf, 0, 1, &viewport); + vkCmdSetScissor(cmdBuf, 0, 1, &scissor); + + VkImageSubresourceRange subresourceRange = {}; + subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + subresourceRange.baseMipLevel = 0; + subresourceRange.levelCount = numMips; + subresourceRange.layerCount = 6; + + vks::tools::setImageLayout( + cmdBuf, + ibltextures.irradianceCube.image, + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + subresourceRange); + + for (uint32_t m = 0; m < numMips; ++m) + { + for (uint32_t f = 0; f < 6; ++f) + { + viewport.width = static_cast(dim * std::pow(0.5f, m)); + viewport.height = static_cast(dim * std::pow(0.5f, m)); + vkCmdSetViewport(cmdBuf, 0, 1, &viewport); + // Render scene from cube face's point of view + vkCmdBeginRenderPass(cmdBuf, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); + irradinacePushBlock.mvp = glm::perspective((float)(M_PI / 2.0), 1.0f, 0.1f, 512.0f) * matrices[f]; + vkCmdPushConstants(cmdBuf, pipelinelayout, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(IrradiancePushBlock), &irradinacePushBlock); + + vkCmdBindPipeline(cmdBuf, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); + vkCmdBindDescriptorSets(cmdBuf, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelinelayout, 0, 1, &descriptorset, 0, NULL); + skyboxModel.draw(cmdBuf, pipelinelayout); + vkCmdEndRenderPass(cmdBuf); + + vks::tools::setImageLayout( + cmdBuf, + offscreen.image, + VK_IMAGE_ASPECT_COLOR_BIT, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); + + VkImageCopy copyRegion = {}; + copyRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + copyRegion.srcSubresource.layerCount = 1; + copyRegion.srcSubresource.mipLevel = 0; + copyRegion.srcSubresource.baseArrayLayer = 0; + + copyRegion.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + copyRegion.dstSubresource.layerCount = 1; + copyRegion.dstSubresource.mipLevel = m; + copyRegion.dstSubresource.baseArrayLayer = f; + + copyRegion.extent.width = static_cast(viewport.width); + copyRegion.extent.height = static_cast(viewport.height); + copyRegion.extent.depth = 1; + + vkCmdCopyImage( + cmdBuf, + offscreen.image, + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + ibltextures.irradianceCube.image, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + 1, + ©Region); + vks::tools::setImageLayout(cmdBuf, + offscreen.image, + VK_IMAGE_ASPECT_COLOR_BIT, + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL + ); + } + } + + vks::tools::setImageLayout(cmdBuf, + ibltextures.irradianceCube.image, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + subresourceRange); + vulkanDevice->flushCommandBuffer(cmdBuf, queue); + + vkDestroyRenderPass(device, renderpass, nullptr); + vkDestroyFramebuffer(device, offscreen.framebuffer, nullptr); + vkFreeMemory(device, offscreen.memory, nullptr); + vkDestroyImageView(device, offscreen.view, nullptr); + vkDestroyImage(device, offscreen.image, nullptr); + vkDestroyDescriptorPool(device, descriptorpool, nullptr); + vkDestroyDescriptorSetLayout(device, descriptorsetlayout, nullptr); + vkDestroyPipeline(device, pipeline, nullptr); + vkDestroyPipelineLayout(device, pipelinelayout, nullptr); + + auto tEnd = std::chrono::high_resolution_clock::now(); + auto tDiff = std::chrono::duration(tEnd - tStart).count(); + std::cout << "Generating irradiance cube with " << numMips << " mip levels took " << tDiff << " ms" << std::endl; + + } + + + void VulkanExample::generatePrefilteredCubemap() + { + auto tStart = std::chrono::high_resolution_clock::now(); + + constexpr VkFormat format = VK_FORMAT_R32G32B32A32_SFLOAT; + constexpr int32_t dim = 512; + const uint32_t numMips = static_cast(floor(log2(dim))) + 1; + + VkImageCreateInfo imageCI = vks::initializers::imageCreateInfo(); + imageCI.imageType = VK_IMAGE_TYPE_2D; + imageCI.format = format; + imageCI.extent.width = dim; + imageCI.extent.height = dim; + imageCI.extent.depth = 1; + imageCI.mipLevels = numMips; + imageCI.arrayLayers = 6; + imageCI.samples = VK_SAMPLE_COUNT_1_BIT; + imageCI.tiling = VK_IMAGE_TILING_OPTIMAL; + imageCI.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; + imageCI.flags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; + + VK_CHECK_RESULT(vkCreateImage(device, &imageCI, nullptr, &ibltextures.prefilteredCube.image)); + VkMemoryAllocateInfo memAlloc = vks::initializers::memoryAllocateInfo(); + VkMemoryRequirements memReqs; + vkGetImageMemoryRequirements(device, ibltextures.prefilteredCube.image, &memReqs); + memAlloc.allocationSize = memReqs.size; + memAlloc.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &ibltextures.prefilteredCube.deviceMemory)); + VK_CHECK_RESULT(vkBindImageMemory(device, ibltextures.prefilteredCube.image, ibltextures.prefilteredCube.deviceMemory, 0)); + + // Image view + VkImageViewCreateInfo viewCI = vks::initializers::imageViewCreateInfo(); + viewCI.viewType = VK_IMAGE_VIEW_TYPE_CUBE; + viewCI.format = format; + viewCI.subresourceRange = {}; + viewCI.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + viewCI.subresourceRange.levelCount = numMips; + viewCI.subresourceRange.layerCount = 6; + viewCI.image = ibltextures.prefilteredCube.image; + VK_CHECK_RESULT(vkCreateImageView(device, &viewCI, nullptr, &ibltextures.prefilteredCube.view)); + + // Sampler + VkSamplerCreateInfo samplerCI = vks::initializers::samplerCreateInfo(); + samplerCI.magFilter = VK_FILTER_LINEAR; + samplerCI.minFilter = VK_FILTER_LINEAR; + samplerCI.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; + samplerCI.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + samplerCI.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + samplerCI.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + samplerCI.minLod = 0.0f; + samplerCI.maxLod = static_cast(numMips); + samplerCI.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE; + VK_CHECK_RESULT(vkCreateSampler(device, &samplerCI, nullptr, &ibltextures.prefilteredCube.sampler)); + + ibltextures.prefilteredCube.descriptor.imageView = ibltextures.prefilteredCube.view; + ibltextures.prefilteredCube.descriptor.sampler = ibltextures.prefilteredCube.sampler; + ibltextures.prefilteredCube.descriptor.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + ibltextures.prefilteredCube.device = vulkanDevice; + + // FB, Att, RP, Pipe, etc. + VkAttachmentDescription attDesc = {}; + // Color attachment + attDesc.format = format; + attDesc.samples = VK_SAMPLE_COUNT_1_BIT; + attDesc.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; + attDesc.storeOp = VK_ATTACHMENT_STORE_OP_STORE; + attDesc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + attDesc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + attDesc.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + attDesc.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + VkAttachmentReference colorReference = { 0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL }; + + VkSubpassDescription subpassDescription = {}; + subpassDescription.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; + subpassDescription.colorAttachmentCount = 1; + subpassDescription.pColorAttachments = &colorReference; + + // Use subpass dependencies for layout transitions + std::array dependencies; + dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL; + dependencies[0].dstSubpass = 0; + dependencies[0].srcStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; + dependencies[0].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + dependencies[0].srcAccessMask = VK_ACCESS_MEMORY_READ_BIT; + dependencies[0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + dependencies[0].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; + dependencies[1].srcSubpass = 0; + dependencies[1].dstSubpass = VK_SUBPASS_EXTERNAL; + dependencies[1].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + dependencies[1].dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; + dependencies[1].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + dependencies[1].dstAccessMask = VK_ACCESS_MEMORY_READ_BIT; + dependencies[1].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; + + // Renderpass + VkRenderPassCreateInfo renderPassCI = vks::initializers::renderPassCreateInfo(); + renderPassCI.attachmentCount = 1; + renderPassCI.pAttachments = &attDesc; + renderPassCI.subpassCount = 1; + renderPassCI.pSubpasses = &subpassDescription; + renderPassCI.dependencyCount = 2; + renderPassCI.pDependencies = dependencies.data(); + VkRenderPass renderpass; + VK_CHECK_RESULT(vkCreateRenderPass(device, &renderPassCI, nullptr, &renderpass)); + + struct { + VkImage image; + VkImageView view; + VkDeviceMemory memory; + VkFramebuffer framebuffer; + } offscreen; + //framebuffer + { + // Color attachment + VkImageCreateInfo imageCreateInfo = vks::initializers::imageCreateInfo(); + imageCreateInfo.imageType = VK_IMAGE_TYPE_2D; + imageCreateInfo.format = format; + imageCreateInfo.extent.width = dim; + imageCreateInfo.extent.height = dim; + imageCreateInfo.extent.depth = 1; + imageCreateInfo.mipLevels = 1; + imageCreateInfo.arrayLayers = 1; + imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT; + imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL; + imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + imageCreateInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT; + imageCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + VK_CHECK_RESULT(vkCreateImage(device, &imageCreateInfo, nullptr, &offscreen.image)); + + VkMemoryAllocateInfo memAlloc = vks::initializers::memoryAllocateInfo(); + VkMemoryRequirements memReqs; + vkGetImageMemoryRequirements(device, offscreen.image, &memReqs); + memAlloc.allocationSize = memReqs.size; + memAlloc.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &offscreen.memory)); + VK_CHECK_RESULT(vkBindImageMemory(device, offscreen.image, offscreen.memory, 0)); + + VkImageViewCreateInfo colorImageView = vks::initializers::imageViewCreateInfo(); + colorImageView.viewType = VK_IMAGE_VIEW_TYPE_2D; + colorImageView.format = format; + colorImageView.flags = 0; + colorImageView.subresourceRange = {}; + colorImageView.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + colorImageView.subresourceRange.baseMipLevel = 0; + colorImageView.subresourceRange.levelCount = 1; + colorImageView.subresourceRange.baseArrayLayer = 0; + colorImageView.subresourceRange.layerCount = 1; + colorImageView.image = offscreen.image; + VK_CHECK_RESULT(vkCreateImageView(device, &colorImageView, nullptr, &offscreen.view)); + + VkFramebufferCreateInfo fbufCreateInfo = vks::initializers::framebufferCreateInfo(); + fbufCreateInfo.renderPass = renderpass; + fbufCreateInfo.attachmentCount = 1; + fbufCreateInfo.pAttachments = &offscreen.view; + fbufCreateInfo.width = dim; + fbufCreateInfo.height = dim; + fbufCreateInfo.layers = 1; + VK_CHECK_RESULT(vkCreateFramebuffer(device, &fbufCreateInfo, nullptr, &offscreen.framebuffer)); + + VkCommandBuffer layoutCmd = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); + vks::tools::setImageLayout( + layoutCmd, + offscreen.image, + VK_IMAGE_ASPECT_COLOR_BIT, + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + vulkanDevice->flushCommandBuffer(layoutCmd, queue, true); + } + + // Descriptors + VkDescriptorSetLayout descriptorsetlayout; + std::vector setLayoutBindings = { + vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 0), + }; + VkDescriptorSetLayoutCreateInfo descriptorsetlayoutCI = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); + VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorsetlayoutCI, nullptr, &descriptorsetlayout)); + + // Descriptor Pool + std::vector poolSizes = { vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1) }; + VkDescriptorPoolCreateInfo descriptorPoolCI = vks::initializers::descriptorPoolCreateInfo(poolSizes, 2); + VkDescriptorPool descriptorpool; + VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolCI, nullptr, &descriptorpool)); + + VkDescriptorSet descriptorset; + VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorpool, &descriptorsetlayout, 1); + VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorset)); + VkWriteDescriptorSet writeDescriptorSet = vks::initializers::writeDescriptorSet(descriptorset, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 0, &ibltextures.skyboxCube.descriptor); + vkUpdateDescriptorSets(device, 1, &writeDescriptorSet, 0, nullptr); + + + std::vector pushConstantRanges = { + vks::initializers::pushConstantRange(VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, sizeof(PrefilterPushBlock), 0), + }; + VkPipelineLayoutCreateInfo pipelineLayoutCI = vks::initializers::pipelineLayoutCreateInfo(&descriptorsetlayout, 1); + pipelineLayoutCI.pushConstantRangeCount = 1; + pipelineLayoutCI.pPushConstantRanges = pushConstantRanges.data(); + VkPipelineLayout pipelinelayout; + VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCI, nullptr, &pipelinelayout)); + + VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); + VkPipelineRasterizationStateCreateInfo rasterizationState = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_NONE, VK_FRONT_FACE_COUNTER_CLOCKWISE); + VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); + VkPipelineColorBlendStateCreateInfo colorBlendState = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); + VkPipelineDepthStencilStateCreateInfo depthStencilState = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_FALSE, VK_FALSE, VK_COMPARE_OP_LESS_OR_EQUAL); + VkPipelineViewportStateCreateInfo viewportState = vks::initializers::pipelineViewportStateCreateInfo(1, 1); + VkPipelineMultisampleStateCreateInfo multisampleState = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT); + std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; + VkPipelineDynamicStateCreateInfo dynamicState = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); + std::array shaderStages; + + const std::vector vertexInputBindings = + { + vks::initializers::vertexInputBindingDescription(0, sizeof(VulkanglTFModel::Vertex), VK_VERTEX_INPUT_RATE_VERTEX), + }; + + const std::vector vertexInputAttributes = { + vks::initializers::vertexInputAttributeDescription(0, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(VulkanglTFModel::Vertex, pos)), // Location 0: Position + }; + VkPipelineVertexInputStateCreateInfo vertexInputStateCI = vks::initializers::pipelineVertexInputStateCreateInfo(); + vertexInputStateCI.vertexBindingDescriptionCount = static_cast(vertexInputBindings.size()); + vertexInputStateCI.pVertexBindingDescriptions = vertexInputBindings.data(); + vertexInputStateCI.vertexAttributeDescriptionCount = static_cast(vertexInputAttributes.size()); + vertexInputStateCI.pVertexAttributeDescriptions = vertexInputAttributes.data(); + + VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(pipelinelayout, renderpass); + pipelineCI.pInputAssemblyState = &inputAssemblyState; + pipelineCI.pRasterizationState = &rasterizationState; + pipelineCI.pColorBlendState = &colorBlendState; + pipelineCI.pMultisampleState = &multisampleState; + pipelineCI.pViewportState = &viewportState; + pipelineCI.pDepthStencilState = &depthStencilState; + pipelineCI.pDynamicState = &dynamicState; + pipelineCI.stageCount = 2; + pipelineCI.pStages = shaderStages.data(); + pipelineCI.renderPass = renderpass; + pipelineCI.pVertexInputState = &vertexInputStateCI; + + shaderStages[0] = loadShader(getHomeworkShadersPath() + "homework1/filtercube.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); + shaderStages[1] = loadShader(getHomeworkShadersPath() + "homework1/prefilterenvmap.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); + + VkPipeline pipeline; + VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipeline)); + + //Render & build cmd + VkClearValue clearValues[1]; + clearValues[0].color = { { 0.0f, 0.0f, 0.2f, 0.0f } }; + + VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); + // Reuse render pass from example pass + renderPassBeginInfo.renderPass = renderpass; + renderPassBeginInfo.framebuffer = offscreen.framebuffer; + renderPassBeginInfo.renderArea.extent.width = dim; + renderPassBeginInfo.renderArea.extent.height = dim; + renderPassBeginInfo.clearValueCount = 1; + renderPassBeginInfo.pClearValues = clearValues; + + std::vector matrices = { + // POSITIVE_X + glm::rotate(glm::rotate(glm::mat4(1.0f), glm::radians(90.0f), glm::vec3(0.0f, 1.0f, 0.0f)), glm::radians(180.0f), glm::vec3(1.0f, 0.0f, 0.0f)), + // NEGATIVE_X + glm::rotate(glm::rotate(glm::mat4(1.0f), glm::radians(-90.0f), glm::vec3(0.0f, 1.0f, 0.0f)), glm::radians(180.0f), glm::vec3(1.0f, 0.0f, 0.0f)), + // POSITIVE_Y + glm::rotate(glm::mat4(1.0f), glm::radians(-90.0f), glm::vec3(1.0f, 0.0f, 0.0f)), + // NEGATIVE_Y + glm::rotate(glm::mat4(1.0f), glm::radians(90.0f), glm::vec3(1.0f, 0.0f, 0.0f)), + // POSITIVE_Z + glm::rotate(glm::mat4(1.0f), glm::radians(180.0f), glm::vec3(1.0f, 0.0f, 0.0f)), + // NEGATIVE_Z + glm::rotate(glm::mat4(1.0f), glm::radians(180.0f), glm::vec3(0.0f, 0.0f, 1.0f)), + }; + VkCommandBuffer cmdBuf = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); + + VkViewport viewport = vks::initializers::viewport((float)dim, (float)dim, 0.0f, 1.0f); + VkRect2D scissor = vks::initializers::rect2D(dim, dim, 0, 0); + + vkCmdSetViewport(cmdBuf, 0, 1, &viewport); + vkCmdSetScissor(cmdBuf, 0, 1, &scissor); + + VkImageSubresourceRange subresourceRange = {}; + subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + subresourceRange.baseMipLevel = 0; + subresourceRange.levelCount = numMips; + subresourceRange.layerCount = 6; + + vks::tools::setImageLayout( + cmdBuf, + ibltextures.prefilteredCube.image, + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + subresourceRange); + + for (uint32_t m = 0; m < numMips; ++m) + { + //mip level according to roughness + prefilterPushBlock.roughness = float(m) / float(numMips - 1); + for (uint32_t f = 0; f < 6; ++f) + { + viewport.width = static_cast(dim * std::pow(0.5f, m)); + viewport.height = static_cast(dim * std::pow(0.5f, m)); + vkCmdSetViewport(cmdBuf, 0, 1, &viewport); + // Render scene from cube face's point of view + vkCmdBeginRenderPass(cmdBuf, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); + + // Update shader push constant block + prefilterPushBlock.mvp = glm::perspective((float)(M_PI / 2.0), 1.0f, 0.1f, 512.0f) * matrices[f]; + + vkCmdPushConstants(cmdBuf, pipelinelayout, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(PrefilterPushBlock), &prefilterPushBlock); + vkCmdBindPipeline(cmdBuf, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); + vkCmdBindDescriptorSets(cmdBuf, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelinelayout, 0, 1, &descriptorset, 0, nullptr); + skyboxModel.draw(cmdBuf, pipelinelayout); + vkCmdEndRenderPass(cmdBuf); + + vks::tools::setImageLayout( + cmdBuf, + offscreen.image, + VK_IMAGE_ASPECT_COLOR_BIT, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); + + VkImageCopy copyRegion{}; + copyRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + copyRegion.srcSubresource.baseArrayLayer = 0; + copyRegion.srcSubresource.mipLevel = 0; + copyRegion.srcSubresource.layerCount = 1; + copyRegion.srcOffset = { 0, 0, 0 }; + + copyRegion.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + copyRegion.dstSubresource.baseArrayLayer = f; + copyRegion.dstSubresource.mipLevel = m; + copyRegion.dstSubresource.layerCount = 1; + copyRegion.dstOffset = { 0, 0, 0 }; + + copyRegion.extent.width = static_cast(viewport.width); + copyRegion.extent.height = static_cast(viewport.height); + copyRegion.extent.depth = 1; + + vkCmdCopyImage( + cmdBuf, + offscreen.image, + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + ibltextures.prefilteredCube.image, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + 1, + ©Region); + + //Reset frame buffer image layout + vks::tools::setImageLayout( + cmdBuf, + offscreen.image, + VK_IMAGE_ASPECT_COLOR_BIT, + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + } + } + + //Set format shader read + vks::tools::setImageLayout( + cmdBuf, + ibltextures.prefilteredCube.image, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + subresourceRange); + + vulkanDevice->flushCommandBuffer(cmdBuf, queue); + + vkDestroyRenderPass(device, renderpass, nullptr); + vkDestroyFramebuffer(device, offscreen.framebuffer, nullptr); + vkFreeMemory(device, offscreen.memory, nullptr); + vkDestroyImageView(device, offscreen.view, nullptr); + vkDestroyImage(device, offscreen.image, nullptr); + vkDestroyDescriptorPool(device, descriptorpool, nullptr); + vkDestroyDescriptorSetLayout(device, descriptorsetlayout, nullptr); + vkDestroyPipeline(device, pipeline, nullptr); + vkDestroyPipelineLayout(device, pipelinelayout, nullptr); + + auto tEnd = std::chrono::high_resolution_clock::now(); + auto tDiff = std::chrono::duration(tEnd - tStart).count(); + std::cout << "Generating pre-filtered enivornment cube with " << numMips << " mip levels took " << tDiff << " ms" << std::endl; + } + + void VulkanExample::generateBRDFLUT() + { + auto tStart = std::chrono::high_resolution_clock::now(); + + constexpr VkFormat format = VK_FORMAT_R16G16_SFLOAT; + constexpr int32_t dim = 512; + + // Image + VkImageCreateInfo imageCI = vks::initializers::imageCreateInfo(); + imageCI.imageType = VK_IMAGE_TYPE_2D; + imageCI.format = format; + imageCI.extent.width = dim; + imageCI.extent.height = dim; + imageCI.extent.depth = 1; + imageCI.mipLevels = 1; + imageCI.arrayLayers = 1; + imageCI.samples = VK_SAMPLE_COUNT_1_BIT; + imageCI.tiling = VK_IMAGE_TILING_OPTIMAL; + imageCI.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; + VK_CHECK_RESULT(vkCreateImage(device, &imageCI, nullptr, &ibltextures.lutBrdf.image)); + VkMemoryAllocateInfo memAlloc = vks::initializers::memoryAllocateInfo(); + VkMemoryRequirements memReqs; + vkGetImageMemoryRequirements(device, ibltextures.lutBrdf.image, &memReqs); + memAlloc.allocationSize = memReqs.size; + memAlloc.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &ibltextures.lutBrdf.deviceMemory)); + VK_CHECK_RESULT(vkBindImageMemory(device, ibltextures.lutBrdf.image, ibltextures.lutBrdf.deviceMemory, 0)); + + // Image view + VkImageViewCreateInfo viewCI = vks::initializers::imageViewCreateInfo(); + viewCI.viewType = VK_IMAGE_VIEW_TYPE_2D; + viewCI.format = format; + viewCI.subresourceRange = {}; + viewCI.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + viewCI.subresourceRange.levelCount = 1; + viewCI.subresourceRange.layerCount = 1; + viewCI.image = ibltextures.lutBrdf.image; + VK_CHECK_RESULT(vkCreateImageView(device, &viewCI, nullptr, &ibltextures.lutBrdf.view)); + + // Sampler + VkSamplerCreateInfo samplerCI = vks::initializers::samplerCreateInfo(); + samplerCI.magFilter = VK_FILTER_LINEAR; + samplerCI.minFilter = VK_FILTER_LINEAR; + samplerCI.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; + samplerCI.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + samplerCI.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + samplerCI.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + samplerCI.minLod = 0.0f; + samplerCI.maxLod = 1.0f; + samplerCI.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE; + VK_CHECK_RESULT(vkCreateSampler(device, &samplerCI, nullptr, &ibltextures.lutBrdf.sampler)); + + ibltextures.lutBrdf.descriptor.imageView = ibltextures.lutBrdf.view; + ibltextures.lutBrdf.descriptor.sampler = ibltextures.lutBrdf.sampler; + ibltextures.lutBrdf.descriptor.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + ibltextures.lutBrdf.device = vulkanDevice; + + // FB, Att, RP, Pipe, etc. + VkAttachmentDescription attDesc = {}; + // Color attachment + attDesc.format = format; + attDesc.samples = VK_SAMPLE_COUNT_1_BIT; + attDesc.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; + attDesc.storeOp = VK_ATTACHMENT_STORE_OP_STORE; + attDesc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + attDesc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + attDesc.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + attDesc.finalLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + VkAttachmentReference colorReference = { 0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL }; + + VkSubpassDescription subpassDescription = {}; + subpassDescription.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; + subpassDescription.colorAttachmentCount = 1; + subpassDescription.pColorAttachments = &colorReference; + + // Use subpass dependencies for layout transitions + std::array dependencies; + dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL; + dependencies[0].dstSubpass = 0; + dependencies[0].srcStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; + dependencies[0].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + dependencies[0].srcAccessMask = VK_ACCESS_MEMORY_READ_BIT; + dependencies[0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + dependencies[0].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; + dependencies[1].srcSubpass = 0; + dependencies[1].dstSubpass = VK_SUBPASS_EXTERNAL; + dependencies[1].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + dependencies[1].dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; + dependencies[1].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + dependencies[1].dstAccessMask = VK_ACCESS_MEMORY_READ_BIT; + dependencies[1].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; + + // Create the actual renderpass + VkRenderPassCreateInfo renderPassCI = vks::initializers::renderPassCreateInfo(); + renderPassCI.attachmentCount = 1; + renderPassCI.pAttachments = &attDesc; + renderPassCI.subpassCount = 1; + renderPassCI.pSubpasses = &subpassDescription; + renderPassCI.dependencyCount = 2; + renderPassCI.pDependencies = dependencies.data(); + + VkRenderPass renderpass; + VK_CHECK_RESULT(vkCreateRenderPass(device, &renderPassCI, nullptr, &renderpass)); + + VkFramebufferCreateInfo framebufferCI = vks::initializers::framebufferCreateInfo(); + framebufferCI.renderPass = renderpass; + framebufferCI.attachmentCount = 1; + framebufferCI.pAttachments = &ibltextures.lutBrdf.view; + framebufferCI.width = dim; + framebufferCI.height = dim; + framebufferCI.layers = 1; + + VkFramebuffer framebuffer; + VK_CHECK_RESULT(vkCreateFramebuffer(device, &framebufferCI, nullptr, &framebuffer)); + + // Descriptors + VkDescriptorSetLayout descriptorsetlayout; + std::vector setLayoutBindings = {}; + VkDescriptorSetLayoutCreateInfo descriptorsetlayoutCI = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); + VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorsetlayoutCI, nullptr, &descriptorsetlayout)); + + // Descriptor Pool + std::vector poolSizes = { vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1) }; + VkDescriptorPoolCreateInfo descriptorPoolCI = vks::initializers::descriptorPoolCreateInfo(poolSizes, 2); + VkDescriptorPool descriptorpool; + VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolCI, nullptr, &descriptorpool)); + + // Descriptor sets + VkDescriptorSet descriptorset; + VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorpool, &descriptorsetlayout, 1); + VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorset)); + + // Pipeline layout + VkPipelineLayout pipelinelayout; + VkPipelineLayoutCreateInfo pipelineLayoutCI = vks::initializers::pipelineLayoutCreateInfo(&descriptorsetlayout, 1); + VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCI, nullptr, &pipelinelayout)); + + // Pipeline + VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); + VkPipelineRasterizationStateCreateInfo rasterizationState = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_NONE, VK_FRONT_FACE_COUNTER_CLOCKWISE); + VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); + VkPipelineColorBlendStateCreateInfo colorBlendState = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); + VkPipelineDepthStencilStateCreateInfo depthStencilState = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_FALSE, VK_FALSE, VK_COMPARE_OP_LESS_OR_EQUAL); + VkPipelineViewportStateCreateInfo viewportState = vks::initializers::pipelineViewportStateCreateInfo(1, 1); + VkPipelineMultisampleStateCreateInfo multisampleState = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT); + std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; + VkPipelineDynamicStateCreateInfo dynamicState = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); + VkPipelineVertexInputStateCreateInfo emptyInputState = vks::initializers::pipelineVertexInputStateCreateInfo(); + std::array shaderStages; + + VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(pipelinelayout, renderpass); + pipelineCI.pInputAssemblyState = &inputAssemblyState; + pipelineCI.pRasterizationState = &rasterizationState; + pipelineCI.pColorBlendState = &colorBlendState; + pipelineCI.pMultisampleState = &multisampleState; + pipelineCI.pViewportState = &viewportState; + pipelineCI.pDepthStencilState = &depthStencilState; + pipelineCI.pDynamicState = &dynamicState; + pipelineCI.stageCount = 2; + pipelineCI.pStages = shaderStages.data(); + pipelineCI.pVertexInputState = &emptyInputState; + + // Look-up-table (from BRDF) pipeline + shaderStages[0] = loadShader(getHomeworkShadersPath() + "homework1/genbrdflut.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); + shaderStages[1] = loadShader(getHomeworkShadersPath() + "homework1/genbrdflut.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); + VkPipeline pipeline; + VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipeline)); + + // Render + VkClearValue clearValues[1]; + clearValues[0].color = { { 0.0f, 0.0f, 0.0f, 1.0f } }; + + VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); + renderPassBeginInfo.renderPass = renderpass; + renderPassBeginInfo.renderArea.extent.width = dim; + renderPassBeginInfo.renderArea.extent.height = dim; + renderPassBeginInfo.clearValueCount = 1; + renderPassBeginInfo.pClearValues = clearValues; + renderPassBeginInfo.framebuffer = framebuffer; + + VkCommandBuffer cmdBuf = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); + vkCmdBeginRenderPass(cmdBuf, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); + VkViewport viewport = vks::initializers::viewport((float)dim, (float)dim, 0.0f, 1.0f); + VkRect2D scissor = vks::initializers::rect2D(dim, dim, 0, 0); + vkCmdSetViewport(cmdBuf, 0, 1, &viewport); + vkCmdSetScissor(cmdBuf, 0, 1, &scissor); + vkCmdBindPipeline(cmdBuf, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); + vkCmdDraw(cmdBuf, 3, 1, 0, 0); + vkCmdEndRenderPass(cmdBuf); + vulkanDevice->flushCommandBuffer(cmdBuf, queue); + + vkQueueWaitIdle(queue); + + vkDestroyPipeline(device, pipeline, nullptr); + vkDestroyPipelineLayout(device, pipelinelayout, nullptr); + vkDestroyRenderPass(device, renderpass, nullptr); + vkDestroyFramebuffer(device, framebuffer, nullptr); + vkDestroyDescriptorSetLayout(device, descriptorsetlayout, nullptr); + vkDestroyDescriptorPool(device, descriptorpool, nullptr); + + auto tEnd = std::chrono::high_resolution_clock::now(); + auto tDiff = std::chrono::duration(tEnd - tStart).count(); + std::cout << "Generating BRDF LUT took " << tDiff << " ms" << std::endl; +} + +//-------------------------- pbr precompute start ---------------------------------- #pragma region pbr render pass setting @@ -1326,6 +2272,9 @@ void VulkanExample::getEnabledFeatures() { VulkanExampleBase::prepare(); loadAssets(); + generateBRDFLUT(); + generateIrradianceCubemap(); + generatePrefilteredCubemap(); prepareUniformBuffers(); setupDescriptors(); preparePipelines(); diff --git a/homework/homework1/homework1.h b/homework/homework1/homework1.h index 5b6bcf3..5b39c45 100644 --- a/homework/homework1/homework1.h +++ b/homework/homework1/homework1.h @@ -249,6 +249,11 @@ public: vks::Buffer skinSSBO; } shaderData; + struct StagingBuffer { + VkBuffer buffer; + VkDeviceMemory memory; + } vertexStaging, indexStaging; + struct Pipelines { VkPipeline solid; VkPipeline wireframe = VK_NULL_HANDLE; @@ -325,6 +330,28 @@ public: vks::Texture2D lutBrdf; } ibltextures; + struct OffScreen + { + VkImage image; + VkImageView view; + VkDeviceMemory memory; + VkFramebuffer framebuffer; + } offscreen; + + struct IrradiancePushBlock + { + glm::mat4 mvp; + // Sampling deltas + float deltaPhi = (2.0f * float(M_PI)) / 180.0f; + float deltaTheta = (0.5f * float(M_PI)) / 64.0f; + } irradinacePushBlock; + + struct PrefilterPushBlock { + glm::mat4 mvp; + float roughness; + uint32_t numSamples = 32u; + } prefilterPushBlock; + VulkanglTFModel skyboxModel; VulkanExample(); @@ -356,7 +383,7 @@ public: shaderData.buffer.destroy(); shaderData.skinSSBO.destroy(); } - void loadglTFFile(std::string filename); + void loadglTFFile(std::string filename, VulkanglTFModel& model, bool bSkyboxFlag = false); virtual void getEnabledFeatures(); void createAttachment(VkFormat format, VkImageUsageFlagBits usage, FrameBufferAttachment* attachment, uint32_t width, uint32_t height); virtual void setupFrameBuffer(); @@ -365,6 +392,9 @@ public: void setupDescriptors(); void preparePipelines(); void prepareToneMappingPipeline(); + void generateIrradianceCubemap(); + void generatePrefilteredCubemap(); + void generateBRDFLUT(); void prepareUniformBuffers(); void updateUniformBuffers(); void prepare(); From 11610c6a6b34b967f69d4f14da2e4b9c83c86671 Mon Sep 17 00:00:00 2001 From: ink-soul Date: Wed, 24 May 2023 17:07:38 +0800 Subject: [PATCH 16/22] Update homework1.cpp --- homework/homework1/homework1.cpp | 43 ++++++++++++++++---------------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/homework/homework1/homework1.cpp b/homework/homework1/homework1.cpp index 4b498c1..44be147 100644 --- a/homework/homework1/homework1.cpp +++ b/homework/homework1/homework1.cpp @@ -838,11 +838,6 @@ void VulkanExample::getEnabledFeatures() this->device = device; -#if defined(__ANDROID__) - // On Android all assets are packed with the apk in a compressed form, so we need to open them using the asset manager - // We let tinygltf handle this, by passing the asset manager of our app - tinygltf::asset_manager = androidApp->activity->assetManager; -#endif bool fileLoaded = gltfContext.LoadASCIIFromFile(&glTFInput, &error, &warning, filename); // Pass some Vulkan resources required for setup and rendering to the glTF model loading class @@ -858,7 +853,7 @@ void VulkanExample::getEnabledFeatures() glTFModel.loadImages(glTFInput); glTFModel.loadMaterials(glTFInput); glTFModel.loadTextures(glTFInput); - glTFModel.loadSkins(glTFInput); + //glTFModel.loadSkins(glTFInput); const tinygltf::Scene& scene = glTFInput.scenes[0]; for (size_t i = 0; i < scene.nodes.size(); i++) { const tinygltf::Node node = glTFInput.nodes[scene.nodes[i]]; @@ -873,7 +868,7 @@ void VulkanExample::getEnabledFeatures() { glTFModel.updateJoints(node); - }*/ + } for (size_t i = 0; i < glTFModel.nodes.size(); i++) { @@ -885,7 +880,7 @@ void VulkanExample::getEnabledFeatures() { continue; } - } + }*/ } else { vks::tools::exitFatal("Could not open the glTF file.\n\nThe file is part of the additional asset pack.\n\nRun \"download_assets.py\" in the repository root to download the latest version.", -1); @@ -969,6 +964,7 @@ void VulkanExample::getEnabledFeatures() loadglTFFile(getAssetPath() + "buster_drone/busterDrone.gltf",glTFModel); loadglTFFile(getAssetPath() + "models/cube.gltf", skyboxModel, true); ibltextures.skyboxCube.loadFromFile(getAssetPath() + "textures/hdr/pisa_cube.ktx", VK_FORMAT_R16G16B16A16_SFLOAT, vulkanDevice, queue); + } void VulkanExample::setupDescriptors() @@ -982,15 +978,16 @@ void VulkanExample::getEnabledFeatures() // One combined image sampler per material image/texture vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, static_cast(glTFModel.images.size())), // One ssbo per skin - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, static_cast(glTFModel.skins.size())), + //vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, static_cast(glTFModel.skins.size())), // sampler descriptor vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,4), //animation storage buffer vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,1) }; + const uint32_t maxSetCount = static_cast(glTFModel.images.size()) + 6; // Number of descriptor sets = One for the scene ubo + one per image + one per skin - const uint32_t maxSetCount = static_cast(glTFModel.images.size()) + static_cast(glTFModel.skins.size()) + 1; + //const uint32_t maxSetCount = static_cast(glTFModel.images.size()) + static_cast(glTFModel.skins.size()) + 1+ 6 ; VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, maxSetCount); VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); @@ -1018,16 +1015,16 @@ void VulkanExample::getEnabledFeatures() VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorSetLayoutCI, nullptr, &descriptorSetLayouts.ssbo)); // Descriptor set layout for passing skin joint matrices - setLayoutBinding = vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorSetLayoutCI, nullptr, &descriptorSetLayouts.jointMatrices)); + //setLayoutBinding = vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0); + //VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorSetLayoutCI, nullptr, &descriptorSetLayouts.jointMatrices)); // The pipeline layout uses three sets: // Set 0 = Scene matrices (VS) // Set 1 = Joint matrices (VS) // Set 2 = Material texture (FS) - std::array setLayouts = { + std::array setLayouts = { descriptorSetLayouts.matrices, - descriptorSetLayouts.jointMatrices, + //descriptorSetLayouts.jointMatrices, descriptorSetLayouts.textures, descriptorSetLayouts.textures, descriptorSetLayouts.textures, @@ -1127,14 +1124,14 @@ void VulkanExample::getEnabledFeatures() vks::initializers::vertexInputBindingDescription(0, sizeof(VulkanglTFModel::Vertex), VK_VERTEX_INPUT_RATE_VERTEX), }; const std::vector vertexInputAttributes = { - {0, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(VulkanglTFModel::Vertex, pos)}, - {1, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(VulkanglTFModel::Vertex, normal)}, - {2, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(VulkanglTFModel::Vertex, uv)}, - {3, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(VulkanglTFModel::Vertex, color)}, - {4, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(VulkanglTFModel::Vertex, tangent)}, + vks::initializers::vertexInputAttributeDescription(0, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(VulkanglTFModel::Vertex, pos)), // Location 0: Position + vks::initializers::vertexInputAttributeDescription(0, 1, VK_FORMAT_R32G32B32_SFLOAT, offsetof(VulkanglTFModel::Vertex, normal)),// Location 1: Normal + vks::initializers::vertexInputAttributeDescription(0, 2, VK_FORMAT_R32G32B32_SFLOAT, offsetof(VulkanglTFModel::Vertex, uv)), // Location 2: Texture coordinates + vks::initializers::vertexInputAttributeDescription(0, 3, VK_FORMAT_R32G32B32_SFLOAT, offsetof(VulkanglTFModel::Vertex, color)), // Location 3: Color + vks::initializers::vertexInputAttributeDescription(0, 4, VK_FORMAT_R32G32B32_SFLOAT, offsetof(VulkanglTFModel::Vertex, tangent)), // Location 4 : Tangent // POI: Per-Vertex Joint indices and weights are passed to the vertex shader - {5, 0, VK_FORMAT_R32G32B32A32_SFLOAT, offsetof(VulkanglTFModel::Vertex, jointIndices)}, - {6, 0, VK_FORMAT_R32G32B32A32_SFLOAT, offsetof(VulkanglTFModel::Vertex, jointWeights)}, + //{5, 0, VK_FORMAT_R32G32B32A32_SFLOAT, offsetof(VulkanglTFModel::Vertex, jointIndices)}, + //{6, 0, VK_FORMAT_R32G32B32A32_SFLOAT, offsetof(VulkanglTFModel::Vertex, jointWeights)}, }; VkPipelineVertexInputStateCreateInfo vertexInputStateCI = vks::initializers::pipelineVertexInputStateCreateInfo(); vertexInputStateCI.vertexBindingDescriptionCount = static_cast(vertexInputBindings.size()); @@ -1147,7 +1144,7 @@ void VulkanExample::getEnabledFeatures() loadShader(getHomeworkShadersPath() + "homework1/mesh.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT) }; - VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(pipelineLayout, renderPass, 0); + VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(pipelineLayouts.pbrLayout, pbrFrameBuffer.fbo.renderPass, 0); pipelineCI.pVertexInputState = &vertexInputStateCI; pipelineCI.pInputAssemblyState = &inputAssemblyStateCI; pipelineCI.pRasterizationState = &rasterizationStateCI; @@ -1168,7 +1165,9 @@ void VulkanExample::getEnabledFeatures() rasterizationStateCI.lineWidth = 1.0f; VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.wireframe)); } + prepareToneMappingPipeline(); } + void VulkanExample::prepareToneMappingPipeline() { if (pipelines.toneMapping != VK_NULL_HANDLE) From 7d36d173f60f44af580c5686dfe47a35915d92ab Mon Sep 17 00:00:00 2001 From: InkSoul Date: Thu, 25 May 2023 00:29:04 +0800 Subject: [PATCH 17/22] bug fix : pbrLayout is null bug found : piplines is null --- homework/homework1/homework1.cpp | 168 ++++++++++++++----------------- 1 file changed, 76 insertions(+), 92 deletions(-) diff --git a/homework/homework1/homework1.cpp b/homework/homework1/homework1.cpp index 44be147..5282594 100644 --- a/homework/homework1/homework1.cpp +++ b/homework/homework1/homework1.cpp @@ -199,7 +199,7 @@ } - + /* // load skins from glTF model void VulkanglTFModel::loadSkins(tinygltf::Model& input) { @@ -249,8 +249,8 @@ - } - + }*/ + //glTF nodes loading helper function //rewrite node loader,simplify logic //Search node from parent to children by index @@ -634,7 +634,7 @@ } // Draw the glTF scene starting at the top-level-nodes - void VulkanglTFModel::draw(VkCommandBuffer commandBuffer, VkPipelineLayout pipelineLayout) + void VulkanglTFModel::draw(VkCommandBuffer commandBuffer, VkPipelineLayout pipelineLayout ) { // All vertices and indices are stored in single buffers, so we only need to bind once VkDeviceSize offsets[1] = { 0 }; @@ -755,7 +755,7 @@ void VulkanExample::setupFrameBuffer() samplerCI.minLod = 0.0f; samplerCI.maxLod = 1.0f; samplerCI.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE; - + VK_CHECK_RESULT(vkCreateSampler(device, &samplerCI, nullptr, &colorSampler)); if (tonemappingDescriptorSet != VK_NULL_HANDLE) { auto imageInfo = vks::initializers::descriptorImageInfo(colorSampler, pbrFrameBuffer.color.imageView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); @@ -780,11 +780,11 @@ void VulkanExample::getEnabledFeatures() VkClearValue clearValues[2]; clearValues[0].color = defaultClearColor; - clearValues[0].color = { { 0.25f, 0.25f, 0.25f, 1.0f } };; + clearValues[0].color = { { 0.25f, 0.25f, 0.25f, 1.0f } }; clearValues[1].depthStencil = { 1.0f, 0 }; VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = renderPass; + renderPassBeginInfo.renderPass = pbrFrameBuffer.fbo.renderPass; renderPassBeginInfo.renderArea.offset.x = 0; renderPassBeginInfo.renderArea.offset.y = 0; renderPassBeginInfo.renderArea.extent.width = width; @@ -797,40 +797,41 @@ void VulkanExample::getEnabledFeatures() for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) { - renderPassBeginInfo.framebuffer = frameBuffers[i]; + renderPassBeginInfo.framebuffer = pbrFrameBuffer.fbo.frameBuffer; VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); // Bind scene matrices descriptor to set 0 - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, nullptr); + vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayouts.pbrLayout, 0, 1, &descriptorSet, 0, nullptr); + vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayouts.pbrLayout, 6, 1, &skinDescriptorSet, 0, nullptr); vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, wireframe ? pipelines.wireframe : pipelines.solid); - glTFModel.draw(drawCmdBuffers[i], pipelineLayout); - drawUI(drawCmdBuffers[i]); + glTFModel.draw(drawCmdBuffers[i], pipelineLayouts.pbrLayout); vkCmdEndRenderPass(drawCmdBuffers[i]); + + { + VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); + renderPassBeginInfo.renderPass = renderPass; + renderPassBeginInfo.framebuffer = VulkanExampleBase::frameBuffers[i]; + renderPassBeginInfo.renderArea.extent.width = width; + renderPassBeginInfo.renderArea.extent.height = height; + renderPassBeginInfo.clearValueCount = 2; + renderPassBeginInfo.pClearValues = clearValues; + + vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); + vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); + vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); + vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayouts.tonemappingLayout, 0, 1, &tonemappingDescriptorSet, 0, NULL); + vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.toneMapping); + vkCmdDraw(drawCmdBuffers[i], 3, 1, 0, 0); + drawUI(drawCmdBuffers[i]); + vkCmdEndRenderPass(drawCmdBuffers[i]); + } VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); - - //tonemapping render pass - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = renderPass; - renderPassBeginInfo.framebuffer = VulkanExampleBase::frameBuffers[i]; - renderPassBeginInfo.renderArea.extent.width = width; - renderPassBeginInfo.renderArea.extent.height = height; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - - vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayouts.tonemappingLayout, 0, 1, &tonemappingDescriptorSet, 0, NULL); - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.toneMapping); - vkCmdDraw(drawCmdBuffers[i], 3, 1, 0, 0); - drawUI(drawCmdBuffers[i]); - vkCmdEndRenderPass(drawCmdBuffers[i]); } } - void VulkanExample::loadglTFFile(std::string filename, VulkanglTFModel& model, bool bSkyboxFlag = false) + void VulkanExample::loadglTFFile(std::string filename, VulkanglTFModel& model, bool bSkyboxFlag) { tinygltf::Model glTFInput; tinygltf::TinyGLTF gltfContext; @@ -838,49 +839,31 @@ void VulkanExample::getEnabledFeatures() this->device = device; +#if defined(__ANDROID__) + // On Android all assets are packed with the apk in a compressed form, so we need to open them using the asset manager + // We let tinygltf handle this, by passing the asset manager of our app + tinygltf::asset_manager = androidApp->activity->assetManager; +#endif bool fileLoaded = gltfContext.LoadASCIIFromFile(&glTFInput, &error, &warning, filename); // Pass some Vulkan resources required for setup and rendering to the glTF model loading class - glTFModel.vulkanDevice = vulkanDevice; - glTFModel.copyQueue = queue; + model.vulkanDevice = vulkanDevice; + model.copyQueue = queue; std::vector indexBuffer; std::vector vertexBuffer; - if (fileLoaded) - { - glTFModel.nodeCount = static_cast(glTFInput.nodes.size()); - glTFModel.loadImages(glTFInput); - glTFModel.loadMaterials(glTFInput); - glTFModel.loadTextures(glTFInput); - //glTFModel.loadSkins(glTFInput); + if (fileLoaded) { + model.nodeCount = static_cast(glTFInput.nodes.size()); + model.loadImages(glTFInput); + model.loadMaterials(glTFInput); + model.loadTextures(glTFInput); const tinygltf::Scene& scene = glTFInput.scenes[0]; for (size_t i = 0; i < scene.nodes.size(); i++) { const tinygltf::Node node = glTFInput.nodes[scene.nodes[i]]; - glTFModel.loadNode(node, glTFInput, nullptr,scene.nodes[i], indexBuffer, vertexBuffer); + model.loadNode(node, glTFInput, nullptr, scene.nodes[i], indexBuffer, vertexBuffer); } - - glTFModel.loadAnimations(glTFInput); - // update joint in nodes - /* - - for (auto node : glTFModel.nodes) - { - - glTFModel.updateJoints(node); - } - - for (size_t i = 0; i < glTFModel.nodes.size(); i++) - { - if (glTFModel.nodes[i]->skin > -1) - { - glTFModel.updateJoints(glTFModel.nodes[i]); - } - else - { - continue; - } - }*/ + model.loadAnimations(glTFInput); } else { vks::tools::exitFatal("Could not open the glTF file.\n\nThe file is part of the additional asset pack.\n\nRun \"download_assets.py\" in the repository root to download the latest version.", -1); @@ -893,9 +876,12 @@ void VulkanExample::getEnabledFeatures() size_t vertexBufferSize = vertexBuffer.size() * sizeof(VulkanglTFModel::Vertex); size_t indexBufferSize = indexBuffer.size() * sizeof(uint32_t); - glTFModel.indices.count = static_cast(indexBuffer.size()); + model.indices.count = static_cast(indexBuffer.size()); - + struct StagingBuffer { + VkBuffer buffer; + VkDeviceMemory memory; + } vertexStaging, indexStaging; // Create host visible staging buffers (source) VK_CHECK_RESULT(vulkanDevice->createBuffer( @@ -919,15 +905,14 @@ void VulkanExample::getEnabledFeatures() VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, vertexBufferSize, - &glTFModel.vertices.buffer, - &glTFModel.vertices.memory)); - + &model.vertices.buffer, + &model.vertices.memory)); VK_CHECK_RESULT(vulkanDevice->createBuffer( VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, indexBufferSize, - &glTFModel.indices.buffer, - &glTFModel.indices.memory)); + &model.indices.buffer, + &model.indices.memory)); // Copy data from staging buffers (host) do device local buffer (gpu) VkCommandBuffer copyCmd = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); @@ -937,16 +922,15 @@ void VulkanExample::getEnabledFeatures() vkCmdCopyBuffer( copyCmd, vertexStaging.buffer, - glTFModel.vertices.buffer, + model.vertices.buffer, 1, ©Region); copyRegion.size = indexBufferSize; - vkCmdCopyBuffer( copyCmd, indexStaging.buffer, - glTFModel.indices.buffer, + model.indices.buffer, 1, ©Region); @@ -985,9 +969,8 @@ void VulkanExample::getEnabledFeatures() vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,1) }; - const uint32_t maxSetCount = static_cast(glTFModel.images.size()) + 6; - // Number of descriptor sets = One for the scene ubo + one per image + one per skin - //const uint32_t maxSetCount = static_cast(glTFModel.images.size()) + static_cast(glTFModel.skins.size()) + 1+ 6 ; + // One set for matrices and one per model image/texture + const uint32_t maxSetCount = static_cast(glTFModel.images.size()) + 6; VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, maxSetCount); VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); @@ -1000,17 +983,17 @@ void VulkanExample::getEnabledFeatures() vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 3), }; VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCI = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - // Descriptor set layout for passing matrices VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorSetLayoutCI, nullptr, &descriptorSetLayouts.matrices)); - // Descriptor set layout for material uniform buffer + VkDescriptorSetLayoutBinding materialBufferLayoutBinding = vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT, 0); descriptorSetLayoutCI = vks::initializers::descriptorSetLayoutCreateInfo(&materialBufferLayoutBinding, 1); VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorSetLayoutCI, nullptr, &descriptorSetLayouts.materialUniform)); + // Descriptor set layout for passing material textures VkDescriptorSetLayoutBinding setLayoutBinding = vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 0); descriptorSetLayoutCI = vks::initializers::descriptorSetLayoutCreateInfo(&setLayoutBinding, 1); VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorSetLayoutCI, nullptr, &descriptorSetLayouts.textures)); - // Descriptor set layout for ssbo + setLayoutBinding = vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0); VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorSetLayoutCI, nullptr, &descriptorSetLayouts.ssbo)); // Descriptor set layout for passing skin joint matrices @@ -1033,7 +1016,7 @@ void VulkanExample::getEnabledFeatures() descriptorSetLayouts.ssbo, }; VkPipelineLayoutCreateInfo pipelineLayoutCI = vks::initializers::pipelineLayoutCreateInfo(setLayouts.data(), static_cast(setLayouts.size())); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCI, nullptr, &pipelineLayout)); + VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCI, nullptr, &pipelineLayouts.pbrLayout)); /* // We will use push constants to push the local matrices of a primitive to the vertex shader @@ -1057,7 +1040,8 @@ void VulkanExample::getEnabledFeatures() vkUpdateDescriptorSets(device, 4, writeDescriptorSets.data(), 0, nullptr); // Descriptor set for glTF model skin joint matrices - if (glTFModel.skins.size() > 0) + /* + if (glTFModel.skins.size() > 0) { for (auto& skin : glTFModel.skins) { @@ -1068,13 +1052,7 @@ void VulkanExample::getEnabledFeatures() } } else - { - const VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayouts.ssbo, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &skinDescriptorSet)); - VkWriteDescriptorSet writeDescriptorSet = vks::initializers::writeDescriptorSet(skinDescriptorSet, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 0, &shaderData.skinSSBO.descriptor); - vkUpdateDescriptorSets(device, 1, &writeDescriptorSet, 0, nullptr); - } - + */ for (auto& material : glTFModel.materials) { @@ -1092,16 +1070,22 @@ void VulkanExample::getEnabledFeatures() VkWriteDescriptorSet writeDescriptorSet = vks::initializers::writeDescriptorSet(image.descriptorSet, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 0, &image.texture.descriptor); vkUpdateDescriptorSets(device, 1, &writeDescriptorSet, 0, nullptr); } - - //tonemapping pipline layout { - VkPipelineLayoutCreateInfo piplineLayoutCI = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayouts.textures, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &piplineLayoutCI, nullptr, &pipelineLayouts.tonemappingLayout)); + const VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayouts.ssbo, 1); + VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &skinDescriptorSet)); + VkWriteDescriptorSet writeDescriptorSet = vks::initializers::writeDescriptorSet(skinDescriptorSet, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 0, &shaderData.skinSSBO.descriptor); + vkUpdateDescriptorSets(device, 1, &writeDescriptorSet, 0, nullptr); + } + + //Tone Mapping pipeline layout + { + auto pipelineLayoutCI = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayouts.textures, 1); + VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCI, nullptr, &pipelineLayouts.tonemappingLayout)); const VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayouts.textures, 1); VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &tonemappingDescriptorSet)); - VkDescriptorImageInfo imageInfo = vks::initializers::descriptorImageInfo(colorSampler, pbrFrameBuffer.color.imageView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + auto imageInfo = vks::initializers::descriptorImageInfo(colorSampler, pbrFrameBuffer.color.imageView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); VkWriteDescriptorSet writeDescriptorSet = vks::initializers::writeDescriptorSet(tonemappingDescriptorSet, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 0, &imageInfo); vkUpdateDescriptorSets(device, 1, &writeDescriptorSet, 0, nullptr); } From 054599f6b0f59358421bd3e10b85ca409e7f7769 Mon Sep 17 00:00:00 2001 From: ink-soul Date: Thu, 25 May 2023 11:38:10 +0800 Subject: [PATCH 18/22] Update homework1.cpp --- homework/homework1/homework1.cpp | 263 +++++++++++-------------------- 1 file changed, 93 insertions(+), 170 deletions(-) diff --git a/homework/homework1/homework1.cpp b/homework/homework1/homework1.cpp index 5282594..5cfd033 100644 --- a/homework/homework1/homework1.cpp +++ b/homework/homework1/homework1.cpp @@ -30,8 +30,6 @@ void VulkanglTFModel::loadImages(tinygltf::Model& input) { - // Images can be stored inside the glTF (which is the case for the sample model), so instead of directly - // loading them from disk, we fetch them from the glTF loader and upload the buffers images.resize(input.images.size()); for (size_t i = 0; i < input.images.size(); i++) { tinygltf::Image& glTFImage = input.images[i]; @@ -290,179 +288,138 @@ void VulkanglTFModel::loadNode(const tinygltf::Node& inputNode, const tinygltf::Model& input, VulkanglTFModel::Node* parent, uint32_t nodeIndex, std::vector& indexBuffer, std::vector& vertexBuffer) { VulkanglTFModel::Node* node = new VulkanglTFModel::Node{}; - node->parent = parent; node->matrix = glm::mat4(1.0f); + node->parent = parent; node->index = nodeIndex; - node->skin = inputNode.skin; - //get distributions of node - if (inputNode.translation.size() == 3) - { - node->matrix =glm::translate(node->matrix,glm::vec3(glm::make_vec3(inputNode.translation.data()))); + // Get the local node matrix + // It's either made up from translation, rotation, scale or a 4x4 matrix + if (inputNode.translation.size() == 3) { + node->matrix = glm::translate(node->matrix, glm::vec3(glm::make_vec3(inputNode.translation.data()))); } - - if (inputNode.rotation.size() == 4) - { //rotation is given by quaternion + if (inputNode.rotation.size() == 4) { glm::quat q = glm::make_quat(inputNode.rotation.data()); - node->matrix = glm::mat4(q); + node->matrix *= glm::mat4(q); } - - if (inputNode.scale.size() == 3) - { - node->matrix =glm::scale(node->matrix,glm::vec3(glm::make_vec3(inputNode.scale.data()))); + if (inputNode.scale.size() == 3) { + node->matrix = glm::scale(node->matrix, glm::vec3(glm::make_vec3(inputNode.scale.data()))); } - - if (inputNode.matrix.size() == 16) - { + if (inputNode.matrix.size() == 16) { node->matrix = glm::make_mat4x4(inputNode.matrix.data()); - } + }; - //find children of nodes if exists - if (inputNode.children.size() > 0) - { - for (size_t i = 0; i < inputNode.children.size(); i++) - { + // Load node's children + if (inputNode.children.size() > 0) { + for (size_t i = 0; i < inputNode.children.size(); i++) { loadNode(input.nodes[inputNode.children[i]], input, node, inputNode.children[i], indexBuffer, vertexBuffer); } - } - //load meshes in nodes if exists - if (inputNode.mesh > -1) - { + + // If the node contains mesh data, we load vertices and indices from the buffers + // In glTF this is done via accessors and buffer views + if (inputNode.mesh > -1) { const tinygltf::Mesh mesh = input.meshes[inputNode.mesh]; - for (size_t i = 0; i < mesh.primitives.size(); i++) - { - const tinygltf::Primitive& glTFPrimmitive = mesh.primitives[i]; + // Iterate through all primitives of this node's mesh + for (size_t i = 0; i < mesh.primitives.size(); i++) { + const tinygltf::Primitive& glTFPrimitive = mesh.primitives[i]; uint32_t firstIndex = static_cast(indexBuffer.size()); uint32_t vertexStart = static_cast(vertexBuffer.size()); uint32_t indexCount = 0; - //vertices - const float* positionBuffer = nullptr; - const float* normalsBuffer = nullptr; - const float* texcoordsBuffer = nullptr; - const float* tangentsBuffer = nullptr; - size_t vertexCount = 0; - //skin joints - const float* jointWeightsBuffer = nullptr; - const uint16_t * jointIndicesBuffer = nullptr; - - bool hasSkin = false; - //get buffer by index in primmitive.attributes + // Vertices { - if (glTFPrimmitive.attributes.find("POSITION") != glTFPrimmitive.attributes.end()) - { - const tinygltf::Accessor& accessor = input.accessors[glTFPrimmitive.attributes.find("POSITION")->second]; - const tinygltf::BufferView &view = input.bufferViews[accessor.bufferView]; - positionBuffer = reinterpret_cast (&(input.buffers[view.buffer].data[accessor.byteOffset + view.byteOffset])); + const float* positionBuffer = nullptr; + const float* normalsBuffer = nullptr; + const float* texCoordsBuffer = nullptr; + const float* tangentsBuffer = nullptr; + size_t vertexCount = 0; + + // Get buffer data for vertex positions + if (glTFPrimitive.attributes.find("POSITION") != glTFPrimitive.attributes.end()) { + const tinygltf::Accessor& accessor = input.accessors[glTFPrimitive.attributes.find("POSITION")->second]; + const tinygltf::BufferView& view = input.bufferViews[accessor.bufferView]; + positionBuffer = reinterpret_cast(&(input.buffers[view.buffer].data[accessor.byteOffset + view.byteOffset])); vertexCount = accessor.count; } - if (glTFPrimmitive.attributes.find("NORMAL") != glTFPrimmitive.attributes.end()) - { - const tinygltf::Accessor& accessor = input.accessors[glTFPrimmitive.attributes.find("NORMAL")->second]; - const tinygltf::BufferView &view = input.bufferViews[accessor.bufferView]; - normalsBuffer = reinterpret_cast (&(input.buffers[view.buffer].data[accessor.byteOffset + view.byteOffset])); - - } - //texture and tangent data - if (glTFPrimmitive.attributes.find("TEXCOORD_0") != glTFPrimmitive.attributes.end()) - { - const tinygltf::Accessor& accessor = input.accessors[glTFPrimmitive.attributes.find("TEXCOORD_0")->second]; - const tinygltf::BufferView &view = input.bufferViews[accessor.bufferView]; - texcoordsBuffer = reinterpret_cast (&(input.buffers[view.buffer].data[accessor.byteOffset + view.byteOffset])); - - } - if (glTFPrimmitive.attributes.find("TANGENT") != glTFPrimmitive.attributes.end()) - { - const tinygltf::Accessor& accessor = input.accessors[glTFPrimmitive.attributes.find("TANGENT")->second]; + // Get buffer data for vertex normals + if (glTFPrimitive.attributes.find("NORMAL") != glTFPrimitive.attributes.end()) { + const tinygltf::Accessor& accessor = input.accessors[glTFPrimitive.attributes.find("NORMAL")->second]; const tinygltf::BufferView& view = input.bufferViews[accessor.bufferView]; - tangentsBuffer = reinterpret_cast (&(input.buffers[view.buffer].data[accessor.byteOffset + view.byteOffset])); - + normalsBuffer = reinterpret_cast(&(input.buffers[view.buffer].data[accessor.byteOffset + view.byteOffset])); } - //skin joints and weights data - if (glTFPrimmitive.attributes.find("JOINTS_0") != glTFPrimmitive.attributes.end()) - { - const tinygltf::Accessor& accessor = input.accessors[glTFPrimmitive.attributes.find("JOINTS_0")->second]; - const tinygltf::BufferView &view = input.bufferViews[accessor.bufferView]; - jointIndicesBuffer = reinterpret_cast (&(input.buffers[view.buffer].data[accessor.byteOffset + view.byteOffset])); - - } - if (glTFPrimmitive.attributes.find("WEIGHTS_0") != glTFPrimmitive.attributes.end()) - { - const tinygltf::Accessor& accessor = input.accessors[glTFPrimmitive.attributes.find("WEIGHTS_0")->second]; - const tinygltf::BufferView &view = input.bufferViews[accessor.bufferView]; - jointWeightsBuffer = reinterpret_cast (&(input.buffers[view.buffer].data[accessor.byteOffset + view.byteOffset])); - + // Get buffer data for vertex texture coordinates + // glTF supports multiple sets, we only load the first one + if (glTFPrimitive.attributes.find("TEXCOORD_0") != glTFPrimitive.attributes.end()) { + const tinygltf::Accessor& accessor = input.accessors[glTFPrimitive.attributes.find("TEXCOORD_0")->second]; + const tinygltf::BufferView& view = input.bufferViews[accessor.bufferView]; + texCoordsBuffer = reinterpret_cast(&(input.buffers[view.buffer].data[accessor.byteOffset + view.byteOffset])); } - hasSkin = (jointIndicesBuffer && jointWeightsBuffer); - - for (size_t v = 0; v < vertexCount; v++) + if (glTFPrimitive.attributes.find("TANGENT") != glTFPrimitive.attributes.end()) { + const tinygltf::Accessor& accessor = input.accessors[glTFPrimitive.attributes.find("TANGENT")->second]; + const tinygltf::BufferView& view = input.bufferViews[accessor.bufferView]; + tangentsBuffer = reinterpret_cast(&(input.buffers[view.buffer].data[accessor.byteOffset + view.byteOffset])); + } + + // Append data to model's vertex buffer + for (size_t v = 0; v < vertexCount; v++) { Vertex vert{}; vert.pos = glm::vec4(glm::make_vec3(&positionBuffer[v * 3]), 1.0f); - vert.uv = texcoordsBuffer ? glm::make_vec2(&texcoordsBuffer[v*2]) : glm::vec3(0.0f); vert.normal = glm::normalize(glm::vec3(normalsBuffer ? glm::make_vec3(&normalsBuffer[v * 3]) : glm::vec3(0.0f))); - vert.color = glm::vec3(1.0f,1.0f,nodeIndex); + vert.uv = texCoordsBuffer ? glm::make_vec2(&texCoordsBuffer[v * 2]) : glm::vec3(0.0f); vert.tangent = tangentsBuffer ? glm::normalize(glm::make_vec3(&tangentsBuffer[v * 4])) : glm::vec3(0.0f); - vert.jointIndices = hasSkin ? glm::vec4(glm::make_vec4(&jointIndicesBuffer[v * 4])) : glm::vec4(0.0f); - vert.jointWeights = hasSkin ? glm::make_vec4(&jointWeightsBuffer[v * 4]) : glm::vec4(0.0f); + vert.color = glm::vec3(1.0f, 1.0f, nodeIndex);//Temp set index in color attribute vertexBuffer.push_back(vert); } } + // Indices { - const tinygltf::Accessor& accessor = input.accessors[glTFPrimmitive.indices]; - const tinygltf::BufferView& bufferview = input.bufferViews[accessor.bufferView]; - const tinygltf::Buffer& buffer = input.buffers[bufferview.buffer]; + const tinygltf::Accessor& accessor = input.accessors[glTFPrimitive.indices]; + const tinygltf::BufferView& bufferView = input.bufferViews[accessor.bufferView]; + const tinygltf::Buffer& buffer = input.buffers[bufferView.buffer]; indexCount += static_cast(accessor.count); - switch (accessor.componentType) - { + // glTF supports different component types of indices + switch (accessor.componentType) { case TINYGLTF_PARAMETER_TYPE_UNSIGNED_INT: { - const uint32_t* buf = reinterpret_cast(&buffer.data[accessor.byteOffset + bufferview.byteOffset]); - for (size_t index = 0; index < accessor.count; index++) - { + const uint32_t* buf = reinterpret_cast(&buffer.data[accessor.byteOffset + bufferView.byteOffset]); + for (size_t index = 0; index < accessor.count; index++) { indexBuffer.push_back(buf[index] + vertexStart); } break; - } - case TINYGLTF_PARAMETER_TYPE_UNSIGNED_SHORT:{ - const uint16_t* buf = reinterpret_cast(&buffer.data[accessor.byteOffset + bufferview.byteOffset]); - for (size_t index = 0; index < accessor.count; index++) - { + case TINYGLTF_PARAMETER_TYPE_UNSIGNED_SHORT: { + const uint16_t* buf = reinterpret_cast(&buffer.data[accessor.byteOffset + bufferView.byteOffset]); + for (size_t index = 0; index < accessor.count; index++) { indexBuffer.push_back(buf[index] + vertexStart); } break; } case TINYGLTF_PARAMETER_TYPE_UNSIGNED_BYTE: { - const uint8_t* buf = reinterpret_cast(&buffer.data[accessor.byteOffset + bufferview.byteOffset]); - for (size_t index = 0; index < accessor.count; index++) - { + const uint8_t* buf = reinterpret_cast(&buffer.data[accessor.byteOffset + bufferView.byteOffset]); + for (size_t index = 0; index < accessor.count; index++) { indexBuffer.push_back(buf[index] + vertexStart); } break; } default: - std::cerr << "index component type" << accessor.componentType << "not supported" << std::endl; - + std::cerr << "Index component type " << accessor.componentType << " not supported!" << std::endl; return; } } Primitive primitive{}; primitive.firstIndex = firstIndex; primitive.indexCount = indexCount; - primitive.materialIndex = glTFPrimmitive.material; + primitive.materialIndex = glTFPrimitive.material; node->mesh.primitives.push_back(primitive); - } } - if (parent) - { + + if (parent) { parent->children.push_back(node); } - else - { + else { nodes.push_back(node); } } @@ -662,6 +619,7 @@ VulkanExample::VulkanExample(): void VulkanExample::setupFrameBuffer() { + VulkanExampleBase::setupFrameBuffer(); if (pbrFrameBuffer.bCreate && (pbrFrameBuffer.fbo.width != width || pbrFrameBuffer.fbo.height != height)) { pbrFrameBuffer.color.destroy(device); @@ -674,6 +632,7 @@ void VulkanExample::setupFrameBuffer() VkFormat attachDepthFormat; VkBool32 validDepthFormat = vks::tools::getSupportedDepthFormat(physicalDevice, &attachDepthFormat); assert(validDepthFormat); + VulkanExample::createAttachment(VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, &pbrFrameBuffer.color, width, height); VulkanExample::createAttachment(attachDepthFormat, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, &pbrFrameBuffer.depth, width, height); @@ -878,11 +837,6 @@ void VulkanExample::getEnabledFeatures() size_t indexBufferSize = indexBuffer.size() * sizeof(uint32_t); model.indices.count = static_cast(indexBuffer.size()); - struct StagingBuffer { - VkBuffer buffer; - VkDeviceMemory memory; - } vertexStaging, indexStaging; - // Create host visible staging buffers (source) VK_CHECK_RESULT(vulkanDevice->createBuffer( VK_BUFFER_USAGE_TRANSFER_SRC_BIT, @@ -1017,15 +971,6 @@ void VulkanExample::getEnabledFeatures() }; VkPipelineLayoutCreateInfo pipelineLayoutCI = vks::initializers::pipelineLayoutCreateInfo(setLayouts.data(), static_cast(setLayouts.size())); VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCI, nullptr, &pipelineLayouts.pbrLayout)); - /* - - // We will use push constants to push the local matrices of a primitive to the vertex shader - VkPushConstantRange pushConstantRange = vks::initializers::pushConstantRange(VK_SHADER_STAGE_VERTEX_BIT, sizeof(glm::mat4), 0); - // Push constant ranges are part of the pipeline layout - pipelineLayoutCI.pushConstantRangeCount = 1; - pipelineLayoutCI.pPushConstantRanges = &pushConstantRange; - - */ // Descriptor set for scene matrices VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayouts.matrices, 1); VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet)); @@ -1038,33 +983,18 @@ void VulkanExample::getEnabledFeatures() }; vkUpdateDescriptorSets(device, 4, writeDescriptorSets.data(), 0, nullptr); - - // Descriptor set for glTF model skin joint matrices - /* - if (glTFModel.skins.size() > 0) - { - for (auto& skin : glTFModel.skins) - { - const VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayouts.jointMatrices, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &skin.descriptorSet)); - VkWriteDescriptorSet writeDescriptorSet = vks::initializers::writeDescriptorSet(skin.descriptorSet, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 0, &skin.ssbo.descriptor); - vkUpdateDescriptorSets(device, 1, &writeDescriptorSet, 0, nullptr); - } - } - else - */ for (auto& material : glTFModel.materials) { const VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayouts.materialUniform, 1); VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &material.materialData.descriptorSet)); - VkWriteDescriptorSet writeDescriptorSet = vks::initializers::writeDescriptorSet(material.materialData.descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &material.materialData.buffer.descriptor); + VkWriteDescriptorSet writeDescriptorSet = vks::initializers::writeDescriptorSet( + material.materialData.descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &material.materialData.buffer.descriptor); vkUpdateDescriptorSets(device, 1, &writeDescriptorSet, 0, nullptr); } - // Descriptor sets for glTF model materials - for (auto& image : glTFModel.images) - { + // Descriptor sets for materials + for (auto& image : glTFModel.images) { const VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayouts.textures, 1); VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &image.descriptorSet)); VkWriteDescriptorSet writeDescriptorSet = vks::initializers::writeDescriptorSet(image.descriptorSet, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 0, &image.texture.descriptor); @@ -1076,18 +1006,18 @@ void VulkanExample::getEnabledFeatures() VkWriteDescriptorSet writeDescriptorSet = vks::initializers::writeDescriptorSet(skinDescriptorSet, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 0, &shaderData.skinSSBO.descriptor); vkUpdateDescriptorSets(device, 1, &writeDescriptorSet, 0, nullptr); } - - //Tone Mapping pipeline layout + + //Tone Mapping pipeline layout { - auto pipelineLayoutCI = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayouts.textures, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCI, nullptr, &pipelineLayouts.tonemappingLayout)); + auto pipelineLayoutCI = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayouts.textures, 1); + VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCI, nullptr, &pipelineLayouts.tonemappingLayout)); - const VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayouts.textures, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &tonemappingDescriptorSet)); + const VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayouts.textures, 1); + VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &tonemappingDescriptorSet)); - auto imageInfo = vks::initializers::descriptorImageInfo(colorSampler, pbrFrameBuffer.color.imageView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - VkWriteDescriptorSet writeDescriptorSet = vks::initializers::writeDescriptorSet(tonemappingDescriptorSet, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 0, &imageInfo); - vkUpdateDescriptorSets(device, 1, &writeDescriptorSet, 0, nullptr); + auto imageInfo = vks::initializers::descriptorImageInfo(colorSampler, pbrFrameBuffer.color.imageView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + VkWriteDescriptorSet writeDescriptorSet = vks::initializers::writeDescriptorSet(tonemappingDescriptorSet, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 0, &imageInfo); + vkUpdateDescriptorSets(device, 1, &writeDescriptorSet, 0, nullptr); } } @@ -1113,9 +1043,6 @@ void VulkanExample::getEnabledFeatures() vks::initializers::vertexInputAttributeDescription(0, 2, VK_FORMAT_R32G32B32_SFLOAT, offsetof(VulkanglTFModel::Vertex, uv)), // Location 2: Texture coordinates vks::initializers::vertexInputAttributeDescription(0, 3, VK_FORMAT_R32G32B32_SFLOAT, offsetof(VulkanglTFModel::Vertex, color)), // Location 3: Color vks::initializers::vertexInputAttributeDescription(0, 4, VK_FORMAT_R32G32B32_SFLOAT, offsetof(VulkanglTFModel::Vertex, tangent)), // Location 4 : Tangent - // POI: Per-Vertex Joint indices and weights are passed to the vertex shader - //{5, 0, VK_FORMAT_R32G32B32A32_SFLOAT, offsetof(VulkanglTFModel::Vertex, jointIndices)}, - //{6, 0, VK_FORMAT_R32G32B32A32_SFLOAT, offsetof(VulkanglTFModel::Vertex, jointWeights)}, }; VkPipelineVertexInputStateCreateInfo vertexInputStateCI = vks::initializers::pipelineVertexInputStateCreateInfo(); vertexInputStateCI.vertexBindingDescriptionCount = static_cast(vertexInputBindings.size()); @@ -1123,7 +1050,7 @@ void VulkanExample::getEnabledFeatures() vertexInputStateCI.vertexAttributeDescriptionCount = static_cast(vertexInputAttributes.size()); vertexInputStateCI.pVertexAttributeDescriptions = vertexInputAttributes.data(); - const std::array shaderStages = { + std::array shaderStages = { loadShader(getHomeworkShadersPath() + "homework1/mesh.vert.spv", VK_SHADER_STAGE_VERTEX_BIT), loadShader(getHomeworkShadersPath() + "homework1/mesh.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT) }; @@ -1149,6 +1076,7 @@ void VulkanExample::getEnabledFeatures() rasterizationStateCI.lineWidth = 1.0f; VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.wireframe)); } + //Create Tone Mapping render pipeline prepareToneMappingPipeline(); } @@ -1206,7 +1134,10 @@ void VulkanExample::getEnabledFeatures() VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &shaderData.skinSSBO, sizeof(glm::mat4) * glTFModel.nodeCount)); - + // Map persistent + VK_CHECK_RESULT(shaderData.buffer.map()); + VK_CHECK_RESULT(shaderData.skinSSBO.map()); + for (auto& material : glTFModel.materials) { VK_CHECK_RESULT(vulkanDevice->createBuffer( @@ -1219,9 +1150,7 @@ void VulkanExample::getEnabledFeatures() } - // Map persistent - VK_CHECK_RESULT(shaderData.buffer.map()); - VK_CHECK_RESULT(shaderData.skinSSBO.map()); + updateUniformBuffers(); } @@ -1705,12 +1634,6 @@ void VulkanExample::getEnabledFeatures() VkRenderPass renderpass; VK_CHECK_RESULT(vkCreateRenderPass(device, &renderPassCI, nullptr, &renderpass)); - struct { - VkImage image; - VkImageView view; - VkDeviceMemory memory; - VkFramebuffer framebuffer; - } offscreen; //framebuffer { // Color attachment From 3e1ec8deac2d6fd3fb9c754d3cd5f6cb42c3b849 Mon Sep 17 00:00:00 2001 From: ink-soul Date: Thu, 25 May 2023 15:29:25 +0800 Subject: [PATCH 19/22] revert --- homework/homework1/homework1.cpp | 18 +++++++++--------- homework/homework1/homework1.h | 18 +++++++++--------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/homework/homework1/homework1.cpp b/homework/homework1/homework1.cpp index 5cfd033..e38e208 100644 --- a/homework/homework1/homework1.cpp +++ b/homework/homework1/homework1.cpp @@ -764,7 +764,7 @@ void VulkanExample::getEnabledFeatures() // Bind scene matrices descriptor to set 0 vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayouts.pbrLayout, 0, 1, &descriptorSet, 0, nullptr); vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayouts.pbrLayout, 6, 1, &skinDescriptorSet, 0, nullptr); - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, wireframe ? pipelines.wireframe : pipelines.solid); + vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, wireframe ? wireframePipeline : solidPipeline); glTFModel.draw(drawCmdBuffers[i], pipelineLayouts.pbrLayout); vkCmdEndRenderPass(drawCmdBuffers[i]); @@ -781,7 +781,7 @@ void VulkanExample::getEnabledFeatures() vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayouts.tonemappingLayout, 0, 1, &tonemappingDescriptorSet, 0, NULL); - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.toneMapping); + vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, toneMappingPipeline); vkCmdDraw(drawCmdBuffers[i], 3, 1, 0, 0); drawUI(drawCmdBuffers[i]); vkCmdEndRenderPass(drawCmdBuffers[i]); @@ -1066,15 +1066,15 @@ void VulkanExample::getEnabledFeatures() pipelineCI.pDynamicState = &dynamicStateCI; pipelineCI.stageCount = static_cast(shaderStages.size()); pipelineCI.pStages = shaderStages.data(); - + // Solid rendering pipeline - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.solid)); + VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &solidPipeline)); // Wire frame rendering pipeline if (deviceFeatures.fillModeNonSolid) { rasterizationStateCI.polygonMode = VK_POLYGON_MODE_LINE; rasterizationStateCI.lineWidth = 1.0f; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.wireframe)); + VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &wireframePipeline)); } //Create Tone Mapping render pipeline prepareToneMappingPipeline(); @@ -1082,10 +1082,10 @@ void VulkanExample::getEnabledFeatures() void VulkanExample::prepareToneMappingPipeline() { - if (pipelines.toneMapping != VK_NULL_HANDLE) + if (toneMappingPipeline != VK_NULL_HANDLE) { - vkDestroyPipeline(device, pipelines.toneMapping, nullptr); - pipelines.toneMapping = VK_NULL_HANDLE; + vkDestroyPipeline(device, toneMappingPipeline, nullptr); + toneMappingPipeline = VK_NULL_HANDLE; } VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCI = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); VkPipelineRasterizationStateCreateInfo rasterizationStateCI = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_BACK_BIT, VK_FRONT_FACE_COUNTER_CLOCKWISE, 0); @@ -1116,7 +1116,7 @@ void VulkanExample::getEnabledFeatures() pipelineCI.stageCount = static_cast(shaderStages.size()); pipelineCI.pStages = shaderStages.data(); - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.toneMapping)); + VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &toneMappingPipeline)); } // Prepare and initialize uniform buffer containing shader uniforms diff --git a/homework/homework1/homework1.h b/homework/homework1/homework1.h index 5b39c45..7a4500a 100644 --- a/homework/homework1/homework1.h +++ b/homework/homework1/homework1.h @@ -254,11 +254,11 @@ public: VkDeviceMemory memory; } vertexStaging, indexStaging; - struct Pipelines { - VkPipeline solid; - VkPipeline wireframe = VK_NULL_HANDLE; - VkPipeline toneMapping = VK_NULL_HANDLE; - } pipelines; + + VkPipeline solidPipeline; + VkPipeline wireframePipeline = VK_NULL_HANDLE; + VkPipeline toneMappingPipeline = VK_NULL_HANDLE; + struct PipelineLayouts { @@ -359,10 +359,10 @@ public: { // 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); + vkDestroyPipeline(device, solidPipeline, nullptr); + vkDestroyPipeline(device, toneMappingPipeline, nullptr); + if (wireframePipeline != VK_NULL_HANDLE) { + vkDestroyPipeline(device, wireframePipeline, nullptr); } vkDestroyPipelineLayout(device, pipelineLayouts.pbrLayout, nullptr); From 3bcee3c01ac4b3be42136137f49c14925ff451ad Mon Sep 17 00:00:00 2001 From: ink-soul Date: Thu, 25 May 2023 15:29:34 +0800 Subject: [PATCH 20/22] Revert "revert" This reverts commit 3e1ec8deac2d6fd3fb9c754d3cd5f6cb42c3b849. --- homework/homework1/homework1.cpp | 18 +++++++++--------- homework/homework1/homework1.h | 18 +++++++++--------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/homework/homework1/homework1.cpp b/homework/homework1/homework1.cpp index e38e208..5cfd033 100644 --- a/homework/homework1/homework1.cpp +++ b/homework/homework1/homework1.cpp @@ -764,7 +764,7 @@ void VulkanExample::getEnabledFeatures() // Bind scene matrices descriptor to set 0 vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayouts.pbrLayout, 0, 1, &descriptorSet, 0, nullptr); vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayouts.pbrLayout, 6, 1, &skinDescriptorSet, 0, nullptr); - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, wireframe ? wireframePipeline : solidPipeline); + vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, wireframe ? pipelines.wireframe : pipelines.solid); glTFModel.draw(drawCmdBuffers[i], pipelineLayouts.pbrLayout); vkCmdEndRenderPass(drawCmdBuffers[i]); @@ -781,7 +781,7 @@ void VulkanExample::getEnabledFeatures() vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayouts.tonemappingLayout, 0, 1, &tonemappingDescriptorSet, 0, NULL); - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, toneMappingPipeline); + vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.toneMapping); vkCmdDraw(drawCmdBuffers[i], 3, 1, 0, 0); drawUI(drawCmdBuffers[i]); vkCmdEndRenderPass(drawCmdBuffers[i]); @@ -1066,15 +1066,15 @@ void VulkanExample::getEnabledFeatures() pipelineCI.pDynamicState = &dynamicStateCI; pipelineCI.stageCount = static_cast(shaderStages.size()); pipelineCI.pStages = shaderStages.data(); - + // Solid rendering pipeline - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &solidPipeline)); + VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.solid)); // Wire frame rendering pipeline if (deviceFeatures.fillModeNonSolid) { rasterizationStateCI.polygonMode = VK_POLYGON_MODE_LINE; rasterizationStateCI.lineWidth = 1.0f; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &wireframePipeline)); + VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.wireframe)); } //Create Tone Mapping render pipeline prepareToneMappingPipeline(); @@ -1082,10 +1082,10 @@ void VulkanExample::getEnabledFeatures() void VulkanExample::prepareToneMappingPipeline() { - if (toneMappingPipeline != VK_NULL_HANDLE) + if (pipelines.toneMapping != VK_NULL_HANDLE) { - vkDestroyPipeline(device, toneMappingPipeline, nullptr); - toneMappingPipeline = VK_NULL_HANDLE; + vkDestroyPipeline(device, pipelines.toneMapping, nullptr); + pipelines.toneMapping = VK_NULL_HANDLE; } VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCI = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); VkPipelineRasterizationStateCreateInfo rasterizationStateCI = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_BACK_BIT, VK_FRONT_FACE_COUNTER_CLOCKWISE, 0); @@ -1116,7 +1116,7 @@ void VulkanExample::getEnabledFeatures() pipelineCI.stageCount = static_cast(shaderStages.size()); pipelineCI.pStages = shaderStages.data(); - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &toneMappingPipeline)); + VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.toneMapping)); } // Prepare and initialize uniform buffer containing shader uniforms diff --git a/homework/homework1/homework1.h b/homework/homework1/homework1.h index 7a4500a..5b39c45 100644 --- a/homework/homework1/homework1.h +++ b/homework/homework1/homework1.h @@ -254,11 +254,11 @@ public: VkDeviceMemory memory; } vertexStaging, indexStaging; - - VkPipeline solidPipeline; - VkPipeline wireframePipeline = VK_NULL_HANDLE; - VkPipeline toneMappingPipeline = VK_NULL_HANDLE; - + struct Pipelines { + VkPipeline solid; + VkPipeline wireframe = VK_NULL_HANDLE; + VkPipeline toneMapping = VK_NULL_HANDLE; + } pipelines; struct PipelineLayouts { @@ -359,10 +359,10 @@ public: { // Clean up used Vulkan resources // Note : Inherited destructor cleans up resources stored in base class - vkDestroyPipeline(device, solidPipeline, nullptr); - vkDestroyPipeline(device, toneMappingPipeline, nullptr); - if (wireframePipeline != VK_NULL_HANDLE) { - vkDestroyPipeline(device, wireframePipeline, nullptr); + 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); From 310ab79454b30c960d28f204a977caa432171dbb Mon Sep 17 00:00:00 2001 From: ink-soul Date: Thu, 25 May 2023 15:41:08 +0800 Subject: [PATCH 21/22] Update homework1.cpp --- homework/homework1/homework1.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/homework/homework1/homework1.cpp b/homework/homework1/homework1.cpp index 5cfd033..fc848b5 100644 --- a/homework/homework1/homework1.cpp +++ b/homework/homework1/homework1.cpp @@ -961,7 +961,6 @@ void VulkanExample::getEnabledFeatures() // Set 2 = Material texture (FS) std::array setLayouts = { descriptorSetLayouts.matrices, - //descriptorSetLayouts.jointMatrices, descriptorSetLayouts.textures, descriptorSetLayouts.textures, descriptorSetLayouts.textures, From 0ed950f7c1833d861e34464f98dcfea2c5d5fe0e Mon Sep 17 00:00:00 2001 From: ink-soul Date: Thu, 25 May 2023 16:13:37 +0800 Subject: [PATCH 22/22] complete --- homework/homework1/homework1.cpp | 1525 ++++++++++++++---------------- homework/homework1/homework1.h | 22 +- 2 files changed, 730 insertions(+), 817 deletions(-) diff --git a/homework/homework1/homework1.cpp b/homework/homework1/homework1.cpp index fc848b5..869031c 100644 --- a/homework/homework1/homework1.cpp +++ b/homework/homework1/homework1.cpp @@ -16,12 +16,8 @@ * * If you are looking for a complete glTF implementation, check out https://github.com/SaschaWillems/Vulkan-glTF-PBR/ */ - - #include "homework1.h" - - /* glTF loading functions @@ -30,6 +26,8 @@ void VulkanglTFModel::loadImages(tinygltf::Model& input) { + // Images can be stored inside the glTF (which is the case for the sample model), so instead of directly + // loading them from disk, we fetch them from the glTF loader and upload the buffers images.resize(input.images.size()); for (size_t i = 0; i < input.images.size(); i++) { tinygltf::Image& glTFImage = input.images[i]; @@ -70,6 +68,95 @@ } } + void VulkanglTFModel::loadAnimations(tinygltf::Model& input) + { + animations.resize(input.animations.size()); + + for (size_t i = 0; i < input.animations.size(); ++i) + { + auto glTFAnimation = input.animations[i]; + animations[i].name = glTFAnimation.name; + + //Samplers + animations[i].samplers.resize(glTFAnimation.samplers.size()); + for (size_t j = 0; j < glTFAnimation.samplers.size(); ++j) + { + auto glTFSampler = glTFAnimation.samplers[j]; + auto& dstSampler = animations[i].samplers[j]; + dstSampler.interpolation = glTFSampler.interpolation; + + // Read sampler keyframe input time values + { + const auto& accessor = input.accessors[glTFSampler.input]; + const auto& bufferView = input.bufferViews[accessor.bufferView]; + const auto& buffer = input.buffers[bufferView.buffer]; + const void* dataPtr = &buffer.data[accessor.byteOffset + bufferView.byteOffset]; + const float* buf = static_cast(dataPtr); + for (size_t index = 0; index < accessor.count; ++index) + { + dstSampler.inputs.push_back(buf[index]); + } + // Adjust animation's start and end times + for (auto input : animations[i].samplers[j].inputs) + { + if (input < animations[i].start) + { + animations[i].start = input; + }; + if (input > animations[i].end) + { + animations[i].end = input; + } + } + } + + // Read sampler keyframe output translate/rotate/scale values + { + const auto& accessor = input.accessors[glTFSampler.output]; + const auto& bufferView = input.bufferViews[accessor.bufferView]; + const auto& buffer = input.buffers[bufferView.buffer]; + const void* dataPtr = &buffer.data[accessor.byteOffset + bufferView.byteOffset]; + switch (accessor.type) + { + case TINYGLTF_TYPE_VEC3: + { + const glm::vec3* buf = static_cast(dataPtr); + for (size_t index = 0; index < accessor.count; index++) + { + dstSampler.outputsVec4.push_back(glm::vec4(buf[index], 0.0f)); + } + break; + } + case TINYGLTF_TYPE_VEC4: + { + const glm::vec4* buf = static_cast(dataPtr); + for (size_t index = 0; index < accessor.count; index++) + { + dstSampler.outputsVec4.push_back(buf[index]); + } + break; + } + default: + { + std::cout << "unknown type" << std::endl; + break; + } + } + } + } + + animations[i].channels.resize(glTFAnimation.channels.size()); + for (size_t j = 0; j < glTFAnimation.channels.size(); ++j) + { + auto glTFChannel = glTFAnimation.channels[j]; + auto& dstChannel = animations[i].channels[j]; + dstChannel.path = glTFChannel.target_path; + dstChannel.samplerIndex = glTFChannel.sampler; + dstChannel.node = nodeFromIndex(glTFChannel.target_node); + } + } + } + void VulkanglTFModel::loadMaterials(tinygltf::Model& input) { materials.resize(input.materials.size()); @@ -99,193 +186,15 @@ { materials[i].materialData.values.emissiveFactor = glm::make_vec3(glTFMaterial.emissiveFactor.data()); } - + if (glTFMaterial.values.find("baseColorFactor") != glTFMaterial.values.end()) { materials[i].materialData.values.baseColorFactor = glm::make_vec4(glTFMaterial.values["baseColorFactor"].ColorFactor().data()); } } } - - - //animation loader - void VulkanglTFModel::loadAnimations(tinygltf::Model& input) - { - animations.resize(input.animations.size()); - for (size_t i = 0; i < input.animations.size(); i++) - { - tinygltf::Animation glTFAnimation = input.animations[i]; - animations[i].name = glTFAnimation.name; - - // Samplers - animations[i].samplers.resize(glTFAnimation.samplers.size()); - for (size_t j = 0; j < glTFAnimation.samplers.size(); j++) - { - tinygltf::AnimationSampler glTFSampler = glTFAnimation.samplers[j]; - AnimationSampler& dstSampler = animations[i].samplers[j]; - dstSampler.interpolation = glTFSampler.interpolation; - - // Read sampler keyframe input time values - { - const tinygltf::Accessor& accessor = input.accessors[glTFSampler.input]; - const tinygltf::BufferView& bufferView = input.bufferViews[accessor.bufferView]; - const tinygltf::Buffer& buffer = input.buffers[bufferView.buffer]; - const void* dataPtr = &buffer.data[accessor.byteOffset + bufferView.byteOffset]; - const float* buf = static_cast(dataPtr); - for (size_t index = 0; index < accessor.count; index++) - { - dstSampler.inputs.push_back(buf[index]); - } - // Adjust animation's start and end times - for (auto input : animations[i].samplers[j].inputs) - { - if (input < animations[i].start) - { - animations[i].start = input; - }; - if (input > animations[i].end) - { - animations[i].end = input; - } - } - } - - // Read sampler keyframe output translate/rotate/scale values - { - const tinygltf::Accessor& accessor = input.accessors[glTFSampler.output]; - const tinygltf::BufferView& bufferView = input.bufferViews[accessor.bufferView]; - const tinygltf::Buffer& buffer = input.buffers[bufferView.buffer]; - const void* dataPtr = &buffer.data[accessor.byteOffset + bufferView.byteOffset]; - switch (accessor.type) - { - case TINYGLTF_TYPE_VEC3: { - const glm::vec3* buf = static_cast(dataPtr); - for (size_t index = 0; index < accessor.count; index++) - { - dstSampler.outputsVec4.push_back(glm::vec4(buf[index], 0.0f)); - } - break; - } - case TINYGLTF_TYPE_VEC4: { - const glm::vec4* buf = static_cast(dataPtr); - for (size_t index = 0; index < accessor.count; index++) - { - dstSampler.outputsVec4.push_back(buf[index]); - } - break; - } - default: { - std::cout << "unknown type" << std::endl; - break; - } - } - } - } - - // Channels - animations[i].channels.resize(glTFAnimation.channels.size()); - for (size_t j = 0; j < glTFAnimation.channels.size(); j++) - { - tinygltf::AnimationChannel glTFChannel = glTFAnimation.channels[j]; - AnimationChannel& dstChannel = animations[i].channels[j]; - dstChannel.path = glTFChannel.target_path; - dstChannel.samplerIndex = glTFChannel.sampler; - dstChannel.node = nodeFromIndex(glTFChannel.target_node); - } - } - - - } - /* - // load skins from glTF model - void VulkanglTFModel::loadSkins(tinygltf::Model& input) - { - - skins.resize(input.skins.size()); - if (skins.size() > 0) - { - for (size_t i = 0; i < input.skins.size(); i++) - { - 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()); - } - } - - } - - - - }*/ - - //glTF nodes loading helper function - //rewrite node loader,simplify logic - //Search node from parent to children by index - VulkanglTFModel::Node* VulkanglTFModel::findNode(Node* parent, uint32_t index) - { - Node* nodeFound = nullptr; - if (parent->index == index) - { - return parent; - } - for (auto& child : parent->children) - { - nodeFound = findNode(child, index); - if (nodeFound) - { - break; - } - } - return nodeFound; - } //iterate vector of nodes to check weather nodes exist or not - VulkanglTFModel::Node* VulkanglTFModel::nodeFromIndex(uint32_t index) - { - Node* nodeFound = nullptr; - for (auto& node : nodes) - { - nodeFound = findNode(node, index); - if (nodeFound) - { - break; - } - } - return nodeFound; - } - - - //node loader - void VulkanglTFModel::loadNode(const tinygltf::Node& inputNode, const tinygltf::Model& input, VulkanglTFModel::Node* parent, uint32_t nodeIndex, std::vector& indexBuffer, std::vector& vertexBuffer) + void VulkanglTFModel::loadNode(const tinygltf::Node& inputNode, const tinygltf::Model& input, VulkanglTFModel::Node* parent, uint32_t nodeIndex,std::vector& indexBuffer, std::vector& vertexBuffer) { VulkanglTFModel::Node* node = new VulkanglTFModel::Node{}; node->matrix = glm::mat4(1.0f); @@ -311,7 +220,7 @@ // Load node's children if (inputNode.children.size() > 0) { for (size_t i = 0; i < inputNode.children.size(); i++) { - loadNode(input.nodes[inputNode.children[i]], input, node, inputNode.children[i], indexBuffer, vertexBuffer); + loadNode(input.nodes[inputNode.children[i]], input , node, inputNode.children[i],indexBuffer, vertexBuffer); } } @@ -424,63 +333,41 @@ } } - - /* - vertex skinning functions - */ - glm::mat4 VulkanglTFModel::getNodeMatrix(VulkanglTFModel::Node* node) + VulkanglTFModel::Node* VulkanglTFModel::findNode(Node* parent, uint32_t index) { - glm::mat4 nodeMatrix = node->getLocalMatrix(); - VulkanglTFModel::Node* currentParent = node->parent; - while (currentParent) + Node* nodeFound = nullptr; + if (parent->index == index) { - nodeMatrix = currentParent->getLocalMatrix() * nodeMatrix; - currentParent = currentParent->parent; + return parent; } - return nodeMatrix; - } - - void VulkanglTFModel::updateNodeMatrix(Node* node, std::vector& nodeMatrics) - { - if (node->skin <= -1) + for (auto& child : parent->children) { - nodeMatrics[node->index] = getNodeMatrix(node); - for (auto& child : node->children) + nodeFound = findNode(child, index); + if (nodeFound) { - updateNodeMatrix(child, nodeMatrics); + break; } } - + return nodeFound; } - void VulkanglTFModel::updateJoints(VulkanglTFModel::Node* node) + VulkanglTFModel::Node* VulkanglTFModel::nodeFromIndex(uint32_t index) { - if (node->skin > -1) + Node* nodeFound = nullptr; + for (auto& node : nodes) { - glm::mat4 inversTransform = glm::inverse(getNodeMatrix(node)); - Skin skin = skins[node->skin]; - size_t numJoints = (uint32_t)skin.joints.size(); - std::vector jointMatrices(numJoints); - for (size_t i = 0; i < numJoints; i++) + nodeFound = findNode(node, index); + if (nodeFound) { - jointMatrices[i] = getNodeMatrix(skin.joints[i]) * skin.inverseBindMatrices[i]; - jointMatrices[i] = inversTransform * jointMatrices[i]; + break; } - skin.ssbo.copyTo(jointMatrices.data(), jointMatrices.size() * sizeof(glm::mat4)); - } - for (auto& child : node->children) - { - updateJoints(child); } + return nodeFound; } - void VulkanglTFModel::updateAnimation(float deltaTime,vks::Buffer buffer) + void VulkanglTFModel::updateAnimation(float deltaTime, vks::Buffer& buffer) { - if (activeAnimation > static_cast(animations.size()) - 1) - { - std::cout << "No animation with index " << activeAnimation << std::endl; - return; - } + constexpr uint32_t activeAnimation = 0; Animation& animation = animations[activeAnimation]; animation.currentTime += deltaTime; if (animation.currentTime > animation.end) @@ -490,7 +377,7 @@ for (auto& channel : animation.channels) { - AnimationSampler& sampler = animation.samplers[channel.samplerIndex]; + auto& sampler = animation.samplers[channel.samplerIndex]; for (size_t i = 0; i < sampler.inputs.size() - 1; ++i) { if (sampler.interpolation != "LINEAR") @@ -498,8 +385,6 @@ std::cout << "This sample only supports linear interpolations\n"; continue; } - - // Get the input keyframe values for the current time stamp if ((animation.currentTime >= sampler.inputs[i]) && (animation.currentTime <= sampler.inputs[i + 1])) { float ratio = (animation.currentTime - sampler.inputs[i]) / (sampler.inputs[i + 1] - sampler.inputs[i]); @@ -533,48 +418,67 @@ } } } - //if no skin in model , update node matrix to update animation stage std::vector nodeMatrics(nodeCount); for (auto& node : nodes) { - //updateJoints(node); updateNodeMatrix(node, nodeMatrics); } buffer.copyTo(nodeMatrics.data(), nodeCount * sizeof(glm::mat4)); - } + + void VulkanglTFModel::updateNodeMatrix(Node* node, std::vector& nodeMatrics) + { + nodeMatrics[node->index] = getNodeMatrix(node); + for (auto& child : node->children) + { + updateNodeMatrix(child, nodeMatrics); + } + } + + glm::mat4 VulkanglTFModel::getNodeMatrix(Node* node) + { + glm::mat4 nodeMatrix = node->getLocalMatrix(); + Node* currentParent = node->parent; + while (currentParent) + { + nodeMatrix = currentParent->getLocalMatrix() * nodeMatrix; + currentParent = currentParent->parent; + } + return nodeMatrix; + } + /* glTF rendering functions */ // Draw a single node including child nodes (if present) - void VulkanglTFModel::drawNode(VkCommandBuffer commandBuffer, VkPipelineLayout pipelineLayout, VulkanglTFModel::Node node) + void VulkanglTFModel::drawNode(VkCommandBuffer commandBuffer, VkPipelineLayout pipelineLayout, VulkanglTFModel::Node* node, bool bPushConstants) { - if (node.mesh.primitives.size() > 0) { + if (node->mesh.primitives.size() > 0) { // Pass the node's matrix via push constants // Traverse the node hierarchy to the top-most parent to get the final matrix of the current node - glm::mat4 nodeMatrix = node.matrix; - VulkanglTFModel::Node* currentParent = node.parent; + glm::mat4 nodeMatrix = node->matrix; + VulkanglTFModel::Node* currentParent = node->parent; while (currentParent) { nodeMatrix = currentParent->matrix * nodeMatrix; currentParent = currentParent->parent; } - - for (VulkanglTFModel::Primitive& primitive : node.mesh.primitives) { + + for (VulkanglTFModel::Primitive& primitive : node->mesh.primitives) { if (primitive.indexCount > 0) { // Get the texture index for this primitive if (textures.size() > 0) { VulkanglTFModel::Texture texture = textures[materials[primitive.materialIndex].baseColorTextureIndex]; - VulkanglTFModel::Texture normalMap = textures[materials[primitive.materialIndex].normalMapTextureIndex]; - VulkanglTFModel::Texture roughMetalMap = textures[materials[primitive.materialIndex].matalicRoughTextureIndex]; - + auto normalMap = textures[materials[primitive.materialIndex].normalMapTextureIndex]; + auto roughMetalMap = textures[materials[primitive.materialIndex].matalicRoughTextureIndex]; + if (materials[primitive.materialIndex].emissiveTextureIndex >= 0) { - VulkanglTFModel::Texture emissiveMap = textures[materials[primitive.materialIndex].emissiveTextureIndex]; + auto emissiveMap = textures[materials[primitive.materialIndex].emissiveTextureIndex]; vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 4, 1, &images[emissiveMap.imageIndex].descriptorSet, 0, nullptr); } - + // Bind the descriptor for the current primitive's texture vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 1, 1, &images[texture.imageIndex].descriptorSet, 0, nullptr); vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 2, 1, &images[normalMap.imageIndex].descriptorSet, 0, nullptr); @@ -585,13 +489,13 @@ } } } - for (auto &child : node.children) { - drawNode(commandBuffer, pipelineLayout, *child); + for (auto& child : node->children) { + drawNode(commandBuffer, pipelineLayout, child, bPushConstants); } } // Draw the glTF scene starting at the top-level-nodes - void VulkanglTFModel::draw(VkCommandBuffer commandBuffer, VkPipelineLayout pipelineLayout ) + void VulkanglTFModel::draw(VkCommandBuffer commandBuffer, VkPipelineLayout pipelineLayout, bool flag = true) { // All vertices and indices are stored in single buffers, so we only need to bind once VkDeviceSize offsets[1] = { 0 }; @@ -599,15 +503,16 @@ vkCmdBindIndexBuffer(commandBuffer, indices.buffer, 0, VK_INDEX_TYPE_UINT32); // Render all nodes at top-level for (auto& node : nodes) { - drawNode(commandBuffer, pipelineLayout, *node); + drawNode(commandBuffer, pipelineLayout, node, flag); } } -VulkanExample::VulkanExample(): - VulkanExampleBase(ENABLE_VALIDATION) + + VulkanExample::VulkanExample(): + VulkanExampleBase(ENABLE_VALIDATION) { title = "homework1"; camera.type = Camera::CameraType::lookat; @@ -617,121 +522,125 @@ VulkanExample::VulkanExample(): camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 256.0f); } -void VulkanExample::setupFrameBuffer() -{ - VulkanExampleBase::setupFrameBuffer(); - if (pbrFrameBuffer.bCreate && (pbrFrameBuffer.fbo.width != width || pbrFrameBuffer.fbo.height != height)) + void VulkanExample::getEnabledFeatures() { - pbrFrameBuffer.color.destroy(device); - pbrFrameBuffer.depth.destroy(device); - pbrFrameBuffer.fbo.destroy(device); - vkDestroySampler(device, colorSampler, nullptr); + // Fill mode non solid is required for wireframe display + if (deviceFeatures.fillModeNonSolid) { + enabledFeatures.fillModeNonSolid = VK_TRUE; + }; } - pbrFrameBuffer.fbo.setSize(width, height); - VkFormat attachDepthFormat; - VkBool32 validDepthFormat = vks::tools::getSupportedDepthFormat(physicalDevice, &attachDepthFormat); - assert(validDepthFormat); - - VulkanExample::createAttachment(VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, &pbrFrameBuffer.color, width, height); - VulkanExample::createAttachment(attachDepthFormat, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, &pbrFrameBuffer.depth, width, height); - - - std::array attachs = {}; - for (uint32_t i = 0; i < static_cast(attachs.size()); i++) + void VulkanExample::setupFrameBuffer() { - attachs[i].samples = VK_SAMPLE_COUNT_1_BIT; - attachs[i].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - attachs[i].storeOp = VK_ATTACHMENT_STORE_OP_STORE; - attachs[i].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - attachs[i].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attachs[i].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - attachs[i].finalLayout = 1 ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL; + VulkanExampleBase::setupFrameBuffer(); + if (pbrFrameBuffer.bCreate && (pbrFrameBuffer.fbo.width != width || pbrFrameBuffer.fbo.height != height)) + { + pbrFrameBuffer.color.destroy(device); + pbrFrameBuffer.depth.destroy(device); + pbrFrameBuffer.fbo.destroy(device); + vkDestroySampler(device, colorSampler, nullptr); + } + + //Create image color attachment + pbrFrameBuffer.fbo.setSize(width, height); + VkFormat attDepthFormat; + VkBool32 validDepthFormat = vks::tools::getSupportedDepthFormat(physicalDevice, &attDepthFormat); + assert(validDepthFormat); + + createAttachment(VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, &pbrFrameBuffer.color, width, height); + createAttachment(attDepthFormat, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, &pbrFrameBuffer.depth, width, height); + { + std::array attachs = {}; + for (uint32_t i = 0; i < static_cast(attachs.size()); ++i) + { + attachs[i].samples = VK_SAMPLE_COUNT_1_BIT; + attachs[i].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; + attachs[i].storeOp = VK_ATTACHMENT_STORE_OP_STORE; + attachs[i].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + attachs[i].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + attachs[i].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + attachs[i].finalLayout = i == 1 ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + } + attachs[0].format = pbrFrameBuffer.color.format; + attachs[1].format = pbrFrameBuffer.depth.format; + + VkAttachmentReference colorReference = {}; + colorReference.attachment = 0; + colorReference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + + VkAttachmentReference depthReference = {}; + depthReference.attachment = 1; + depthReference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + + VkSubpassDescription subpass = {}; + subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; + subpass.pColorAttachments = &colorReference; + subpass.colorAttachmentCount = 1; + subpass.pDepthStencilAttachment = &depthReference; + + std::array dependencies; + //To test src 0 + dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL; + dependencies[0].dstSubpass = 0; + dependencies[0].srcStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + dependencies[0].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + dependencies[0].srcAccessMask = VK_ACCESS_SHADER_READ_BIT; + dependencies[0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + dependencies[0].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; + + dependencies[1].srcSubpass = 0; + dependencies[1].dstSubpass = VK_SUBPASS_EXTERNAL; + dependencies[1].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + dependencies[1].dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + dependencies[1].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + dependencies[1].dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + dependencies[1].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; + + VkRenderPassCreateInfo renderPassCI = {}; + renderPassCI.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; + renderPassCI.pAttachments = attachs.data(); + renderPassCI.attachmentCount = static_cast(attachs.size()); + renderPassCI.pSubpasses = &subpass; + renderPassCI.subpassCount = 1; + renderPassCI.pDependencies = dependencies.data(); + renderPassCI.dependencyCount = 2; + VK_CHECK_RESULT(vkCreateRenderPass(device, &renderPassCI, nullptr, &pbrFrameBuffer.fbo.renderPass)); + + //Create FBO + VkImageView attachments[2] = { pbrFrameBuffer.color.imageView, pbrFrameBuffer.depth.imageView }; + VkFramebufferCreateInfo fbufCreateInfo = vks::initializers::framebufferCreateInfo(); + fbufCreateInfo.renderPass = pbrFrameBuffer.fbo.renderPass; + fbufCreateInfo.pAttachments = attachments; + fbufCreateInfo.attachmentCount = 2; + fbufCreateInfo.width = pbrFrameBuffer.fbo.width; + fbufCreateInfo.height = pbrFrameBuffer.fbo.height; + fbufCreateInfo.layers = 1; + VK_CHECK_RESULT(vkCreateFramebuffer(device, &fbufCreateInfo, nullptr, &pbrFrameBuffer.fbo.frameBuffer)); + } + + //Create Image sampler + VkSamplerCreateInfo samplerCI = vks::initializers::samplerCreateInfo(); + samplerCI.magFilter = VK_FILTER_NEAREST; + samplerCI.minFilter = VK_FILTER_NEAREST; + samplerCI.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; + samplerCI.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + samplerCI.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + samplerCI.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + //samplerCI.mipLodBias = 0.0f; + //samplerCI.maxAnisotropy = 1.0f; + samplerCI.minLod = 0.0f; + samplerCI.maxLod = 1.0f; + samplerCI.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE; + VK_CHECK_RESULT(vkCreateSampler(device, &samplerCI, nullptr, &colorSampler)); + + if (tonemappingDescriptorSet != VK_NULL_HANDLE) //Bad logic + { + auto imageInfo = vks::initializers::descriptorImageInfo(colorSampler, pbrFrameBuffer.color.imageView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + VkWriteDescriptorSet writeDescriptorSet = vks::initializers::writeDescriptorSet(tonemappingDescriptorSet, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 0, &imageInfo); + vkUpdateDescriptorSets(device, 1, &writeDescriptorSet, 0, nullptr); + } + pbrFrameBuffer.bCreate = true; } - attachs[0].format = pbrFrameBuffer.color.format; - attachs[1].format = pbrFrameBuffer.depth.format; - - - VkAttachmentReference colorRefference = {}; - colorRefference.attachment = 0; - colorRefference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - - VkAttachmentReference depthRefference = {}; - colorRefference.attachment = 1; - colorRefference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - - VkSubpassDescription subpass = {}; - subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - subpass.pColorAttachments = &colorRefference; - subpass.colorAttachmentCount = 1; - subpass.pDepthStencilAttachment = &depthRefference; - - std::array dependencies; - //To test src 0 - dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL; - dependencies[0].dstSubpass = 0; - dependencies[0].srcStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; - dependencies[0].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependencies[0].srcAccessMask = VK_ACCESS_SHADER_READ_BIT; - dependencies[0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - dependencies[0].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; - - dependencies[1].srcSubpass = 0; - dependencies[1].dstSubpass = VK_SUBPASS_EXTERNAL; - dependencies[1].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependencies[1].dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; - dependencies[1].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - dependencies[1].dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - dependencies[1].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; - - VkRenderPassCreateInfo renderPassCI = {}; - renderPassCI.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; - renderPassCI.pAttachments = attachs.data(); - renderPassCI.attachmentCount = static_cast(attachs.size()); - renderPassCI.pSubpasses = &subpass; - renderPassCI.pDependencies = dependencies.data(); - renderPassCI.dependencyCount = 2; - VK_CHECK_RESULT(vkCreateRenderPass(device, &renderPassCI, nullptr, &pbrFrameBuffer.fbo.renderPass)); - // FBO - VkImageView attachments[2] = { pbrFrameBuffer.color.imageView,pbrFrameBuffer.depth.imageView }; - VkFramebufferCreateInfo frameBufferCreateInfo = vks::initializers::framebufferCreateInfo(); - frameBufferCreateInfo.renderPass = pbrFrameBuffer.fbo.renderPass; - frameBufferCreateInfo.pAttachments = attachments; - frameBufferCreateInfo.attachmentCount = 2; - frameBufferCreateInfo.width = pbrFrameBuffer.fbo.width; - frameBufferCreateInfo.height = pbrFrameBuffer.fbo.height; - frameBufferCreateInfo.layers = 1; - VK_CHECK_RESULT(vkCreateFramebuffer(device, &frameBufferCreateInfo, nullptr, &pbrFrameBuffer.fbo.frameBuffer)); - - VkSamplerCreateInfo samplerCI = vks::initializers::samplerCreateInfo(); - samplerCI.magFilter = VK_FILTER_NEAREST; - samplerCI.minFilter = VK_FILTER_NEAREST; - samplerCI.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; - samplerCI.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; - samplerCI.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; - samplerCI.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; - - samplerCI.minLod = 0.0f; - samplerCI.maxLod = 1.0f; - samplerCI.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE; - VK_CHECK_RESULT(vkCreateSampler(device, &samplerCI, nullptr, &colorSampler)); - if (tonemappingDescriptorSet != VK_NULL_HANDLE) - { - auto imageInfo = vks::initializers::descriptorImageInfo(colorSampler, pbrFrameBuffer.color.imageView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - VkWriteDescriptorSet writeDescriptorSet = vks::initializers::writeDescriptorSet(tonemappingDescriptorSet, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 0, &imageInfo); - vkUpdateDescriptorSets(device, 1, &writeDescriptorSet, 0, nullptr); - - } - pbrFrameBuffer.bCreate = true; -} - -void VulkanExample::getEnabledFeatures() -{ - // Fill mode non solid is required for wireframe display - if (deviceFeatures.fillModeNonSolid) { - enabledFeatures.fillModeNonSolid = VK_TRUE; - }; -} void VulkanExample::buildCommandBuffers() { @@ -790,7 +699,7 @@ void VulkanExample::getEnabledFeatures() } } - void VulkanExample::loadglTFFile(std::string filename, VulkanglTFModel& model, bool bSkyboxFlag) + void VulkanExample::loadglTFFile(std::string filename, VulkanglTFModel& model, bool bSkyboxFlag = false) { tinygltf::Model glTFInput; tinygltf::TinyGLTF gltfContext; @@ -837,6 +746,11 @@ void VulkanExample::getEnabledFeatures() size_t indexBufferSize = indexBuffer.size() * sizeof(uint32_t); model.indices.count = static_cast(indexBuffer.size()); + struct StagingBuffer { + VkBuffer buffer; + VkDeviceMemory memory; + } vertexStaging, indexStaging; + // Create host visible staging buffers (source) VK_CHECK_RESULT(vulkanDevice->createBuffer( VK_BUFFER_USAGE_TRANSFER_SRC_BIT, @@ -899,10 +813,9 @@ void VulkanExample::getEnabledFeatures() void VulkanExample::loadAssets() { - loadglTFFile(getAssetPath() + "buster_drone/busterDrone.gltf",glTFModel); + loadglTFFile(getAssetPath() + "buster_drone/busterDrone.gltf", glTFModel); loadglTFFile(getAssetPath() + "models/cube.gltf", skyboxModel, true); ibltextures.skyboxCube.loadFromFile(getAssetPath() + "textures/hdr/pisa_cube.ktx", VK_FORMAT_R16G16B16A16_SFLOAT, vulkanDevice, queue); - } void VulkanExample::setupDescriptors() @@ -910,26 +823,24 @@ void VulkanExample::getEnabledFeatures() /* This sample uses separate descriptor sets (and layouts) for the matrices and materials (textures) */ + //Descriptor Pool Alloc + { + std::vector poolSizes = { + vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 4), + // One combined image sampler per model image/texture + vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, static_cast(glTFModel.images.size())), + vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 4), // Add aditional sampler descriptor + vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1) + }; + // One set for matrices and one per model image/texture + const uint32_t maxSetCount = static_cast(glTFModel.images.size()) + 6; + VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, maxSetCount); + VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); + } - std::vector poolSizes = { - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 4), - // One combined image sampler per material image/texture - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, static_cast(glTFModel.images.size())), - // One ssbo per skin - //vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, static_cast(glTFModel.skins.size())), - // sampler descriptor - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,4), - //animation storage buffer - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,1) - }; - // One set for matrices and one per model image/texture - const uint32_t maxSetCount = static_cast(glTFModel.images.size()) + 6; - VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, maxSetCount); - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); - - // Descriptor set layouts - std::vector setLayoutBindings = + // Descriptor set layout for passing matrices ---and precompute texture add in this descriptor + std::vector setLayoutBindings = { vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0), vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 1), @@ -950,75 +861,69 @@ void VulkanExample::getEnabledFeatures() setLayoutBinding = vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0); VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorSetLayoutCI, nullptr, &descriptorSetLayouts.ssbo)); - // Descriptor set layout for passing skin joint matrices - - //setLayoutBinding = vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0); - //VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorSetLayoutCI, nullptr, &descriptorSetLayouts.jointMatrices)); - - // The pipeline layout uses three sets: - // Set 0 = Scene matrices (VS) - // Set 1 = Joint matrices (VS) - // Set 2 = Material texture (FS) - std::array setLayouts = { - descriptorSetLayouts.matrices, - descriptorSetLayouts.textures, - descriptorSetLayouts.textures, - descriptorSetLayouts.textures, - descriptorSetLayouts.textures, - descriptorSetLayouts.materialUniform, - descriptorSetLayouts.ssbo, - }; - VkPipelineLayoutCreateInfo pipelineLayoutCI = vks::initializers::pipelineLayoutCreateInfo(setLayouts.data(), static_cast(setLayouts.size())); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCI, nullptr, &pipelineLayouts.pbrLayout)); - // Descriptor set for scene matrices - VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayouts.matrices, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet)); - std::vector writeDescriptorSets = + //Pbr pipeline layout { - vks::initializers::writeDescriptorSet(descriptorSet,VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,0,&shaderData.buffer.descriptor), - vks::initializers::writeDescriptorSet(descriptorSet,VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,1,&ibltextures.irradianceCube.descriptor), - vks::initializers::writeDescriptorSet(descriptorSet,VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,2,&ibltextures.lutBrdf.descriptor), - vks::initializers::writeDescriptorSet(descriptorSet,VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,3,&ibltextures.prefilteredCube.descriptor), - }; + // Pipeline layout using both descriptor sets (set 0 = matrices, set 1 = material) + std::array setLayouts = + { descriptorSetLayouts.matrices, + descriptorSetLayouts.textures, + descriptorSetLayouts.textures, + descriptorSetLayouts.textures, + descriptorSetLayouts.textures, + descriptorSetLayouts.materialUniform, + descriptorSetLayouts.ssbo + }; + VkPipelineLayoutCreateInfo pipelineLayoutCI = vks::initializers::pipelineLayoutCreateInfo(setLayouts.data(), static_cast(setLayouts.size())); + VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCI, nullptr, &pipelineLayouts.pbrLayout)); - vkUpdateDescriptorSets(device, 4, writeDescriptorSets.data(), 0, nullptr); - - for (auto& material : glTFModel.materials) - { - const VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayouts.materialUniform, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &material.materialData.descriptorSet)); - VkWriteDescriptorSet writeDescriptorSet = vks::initializers::writeDescriptorSet( - material.materialData.descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &material.materialData.buffer.descriptor); - vkUpdateDescriptorSets(device, 1, &writeDescriptorSet, 0, nullptr); + // Descriptor set for scene matrices + VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayouts.matrices, 1); + VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet)); + std::vector writeDescriptorSets = + { + vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &shaderData.buffer.descriptor), + vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &ibltextures.irradianceCube.descriptor), + vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2, &ibltextures.lutBrdf.descriptor), + vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 3, &ibltextures.prefilteredCube.descriptor), + }; + vkUpdateDescriptorSets(device, 4, writeDescriptorSets.data(), 0, nullptr); + + for (auto& material : glTFModel.materials) + { + const VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayouts.materialUniform, 1); + VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &material.materialData.descriptorSet)); + VkWriteDescriptorSet writeDescriptorSet = vks::initializers::writeDescriptorSet( + material.materialData.descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &material.materialData.buffer.descriptor); + vkUpdateDescriptorSets(device, 1, &writeDescriptorSet, 0, nullptr); + } + + // Descriptor sets for materials + for (auto& image : glTFModel.images) { + const VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayouts.textures, 1); + VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &image.descriptorSet)); + VkWriteDescriptorSet writeDescriptorSet = vks::initializers::writeDescriptorSet(image.descriptorSet, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 0, &image.texture.descriptor); + vkUpdateDescriptorSets(device, 1, &writeDescriptorSet, 0, nullptr); + } + { + const VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayouts.ssbo, 1); + VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &skinDescriptorSet)); + VkWriteDescriptorSet writeDescriptorSet = vks::initializers::writeDescriptorSet(skinDescriptorSet, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 0, &shaderData.skinSSBO.descriptor); + vkUpdateDescriptorSets(device, 1, &writeDescriptorSet, 0, nullptr); + } } + //Tone Mapping pipeline layout + { + auto pipelineLayoutCI = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayouts.textures, 1); + VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCI, nullptr, &pipelineLayouts.tonemappingLayout)); - // Descriptor sets for materials - for (auto& image : glTFModel.images) { const VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayouts.textures, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &image.descriptorSet)); - VkWriteDescriptorSet writeDescriptorSet = vks::initializers::writeDescriptorSet(image.descriptorSet, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 0, &image.texture.descriptor); + VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &tonemappingDescriptorSet)); + + auto imageInfo = vks::initializers::descriptorImageInfo(colorSampler, pbrFrameBuffer.color.imageView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + VkWriteDescriptorSet writeDescriptorSet = vks::initializers::writeDescriptorSet(tonemappingDescriptorSet, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 0, &imageInfo); vkUpdateDescriptorSets(device, 1, &writeDescriptorSet, 0, nullptr); } - { - const VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayouts.ssbo, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &skinDescriptorSet)); - VkWriteDescriptorSet writeDescriptorSet = vks::initializers::writeDescriptorSet(skinDescriptorSet, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 0, &shaderData.skinSSBO.descriptor); - vkUpdateDescriptorSets(device, 1, &writeDescriptorSet, 0, nullptr); - } - - //Tone Mapping pipeline layout - { - auto pipelineLayoutCI = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayouts.textures, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCI, nullptr, &pipelineLayouts.tonemappingLayout)); - const VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayouts.textures, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &tonemappingDescriptorSet)); - - auto imageInfo = vks::initializers::descriptorImageInfo(colorSampler, pbrFrameBuffer.color.imageView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - VkWriteDescriptorSet writeDescriptorSet = vks::initializers::writeDescriptorSet(tonemappingDescriptorSet, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 0, &imageInfo); - vkUpdateDescriptorSets(device, 1, &writeDescriptorSet, 0, nullptr); - } - } void VulkanExample::preparePipelines() @@ -1076,10 +981,10 @@ void VulkanExample::getEnabledFeatures() VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.wireframe)); } //Create Tone Mapping render pipeline - prepareToneMappingPipeline(); + CreateToneMappingPipeline(); } - void VulkanExample::prepareToneMappingPipeline() + void VulkanExample::CreateToneMappingPipeline() { if (pipelines.toneMapping != VK_NULL_HANDLE) { @@ -1087,16 +992,17 @@ void VulkanExample::getEnabledFeatures() pipelines.toneMapping = VK_NULL_HANDLE; } VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCI = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationStateCI = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_BACK_BIT, VK_FRONT_FACE_COUNTER_CLOCKWISE, 0); + VkPipelineRasterizationStateCreateInfo rasterizationStateCI = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_NONE, VK_FRONT_FACE_COUNTER_CLOCKWISE, 0); VkPipelineColorBlendAttachmentState blendAttachmentStateCI = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); VkPipelineColorBlendStateCreateInfo colorBlendStateCI = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentStateCI); - VkPipelineDepthStencilStateCreateInfo depthStencilStateCI = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL); + VkPipelineDepthStencilStateCreateInfo depthStencilStateCI = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_FALSE, VK_FALSE, VK_COMPARE_OP_LESS_OR_EQUAL); VkPipelineViewportStateCreateInfo viewportStateCI = vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); VkPipelineMultisampleStateCreateInfo multisampleStateCI = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT, 0); const std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; VkPipelineDynamicStateCreateInfo dynamicStateCI = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables.data(), static_cast(dynamicStateEnables.size()), 0); VkPipelineVertexInputStateCreateInfo emptyInputState = vks::initializers::pipelineVertexInputStateCreateInfo(); + const std::string fragPath = ToneMapping ? "homework1/tonemapping_enable.frag.spv" : "homework1/tonemapping_disable.frag.spv"; std::array shaderStages = { loadShader(getHomeworkShadersPath() + "homework1/genbrdflut.vert.spv", VK_SHADER_STAGE_VERTEX_BIT), @@ -1118,55 +1024,10 @@ void VulkanExample::getEnabledFeatures() VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.toneMapping)); } - // Prepare and initialize uniform buffer containing shader uniforms - void VulkanExample::prepareUniformBuffers() - { - // Vertex shader uniform buffer block - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &shaderData.buffer, - sizeof(shaderData.values))); - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &shaderData.skinSSBO, - sizeof(glm::mat4) * glTFModel.nodeCount)); - // Map persistent - VK_CHECK_RESULT(shaderData.buffer.map()); - VK_CHECK_RESULT(shaderData.skinSSBO.map()); - - for (auto& material : glTFModel.materials) - { - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &material.materialData.buffer, - sizeof(VulkanglTFModel::MaterialData::Values), - &material.materialData.values - )); - - } - - - - updateUniformBuffers(); - } - - void VulkanExample::updateUniformBuffers() - { - shaderData.values.projection = camera.matrices.perspective; - shaderData.values.model = camera.matrices.view; - shaderData.values.viewPos = camera.viewPos; - shaderData.values.bFlagSet.x = normalMapping; - shaderData.values.bFlagSet.y = pbrEnabled; - - memcpy(shaderData.buffer.mapped, &shaderData.values, sizeof(shaderData.values)); - } - -// --------- BRDF LUT precompute preparation ---------------- - void VulkanExample::generateIrradianceCubemap() + //----------------------------Prepare precompute Lighting or BRDF LUT-----------------------------------------------// + //Irradiance map for diffuse lighting + void VulkanExample::GenerateIrradianceCubemap() { auto tStart = std::chrono::high_resolution_clock::now(); @@ -1187,8 +1048,6 @@ void VulkanExample::getEnabledFeatures() imageCI.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; imageCI.flags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; VK_CHECK_RESULT(vkCreateImage(device, &imageCI, nullptr, &ibltextures.irradianceCube.image)) - - // allocate memory for irradiance cube map VkMemoryAllocateInfo memAlloc = vks::initializers::memoryAllocateInfo(); VkMemoryRequirements memReqs; vkGetImageMemoryRequirements(device, ibltextures.irradianceCube.image, &memReqs); @@ -1196,8 +1055,6 @@ void VulkanExample::getEnabledFeatures() memAlloc.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &ibltextures.irradianceCube.deviceMemory)) VK_CHECK_RESULT(vkBindImageMemory(device, ibltextures.irradianceCube.image, ibltextures.irradianceCube.deviceMemory, 0)) - - VkImageViewCreateInfo viewCI = vks::initializers::imageViewCreateInfo(); viewCI.viewType = VK_IMAGE_VIEW_TYPE_CUBE; viewCI.format = format; @@ -1208,7 +1065,6 @@ void VulkanExample::getEnabledFeatures() viewCI.image = ibltextures.irradianceCube.image; VK_CHECK_RESULT(vkCreateImageView(device, &viewCI, nullptr, &ibltextures.irradianceCube.view)) - // set up sampler and image view VkSamplerCreateInfo samplerCI = vks::initializers::samplerCreateInfo(); samplerCI.magFilter = VK_FILTER_LINEAR; samplerCI.minFilter = VK_FILTER_LINEAR; @@ -1226,18 +1082,17 @@ void VulkanExample::getEnabledFeatures() ibltextures.irradianceCube.descriptor.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; ibltextures.irradianceCube.device = vulkanDevice; - //Setup Framebuffer and so on - VkAttachmentDescription attachDescription = {}; - attachDescription.format = format; - attachDescription.samples = VK_SAMPLE_COUNT_1_BIT; - attachDescription.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - attachDescription.storeOp = VK_ATTACHMENT_STORE_OP_STORE; - attachDescription.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - attachDescription.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attachDescription.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - attachDescription.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - + VkAttachmentDescription attDesc = {}; + attDesc.format = format; + attDesc.samples = VK_SAMPLE_COUNT_1_BIT; + attDesc.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; + attDesc.storeOp = VK_ATTACHMENT_STORE_OP_STORE; + attDesc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + attDesc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + attDesc.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + attDesc.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + VkAttachmentReference colorReference = { 0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL }; VkSubpassDescription subpassDescription = {}; subpassDescription.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; @@ -1259,10 +1114,10 @@ void VulkanExample::getEnabledFeatures() dependencies[1].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; dependencies[1].dstAccessMask = VK_ACCESS_MEMORY_READ_BIT; dependencies[1].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; - //set up render pass + VkRenderPassCreateInfo renderPassCI = vks::initializers::renderPassCreateInfo(); renderPassCI.attachmentCount = 1; - renderPassCI.pAttachments = &attachDescription; + renderPassCI.pAttachments = &attDesc; renderPassCI.subpassCount = 1; renderPassCI.pSubpasses = &subpassDescription; renderPassCI.dependencyCount = 2; @@ -1270,89 +1125,87 @@ void VulkanExample::getEnabledFeatures() VkRenderPass renderpass; VK_CHECK_RESULT(vkCreateRenderPass(device, &renderPassCI, nullptr, &renderpass)); - // create offscreen image - VkImageCreateInfo imageCreateInfo = vks::initializers::imageCreateInfo(); - imageCreateInfo.imageType = VK_IMAGE_TYPE_2D; - imageCreateInfo.format = format; - imageCreateInfo.extent.width = dim; - imageCreateInfo.extent.height = dim; - imageCreateInfo.extent.depth = 1; - imageCreateInfo.mipLevels = 1; - imageCreateInfo.arrayLayers = 1; - imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT; - imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL; - imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - imageCreateInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT; - imageCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - VK_CHECK_RESULT(vkCreateImage(device, &imageCreateInfo, nullptr, &offscreen.image)) + { + VkImageCreateInfo imageCreateInfo = vks::initializers::imageCreateInfo(); + imageCreateInfo.imageType = VK_IMAGE_TYPE_2D; + imageCreateInfo.format = format; + imageCreateInfo.extent.width = dim; + imageCreateInfo.extent.height = dim; + imageCreateInfo.extent.depth = 1; + imageCreateInfo.mipLevels = 1; + imageCreateInfo.arrayLayers = 1; + imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT; + imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL; + imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + imageCreateInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT; + imageCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + VK_CHECK_RESULT(vkCreateImage(device, &imageCreateInfo, nullptr, &offscreen.image)) - // allocate memory - VkMemoryAllocateInfo imageCIMemAlloc = vks::initializers::memoryAllocateInfo(); - VkMemoryRequirements imageCIMemReqs; - vkGetImageMemoryRequirements(device, offscreen.image, &imageCIMemReqs); - imageCIMemAlloc.allocationSize = imageCIMemReqs.size; - imageCIMemAlloc.memoryTypeIndex = vulkanDevice->getMemoryType(imageCIMemReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - VK_CHECK_RESULT(vkAllocateMemory(device, &imageCIMemAlloc, nullptr, &offscreen.memory)) - VK_CHECK_RESULT(vkBindImageMemory(device, offscreen.image, offscreen.memory, 0)) + VkMemoryAllocateInfo memAlloc = vks::initializers::memoryAllocateInfo(); + VkMemoryRequirements memReqs; + vkGetImageMemoryRequirements(device, offscreen.image, &memReqs); + memAlloc.allocationSize = memReqs.size; + memAlloc.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &offscreen.memory)) + VK_CHECK_RESULT(vkBindImageMemory(device, offscreen.image, offscreen.memory, 0)) - // create color image view - VkImageViewCreateInfo colorImageView = vks::initializers::imageViewCreateInfo(); - colorImageView.viewType = VK_IMAGE_VIEW_TYPE_2D; - colorImageView.format = format; - colorImageView.flags = 0; - colorImageView.subresourceRange = {}; - colorImageView.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - colorImageView.subresourceRange.baseMipLevel = 0; - colorImageView.subresourceRange.levelCount = 1; - colorImageView.subresourceRange.baseArrayLayer = 0; - colorImageView.subresourceRange.layerCount = 1; - colorImageView.image = offscreen.image; - VK_CHECK_RESULT(vkCreateImageView(device, &colorImageView, nullptr, &offscreen.view)) + VkImageViewCreateInfo colorImageView = vks::initializers::imageViewCreateInfo(); + colorImageView.viewType = VK_IMAGE_VIEW_TYPE_2D; + colorImageView.format = format; + colorImageView.flags = 0; + colorImageView.subresourceRange = {}; + colorImageView.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + colorImageView.subresourceRange.baseMipLevel = 0; + colorImageView.subresourceRange.levelCount = 1; + colorImageView.subresourceRange.baseArrayLayer = 0; + colorImageView.subresourceRange.layerCount = 1; + colorImageView.image = offscreen.image; + VK_CHECK_RESULT(vkCreateImageView(device, &colorImageView, nullptr, &offscreen.view)) - // set up framebuffer for offscreen image - VkFramebufferCreateInfo fbufCreateInfo = vks::initializers::framebufferCreateInfo(); - fbufCreateInfo.renderPass = renderpass; - fbufCreateInfo.attachmentCount = 1; - fbufCreateInfo.pAttachments = &offscreen.view; - fbufCreateInfo.width = dim; - fbufCreateInfo.height = dim; - fbufCreateInfo.layers = 1; - VK_CHECK_RESULT(vkCreateFramebuffer(device, &fbufCreateInfo, nullptr, &offscreen.framebuffer)) + VkFramebufferCreateInfo fbufCreateInfo = vks::initializers::framebufferCreateInfo(); + fbufCreateInfo.renderPass = renderpass; + fbufCreateInfo.attachmentCount = 1; + fbufCreateInfo.pAttachments = &offscreen.view; + fbufCreateInfo.width = dim; + fbufCreateInfo.height = dim; + fbufCreateInfo.layers = 1; + VK_CHECK_RESULT(vkCreateFramebuffer(device, &fbufCreateInfo, nullptr, &offscreen.framebuffer)) - VkCommandBuffer layoutCmd = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); - vks::tools::setImageLayout( - layoutCmd, - offscreen.image, - VK_IMAGE_ASPECT_COLOR_BIT, - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); - vulkanDevice->flushCommandBuffer(layoutCmd, queue, true); - - // create descriptor set layout + VkCommandBuffer layoutCmd = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); + vks::tools::setImageLayout( + layoutCmd, + offscreen.image, + VK_IMAGE_ASPECT_COLOR_BIT, + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + vulkanDevice->flushCommandBuffer(layoutCmd, queue, true); + } VkDescriptorSetLayout descriptorsetlayout; std::vector setLayoutBindings = - { - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 0), - }; + { + vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 0), + }; VkDescriptorSetLayoutCreateInfo descriptorsetlayoutCI = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorsetlayoutCI, nullptr, &descriptorsetlayout)); - // allocate pool + std::vector poolSizes = { vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1) }; VkDescriptorPoolCreateInfo descriptorPoolCI = vks::initializers::descriptorPoolCreateInfo(poolSizes, 2); VkDescriptorPool descriptorpool; VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolCI, nullptr, &descriptorpool)); - //write to poos + VkDescriptorSet descriptorset; - VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorpool, &descriptorsetlayout, 1); + VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorpool, &descriptorsetlayout, 1); VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorset)); VkWriteDescriptorSet writeDescriptorSet = vks::initializers::writeDescriptorSet(descriptorset, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 0, &ibltextures.skyboxCube.descriptor); vkUpdateDescriptorSets(device, 1, &writeDescriptorSet, 0, nullptr); - // push matrix + + + VkPipelineLayout pipelinelayout; std::vector pushConstantRanges = - { - vks::initializers::pushConstantRange(VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, sizeof(IrradiancePushBlock), 0) - }; + { + vks::initializers::pushConstantRange(VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, sizeof(IrradiancePushBlock), 0) + }; VkPipelineLayoutCreateInfo pipelineLayoutCI = vks::initializers::pipelineLayoutCreateInfo(&descriptorsetlayout, 1); pipelineLayoutCI.pushConstantRangeCount = 1; pipelineLayoutCI.pPushConstantRanges = pushConstantRanges.data(); @@ -1370,13 +1223,17 @@ void VulkanExample::getEnabledFeatures() VkPipelineDynamicStateCreateInfo dynamicState = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); std::array shaderStages; - const std::vector vertexInputBindings = + const std::vector vertexInputBindings = { vks::initializers::vertexInputBindingDescription(0, sizeof(VulkanglTFModel::Vertex), VK_VERTEX_INPUT_RATE_VERTEX), }; const std::vector vertexInputAttributes = { vks::initializers::vertexInputAttributeDescription(0, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(VulkanglTFModel::Vertex, pos)), // Location 0: Position + //vks::initializers::vertexInputAttributeDescription(0, 1, VK_FORMAT_R32G32B32_SFLOAT, offsetof(VulkanglTFModel::Vertex, normal)),// Location 1: Normal + //vks::initializers::vertexInputAttributeDescription(0, 2, VK_FORMAT_R32G32B32_SFLOAT, offsetof(VulkanglTFModel::Vertex, uv)), // Location 2: Texture coordinates + //vks::initializers::vertexInputAttributeDescription(0, 3, VK_FORMAT_R32G32B32_SFLOAT, offsetof(VulkanglTFModel::Vertex, color)), // Location 3: Color + //vks::initializers::vertexInputAttributeDescription(0, 4, VK_FORMAT_R32G32B32_SFLOAT, offsetof(VulkanglTFModel::Vertex, tangent)), // Location 4 : Tangent }; VkPipelineVertexInputStateCreateInfo vertexInputStateCI = vks::initializers::pipelineVertexInputStateCreateInfo(); vertexInputStateCI.vertexBindingDescriptionCount = static_cast(vertexInputBindings.size()); @@ -1402,7 +1259,7 @@ void VulkanExample::getEnabledFeatures() VkPipeline pipeline; VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipeline)); - // offscreen Render pass begin + //Render VkClearValue clearValues[1]; clearValues[0].color = { { 0.0f, 0.0f, 0.2f, 0.0f } }; VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); @@ -1431,38 +1288,38 @@ void VulkanExample::getEnabledFeatures() VkCommandBuffer cmdBuf = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); VkViewport viewport = vks::initializers::viewport((float)dim, (float)dim, 0.0f, 1.0f); VkRect2D scissor = vks::initializers::rect2D(dim, dim, 0, 0); - + vkCmdSetViewport(cmdBuf, 0, 1, &viewport); vkCmdSetScissor(cmdBuf, 0, 1, &scissor); - + VkImageSubresourceRange subresourceRange = {}; subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; subresourceRange.baseMipLevel = 0; subresourceRange.levelCount = numMips; subresourceRange.layerCount = 6; - + vks::tools::setImageLayout( - cmdBuf, - ibltextures.irradianceCube.image, - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - subresourceRange); + cmdBuf, + ibltextures.irradianceCube.image, + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + subresourceRange); - for (uint32_t m = 0; m < numMips; ++m) + for(uint32_t m = 0; m < numMips; ++m) { - for (uint32_t f = 0; f < 6; ++f) + for(uint32_t f = 0; f < 6; ++f) { viewport.width = static_cast(dim * std::pow(0.5f, m)); viewport.height = static_cast(dim * std::pow(0.5f, m)); vkCmdSetViewport(cmdBuf, 0, 1, &viewport); // Render scene from cube face's point of view vkCmdBeginRenderPass(cmdBuf, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - irradinacePushBlock.mvp = glm::perspective((float)(M_PI / 2.0), 1.0f, 0.1f, 512.0f) * matrices[f]; - vkCmdPushConstants(cmdBuf, pipelinelayout, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(IrradiancePushBlock), &irradinacePushBlock); - + irradiancePushBlock.mvp = glm::perspective((float)(M_PI / 2.0), 1.0f, 0.1f, 512.0f) * matrices[f]; + vkCmdPushConstants(cmdBuf, pipelinelayout, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(IrradiancePushBlock), &irradiancePushBlock); + vkCmdBindPipeline(cmdBuf, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); vkCmdBindDescriptorSets(cmdBuf, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelinelayout, 0, 1, &descriptorset, 0, NULL); - skyboxModel.draw(cmdBuf, pipelinelayout); + skyboxModel.draw(cmdBuf, pipelinelayout, false); vkCmdEndRenderPass(cmdBuf); vks::tools::setImageLayout( @@ -1500,7 +1357,7 @@ void VulkanExample::getEnabledFeatures() VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL - ); + ); } } @@ -1524,11 +1381,9 @@ void VulkanExample::getEnabledFeatures() auto tEnd = std::chrono::high_resolution_clock::now(); auto tDiff = std::chrono::duration(tEnd - tStart).count(); std::cout << "Generating irradiance cube with " << numMips << " mip levels took " << tDiff << " ms" << std::endl; - } - - void VulkanExample::generatePrefilteredCubemap() + void VulkanExample::GeneratePrefilteredCubemap() { auto tStart = std::chrono::high_resolution_clock::now(); @@ -1633,6 +1488,12 @@ void VulkanExample::getEnabledFeatures() VkRenderPass renderpass; VK_CHECK_RESULT(vkCreateRenderPass(device, &renderPassCI, nullptr, &renderpass)); + struct { + VkImage image; + VkImageView view; + VkDeviceMemory memory; + VkFramebuffer framebuffer; + } offscreen; //framebuffer { // Color attachment @@ -1691,218 +1552,223 @@ void VulkanExample::getEnabledFeatures() vulkanDevice->flushCommandBuffer(layoutCmd, queue, true); } - // Descriptors - VkDescriptorSetLayout descriptorsetlayout; - std::vector setLayoutBindings = { - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 0), - }; - VkDescriptorSetLayoutCreateInfo descriptorsetlayoutCI = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorsetlayoutCI, nullptr, &descriptorsetlayout)); + // Descriptors + VkDescriptorSetLayout descriptorsetlayout; + std::vector setLayoutBindings = { + vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 0), + }; + VkDescriptorSetLayoutCreateInfo descriptorsetlayoutCI = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); + VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorsetlayoutCI, nullptr, &descriptorsetlayout)); - // Descriptor Pool - std::vector poolSizes = { vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1) }; - VkDescriptorPoolCreateInfo descriptorPoolCI = vks::initializers::descriptorPoolCreateInfo(poolSizes, 2); - VkDescriptorPool descriptorpool; - VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolCI, nullptr, &descriptorpool)); + // Descriptor Pool + std::vector poolSizes = { vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1) }; + VkDescriptorPoolCreateInfo descriptorPoolCI = vks::initializers::descriptorPoolCreateInfo(poolSizes, 2); + VkDescriptorPool descriptorpool; + VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolCI, nullptr, &descriptorpool)); - VkDescriptorSet descriptorset; - VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorpool, &descriptorsetlayout, 1); - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorset)); - VkWriteDescriptorSet writeDescriptorSet = vks::initializers::writeDescriptorSet(descriptorset, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 0, &ibltextures.skyboxCube.descriptor); - vkUpdateDescriptorSets(device, 1, &writeDescriptorSet, 0, nullptr); + VkDescriptorSet descriptorset; + VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorpool, &descriptorsetlayout, 1); + VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorset)); + VkWriteDescriptorSet writeDescriptorSet = vks::initializers::writeDescriptorSet(descriptorset, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 0, &ibltextures.skyboxCube.descriptor); + vkUpdateDescriptorSets(device, 1, &writeDescriptorSet, 0, nullptr); + struct PushBlock { + glm::mat4 mvp; + float roughness; + uint32_t numSamples = 32u; + } pushBlock; - std::vector pushConstantRanges = { - vks::initializers::pushConstantRange(VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, sizeof(PrefilterPushBlock), 0), - }; - VkPipelineLayoutCreateInfo pipelineLayoutCI = vks::initializers::pipelineLayoutCreateInfo(&descriptorsetlayout, 1); - pipelineLayoutCI.pushConstantRangeCount = 1; - pipelineLayoutCI.pPushConstantRanges = pushConstantRanges.data(); - VkPipelineLayout pipelinelayout; - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCI, nullptr, &pipelinelayout)); + std::vector pushConstantRanges = { + vks::initializers::pushConstantRange(VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, sizeof(PushBlock), 0), + }; + VkPipelineLayoutCreateInfo pipelineLayoutCI = vks::initializers::pipelineLayoutCreateInfo(&descriptorsetlayout, 1); + pipelineLayoutCI.pushConstantRangeCount = 1; + pipelineLayoutCI.pPushConstantRanges = pushConstantRanges.data(); + VkPipelineLayout pipelinelayout; + VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCI, nullptr, &pipelinelayout)); - VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationState = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_NONE, VK_FRONT_FACE_COUNTER_CLOCKWISE); - VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendState = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); - VkPipelineDepthStencilStateCreateInfo depthStencilState = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_FALSE, VK_FALSE, VK_COMPARE_OP_LESS_OR_EQUAL); - VkPipelineViewportStateCreateInfo viewportState = vks::initializers::pipelineViewportStateCreateInfo(1, 1); - VkPipelineMultisampleStateCreateInfo multisampleState = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT); - std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; - VkPipelineDynamicStateCreateInfo dynamicState = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); - std::array shaderStages; + VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); + VkPipelineRasterizationStateCreateInfo rasterizationState = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_NONE, VK_FRONT_FACE_COUNTER_CLOCKWISE); + VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); + VkPipelineColorBlendStateCreateInfo colorBlendState = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); + VkPipelineDepthStencilStateCreateInfo depthStencilState = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_FALSE, VK_FALSE, VK_COMPARE_OP_LESS_OR_EQUAL); + VkPipelineViewportStateCreateInfo viewportState = vks::initializers::pipelineViewportStateCreateInfo(1, 1); + VkPipelineMultisampleStateCreateInfo multisampleState = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT); + std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; + VkPipelineDynamicStateCreateInfo dynamicState = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); + std::array shaderStages; - const std::vector vertexInputBindings = + const std::vector vertexInputBindings = + { + vks::initializers::vertexInputBindingDescription(0, sizeof(VulkanglTFModel::Vertex), VK_VERTEX_INPUT_RATE_VERTEX), + }; + + const std::vector vertexInputAttributes = { + vks::initializers::vertexInputAttributeDescription(0, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(VulkanglTFModel::Vertex, pos)), // Location 0: Position + }; + VkPipelineVertexInputStateCreateInfo vertexInputStateCI = vks::initializers::pipelineVertexInputStateCreateInfo(); + vertexInputStateCI.vertexBindingDescriptionCount = static_cast(vertexInputBindings.size()); + vertexInputStateCI.pVertexBindingDescriptions = vertexInputBindings.data(); + vertexInputStateCI.vertexAttributeDescriptionCount = static_cast(vertexInputAttributes.size()); + vertexInputStateCI.pVertexAttributeDescriptions = vertexInputAttributes.data(); + + VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(pipelinelayout, renderpass); + pipelineCI.pInputAssemblyState = &inputAssemblyState; + pipelineCI.pRasterizationState = &rasterizationState; + pipelineCI.pColorBlendState = &colorBlendState; + pipelineCI.pMultisampleState = &multisampleState; + pipelineCI.pViewportState = &viewportState; + pipelineCI.pDepthStencilState = &depthStencilState; + pipelineCI.pDynamicState = &dynamicState; + pipelineCI.stageCount = 2; + pipelineCI.pStages = shaderStages.data(); + pipelineCI.renderPass = renderpass; + pipelineCI.pVertexInputState = &vertexInputStateCI; + + shaderStages[0] = loadShader(getHomeworkShadersPath() + "homework1/filtercube.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); + shaderStages[1] = loadShader(getHomeworkShadersPath() + "homework1/prefilterenvmap.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); + + VkPipeline pipeline; + VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipeline)); + + //Render & build cmd + VkClearValue clearValues[1]; + clearValues[0].color = { { 0.0f, 0.0f, 0.2f, 0.0f } }; + + VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); + // Reuse render pass from example pass + renderPassBeginInfo.renderPass = renderpass; + renderPassBeginInfo.framebuffer = offscreen.framebuffer; + renderPassBeginInfo.renderArea.extent.width = dim; + renderPassBeginInfo.renderArea.extent.height = dim; + renderPassBeginInfo.clearValueCount = 1; + renderPassBeginInfo.pClearValues = clearValues; + + std::vector matrices = { + // POSITIVE_X + glm::rotate(glm::rotate(glm::mat4(1.0f), glm::radians(90.0f), glm::vec3(0.0f, 1.0f, 0.0f)), glm::radians(180.0f), glm::vec3(1.0f, 0.0f, 0.0f)), + // NEGATIVE_X + glm::rotate(glm::rotate(glm::mat4(1.0f), glm::radians(-90.0f), glm::vec3(0.0f, 1.0f, 0.0f)), glm::radians(180.0f), glm::vec3(1.0f, 0.0f, 0.0f)), + // POSITIVE_Y + glm::rotate(glm::mat4(1.0f), glm::radians(-90.0f), glm::vec3(1.0f, 0.0f, 0.0f)), + // NEGATIVE_Y + glm::rotate(glm::mat4(1.0f), glm::radians(90.0f), glm::vec3(1.0f, 0.0f, 0.0f)), + // POSITIVE_Z + glm::rotate(glm::mat4(1.0f), glm::radians(180.0f), glm::vec3(1.0f, 0.0f, 0.0f)), + // NEGATIVE_Z + glm::rotate(glm::mat4(1.0f), glm::radians(180.0f), glm::vec3(0.0f, 0.0f, 1.0f)), + }; + VkCommandBuffer cmdBuf = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); + + VkViewport viewport = vks::initializers::viewport((float)dim, (float)dim, 0.0f, 1.0f); + VkRect2D scissor = vks::initializers::rect2D(dim, dim, 0, 0); + + vkCmdSetViewport(cmdBuf, 0, 1, &viewport); + vkCmdSetScissor(cmdBuf, 0, 1, &scissor); + + VkImageSubresourceRange subresourceRange = {}; + subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + subresourceRange.baseMipLevel = 0; + subresourceRange.levelCount = numMips; + subresourceRange.layerCount = 6; + + vks::tools::setImageLayout( + cmdBuf, + ibltextures.prefilteredCube.image, + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + subresourceRange); + + for (uint32_t m = 0; m < numMips; ++m) + { + //mip level according to roughness + pushBlock.roughness = float(m) / float(numMips - 1); + for (uint32_t f = 0; f < 6; ++f) { - vks::initializers::vertexInputBindingDescription(0, sizeof(VulkanglTFModel::Vertex), VK_VERTEX_INPUT_RATE_VERTEX), - }; + viewport.width = static_cast(dim * std::pow(0.5f, m)); + viewport.height = static_cast(dim * std::pow(0.5f, m)); + vkCmdSetViewport(cmdBuf, 0, 1, &viewport); + // Render scene from cube face's point of view + vkCmdBeginRenderPass(cmdBuf, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - const std::vector vertexInputAttributes = { - vks::initializers::vertexInputAttributeDescription(0, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(VulkanglTFModel::Vertex, pos)), // Location 0: Position - }; - VkPipelineVertexInputStateCreateInfo vertexInputStateCI = vks::initializers::pipelineVertexInputStateCreateInfo(); - vertexInputStateCI.vertexBindingDescriptionCount = static_cast(vertexInputBindings.size()); - vertexInputStateCI.pVertexBindingDescriptions = vertexInputBindings.data(); - vertexInputStateCI.vertexAttributeDescriptionCount = static_cast(vertexInputAttributes.size()); - vertexInputStateCI.pVertexAttributeDescriptions = vertexInputAttributes.data(); + // Update shader push constant block + pushBlock.mvp = glm::perspective((float)(M_PI / 2.0), 1.0f, 0.1f, 512.0f) * matrices[f]; - VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(pipelinelayout, renderpass); - pipelineCI.pInputAssemblyState = &inputAssemblyState; - pipelineCI.pRasterizationState = &rasterizationState; - pipelineCI.pColorBlendState = &colorBlendState; - pipelineCI.pMultisampleState = &multisampleState; - pipelineCI.pViewportState = &viewportState; - pipelineCI.pDepthStencilState = &depthStencilState; - pipelineCI.pDynamicState = &dynamicState; - pipelineCI.stageCount = 2; - pipelineCI.pStages = shaderStages.data(); - pipelineCI.renderPass = renderpass; - pipelineCI.pVertexInputState = &vertexInputStateCI; + vkCmdPushConstants(cmdBuf, pipelinelayout, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(PushBlock), &pushBlock); + vkCmdBindPipeline(cmdBuf, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); + vkCmdBindDescriptorSets(cmdBuf, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelinelayout, 0, 1, &descriptorset, 0, nullptr); + skyboxModel.draw(cmdBuf, pipelinelayout, false); + vkCmdEndRenderPass(cmdBuf); - shaderStages[0] = loadShader(getHomeworkShadersPath() + "homework1/filtercube.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getHomeworkShadersPath() + "homework1/prefilterenvmap.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); + vks::tools::setImageLayout( + cmdBuf, + offscreen.image, + VK_IMAGE_ASPECT_COLOR_BIT, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); - VkPipeline pipeline; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipeline)); + VkImageCopy copyRegion{}; + copyRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + copyRegion.srcSubresource.baseArrayLayer = 0; + copyRegion.srcSubresource.mipLevel = 0; + copyRegion.srcSubresource.layerCount = 1; + copyRegion.srcOffset = { 0, 0, 0 }; - //Render & build cmd - VkClearValue clearValues[1]; - clearValues[0].color = { { 0.0f, 0.0f, 0.2f, 0.0f } }; + copyRegion.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + copyRegion.dstSubresource.baseArrayLayer = f; + copyRegion.dstSubresource.mipLevel = m; + copyRegion.dstSubresource.layerCount = 1; + copyRegion.dstOffset = { 0, 0, 0 }; - VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); - // Reuse render pass from example pass - renderPassBeginInfo.renderPass = renderpass; - renderPassBeginInfo.framebuffer = offscreen.framebuffer; - renderPassBeginInfo.renderArea.extent.width = dim; - renderPassBeginInfo.renderArea.extent.height = dim; - renderPassBeginInfo.clearValueCount = 1; - renderPassBeginInfo.pClearValues = clearValues; + copyRegion.extent.width = static_cast(viewport.width); + copyRegion.extent.height = static_cast(viewport.height); + copyRegion.extent.depth = 1; - std::vector matrices = { - // POSITIVE_X - glm::rotate(glm::rotate(glm::mat4(1.0f), glm::radians(90.0f), glm::vec3(0.0f, 1.0f, 0.0f)), glm::radians(180.0f), glm::vec3(1.0f, 0.0f, 0.0f)), - // NEGATIVE_X - glm::rotate(glm::rotate(glm::mat4(1.0f), glm::radians(-90.0f), glm::vec3(0.0f, 1.0f, 0.0f)), glm::radians(180.0f), glm::vec3(1.0f, 0.0f, 0.0f)), - // POSITIVE_Y - glm::rotate(glm::mat4(1.0f), glm::radians(-90.0f), glm::vec3(1.0f, 0.0f, 0.0f)), - // NEGATIVE_Y - glm::rotate(glm::mat4(1.0f), glm::radians(90.0f), glm::vec3(1.0f, 0.0f, 0.0f)), - // POSITIVE_Z - glm::rotate(glm::mat4(1.0f), glm::radians(180.0f), glm::vec3(1.0f, 0.0f, 0.0f)), - // NEGATIVE_Z - glm::rotate(glm::mat4(1.0f), glm::radians(180.0f), glm::vec3(0.0f, 0.0f, 1.0f)), - }; - VkCommandBuffer cmdBuf = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); + vkCmdCopyImage( + cmdBuf, + offscreen.image, + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + ibltextures.prefilteredCube.image, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + 1, + ©Region); - VkViewport viewport = vks::initializers::viewport((float)dim, (float)dim, 0.0f, 1.0f); - VkRect2D scissor = vks::initializers::rect2D(dim, dim, 0, 0); - - vkCmdSetViewport(cmdBuf, 0, 1, &viewport); - vkCmdSetScissor(cmdBuf, 0, 1, &scissor); - - VkImageSubresourceRange subresourceRange = {}; - subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - subresourceRange.baseMipLevel = 0; - subresourceRange.levelCount = numMips; - subresourceRange.layerCount = 6; - - vks::tools::setImageLayout( - cmdBuf, - ibltextures.prefilteredCube.image, - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - subresourceRange); - - for (uint32_t m = 0; m < numMips; ++m) - { - //mip level according to roughness - prefilterPushBlock.roughness = float(m) / float(numMips - 1); - for (uint32_t f = 0; f < 6; ++f) - { - viewport.width = static_cast(dim * std::pow(0.5f, m)); - viewport.height = static_cast(dim * std::pow(0.5f, m)); - vkCmdSetViewport(cmdBuf, 0, 1, &viewport); - // Render scene from cube face's point of view - vkCmdBeginRenderPass(cmdBuf, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - // Update shader push constant block - prefilterPushBlock.mvp = glm::perspective((float)(M_PI / 2.0), 1.0f, 0.1f, 512.0f) * matrices[f]; - - vkCmdPushConstants(cmdBuf, pipelinelayout, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(PrefilterPushBlock), &prefilterPushBlock); - vkCmdBindPipeline(cmdBuf, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); - vkCmdBindDescriptorSets(cmdBuf, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelinelayout, 0, 1, &descriptorset, 0, nullptr); - skyboxModel.draw(cmdBuf, pipelinelayout); - vkCmdEndRenderPass(cmdBuf); - - vks::tools::setImageLayout( - cmdBuf, - offscreen.image, - VK_IMAGE_ASPECT_COLOR_BIT, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); - - VkImageCopy copyRegion{}; - copyRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - copyRegion.srcSubresource.baseArrayLayer = 0; - copyRegion.srcSubresource.mipLevel = 0; - copyRegion.srcSubresource.layerCount = 1; - copyRegion.srcOffset = { 0, 0, 0 }; - - copyRegion.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - copyRegion.dstSubresource.baseArrayLayer = f; - copyRegion.dstSubresource.mipLevel = m; - copyRegion.dstSubresource.layerCount = 1; - copyRegion.dstOffset = { 0, 0, 0 }; - - copyRegion.extent.width = static_cast(viewport.width); - copyRegion.extent.height = static_cast(viewport.height); - copyRegion.extent.depth = 1; - - vkCmdCopyImage( - cmdBuf, - offscreen.image, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - ibltextures.prefilteredCube.image, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - 1, - ©Region); - - //Reset frame buffer image layout - vks::tools::setImageLayout( - cmdBuf, - offscreen.image, - VK_IMAGE_ASPECT_COLOR_BIT, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); - } + //Reset frame buffer image layout + vks::tools::setImageLayout( + cmdBuf, + offscreen.image, + VK_IMAGE_ASPECT_COLOR_BIT, + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); } - - //Set format shader read - vks::tools::setImageLayout( - cmdBuf, - ibltextures.prefilteredCube.image, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, - subresourceRange); - - vulkanDevice->flushCommandBuffer(cmdBuf, queue); - - vkDestroyRenderPass(device, renderpass, nullptr); - vkDestroyFramebuffer(device, offscreen.framebuffer, nullptr); - vkFreeMemory(device, offscreen.memory, nullptr); - vkDestroyImageView(device, offscreen.view, nullptr); - vkDestroyImage(device, offscreen.image, nullptr); - vkDestroyDescriptorPool(device, descriptorpool, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorsetlayout, nullptr); - vkDestroyPipeline(device, pipeline, nullptr); - vkDestroyPipelineLayout(device, pipelinelayout, nullptr); - - auto tEnd = std::chrono::high_resolution_clock::now(); - auto tDiff = std::chrono::duration(tEnd - tStart).count(); - std::cout << "Generating pre-filtered enivornment cube with " << numMips << " mip levels took " << tDiff << " ms" << std::endl; } - void VulkanExample::generateBRDFLUT() + //Set format shader read + vks::tools::setImageLayout( + cmdBuf, + ibltextures.prefilteredCube.image, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + subresourceRange); + + vulkanDevice->flushCommandBuffer(cmdBuf, queue); + + vkDestroyRenderPass(device, renderpass, nullptr); + vkDestroyFramebuffer(device, offscreen.framebuffer, nullptr); + vkFreeMemory(device, offscreen.memory, nullptr); + vkDestroyImageView(device, offscreen.view, nullptr); + vkDestroyImage(device, offscreen.image, nullptr); + vkDestroyDescriptorPool(device, descriptorpool, nullptr); + vkDestroyDescriptorSetLayout(device, descriptorsetlayout, nullptr); + vkDestroyPipeline(device, pipeline, nullptr); + vkDestroyPipelineLayout(device, pipelinelayout, nullptr); + + auto tEnd = std::chrono::high_resolution_clock::now(); + auto tDiff = std::chrono::duration(tEnd - tStart).count(); + std::cout << "Generating pre-filtered enivornment cube with " << numMips << " mip levels took " << tDiff << " ms" << std::endl; +} + + void VulkanExample::GenerateBRDFLUT() { auto tStart = std::chrono::high_resolution_clock::now(); @@ -2105,13 +1971,16 @@ void VulkanExample::getEnabledFeatures() auto tEnd = std::chrono::high_resolution_clock::now(); auto tDiff = std::chrono::duration(tEnd - tStart).count(); std::cout << "Generating BRDF LUT took " << tDiff << " ms" << std::endl; -} - -//-------------------------- pbr precompute start ---------------------------------- - + } + //----------------------------End Precompute brick------------------------------------------------------------------// #pragma region pbr render pass setting - void VulkanExample::createAttachment(VkFormat format, VkImageUsageFlagBits usage, VulkanExample::FrameBufferAttachment* attachment, uint32_t width, uint32_t height) + void VulkanExample::createAttachment( + VkFormat format, + VkImageUsageFlagBits usage, + FrameBufferAttachment* attachment, + uint32_t width, + uint32_t height) { VkImageAspectFlags aspectMask = 0; VkImageUsageFlags imageUsage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT; @@ -2164,22 +2033,58 @@ void VulkanExample::getEnabledFeatures() imageView.image = attachment->image; VK_CHECK_RESULT(vkCreateImageView(device, &imageView, nullptr, &attachment->imageView)); } - #pragma endregion - -// ----------------------- pbr precompute end --------------------------------------- + // Prepare and initialize uniform buffer containing shader uniforms + void VulkanExample::prepareUniformBuffers() + { + // Vertex shader uniform buffer block + VK_CHECK_RESULT(vulkanDevice->createBuffer( + VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, + &shaderData.buffer, + sizeof(shaderData.values))); + VK_CHECK_RESULT(vulkanDevice->createBuffer( + VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, + &shaderData.skinSSBO, + sizeof(glm::mat4) * glTFModel.nodeCount)); + // Map persistent + VK_CHECK_RESULT(shaderData.buffer.map()); + VK_CHECK_RESULT(shaderData.skinSSBO.map()); + + for (auto& material : glTFModel.materials) + { + VK_CHECK_RESULT(vulkanDevice->createBuffer( + VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, + &material.materialData.buffer, + sizeof(VulkanglTFModel::MaterialData::Values), + &material.materialData.values)); + } + + updateUniformBuffers(); + } + + void VulkanExample::updateUniformBuffers() + { + shaderData.values.projection = camera.matrices.perspective; + shaderData.values.model = camera.matrices.view; + shaderData.values.viewPos = camera.viewPos; + shaderData.values.bFlagSet.x = normalMapping; + shaderData.values.bFlagSet.y = pbrEnabled; + memcpy(shaderData.buffer.mapped, &shaderData.values, sizeof(shaderData.values)); + } - void VulkanExample::prepare() { VulkanExampleBase::prepare(); loadAssets(); - generateBRDFLUT(); - generateIrradianceCubemap(); - generatePrefilteredCubemap(); + GenerateBRDFLUT(); + GenerateIrradianceCubemap(); + GeneratePrefilteredCubemap(); prepareUniformBuffers(); setupDescriptors(); preparePipelines(); @@ -2193,10 +2098,8 @@ void VulkanExample::getEnabledFeatures() if (camera.updated) { updateUniformBuffers(); } - if (!paused) - { - glTFModel.updateAnimation(frameTimer,shaderData.skinSSBO); - } + if(!paused) + glTFModel.updateAnimation(frameTimer, shaderData.skinSSBO); } void VulkanExample::viewChanged() @@ -2210,10 +2113,20 @@ void VulkanExample::getEnabledFeatures() if (overlay->checkBox("Wireframe", &wireframe)) { buildCommandBuffers(); } + if (overlay->checkBox("NormalMapping", &normalMapping)) + { + } + if (overlay->checkBox("ToneMapping", &ToneMapping)) + { + CreateToneMappingPipeline(); + } + if (overlay->checkBox("PbrIndirect", &pbrEnabled)) + { + } } if (overlay->header("Animation")) { - overlay->checkBox("pause", &paused); + overlay->checkBox("Pause", &paused); } } diff --git a/homework/homework1/homework1.h b/homework/homework1/homework1.h index 5b39c45..1385b9c 100644 --- a/homework/homework1/homework1.h +++ b/homework/homework1/homework1.h @@ -216,15 +216,15 @@ public: void loadMaterials(tinygltf::Model& input); Node* findNode(Node* parent, uint32_t index); Node* nodeFromIndex(uint32_t index); - void loadSkins(tinygltf::Model& input); + //void loadSkins(tinygltf::Model& input); void loadAnimations(tinygltf::Model& input); void loadNode(const tinygltf::Node& inputNode, const tinygltf::Model& input, VulkanglTFModel::Node* parent, uint32_t nodeIndex, std::vector& indexBuffer, std::vector& vertexBuffer); glm::mat4 getNodeMatrix(VulkanglTFModel::Node* node); void updateNodeMatrix(Node* node, std::vector& nodeMatrics); - void updateJoints(VulkanglTFModel::Node* node); - void updateAnimation(float deltaTime,vks::Buffer buffer); - void drawNode(VkCommandBuffer commandBuffer, VkPipelineLayout pipelineLayout, VulkanglTFModel::Node node); - void draw(VkCommandBuffer commandBuffer, VkPipelineLayout pipelineLayout); + //void updateJoints(VulkanglTFModel::Node* node); + void updateAnimation(float deltaTime, vks::Buffer& buffer); + void drawNode(VkCommandBuffer commandBuffer, VkPipelineLayout pipelineLayout, VulkanglTFModel::Node* node, bool bPushConstants); + void draw(VkCommandBuffer commandBuffer, VkPipelineLayout pipelineLayout, bool flag); }; class VulkanExample : public VulkanExampleBase @@ -344,7 +344,7 @@ public: // Sampling deltas float deltaPhi = (2.0f * float(M_PI)) / 180.0f; float deltaTheta = (0.5f * float(M_PI)) / 64.0f; - } irradinacePushBlock; + } irradiancePushBlock; struct PrefilterPushBlock { glm::mat4 mvp; @@ -383,7 +383,7 @@ public: shaderData.buffer.destroy(); shaderData.skinSSBO.destroy(); } - void loadglTFFile(std::string filename, VulkanglTFModel& model, bool bSkyboxFlag = false); + void loadglTFFile(std::string filename, VulkanglTFModel& model, bool bSkyboxFlag); virtual void getEnabledFeatures(); void createAttachment(VkFormat format, VkImageUsageFlagBits usage, FrameBufferAttachment* attachment, uint32_t width, uint32_t height); virtual void setupFrameBuffer(); @@ -391,10 +391,10 @@ public: void loadAssets(); void setupDescriptors(); void preparePipelines(); - void prepareToneMappingPipeline(); - void generateIrradianceCubemap(); - void generatePrefilteredCubemap(); - void generateBRDFLUT(); + void CreateToneMappingPipeline(); + void GenerateIrradianceCubemap(); + void GeneratePrefilteredCubemap(); + void GenerateBRDFLUT(); void prepareUniformBuffers(); void updateUniformBuffers(); void prepare();