From 841948b82cd56821036f2ccd115bc412e48d8d59 Mon Sep 17 00:00:00 2001 From: Kah Wei Date: Sun, 20 Nov 2022 01:33:55 +0800 Subject: [PATCH] Added support for Bone Weights and Bone Indices vertex attributes for meshes --- Assets/Shaders/DefaultSkinned_VS.glsl | 65 +++ .../Assets/Asset Types/Models/SHMeshAsset.h | 14 +- .../MiddleEnd/Interface/SHGraphicsConstants.h | 14 + .../MiddleEnd/Interface/SHGraphicsSystem.cpp | 11 +- .../MiddleEnd/Interface/SHGraphicsSystem.h | 2 +- .../MiddleEnd/Interface/SHMeshLibrary.cpp | 400 ++++++++++-------- .../MiddleEnd/Interface/SHMeshLibrary.h | 334 ++++++++------- .../MiddleEnd/Meshes/SHPrimitiveGenerator.cpp | 8 +- 8 files changed, 505 insertions(+), 343 deletions(-) create mode 100644 Assets/Shaders/DefaultSkinned_VS.glsl diff --git a/Assets/Shaders/DefaultSkinned_VS.glsl b/Assets/Shaders/DefaultSkinned_VS.glsl new file mode 100644 index 00000000..22199ff5 --- /dev/null +++ b/Assets/Shaders/DefaultSkinned_VS.glsl @@ -0,0 +1,65 @@ +#version 450 +#extension GL_KHR_vulkan_glsl : enable + +//#include "ShaderDescriptorDefinitions.glsl" + + +layout(location = 0) in vec3 aVertexPos; +layout(location = 1) in vec2 aUV; +layout(location = 2) in vec3 aNormal; +layout(location = 3) in vec3 aTangent; +layout(location = 4) in mat4 worldTransform; +layout(location = 5) in ivec4 aBoneIndices; +layout(location = 6) in vec4 aBoneWeights; +layout(location = 8) in uvec2 integerData; + + +layout(location = 0) out struct +{ + vec4 vertPos; // location 0 + vec2 uv; // location = 1 + vec4 normal; // location = 2 + +} Out; + +// material stuff +layout(location = 3) out struct +{ + int materialIndex; + uint eid; + uint lightLayerIndex; + +} Out2; + +layout(set = 2, binding = 0) uniform CameraData +{ + vec4 position; + mat4 vpMat; + mat4 viewMat; + mat4 projMat; +} cameraData; + +void main() +{ + Out2.materialIndex = gl_InstanceIndex; + Out2.eid = integerData[0]; + Out2.lightLayerIndex = integerData[1]; + + // for transforming gBuffer position and normal data + mat4 modelViewMat = cameraData.viewMat * worldTransform; + + // gBuffer position will be in view space + Out.vertPos = modelViewMat * vec4(aVertexPos, 1.0f); + + // uvs for texturing in fragment shader + Out.uv = aUV; + + mat3 transposeInv = mat3 (transpose(inverse(modelViewMat))); + + // normals are also in view space + Out.normal.rgb = transposeInv * aNormal.rgb; + Out.normal.rgb = normalize (Out.normal.rgb); + + // clip space for rendering + gl_Position = cameraData.vpMat * worldTransform * vec4 (aVertexPos, 1.0f); +} \ No newline at end of file diff --git a/SHADE_Engine/src/Assets/Asset Types/Models/SHMeshAsset.h b/SHADE_Engine/src/Assets/Asset Types/Models/SHMeshAsset.h index c10e0cc3..e8780669 100644 --- a/SHADE_Engine/src/Assets/Asset Types/Models/SHMeshAsset.h +++ b/SHADE_Engine/src/Assets/Asset Types/Models/SHMeshAsset.h @@ -48,13 +48,13 @@ namespace SHADE struct SH_API SHMeshAsset : SHAssetData { - SHMeshDataHeader header; - std::vector VertexPositions; - std::vector VertexTangents; - std::vector VertexNormals; - std::vector VertexTexCoords; + SHMeshDataHeader header; + std::vector VertexPositions; + std::vector VertexTangents; + std::vector VertexNormals; + std::vector VertexTexCoords; std::vector Indices; - std::vector BonesInfo; - std::vector Bones; + std::vector VertexBoneIndices; + std::vector VertexBoneWeights; }; } diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsConstants.h b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsConstants.h index 0a67cd9f..b1da9242 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsConstants.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsConstants.h @@ -176,6 +176,20 @@ namespace SHADE */ /***************************************************************************/ static constexpr uint32_t INTEGER_DATA = 5; + /***************************************************************************/ + /*! + \brief + Vertex buffer bindings for the bone indices buffer. + */ + /***************************************************************************/ + static constexpr uint32_t BONE_INDICES = 6; + /***************************************************************************/ + /*! + \brief + Vertex buffer bindings for the bone weights buffer. + */ + /***************************************************************************/ + static constexpr uint32_t BONE_WEIGHTS = 7; }; diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp index 5b40a745..8f6ad9c9 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp @@ -432,6 +432,8 @@ namespace SHADE std::make_pair(meshLibrary.GetVertexTexCoordsBuffer(), SHGraphicsConstants::VertexBufferBindings::TEX_COORD), std::make_pair(meshLibrary.GetVertexNormalsBuffer(), SHGraphicsConstants::VertexBufferBindings::NORMAL), std::make_pair(meshLibrary.GetVertexTangentsBuffer(), SHGraphicsConstants::VertexBufferBindings::TANGENT), + std::make_pair(meshLibrary.GetVertexBoneIndicesBuffer(), SHGraphicsConstants::VertexBufferBindings::BONE_INDICES), + std::make_pair(meshLibrary.GetVertexBoneWeightsBuffer(), SHGraphicsConstants::VertexBufferBindings::BONE_WEIGHTS), std::make_pair(meshLibrary.GetIndexBuffer(), 0), }; @@ -483,6 +485,11 @@ namespace SHADE // Bind all the buffers required for meshes for (auto& [buffer, bindingPoint] : MESH_DATA) { + // Ignore invalid buffers + if (!buffer) + continue; + + // Assign based on type if (buffer->GetUsageBits() & vk::BufferUsageFlagBits::eVertexBuffer) currentCmdBuffer->BindVertexBuffer(bindingPoint, buffer, 0); else if (buffer->GetUsageBits() & vk::BufferUsageFlagBits::eIndexBuffer) @@ -721,9 +728,9 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ /* Mesh Registration Functions */ /*---------------------------------------------------------------------------------*/ - SHADE::Handle SHGraphicsSystem::AddMesh(uint32_t vertexCount, const SHMesh::VertexPosition* const positions, const SHMesh::VertexTexCoord* const texCoords, const SHMesh::VertexTangent* const tangents, const SHMesh::VertexNormal* const normals, uint32_t indexCount, const SHMesh::Index* const indices) + SHADE::Handle SHGraphicsSystem::AddMesh(uint32_t vertexCount, const SHMesh::VertexPosition* const positions, const SHMesh::VertexTexCoord* const texCoords, const SHMesh::VertexTangent* const tangents, const SHMesh::VertexNormal* const normals, uint32_t indexCount, const SHMesh::Index* const indices, const SHMesh::VertexBoneIndices* const boneIndices, const SHMesh::VertexWeights* const boneWeights) { - return meshLibrary.AddMesh(vertexCount, positions, texCoords, tangents, normals, indexCount, indices); + return meshLibrary.AddMesh(vertexCount, positions, texCoords, tangents, normals, boneIndices, boneWeights, indexCount, indices); } void SHGraphicsSystem::RemoveMesh(Handle mesh) diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.h b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.h index 2a186041..d7e43aea 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.h @@ -204,7 +204,7 @@ namespace SHADE */ /*******************************************************************************/ - Handle AddMesh(uint32_t vertexCount, const SHMesh::VertexPosition* const positions, const SHMesh::VertexTexCoord* const texCoords, const SHMesh::VertexTangent* const tangents, const SHMesh::VertexNormal* const normals, uint32_t indexCount, const SHMesh::Index* const indices); + Handle AddMesh(uint32_t vertexCount, const SHMesh::VertexPosition* const positions, const SHMesh::VertexTexCoord* const texCoords, const SHMesh::VertexTangent* const tangents, const SHMesh::VertexNormal* const normals, uint32_t indexCount, const SHMesh::Index* const indices, const SHMesh::VertexBoneIndices* const boneIndices = nullptr, const SHMesh::VertexWeights* const boneWeights = nullptr); /*******************************************************************************/ /*! diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMeshLibrary.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMeshLibrary.cpp index d34c1b7d..dda5d423 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMeshLibrary.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMeshLibrary.cpp @@ -3,7 +3,7 @@ \author Tng Kah Wei, kahwei.tng, 390009620 \par email: kahwei.tng\@digipen.edu \date Aug 30, 2022 -\brief Contains definitions for all of the functions of the classes that deal +\brief Contains definitions for all of the functions of the classes that deal with storage and management of vertex and index buffers of meshes. Copyright (C) 2022 DigiPen Institute of Technology. @@ -20,187 +20,239 @@ of DigiPen Institute of Technology is prohibited. namespace SHADE { - SHADE::Handle SHMeshLibrary::AddMesh(uint32_t vertexCount, const SHMesh::VertexPosition* const positions, const SHMesh::VertexTexCoord* const texCoords, const SHMesh::VertexTangent* const tangents, const SHMesh::VertexNormal* const normals, uint32_t indexCount, const SHMesh::Index* const indices) - { - isDirty = true; + SHADE::Handle SHMeshLibrary::AddMesh + ( + uint32_t vertexCount, const SHMesh::VertexPosition* const positions, + const SHMesh::VertexTexCoord* const texCoords, + const SHMesh::VertexTangent* const tangents, + const SHMesh::VertexNormal* const normals, + const SHMesh::VertexBoneIndices* const boneIndices, + const SHMesh::VertexWeights* const boneWeights, + uint32_t indexCount, const SHMesh::Index* const indices) + { + isDirty = true; - auto handle = meshes.Create(); - meshAddJobs.emplace_back( MeshAddJob - { - vertexCount, - positions, - texCoords, - tangents, - normals, - indexCount, - indices, - handle - }); - return handle; - } - - void SHMeshLibrary::RemoveMesh(Handle mesh) + auto handle = meshes.Create(); + meshAddJobs.emplace_back(MeshAddJob { - if (!mesh) - throw std::invalid_argument("Attempted to remove a Mesh that did not belong to the Mesh Library!"); - - meshRemoveJobs.emplace_back(mesh); - isDirty = true; + vertexCount, + positions, + texCoords, + tangents, + normals, + boneIndices, + boneWeights, + indexCount, + indices, + handle + }); + return handle; + } + + void SHMeshLibrary::RemoveMesh(Handle mesh) + { + if (!mesh) + throw std::invalid_argument("Attempted to remove a Mesh that did not belong to the Mesh Library!"); + + meshRemoveJobs.emplace_back(mesh); + isDirty = true; + } + + void SHMeshLibrary::BuildBuffers(Handle device, Handle cmdBuffer) + { + // No changes + if (!isDirty) + return; + + // Remove + if (!meshRemoveJobs.empty()) + { + // - Remove from order list + for (const auto& meshToRemove : meshRemoveJobs) + { + auto searchResult = std::find(meshOrder.begin(), meshOrder.end(), meshToRemove); + // Shouldn't happen, ignore + if (searchResult == meshOrder.end()) + continue; + + // Remove from mesh list + meshOrder.erase(searchResult); + } + meshRemoveJobs.clear(); + // - Shift existing elements in to close up the gaps + int32_t nextVertInsertPoint = 0; + uint32_t nextIdxInsertPoint = 0; + for (auto& mesh : meshOrder) + { + // Check if already in the correct place + if (nextVertInsertPoint != mesh->FirstVertex) + { + /* There's a gap, we need to shift */ + // Vertices + vertPosStorage.erase(vertPosStorage.begin() + nextVertInsertPoint, vertPosStorage.begin() + mesh->FirstVertex); + vertTexCoordStorage.erase(vertTexCoordStorage.begin() + nextVertInsertPoint, vertTexCoordStorage.begin() + mesh->FirstVertex); + vertTangentStorage.erase(vertTangentStorage.begin() + nextVertInsertPoint, vertTangentStorage.begin() + mesh->FirstVertex); + vertNormalStorage.erase(vertNormalStorage.begin() + nextVertInsertPoint, vertNormalStorage.begin() + mesh->FirstVertex); + vertBoneIdxStorage.erase(vertBoneIdxStorage.begin() + nextVertInsertPoint, vertBoneIdxStorage.begin() + mesh->FirstVertex); + vertBoneWeightStorage.erase(vertBoneWeightStorage.begin() + nextVertInsertPoint, vertBoneWeightStorage.begin() + mesh->FirstVertex); + // - Update mesh data + mesh->FirstVertex = nextVertInsertPoint; + + // Indices + indexStorage.erase(indexStorage.begin() + nextIdxInsertPoint, indexStorage.begin() + mesh->FirstIndex); + // - Update mesh data + mesh->FirstIndex = nextIdxInsertPoint; + + // Prepare for next + nextVertInsertPoint += mesh->VertexCount; + nextIdxInsertPoint += mesh->IndexCount; + } + } } - void SHMeshLibrary::BuildBuffers(Handle device, Handle cmdBuffer) + // Add + if (!meshAddJobs.empty()) { - // No changes - if (!isDirty) - return; - - // Remove - if (!meshRemoveJobs.empty()) + // - Compute updated size + size_t newVertElems = vertPosStorage.size(); + size_t newIdxElems = indexStorage.size(); + for (const auto& addJob : meshAddJobs) + { + newVertElems += addJob.VertexCount; + newIdxElems += addJob.IndexCount; + } + // - Reserve new memory + vertPosStorage.reserve(newVertElems); + vertTexCoordStorage.reserve(newVertElems); + vertTangentStorage.reserve(newVertElems); + vertNormalStorage.reserve(newVertElems); + vertBoneIdxStorage.reserve(newVertElems); + vertBoneWeightStorage.reserve(newVertElems); + indexStorage.reserve(newIdxElems); + // - Append new data + for (auto& addJob : meshAddJobs) + { + // Update handle + SHMesh& meshData = *addJob.Handle; + meshData = SHMesh { - // - Remove from order list - for (const auto& meshToRemove : meshRemoveJobs) - { - auto searchResult = std::find(meshOrder.begin(), meshOrder.end(), meshToRemove); - // Shouldn't happen, ignore - if (searchResult == meshOrder.end()) - continue; + .FirstVertex = static_cast(vertPosStorage.size()), + .VertexCount = static_cast(addJob.VertexCount), + .FirstIndex = static_cast(indexStorage.size()), + .IndexCount = static_cast(addJob.IndexCount), + }; - // Remove from mesh list - meshOrder.erase(searchResult); - } - meshRemoveJobs.clear(); - // - Shift existing elements in to close up the gaps - int32_t nextVertInsertPoint = 0; - uint32_t nextIdxInsertPoint = 0; - for (auto& mesh : meshOrder) - { - // Check if already in the correct place - if (nextVertInsertPoint != mesh->FirstVertex) - { - /* There's a gap, we need to shift */ - // Vertices - vertPosStorage.erase(vertPosStorage.begin() + nextVertInsertPoint, vertPosStorage.begin() + mesh->FirstVertex); - vertTexCoordStorage.erase(vertTexCoordStorage.begin() + nextVertInsertPoint, vertTexCoordStorage.begin() + mesh->FirstVertex); - vertTangentStorage.erase(vertTangentStorage.begin() + nextVertInsertPoint, vertTangentStorage.begin() + mesh->FirstVertex); - vertNormalStorage.erase(vertNormalStorage.begin() + nextVertInsertPoint, vertNormalStorage.begin() + mesh->FirstVertex); - // - Update mesh data - mesh->FirstVertex = nextVertInsertPoint; - - // Indices - indexStorage.erase(indexStorage.begin() + nextIdxInsertPoint, indexStorage.begin() + mesh->FirstIndex); - // - Update mesh data - mesh->FirstIndex = nextIdxInsertPoint; - - // Prepare for next - nextVertInsertPoint += mesh->VertexCount; - nextIdxInsertPoint += mesh->IndexCount; - } - } - } - - // Add - if (!meshAddJobs.empty()) + // Copy into storage + vertPosStorage.insert + ( + vertPosStorage.end(), + addJob.VertexPositions, addJob.VertexPositions + addJob.VertexCount + ); + vertTexCoordStorage.insert + ( + vertTexCoordStorage.end(), + addJob.VertexTexCoords, addJob.VertexTexCoords + addJob.VertexCount + ); + vertTangentStorage.insert + ( + vertTangentStorage.end(), + addJob.VertexTangents, addJob.VertexTangents + addJob.VertexCount + ); + vertNormalStorage.insert + ( + vertNormalStorage.end(), + addJob.VertexNormals, addJob.VertexNormals + addJob.VertexCount + ); + if (addJob.VertexBoneIndices) { - // - Compute updated size - size_t newVertElems = vertPosStorage.size(); - size_t newIdxElems = indexStorage.size(); - for (const auto& addJob : meshAddJobs) - { - newVertElems += addJob.VertexCount; - newIdxElems += addJob.IndexCount; - } - // - Reserve new memory - vertPosStorage .reserve(newVertElems); - vertTexCoordStorage.reserve(newVertElems); - vertTangentStorage .reserve(newVertElems); - vertNormalStorage .reserve(newVertElems); - indexStorage .reserve(newIdxElems); - // - Append new data - for (auto& addJob : meshAddJobs) - { - // Update handle - SHMesh& meshData = *addJob.Handle; - meshData = SHMesh - { - .FirstVertex = static_cast(vertPosStorage.size()), - .VertexCount = static_cast(addJob.VertexCount), - .FirstIndex = static_cast(indexStorage.size()), - .IndexCount = static_cast(addJob.IndexCount), - }; - - // Copy into storage - vertPosStorage.insert - ( - vertPosStorage.end(), - addJob.VertexPositions, addJob.VertexPositions + addJob.VertexCount - ); - vertTexCoordStorage.insert - ( - vertTexCoordStorage.end(), - addJob.VertexTexCoords, addJob.VertexTexCoords + addJob.VertexCount - ); - vertTangentStorage.insert - ( - vertTangentStorage.end(), - addJob.VertexTangents, addJob.VertexTangents + addJob.VertexCount - ); - vertNormalStorage.insert - ( - vertNormalStorage.end(), - addJob.VertexNormals, addJob.VertexNormals + addJob.VertexCount - ); - indexStorage.insert - ( - indexStorage.end(), - addJob.Indices, addJob.Indices + addJob.IndexCount - ); - } - meshAddJobs.clear(); + vertBoneIdxStorage.insert + ( + vertBoneIdxStorage.end(), + addJob.VertexBoneIndices, addJob.VertexBoneIndices + addJob.VertexCount * SHMesh::BONE_INDICES_PER_VERTEX + ); } - - // Send to GPU - using BuffUsage = vk::BufferUsageFlagBits; - SHVkUtil::EnsureBufferAndCopyData - ( - device, cmdBuffer, vertPosBuffer, - vertPosStorage.data(), - static_cast(vertPosStorage.size()) * sizeof(SHMesh::VertexPosition), - BuffUsage::eVertexBuffer, - "Mesh Library Vertex Positions" - ); - SHVkUtil::EnsureBufferAndCopyData - ( - device, cmdBuffer, vertTexCoordBuffer, - vertTexCoordStorage.data(), - static_cast(vertTexCoordStorage.size()) * sizeof(SHMesh::VertexTexCoord), - BuffUsage::eVertexBuffer, - "Mesh Library Vertex TexCoords" - ); - SHVkUtil::EnsureBufferAndCopyData - ( - device, cmdBuffer, vertTangentBuffer, - vertTangentStorage.data(), - static_cast(vertTangentStorage.size()) * sizeof(SHMesh::VertexTangent), - BuffUsage::eVertexBuffer, - "Mesh Library Vertex Tangents" - ); - SHVkUtil::EnsureBufferAndCopyData - ( - device, cmdBuffer, vertNormalBuffer, - vertNormalStorage.data(), - static_cast(vertNormalStorage.size()) * sizeof(SHMesh::VertexNormal), - BuffUsage::eVertexBuffer, - "Mesh Library Vertex Normals" - ); - SHVkUtil::EnsureBufferAndCopyData - ( - device, cmdBuffer, indexBuffer, - indexStorage.data(), - static_cast(indexStorage.size()) * sizeof(SHMesh::Index), - BuffUsage::eIndexBuffer, - "Mesh Library Indices" - ); - - isDirty = false; + if (addJob.VertexBoneWeights) + { + vertBoneWeightStorage.insert + ( + vertBoneWeightStorage.end(), + addJob.VertexBoneWeights, addJob.VertexBoneWeights + addJob.VertexCount + ); + } + indexStorage.insert + ( + indexStorage.end(), + addJob.Indices, addJob.Indices + addJob.IndexCount + ); + } + meshAddJobs.clear(); } + + // Send to GPU + using BuffUsage = vk::BufferUsageFlagBits; + SHVkUtil::EnsureBufferAndCopyData + ( + device, cmdBuffer, vertPosBuffer, + vertPosStorage.data(), + static_cast(vertPosStorage.size()) * sizeof(SHMesh::VertexPosition), + BuffUsage::eVertexBuffer, + "Mesh Library Vertex Positions" + ); + SHVkUtil::EnsureBufferAndCopyData + ( + device, cmdBuffer, vertTexCoordBuffer, + vertTexCoordStorage.data(), + static_cast(vertTexCoordStorage.size()) * sizeof(SHMesh::VertexTexCoord), + BuffUsage::eVertexBuffer, + "Mesh Library Vertex TexCoords" + ); + SHVkUtil::EnsureBufferAndCopyData + ( + device, cmdBuffer, vertTangentBuffer, + vertTangentStorage.data(), + static_cast(vertTangentStorage.size()) * sizeof(SHMesh::VertexTangent), + BuffUsage::eVertexBuffer, + "Mesh Library Vertex Tangents" + ); + SHVkUtil::EnsureBufferAndCopyData + ( + device, cmdBuffer, vertNormalBuffer, + vertNormalStorage.data(), + static_cast(vertNormalStorage.size()) * sizeof(SHMesh::VertexNormal), + BuffUsage::eVertexBuffer, + "Mesh Library Vertex Normals" + ); + if (!vertBoneIdxStorage.empty()) + { + SHVkUtil::EnsureBufferAndCopyData + ( + device, cmdBuffer, vertBoneIdxBuffer, + vertBoneIdxStorage.data(), + static_cast(vertBoneIdxStorage.size()) * sizeof(SHMesh::VertexBoneIndices), + BuffUsage::eVertexBuffer, + "Mesh Library Vertex Bone Indices" + ); + } + if (!vertBoneWeightStorage.empty()) + { + SHVkUtil::EnsureBufferAndCopyData + ( + device, cmdBuffer, vertBoneWeightBuffer, + vertBoneWeightStorage.data(), + static_cast(vertBoneWeightStorage.size()) * sizeof(SHMesh::VertexWeights), + BuffUsage::eVertexBuffer, + "Mesh Library Vertex Bone Weights" + ); + } + SHVkUtil::EnsureBufferAndCopyData + ( + device, cmdBuffer, indexBuffer, + indexStorage.data(), + static_cast(indexStorage.size()) * sizeof(SHMesh::Index), + BuffUsage::eIndexBuffer, + "Mesh Library Indices" + ); + + isDirty = false; + } } diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMeshLibrary.h b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMeshLibrary.h index b0cbdce1..f61e4a20 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMeshLibrary.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMeshLibrary.h @@ -19,170 +19,192 @@ of DigiPen Institute of Technology is prohibited. #include "Resource/SHResourceLibrary.h" #include "Math/Vector/SHVec2.h" #include "Math/Vector/SHVec3.h" +#include "Math/Vector/SHVec4.h" namespace SHADE { - /*---------------------------------------------------------------------------------*/ - /* Forward Declarations */ - /*---------------------------------------------------------------------------------*/ - class SHVkBuffer; - class SHVkLogicalDevice; - class SHVkCommandBuffer; + /*---------------------------------------------------------------------------------*/ + /* Forward Declarations */ + /*---------------------------------------------------------------------------------*/ + class SHVkBuffer; + class SHVkLogicalDevice; + class SHVkCommandBuffer; - /*---------------------------------------------------------------------------------*/ - /* Type Definitions */ - /*---------------------------------------------------------------------------------*/ - /***********************************************************************************/ + /*---------------------------------------------------------------------------------*/ + /* Type Definitions */ + /*---------------------------------------------------------------------------------*/ + /***********************************************************************************/ + /*! + \brief + Represents a single mesh that is stored in a SHMeshLibrary. + */ + /***********************************************************************************/ + class SHMesh + { + public: + /*-----------------------------------------------------------------------------*/ + /* Type Definitions */ + /*-----------------------------------------------------------------------------*/ + using Index = uint32_t; + using VertexPosition = SHVec3; + using VertexTexCoord = SHVec2; + using VertexTangent = SHVec3; + using VertexNormal = SHVec3; + using VertexBoneIndices = int; + using VertexWeights = SHVec4; + + /*-----------------------------------------------------------------------------*/ + /* Constants */ + /*-----------------------------------------------------------------------------*/ + static constexpr size_t BONE_INDICES_PER_VERTEX = 4; + + /*-----------------------------------------------------------------------------*/ + /* Data Members */ + /*-----------------------------------------------------------------------------*/ + int32_t FirstVertex; + uint32_t VertexCount; + uint32_t FirstIndex; + uint32_t IndexCount; + }; + /***********************************************************************************/ + /*! + \brief + Manages storage for all Meshes in the Graphics System as a single set of Vertex + and Index Buffers. + */ + /***********************************************************************************/ + class SHMeshLibrary + { + public: + /*-----------------------------------------------------------------------------*/ + /* Usage Functions */ + /*-----------------------------------------------------------------------------*/ + /*******************************************************************************/ /*! - \brief - Represents a single mesh that is stored in a SHMeshLibrary. - */ - /***********************************************************************************/ - class SHMesh - { - public: - /*-----------------------------------------------------------------------------*/ - /* Type Definitions */ - /*-----------------------------------------------------------------------------*/ - using Index = uint32_t; - using VertexPosition = SHVec3; - using VertexTexCoord = SHVec2; - using VertexTangent = SHVec3; - using VertexNormal = SHVec3; - /*-----------------------------------------------------------------------------*/ - /* Data Members */ - /*-----------------------------------------------------------------------------*/ - int32_t FirstVertex; - uint32_t VertexCount; - uint32_t FirstIndex; - uint32_t IndexCount; - }; - /***********************************************************************************/ + \brief + Adds a mesh to the Mesh Library. But this does not mean that the meshes have + been added yet. A call to "BuildBuffers()" is required to transfer all + meshes into the GPU. + + \param vertexCount + Number of vertices in this Mesh. + \param positions + Pointer to the first in a contiguous array of SHMathVec3s that define vertex + positions. + \param texCoords + Pointer to the first in a contiguous array of SHMathVec2s that define vertex + texture coordinates. + \param tangents + Pointer to the first in a contiguous array of SHMathVec3s that define vertex + tangents. + \param normals + Pointer to the first in a contiguous array of SHMathVec3s that define vertex + normals. + \param indexCount + Number of indices in this mesh. + \param indices + Pointer to the first in a contiguous array of uint32_ts that define mesh + indicies. + + \return + Handle to the created Mesh. This is not valid to be used until a call to + BuildBuffers(). + + */ + /*******************************************************************************/ + Handle AddMesh(uint32_t vertexCount, const SHMesh::VertexPosition* const positions, + const SHMesh::VertexTexCoord* const texCoords, + const SHMesh::VertexTangent* const tangents, + const SHMesh::VertexNormal* const normals, + const SHMesh::VertexBoneIndices* const boneIndices, + const SHMesh::VertexWeights* const boneWeights, + uint32_t indexCount, const SHMesh::Index* const indices); + /*******************************************************************************/ /*! - \brief - Manages storage for all Meshes in the Graphics System as a single set of Vertex - and Index Buffers. + + \brief + Removes a mesh from the MeshLibrary. But this does not mean that the meshes + have been removed yet. A call to "BuildBuffers()" is required to finalise all + changes. + + \param mesh + Handle to the mesh to remove. + */ - /***********************************************************************************/ - class SHMeshLibrary + /*******************************************************************************/ + void RemoveMesh(Handle mesh); + /***************************************************************************/ + /*! + + \brief + Finalises all changes to the MeshLibrary into the GPU buffers. + + \param device + Device used to create and update the buffers. + \param cmdBuffer + Command buffer used to set up transfers of data in the GPU memory. This + call must be preceded by calls to cmdBuffer's BeginRecording() and ended + with EndRecording(). Do recall to also submit the cmdBuffer to a transfer + queue. + */ + /***************************************************************************/ + void BuildBuffers(Handle device, Handle cmdBuffer); + + /*-----------------------------------------------------------------------------*/ + /* Getter Functions */ + /*-----------------------------------------------------------------------------*/ + Handle GetVertexPositionsBuffer() const noexcept { return vertPosBuffer; } + Handle GetVertexTexCoordsBuffer() const noexcept { return vertTexCoordBuffer; } + Handle GetVertexTangentsBuffer() const noexcept { return vertTangentBuffer; } + Handle GetVertexNormalsBuffer() const noexcept { return vertNormalBuffer; } + Handle GetVertexBoneIndicesBuffer() const noexcept { return vertBoneIdxBuffer; } + Handle GetVertexBoneWeightsBuffer() const noexcept { return vertBoneWeightBuffer; } + Handle GetIndexBuffer() const noexcept { return indexBuffer; } + + private: + /*-----------------------------------------------------------------------------*/ + /* Type Definition */ + /*-----------------------------------------------------------------------------*/ + struct MeshAddJob { - public: - /*-----------------------------------------------------------------------------*/ - /* Usage Functions */ - /*-----------------------------------------------------------------------------*/ - /*******************************************************************************/ - /*! - - \brief - Adds a mesh to the Mesh Library. But this does not mean that the meshes have - been added yet. A call to "BuildBuffers()" is required to transfer all - meshes into the GPU. - - \param vertexCount - Number of vertices in this Mesh. - \param positions - Pointer to the first in a contiguous array of SHMathVec3s that define vertex - positions. - \param texCoords - Pointer to the first in a contiguous array of SHMathVec2s that define vertex - texture coordinates. - \param tangents - Pointer to the first in a contiguous array of SHMathVec3s that define vertex - tangents. - \param normals - Pointer to the first in a contiguous array of SHMathVec3s that define vertex - normals. - \param indexCount - Number of indices in this mesh. - \param indices - Pointer to the first in a contiguous array of uint32_ts that define mesh - indicies. - - \return - Handle to the created Mesh. This is not valid to be used until a call to - BuildBuffers(). - - */ - /*******************************************************************************/ - Handle AddMesh(uint32_t vertexCount, const SHMesh::VertexPosition* const positions, const SHMesh::VertexTexCoord* const texCoords, const SHMesh::VertexTangent* const tangents, const SHMesh::VertexNormal* const normals, uint32_t indexCount, const SHMesh::Index* const indices); - /*******************************************************************************/ - /*! - - \brief - Removes a mesh from the MeshLibrary. But this does not mean that the meshes - have been removed yet. A call to "BuildBuffers()" is required to finalise all - changes. - - \param mesh - Handle to the mesh to remove. - - */ - /*******************************************************************************/ - void RemoveMesh(Handle mesh); - /***************************************************************************/ - /*! - - \brief - Finalises all changes to the MeshLibrary into the GPU buffers. - - \param device - Device used to create and update the buffers. - \param cmdBuffer - Command buffer used to set up transfers of data in the GPU memory. This - call must be preceded by calls to cmdBuffer's BeginRecording() and ended - with EndRecording(). Do recall to also submit the cmdBuffer to a transfer - queue. - */ - /***************************************************************************/ - void BuildBuffers(Handle device, Handle cmdBuffer); - - /*-----------------------------------------------------------------------------*/ - /* Getter Functions */ - /*-----------------------------------------------------------------------------*/ - Handle GetVertexPositionsBuffer() const noexcept { return vertPosBuffer; } - Handle GetVertexTexCoordsBuffer() const noexcept { return vertTexCoordBuffer; } - Handle GetVertexTangentsBuffer() const noexcept { return vertTangentBuffer; } - Handle GetVertexNormalsBuffer() const noexcept { return vertNormalBuffer; } - Handle GetIndexBuffer() const { return indexBuffer; } - - private: - /*-----------------------------------------------------------------------------*/ - /* Type Definition */ - /*-----------------------------------------------------------------------------*/ - struct MeshAddJob - { - uint32_t VertexCount = 0; - const SHMesh::VertexPosition* VertexPositions = nullptr; - const SHMesh::VertexTexCoord* VertexTexCoords = nullptr; - const SHMesh::VertexTangent * VertexTangents = nullptr; - const SHMesh::VertexNormal * VertexNormals = nullptr; - uint32_t IndexCount = 0; - const SHMesh::Index * Indices = nullptr; - Handle Handle; - }; - /*-----------------------------------------------------------------------------*/ - /* Data Members */ - /*-----------------------------------------------------------------------------*/ - // Manipulation Queues - std::vector meshAddJobs; - std::vector> meshRemoveJobs; - // Tracking - SHResourceLibrary meshes{}; - std::vector> meshOrder; - // CPU Storage - std::vector vertPosStorage; - std::vector vertTexCoordStorage; - std::vector vertTangentStorage; - std::vector vertNormalStorage; - std::vector indexStorage; - // GPU Storage - Handle vertPosBuffer{}; - Handle vertTexCoordBuffer{}; - Handle vertTangentBuffer{}; - Handle vertNormalBuffer{}; - Handle indexBuffer {}; - // Flags - bool isDirty = true; + uint32_t VertexCount = 0; + const SHMesh::VertexPosition* VertexPositions = nullptr; + const SHMesh::VertexTexCoord* VertexTexCoords = nullptr; + const SHMesh::VertexTangent* VertexTangents = nullptr; + const SHMesh::VertexNormal* VertexNormals = nullptr; + const SHMesh::VertexBoneIndices* VertexBoneIndices = nullptr; + const SHMesh::VertexWeights* VertexBoneWeights = nullptr; + uint32_t IndexCount = 0; + const SHMesh::Index* Indices = nullptr; + Handle Handle; }; + /*-----------------------------------------------------------------------------*/ + /* Data Members */ + /*-----------------------------------------------------------------------------*/ + // Manipulation Queues + std::vector meshAddJobs; + std::vector> meshRemoveJobs; + // Tracking + SHResourceLibrary meshes; + std::vector> meshOrder; + // CPU Storage + std::vector vertPosStorage; + std::vector vertTexCoordStorage; + std::vector vertTangentStorage; + std::vector vertNormalStorage; + std::vector vertBoneIdxStorage; // Must be in multiples of 4 + std::vector vertBoneWeightStorage; + std::vector indexStorage; + // GPU Storage + Handle vertPosBuffer{}; + Handle vertTexCoordBuffer{}; + Handle vertTangentBuffer{}; + Handle vertNormalBuffer{}; + Handle vertBoneIdxBuffer{}; + Handle vertBoneWeightBuffer{}; + Handle indexBuffer{}; + // Flags + bool isDirty = true; + }; } diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Meshes/SHPrimitiveGenerator.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Meshes/SHPrimitiveGenerator.cpp index bf60c7df..c6200929 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Meshes/SHPrimitiveGenerator.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Meshes/SHPrimitiveGenerator.cpp @@ -288,11 +288,13 @@ namespace SHADE { return meshLibrary.AddMesh ( - static_cast(meshData.VertexPositions.size()), + static_cast(meshData.VertexPositions.size()), meshData.VertexPositions.data(), meshData.VertexTexCoords.data(), meshData.VertexTangents.data(), meshData.VertexNormals.data(), + nullptr, + nullptr, static_cast(meshData.Indices.size()), meshData.Indices.data() ); @@ -302,12 +304,12 @@ namespace SHADE { return gfxSystem.AddMesh ( - static_cast(meshData.VertexPositions.size()), + static_cast(meshData.VertexPositions.size()), meshData.VertexPositions.data(), meshData.VertexTexCoords.data(), meshData.VertexTangents.data(), meshData.VertexNormals.data(), - static_cast(meshData.Indices.size()), + static_cast(meshData.Indices.size()), meshData.Indices.data() ); }