Modified shader to support instanced bone first index and system to support runtime updating of animations

This commit is contained in:
Kah Wei 2023-01-16 21:02:37 +08:00
parent a668f38c87
commit bce7237e20
14 changed files with 108 additions and 16 deletions

View File

@ -12,6 +12,7 @@ layout(location = 4) in mat4 worldTransform;
layout(location = 8) in uvec2 integerData; layout(location = 8) in uvec2 integerData;
layout(location = 9) in uvec4 aBoneIndices; layout(location = 9) in uvec4 aBoneIndices;
layout(location = 10) in vec4 aBoneWeights; layout(location = 10) in vec4 aBoneWeights;
layout(location = 11) in uint firstBoneIndex;
layout(location = 0) out struct layout(location = 0) out struct
{ {
@ -65,10 +66,10 @@ void main()
Out.normal.rgb = normalize (Out.normal.rgb); Out.normal.rgb = normalize (Out.normal.rgb);
// Compute bone matrix // Compute bone matrix
mat4 boneMatrix = BoneMatrices.data[aBoneIndices[0]] * aBoneWeights[0]; mat4 boneMatrix = BoneMatrices.data[firstBoneIndex + aBoneIndices[0]] * aBoneWeights[0];
boneMatrix += BoneMatrices.data[aBoneIndices[1]] * aBoneWeights[1]; boneMatrix += BoneMatrices.data[firstBoneIndex + aBoneIndices[1]] * aBoneWeights[1];
boneMatrix += BoneMatrices.data[aBoneIndices[2]] * aBoneWeights[2]; boneMatrix += BoneMatrices.data[firstBoneIndex + aBoneIndices[2]] * aBoneWeights[2];
boneMatrix += BoneMatrices.data[aBoneIndices[3]] * aBoneWeights[3]; boneMatrix += BoneMatrices.data[firstBoneIndex + aBoneIndices[3]] * aBoneWeights[3];
// clip space for rendering // clip space for rendering
gl_Position = cameraData.vpMat * worldTransform * boneMatrix * vec4 (aVertexPos, 1.0f); gl_Position = cameraData.vpMat * worldTransform * boneMatrix * vec4 (aVertexPos, 1.0f);

Binary file not shown.

View File

@ -34,6 +34,7 @@
#include "Physics/System/SHPhysicsDebugDrawSystem.h" #include "Physics/System/SHPhysicsDebugDrawSystem.h"
#include "Scripting/SHScriptEngine.h" #include "Scripting/SHScriptEngine.h"
#include "UI/SHUISystem.h" #include "UI/SHUISystem.h"
#include "Animation/SHAnimationSystem.h"
// Components // Components
#include "Graphics/MiddleEnd/Interface/SHRenderable.h" #include "Graphics/MiddleEnd/Interface/SHRenderable.h"
@ -96,6 +97,7 @@ namespace Sandbox
// Link up SHDebugDraw // Link up SHDebugDraw
SHSystemManager::CreateSystem<SHDebugDrawSystem>(); SHSystemManager::CreateSystem<SHDebugDrawSystem>();
SHDebugDraw::Init(SHSystemManager::GetSystem<SHDebugDrawSystem>()); SHDebugDraw::Init(SHSystemManager::GetSystem<SHDebugDrawSystem>());
SHSystemManager::CreateSystem<SHAnimationSystem>();
#ifdef SHEDITOR #ifdef SHEDITOR
SDL_Init(SDL_INIT_VIDEO); SDL_Init(SDL_INIT_VIDEO);
@ -142,7 +144,7 @@ namespace Sandbox
#ifdef SHEDITOR #ifdef SHEDITOR
SHSystemManager::RegisterRoutine<SHEditor, SHEditor::EditorRoutine>(); SHSystemManager::RegisterRoutine<SHEditor, SHEditor::EditorRoutine>();
#endif #endif
SHSystemManager::RegisterRoutine<SHAnimationSystem, SHAnimationSystem::UpdateRoutine>();
SHSystemManager::RegisterRoutine<SHGraphicsSystem, SHGraphicsSystem::RenderRoutine>(); SHSystemManager::RegisterRoutine<SHGraphicsSystem, SHGraphicsSystem::RenderRoutine>();
SHSystemManager::RegisterRoutine<SHGraphicsSystem, SHGraphicsSystem::EndRoutine>(); SHSystemManager::RegisterRoutine<SHGraphicsSystem, SHGraphicsSystem::EndRoutine>();

View File

@ -16,6 +16,7 @@ of DigiPen Institute of Technology is prohibited.
// Project Includes // Project Includes
#include "ECS_Base/Managers/SHComponentManager.h" #include "ECS_Base/Managers/SHComponentManager.h"
#include "SHAnimatorComponent.h" #include "SHAnimatorComponent.h"
#include "ECS_Base/General/SHFamily.h"
namespace SHADE namespace SHADE
{ {
@ -23,8 +24,11 @@ namespace SHADE
/* System Routine Functions - UpdateRoutine */ /* System Routine Functions - UpdateRoutine */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
SHAnimationSystem::UpdateRoutine::UpdateRoutine() SHAnimationSystem::UpdateRoutine::UpdateRoutine()
: SHSystemRoutine("Animation System Update", false) : SHSystemRoutine("Animation System Update", true)
{} {
SHFamilyID<SHSystem>::GetID<SHAnimationSystem>();
}
void SHAnimationSystem::UpdateRoutine::Execute(double dt) noexcept void SHAnimationSystem::UpdateRoutine::Execute(double dt) noexcept
{ {
auto& animators = SHComponentManager::GetDense<SHAnimatorComponent>(); auto& animators = SHComponentManager::GetDense<SHAnimatorComponent>();
@ -33,4 +37,18 @@ namespace SHADE
animator.Update(dt); animator.Update(dt);
} }
} }
/*---------------------------------------------------------------------------------*/
/* SHSystem Overrides */
/*---------------------------------------------------------------------------------*/
void SHAnimationSystem::Init(void)
{
}
void SHAnimationSystem::Exit(void)
{
}
} }

View File

@ -18,10 +18,6 @@ of DigiPen Institute of Technology is prohibited.
namespace SHADE namespace SHADE
{ {
/*-----------------------------------------------------------------------------------*/
/* Forward Declarations */
/*-----------------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Type Definitions */ /* Type Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
@ -30,7 +26,7 @@ namespace SHADE
/// </summary> /// </summary>
class SH_API SHAnimationSystem : public SHSystem class SH_API SHAnimationSystem : public SHSystem
{ {
public: public:
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Type Definitions */ /* Type Definitions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
@ -44,5 +40,16 @@ namespace SHADE
UpdateRoutine(); UpdateRoutine();
void Execute(double dt) noexcept override final; void Execute(double dt) noexcept override final;
}; };
/*---------------------------------------------------------------------------------*/
/* Constructors */
/*---------------------------------------------------------------------------------*/
SHAnimationSystem() = default;
/*---------------------------------------------------------------------------------*/
/* SHSystem Overrides */
/*---------------------------------------------------------------------------------*/
virtual void Init(void) override final;
virtual void Exit(void) override final;
}; };
} }

View File

@ -128,7 +128,7 @@ namespace SHADE
Handle<SHAnimationClip> currClip; Handle<SHAnimationClip> currClip;
// Playback Tracking // Playback Tracking
float currPlaybackTime = 0.0f; float currPlaybackTime = 0.0f;
bool isPlaying = false; bool isPlaying = true;
// Useful Cached Data // Useful Cached Data
float secsPerTick = 0.0f; float secsPerTick = 0.0f;
// Buffer // Buffer

View File

@ -55,15 +55,20 @@ namespace SHADE
// No keyframes at all, means no changes // No keyframes at all, means no changes
if (nextKeyFrame == keyframes.end()) if (nextKeyFrame == keyframes.end())
return T(); return T();
// At the back, so no keyframes will follow // Out of range, clamp to the back
else else
return firstKeyFrame->Data; return nextKeyFrame->Data;
} }
// At the front, so no prior key frames // At the front, so no prior key frames
else if (nextKeyFrame != keyframes.end()) else if (nextKeyFrame != keyframes.end())
{ {
return nextKeyFrame->Data; return nextKeyFrame->Data;
} }
// At the back, so no keyframes will follow
else
{
return firstKeyFrame->Data;
}
// Get interpolated vector // Get interpolated vector
const float PREV_FRAME_TIME = firstKeyFrame->FrameIndex * secsPerTick; const float PREV_FRAME_TIME = firstKeyFrame->FrameIndex * secsPerTick;

View File

@ -79,6 +79,7 @@ namespace SHADE
void SHModelLoader::ReadAnimNode(FileReference file, SHAnimNodeInfo const& info, SHAnimData& data) void SHModelLoader::ReadAnimNode(FileReference file, SHAnimNodeInfo const& info, SHAnimData& data)
{ {
data.name.resize(info.charCount);
file.read( file.read(
data.name.data(), data.name.data(),
info.charCount info.charCount

View File

@ -607,7 +607,7 @@ namespace SHADE
}, SHDragDrop::DRAG_RESOURCE); }, SHDragDrop::DRAG_RESOURCE);
Handle<SHAnimationClip> const& clip = component->GetCurrentClip(); Handle<SHAnimationClip> const& clip = component->GetCurrentClip();
const auto CLIP_NAME = rig ? SHResourceManager::GetAssetName<SHAnimationClip>(clip).value_or("") : ""; const auto CLIP_NAME = clip ? SHResourceManager::GetAssetName<SHAnimationClip>(clip).value_or("") : "";
SHEditorWidgets::DragDropReadOnlyField<AssetID>("Clip", CLIP_NAME, SHEditorWidgets::DragDropReadOnlyField<AssetID>("Clip", CLIP_NAME,
[component]() [component]()
{ {

View File

@ -380,6 +380,38 @@ namespace SHADE
} }
void SHBatch::UpdateAnimationBuffer(uint32_t frameIndex)
{
// Frame Index check
if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS)
{
SHLOG_WARNING("[SHBatch] Attempted to update animation buffers with an invalid frame index.");
return;
}
// Reset Animation Matrix Data
boneMatrixData.clear();
// Populate on the CPU
for (auto& subBatch : subBatches)
for (auto rendId : subBatch.Renderables)
{
auto animator = SHComponentManager::GetComponent_s<SHAnimatorComponent>(rendId);
if (animator)
{
const auto& MATRICES = animator->GetBoneMatrices();
boneMatrixData.insert(boneMatrixData.end(), MATRICES.cbegin(), MATRICES.cend());
}
}
// Update GPU Buffers
const uint32_t BONE_MTX_DATA_BYTES = static_cast<uint32_t>(boneMatrixData.size() * sizeof(SHMatrix));
if (boneMatrixBuffer[frameIndex])
{
boneMatrixBuffer[frameIndex]->WriteToMemory(boneMatrixData.data(), BONE_MTX_DATA_BYTES, 0, 0);
}
}
void SHBatch::Build(Handle<SHVkLogicalDevice> _device, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) void SHBatch::Build(Handle<SHVkLogicalDevice> _device, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex)
{ {
if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS) if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS)
@ -557,6 +589,17 @@ namespace SHADE
BuffUsage::eVertexBuffer, BuffUsage::eVertexBuffer,
"Batch Instance Data Buffer" "Batch Instance Data Buffer"
); );
// - Bone Matrix Indices
if (!boneMatrixIndices.empty())
{
const uint32_t BMI_DATA_BYTES = static_cast<uint32_t>(boneMatrixIndices.size() * sizeof(uint32_t));
SHVkUtil::EnsureBufferAndCopyHostVisibleData
(
device, boneMatrixFirstIndexBuffer[frameIndex], boneMatrixIndices.data(), BMI_DATA_BYTES,
BuffUsage::eVertexBuffer,
"Batch Instance Bone Matrix First Index Buffer"
);
}
// - Material and bone buffers/descriptor sets // - Material and bone buffers/descriptor sets
rebuildDescriptorSetBuffers(frameIndex, descPool); rebuildDescriptorSetBuffers(frameIndex, descPool);
} }
@ -590,6 +633,10 @@ namespace SHADE
cmdBuffer->BindPipeline(pipeline); cmdBuffer->BindPipeline(pipeline);
cmdBuffer->BindVertexBuffer(SHGraphicsConstants::VertexBufferBindings::TRANSFORM, transformDataBuffer[frameIndex], 0); cmdBuffer->BindVertexBuffer(SHGraphicsConstants::VertexBufferBindings::TRANSFORM, transformDataBuffer[frameIndex], 0);
cmdBuffer->BindVertexBuffer(SHGraphicsConstants::VertexBufferBindings::INTEGER_DATA, instancedIntegerBuffer[frameIndex], 0); cmdBuffer->BindVertexBuffer(SHGraphicsConstants::VertexBufferBindings::INTEGER_DATA, instancedIntegerBuffer[frameIndex], 0);
if (boneMatrixFirstIndexBuffer[frameIndex])
{
cmdBuffer->BindVertexBuffer(SHGraphicsConstants::VertexBufferBindings::BONE_MATRIX_FIRST_INDEX, boneMatrixFirstIndexBuffer[frameIndex], 0);
}
auto const& descMappings = SHGraphicsPredefinedData::GetMappings(SHGraphicsPredefinedData::SystemType::BATCHING); auto const& descMappings = SHGraphicsPredefinedData::GetMappings(SHGraphicsPredefinedData::SystemType::BATCHING);
if (instanceDataDescSet[frameIndex]) if (instanceDataDescSet[frameIndex])

View File

@ -86,6 +86,7 @@ namespace SHADE
void UpdateMaterialBuffer(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool); void UpdateMaterialBuffer(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool);
void UpdateTransformBuffer(uint32_t frameIndex); void UpdateTransformBuffer(uint32_t frameIndex);
void UpdateInstancedIntegerBuffer(uint32_t frameIndex); void UpdateInstancedIntegerBuffer(uint32_t frameIndex);
void UpdateAnimationBuffer(uint32_t frameIndex);
void Build(Handle<SHVkLogicalDevice> device, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex); void Build(Handle<SHVkLogicalDevice> device, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex);
void Draw(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex); void Draw(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex);
@ -134,6 +135,7 @@ namespace SHADE
TripleBuffer instancedIntegerBuffer; TripleBuffer instancedIntegerBuffer;
TripleBuffer matPropsBuffer; TripleBuffer matPropsBuffer;
TripleBuffer boneMatrixBuffer; TripleBuffer boneMatrixBuffer;
TripleBuffer boneMatrixFirstIndexBuffer; // Instanced buffer, indicates where the first bone matrix is
TripleDescSet instanceDataDescSet; TripleDescSet instanceDataDescSet;
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/

View File

@ -94,6 +94,7 @@ namespace SHADE
{ {
batch.UpdateMaterialBuffer(frameIndex, descPool); batch.UpdateMaterialBuffer(frameIndex, descPool);
batch.UpdateTransformBuffer(frameIndex); batch.UpdateTransformBuffer(frameIndex);
batch.UpdateAnimationBuffer(frameIndex);
batch.UpdateInstancedIntegerBuffer(frameIndex); batch.UpdateInstancedIntegerBuffer(frameIndex);
} }
} }

View File

@ -218,6 +218,7 @@ namespace SHADE
defaultVertexInputState.AddBinding(true , true , { SHVertexAttribute(SHAttribFormat::UINT32_2D) }); // Instanced integer data at index 8 defaultVertexInputState.AddBinding(true , true , { SHVertexAttribute(SHAttribFormat::UINT32_2D) }); // Instanced integer data at index 8
defaultVertexInputState.AddBinding(false, false, { SHVertexAttribute(SHAttribFormat::UINT32_4D) }); // Attribute bone indices at index 9 defaultVertexInputState.AddBinding(false, false, { SHVertexAttribute(SHAttribFormat::UINT32_4D) }); // Attribute bone indices at index 9
defaultVertexInputState.AddBinding(false, false, { SHVertexAttribute(SHAttribFormat::FLOAT_4D) }); // Attribute bone weights at index 10 defaultVertexInputState.AddBinding(false, false, { SHVertexAttribute(SHAttribFormat::FLOAT_4D) }); // Attribute bone weights at index 10
defaultVertexInputState.AddBinding(true , true , { SHVertexAttribute(SHAttribFormat::UINT32_1D) }); // Instance bone matrix first index at index 11
} }
void SHGraphicsPredefinedData::Init(Handle<SHVkLogicalDevice> logicalDevice) noexcept void SHGraphicsPredefinedData::Init(Handle<SHVkLogicalDevice> logicalDevice) noexcept

View File

@ -234,6 +234,13 @@ namespace SHADE
*/ */
/***************************************************************************/ /***************************************************************************/
static constexpr uint32_t BONE_WEIGHTS = 7; static constexpr uint32_t BONE_WEIGHTS = 7;
/***************************************************************************/
/*!
\brief
Vertex buffer bindings for the bone matrix first index buffer.
*/
/***************************************************************************/
static constexpr uint32_t BONE_MATRIX_FIRST_INDEX = 8;
static constexpr uint32_t CALCULATED_GLYPH_POSITION = 0; static constexpr uint32_t CALCULATED_GLYPH_POSITION = 0;
static constexpr uint32_t GLYPH_INDEX = 1; static constexpr uint32_t GLYPH_INDEX = 1;