pull/2/head
ink-soul 2023-05-17 16:50:09 +08:00
parent 2aa0ab76d1
commit 3532369f08
2 changed files with 84 additions and 63 deletions

27
CMakeSettings.json 100644
View File

@ -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": []
}
]
}

View File

@ -157,26 +157,26 @@ VulkanglTFModel::~VulkanglTFModel()
tinygltf::Animation glTFAnimation = input.animations[i]; tinygltf::Animation glTFAnimation = input.animations[i];
animations[i].name = glTFAnimation.name; animations[i].name = glTFAnimation.name;
// Samplers
animations[i].samplers.resize(glTFAnimation.samplers.size()); animations[i].samplers.resize(glTFAnimation.samplers.size());
for (size_t j = 0; j < glTFAnimation.samplers.size(); j++) for (size_t j = 0; j < glTFAnimation.samplers.size(); j++)
{ {
tinygltf::AnimationSampler glTFSampler = glTFAnimation.samplers[j]; tinygltf::AnimationSampler glTFSampler = glTFAnimation.samplers[j];
AnimationSampler& dstSampler = animations[i].samplers[j]; AnimationSampler& dstSampler = animations[i].samplers[j];
dstSampler.interpolation = glTFSampler.interpolation; dstSampler.interpolation = glTFSampler.interpolation;
//sample keyframes to input
// Read sampler keyframe input time values
{ {
const tinygltf::Accessor& accessor = input.accessors[glTFSampler.input]; const tinygltf::Accessor& accessor = input.accessors[glTFSampler.input];
const tinygltf::BufferView& bufferView = input.bufferViews[accessor.bufferView]; const tinygltf::BufferView& bufferView = input.bufferViews[accessor.bufferView];
const tinygltf::Buffer& buffer = input.buffers[bufferView.buffer]; 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]; const float* buf = static_cast<const float*>(dataPtr);
const float* buf = static_cast<const float*>(dataptr);
for (size_t index = 0; index < accessor.count; index++) for (size_t index = 0; index < accessor.count; index++)
{ {
dstSampler.inputs.push_back(buf[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) for (auto input : animations[i].samplers[j].inputs)
{ {
if (input < animations[i].start) 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::BufferView& bufferView = input.bufferViews[accessor.bufferView];
const tinygltf::Buffer& buffer = input.buffers[bufferView.buffer]; 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) switch (accessor.type)
{ {
case TINYGLTF_TYPE_VEC3: case TINYGLTF_TYPE_VEC3: {
{ const glm::vec3* buf = static_cast<const glm::vec3*>(dataPtr);
const glm::vec3* buf = static_cast<const glm::vec3*> (dataptr);
for (size_t index = 0; index < accessor.count; index++) for (size_t index = 0; index < accessor.count; index++)
{ {
dstSampler.outputsVec4.push_back(glm::vec4(buf[index], 0.0f)); dstSampler.outputsVec4.push_back(glm::vec4(buf[index], 0.0f));
} }
break; break;
} }
case TINYGLTF_TYPE_VEC4: case TINYGLTF_TYPE_VEC4: {
{ const glm::vec4* buf = static_cast<const glm::vec4*>(dataPtr);
const glm::vec4* buf = static_cast<const glm::vec4*>(dataptr);
for (size_t index = 0; index < accessor.count; index++) for (size_t index = 0; index < accessor.count; index++)
{ {
dstSampler.outputsVec4.push_back(buf[index]); dstSampler.outputsVec4.push_back(buf[index]);
} }
break; break;
} }
default: default: {
{ std::cout << "unknown type" << std::endl;
std::cout << "unknown type in accessor" << std::endl; break;
} }
break;
} }
} }
} }
// Channels
animations[i].channels.resize(glTFAnimation.channels.size()); animations[i].channels.resize(glTFAnimation.channels.size());
for (size_t j = 0; j < glTFAnimation.channels.size(); j++) for (size_t j = 0; j < glTFAnimation.channels.size(); j++)
{ {
@ -235,7 +232,6 @@ VulkanglTFModel::~VulkanglTFModel()
dstChannel.samplerIndex = glTFChannel.sampler; dstChannel.samplerIndex = glTFChannel.sampler;
dstChannel.node = nodeFromIndex(glTFChannel.target_node); dstChannel.node = nodeFromIndex(glTFChannel.target_node);
} }
} }
@ -273,7 +269,7 @@ VulkanglTFModel::~VulkanglTFModel()
{ {
for (size_t i = 0; i < inputNode.children.size(); i++) 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) void VulkanglTFModel::updateAnimation(float deltaTime)
{ {
if (activeAnimation > static_cast<uint32_t>(animations.size())-1) if (activeAnimation > static_cast<uint32_t>(animations.size()) - 1)
{ {
std::cout << "no animation with index" << activeAnimation << std::endl; std::cout << "No animation with index " << activeAnimation << std::endl;
return; return;
} }
Animation& animation = animations[activeAnimation]; Animation& animation = animations[activeAnimation];
@ -495,17 +491,19 @@ VulkanglTFModel::~VulkanglTFModel()
{ {
animation.currentTime -= animation.end; animation.currentTime -= animation.end;
} }
for (auto& channel : animation.channels) for (auto& channel : animation.channels)
{ {
AnimationSampler& sampler = animation.samplers[channel.samplerIndex]; 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") if (sampler.interpolation != "LINEAR")
{ {
std::cout << "sample only supports linear interpolaton" << std::endl; std::cout << "This sample only supports linear interpolations\n";
continue; continue;
} }
// Get the input keyframe values for the current time stamp
if ((animation.currentTime >= sampler.inputs[i]) && (animation.currentTime <= sampler.inputs[i + 1])) 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 a = (animation.currentTime - sampler.inputs[i]) / (sampler.inputs[i + 1] - sampler.inputs[i]);
@ -515,7 +513,6 @@ VulkanglTFModel::~VulkanglTFModel()
} }
if (channel.path == "rotation") if (channel.path == "rotation")
{ {
//quaternion
glm::quat q1; glm::quat q1;
q1.x = sampler.outputsVec4[i].x; q1.x = sampler.outputsVec4[i].x;
q1.y = sampler.outputsVec4[i].y; q1.y = sampler.outputsVec4[i].y;
@ -523,13 +520,12 @@ VulkanglTFModel::~VulkanglTFModel()
q1.w = sampler.outputsVec4[i].w; q1.w = sampler.outputsVec4[i].w;
glm::quat q2; glm::quat q2;
q2.x = sampler.outputsVec4[i].x; q2.x = sampler.outputsVec4[i + 1].x;
q2.y = sampler.outputsVec4[i].y; q2.y = sampler.outputsVec4[i + 1].y;
q2.z = sampler.outputsVec4[i].z; q2.z = sampler.outputsVec4[i + 1].z;
q2.w = sampler.outputsVec4[i].w; 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, a));
} }
if (channel.path == "scale") if (channel.path == "scale")
{ {
@ -563,8 +559,7 @@ VulkanglTFModel::~VulkanglTFModel()
// Pass the final matrix to the vertex shader using push constants // Pass the final matrix to the vertex shader using push constants
vkCmdPushConstants(commandBuffer, pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(glm::mat4), &nodeMatrix); 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) { for (VulkanglTFModel::Primitive& primitive : node.mesh.primitives) {
@ -806,15 +801,14 @@ void VulkanExample::getEnabledFeatures()
*/ */
std::vector<VkDescriptorPoolSize> poolSizes = { std::vector<VkDescriptorPoolSize> poolSizes = {
vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1), vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1),
// One combined image sampler per model image/texture // One combined image sampler per material image/texture
vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, static_cast<uint32_t>(glTFModel.images.size())), vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, static_cast<uint32_t>(glTFModel.images.size())),
//initialize descriptor pool size for skin // One ssbo per skin
vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,static_cast<uint32_t>(glTFModel.skins.size())), vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, static_cast<uint32_t>(glTFModel.skins.size())),
}; };
// Number of descriptor sets = One for the scene ubo + one per image + one per skin
// One set for matrices and one per model image/texture const uint32_t maxSetCount = static_cast<uint32_t>(glTFModel.images.size()) + static_cast<uint32_t>(glTFModel.skins.size()) + 1;
const uint32_t maxSetCount = static_cast<uint32_t>(glTFModel.images.size()) + static_cast<uint32_t>(glTFModel.skins.size())+1;
VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, maxSetCount); VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, maxSetCount);
VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); 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); 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)); 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); setLayoutBinding = vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0);
VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorSetLayoutCI, nullptr, &descriptorSetLayouts.jointMatrices)); 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) // The pipeline layout uses three sets:
std::array<VkDescriptorSetLayout, 3> setLayouts = // Set 0 = Scene matrices (VS)
{ // Set 1 = Joint matrices (VS)
// Set 2 = Material texture (FS)
std::array<VkDescriptorSetLayout, 3> setLayouts = {
descriptorSetLayouts.matrices, descriptorSetLayouts.matrices,
descriptorSetLayouts.jointMatrices, descriptorSetLayouts.jointMatrices,
descriptorSetLayouts.textures descriptorSetLayouts.textures };
}; VkPipelineLayoutCreateInfo pipelineLayoutCI = vks::initializers::pipelineLayoutCreateInfo(setLayouts.data(), static_cast<uint32_t>(setLayouts.size()));
VkPipelineLayoutCreateInfo pipelineLayoutCI= vks::initializers::pipelineLayoutCreateInfo(setLayouts.data(), static_cast<uint32_t>(setLayouts.size()));
// We will use push constants to push the local matrices of a primitive to the vertex shader // 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); VkPushConstantRange pushConstantRange = vks::initializers::pushConstantRange(VK_SHADER_STAGE_VERTEX_BIT, sizeof(glm::mat4), 0);
// Push constant ranges are part of the pipeline layout // Push constant ranges are part of the pipeline layout
pipelineLayoutCI.pushConstantRangeCount = 1; pipelineLayoutCI.pushConstantRangeCount = 1;
pipelineLayoutCI.pPushConstantRanges = &pushConstantRange; 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); VkWriteDescriptorSet writeDescriptorSet = vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &shaderData.buffer.descriptor);
vkUpdateDescriptorSets(device, 1, &writeDescriptorSet, 0, nullptr); 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) for (auto& skin : glTFModel.skins)
{ {
const VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayouts.jointMatrices, 1); const VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayouts.jointMatrices, 1);
@ -866,15 +860,15 @@ void VulkanExample::getEnabledFeatures()
vkUpdateDescriptorSets(device, 1, &writeDescriptorSet, 0, nullptr); vkUpdateDescriptorSets(device, 1, &writeDescriptorSet, 0, nullptr);
} }
// Descriptor sets for materials // Descriptor sets for glTF model materials
for (auto& image : glTFModel.images) { for (auto& image : glTFModel.images)
{
const VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayouts.textures, 1); const VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayouts.textures, 1);
VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &image.descriptorSet)); 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); VkWriteDescriptorSet writeDescriptorSet = vks::initializers::writeDescriptorSet(image.descriptorSet, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 0, &image.texture.descriptor);
vkUpdateDescriptorSets(device, 1, &writeDescriptorSet, 0, nullptr); vkUpdateDescriptorSets(device, 1, &writeDescriptorSet, 0, nullptr);
} }
} }
void VulkanExample::preparePipelines() void VulkanExample::preparePipelines()
@ -893,13 +887,13 @@ void VulkanExample::getEnabledFeatures()
vks::initializers::vertexInputBindingDescription(0, sizeof(VulkanglTFModel::Vertex), VK_VERTEX_INPUT_RATE_VERTEX), vks::initializers::vertexInputBindingDescription(0, sizeof(VulkanglTFModel::Vertex), VK_VERTEX_INPUT_RATE_VERTEX),
}; };
const std::vector<VkVertexInputAttributeDescription> vertexInputAttributes = { const std::vector<VkVertexInputAttributeDescription> vertexInputAttributes = {
vks::initializers::vertexInputAttributeDescription(0, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(VulkanglTFModel::Vertex, pos)), // Location 0: Position {0, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(VulkanglTFModel::Vertex, pos)},
vks::initializers::vertexInputAttributeDescription(0, 1, VK_FORMAT_R32G32B32_SFLOAT, offsetof(VulkanglTFModel::Vertex, normal)),// Location 1: Normal {1, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(VulkanglTFModel::Vertex, normal)},
vks::initializers::vertexInputAttributeDescription(0, 2, VK_FORMAT_R32G32B32_SFLOAT, offsetof(VulkanglTFModel::Vertex, uv)), // Location 2: Texture coordinates {2, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(VulkanglTFModel::Vertex, uv)},
vks::initializers::vertexInputAttributeDescription(0, 3, VK_FORMAT_R32G32B32_SFLOAT, offsetof(VulkanglTFModel::Vertex, color)), // Location 3: Color {3, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(VulkanglTFModel::Vertex, color)},
vks::initializers::vertexInputAttributeDescription(0, 4, VK_FORMAT_R32G32B32_SFLOAT, offsetof(VulkanglTFModel::Vertex,jointIndices)), // Location 4 : jointIndices // POI: Per-Vertex Joint indices and weights are passed to the vertex shader
vks::initializers::vertexInputAttributeDescription(0, 5, VK_FORMAT_R32G32B32_SFLOAT, offsetof(VulkanglTFModel::Vertex,jointWeights)), //Location 5 : jointWeights {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(); VkPipelineVertexInputStateCreateInfo vertexInputStateCI = vks::initializers::pipelineVertexInputStateCreateInfo();
vertexInputStateCI.vertexBindingDescriptionCount = static_cast<uint32_t>(vertexInputBindings.size()); vertexInputStateCI.vertexBindingDescriptionCount = static_cast<uint32_t>(vertexInputBindings.size());