Updated sekeletal animation example
This commit is contained in:
parent
bbce1bd743
commit
26b02736d5
1 changed files with 252 additions and 80 deletions
|
|
@ -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;
|
||||||
|
|
||||||
|
if (useStaging)
|
||||||
|
{
|
||||||
|
struct {
|
||||||
|
VkBuffer buffer;
|
||||||
|
VkDeviceMemory memory;
|
||||||
|
} vertexStaging, indexStaging;
|
||||||
|
|
||||||
|
// 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,
|
||||||
|
©Region);
|
||||||
|
|
||||||
|
copyRegion.size = indexBufferSize;
|
||||||
|
vkCmdCopyBuffer(
|
||||||
|
copyCmd,
|
||||||
|
indexStaging.buffer,
|
||||||
|
mesh.meshBuffer.indices.buf,
|
||||||
|
1,
|
||||||
|
©Region);
|
||||||
|
|
||||||
|
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(
|
createBuffer(
|
||||||
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
|
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
|
||||||
|
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
|
||||||
vertexBufferSize,
|
vertexBufferSize,
|
||||||
vertexBuffer.data(),
|
vertexBuffer.data(),
|
||||||
&mesh.meshBuffer.vertices.buf,
|
&mesh.meshBuffer.vertices.buf,
|
||||||
&mesh.meshBuffer.vertices.mem);
|
&mesh.meshBuffer.vertices.mem);
|
||||||
|
// Index buffer
|
||||||
// Generate index buffer
|
|
||||||
createBuffer(
|
createBuffer(
|
||||||
VK_BUFFER_USAGE_INDEX_BUFFER_BIT,
|
VK_BUFFER_USAGE_INDEX_BUFFER_BIT,
|
||||||
|
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
|
||||||
indexBufferSize,
|
indexBufferSize,
|
||||||
indexBuffer.data(),
|
indexBuffer.data(),
|
||||||
&mesh.meshBuffer.indices.buf,
|
&mesh.meshBuffer.indices.buf,
|
||||||
&mesh.meshBuffer.indices.mem);
|
&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 =
|
||||||
|
|
@ -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,28 +933,55 @@ 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;
|
||||||
boneTransform(runningTime, boneTransforms);
|
boneTransform(runningTime, 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);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue