Updated sekeletal animation example

This commit is contained in:
saschawillems 2016-05-14 20:03:29 +02:00
parent bbce1bd743
commit 26b02736d5

View file

@ -35,11 +35,22 @@ struct Vertex {
uint32_t boneIDs[4]; uint32_t boneIDs[4];
}; };
std::vector<vkMeshLoader::VertexLayout> vertexLayout =
{
vkMeshLoader::VERTEX_LAYOUT_POSITION,
vkMeshLoader::VERTEX_LAYOUT_NORMAL,
vkMeshLoader::VERTEX_LAYOUT_UV,
vkMeshLoader::VERTEX_LAYOUT_COLOR,
vkMeshLoader::VERTEX_LAYOUT_DUMMY_VEC4,
vkMeshLoader::VERTEX_LAYOUT_DUMMY_VEC4
};
class VulkanExample : public VulkanExampleBase class VulkanExample : public VulkanExampleBase
{ {
public: public:
struct { struct {
vkTools::VulkanTexture colorMap; vkTools::VulkanTexture colorMap;
vkTools::VulkanTexture floor;
} textures; } textures;
struct { struct {
@ -109,44 +120,64 @@ public:
struct { struct {
vkTools::UniformData vsScene; vkTools::UniformData vsScene;
vkTools::UniformData floor;
} uniformData; } uniformData;
// Must not be higher than same const in skinning shader // Must not be higher than same const in skinning shader
#define MAX_BONES 128 #define MAX_BONES 64
struct { struct {
glm::mat4 projection; glm::mat4 projection;
glm::mat4 model; glm::mat4 model;
glm::mat4 bones[MAX_BONES]; glm::mat4 bones[MAX_BONES];
glm::vec4 lightPos = glm::vec4(0.0, -5.0, 25.0, 1.0); glm::vec4 lightPos = glm::vec4(0.0f, -250.0f, 250.0f, 1.0);
glm::vec4 viewPos;
} uboVS; } uboVS;
struct { struct {
VkPipeline solid; glm::mat4 projection;
glm::mat4 model;
glm::vec4 lightPos = glm::vec4(0.0, 0.0f, -25.0f, 1.0);
glm::vec4 viewPos;
glm::vec2 uvOffset;
} uboFloor;
struct {
VkPipeline skinning;
VkPipeline texture;
} pipelines; } pipelines;
struct {
vkMeshLoader::MeshBuffer floor;
} meshes;
VkPipelineLayout pipelineLayout; VkPipelineLayout pipelineLayout;
VkDescriptorSet descriptorSet; VkDescriptorSet descriptorSet;
VkDescriptorSetLayout descriptorSetLayout; VkDescriptorSetLayout descriptorSetLayout;
struct {
VkDescriptorSet skinning;
VkDescriptorSet floor;
} descriptorSets;
float runningTime = 0.0f; float runningTime = 0.0f;
VulkanExample() : VulkanExampleBase(ENABLE_VALIDATION) VulkanExample() : VulkanExampleBase(ENABLE_VALIDATION)
{ {
width = 1280; zoom = -166.0f;
height = 720;
zoom = -8.0f;
zoomSpeed = 2.5f; zoomSpeed = 2.5f;
rotationSpeed = 0.5f; rotationSpeed = 0.5f;
rotation = { -180.0f, -50.0f, 180.0f }; rotation = { -187.0f, 60.0f, 180.0f };
title = "Vulkan Example - Skeletal animation"; title = "Vulkan Example - Skeletal animation";
paused = true;
cameraPos = { 0.0f, 0.0f, 12.0f };
} }
~VulkanExample() ~VulkanExample()
{ {
// Clean up used Vulkan resources // Clean up used Vulkan resources
// Note : Inherited destructor cleans up resources stored in base class // Note : Inherited destructor cleans up resources stored in base class
vkDestroyPipeline(device, pipelines.solid, nullptr); vkDestroyPipeline(device, pipelines.skinning, nullptr);
vkDestroyPipelineLayout(device, pipelineLayout, nullptr); vkDestroyPipelineLayout(device, pipelineLayout, nullptr);
vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr);
@ -166,7 +197,7 @@ public:
VkCommandBufferBeginInfo cmdBufInfo = vkTools::initializers::commandBufferBeginInfo(); VkCommandBufferBeginInfo cmdBufInfo = vkTools::initializers::commandBufferBeginInfo();
VkClearValue clearValues[2]; VkClearValue clearValues[2];
clearValues[0].color = defaultClearColor; clearValues[0].color = { { 0.0f, 0.0f, 0.0f, 0.0f} };
clearValues[1].depthStencil = { 1.0f, 0 }; clearValues[1].depthStencil = { 1.0f, 0 };
VkRenderPassBeginInfo renderPassBeginInfo = vkTools::initializers::renderPassBeginInfo(); VkRenderPassBeginInfo renderPassBeginInfo = vkTools::initializers::renderPassBeginInfo();
@ -178,47 +209,41 @@ public:
renderPassBeginInfo.clearValueCount = 2; renderPassBeginInfo.clearValueCount = 2;
renderPassBeginInfo.pClearValues = clearValues; renderPassBeginInfo.pClearValues = clearValues;
VkResult err;
for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) for (int32_t i = 0; i < drawCmdBuffers.size(); ++i)
{ {
// Set target frame buffer
renderPassBeginInfo.framebuffer = frameBuffers[i]; renderPassBeginInfo.framebuffer = frameBuffers[i];
err = vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo); vkTools::checkResult(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo));
assert(!err);
vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
VkViewport viewport = vkTools::initializers::viewport( VkViewport viewport = vkTools::initializers::viewport((float)width, (float)height, 0.0f, 1.0f);
(float)width,
(float)height,
0.0f,
1.0f);
vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport);
VkRect2D scissor = vkTools::initializers::rect2D( VkRect2D scissor = vkTools::initializers::rect2D(width, height, 0, 0);
width,
height,
0,
0);
vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor);
vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, NULL);
vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.solid);
VkDeviceSize offsets[1] = { 0 }; VkDeviceSize offsets[1] = { 0 };
// Bind mesh vertex buffer
// Skinned mesh
vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, NULL);
vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.skinning);
vkCmdBindVertexBuffers(drawCmdBuffers[i], VERTEX_BUFFER_BIND_ID, 1, &mesh.meshBuffer.vertices.buf, offsets); vkCmdBindVertexBuffers(drawCmdBuffers[i], VERTEX_BUFFER_BIND_ID, 1, &mesh.meshBuffer.vertices.buf, offsets);
// Bind mesh index buffer
vkCmdBindIndexBuffer(drawCmdBuffers[i], mesh.meshBuffer.indices.buf, 0, VK_INDEX_TYPE_UINT32); vkCmdBindIndexBuffer(drawCmdBuffers[i], mesh.meshBuffer.indices.buf, 0, VK_INDEX_TYPE_UINT32);
// Render mesh vertex buffer using it's indices
vkCmdDrawIndexed(drawCmdBuffers[i], mesh.meshBuffer.indexCount, 1, 0, 0, 0); vkCmdDrawIndexed(drawCmdBuffers[i], mesh.meshBuffer.indexCount, 1, 0, 0, 0);
// Floor
vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSets.floor, 0, NULL);
vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.texture);
vkCmdBindVertexBuffers(drawCmdBuffers[i], VERTEX_BUFFER_BIND_ID, 1, &meshes.floor.vertices.buf, offsets);
vkCmdBindIndexBuffer(drawCmdBuffers[i], meshes.floor.indices.buf, 0, VK_INDEX_TYPE_UINT32);
vkCmdDrawIndexed(drawCmdBuffers[i], meshes.floor.indexCount, 1, 0, 0, 0);
vkCmdEndRenderPass(drawCmdBuffers[i]); vkCmdEndRenderPass(drawCmdBuffers[i]);
err = vkEndCommandBuffer(drawCmdBuffers[i]); vkTools::checkResult(vkEndCommandBuffer(drawCmdBuffers[i]));
assert(!err);
} }
} }
@ -255,6 +280,9 @@ public:
for (uint32_t i = 0; i < pMesh->mNumBones; i++) for (uint32_t i = 0; i < pMesh->mNumBones; i++)
{ {
uint32_t index = 0; uint32_t index = 0;
assert(pMesh->mNumBones <= MAX_BONES);
std::string name(pMesh->mBones[i]->mName.data); std::string name(pMesh->mBones[i]->mName.data);
if (mesh.boneMapping.find(name) == mesh.boneMapping.end()) if (mesh.boneMapping.find(name) == mesh.boneMapping.end())
@ -424,11 +452,12 @@ public:
aiMatrix4x4 matRotation = interpolateRotation(AnimationTime, pNodeAnim); aiMatrix4x4 matRotation = interpolateRotation(AnimationTime, pNodeAnim);
aiMatrix4x4 matTranslation = interpolateTranslation(AnimationTime, pNodeAnim); aiMatrix4x4 matTranslation = interpolateTranslation(AnimationTime, pNodeAnim);
NodeTransformation = matTranslation * matRotation;// *matScale; NodeTransformation = matTranslation * matRotation * matScale;
} }
aiMatrix4x4 GlobalTransformation = ParentTransform * NodeTransformation; aiMatrix4x4 GlobalTransformation = ParentTransform * NodeTransformation;
// todo : replace name lookup with hash or index
if (mesh.boneMapping.find(NodeName) != mesh.boneMapping.end()) if (mesh.boneMapping.find(NodeName) != mesh.boneMapping.end())
{ {
uint32_t BoneIndex = mesh.boneMapping[NodeName]; uint32_t BoneIndex = mesh.boneMapping[NodeName];
@ -452,7 +481,7 @@ public:
aiMatrix4x4 identity = aiMatrix4x4(); aiMatrix4x4 identity = aiMatrix4x4();
readNodeHierarchy(AnimationTime, mesh.meshLoader->pScene->mRootNode, identity); readNodeHierarchy(AnimationTime, mesh.meshLoader->pScene->mRootNode, identity);
boneTransforms.resize(mesh.numBones); boneTransforms.resize(mesh.numBones); // todo : resize only once
for (uint32_t i = 0; i < boneTransforms.size(); i++) for (uint32_t i = 0; i < boneTransforms.size(); i++)
{ {
@ -469,7 +498,7 @@ public:
#if defined(__ANDROID__) #if defined(__ANDROID__)
mesh.meshLoader->assetManager = androidApp->activity->assetManager; mesh.meshLoader->assetManager = androidApp->activity->assetManager;
#endif #endif
mesh.meshLoader->LoadMesh(getAssetPath() + "models/astroboy/astroBoy_walk.dae", 0); mesh.meshLoader->LoadMesh(getAssetPath() + "models/goblin_3ds.DAE", 0);
// Setup bones // Setup bones
// One vertex bone info structure per vertex // One vertex bone info structure per vertex
@ -488,7 +517,6 @@ public:
} }
// Generate vertex buffer // Generate vertex buffer
float scale = 1.0f;
std::vector<Vertex> vertexBuffer; std::vector<Vertex> vertexBuffer;
// Iterate through all meshes in the file // Iterate through all meshes in the file
// and extract the vertex information used in this demo // and extract the vertex information used in this demo
@ -498,14 +526,14 @@ public:
{ {
Vertex vertex; Vertex vertex;
vertex.pos = mesh.meshLoader->m_Entries[m].Vertices[i].m_pos * scale; vertex.pos = mesh.meshLoader->m_Entries[m].Vertices[i].m_pos;
vertex.pos.y = -vertex.pos.y; vertex.pos.y = -vertex.pos.y;
vertex.normal = mesh.meshLoader->m_Entries[m].Vertices[i].m_normal; vertex.normal = mesh.meshLoader->m_Entries[m].Vertices[i].m_normal;
vertex.uv = mesh.meshLoader->m_Entries[m].Vertices[i].m_tex; vertex.uv = mesh.meshLoader->m_Entries[m].Vertices[i].m_tex;
vertex.color = mesh.meshLoader->m_Entries[m].Vertices[i].m_color; vertex.color = mesh.meshLoader->m_Entries[m].Vertices[i].m_color;
// Fetch bone weights and IDs // Fetch bone weights and IDs
for (uint32_t j = 0; j < 4; j++) for (uint32_t j = 0; j < MAX_BONES_PER_VERTEX; j++)
{ {
vertex.boneWeights[j] = mesh.bones[mesh.meshLoader->m_Entries[m].vertexBase + i].weights[j]; vertex.boneWeights[j] = mesh.bones[mesh.meshLoader->m_Entries[m].vertexBase + i].weights[j];
vertex.boneIDs[j] = mesh.bones[mesh.meshLoader->m_Entries[m].vertexBase + i].IDs[j]; vertex.boneIDs[j] = mesh.bones[mesh.meshLoader->m_Entries[m].vertexBase + i].IDs[j];
@ -529,29 +557,116 @@ public:
uint32_t indexBufferSize = indexBuffer.size() * sizeof(uint32_t); uint32_t indexBufferSize = indexBuffer.size() * sizeof(uint32_t);
mesh.meshBuffer.indexCount = indexBuffer.size(); mesh.meshBuffer.indexCount = indexBuffer.size();
// Generate vertex buffer bool useStaging = true;
createBuffer(
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
vertexBufferSize,
vertexBuffer.data(),
&mesh.meshBuffer.vertices.buf,
&mesh.meshBuffer.vertices.mem);
// Generate index buffer if (useStaging)
createBuffer( {
VK_BUFFER_USAGE_INDEX_BUFFER_BIT, struct {
indexBufferSize, VkBuffer buffer;
indexBuffer.data(), VkDeviceMemory memory;
&mesh.meshBuffer.indices.buf, } vertexStaging, indexStaging;
&mesh.meshBuffer.indices.mem);
// Create staging buffers
// Vertex data
createBuffer(
VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
vertexBufferSize,
vertexBuffer.data(),
&vertexStaging.buffer,
&vertexStaging.memory);
// Index data
createBuffer(
VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
indexBufferSize,
indexBuffer.data(),
&indexStaging.buffer,
&indexStaging.memory);
// Create device local buffers
// Vertex buffer
createBuffer(
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
vertexBufferSize,
nullptr,
&mesh.meshBuffer.vertices.buf,
&mesh.meshBuffer.vertices.mem);
// Index buffer
createBuffer(
VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
indexBufferSize,
nullptr,
&mesh.meshBuffer.indices.buf,
&mesh.meshBuffer.indices.mem);
// Copy from staging buffers
VkCommandBuffer copyCmd = VulkanExampleBase::createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true);
VkBufferCopy copyRegion = {};
copyRegion.size = vertexBufferSize;
vkCmdCopyBuffer(
copyCmd,
vertexStaging.buffer,
mesh.meshBuffer.vertices.buf,
1,
&copyRegion);
copyRegion.size = indexBufferSize;
vkCmdCopyBuffer(
copyCmd,
indexStaging.buffer,
mesh.meshBuffer.indices.buf,
1,
&copyRegion);
VulkanExampleBase::flushCommandBuffer(copyCmd, queue, true);
vkDestroyBuffer(device, vertexStaging.buffer, nullptr);
vkFreeMemory(device, vertexStaging.memory, nullptr);
vkDestroyBuffer(device, indexStaging.buffer, nullptr);
vkFreeMemory(device, indexStaging.memory, nullptr);
}
else
{
// Vertex buffer
createBuffer(
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
vertexBufferSize,
vertexBuffer.data(),
&mesh.meshBuffer.vertices.buf,
&mesh.meshBuffer.vertices.mem);
// Index buffer
createBuffer(
VK_BUFFER_USAGE_INDEX_BUFFER_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
indexBufferSize,
indexBuffer.data(),
&mesh.meshBuffer.indices.buf,
&mesh.meshBuffer.indices.mem);
}
} }
void loadTextures() void loadTextures()
{ {
textureLoader->loadTexture( textureLoader->loadTexture(
getAssetPath() + "models/astroboy/astroboy.ktx", getAssetPath() + "textures/goblin.ktx",
VK_FORMAT_BC3_UNORM_BLOCK, VK_FORMAT_BC3_UNORM_BLOCK,
&textures.colorMap); &textures.colorMap);
textureLoader->loadTexture(
getAssetPath() + "textures/stonefloor_color_specular_bc3.ktx",
VK_FORMAT_BC3_UNORM_BLOCK,
&textures.floor);
}
void loadMeshes()
{
VulkanExampleBase::loadMesh(getAssetPath() + "models/plane_z.obj", &meshes.floor, vertexLayout, 512.0f);
} }
void setupVertexDescriptions() void setupVertexDescriptions()
@ -622,8 +737,8 @@ public:
// Example uses one ubo and one combined image sampler // Example uses one ubo and one combined image sampler
std::vector<VkDescriptorPoolSize> poolSizes = std::vector<VkDescriptorPoolSize> poolSizes =
{ {
vkTools::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1), vkTools::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2),
vkTools::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1), vkTools::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2),
}; };
VkDescriptorPoolCreateInfo descriptorPoolInfo = VkDescriptorPoolCreateInfo descriptorPoolInfo =
@ -690,7 +805,7 @@ public:
{ {
// Binding 0 : Vertex shader uniform buffer // Binding 0 : Vertex shader uniform buffer
vkTools::initializers::writeDescriptorSet( vkTools::initializers::writeDescriptorSet(
descriptorSet, descriptorSet,
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
0, 0,
&uniformData.vsScene.descriptor), &uniformData.vsScene.descriptor),
@ -703,6 +818,31 @@ public:
}; };
vkUpdateDescriptorSets(device, writeDescriptorSets.size(), writeDescriptorSets.data(), 0, NULL); vkUpdateDescriptorSets(device, writeDescriptorSets.size(), writeDescriptorSets.data(), 0, NULL);
// Floor
vkTools::checkResult(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSets.floor));
texDescriptor.imageView = textures.floor.view;
texDescriptor.sampler = textures.floor.sampler;
writeDescriptorSets.clear();
// Binding 0 : Vertex shader uniform buffer
writeDescriptorSets.push_back(
vkTools::initializers::writeDescriptorSet(
descriptorSets.floor,
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
0,
&uniformData.floor.descriptor));
// Binding 1 : Color map
writeDescriptorSets.push_back(
vkTools::initializers::writeDescriptorSet(
descriptorSets.floor,
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
1,
&texDescriptor));
vkUpdateDescriptorSets(device, writeDescriptorSets.size(), writeDescriptorSets.data(), 0, NULL);
} }
void preparePipelines() void preparePipelines()
@ -754,8 +894,7 @@ public:
dynamicStateEnables.size(), dynamicStateEnables.size(),
0); 0);
// Solid rendering pipeline // Skinned rendering pipeline
// Load shaders
std::array<VkPipelineShaderStageCreateInfo, 2> shaderStages; std::array<VkPipelineShaderStageCreateInfo, 2> shaderStages;
shaderStages[0] = loadShader(getAssetPath() + "shaders/skeletalanimation/mesh.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); shaderStages[0] = loadShader(getAssetPath() + "shaders/skeletalanimation/mesh.vert.spv", VK_SHADER_STAGE_VERTEX_BIT);
@ -778,8 +917,13 @@ public:
pipelineCreateInfo.stageCount = shaderStages.size(); pipelineCreateInfo.stageCount = shaderStages.size();
pipelineCreateInfo.pStages = shaderStages.data(); pipelineCreateInfo.pStages = shaderStages.data();
VkResult err = vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipelines.solid); VkResult err = vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipelines.skinning);
assert(!err); assert(!err);
shaderStages[0] = loadShader(getAssetPath() + "shaders/skeletalanimation/texture.vert.spv", VK_SHADER_STAGE_VERTEX_BIT);
shaderStages[1] = loadShader(getAssetPath() + "shaders/skeletalanimation/texture.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT);
vkTools::checkResult(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipelines.texture));
} }
// Prepare and initialize uniform buffer containing shader uniforms // Prepare and initialize uniform buffer containing shader uniforms
@ -789,27 +933,54 @@ public:
createBuffer( createBuffer(
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
sizeof(uboVS), sizeof(uboVS),
&uboVS, nullptr,
&uniformData.vsScene.buffer, &uniformData.vsScene.buffer,
&uniformData.vsScene.memory, &uniformData.vsScene.memory,
&uniformData.vsScene.descriptor); &uniformData.vsScene.descriptor);
updateUniformBuffers(); // Map for host access
vkTools::checkResult(vkMapMemory(device, uniformData.vsScene.memory, 0, sizeof(uboVS), 0, (void **)&uniformData.vsScene.mapped));
// Floor
createBuffer(
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
sizeof(uboFloor),
nullptr,
&uniformData.floor.buffer,
&uniformData.floor.memory,
&uniformData.floor.descriptor);
// Map for host access
vkTools::checkResult(vkMapMemory(device, uniformData.floor.memory, 0, sizeof(uboFloor), 0, (void **)&uniformData.floor.mapped));
updateUniformBuffers(true);
} }
void updateUniformBuffers() void updateUniformBuffers(bool viewChanged)
{ {
// Vertex shader if (viewChanged)
uboVS.projection = glm::perspective(glm::radians(60.0f), (float)width / (float)height, 0.1f, 256.0f); {
uboVS.projection = glm::perspective(glm::radians(60.0f), (float)width / (float)height, 0.1f, 512.0f);
glm::mat4 viewMatrix = glm::translate(glm::mat4(), glm::vec3(0.0f, 0.0f, zoom)); glm::mat4 viewMatrix = glm::translate(glm::mat4(), glm::vec3(0.0f, 0.0f, zoom));
viewMatrix = glm::rotate(viewMatrix, glm::radians(90.0f), glm::vec3(1.0f, 0.0f, 0.0f)); viewMatrix = glm::rotate(viewMatrix, glm::radians(90.0f), glm::vec3(1.0f, 0.0f, 0.0f));
viewMatrix = glm::scale(viewMatrix, glm::vec3(0.025f));
uboVS.model = glm::mat4(); uboVS.model = viewMatrix * glm::translate(glm::mat4(), glm::vec3(cameraPos.x, -cameraPos.z, cameraPos.y) * 100.0f);
uboVS.model = viewMatrix * glm::translate(uboVS.model, glm::vec3(0.0f, 0.0f, -3.5f)); uboVS.model = glm::rotate(uboVS.model, glm::radians(rotation.x), glm::vec3(1.0f, 0.0f, 0.0f));
uboVS.model = glm::rotate(uboVS.model, glm::radians(rotation.x), glm::vec3(1.0f, 0.0f, 0.0f)); uboVS.model = glm::rotate(uboVS.model, glm::radians(rotation.z), glm::vec3(0.0f, 1.0f, 0.0f));
uboVS.model = glm::rotate(uboVS.model, glm::radians(rotation.z), glm::vec3(0.0f, 1.0f, 0.0f)); uboVS.model = glm::rotate(uboVS.model, glm::radians(-rotation.y), glm::vec3(0.0f, 0.0f, 1.0f));
uboVS.model = glm::rotate(uboVS.model, glm::radians(-rotation.y), glm::vec3(0.0f, 0.0f, 1.0f));
uboVS.viewPos = glm::vec4(0.0f, 0.0f, -zoom, 0.0f);
uboFloor.projection = uboVS.projection;
uboFloor.model = viewMatrix * glm::translate(glm::mat4(), glm::vec3(cameraPos.x, -cameraPos.z, cameraPos.y) * 100.0f);
uboFloor.model = glm::rotate(uboFloor.model, glm::radians(rotation.x), glm::vec3(1.0f, 0.0f, 0.0f));
uboFloor.model = glm::rotate(uboFloor.model, glm::radians(rotation.z), glm::vec3(0.0f, 1.0f, 0.0f));
uboFloor.model = glm::rotate(uboFloor.model, glm::radians(-rotation.y), glm::vec3(0.0f, 0.0f, 1.0f));
uboFloor.model = glm::translate(uboFloor.model, glm::vec3(0.0f, 0.0f, -1800.0f));
uboFloor.viewPos = glm::vec4(0.0f, 0.0f, -zoom, 0.0f);
}
// Update bones // Update bones
std::vector<aiMatrix4x4> boneTransforms; std::vector<aiMatrix4x4> boneTransforms;
@ -820,11 +991,11 @@ public:
uboVS.bones[i] = glm::transpose(glm::make_mat4(&boneTransforms[i].a1)); uboVS.bones[i] = glm::transpose(glm::make_mat4(&boneTransforms[i].a1));
} }
uint8_t *pData; memcpy(uniformData.vsScene.mapped, &uboVS, sizeof(uboVS));
VkResult err = vkMapMemory(device, uniformData.vsScene.memory, 0, sizeof(uboVS), 0, (void **)&pData);
assert(!err); // Update floor animation
memcpy(pData, &uboVS, sizeof(uboVS)); uboFloor.uvOffset.t -= 0.35f * frameTimer;
vkUnmapMemory(device, uniformData.vsScene.memory); memcpy(uniformData.floor.mapped, &uboFloor, sizeof(uboFloor));
} }
void prepare() void prepare()
@ -832,6 +1003,7 @@ public:
VulkanExampleBase::prepare(); VulkanExampleBase::prepare();
loadTextures(); loadTextures();
loadMesh(); loadMesh();
loadMeshes();
setupVertexDescriptions(); setupVertexDescriptions();
prepareUniformBuffers(); prepareUniformBuffers();
setupDescriptorSetLayout(); setupDescriptorSetLayout();
@ -846,19 +1018,19 @@ public:
{ {
if (!prepared) if (!prepared)
return; return;
vkDeviceWaitIdle(device);
draw(); draw();
vkDeviceWaitIdle(device);
if (!paused) if (!paused)
{ {
runningTime += frameTimer * 0.75f; runningTime += frameTimer * 0.75f;
updateUniformBuffers(); vkDeviceWaitIdle(device);
updateUniformBuffers(false);
} }
} }
virtual void viewChanged() virtual void viewChanged()
{ {
updateUniformBuffers(); vkDeviceWaitIdle(device);
updateUniformBuffers(true);
} }
}; };