Added support for Bone Weights and Bone Indices vertex attributes for meshes

This commit is contained in:
Kah Wei 2022-11-20 01:33:55 +08:00
parent 6fa14aff85
commit 841948b82c
8 changed files with 505 additions and 343 deletions

View File

@ -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);
}

View File

@ -48,13 +48,13 @@ namespace SHADE
struct SH_API SHMeshAsset : SHAssetData struct SH_API SHMeshAsset : SHAssetData
{ {
SHMeshDataHeader header; SHMeshDataHeader header;
std::vector<SHVec3> VertexPositions; std::vector<SHVec3> VertexPositions;
std::vector<SHVec3> VertexTangents; std::vector<SHVec3> VertexTangents;
std::vector<SHVec3> VertexNormals; std::vector<SHVec3> VertexNormals;
std::vector<SHVec2> VertexTexCoords; std::vector<SHVec2> VertexTexCoords;
std::vector<uint32_t> Indices; std::vector<uint32_t> Indices;
std::vector<MeshBoneInfo> BonesInfo; std::vector<int> VertexBoneIndices;
std::vector<MeshBone> Bones; std::vector<SHVec4> VertexBoneWeights;
}; };
} }

View File

@ -176,6 +176,20 @@ namespace SHADE
*/ */
/***************************************************************************/ /***************************************************************************/
static constexpr uint32_t INTEGER_DATA = 5; 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;
}; };

View File

@ -432,6 +432,8 @@ namespace SHADE
std::make_pair(meshLibrary.GetVertexTexCoordsBuffer(), SHGraphicsConstants::VertexBufferBindings::TEX_COORD), std::make_pair(meshLibrary.GetVertexTexCoordsBuffer(), SHGraphicsConstants::VertexBufferBindings::TEX_COORD),
std::make_pair(meshLibrary.GetVertexNormalsBuffer(), SHGraphicsConstants::VertexBufferBindings::NORMAL), std::make_pair(meshLibrary.GetVertexNormalsBuffer(), SHGraphicsConstants::VertexBufferBindings::NORMAL),
std::make_pair(meshLibrary.GetVertexTangentsBuffer(), SHGraphicsConstants::VertexBufferBindings::TANGENT), 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), std::make_pair(meshLibrary.GetIndexBuffer(), 0),
}; };
@ -483,6 +485,11 @@ namespace SHADE
// Bind all the buffers required for meshes // Bind all the buffers required for meshes
for (auto& [buffer, bindingPoint] : MESH_DATA) for (auto& [buffer, bindingPoint] : MESH_DATA)
{ {
// Ignore invalid buffers
if (!buffer)
continue;
// Assign based on type
if (buffer->GetUsageBits() & vk::BufferUsageFlagBits::eVertexBuffer) if (buffer->GetUsageBits() & vk::BufferUsageFlagBits::eVertexBuffer)
currentCmdBuffer->BindVertexBuffer(bindingPoint, buffer, 0); currentCmdBuffer->BindVertexBuffer(bindingPoint, buffer, 0);
else if (buffer->GetUsageBits() & vk::BufferUsageFlagBits::eIndexBuffer) else if (buffer->GetUsageBits() & vk::BufferUsageFlagBits::eIndexBuffer)
@ -721,9 +728,9 @@ namespace SHADE
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Mesh Registration Functions */ /* Mesh Registration Functions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
SHADE::Handle<SHADE::SHMesh> 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<SHADE::SHMesh> 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<SHMesh> mesh) void SHGraphicsSystem::RemoveMesh(Handle<SHMesh> mesh)

View File

@ -204,7 +204,7 @@ namespace SHADE
*/ */
/*******************************************************************************/ /*******************************************************************************/
Handle<SHMesh> 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<SHMesh> 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);
/*******************************************************************************/ /*******************************************************************************/
/*! /*!

View File

@ -20,187 +20,239 @@ of DigiPen Institute of Technology is prohibited.
namespace SHADE namespace SHADE
{ {
SHADE::Handle<SHADE::SHMesh> 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) SHADE::Handle<SHADE::SHMesh> SHMeshLibrary::AddMesh
{ (
isDirty = true; 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(); auto handle = meshes.Create();
meshAddJobs.emplace_back( MeshAddJob meshAddJobs.emplace_back(MeshAddJob
{
vertexCount,
positions,
texCoords,
tangents,
normals,
indexCount,
indices,
handle
});
return handle;
}
void SHMeshLibrary::RemoveMesh(Handle<SHMesh> mesh)
{ {
if (!mesh) vertexCount,
throw std::invalid_argument("Attempted to remove a Mesh that did not belong to the Mesh Library!"); positions,
texCoords,
tangents,
normals,
boneIndices,
boneWeights,
indexCount,
indices,
handle
});
return handle;
}
meshRemoveJobs.emplace_back(mesh); void SHMeshLibrary::RemoveMesh(Handle<SHMesh> mesh)
isDirty = true; {
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<SHVkLogicalDevice> device, Handle<SHVkCommandBuffer> 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<SHVkLogicalDevice> device, Handle<SHVkCommandBuffer> cmdBuffer) // Add
if (!meshAddJobs.empty())
{ {
// No changes // - Compute updated size
if (!isDirty) size_t newVertElems = vertPosStorage.size();
return; size_t newIdxElems = indexStorage.size();
for (const auto& addJob : meshAddJobs)
// Remove {
if (!meshRemoveJobs.empty()) 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 .FirstVertex = static_cast<int32_t>(vertPosStorage.size()),
for (const auto& meshToRemove : meshRemoveJobs) .VertexCount = static_cast<uint32_t>(addJob.VertexCount),
{ .FirstIndex = static_cast<uint32_t>(indexStorage.size()),
auto searchResult = std::find(meshOrder.begin(), meshOrder.end(), meshToRemove); .IndexCount = static_cast<uint32_t>(addJob.IndexCount),
// Shouldn't happen, ignore };
if (searchResult == meshOrder.end())
continue;
// Remove from mesh list // Copy into storage
meshOrder.erase(searchResult); vertPosStorage.insert
} (
meshRemoveJobs.clear(); vertPosStorage.end(),
// - Shift existing elements in to close up the gaps addJob.VertexPositions, addJob.VertexPositions + addJob.VertexCount
int32_t nextVertInsertPoint = 0; );
uint32_t nextIdxInsertPoint = 0; vertTexCoordStorage.insert
for (auto& mesh : meshOrder) (
{ vertTexCoordStorage.end(),
// Check if already in the correct place addJob.VertexTexCoords, addJob.VertexTexCoords + addJob.VertexCount
if (nextVertInsertPoint != mesh->FirstVertex) );
{ vertTangentStorage.insert
/* There's a gap, we need to shift */ (
// Vertices vertTangentStorage.end(),
vertPosStorage.erase(vertPosStorage.begin() + nextVertInsertPoint, vertPosStorage.begin() + mesh->FirstVertex); addJob.VertexTangents, addJob.VertexTangents + addJob.VertexCount
vertTexCoordStorage.erase(vertTexCoordStorage.begin() + nextVertInsertPoint, vertTexCoordStorage.begin() + mesh->FirstVertex); );
vertTangentStorage.erase(vertTangentStorage.begin() + nextVertInsertPoint, vertTangentStorage.begin() + mesh->FirstVertex); vertNormalStorage.insert
vertNormalStorage.erase(vertNormalStorage.begin() + nextVertInsertPoint, vertNormalStorage.begin() + mesh->FirstVertex); (
// - Update mesh data vertNormalStorage.end(),
mesh->FirstVertex = nextVertInsertPoint; addJob.VertexNormals, addJob.VertexNormals + addJob.VertexCount
);
// Indices if (addJob.VertexBoneIndices)
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())
{ {
// - Compute updated size vertBoneIdxStorage.insert
size_t newVertElems = vertPosStorage.size(); (
size_t newIdxElems = indexStorage.size(); vertBoneIdxStorage.end(),
for (const auto& addJob : meshAddJobs) addJob.VertexBoneIndices, addJob.VertexBoneIndices + addJob.VertexCount * SHMesh::BONE_INDICES_PER_VERTEX
{ );
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<int32_t>(vertPosStorage.size()),
.VertexCount = static_cast<uint32_t>(addJob.VertexCount),
.FirstIndex = static_cast<uint32_t>(indexStorage.size()),
.IndexCount = static_cast<uint32_t>(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();
} }
if (addJob.VertexBoneWeights)
// Send to GPU {
using BuffUsage = vk::BufferUsageFlagBits; vertBoneWeightStorage.insert
SHVkUtil::EnsureBufferAndCopyData (
( vertBoneWeightStorage.end(),
device, cmdBuffer, vertPosBuffer, addJob.VertexBoneWeights, addJob.VertexBoneWeights + addJob.VertexCount
vertPosStorage.data(), );
static_cast<uint32_t>(vertPosStorage.size()) * sizeof(SHMesh::VertexPosition), }
BuffUsage::eVertexBuffer, indexStorage.insert
"Mesh Library Vertex Positions" (
); indexStorage.end(),
SHVkUtil::EnsureBufferAndCopyData addJob.Indices, addJob.Indices + addJob.IndexCount
( );
device, cmdBuffer, vertTexCoordBuffer, }
vertTexCoordStorage.data(), meshAddJobs.clear();
static_cast<uint32_t>(vertTexCoordStorage.size()) * sizeof(SHMesh::VertexTexCoord),
BuffUsage::eVertexBuffer,
"Mesh Library Vertex TexCoords"
);
SHVkUtil::EnsureBufferAndCopyData
(
device, cmdBuffer, vertTangentBuffer,
vertTangentStorage.data(),
static_cast<uint32_t>(vertTangentStorage.size()) * sizeof(SHMesh::VertexTangent),
BuffUsage::eVertexBuffer,
"Mesh Library Vertex Tangents"
);
SHVkUtil::EnsureBufferAndCopyData
(
device, cmdBuffer, vertNormalBuffer,
vertNormalStorage.data(),
static_cast<uint32_t>(vertNormalStorage.size()) * sizeof(SHMesh::VertexNormal),
BuffUsage::eVertexBuffer,
"Mesh Library Vertex Normals"
);
SHVkUtil::EnsureBufferAndCopyData
(
device, cmdBuffer, indexBuffer,
indexStorage.data(),
static_cast<uint32_t>(indexStorage.size()) * sizeof(SHMesh::Index),
BuffUsage::eIndexBuffer,
"Mesh Library Indices"
);
isDirty = false;
} }
// Send to GPU
using BuffUsage = vk::BufferUsageFlagBits;
SHVkUtil::EnsureBufferAndCopyData
(
device, cmdBuffer, vertPosBuffer,
vertPosStorage.data(),
static_cast<uint32_t>(vertPosStorage.size()) * sizeof(SHMesh::VertexPosition),
BuffUsage::eVertexBuffer,
"Mesh Library Vertex Positions"
);
SHVkUtil::EnsureBufferAndCopyData
(
device, cmdBuffer, vertTexCoordBuffer,
vertTexCoordStorage.data(),
static_cast<uint32_t>(vertTexCoordStorage.size()) * sizeof(SHMesh::VertexTexCoord),
BuffUsage::eVertexBuffer,
"Mesh Library Vertex TexCoords"
);
SHVkUtil::EnsureBufferAndCopyData
(
device, cmdBuffer, vertTangentBuffer,
vertTangentStorage.data(),
static_cast<uint32_t>(vertTangentStorage.size()) * sizeof(SHMesh::VertexTangent),
BuffUsage::eVertexBuffer,
"Mesh Library Vertex Tangents"
);
SHVkUtil::EnsureBufferAndCopyData
(
device, cmdBuffer, vertNormalBuffer,
vertNormalStorage.data(),
static_cast<uint32_t>(vertNormalStorage.size()) * sizeof(SHMesh::VertexNormal),
BuffUsage::eVertexBuffer,
"Mesh Library Vertex Normals"
);
if (!vertBoneIdxStorage.empty())
{
SHVkUtil::EnsureBufferAndCopyData
(
device, cmdBuffer, vertBoneIdxBuffer,
vertBoneIdxStorage.data(),
static_cast<uint32_t>(vertBoneIdxStorage.size()) * sizeof(SHMesh::VertexBoneIndices),
BuffUsage::eVertexBuffer,
"Mesh Library Vertex Bone Indices"
);
}
if (!vertBoneWeightStorage.empty())
{
SHVkUtil::EnsureBufferAndCopyData
(
device, cmdBuffer, vertBoneWeightBuffer,
vertBoneWeightStorage.data(),
static_cast<uint32_t>(vertBoneWeightStorage.size()) * sizeof(SHMesh::VertexWeights),
BuffUsage::eVertexBuffer,
"Mesh Library Vertex Bone Weights"
);
}
SHVkUtil::EnsureBufferAndCopyData
(
device, cmdBuffer, indexBuffer,
indexStorage.data(),
static_cast<uint32_t>(indexStorage.size()) * sizeof(SHMesh::Index),
BuffUsage::eIndexBuffer,
"Mesh Library Indices"
);
isDirty = false;
}
} }

View File

@ -19,170 +19,192 @@ of DigiPen Institute of Technology is prohibited.
#include "Resource/SHResourceLibrary.h" #include "Resource/SHResourceLibrary.h"
#include "Math/Vector/SHVec2.h" #include "Math/Vector/SHVec2.h"
#include "Math/Vector/SHVec3.h" #include "Math/Vector/SHVec3.h"
#include "Math/Vector/SHVec4.h"
namespace SHADE namespace SHADE
{ {
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Forward Declarations */ /* Forward Declarations */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
class SHVkBuffer; class SHVkBuffer;
class SHVkLogicalDevice; class SHVkLogicalDevice;
class SHVkCommandBuffer; 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;
/*-----------------------------------------------------------------------------*/ \brief
/* Data Members */ 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
int32_t FirstVertex; meshes into the GPU.
uint32_t VertexCount;
uint32_t FirstIndex; \param vertexCount
uint32_t IndexCount; 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<SHMesh> 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 \brief
and Index Buffers. 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<SHMesh> 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<SHVkLogicalDevice> device, Handle<SHVkCommandBuffer> cmdBuffer);
/*-----------------------------------------------------------------------------*/
/* Getter Functions */
/*-----------------------------------------------------------------------------*/
Handle<SHVkBuffer> GetVertexPositionsBuffer() const noexcept { return vertPosBuffer; }
Handle<SHVkBuffer> GetVertexTexCoordsBuffer() const noexcept { return vertTexCoordBuffer; }
Handle<SHVkBuffer> GetVertexTangentsBuffer() const noexcept { return vertTangentBuffer; }
Handle<SHVkBuffer> GetVertexNormalsBuffer() const noexcept { return vertNormalBuffer; }
Handle<SHVkBuffer> GetVertexBoneIndicesBuffer() const noexcept { return vertBoneIdxBuffer; }
Handle<SHVkBuffer> GetVertexBoneWeightsBuffer() const noexcept { return vertBoneWeightBuffer; }
Handle<SHVkBuffer> GetIndexBuffer() const noexcept { return indexBuffer; }
private:
/*-----------------------------------------------------------------------------*/
/* Type Definition */
/*-----------------------------------------------------------------------------*/
struct MeshAddJob
{ {
public: uint32_t VertexCount = 0;
/*-----------------------------------------------------------------------------*/ const SHMesh::VertexPosition* VertexPositions = nullptr;
/* Usage Functions */ 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;
\brief uint32_t IndexCount = 0;
Adds a mesh to the Mesh Library. But this does not mean that the meshes have const SHMesh::Index* Indices = nullptr;
been added yet. A call to "BuildBuffers()" is required to transfer all Handle<SHMesh> Handle;
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<SHMesh> 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<SHMesh> 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<SHVkLogicalDevice> device, Handle<SHVkCommandBuffer> cmdBuffer);
/*-----------------------------------------------------------------------------*/
/* Getter Functions */
/*-----------------------------------------------------------------------------*/
Handle<SHVkBuffer> GetVertexPositionsBuffer() const noexcept { return vertPosBuffer; }
Handle<SHVkBuffer> GetVertexTexCoordsBuffer() const noexcept { return vertTexCoordBuffer; }
Handle<SHVkBuffer> GetVertexTangentsBuffer() const noexcept { return vertTangentBuffer; }
Handle<SHVkBuffer> GetVertexNormalsBuffer() const noexcept { return vertNormalBuffer; }
Handle<SHVkBuffer> 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<SHMesh> Handle;
};
/*-----------------------------------------------------------------------------*/
/* Data Members */
/*-----------------------------------------------------------------------------*/
// Manipulation Queues
std::vector<MeshAddJob> meshAddJobs;
std::vector<Handle<SHMesh>> meshRemoveJobs;
// Tracking
SHResourceLibrary<SHMesh> meshes{};
std::vector<Handle<SHMesh>> meshOrder;
// CPU Storage
std::vector<SHMesh::VertexPosition> vertPosStorage;
std::vector<SHMesh::VertexTexCoord> vertTexCoordStorage;
std::vector<SHMesh::VertexTangent> vertTangentStorage;
std::vector<SHMesh::VertexNormal> vertNormalStorage;
std::vector<SHMesh::Index> indexStorage;
// GPU Storage
Handle<SHVkBuffer> vertPosBuffer{};
Handle<SHVkBuffer> vertTexCoordBuffer{};
Handle<SHVkBuffer> vertTangentBuffer{};
Handle<SHVkBuffer> vertNormalBuffer{};
Handle<SHVkBuffer> indexBuffer {};
// Flags
bool isDirty = true;
}; };
/*-----------------------------------------------------------------------------*/
/* Data Members */
/*-----------------------------------------------------------------------------*/
// Manipulation Queues
std::vector<MeshAddJob> meshAddJobs;
std::vector<Handle<SHMesh>> meshRemoveJobs;
// Tracking
SHResourceLibrary<SHMesh> meshes;
std::vector<Handle<SHMesh>> meshOrder;
// CPU Storage
std::vector<SHMesh::VertexPosition> vertPosStorage;
std::vector<SHMesh::VertexTexCoord> vertTexCoordStorage;
std::vector<SHMesh::VertexTangent> vertTangentStorage;
std::vector<SHMesh::VertexNormal> vertNormalStorage;
std::vector<SHMesh::VertexBoneIndices> vertBoneIdxStorage; // Must be in multiples of 4
std::vector<SHMesh::VertexWeights> vertBoneWeightStorage;
std::vector<SHMesh::Index> indexStorage;
// GPU Storage
Handle<SHVkBuffer> vertPosBuffer{};
Handle<SHVkBuffer> vertTexCoordBuffer{};
Handle<SHVkBuffer> vertTangentBuffer{};
Handle<SHVkBuffer> vertNormalBuffer{};
Handle<SHVkBuffer> vertBoneIdxBuffer{};
Handle<SHVkBuffer> vertBoneWeightBuffer{};
Handle<SHVkBuffer> indexBuffer{};
// Flags
bool isDirty = true;
};
} }

View File

@ -288,11 +288,13 @@ namespace SHADE
{ {
return meshLibrary.AddMesh return meshLibrary.AddMesh
( (
static_cast<uint32_t>(meshData.VertexPositions.size()), static_cast<uint32_t>(meshData.VertexPositions.size()),
meshData.VertexPositions.data(), meshData.VertexPositions.data(),
meshData.VertexTexCoords.data(), meshData.VertexTexCoords.data(),
meshData.VertexTangents.data(), meshData.VertexTangents.data(),
meshData.VertexNormals.data(), meshData.VertexNormals.data(),
nullptr,
nullptr,
static_cast<uint32_t>(meshData.Indices.size()), static_cast<uint32_t>(meshData.Indices.size()),
meshData.Indices.data() meshData.Indices.data()
); );
@ -302,12 +304,12 @@ namespace SHADE
{ {
return gfxSystem.AddMesh return gfxSystem.AddMesh
( (
static_cast<uint32_t>(meshData.VertexPositions.size()), static_cast<uint32_t>(meshData.VertexPositions.size()),
meshData.VertexPositions.data(), meshData.VertexPositions.data(),
meshData.VertexTexCoords.data(), meshData.VertexTexCoords.data(),
meshData.VertexTangents.data(), meshData.VertexTangents.data(),
meshData.VertexNormals.data(), meshData.VertexNormals.data(),
static_cast<uint32_t>(meshData.Indices.size()), static_cast<uint32_t>(meshData.Indices.size()),
meshData.Indices.data() meshData.Indices.data()
); );
} }