Implemented Animation Clip asset and animation controller #410

Merged
XiaoQiDigipen merged 66 commits from SP3-22-AnimationController into main 2023-03-09 16:19:40 +08:00
75 changed files with 4642 additions and 768 deletions
Showing only changes of commit 79fe9ec43d - Show all commits

View File

@ -1,4 +1,4 @@
Start in Fullscreen: false Start in Fullscreen: false
Starting Scene ID: 86098106 Starting Scene ID: 91478134
Window Size: {x: 1920, y: 1080} Window Size: {x: 1920, y: 1080}
Window Title: SHADE Engine Window Title: SHADE Engine

View File

@ -0,0 +1,3 @@
Name: Master
ID: 187131295
Type: 11

View File

@ -0,0 +1,3 @@
Name: Master.strings
ID: 184993030
Type: 11

View File

@ -0,0 +1,3 @@
Name: Music
ID: 187337426
Type: 11

View File

@ -0,0 +1,3 @@
Name: SFX
ID: 200039123
Type: 11

View File

@ -0,0 +1,3 @@
Name: UI
ID: 185075145
Type: 11

View File

@ -0,0 +1,8 @@
- VertexShader: 47911992
FragmentShader: 46377769
SubPass: G-Buffer Write
Properties:
data.color: {x: 1, y: 1, z: 1, w: 1}
data.textureIndex: 57342922
data.alpha: 0
data.beta: {x: 1, y: 1, z: 1}

View File

@ -0,0 +1,3 @@
Name: AnimatedHomeowner
ID: 121518381
Type: 7

View File

@ -0,0 +1,8 @@
- VertexShader: 39210065
FragmentShader: 46377769
SubPass: G-Buffer Write
Properties:
data.color: {x: 1, y: 1, z: 1, w: 1}
data.textureIndex: 64651793
data.alpha: 0
data.beta: {x: 1, y: 1, z: 1}

View File

@ -0,0 +1,3 @@
Name: default_racoon
ID: 125722190
Type: 7

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@ -0,0 +1,7 @@
Name: MD_HomeownerV2
ID: 76586906
Type: 4
Sub Assets:
Name: Cube
ID: 148542784
Type: 8

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

33
Assets/Scenes/anim.shade Normal file
View File

@ -0,0 +1,33 @@
- EID: 0
Name: Default
IsActive: true
NumberOfChildren: 0
Components:
Light Component:
Position: {x: 0, y: 0, z: 0}
Type: Ambient
Direction: {x: 0, y: 0, z: 1}
Color: {x: 1, y: 1, z: 1, w: 1}
Layer: 4294967295
Strength: 1
IsActive: true
Scripts: ~
- EID: 2
Name: Default
IsActive: true
NumberOfChildren: 0
Components:
Transform Component:
Translate: {x: 0, y: 0, z: 0}
Rotate: {x: 0, y: 0, z: 0}
Scale: {x: 1, y: 1, z: 1}
IsActive: true
Renderable Component:
Mesh: 148542784
Material: 121518381
IsActive: true
Animator Component:
Rig: 76586906
Clip: 76586906
IsActive: true
Scripts: ~

View File

@ -0,0 +1,3 @@
Name: anim
ID: 91478134
Type: 5

View File

@ -20,10 +20,11 @@ layout(location = 0) out struct
vec2 uv; // location = 1 vec2 uv; // location = 1
vec4 normal; // location = 2 vec4 normal; // location = 2
vec4 worldPos; // location = 3 vec4 worldPos; // location = 3
vec3 worldNormal; // location = 4
} Out; } Out;
// material stuff // material stuff
layout(location = 4) out struct layout(location = 5) out struct
{ {
int materialIndex; int materialIndex;
uint eid; uint eid;
@ -61,11 +62,13 @@ void main()
// uvs for texturing in fragment shader // uvs for texturing in fragment shader
Out.uv = aUV; Out.uv = aUV;
mat3 transposeInv = mat3 (transpose(inverse(modelViewMat))); mat3 mvTransInv = mat3 (transpose(inverse(modelViewMat)));
mat3 modelTransInv = mat3 (transpose(inverse(worldTransform)));
// normals are also in view space // normals are also in view space
Out.normal.rgb = transposeInv * aNormal.rgb; Out.normal.rgb = mvTransInv * aNormal.rgb;
Out.normal.rgb = normalize (Out.normal.rgb); Out.normal.rgb = normalize (Out.normal.rgb);
Out.worldNormal = normalize (modelTransInv * aNormal);
// Compute bone matrix // Compute bone matrix
mat4 boneMatrix = BoneMatrices.data[firstBoneIndex + aBoneIndices[0]] * aBoneWeights[0]; mat4 boneMatrix = BoneMatrices.data[firstBoneIndex + aBoneIndices[0]] * aBoneWeights[0];

Binary file not shown.

View File

@ -2,6 +2,7 @@
struct DirectionalLightStruct struct DirectionalLightStruct
{ {
vec4 directionWorld;
vec3 direction; vec3 direction;
uint isActive; uint isActive;
uint cullingMask; uint cullingMask;
@ -22,7 +23,7 @@ layout(local_size_x = 16, local_size_y = 16) in;
layout(set = 3, binding = 0, rgba32f) uniform image2D positions; layout(set = 3, binding = 0, rgba32f) uniform image2D positions;
layout(set = 3, binding = 1, rgba32f) uniform image2D normals; layout(set = 3, binding = 1, rgba32f) uniform image2D normals;
layout(set = 3, binding = 2, rgba8) uniform image2D albedo; layout(set = 3, binding = 2, rgba8) uniform image2D albedo;
layout(set = 3, binding = 3, r32ui) uniform uimage2D lightLayerData; layout(set = 3, binding = 3, rgba32ui) uniform uimage2D lightLayerData;
layout(set = 3, binding = 4, r8) uniform image2D ssaoBlurredImage; layout(set = 3, binding = 4, r8) uniform image2D ssaoBlurredImage;
layout(set = 3, binding = 5, rgba8) uniform image2D positionWorldSpace; layout(set = 3, binding = 5, rgba8) uniform image2D positionWorldSpace;
layout(set = 3, binding = 6, rgba8) uniform image2D targetImage; layout(set = 3, binding = 6, rgba8) uniform image2D targetImage;
@ -54,7 +55,7 @@ float LinStep (float val, float low, float high)
return clamp ((val - low)/(high - low), 0.0f, 1.0f); return clamp ((val - low)/(high - low), 0.0f, 1.0f);
} }
float CalcShadowValue (sampler2D shadowMap, vec4 worldSpaceFragPos, mat4 lightPV) float CalcShadowValue (sampler2D shadowMap, vec4 worldSpaceFragPos, mat4 lightPV, vec3 worldNormal, vec3 lightDir)
{ {
// clip space for fragment from light view space // clip space for fragment from light view space
vec4 fragPosLightPOV = lightPV * worldSpaceFragPos; vec4 fragPosLightPOV = lightPV * worldSpaceFragPos;
@ -69,6 +70,13 @@ float CalcShadowValue (sampler2D shadowMap, vec4 worldSpaceFragPos, mat4 lightPV
if (converted.x < 0.0f || converted.x > 1.0f || converted.y < 0.0f || converted.y > 1.0f) if (converted.x < 0.0f || converted.x > 1.0f || converted.y < 0.0f || converted.y > 1.0f)
return 1.0f; return 1.0f;
float returnVal = 0.0f;
float worldNormalDotLight = dot (normalize (worldNormal), normalize(lightDir));
if (worldNormalDotLight < 0.0f)
return 0.7f;
if (fragPosLightPOV.z > moments.x && fragPosLightPOV.w > 0.0f) if (fragPosLightPOV.z > moments.x && fragPosLightPOV.w > 0.0f)
{ {
float p = step (fragPosLightPOV.z, moments.x); float p = step (fragPosLightPOV.z, moments.x);
@ -76,15 +84,19 @@ float CalcShadowValue (sampler2D shadowMap, vec4 worldSpaceFragPos, mat4 lightPV
float d = fragPosLightPOV.z - moments.x; float d = fragPosLightPOV.z - moments.x;
float pMax = LinStep (variance / (variance + (d * d)), 0.9f, 1.0f); float pMax = LinStep (variance / (variance + (d * d)), 0.9f, 1.0f);
return min (max (p, pMax), 1.0f);
returnVal = min (max (p, pMax) + 0.7f, 1.0f);
return returnVal;
} }
else if (fragPosLightPOV.z > 1.0f) else if (fragPosLightPOV.z > 1.0f)
{ {
return 0.0f; return 0.0f;
} }
else
return 0.3f; return 1.0f;
// return step (fragPosLightPOV.z, );
} }
void main() void main()
@ -104,8 +116,12 @@ void main()
// normal of fragment // normal of fragment
vec3 normalView = imageLoad(normals, globalThread).rgb; vec3 normalView = imageLoad(normals, globalThread).rgb;
uvec4 lightLayerAndNormal = imageLoad (lightLayerData, globalThread);
// light layer index // light layer index
uint lightLayer = imageLoad (lightLayerData, globalThread).r; uint lightLayer = lightLayerAndNormal.x;
vec3 worldNormal = vec3 (unpackHalf2x16 (lightLayerAndNormal.y).xy, unpackHalf2x16 (lightLayerAndNormal.z).x);
vec3 fragColor = vec3 (0.0f); vec3 fragColor = vec3 (0.0f);
@ -138,7 +154,7 @@ void main()
if ((DirLightData.dLightData[i].shadowData & uint(1)) == 1) if ((DirLightData.dLightData[i].shadowData & uint(1)) == 1)
{ {
// calculate shadow map here // calculate shadow map here
fragColor *= CalcShadowValue (shadowMaps[0], positionWorld, DirLightData.dLightData[i].pvMatrix).xxx; fragColor.rgb *= CalcShadowValue (shadowMaps[0], positionWorld, DirLightData.dLightData[i].pvMatrix, worldNormal, DirLightData.dLightData[i].directionWorld.xyz).xxx;
} }
} }
} }

View File

@ -0,0 +1,58 @@
#version 450
#define BLUR_WIDTH 7
#define BLUR_HALF_WIDTH BLUR_WIDTH / 2
#define SHM_WIDTH BLUR_WIDTH + 16 - 1
layout(local_size_x = 16, local_size_y = 16) in;
layout(set = 3, binding = 0, r8) uniform image2D shadowMap;
layout(set = 3, binding = 1, r8) uniform image2D shadowMapBlurred;
vec4 GetShadowMapValue(ivec2 uv, ivec2 imageSize)
{
if (uv.x >= 0 && uv.y >= 0 && uv.x < imageSize.x && uv.y < imageSize.y)
{
return imageLoad (shadowMap, uv);
}
return vec4 (0.0f);
}
shared vec4 sharedPixels[16 + BLUR_WIDTH - 1][16 + BLUR_WIDTH - 1];
void main()
{
ivec2 globalThread = ivec2 (gl_GlobalInvocationID.xy);
ivec2 localThread = ivec2 (gl_LocalInvocationID.xy);
ivec2 inputImageSize = imageSize(shadowMap);
// Load color into shared memory
ivec2 start = ivec2 (gl_WorkGroupID) * ivec2 (gl_WorkGroupSize) - (BLUR_HALF_WIDTH);
for (int i = localThread.x; i < SHM_WIDTH; i += int (gl_WorkGroupSize.x))
{
for (int j = localThread.y; j < SHM_WIDTH; j += int (gl_WorkGroupSize.y))
{
vec4 value = GetShadowMapValue (start + ivec2 (i, j), inputImageSize);
sharedPixels[i][j] = value;
}
}
// wait for all shared memory to load
barrier();
ivec2 shmStart = ivec2 (localThread + (BLUR_HALF_WIDTH));
vec4 sum = vec4 (0.0f);
for (int i = -BLUR_HALF_WIDTH; i <= BLUR_HALF_WIDTH; ++i)
{
for (int j = -BLUR_HALF_WIDTH; j <= BLUR_HALF_WIDTH; ++j)
{
vec4 sharedVal = sharedPixels[shmStart.x + i][shmStart.y + j];
sum += sharedVal;
}
}
sum /= (BLUR_WIDTH * BLUR_WIDTH);
imageStore(shadowMapBlurred, globalThread, sum);
}

Binary file not shown.

View File

@ -0,0 +1,3 @@
Name: ShadowMapBlur_CS
ID: 38004013
Type: 2

View File

@ -7,6 +7,12 @@ layout(location = 0) out vec4 shadowMap;
void main() void main()
{ {
float depth = gl_FragCoord.z;
float dx = dFdx(depth);
float dy = dFdy(depth);
float moment2 = depth * depth + 0.25f * (dx * dx + dy * dy);
// shadowMap = vec4 (0.0f, 0.0f, gl_FragCoord.z, 1.0f); // shadowMap = vec4 (0.0f, 0.0f, gl_FragCoord.z, 1.0f);
shadowMap = vec4 (gl_FragCoord.z, gl_FragCoord.z * gl_FragCoord.z, 0.0f, 1.0f); shadowMap = vec4 (gl_FragCoord.z, moment2, 0.0f, 1.0f);
} }

View File

@ -32,10 +32,11 @@ layout(location = 0) in struct
vec2 uv; // location = 1 vec2 uv; // location = 1
vec4 normal; // location = 2 vec4 normal; // location = 2
vec4 worldPos; // location = 3 vec4 worldPos; // location = 3
vec3 worldNormal; // location = 4
} In; } In;
// material stuff // material stuff
layout(location = 4) flat in struct layout(location = 5) flat in struct
{ {
int materialIndex; int materialIndex;
uint eid; uint eid;
@ -57,7 +58,7 @@ layout (std430, set = 2, binding = 0) buffer MaterialProperties // For mater
layout(location = 0) out vec4 position; layout(location = 0) out vec4 position;
layout(location = 1) out uint outEntityID; layout(location = 1) out uint outEntityID;
layout(location = 2) out uint lightLayerIndices; layout(location = 2) out uvec4 lightLayerIndices;
layout(location = 3) out vec4 normals; layout(location = 3) out vec4 normals;
layout(location = 4) out vec4 albedo; layout(location = 4) out vec4 albedo;
layout(location = 5) out vec4 worldSpacePosition; layout(location = 5) out vec4 worldSpacePosition;
@ -72,11 +73,11 @@ void main()
{ {
position = In.vertPos; position = In.vertPos;
normals = In.normal; normals = In.normal;
albedo = texture(textures[nonuniformEXT(MatProp.data[In2.materialIndex].textureIndex)], In.uv); albedo = vec4 (texture(textures[nonuniformEXT(MatProp.data[In2.materialIndex].textureIndex)], In.uv).xyz, 1.0f);
worldSpacePosition = In.worldPos; worldSpacePosition = In.worldPos;
outEntityID = In2.eid; outEntityID = In2.eid;
lightLayerIndices = In2.lightLayerIndex; lightLayerIndices = uvec4 (In2.lightLayerIndex, 0, 0, 1);
// float vpHeight = float (In2.screenSpacePos.y) - MatProp.data[In2.materialIndex].highlightPosition; // float vpHeight = float (In2.screenSpacePos.y) - MatProp.data[In2.materialIndex].highlightPosition;
// bring the frame of reference to the object's screen space pos // bring the frame of reference to the object's screen space pos
@ -101,4 +102,6 @@ void main()
} }
else else
objectVFX = vec4(0.0f, 0.0f, 0.0f, 1.0f); objectVFX = vec4(0.0f, 0.0f, 0.0f, 1.0f);
objectVFX.a = 1.0f;
} }

View File

@ -17,6 +17,7 @@ layout(location = 0) out struct
vec2 uv; // location = 1 vec2 uv; // location = 1
vec4 normal; // location = 2 vec4 normal; // location = 2
vec4 worldPos; // location = 3 vec4 worldPos; // location = 3
vec3 worldNormal; // location = 4
} Out; } Out;
@ -36,7 +37,7 @@ struct GenericData
}; };
// material stuff // material stuff
layout(location = 4) out struct layout(location = 5) out struct
{ {
int materialIndex; int materialIndex;
uint eid; uint eid;
@ -76,11 +77,13 @@ void main()
// uvs for texturing in fragment shader // uvs for texturing in fragment shader
Out.uv = aUV; Out.uv = aUV;
mat3 transposeInv = mat3 (transpose(inverse(modelViewMat))); mat3 mvTransInv = mat3 (transpose(inverse(modelViewMat)));
mat3 modelTransInv = mat3 (transpose(inverse(worldTransform)));
// normals are also in view space // normals are also in view space
Out.normal.rgb = transposeInv * aNormal.rgb; Out.normal.rgb = mvTransInv * aNormal.rgb;
Out.normal.rgb = normalize (Out.normal.rgb); Out.normal.rgb = normalize (Out.normal.rgb);
Out.worldNormal = normalize (modelTransInv * aNormal);
// Get center of object in world position // Get center of object in world position
vec4 worldPos = vec4(worldTransform[3][0], worldTransform[3][1], worldTransform[3][2], 1.0f); vec4 worldPos = vec4(worldTransform[3][0], worldTransform[3][1], worldTransform[3][2], 1.0f);

View File

@ -17,10 +17,11 @@ layout(location = 0) in struct
vec2 uv; // location = 1 vec2 uv; // location = 1
vec4 normal; // location = 2 vec4 normal; // location = 2
vec4 worldPos; // location = 3 vec4 worldPos; // location = 3
vec3 worldNormal; // location = 4
} In; } In;
// material stuff // material stuff
layout(location = 4) flat in struct layout(location = 5) flat in struct
{ {
int materialIndex; int materialIndex;
uint eid; uint eid;
@ -35,7 +36,7 @@ layout (std430, set = 2, binding = 0) buffer MaterialProperties // For mater
layout(location = 0) out vec4 position; layout(location = 0) out vec4 position;
layout(location = 1) out uint outEntityID; layout(location = 1) out uint outEntityID;
layout(location = 2) out uint lightLayerIndices; layout(location = 2) out uvec4 lightLayerIndices;
layout(location = 3) out vec4 normals; layout(location = 3) out vec4 normals;
layout(location = 4) out vec4 albedo; layout(location = 4) out vec4 albedo;
layout(location = 5) out vec4 worldSpacePosition; layout(location = 5) out vec4 worldSpacePosition;
@ -48,5 +49,5 @@ void main()
worldSpacePosition = In.worldPos; worldSpacePosition = In.worldPos;
outEntityID = In2.eid; outEntityID = In2.eid;
lightLayerIndices = In2.lightLayerIndex; lightLayerIndices = uvec4 (In2.lightLayerIndex, packHalf2x16 (In.worldNormal.xy), packHalf2x16 (vec2 (In.worldNormal.z, 1.0f)), 1);
} }

Binary file not shown.

View File

@ -20,11 +20,12 @@ layout(location = 0) out struct
vec2 uv; // location = 1 vec2 uv; // location = 1
vec4 normal; // location = 2 vec4 normal; // location = 2
vec4 worldPos; // location = 3 vec4 worldPos; // location = 3
vec3 worldNormal; // location = 4
} Out; } Out;
// material stuff // material stuff
layout(location = 4) out struct layout(location = 5) out struct
{ {
int materialIndex; int materialIndex;
uint eid; uint eid;
@ -57,11 +58,13 @@ void main()
// uvs for texturing in fragment shader // uvs for texturing in fragment shader
Out.uv = aUV; Out.uv = aUV;
mat3 transposeInv = mat3 (transpose(inverse(modelViewMat))); mat3 mvTransInv = mat3 (transpose(inverse(modelViewMat)));
mat3 modelTransInv = mat3 (transpose(inverse(worldTransform)));
// normals are also in view space // normals are also in view space
Out.normal.rgb = transposeInv * aNormal.rgb; Out.normal.rgb = mvTransInv * aNormal.rgb;
Out.normal.rgb = normalize (Out.normal.rgb); Out.normal.rgb = normalize (Out.normal.rgb);
Out.worldNormal = normalize (modelTransInv * aNormal);
// clip space for rendering // clip space for rendering
gl_Position = cameraData.vpMat * worldTransform * vec4 (aVertexPos, 1.0f); gl_Position = cameraData.vpMat * worldTransform * vec4 (aVertexPos, 1.0f);

Binary file not shown.

View File

@ -62,7 +62,6 @@ if %_e%==3 (goto :done) else (goto :ModelCompiler)
echo -----------------------ModelCompiler---------------------------- echo -----------------------ModelCompiler----------------------------
rmdir "Dependencies/ModelCompiler" /S /Q rmdir "Dependencies/ModelCompiler" /S /Q
git clone https://github.com/SHADE-DP/ModelCompiler.git "Dependencies/ModelCompiler" git clone https://github.com/SHADE-DP/ModelCompiler.git "Dependencies/ModelCompiler"
git clone https://github.com/SHADE-DP/assimp.git "Dependencies/ModelCompiler/Dependencies/assimp"
if %_e%==4 (goto :done) else (goto :spdlog) if %_e%==4 (goto :done) else (goto :spdlog)
@REM :ktx @REM :ktx

View File

@ -55,14 +55,11 @@ namespace SHADE
// Set accordingly // Set accordingly
currClip = clip; currClip = clip;
currPlaybackTime = 0.0f; currPlaybackTime = 0.0f;
channelMaps.clear();
auto RAW_ANIM = clip->GetRawAnimation(); auto RAW_ANIM = clip->GetRawAnimation();
// Set up if valid // Set up if valid
if (currClip && RAW_ANIM) if (currClip && RAW_ANIM)
{ {
// Create channel maps
channelMaps.emplace(RAW_ANIM, createChannelMap(RAW_ANIM));
// Calculate secs for the clip // Calculate secs for the clip
secsPerTick = 1.0f / RAW_ANIM->GetTicksPerSecond(); secsPerTick = 1.0f / RAW_ANIM->GetTicksPerSecond();
@ -202,12 +199,6 @@ namespace SHADE
// Store // Store
rawAnims.emplace(RAW_ANIM); rawAnims.emplace(RAW_ANIM);
} }
// Load channel maps
for (auto anim : rawAnims)
{
channelMaps.emplace(anim, createChannelMap(anim));
}
} }
} }
@ -219,19 +210,6 @@ namespace SHADE
return animController->SetTrigger(animInstanceData, paramName); return animController->SetTrigger(animInstanceData, paramName);
} }
/*-----------------------------------------------------------------------------------*/
/* Helper Functions - Loading */
/*-----------------------------------------------------------------------------------*/
SHAnimatorComponent::ChannelMap SHAnimatorComponent::createChannelMap(Handle<SHRawAnimation> rawAnimData)
{
ChannelMap channelMap;
for (const auto& channel : rawAnimData->GetChannels())
{
channelMap.emplace(channel.Name, &channel);
}
return channelMap;
}
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Helper Functions - Update */ /* Helper Functions - Update */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
@ -283,31 +261,25 @@ namespace SHADE
} }
void SHAnimatorComponent::updatePoseWithClip(Handle<SHAnimationClip> clip, float poseTime) void SHAnimatorComponent::updatePoseWithClip(Handle<SHAnimationClip> clip, float poseTime)
{ {
// Get closest frame index updatePoseWithClip(poseTime, clip->GetRawAnimation(), rig->GetRootNode(), SHMatrix::Identity);
const int CLOSEST_FRAME_IDX = clip->GetStartFrameIndex() + static_cast<int>(std::floorf(poseTime / secsPerTick));
updatePoseWithClip(CLOSEST_FRAME_IDX, poseTime, clip->GetRawAnimation(), rig->GetRootNode(), SHMatrix::Identity);
} }
void SHAnimatorComponent::updatePoseWithClip(int closestFrameIndex, float poseTime, Handle<SHRawAnimation> rawAnimData, Handle<SHRigNode> node, const SHMatrix& parentMatrix) void SHAnimatorComponent::updatePoseWithClip(float poseTime, Handle<SHRawAnimation> rawAnimData, Handle<SHRigNode> node, const SHMatrix& parentMatrix)
{ {
// Check if there is a channel for this node // Check if there is a channel for this node
const std::string& BONE_NAME = rig->GetName(node);
SHMatrix transformMatrix = node->TransformMatrix; SHMatrix transformMatrix = node->TransformMatrix;
const int BONE_IDX = rig->GetNodeIndex(node);
if (channelMaps.contains(rawAnimData)) const auto& CHANNELS = rawAnimData->GetChannels();
if (BONE_IDX < CHANNELS.size())
{ {
auto channelMap = channelMaps[rawAnimData]; const auto& CHANNEL = CHANNELS[BONE_IDX];
if (channelMap.contains(BONE_NAME))
{
const auto CHANNEL = channelMap[BONE_NAME];
transformMatrix = SHMatrix::Transform transformMatrix = SHMatrix::Transform
( (
getInterpolatedValue(CHANNEL->PositionKeyFrames, closestFrameIndex, poseTime), getInterpolatedValue(CHANNEL.PositionKeyFrames, poseTime),
getInterpolatedValue(CHANNEL->RotationKeyFrames, closestFrameIndex, poseTime), getInterpolatedValue(CHANNEL.RotationKeyFrames, poseTime),
getInterpolatedValue(CHANNEL->ScaleKeyFrames, closestFrameIndex, poseTime) getInterpolatedValue(CHANNEL.ScaleKeyFrames, poseTime)
); );
} }
}
// Apply parent's transformation // Apply parent's transformation
transformMatrix = transformMatrix * parentMatrix; transformMatrix = transformMatrix * parentMatrix;
@ -323,7 +295,7 @@ namespace SHADE
// Apply pose to children // Apply pose to children
for (auto& child : node->Children) for (auto& child : node->Children)
{ {
updatePoseWithClip(closestFrameIndex, poseTime, rawAnimData, child, transformMatrix); updatePoseWithClip(poseTime, rawAnimData, node, transformMatrix);
} }
} }
} }

View File

@ -190,22 +190,17 @@ namespace SHADE
float secsPerTick = 0.0f; float secsPerTick = 0.0f;
// Buffer // Buffer
std::vector<SHMatrix> boneMatrices; std::vector<SHMatrix> boneMatrices;
// Caches
std::unordered_map<Handle<SHRawAnimation>, ChannelMap> channelMaps;
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Helper Functions */ /* Helper Functions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
// Loading
ChannelMap createChannelMap(Handle<SHRawAnimation> rawAnimData);
// Update
void updateAnimController(float dt); void updateAnimController(float dt);
void updateManualClipState(float dt); void updateManualClipState(float dt);
void updateCurrentAnimatorState(Handle<SHAnimationClip> clip, float playbackTime); void updateCurrentAnimatorState(Handle<SHAnimationClip> clip, float playbackTime);
void updatePoseWithClip(Handle<SHAnimationClip> clip, float poseTime); void updatePoseWithClip(Handle<SHAnimationClip> clip, float poseTime);
void updatePoseWithClip(int closestFrameIndex, float poseTime, Handle<SHRawAnimation> rawAnimData, Handle<SHRigNode> node, const SHMatrix& parentMatrix); void updatePoseWithClip(float poseTime, Handle<SHRawAnimation> rawAnimData, Handle<SHRigNode> node, const SHMatrix& parentMatrix);
template<typename T> template<typename T>
T getInterpolatedValue(const std::vector<SHAnimationKeyFrame<T>>& keyframes, int closestFrameIndex, float poseTime); T getInterpolatedValue(const std::vector<SHAnimationKeyFrame<T>>& keyframes, float poseTime);
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* RTTR */ /* RTTR */

View File

@ -44,7 +44,7 @@ namespace SHADE
/* Helper Functions */ /* Helper Functions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
template<typename T> template<typename T>
T SHAnimatorComponent::getInterpolatedValue(const std::vector<SHAnimationKeyFrame<T>>& keyframes, int closestFrameIndex, float poseTime) T SHAnimatorComponent::getInterpolatedValue(const std::vector<SHAnimationKeyFrame<T>>& keyframes, float poseTime)
{ {
// Only allow SHVec3 and SHQuaternion // Only allow SHVec3 and SHQuaternion
static_assert(std::is_same_v<T, SHVec3> || std::is_same_v<T, SHQuaternion>, "Only interpolation for SHVec3 and SHQuaternion is allowed."); static_assert(std::is_same_v<T, SHVec3> || std::is_same_v<T, SHQuaternion>, "Only interpolation for SHVec3 and SHQuaternion is allowed.");
@ -56,11 +56,11 @@ namespace SHADE
{ {
const auto& KEYFRAME = *iter; const auto& KEYFRAME = *iter;
if (KEYFRAME.FrameIndex <= closestFrameIndex) if (KEYFRAME.TimeStamp <= poseTime)
{ {
firstKeyFrame = iter; firstKeyFrame = iter;
} }
else // KEYFRAME.FrameIndex > closestFrameIndex else // KEYFRAME.FrameIndex > poseTime
{ {
nextKeyFrame = iter; nextKeyFrame = iter;
break; break;
@ -84,8 +84,8 @@ namespace SHADE
} }
// Get interpolated vector // Get interpolated vector
const float PREV_FRAME_TIME = firstKeyFrame->FrameIndex * secsPerTick; const float PREV_FRAME_TIME = firstKeyFrame->TimeStamp;
const float NEXT_FRAME_TIME = nextKeyFrame->FrameIndex * secsPerTick; const float NEXT_FRAME_TIME = nextKeyFrame->TimeStamp;
const float NORMALISED_TIME = (poseTime - PREV_FRAME_TIME) / (NEXT_FRAME_TIME - PREV_FRAME_TIME); const float NORMALISED_TIME = (poseTime - PREV_FRAME_TIME) / (NEXT_FRAME_TIME - PREV_FRAME_TIME);
if constexpr (std::is_same_v<T, SHQuaternion>) if constexpr (std::is_same_v<T, SHQuaternion>)

View File

@ -20,16 +20,14 @@ namespace SHADE
/* Constructors */ /* Constructors */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
SHRawAnimation::SHRawAnimation(const SHAnimAsset& asset) SHRawAnimation::SHRawAnimation(const SHAnimAsset& asset)
: ticksPerSecond { static_cast<int>(asset.ticksPerSecond) }
, totalTime { static_cast<float>(asset.duration) / static_cast<int>(asset.ticksPerSecond) }
, totalFrames { static_cast<int>(asset.duration) }
{ {
// Populate keyframes // Populate keyframes
int maxFrames = 0;
totalTime = 0.0f;
for (const auto& channel : asset.nodeChannels) for (const auto& channel : asset.nodeChannels)
{ {
// Create a channel // Create a channel
Channel newChannel; Channel newChannel;
newChannel.Name = std::string(channel.name);
newChannel.PositionKeyFrames.reserve(channel.positionKeys.size()); newChannel.PositionKeyFrames.reserve(channel.positionKeys.size());
newChannel.RotationKeyFrames.reserve(channel.rotationKeys.size()); newChannel.RotationKeyFrames.reserve(channel.rotationKeys.size());
newChannel.ScaleKeyFrames.reserve(channel.scaleKeys.size()); newChannel.ScaleKeyFrames.reserve(channel.scaleKeys.size());
@ -37,21 +35,30 @@ namespace SHADE
// Populate Keyframes // Populate Keyframes
for (const auto& posKey : channel.positionKeys) for (const auto& posKey : channel.positionKeys)
{ {
newChannel.PositionKeyFrames.emplace_back(SHAnimationKeyFrame<SHVec3>{ static_cast<int>(posKey.time), posKey.value}); newChannel.PositionKeyFrames.emplace_back(SHAnimationKeyFrame<SHVec3>{ posKey.time, posKey.value});
} }
for (const auto& rotKey : channel.rotationKeys) for (const auto& rotKey : channel.rotationKeys)
{ {
newChannel.RotationKeyFrames.emplace_back(SHAnimationKeyFrame<SHQuaternion>{ static_cast<int>(rotKey.time), rotKey.value}); newChannel.RotationKeyFrames.emplace_back(SHAnimationKeyFrame<SHQuaternion>{ rotKey.time, rotKey.value});
} }
for (const auto& scaleKey : channel.scaleKeys) for (const auto& scaleKey : channel.scaleKeys)
{ {
newChannel.ScaleKeyFrames.emplace_back(SHAnimationKeyFrame<SHVec3>{ static_cast<int>(scaleKey.time), scaleKey.value}); newChannel.ScaleKeyFrames.emplace_back(SHAnimationKeyFrame<SHVec3>{ scaleKey.time, scaleKey.value});
} }
newChannel.MaxFrames = std::max({ newChannel.PositionKeyFrames.size(), newChannel.RotationKeyFrames.size(), newChannel.ScaleKeyFrames.size() }); newChannel.MaxFrames = std::max({ newChannel.PositionKeyFrames.size(), newChannel.RotationKeyFrames.size(), newChannel.ScaleKeyFrames.size() });
// Compute max frames
maxFrames = std::max(maxFrames, newChannel.MaxFrames);
// Compute total time
totalTime = std::max({ totalTime, newChannel.PositionKeyFrames.back().TimeStamp, newChannel.RotationKeyFrames.back().TimeStamp, newChannel.ScaleKeyFrames.back().TimeStamp });
// Insert the channel // Insert the channel
channels.emplace_back(std::move(newChannel)); channels.emplace_back(std::move(newChannel));
// Compute fps
ticksPerSecond = static_cast<int>(maxFrames / totalTime);
} }
} }

View File

@ -27,7 +27,7 @@ namespace SHADE
template<typename T> template<typename T>
struct SHAnimationKeyFrame struct SHAnimationKeyFrame
{ {
int FrameIndex; float TimeStamp;
T Data; T Data;
}; };
@ -45,7 +45,6 @@ namespace SHADE
/// </summary> /// </summary>
struct Channel struct Channel
{ {
std::string Name;
std::vector<SHAnimationKeyFrame<SHVec3>> PositionKeyFrames; std::vector<SHAnimationKeyFrame<SHVec3>> PositionKeyFrames;
std::vector<SHAnimationKeyFrame<SHQuaternion>> RotationKeyFrames; std::vector<SHAnimationKeyFrame<SHQuaternion>> RotationKeyFrames;
std::vector<SHAnimationKeyFrame<SHVec3>> ScaleKeyFrames; std::vector<SHAnimationKeyFrame<SHVec3>> ScaleKeyFrames;

View File

@ -120,8 +120,10 @@ namespace SHADE
// Fill the node with data // Fill the node with data
const auto& NODE_DATA = asset.nodeDataCollection.at(sourceNode->idRef); const auto& NODE_DATA = asset.nodeDataCollection.at(sourceNode->idRef);
newNode->OffsetMatrix = SHMatrix::Transpose(NODE_DATA.offset); //newNode->OffsetMatrix = SHMatrix::Transpose(NODE_DATA.inverseBindMatrix);
newNode->TransformMatrix = SHMatrix::Transpose(NODE_DATA.transform); //newNode->TransformMatrix = SHMatrix::Transpose(NODE_DATA.transform);
newNode->OffsetMatrix = NODE_DATA.inverseBindMatrix;
newNode->TransformMatrix = NODE_DATA.transform;
// Populate maps // Populate maps
if (!NODE_DATA.name.empty()) if (!NODE_DATA.name.empty())

View File

@ -20,69 +20,61 @@
namespace SHADE namespace SHADE
{ {
enum class SHAnimationBehaviour : uint8_t enum class AnimationInterpolation : uint8_t
{ {
DEFAULT = 0x0, DEFAULT = 0x1,
CONSTANT = 0x1, LINEAR = 0x1,
LINEAR = 0x2, STEP = 0x2,
REPEAT = 0x3 CUBICSPLINE = 0x3
};
// Base
struct KeyBase
{
float time;
}; };
// Smallest data containers // Smallest data containers
struct PositionKey struct PositionKey :KeyBase
{ {
float time;
SHVec3 value; SHVec3 value;
}; };
struct RotationKey struct RotationKey : KeyBase
{ {
float time;
SHVec4 value; SHVec4 value;
}; };
struct ScaleKey struct ScaleKey :KeyBase
{ {
float time;
SHVec3 value; SHVec3 value;
}; };
// Headers for read/write // Headers for read/write
struct SHAnimNodeInfo
{
uint32_t charCount;
uint32_t posKeyCount;
uint32_t rotKeyCount;
uint32_t scaKeyCount;
};
struct SHAnimDataHeader struct SHAnimDataHeader
{ {
uint32_t charCount; uint32_t charCount;
uint32_t animNodeCount; uint32_t animNodeCount;
std::vector<SHAnimNodeInfo> nodeHeaders; uint32_t frameCount;
}; };
// Main data containers // Main data containers
struct SHAnimData struct SHAnimNode
{ {
std::string name; AnimationInterpolation interpolation;
SHAnimationBehaviour pre;
SHAnimationBehaviour post;
std::vector<PositionKey> positionKeys;
std::vector<RotationKey> rotationKeys;
std::vector<ScaleKey> scaleKeys;
std::vector<PositionKey> positionKeys{};
std::vector<RotationKey> rotationKeys{};
std::vector<ScaleKey> scaleKeys{};
}; };
struct SH_API SHAnimAsset : SHAssetData struct SH_API SHAnimAsset final : SHAssetData
{ {
std::string name; std::string name;
double duration; double duration{};
double ticksPerSecond; double ticksPerSecond{};
std::vector<SHAnimData> nodeChannels; std::vector<SHAnimNode> nodeChannels{};
}; };
} }

View File

@ -19,45 +19,28 @@
namespace SHADE namespace SHADE
{ {
constexpr int BONE_INDEX_ALIGHTMENT = 4;
struct SHMeshDataHeader struct SHMeshDataHeader
{ {
uint32_t vertexCount; uint32_t vertexCount;
uint32_t indexCount; uint32_t indexCount;
uint32_t charCount; uint32_t charCount;
uint32_t boneCount; bool hasWeights;
};
struct MeshBoneInfo
{
uint32_t charCount;
uint32_t weightCount; // Size should be same as boneCount
};
struct BoneWeight
{
uint32_t index;
float weight;
};
struct MeshBone
{
std::string name;
SHMatrix offset;
std::vector<BoneWeight> weights;
}; };
struct SH_API SHMeshAsset : SHAssetData struct SH_API SHMeshAsset : SHAssetData
{ {
std::string name; std::string name;
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<SHVec4U> VertexBoneIndices;
std::vector<SHVec4> VertexBoneWeights; //Variables
std::vector<SHVec4> VertexBoneWeights{};
std::vector<SHVec4U> VertexBoneIndices{};
uint32_t BoneCount; uint32_t BoneCount;
}; };
} }

View File

@ -1,8 +1,6 @@
#include "SHpch.h" #include "SHpch.h"
#include "SHRigAsset.h" #include "SHRigAsset.h"
#include <queue>
namespace SHADE namespace SHADE
{ {
SHRigAsset::~SHRigAsset() SHRigAsset::~SHRigAsset()

View File

@ -17,17 +17,30 @@
namespace SHADE namespace SHADE
{ {
using NodeDataFlag = unsigned char;
constexpr NodeDataFlag NODE_DATA_ROTATION = 0b0001;
constexpr NodeDataFlag NODE_DATA_SCALE = 0b0010;
constexpr NodeDataFlag NODE_DATA_TRANSLATION = 0b0100;
constexpr NodeDataFlag NODE_DATA_MATRIX = 0b1000;
constexpr size_t NODE_COMPONENT_COUNT_ROTATION{ 4 };
constexpr size_t NODE_COMPONENT_COUNT_SCALE{ 3 };
constexpr size_t NODE_COMPONENT_COUNT_TRANSLATION{ 3 };
constexpr size_t NODE_COMPONENT_COUNT_MATRIX{ 16 };
struct SHRigDataHeader struct SHRigDataHeader
{ {
uint32_t nodeCount; uint32_t nodeCount{};
std::vector<uint32_t> charCounts; uint32_t startNode{};
std::vector<uint32_t> charCounts{};
}; };
struct SHRigNodeData struct SHRigNodeData
{ {
std::string name; std::string name;
SHMatrix transform; SHMatrix transform;
SHMatrix offset; SHMatrix inverseBindMatrix;
}; };
struct SHRigNodeAsset struct SHRigNodeAsset
@ -39,9 +52,8 @@ namespace SHADE
struct SH_API SHRigAsset : SHAssetData struct SH_API SHRigAsset : SHAssetData
{ {
~SHRigAsset(); ~SHRigAsset();
SHRigDataHeader header; SHRigDataHeader header;
std::vector<SHRigNodeData> nodeDataCollection; std::vector<SHRigNodeData> nodeDataCollection{};
SHRigNodeAsset* root; SHRigNodeAsset* root;
}; };
} }

View File

@ -0,0 +1,23 @@
/******************************************************************************
* \file SHAudioBankAsset.h
* \author Loh Xiao Qi
* \date 31 January 2023
* \brief
*
* \copyright Copyright (c) 2023 Digipen Institute of Technology. Reproduction
* or disclosure of this file or its contents without the prior
* written consent of Digipen Institute of Technology is prohibited.
******************************************************************************/
#pragma once
#include "SHAssetData.h"
#include <string>
namespace SHADE
{
struct SHAudioBankAsset : SHAssetData
{
std::string name;
std::string path;
};
}

View File

@ -17,6 +17,52 @@
namespace SHADE namespace SHADE
{ {
inline SHVec3 GetVec3FromVector(std::vector<double> const& vec)
{
assert(vec.size() == NODE_COMPONENT_COUNT_TRANSLATION);
return SHVec3{
static_cast<float>(vec[0]),
static_cast<float>(vec[1]),
static_cast<float>(vec[2])
};
}
inline SHVec4 GetVec4FromVector(std::vector<double> const& vec)
{
assert(vec.size() == NODE_COMPONENT_COUNT_ROTATION);
return SHVec4{
static_cast<float>(vec[0]),
static_cast<float>(vec[1]),
static_cast<float>(vec[2]),
static_cast<float>(vec[3])
};
}
inline SHMatrix GetMatrixFromVector(std::vector<double> const& vec)
{
assert(vec.size() == NODE_COMPONENT_COUNT_MATRIX);
return SHMatrix{
static_cast<float>(vec[0]),
static_cast<float>(vec[1]),
static_cast<float>(vec[2]),
static_cast<float>(vec[3]),
static_cast<float>(vec[4]),
static_cast<float>(vec[5]),
static_cast<float>(vec[6]),
static_cast<float>(vec[7]),
static_cast<float>(vec[8]),
static_cast<float>(vec[9]),
static_cast<float>(vec[10]),
static_cast<float>(vec[11]),
static_cast<float>(vec[12]),
static_cast<float>(vec[13]),
static_cast<float>(vec[14]),
static_cast<float>(vec[15])
};
}
void SHModelLoader::ReadHeaders(FileReference file, SHModelAsset& asset) void SHModelLoader::ReadHeaders(FileReference file, SHModelAsset& asset)
{ {
file.read( file.read(
@ -36,29 +82,12 @@ namespace SHADE
if (asset.header.animCount > 0) if (asset.header.animCount > 0)
{ {
asset.animHeaders.resize(asset.header.animCount); asset.animHeaders.resize(asset.header.animCount);
for (auto i {0}; i < asset.header.animCount; ++i) for (auto& animHeader : asset.animHeaders)
{ {
auto& animHeader = asset.animHeaders[i];
file.read( file.read(
reinterpret_cast<char*>(&animHeader.charCount), reinterpret_cast<char*>(&animHeader),
sizeof(uint32_t) sizeof(animHeader)
); );
file.read(
reinterpret_cast<char*>(&animHeader.animNodeCount),
sizeof(uint32_t)
);
animHeader.nodeHeaders.resize(animHeader.animNodeCount);
for (auto j {0}; j < animHeader.animNodeCount; ++j)
{
auto& nodeHeader = animHeader.nodeHeaders[j];
file.read(
reinterpret_cast<char*>(&nodeHeader),
sizeof(SHAnimNodeInfo)
);
}
} }
} }
} }
@ -74,53 +103,63 @@ namespace SHADE
ReadRigHeader(file, asset.rig.header); ReadRigHeader(file, asset.rig.header);
ReadRigData(file, asset.rig.header, asset.rig.nodeDataCollection); ReadRigData(file, asset.rig.header, asset.rig.nodeDataCollection);
ReadRigTree(file, asset.rig.header, asset.rig.root); ReadRigTree(file, asset.rig.header, asset.rig.root);
}
}
void SHModelLoader::ReadAnimNode(FileReference file, SHAnimNodeInfo const& info, SHAnimData& data) for (auto& mesh : asset.meshes)
{
mesh->BoneCount = asset.rig.nodeDataCollection.size();
}
//BuildTransformMatrices(asset.rig);
}
}
void SHModelLoader::ReadAnimNode(FileReference file, uint32_t frameCount, SHAnimNode& data)
{ {
data.name.resize(info.charCount);
file.read( file.read(
data.name.data(), reinterpret_cast<char*>(&data.interpolation),
info.charCount 1
); );
file.read( data.positionKeys.resize(frameCount);
reinterpret_cast<char*>(&data.pre), data.rotationKeys.resize(frameCount);
sizeof(SHAnimationBehaviour) data.scaleKeys.resize(frameCount);
);
file.read(
reinterpret_cast<char*>(&data.post),
sizeof(SHAnimationBehaviour)
);
uint32_t keySize {0};
file.read(
reinterpret_cast<char*>(&keySize),
sizeof(uint32_t)
);
data.positionKeys.resize(keySize);
data.rotationKeys.resize(keySize);
data.scaleKeys.resize(keySize);
file.read( file.read(
reinterpret_cast<char*>(data.positionKeys.data()), reinterpret_cast<char*>(data.positionKeys.data()),
sizeof(PositionKey) * keySize sizeof(PositionKey) * frameCount
); );
file.read( file.read(
reinterpret_cast<char*>(data.rotationKeys.data()), reinterpret_cast<char*>(data.rotationKeys.data()),
sizeof(RotationKey) * keySize sizeof(RotationKey) * frameCount
); );
file.read( file.read(
reinterpret_cast<char*>(data.scaleKeys.data()), reinterpret_cast<char*>(data.scaleKeys.data()),
sizeof(ScaleKey) * keySize sizeof(ScaleKey) * frameCount
); );
} }
void SHModelLoader::BuildTransformMatrices(SHRigAsset& rig)
{
std::queue<SHRigNodeAsset const*> nodeQueue;
nodeQueue.push(rig.root);
while(!nodeQueue.empty())
{
auto& current = nodeQueue.front();
nodeQueue.pop();
auto& parentData {rig.nodeDataCollection[current->idRef]};
for (auto const& child: current->children)
{
nodeQueue.push(child);
auto& childData {rig.nodeDataCollection[child->idRef]};
childData.transform = childData.transform * parentData.transform;
}
}
}
void SHModelLoader::ReadRigHeader(FileReference file, SHRigDataHeader& header) void SHModelLoader::ReadRigHeader(FileReference file, SHRigDataHeader& header)
{ {
file.read( file.read(
@ -128,6 +167,11 @@ namespace SHADE
sizeof(uint32_t) sizeof(uint32_t)
); );
file.read(
reinterpret_cast<char*>(&header.startNode),
sizeof(uint32_t)
);
header.charCounts.resize(header.nodeCount); header.charCounts.resize(header.nodeCount);
file.read( file.read(
reinterpret_cast<char*>(header.charCounts.data()), reinterpret_cast<char*>(header.charCounts.data()),
@ -141,21 +185,72 @@ namespace SHADE
for (auto i {0}; i < header.nodeCount; ++i) for (auto i {0}; i < header.nodeCount; ++i)
{ {
data[i].name.resize(header.charCounts[i]); auto& node = data[i];
node.name.resize(header.charCounts[i]);
file.read( file.read(
data[i].name.data(), node.name.data(),
header.charCounts[i] header.charCounts[i]
); );
file.read( file.read(
reinterpret_cast<char*>(&data[i].transform), reinterpret_cast<char*>(&node.inverseBindMatrix),
sizeof(SHMatrix) sizeof(SHMatrix)
); );
node.inverseBindMatrix = node.inverseBindMatrix;
NodeDataFlag flag;
file.get(reinterpret_cast<char&>(flag));
SHVec3 scale{ SHVec3::One }, translation{ SHVec3::Zero };
SHVec4 rotation{ SHVec4::UnitW };
SHMatrix matrix{ SHMatrix::Identity };
std::vector<double> carrier;
if (flag & NODE_DATA_ROTATION)
{
carrier.resize(NODE_COMPONENT_COUNT_ROTATION);
file.read( file.read(
reinterpret_cast<char*>(&data[i].offset), reinterpret_cast<char*>(carrier.data()),
sizeof(SHMatrix) sizeof(double) * NODE_COMPONENT_COUNT_ROTATION
); );
rotation = GetVec4FromVector(carrier);
}
if (flag & NODE_DATA_SCALE)
{
carrier.resize(NODE_COMPONENT_COUNT_SCALE);
file.read(
reinterpret_cast<char*>(carrier.data()),
sizeof(double) * NODE_COMPONENT_COUNT_SCALE
);
scale = GetVec3FromVector(carrier);
}
if (flag & NODE_DATA_TRANSLATION)
{
carrier.resize(NODE_COMPONENT_COUNT_TRANSLATION);
file.read(
reinterpret_cast<char*>(carrier.data()),
sizeof(double) * NODE_COMPONENT_COUNT_TRANSLATION
);
translation = GetVec3FromVector(carrier);
}
if (flag & NODE_DATA_MATRIX)
{
carrier.resize(NODE_COMPONENT_COUNT_MATRIX);
file.read(
reinterpret_cast<char*>(carrier.data()),
sizeof(double) * NODE_COMPONENT_COUNT_MATRIX
);
matrix = GetMatrixFromVector(carrier);
}
//matrix *= SHMatrix::Transform(translation, rotation, scale);
matrix *= SHMatrix::Translate(translation) * SHMatrix::Rotate(rotation) * SHMatrix::Scale(scale);
node.transform = matrix;
//node.transform = SHMatrix::Inverse(node.inverseBindMatrix);
} }
} }
@ -199,8 +294,6 @@ namespace SHADE
nodeQueue.emplace(depthPtr++, depthTempPtr++); nodeQueue.emplace(depthPtr++, depthTempPtr++);
} }
} }
delete[] dst;
} }
void SHModelLoader::ReadMeshData(FileReference file, std::vector<SHMeshDataHeader> const& headers, void SHModelLoader::ReadMeshData(FileReference file, std::vector<SHMeshDataHeader> const& headers,
@ -221,7 +314,6 @@ namespace SHADE
data.VertexNormals.resize(header.vertexCount); data.VertexNormals.resize(header.vertexCount);
data.VertexTexCoords.resize(header.vertexCount); data.VertexTexCoords.resize(header.vertexCount);
data.Indices.resize(header.indexCount); data.Indices.resize(header.indexCount);
data.BoneCount = header.boneCount;
file.read(data.name.data(), header.charCount); file.read(data.name.data(), header.charCount);
file.read(reinterpret_cast<char*>(data.VertexPositions.data()), vertexVec3Byte); file.read(reinterpret_cast<char*>(data.VertexPositions.data()), vertexVec3Byte);
@ -230,48 +322,20 @@ namespace SHADE
file.read(reinterpret_cast<char*>(data.VertexTexCoords.data()), vertexVec2Byte); file.read(reinterpret_cast<char*>(data.VertexTexCoords.data()), vertexVec2Byte);
file.read(reinterpret_cast<char*>(data.Indices.data()), sizeof(uint32_t) * header.indexCount); file.read(reinterpret_cast<char*>(data.Indices.data()), sizeof(uint32_t) * header.indexCount);
if (header.boneCount) if (header.hasWeights)
{ {
std::vector<MeshBoneInfo> boneInfos(header.boneCount);
std::vector<MeshBone> bones(header.boneCount);
file.read(reinterpret_cast<char*>(boneInfos.data()), sizeof(MeshBoneInfo) * header.boneCount);
for (auto i{ 0 }; i < header.boneCount; ++i)
{
auto& bone = bones[i];
auto const& info = boneInfos[i];
bone.name.resize(info.charCount);
file.read(bone.name.data(), info.charCount);
file.read(reinterpret_cast<char*>(&bone.offset), sizeof(SHMatrix));
bone.weights.resize(info.weightCount);
file.read(reinterpret_cast<char*>(bone.weights.data()), sizeof(BoneWeight) * info.weightCount);
}
data.VertexBoneIndices.resize(header.vertexCount); data.VertexBoneIndices.resize(header.vertexCount);
data.VertexBoneWeights.resize(header.vertexCount); data.VertexBoneWeights.resize(header.vertexCount);
for (uint32_t boneIndex{0}; boneIndex < bones.size(); ++boneIndex) file.read(
{ reinterpret_cast<char*>(data.VertexBoneWeights.data()),
auto const& bone = bones[boneIndex]; sizeof(SHVec4) * header.vertexCount
for (auto const& weight : bone.weights) );
{
auto& boneIndices = data.VertexBoneIndices[weight.index];
auto& boneWeight = data.VertexBoneWeights[weight.index];
for (auto j{0}; j < BONE_INDEX_ALIGHTMENT; ++j) file.read(
{ reinterpret_cast<char*>(data.VertexBoneIndices.data()),
if (boneWeight[j] == 0.f) sizeof(SHVec4U) * header.vertexCount
{ );
boneIndices[j] = boneIndex;
boneWeight[j] = weight.weight;
break;
}
}
}
}
} }
meshes[i] = &data; meshes[i] = &data;
@ -306,7 +370,7 @@ namespace SHADE
animAsset.nodeChannels.resize(header.animNodeCount); animAsset.nodeChannels.resize(header.animNodeCount);
for (auto i {0}; i < header.animNodeCount; ++i) for (auto i {0}; i < header.animNodeCount; ++i)
{ {
ReadAnimNode(file, header.nodeHeaders[i], animAsset.nodeChannels[i]); ReadAnimNode(file, header.frameCount, animAsset.nodeChannels[i]);
} }
anims[i] = &animAsset; anims[i] = &animAsset;

View File

@ -20,7 +20,6 @@ namespace SHADE
{ {
using FileReference = std::ifstream&; using FileReference = std::ifstream&;
void ReadAnimNode(FileReference file, SHAnimNodeInfo const& info, SHAnimData& data);
void ReadRigHeader(FileReference file, SHRigDataHeader& header); void ReadRigHeader(FileReference file, SHRigDataHeader& header);
void ReadRigData(FileReference file, SHRigDataHeader const& header, std::vector<SHRigNodeData>& data); void ReadRigData(FileReference file, SHRigDataHeader const& header, std::vector<SHRigNodeData>& data);
@ -28,6 +27,9 @@ namespace SHADE
void ReadMeshData(FileReference file, std::vector<SHMeshDataHeader> const& headers, std::vector<SHMeshAsset*>& meshes); void ReadMeshData(FileReference file, std::vector<SHMeshDataHeader> const& headers, std::vector<SHMeshAsset*>& meshes);
void ReadAnimData(FileReference file, std::vector<SHAnimDataHeader> const& headers, std::vector<SHAnimAsset*>& anims); void ReadAnimData(FileReference file, std::vector<SHAnimDataHeader> const& headers, std::vector<SHAnimAsset*>& anims);
void ReadAnimNode(FileReference file, uint32_t frameCount, SHAnimNode& data);
void BuildTransformMatrices(SHRigAsset& rig);
void ReadHeaders(FileReference file, SHModelAsset& asset); void ReadHeaders(FileReference file, SHModelAsset& asset);
void ReadData(FileReference file, SHModelAsset& asset); void ReadData(FileReference file, SHModelAsset& asset);

View File

@ -14,6 +14,7 @@
#include "Assets/Asset Types/SHSceneAsset.h" #include "Assets/Asset Types/SHSceneAsset.h"
#include "Assets/Asset Types/SHPrefabAsset.h" #include "Assets/Asset Types/SHPrefabAsset.h"
#include "Assets/Asset Types/SHMaterialAsset.h" #include "Assets/Asset Types/SHMaterialAsset.h"
#include "Assets/Asset Types/SHAudioBankAsset.h"
#include <fstream> #include <fstream>
#include <sstream> #include <sstream>
@ -22,6 +23,14 @@ namespace SHADE
{ {
SHAssetData* SHTextBasedLoader::Load(AssetPath path) SHAssetData* SHTextBasedLoader::Load(AssetPath path)
{ {
if (path.extension().string() == AUDIO_BANK_EXTENSION)
{
auto data = new SHAudioBankAsset();
data->name = path.stem().string();
data->path = path.string();
return data;
}
std::ifstream file{ path, std::ios::in }; std::ifstream file{ path, std::ios::in };
if (!file.is_open()) if (!file.is_open())

View File

@ -57,6 +57,7 @@ enum class AssetType : AssetTypeMeta
MESH, MESH,
SCRIPT, SCRIPT,
FONT, FONT,
AUDIO_BANK,
ANIM_CONTAINER, ANIM_CONTAINER,
ANIM_CLIP, ANIM_CLIP,
MAX_COUNT MAX_COUNT
@ -87,6 +88,7 @@ constexpr std::string_view ANIM_CLIP_FOLDER{ "/Animations/" };
constexpr std::string_view META_EXTENSION {".shmeta"}; constexpr std::string_view META_EXTENSION {".shmeta"};
constexpr std::string_view AUDIO_EXTENSION {".ogg"}; constexpr std::string_view AUDIO_EXTENSION {".ogg"};
constexpr std::string_view AUDIO_WAV_EXTENSION {".wav"}; constexpr std::string_view AUDIO_WAV_EXTENSION {".wav"};
constexpr std::string_view AUDIO_BANK_EXTENSION {".bank"};
constexpr std::string_view SHADER_EXTENSION{ ".shshader" }; constexpr std::string_view SHADER_EXTENSION{ ".shshader" };
constexpr std::string_view SHADER_BUILT_IN_EXTENSION{ ".shshaderb" }; constexpr std::string_view SHADER_BUILT_IN_EXTENSION{ ".shshaderb" };
constexpr std::string_view FONT_EXTENSION{ ".shfont" }; constexpr std::string_view FONT_EXTENSION{ ".shfont" };
@ -111,7 +113,7 @@ constexpr std::string_view EXTENSIONS[] = {
FILLER_EXTENSION, FILLER_EXTENSION,
SCRIPT_EXTENSION, SCRIPT_EXTENSION,
FONT_EXTENSION, FONT_EXTENSION,
AUDIO_WAV_EXTENSION, AUDIO_BANK_EXTENSION,
ANIM_CONTAINER_EXTENSION, ANIM_CONTAINER_EXTENSION,
FILLER_EXTENSION FILLER_EXTENSION
}; };

View File

@ -499,6 +499,10 @@ namespace SHADE
fontPath += FONT_EXTENSION; fontPath += FONT_EXTENSION;
newPath = fontPath; newPath = fontPath;
} }
else if (ext == AUDIO_BANK_EXTENSION.data())
{
newPath = path.string();
}
else else
{ {
SHLOG_WARNING("[Asset Manager] File Type compilation not yet Implemented: {}", path.string()); SHLOG_WARNING("[Asset Manager] File Type compilation not yet Implemented: {}", path.string());
@ -582,6 +586,7 @@ namespace SHADE
loaders[static_cast<size_t>(AssetType::MESH)] = nullptr; loaders[static_cast<size_t>(AssetType::MESH)] = nullptr;
loaders[static_cast<size_t>(AssetType::SCRIPT)] = nullptr; loaders[static_cast<size_t>(AssetType::SCRIPT)] = nullptr;
loaders[static_cast<size_t>(AssetType::FONT)] = dynamic_cast<SHAssetLoader*>(new SHFontLoader()); loaders[static_cast<size_t>(AssetType::FONT)] = dynamic_cast<SHAssetLoader*>(new SHFontLoader());
loaders[static_cast<size_t>(AssetType::AUDIO_BANK)] = loaders[static_cast<size_t>(AssetType::SCENE)];
loaders[static_cast<size_t>(AssetType::ANIM_CONTAINER)] = dynamic_cast<SHAssetLoader*>(new SHBinaryLoader()); loaders[static_cast<size_t>(AssetType::ANIM_CONTAINER)] = dynamic_cast<SHAssetLoader*>(new SHBinaryLoader());
loaders[static_cast<size_t>(AssetType::ANIM_CLIP)] = nullptr; loaders[static_cast<size_t>(AssetType::ANIM_CLIP)] = nullptr;
} }
@ -752,6 +757,20 @@ namespace SHADE
return newAsset.id; return newAsset.id;
} }
else if (ext == AUDIO_BANK_EXTENSION)
{
SHAsset newAsset{
path.stem().string(),
GenerateAssetID(AssetType::AUDIO_BANK),
AssetType::AUDIO_BANK,
path,
false
};
assetCollection.emplace(newAsset.id, newAsset);
SHAssetMetaHandler::WriteMetaData(newAsset);
return newAsset.id;
}
else if(ext == MATERIAL_EXTENSION) else if(ext == MATERIAL_EXTENSION)
{ {
SHAsset newAsset{ SHAsset newAsset{

View File

@ -486,6 +486,7 @@ namespace SHADE
SHEditorWidgets::DragVec3("Direction", { "X", "Y", "Z" }, [component]() {return component->GetDirection(); }, [component](SHVec3 const& vec) {component->SetDirection(vec); }); SHEditorWidgets::DragVec3("Direction", { "X", "Y", "Z" }, [component]() {return component->GetDirection(); }, [component](SHVec3 const& vec) {component->SetDirection(vec); });
SHEditorWidgets::ColorPicker("Color", [component]() {return component->GetColor(); }, [component](SHVec4 const& rgba) {component->SetColor(rgba); }); SHEditorWidgets::ColorPicker("Color", [component]() {return component->GetColor(); }, [component](SHVec4 const& rgba) {component->SetColor(rgba); });
SHEditorWidgets::DragFloat("Strength", [component]() {return component->GetStrength(); }, [component](float const& value) {component->SetStrength(value); }); SHEditorWidgets::DragFloat("Strength", [component]() {return component->GetStrength(); }, [component](float const& value) {component->SetStrength(value); });
SHEditorWidgets::CheckBox("Casting Shadows", [comp = component]() {return comp->GetEnableShadow(); }, [comp = component](bool b) {comp->SetEnableShadow(b);});
} }
else else
{ {

View File

@ -30,4 +30,5 @@ constexpr SHEventIdentifier SH_BUTTON_RELEASE_EVENT { 21 };
constexpr SHEventIdentifier SH_BUTTON_HOVER_ENTER_EVENT { 22 }; constexpr SHEventIdentifier SH_BUTTON_HOVER_ENTER_EVENT { 22 };
constexpr SHEventIdentifier SH_BUTTON_HOVER_EXIT_EVENT { 23 }; constexpr SHEventIdentifier SH_BUTTON_HOVER_EXIT_EVENT { 23 };
constexpr SHEventIdentifier SH_ASSET_COMPILE_EVENT { 24 }; constexpr SHEventIdentifier SH_ASSET_COMPILE_EVENT { 24 };
constexpr SHEventIdentifier SH_GRAPHICS_LIGHT_DELETE_EVENT { 25 };

View File

@ -162,6 +162,7 @@ namespace SHADE
{ {
assetCollection.emplace(asset.id, asset); assetCollection.emplace(asset.id, asset);
} }
if (file.name == asset.name) if (file.name == asset.name)
{ {
AssetPath path{ file.path }; AssetPath path{ file.path };

View File

@ -6,13 +6,16 @@
namespace SHADE namespace SHADE
{ {
struct SHLightEnableShadowEvent struct SHLightShadowEvent
{ {
//! We need to get the light component and initialize the relevant variables. //! We need to get the light component and initialize the relevant variables.
EntityID lightEntity; EntityID lightEntity;
//! Generate a renderer for the light component //! Generate a renderer for the light component
bool generateRenderer; bool firstEnable;
//! True when light is set enable shadow
bool enableShadow;
}; };
struct SHWindowResizeEvent struct SHWindowResizeEvent
@ -23,4 +26,10 @@ namespace SHADE
// New height when window resizes // New height when window resizes
uint32_t resizeHeight; uint32_t resizeHeight;
}; };
struct SHDeleteLightEvent
{
//! Entity of the light we are deleting
EntityID lightEntity;
};
} }

View File

@ -128,7 +128,7 @@ namespace SHADE
SHFreetypeInstance::Init(); SHFreetypeInstance::Init();
//SHAssetManager::CompileAsset("../../Assets/Shaders/DeferredComposite_CS.glsl", false); SHAssetManager::CompileAsset("../../Assets/Shaders/DeferredComposite_CS.glsl", false);
//SHAssetManager::CompileAsset("../../Assets/Shaders/ShadowMap_FS.glsl", false); //SHAssetManager::CompileAsset("../../Assets/Shaders/ShadowMap_FS.glsl", false);
//SHAssetManager::CompileAsset("../../Assets/Shaders/ShadowMap_FS.glsl", false); //SHAssetManager::CompileAsset("../../Assets/Shaders/ShadowMap_FS.glsl", false);
//SHAssetManager::CompileAsset("../../Assets/Shaders/SSAO_CS.glsl", false); //SHAssetManager::CompileAsset("../../Assets/Shaders/SSAO_CS.glsl", false);
@ -141,6 +141,8 @@ namespace SHADE
//SHAssetManager::CompileAsset("../../Assets/Shaders/Text_VS.glsl", false); //SHAssetManager::CompileAsset("../../Assets/Shaders/Text_VS.glsl", false);
//SHAssetManager::CompileAsset("../../Assets/Shaders/Trajectory_VS.glsl", false); //SHAssetManager::CompileAsset("../../Assets/Shaders/Trajectory_VS.glsl", false);
//SHAssetManager::CompileAsset("../../Assets/Shaders/Trajectory_FS.glsl", false); //SHAssetManager::CompileAsset("../../Assets/Shaders/Trajectory_FS.glsl", false);
//SHAssetManager::CompileAsset("../../Assets/Shaders/ShadowMapBlur_CS.glsl", false);
//SHAssetManager::CompileAsset("../../Assets/Shaders/Anim_VS.glsl", false);
// Load Built In Shaders // Load Built In Shaders
static constexpr AssetID VS_DEFAULT = 39210065; defaultVertShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(VS_DEFAULT); static constexpr AssetID VS_DEFAULT = 39210065; defaultVertShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(VS_DEFAULT);
@ -160,6 +162,7 @@ namespace SHADE
static constexpr AssetID SHADOW_MAP_FS = 45925790; shadowMapFS = SHResourceManager::LoadOrGet<SHVkShaderModule>(SHADOW_MAP_FS); static constexpr AssetID SHADOW_MAP_FS = 45925790; shadowMapFS = SHResourceManager::LoadOrGet<SHVkShaderModule>(SHADOW_MAP_FS);
static constexpr AssetID TRAJECTORY_VS = 41042628; trajectoryVS = SHResourceManager::LoadOrGet<SHVkShaderModule>(TRAJECTORY_VS); static constexpr AssetID TRAJECTORY_VS = 41042628; trajectoryVS = SHResourceManager::LoadOrGet<SHVkShaderModule>(TRAJECTORY_VS);
static constexpr AssetID TRAJECTORY_FS = 45635685; trajectoryFS = SHResourceManager::LoadOrGet<SHVkShaderModule>(TRAJECTORY_FS); static constexpr AssetID TRAJECTORY_FS = 45635685; trajectoryFS = SHResourceManager::LoadOrGet<SHVkShaderModule>(TRAJECTORY_FS);
static constexpr AssetID SHADOW_BLUR_CS = 38004013; shadowMapBlurCS = SHResourceManager::LoadOrGet<SHVkShaderModule>(SHADOW_BLUR_CS);
} }
@ -217,7 +220,7 @@ namespace SHADE
renderGraph->AddResource("Albedo", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE }, true, windowDims.first, windowDims.second); renderGraph->AddResource("Albedo", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE }, true, windowDims.first, windowDims.second);
renderGraph->AddResource("Depth Buffer", { SH_RENDER_GRAPH_RESOURCE_FLAGS::DEPTH, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT }, true, windowDims.first, windowDims.second, vk::Format::eD32SfloatS8Uint); renderGraph->AddResource("Depth Buffer", { SH_RENDER_GRAPH_RESOURCE_FLAGS::DEPTH, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT }, true, windowDims.first, windowDims.second, vk::Format::eD32SfloatS8Uint);
renderGraph->AddResource("Entity ID", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::SHARED }, true, windowDims.first, windowDims.second, vk::Format::eR32Uint, 1, vk::ImageUsageFlagBits::eTransferSrc); renderGraph->AddResource("Entity ID", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::SHARED }, true, windowDims.first, windowDims.second, vk::Format::eR32Uint, 1, vk::ImageUsageFlagBits::eTransferSrc);
renderGraph->AddResource("Light Layer Indices", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE }, true, windowDims.first, windowDims.second, vk::Format::eR32Uint, 1, vk::ImageUsageFlagBits::eTransferSrc); renderGraph->AddResource("Light Layer Indices And World Normals", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE }, true, windowDims.first, windowDims.second, vk::Format::eR32G32B32A32Uint, 1, vk::ImageUsageFlagBits::eTransferSrc);
renderGraph->AddResource("Scene", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE, SH_RENDER_GRAPH_RESOURCE_FLAGS::SHARED }, true, windowDims.first, windowDims.second); renderGraph->AddResource("Scene", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE, SH_RENDER_GRAPH_RESOURCE_FLAGS::SHARED }, true, windowDims.first, windowDims.second);
renderGraph->AddResource("SSAO", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE }, true, windowDims.first, windowDims.second, vk::Format::eR8Unorm); renderGraph->AddResource("SSAO", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE }, true, windowDims.first, windowDims.second, vk::Format::eR8Unorm);
renderGraph->AddResource("SSAO Blur", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE }, true, windowDims.first, windowDims.second, vk::Format::eR8Unorm); renderGraph->AddResource("SSAO Blur", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE }, true, windowDims.first, windowDims.second, vk::Format::eR8Unorm);
@ -231,7 +234,7 @@ namespace SHADE
{ {
"Position", "Position",
"Entity ID", "Entity ID",
"Light Layer Indices", "Light Layer Indices And World Normals",
"Normals", "Normals",
"Albedo", "Albedo",
"Depth Buffer", "Depth Buffer",
@ -248,7 +251,7 @@ namespace SHADE
auto gBufferSubpass = gBufferNode->AddSubpass(SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_WRITE_SUBPASS.data(), worldViewport, worldRenderer); auto gBufferSubpass = gBufferNode->AddSubpass(SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_WRITE_SUBPASS.data(), worldViewport, worldRenderer);
gBufferSubpass->AddColorOutput("Position"); gBufferSubpass->AddColorOutput("Position");
gBufferSubpass->AddColorOutput("Entity ID"); gBufferSubpass->AddColorOutput("Entity ID");
gBufferSubpass->AddColorOutput("Light Layer Indices"); gBufferSubpass->AddColorOutput("Light Layer Indices And World Normals");
gBufferSubpass->AddColorOutput("Normals"); gBufferSubpass->AddColorOutput("Normals");
gBufferSubpass->AddColorOutput("Albedo"); gBufferSubpass->AddColorOutput("Albedo");
gBufferSubpass->AddColorOutput("Position World Space"); gBufferSubpass->AddColorOutput("Position World Space");
@ -258,7 +261,7 @@ namespace SHADE
auto gBufferVfxSubpass = gBufferNode->AddSubpass(SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_WRITE_VFX_SUBPASS.data(), worldViewport, worldRenderer); auto gBufferVfxSubpass = gBufferNode->AddSubpass(SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_WRITE_VFX_SUBPASS.data(), worldViewport, worldRenderer);
gBufferVfxSubpass->AddColorOutput("Position"); gBufferVfxSubpass->AddColorOutput("Position");
gBufferVfxSubpass->AddColorOutput("Entity ID"); gBufferVfxSubpass->AddColorOutput("Entity ID");
gBufferVfxSubpass->AddColorOutput("Light Layer Indices"); gBufferVfxSubpass->AddColorOutput("Light Layer Indices And World Normals");
gBufferVfxSubpass->AddColorOutput("Normals"); gBufferVfxSubpass->AddColorOutput("Normals");
gBufferVfxSubpass->AddColorOutput("Albedo"); gBufferVfxSubpass->AddColorOutput("Albedo");
gBufferVfxSubpass->AddColorOutput("Position World Space"); gBufferVfxSubpass->AddColorOutput("Position World Space");
@ -314,7 +317,7 @@ namespace SHADE
auto deferredCompositeNode = renderGraph->AddNode(SHGraphicsConstants::RenderGraphEntityNames::DEFERRED_COMPOSITE_PASS.data(), auto deferredCompositeNode = renderGraph->AddNode(SHGraphicsConstants::RenderGraphEntityNames::DEFERRED_COMPOSITE_PASS.data(),
{ {
"Position", "Position",
"Light Layer Indices", "Light Layer Indices And World Normals",
"Normals", "Normals",
"Albedo", "Albedo",
"Scene", "Scene",
@ -327,7 +330,7 @@ namespace SHADE
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* DEFERRED COMPOSITE SUBPASS INIT */ /* DEFERRED COMPOSITE SUBPASS INIT */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
auto deferredCompositeCompute = deferredCompositeNode->AddNodeCompute(SHGraphicsConstants::RenderGraphEntityNames::DEFERRED_COMPOSITE_COMPUTE.data(), deferredCompositeShader, {"Position", "Normals", "Albedo", "Light Layer Indices", "SSAO Blur", "Position World Space", "Scene", "Object VFX"}, {}, SHLightingSubSystem::MAX_SHADOWS); auto deferredCompositeCompute = deferredCompositeNode->AddNodeCompute(SHGraphicsConstants::RenderGraphEntityNames::DEFERRED_COMPOSITE_COMPUTE.data(), deferredCompositeShader, {"Position", "Normals", "Albedo", "Light Layer Indices And World Normals", "SSAO Blur", "Position World Space", "Scene", "Object VFX"}, {}, SHLightingSubSystem::MAX_SHADOWS);
deferredCompositeCompute->AddPreComputeFunction([=](Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) deferredCompositeCompute->AddPreComputeFunction([=](Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex)
{ {
lightingSubSystem->PrepareShadowMapsForRead(cmdBuffer); lightingSubSystem->PrepareShadowMapsForRead(cmdBuffer);
@ -534,12 +537,21 @@ namespace SHADE
ReceiverPtr lightEnableShadowReceivePtr = std::dynamic_pointer_cast<SHEventReceiver>(lightEnableShadowReceiver); ReceiverPtr lightEnableShadowReceivePtr = std::dynamic_pointer_cast<SHEventReceiver>(lightEnableShadowReceiver);
SHEventManager::SubscribeTo(SH_GRAPHICS_LIGHT_ENABLE_SHADOW_EVENT, lightEnableShadowReceivePtr); SHEventManager::SubscribeTo(SH_GRAPHICS_LIGHT_ENABLE_SHADOW_EVENT, lightEnableShadowReceivePtr);
std::shared_ptr<SHEventReceiverSpec<SHGraphicsSystem>> lightDeleteEvent
{
std::make_shared<SHEventReceiverSpec<SHGraphicsSystem>>(this, &SHGraphicsSystem::ReceiveLightDeleteEvent)
};
ReceiverPtr lightDeleteReceivePtr = std::dynamic_pointer_cast<SHEventReceiver>(lightDeleteEvent);
SHEventManager::SubscribeTo(SH_GRAPHICS_LIGHT_DELETE_EVENT, lightDeleteReceivePtr);
std::shared_ptr<SHEventReceiverSpec<SHGraphicsSystem>> compileAssetReceiever std::shared_ptr<SHEventReceiverSpec<SHGraphicsSystem>> compileAssetReceiever
{ {
std::make_shared<SHEventReceiverSpec<SHGraphicsSystem>>(this, &SHGraphicsSystem::ReceiveCompileAssetEvent) std::make_shared<SHEventReceiverSpec<SHGraphicsSystem>>(this, &SHGraphicsSystem::ReceiveCompileAssetEvent)
}; };
ReceiverPtr compileAssetReceivePtr = std::dynamic_pointer_cast<SHEventReceiver>(compileAssetReceiever); ReceiverPtr compileAssetReceivePtr = std::dynamic_pointer_cast<SHEventReceiver>(compileAssetReceiever);
SHEventManager::SubscribeTo(SH_ASSET_COMPILE_EVENT, compileAssetReceivePtr); SHEventManager::SubscribeTo(SH_ASSET_COMPILE_EVENT, compileAssetReceivePtr);
} }
void SHGraphicsSystem::InitGenericDataAndTexturesDescSet(void) noexcept void SHGraphicsSystem::InitGenericDataAndTexturesDescSet(void) noexcept
@ -674,22 +686,6 @@ namespace SHADE
#endif #endif
} }
//static bool shadowAdded = false;
//if (shadowAdded == false && SHInputManager::GetKey(SHInputManager::SH_KEYCODE::B))
//{
// shadowAdded = true;
// auto& lightComps = SHComponentManager::GetDense<SHLightComponent>();
// //if (lightComps.size() > 2)
// //{
// // lightComps[2].SetEnableShadow(true);
// //}
// for (auto& comp : lightComps)
// {
// comp.SetEnableShadow(true);
// }
//}
renderGraph->Begin(frameIndex); renderGraph->Begin(frameIndex);
auto cmdBuffer = renderGraph->GetCommandBuffer(frameIndex); auto cmdBuffer = renderGraph->GetCommandBuffer(frameIndex);
@ -864,36 +860,47 @@ namespace SHADE
SHEventHandle SHGraphicsSystem::ReceiveLightEnableShadowEvent(SHEventPtr eventPtr) noexcept SHEventHandle SHGraphicsSystem::ReceiveLightEnableShadowEvent(SHEventPtr eventPtr) noexcept
{ {
// we need to wait for the device to finish using the graph first auto const& EVENT_DATA = reinterpret_cast<const SHEventSpec<SHLightShadowEvent>*>(eventPtr.get())->data;
device->WaitIdle();
auto const& EVENT_DATA = reinterpret_cast<const SHEventSpec<SHLightEnableShadowEvent>*>(eventPtr.get())->data;
auto* lightComp = SHComponentManager::GetComponent<SHLightComponent>(EVENT_DATA->lightEntity); auto* lightComp = SHComponentManager::GetComponent<SHLightComponent>(EVENT_DATA->lightEntity);
std::string depthResourceName = "ShadowMap_Depth " + std::to_string(EVENT_DATA->lightEntity); std::string depthResourceName = "ShadowMap_Depth " + std::to_string(EVENT_DATA->lightEntity);
std::string shadowMapResourceName = "ShadowMap " + std::to_string(EVENT_DATA->lightEntity); std::string shadowMapResourceName = "ShadowMap " + std::to_string(EVENT_DATA->lightEntity);
Handle<SHSubpass> companionSubpass = renderGraph->GetNode(SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_PASS.data())->GetSubpass(SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_WRITE_SUBPASS); std::string shadowMapBlurredResourceName = "ShadowMap Blurred" + std::to_string(EVENT_DATA->lightEntity);
Handle<SHSubpass> gBufferWriteSubpass = renderGraph->GetNode(SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_PASS.data())->GetSubpass(SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_WRITE_SUBPASS);
Handle<SHSubpass> gBufferWriteVfxSubpass = renderGraph->GetNode(SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_PASS.data())->GetSubpass(SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_WRITE_VFX_SUBPASS);
if (EVENT_DATA->generateRenderer) if (EVENT_DATA->enableShadow)
{ {
// When the light first enables shadow rendering, we need to prepare the relevant objects to render shadows; namely renderpasses and subpasses, pipelines and descriptor sets
if (EVENT_DATA->firstEnable)
{
// we need to wait for the device to finish using the graph first
device->WaitIdle();
// Create new renderer for the light component and give it to the light component // Create new renderer for the light component and give it to the light component
Handle<SHRenderer> newRenderer = resourceManager.Create<SHRenderer>(device, swapchain->GetNumImages(), descPool, SHRenderer::PROJECTION_TYPE::ORTHOGRAPHIC); Handle<SHRenderer> newRenderer = resourceManager.Create<SHRenderer>(device, swapchain->GetNumImages(), descPool, SHRenderer::PROJECTION_TYPE::ORTHOGRAPHIC);
lightComp->SetRenderer(newRenderer); lightComp->SetRenderer(newRenderer);
// assign shadow map index to light component // assign shadow map index to light component
lightComp->SetShadowMapIndex(lightingSubSystem->GetNumShadowMaps()); lightComp->SetShadowMapIndex(lightingSubSystem->GetNumShadowMaps());
}
// Add the shadow map resource to the graph // Add the shadow map resource to the graph
renderGraph->AddResource(depthResourceName, { SH_RENDER_GRAPH_RESOURCE_FLAGS::DEPTH }, false, SHLightingSubSystem::SHADOW_MAP_WIDTH, SHLightingSubSystem::SHADOW_MAP_HEIGHT, vk::Format::eD32Sfloat); renderGraph->AddResource(depthResourceName, { SH_RENDER_GRAPH_RESOURCE_FLAGS::DEPTH }, false, SHLightingSubSystem::SHADOW_MAP_WIDTH, SHLightingSubSystem::SHADOW_MAP_HEIGHT, vk::Format::eD32Sfloat);
renderGraph->AddResource(shadowMapResourceName, { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT }, false, SHLightingSubSystem::SHADOW_MAP_WIDTH, SHLightingSubSystem::SHADOW_MAP_HEIGHT, vk::Format::eR32G32B32A32Sfloat); renderGraph->AddResource(shadowMapResourceName, { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE }, false, SHLightingSubSystem::SHADOW_MAP_WIDTH, SHLightingSubSystem::SHADOW_MAP_HEIGHT, vk::Format::eR32G32B32A32Sfloat);
renderGraph->AddResource(shadowMapBlurredResourceName, { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE }, false, SHLightingSubSystem::SHADOW_MAP_WIDTH, SHLightingSubSystem::SHADOW_MAP_HEIGHT, vk::Format::eR32G32B32A32Sfloat);
// link resource to node. This means linking the resource and regenerating the node's renderpass and framebuffer. // link resource to node. This means linking the resource and regenerating the node's renderpass and framebuffer.
auto shadowMapNode = renderGraph->AddNodeAfter(SHGraphicsConstants::RenderGraphEntityNames::SHADOW_MAP_PASS.data() + shadowMapResourceName, {depthResourceName.c_str(), shadowMapResourceName.c_str()}, SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_PASS.data()); auto shadowMapNode = renderGraph->AddNodeAfter(SHGraphicsConstants::RenderGraphEntityNames::SHADOW_MAP_PASS.data() + shadowMapResourceName, { depthResourceName.c_str(), shadowMapResourceName.c_str(), shadowMapBlurredResourceName.c_str() }, SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_PASS.data());
// Add a subpass to render to that shadow map // Add a subpass to render to that shadow map
auto newSubpass = shadowMapNode->RuntimeAddSubpass(shadowMapResourceName + " Subpass", shadowMapViewport, lightComp->GetRenderer()); auto shadowMapDrawSubpass = shadowMapNode->RuntimeAddSubpass(shadowMapResourceName + " Subpass", shadowMapViewport, lightComp->GetRenderer());
newSubpass->AddColorOutput(shadowMapResourceName); shadowMapDrawSubpass->AddColorOutput(shadowMapResourceName);
newSubpass->AddDepthOutput(depthResourceName, SH_RENDER_GRAPH_RESOURCE_FLAGS::DEPTH); shadowMapDrawSubpass->AddDepthOutput(depthResourceName, SH_RENDER_GRAPH_RESOURCE_FLAGS::DEPTH);
// add compute pass to blur shadow ma
shadowMapNode->AddNodeCompute(SHGraphicsConstants::RenderGraphEntityNames::SHADOW_MAP_PASS.data() + shadowMapResourceName, shadowMapBlurCS, { shadowMapResourceName.c_str(), shadowMapBlurredResourceName.c_str() });
// regenerate the node // regenerate the node
shadowMapNode->RuntimeStandaloneRegenerate(); shadowMapNode->RuntimeStandaloneRegenerate();
@ -910,19 +917,63 @@ namespace SHADE
tempLibrary.Init(device); tempLibrary.Init(device);
tempLibrary.CreateGraphicsPipelines tempLibrary.CreateGraphicsPipelines
( (
{ shadowMapVS, shadowMapFS }, shadowMapNode->GetRenderpass(), newSubpass, { shadowMapVS, shadowMapFS }, shadowMapNode->GetRenderpass(), shadowMapDrawSubpass,
SHGraphicsPredefinedData::SystemType::BATCHING, SHGraphicsPredefinedData::SystemType::BATCHING,
SHGraphicsPredefinedData::GetShadowMapViState(), rasterState SHGraphicsPredefinedData::GetShadowMapViState(), rasterState
); );
shadowMapPipeline = tempLibrary.GetGraphicsPipeline({ shadowMapVS, shadowMapFS, newSubpass }); shadowMapPipeline = tempLibrary.GetGraphicsPipeline({ shadowMapVS, shadowMapFS, shadowMapDrawSubpass });
} }
newSubpass->SetCompanionSubpass(companionSubpass, shadowMapPipeline); // set companion subpass and pipeline shadowMapDrawSubpass->AddCompanionSubpass(gBufferWriteSubpass, shadowMapPipeline); // set companion subpass and pipeline
shadowMapDrawSubpass->AddCompanionSubpass(gBufferWriteVfxSubpass, shadowMapPipeline); // set companion subpass and pipeline
// add the shadow map to the lighting system // add the shadow map and the blurred version to the lighting system
uint32_t const NEW_SHADOW_MAP_INDEX = lightingSubSystem->AddShadowMap(renderGraph->GetRenderGraphResource(shadowMapResourceName), EVENT_DATA->lightEntity); uint32_t const NEW_SHADOW_MAP_INDEX = lightingSubSystem->AddShadowMap(renderGraph->GetRenderGraphResource(shadowMapBlurredResourceName), EVENT_DATA->lightEntity);
// Get deferred composite node compute and modify descriptor set
auto nodeCompute = renderGraph->GetNode(SHGraphicsConstants::RenderGraphEntityNames::DEFERRED_COMPOSITE_PASS.data())->GetNodeCompute(SHGraphicsConstants::RenderGraphEntityNames::DEFERRED_COMPOSITE_COMPUTE.data()); auto nodeCompute = renderGraph->GetNode(SHGraphicsConstants::RenderGraphEntityNames::DEFERRED_COMPOSITE_PASS.data())->GetNodeCompute(SHGraphicsConstants::RenderGraphEntityNames::DEFERRED_COMPOSITE_COMPUTE.data());
nodeCompute->ModifyWriteDescImageComputeResource(SHGraphicsConstants::DescriptorSetBindings::SHADOW_MAP_IMAGE_SAMPLER_DATA, lightingSubSystem->GetViewSamplerLayout(NEW_SHADOW_MAP_INDEX), NEW_SHADOW_MAP_INDEX); nodeCompute->ModifyWriteDescImageComputeResource(SHGraphicsConstants::DescriptorSetBindings::SHADOW_MAP_IMAGE_SAMPLER_DATA, lightingSubSystem->GetViewSamplerLayout(NEW_SHADOW_MAP_INDEX), NEW_SHADOW_MAP_INDEX);
}
else
{
// get the shadow map node
renderGraph->GetNode (SHGraphicsConstants::RenderGraphEntityNames::SHADOW_MAP_PASS.data() + shadowMapResourceName)->SetDynamicActive(true);
}
}
else
{
// get the shadow map node
renderGraph->GetNode(SHGraphicsConstants::RenderGraphEntityNames::SHADOW_MAP_PASS.data() + shadowMapResourceName)->SetDynamicActive(false);
}
return eventPtr->handle;
}
SHEventHandle SHGraphicsSystem::ReceiveLightDeleteEvent(SHEventPtr eventPtr) noexcept
{
// we need to wait for the device to finish using the graph first
device->WaitIdle();
auto const& EVENT_DATA = reinterpret_cast<const SHEventSpec<SHLightShadowEvent>*>(eventPtr.get())->data;
auto* lightComp = SHComponentManager::GetComponent<SHLightComponent>(EVENT_DATA->lightEntity);
if (lightComp && lightComp->GetShadowMapIndex() != SHLightData::INVALID_SHADOW_MAP_INDEX)
{
std::string depthResourceName = "ShadowMap_Depth " + std::to_string(EVENT_DATA->lightEntity);
std::string shadowMapResourceName = "ShadowMap " + std::to_string(EVENT_DATA->lightEntity);
std::string shadowMapBlurredResourceName = "ShadowMap Blurred" + std::to_string(EVENT_DATA->lightEntity);
// Remove render graph node
//renderGraph->RemoveNode(SHGraphicsConstants::RenderGraphEntityNames::SHADOW_MAP_PASS.data() + shadowMapResourceName);
// Remove render graph resource
//renderGraph->RemoveResource(depthResourceName);
//renderGraph->RemoveResource(shadowMapResourceName);
//renderGraph->RemoveResource(shadowMapBlurredResourceName);
// Register light component shadow map index into light system as recyclable
lightingSubSystem->RemoveShadowMap (EVENT_DATA->lightEntity);
}
return eventPtr->handle; return eventPtr->handle;
} }

View File

@ -182,6 +182,7 @@ namespace SHADE
/* Light functions */ /* Light functions */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
SHEventHandle ReceiveLightEnableShadowEvent (SHEventPtr eventPtr) noexcept; SHEventHandle ReceiveLightEnableShadowEvent (SHEventPtr eventPtr) noexcept;
SHEventHandle ReceiveLightDeleteEvent (SHEventPtr eventPtr) noexcept;
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* Asset Events */ /* Asset Events */
@ -481,6 +482,7 @@ namespace SHADE
Handle<SHVkShaderModule> shadowMapFS; Handle<SHVkShaderModule> shadowMapFS;
Handle<SHVkShaderModule> trajectoryVS; Handle<SHVkShaderModule> trajectoryVS;
Handle<SHVkShaderModule> trajectoryFS; Handle<SHVkShaderModule> trajectoryFS;
Handle<SHVkShaderModule> shadowMapBlurCS;
// Fonts // Fonts
Handle<SHFont> testFont; Handle<SHFont> testFont;

View File

@ -21,6 +21,14 @@ namespace SHADE
void SHLightComponent::OnDestroy(void) void SHLightComponent::OnDestroy(void)
{ {
if (lightData.shadowMapIndex != SHLightData::INVALID_SHADOW_MAP_INDEX)
{
// Create new event and broadcast it
SHDeleteLightEvent newEvent;
newEvent.lightEntity = GetEID();
SHEventManager::BroadcastEvent<SHDeleteLightEvent>(newEvent, SH_GRAPHICS_LIGHT_DELETE_EVENT);
}
} }
@ -113,15 +121,21 @@ namespace SHADE
lightData.castShadows = flag; lightData.castShadows = flag;
// If the flag is true // If the flag is true
if (flag && lightData.shadowMapIndex == SHLightData::INVALID_SHADOW_MAP_INDEX) if (flag)
{ {
// Create new event and broadcast it // Create new event and broadcast it
SHLightEnableShadowEvent newEvent; SHLightShadowEvent newEvent;
newEvent.lightEntity = GetEID(); newEvent.lightEntity = GetEID();
newEvent.generateRenderer = static_cast<bool>(!renderer);
SHEventManager::BroadcastEvent<SHLightEnableShadowEvent>(newEvent, SH_GRAPHICS_LIGHT_ENABLE_SHADOW_EVENT); // If shadow map index is invalid, that means light is enabling shadow for the first time.
newEvent.firstEnable = (lightData.shadowMapIndex == SHLightData::INVALID_SHADOW_MAP_INDEX);
// pass the flag to the event
newEvent.enableShadow = flag;
SHEventManager::BroadcastEvent<SHLightShadowEvent>(newEvent, SH_GRAPHICS_LIGHT_ENABLE_SHADOW_EVENT);
} }
} }
void SHLightComponent::SetRenderer(Handle<SHRenderer> newRenderer) noexcept void SHLightComponent::SetRenderer(Handle<SHRenderer> newRenderer) noexcept
@ -190,6 +204,16 @@ namespace SHADE
return renderer; return renderer;
} }
bool SHLightComponent::GetEnableShadow(void) const noexcept
{
return lightData.castShadows;
}
uint32_t SHLightComponent::GetShadowMapIndex(void) const noexcept
{
return lightData.shadowMapIndex;
}
} }
RTTR_REGISTRATION RTTR_REGISTRATION
@ -212,5 +236,6 @@ RTTR_REGISTRATION
.property("Color", &SHLightComponent::GetColor, &SHLightComponent::SetColor) .property("Color", &SHLightComponent::GetColor, &SHLightComponent::SetColor)
.property("Layer", &SHLightComponent::GetCullingMask, &SHLightComponent::SetCullingMask) .property("Layer", &SHLightComponent::GetCullingMask, &SHLightComponent::SetCullingMask)
.property("Strength", &SHLightComponent::GetStrength, &SHLightComponent::SetStrength) .property("Strength", &SHLightComponent::GetStrength, &SHLightComponent::SetStrength)
.property("Casting Shadows", &SHLightComponent::GetEnableShadow, &SHLightComponent::SetEnableShadow)
; ;
} }

View File

@ -69,6 +69,9 @@ namespace SHADE
//uint32_t GetIndexInBuffer (void) const noexcept; //uint32_t GetIndexInBuffer (void) const noexcept;
float GetStrength (void) const noexcept; float GetStrength (void) const noexcept;
Handle<SHRenderer> GetRenderer (void) const noexcept; Handle<SHRenderer> GetRenderer (void) const noexcept;
bool GetEnableShadow (void) const noexcept;
uint32_t GetShadowMapIndex (void) const noexcept;
RTTR_ENABLE() RTTR_ENABLE()
}; };
} }

View File

@ -53,6 +53,7 @@ namespace SHADE
SHVec4 transformedDir = SHMatrix::Transpose(viewMat) * SHVec4(lightData.direction[0], lightData.direction[1], lightData.direction[2], 0.0f); SHVec4 transformedDir = SHMatrix::Transpose(viewMat) * SHVec4(lightData.direction[0], lightData.direction[1], lightData.direction[2], 0.0f);
lightPtr->cullingMask = lightData.cullingMask; lightPtr->cullingMask = lightData.cullingMask;
lightPtr->directionWorld = SHVec4 (lightData.direction.x, lightData.direction.y, lightData.direction.z, 1.0f);
lightPtr->direction = SHVec3(transformedDir.x, transformedDir.y, transformedDir.z); lightPtr->direction = SHVec3(transformedDir.x, transformedDir.y, transformedDir.z);
//lightPtr->direction = lightData.direction; //lightPtr->direction = lightData.direction;
lightPtr->diffuseColor = lightData.color; lightPtr->diffuseColor = lightData.color;
@ -525,7 +526,7 @@ namespace SHADE
if (auto renderer = light.GetRenderer()) if (auto renderer = light.GetRenderer())
{ {
//SHMatrix orthoMatrix = SHMatrix::OrthographicRH() //SHMatrix orthoMatrix = SHMatrix::OrthographicRH()
renderer->UpdateDataManual(frameIndex, GetViewMatrix(&light), SHMatrix::OrthographicLH(12.0f, 12.0f, 1.0f, 80.0f)); renderer->UpdateDataManual(frameIndex, GetViewMatrix(&light), SHMatrix::OrthographicLH(15.0f, 15.0f, 1.0f, 80.0f));
} }
auto enumValue = SHUtilities::ConvertEnum(light.GetLightData().type); auto enumValue = SHUtilities::ConvertEnum(light.GetLightData().type);
@ -598,49 +599,25 @@ namespace SHADE
{ {
//Bind descriptor set(We bind at an offset because the buffer holds NUM_FRAME_BUFFERS sets of data). //Bind descriptor set(We bind at an offset because the buffer holds NUM_FRAME_BUFFERS sets of data).
cmdBuffer->BindDescriptorSet(lightingDataDescSet, SH_PIPELINE_TYPE::COMPUTE, setIndex, { dynamicOffsets[frameIndex] }); cmdBuffer->BindDescriptorSet(lightingDataDescSet, SH_PIPELINE_TYPE::COMPUTE, setIndex, { dynamicOffsets[frameIndex] });
} }
uint32_t SHLightingSubSystem::AddShadowMap(Handle<SHRenderGraphResource> newShadowMap, EntityID lightEntity) noexcept uint32_t SHLightingSubSystem::AddShadowMap(Handle<SHRenderGraphResource> newShadowMapBlurred, EntityID lightEntity) noexcept
{ {
// Add to container of shadow maps uint32_t usedIndex = 0;
shadowMapIndexing.emplace(lightEntity, static_cast<uint32_t> (shadowMaps.size()));
shadowMaps.emplace_back(newShadowMap);
// Just use the image view stored in the resource // Just use the image view stored in the resource
Handle<SHVkImageView> const NEW_IMAGE_VIEW = newShadowMap->GetImageView(); Handle<SHVkImageView> const NEW_IMAGE_VIEW = newShadowMapBlurred->GetImageView();
// Prepare to write to descriptor
shadowMapImageSamplers.emplace_back(NEW_IMAGE_VIEW, shadowMapSampler, vk::ImageLayout::eShaderReadOnlyOptimal);
// Update descriptor set
//static constexpr uint32_t SHADOW_MAP_DESC_SET_INDEX = 0;
//uint32_t const SHADOW_MAP_DESC_ARRAY_INDEX = static_cast<uint32_t>(shadowMapImageSamplers.size()) - 1u;
//shadowMapDescriptorSet->ModifyWriteDescImage
//(
// SHADOW_MAP_DESC_SET_INDEX,
// SHGraphicsConstants::DescriptorSetBindings::SHADOW_MAP_IMAGE_SAMPLER_DATA,
// shadowMapImageSamplers[SHADOW_MAP_DESC_ARRAY_INDEX],
// SHADOW_MAP_DESC_ARRAY_INDEX
//);
//// TODO: Definitely can be optimized by writing a function that modifies a specific descriptor in the array
//shadowMapDescriptorSet->UpdateDescriptorSetImages
//(
// SHADOW_MAP_DESC_SET_INDEX,
// SHGraphicsConstants::DescriptorSetBindings::SHADOW_MAP_IMAGE_SAMPLER_DATA
//);
// add to barriers // add to barriers
shadowMapMemoryBarriers.push_back (vk::ImageMemoryBarrier shadowMapMemoryBarriers.push_back (vk::ImageMemoryBarrier
{ {
.srcAccessMask = vk::AccessFlagBits::eColorAttachmentWrite | vk::AccessFlagBits::eColorAttachmentRead, .srcAccessMask = vk::AccessFlagBits::eShaderWrite,
.dstAccessMask = vk::AccessFlagBits::eShaderRead, .dstAccessMask = vk::AccessFlagBits::eShaderRead,
.oldLayout = vk::ImageLayout::eColorAttachmentOptimal, .oldLayout = vk::ImageLayout::eGeneral,
.newLayout = vk::ImageLayout::eShaderReadOnlyOptimal, .newLayout = vk::ImageLayout::eGeneral,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.image = newShadowMap->GetImage()->GetVkImage(), .image = newShadowMapBlurred->GetImage()->GetVkImage(),
.subresourceRange = vk::ImageSubresourceRange .subresourceRange = vk::ImageSubresourceRange
{ {
.aspectMask = vk::ImageAspectFlagBits::eColor, .aspectMask = vk::ImageAspectFlagBits::eColor,
@ -651,38 +628,76 @@ namespace SHADE
} }
}); });
if (recyclableIndices.empty())
{
shadowMaps.emplace_back(newShadowMapBlurred);
// Prepare to write to descriptor
shadowMapImageSamplers.emplace_back(NEW_IMAGE_VIEW, shadowMapSampler, vk::ImageLayout::eShaderReadOnlyOptimal);
// Add to container of shadow maps
shadowMapIndexing.emplace(lightEntity, static_cast<uint32_t> (shadowMaps.size()));
usedIndex = static_cast<uint32_t>(shadowMapImageSamplers.size()) - 1u;
}
else
{
uint32_t usedIndex = recyclableIndices.top();
recyclableIndices.pop();
// Recycle the slot in the vector of shadow maps
shadowMaps[usedIndex] = newShadowMapBlurred;
// register indexing for shadow maps
shadowMapIndexing.emplace(lightEntity, usedIndex);
// Recycle the slot in the vector of image view, samplers and layout
shadowMapImageSamplers[usedIndex] = std::make_tuple(NEW_IMAGE_VIEW, shadowMapSampler, vk::ImageLayout::eShaderReadOnlyOptimal);
}
// return new index of shadow map // return new index of shadow map
return static_cast<uint32_t>(shadowMapImageSamplers.size()) - 1u; return usedIndex;
}
void SHLightingSubSystem::RemoveShadowMap(EntityID lightEntity) noexcept
{
auto* lightComp = SHComponentManager::GetComponent<SHLightComponent>(lightEntity);
if (lightComp && shadowMapIndexing.contains(lightEntity))
{
uint32_t shadowMapIndex = shadowMapIndexing[lightEntity];
// Recycle the shadow map index used by the component
RecycleShadowMapIndex(lightComp);
// Not removed from container, can recycle
shadowMaps[shadowMapIndex] = {};
// Not removed from container, can recycle
shadowMapImageSamplers[shadowMapIndex] = {};
// Remove from barriers
shadowMapMemoryBarriers.erase(shadowMapMemoryBarriers.begin() + shadowMapIndex);
// remove from map for indexing
shadowMapIndexing.erase(lightEntity);
}
}
void SHLightingSubSystem::RecycleShadowMapIndex(SHLightComponent* lightComp) noexcept
{
// if index is recyclable, recycle it
if (lightComp && lightComp->GetShadowMapIndex() != SHLightData::INVALID_SHADOW_MAP_INDEX)
recyclableIndices.push (lightComp->GetShadowMapIndex());
} }
void SHLightingSubSystem::PrepareShadowMapsForRead(Handle<SHVkCommandBuffer> cmdBuffer) noexcept void SHLightingSubSystem::PrepareShadowMapsForRead(Handle<SHVkCommandBuffer> cmdBuffer) noexcept
{ {
// Issue barrier to transition shadow maps for reading in compute shader // Issue barrier to transition shadow maps for reading in compute shader
cmdBuffer->PipelineBarrier(vk::PipelineStageFlagBits::eColorAttachmentOutput, vk::PipelineStageFlagBits::eComputeShader, {}, {}, {}, shadowMapMemoryBarriers); cmdBuffer->PipelineBarrier(vk::PipelineStageFlagBits::eComputeShader, vk::PipelineStageFlagBits::eComputeShader, {}, {}, {}, shadowMapMemoryBarriers);
} }
//void SHLightingSubSystem::HandleResize(Handle<SHRenderGraphNodeCompute> compute) noexcept
//{
// uint32_t const NUM_SHADOW_MAPS = static_cast<uint32_t>(shadowMaps.size());
// for (uint32_t i = 0; i < NUM_SHADOW_MAPS; ++i)
// {
// // Just use the image view stored in the resource
// Handle<SHVkImageView> const NEW_IMAGE_VIEW = shadowMaps[i]->GetImageView();
// // set new image view
// std::get<Handle<SHVkImageView>>(shadowMapImageSamplers[i]) = NEW_IMAGE_VIEW;
// // Set image for barrier
// shadowMapMemoryBarriers[i].image = shadowMaps[i]->GetImage()->GetVkImage();
// }
// if (NUM_SHADOW_MAPS > 0)
// {
// // modify descriptors in render graph node compute
// compute->ModifyWriteDescImageComputeResource (SHGraphicsConstants::DescriptorSetBindings::SHADOW_MAP_IMAGE_SAMPLER_DATA, shadowMapImageSamplers);
// }
//}
Handle<SHVkDescriptorSetGroup> SHLightingSubSystem::GetLightDataDescriptorSet(void) const noexcept Handle<SHVkDescriptorSetGroup> SHLightingSubSystem::GetLightDataDescriptorSet(void) const noexcept
{ {
return lightingDataDescSet; return lightingDataDescSet;

View File

@ -9,6 +9,7 @@
#include "Graphics/MiddleEnd/Interface/SHGraphicsConstants.h" #include "Graphics/MiddleEnd/Interface/SHGraphicsConstants.h"
#include "Graphics/RenderGraph/SHRenderGraphResource.h" #include "Graphics/RenderGraph/SHRenderGraphResource.h"
#include "ECS_Base/SHECSMacros.h" #include "ECS_Base/SHECSMacros.h"
#include <stack>
namespace SHADE namespace SHADE
@ -28,6 +29,9 @@ namespace SHADE
// Represents how the data will be interpreted in GPU. we want to copy to a container of these before passing to GPU. // Represents how the data will be interpreted in GPU. we want to copy to a container of these before passing to GPU.
struct SHDirectionalLightData struct SHDirectionalLightData
{ {
//! Direction of the light
SHVec4 directionWorld;
//! Direction of the light //! Direction of the light
SHVec3 direction; SHVec3 direction;
@ -180,10 +184,6 @@ namespace SHADE
//! Shadow maps for every light that casts a shadow Order here doesn't matter. We just want to store it //! Shadow maps for every light that casts a shadow Order here doesn't matter. We just want to store it
std::vector<Handle<SHRenderGraphResource>> shadowMaps; std::vector<Handle<SHRenderGraphResource>> shadowMaps;
//! Descriptor sets required to be given to the compute shader for shadow calculation. This will be a descriptor array.
//! It will also be preallocated.
//Handle<SHVkDescriptorSetGroup> shadowMapDescriptorSet;
//! Combined image samplers for the texture descriptors //! Combined image samplers for the texture descriptors
std::vector<std::tuple<Handle<SHVkImageView>, Handle<SHVkSampler>, vk::ImageLayout>> shadowMapImageSamplers; std::vector<std::tuple<Handle<SHVkImageView>, Handle<SHVkSampler>, vk::ImageLayout>> shadowMapImageSamplers;
@ -191,6 +191,9 @@ namespace SHADE
//! to VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) //! to VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
std::vector<vk::ImageMemoryBarrier> shadowMapMemoryBarriers; std::vector<vk::ImageMemoryBarrier> shadowMapMemoryBarriers;
//! recycled indices after deleting lights with shadows
std::stack<uint32_t> recyclableIndices;
//! Resource hub from Graphics System //! Resource hub from Graphics System
SHResourceHub* resourceHub; SHResourceHub* resourceHub;
@ -213,7 +216,9 @@ namespace SHADE
void Run (SHMatrix const& viewMat, uint32_t frameIndex) noexcept; void Run (SHMatrix const& viewMat, uint32_t frameIndex) noexcept;
void Exit (void) noexcept; void Exit (void) noexcept;
void BindDescSet (Handle<SHVkCommandBuffer> cmdBuffer, uint32_t setIndex, uint32_t frameIndex) noexcept; void BindDescSet (Handle<SHVkCommandBuffer> cmdBuffer, uint32_t setIndex, uint32_t frameIndex) noexcept;
uint32_t AddShadowMap (Handle<SHRenderGraphResource> newShadowMap, EntityID lightEntity) noexcept; uint32_t AddShadowMap (Handle<SHRenderGraphResource> newShadowMapBlurred, EntityID lightEntity) noexcept;
void RemoveShadowMap (EntityID lightEntity) noexcept;
void RecycleShadowMapIndex (SHLightComponent* lightComp) noexcept;
void PrepareShadowMapsForRead (Handle<SHVkCommandBuffer> cmdBuffer) noexcept; void PrepareShadowMapsForRead (Handle<SHVkCommandBuffer> cmdBuffer) noexcept;
//void HandleResize (Handle<SHRenderGraphNodeCompute> compute) noexcept; //void HandleResize (Handle<SHRenderGraphNodeCompute> compute) noexcept;
//void RemoveShadowMap (uint32_t index) noexcept; //void RemoveShadowMap (uint32_t index) noexcept;

View File

@ -81,7 +81,8 @@ namespace SHADE
renderGraphStorage->logicalDevice->WaitIdle(); renderGraphStorage->logicalDevice->WaitIdle();
uint64_t handleID = renderGraphStorage->graphResources->at (resourceName).GetId().Raw; auto resourceHdl = renderGraphStorage->graphResources->at(resourceName);
uint64_t handleID = resourceHdl.GetId().Raw;
// Record nodes that will be affected // Record nodes that will be affected
std::vector<uint32_t> affectedNodes{}; std::vector<uint32_t> affectedNodes{};
@ -89,7 +90,7 @@ namespace SHADE
// Detach resource from all nodes if applicable // Detach resource from all nodes if applicable
for (uint32_t i = 0; i < nodes.size(); ++i) for (uint32_t i = 0; i < nodes.size(); ++i)
{ {
if (nodes[i]->DetachResource(resourceName, handleID)) if (nodes[i] && nodes[i]->DetachResource(resourceName, handleID))
affectedNodes.emplace_back(i); affectedNodes.emplace_back(i);
} }
@ -109,6 +110,8 @@ namespace SHADE
renderGraphStorage->graphResources->at(resourceName).Free(); renderGraphStorage->graphResources->at(resourceName).Free();
renderGraphStorage->graphResources->erase (resourceName); renderGraphStorage->graphResources->erase (resourceName);
resourceHdl.Free ();
/* /*
* IMPORTANT NOTES * IMPORTANT NOTES
* *
@ -121,6 +124,21 @@ namespace SHADE
*/ */
} }
void SHRenderGraph::RemoveNode(std::string nodeName) noexcept
{
if (nodeIndexing.contains(nodeName))
{
// wait for device to stop
renderGraphStorage->logicalDevice->WaitIdle();
// Get handle to node since it exists
auto nodeHdl = nodes[nodeIndexing[nodeName]];
nodeHdl.Free();
nodeIndexing.erase(nodeName);
}
}
void SHRenderGraph::LinkNonOwningResource(Handle<SHRenderGraph> resourceOrigin, std::string resourceName) noexcept void SHRenderGraph::LinkNonOwningResource(Handle<SHRenderGraph> resourceOrigin, std::string resourceName) noexcept
{ {
// resource to link // resource to link
@ -479,7 +497,7 @@ namespace SHADE
// get target node // get target node
auto targetNode = nodes.begin() + nodeIndexing.at(nodeToAddAfter); auto targetNode = nodes.begin() + nodeIndexing.at(nodeToAddAfter);
auto node = nodes.insert(targetNode, renderGraphStorage->resourceHub->Create<SHRenderGraphNode>(nodeName, renderGraphStorage, std::move(descInitParams), std::vector<Handle<SHRenderGraphNode>>())); auto node = nodes.insert(targetNode, renderGraphStorage->resourceHub->Create<SHRenderGraphNode>(nodeName, renderGraphStorage, std::move(descInitParams), std::vector<Handle<SHRenderGraphNode>>(), true));
ReindexNodes (); ReindexNodes ();
return *node; return *node;
@ -583,6 +601,10 @@ namespace SHADE
for (auto& node : nodes) for (auto& node : nodes)
{ {
// if node is dynamic check for active flag
if ((node->isDynamic) ? !node->dynamicIsActive : false)
continue;
if (node->renderpass) if (node->renderpass)
{ {
// bind static global data // bind static global data

View File

@ -112,6 +112,7 @@ namespace SHADE
); );
void RemoveResource (std::string resourceName) noexcept; void RemoveResource (std::string resourceName) noexcept;
void RemoveNode (std::string nodeName) noexcept;
void LinkNonOwningResource void LinkNonOwningResource
( (

View File

@ -292,7 +292,7 @@ namespace SHADE
*/ */
/***************************************************************************/ /***************************************************************************/
SHRenderGraphNode::SHRenderGraphNode(std::string nodeName, Handle<SHRenderGraphStorage> renderGraphStorage, std::vector<SHAttachmentDescInitParams> attDescInitParams, std::vector<Handle<SHRenderGraphNode>> predecessors) noexcept SHRenderGraphNode::SHRenderGraphNode(std::string nodeName, Handle<SHRenderGraphStorage> renderGraphStorage, std::vector<SHAttachmentDescInitParams> attDescInitParams, std::vector<Handle<SHRenderGraphNode>> predecessors, bool inIsDynamic) noexcept
: graphStorage{ renderGraphStorage} : graphStorage{ renderGraphStorage}
, renderpass{} , renderpass{}
, framebuffers{} , framebuffers{}
@ -305,6 +305,8 @@ namespace SHADE
, configured{ false } , configured{ false }
, nodeComputes{} , nodeComputes{}
, name { std::move(nodeName) } , name { std::move(nodeName) }
, dynamicIsActive {true} // default set to true
, isDynamic{inIsDynamic}
{ {
// pipeline library initialization // pipeline library initialization
pipelineLibrary.Init(graphStorage->logicalDevice); pipelineLibrary.Init(graphStorage->logicalDevice);
@ -368,6 +370,8 @@ namespace SHADE
, nodeComputes{ std::move(rhs.nodeComputes) } , nodeComputes{ std::move(rhs.nodeComputes) }
, name { std::move(rhs.name) } , name { std::move(rhs.name) }
, ISelfHandle<SHRenderGraphNode>{std::move(rhs)} , ISelfHandle<SHRenderGraphNode>{std::move(rhs)}
, dynamicIsActive {rhs.dynamicIsActive}
, isDynamic {rhs.isDynamic}
{ {
rhs.renderpass = {}; rhs.renderpass = {};
@ -393,12 +397,30 @@ namespace SHADE
spDeps = std::move(rhs.spDeps); spDeps = std::move(rhs.spDeps);
nodeComputes = std::move(rhs.nodeComputes); nodeComputes = std::move(rhs.nodeComputes);
name = std::move(rhs.name); name = std::move(rhs.name);
dynamicIsActive = rhs.dynamicIsActive;
isDynamic = rhs.isDynamic;
rhs.renderpass = {}; rhs.renderpass = {};
return *this; return *this;
} }
SHRenderGraphNode::~SHRenderGraphNode(void) noexcept
{
if (renderpass)
renderpass.Free();
for (auto& framebuffer : framebuffers)
framebuffer.Free();
for (auto& subpass : subpasses)
subpass.Free();
// Too tired to test, its nearing end of milestone 3....
//for (auto& nc : nodeComputes)
// nc.Free();
}
/***************************************************************************/ /***************************************************************************/
/*! /*!
@ -798,12 +820,18 @@ namespace SHADE
/***************************************************************************/ /***************************************************************************/
void SHRenderGraphNode::RuntimeStandaloneRegenerate(void) noexcept void SHRenderGraphNode::RuntimeStandaloneRegenerate(void) noexcept
{ {
AddDummySubpassIfNeeded();
StandaloneConfigureAttDesc(false); StandaloneConfigureAttDesc(false);
ConfigureSubpasses(); ConfigureSubpasses();
CreateRenderpass(); CreateRenderpass();
CreateFramebuffer(); CreateFramebuffer();
} }
void SHRenderGraphNode::SetDynamicActive(bool active) noexcept
{
dynamicIsActive = active;
}
/***************************************************************************/ /***************************************************************************/
/*! /*!
@ -849,4 +877,9 @@ namespace SHADE
return {}; return {};
} }
bool SHRenderGraphNode::GetDynamicActive(void) const noexcept
{
return dynamicIsActive;
}
} }

View File

@ -80,6 +80,13 @@ namespace SHADE
//! Whether or not the node has been configured already or not //! Whether or not the node has been configured already or not
bool configured; bool configured;
//! Whether or not the rendergraph should be executed. Should ONLY be used for dynamic
//! nodes that are independent from other nodes.
bool dynamicIsActive;
//! True if the function is dynamic
bool isDynamic;
//! Manages batching for this RenderPass //! Manages batching for this RenderPass
SHBatcher batcher; SHBatcher batcher;
@ -101,9 +108,10 @@ namespace SHADE
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* CTORS AND DTORS */ /* CTORS AND DTORS */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
SHRenderGraphNode(std::string nodeName, Handle<SHRenderGraphStorage> renderGraphStorage, std::vector<SHAttachmentDescInitParams> attDescInitParams, std::vector<Handle<SHRenderGraphNode>> predecessors) noexcept; SHRenderGraphNode(std::string nodeName, Handle<SHRenderGraphStorage> renderGraphStorage, std::vector<SHAttachmentDescInitParams> attDescInitParams, std::vector<Handle<SHRenderGraphNode>> predecessors, bool inIsDynamic = false) noexcept;
SHRenderGraphNode(SHRenderGraphNode&& rhs) noexcept; SHRenderGraphNode(SHRenderGraphNode&& rhs) noexcept;
SHRenderGraphNode& operator= (SHRenderGraphNode&& rhs) noexcept; SHRenderGraphNode& operator= (SHRenderGraphNode&& rhs) noexcept;
~SHRenderGraphNode (void) noexcept;
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* PUBLIC MEMBER FUNCTIONS */ /* PUBLIC MEMBER FUNCTIONS */
@ -123,11 +131,15 @@ namespace SHADE
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* SETTERS AND GETTERS */ /* SETTERS AND GETTERS */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
void SetDynamicActive(bool active) noexcept;
Handle<SHVkRenderpass> GetRenderpass(void) const noexcept; Handle<SHVkRenderpass> GetRenderpass(void) const noexcept;
Handle<SHSubpass> GetSubpass(std::string_view subpassName) const noexcept; Handle<SHSubpass> GetSubpass(std::string_view subpassName) const noexcept;
Handle<SHRenderGraphResource> GetResource (uint32_t resourceIndex) const noexcept; Handle<SHRenderGraphResource> GetResource (uint32_t resourceIndex) const noexcept;
std::vector<Handle<SHRenderGraphResource>> const& GetResources (void) const noexcept; std::vector<Handle<SHRenderGraphResource>> const& GetResources (void) const noexcept;
Handle<SHRenderGraphNodeCompute> GetNodeCompute (std::string nodeComputeName) const noexcept; Handle<SHRenderGraphNodeCompute> GetNodeCompute (std::string nodeComputeName) const noexcept;
bool GetDynamicActive (void) const noexcept;
friend class SHRenderGraph; friend class SHRenderGraph;
}; };

View File

@ -77,9 +77,17 @@ namespace SHADE
, name { rhs.name } , name { rhs.name }
, viewport {rhs.viewport} , viewport {rhs.viewport}
, renderer {rhs.renderer} , renderer {rhs.renderer}
, companionSubpass {rhs.companionSubpass} , companionSubpasses {std::move (rhs.companionSubpasses)}
, dummyPipelineLayout{rhs.dummyPipelineLayout} , dummyPipelineLayout{rhs.dummyPipelineLayout}
{ {
superBatch = std::move(rhs.superBatch);
rhs.superBatch = {};
inputDescriptorLayout = std::move(rhs.inputDescriptorLayout);
rhs.inputDescriptorLayout = {};
dummyPipelineLayout = std::move(rhs.dummyPipelineLayout);
rhs.dummyPipelineLayout = {};
} }
@ -101,7 +109,6 @@ namespace SHADE
subpassIndex = std::move(rhs.subpassIndex); subpassIndex = std::move(rhs.subpassIndex);
parentNode = std::move(rhs.parentNode); parentNode = std::move(rhs.parentNode);
superBatch = std::move(rhs.superBatch);
colorReferences = std::move(rhs.colorReferences); colorReferences = std::move(rhs.colorReferences);
depthReferences = std::move(rhs.depthReferences); depthReferences = std::move(rhs.depthReferences);
inputReferences = std::move(rhs.inputReferences); inputReferences = std::move(rhs.inputReferences);
@ -115,13 +122,39 @@ namespace SHADE
name = std::move(rhs.name); name = std::move(rhs.name);
renderer = rhs.renderer; renderer = rhs.renderer;
viewport = rhs.viewport; viewport = rhs.viewport;
companionSubpass = rhs.companionSubpass; companionSubpasses = rhs.companionSubpasses;
dummyPipelineLayout = rhs.dummyPipelineLayout; dummyPipelineLayout = rhs.dummyPipelineLayout;
superBatch = std::move(rhs.superBatch);
rhs.superBatch = {};
inputDescriptorLayout = std::move(rhs.inputDescriptorLayout);
rhs.inputDescriptorLayout = {};
dummyPipelineLayout = std::move(rhs.dummyPipelineLayout);
rhs.dummyPipelineLayout = {};
return *this; return *this;
} }
SHSubpass::~SHSubpass(void) noexcept
{
graphStorage->logicalDevice->WaitIdle();
for (auto& set : inputImageDescriptorSets)
set.Free();
if (inputDescriptorLayout)
inputDescriptorLayout.Free();
if (dummyPipelineLayout)
dummyPipelineLayout.Free();
// not working
//if (superBatch)
// superBatch.Free();
}
/***************************************************************************/ /***************************************************************************/
/*! /*!
@ -237,17 +270,19 @@ namespace SHADE
BindInputDescriptorSets (commandBuffer, descMappings.at(SHPredefinedDescriptorTypes::RENDER_GRAPH_RESOURCE), frameIndex); BindInputDescriptorSets (commandBuffer, descMappings.at(SHPredefinedDescriptorTypes::RENDER_GRAPH_RESOURCE), frameIndex);
// If companion subpass is not a valid handle, render super batch normally if (companionSubpasses.empty())
if (!companionSubpass.companion)
{ {
// Draw all the batches // Draw all the batches
superBatch->Draw(commandBuffer, frameIndex); superBatch->Draw(commandBuffer, frameIndex);
} }
else else
{
for (auto& companion : companionSubpasses)
{ {
// if not bind pipeline for companion and and execute draw command // if not bind pipeline for companion and and execute draw command
commandBuffer->BindPipeline(companionSubpass.pipeline); commandBuffer->BindPipeline(companion.pipeline);
companionSubpass.companion->superBatch->Draw(commandBuffer, frameIndex, false); companion.subpass->superBatch->Draw(commandBuffer, frameIndex, false);
}
} }
} }
@ -493,10 +528,11 @@ namespace SHADE
subpassIndex = index; subpassIndex = index;
} }
void SHSubpass::SetCompanionSubpass(Handle<SHSubpass> companion, Handle<SHVkPipeline> pipeline) noexcept void SHSubpass::AddCompanionSubpass(Handle<SHSubpass> companion, Handle<SHVkPipeline> pipeline) noexcept
{ {
companionSubpass.companion = companion; companionSubpasses.push_back(CompanionSubpass{companion, pipeline});
companionSubpass.pipeline = pipeline; //companionSubpass.companion = companion;
//companionSubpass.pipeline = pipeline;
} }
/***************************************************************************/ /***************************************************************************/

View File

@ -33,7 +33,7 @@ namespace SHADE
struct CompanionSubpass struct CompanionSubpass
{ {
// subpass whose data will be borrowed to draw // subpass whose data will be borrowed to draw
Handle<SHSubpass> companion; Handle<SHSubpass> subpass;
// Pipeline that will be used for all the draw calls from all batches of the companion subpass // Pipeline that will be used for all the draw calls from all batches of the companion subpass
Handle<SHVkPipeline> pipeline; Handle<SHVkPipeline> pipeline;
@ -114,7 +114,8 @@ namespace SHADE
//! Optional component to a companion subpass. If the subpass handle of this object //! Optional component to a companion subpass. If the subpass handle of this object
//! is valid, the subpass will be drawn using this companion's data. //! is valid, the subpass will be drawn using this companion's data.
CompanionSubpass companionSubpass; //CompanionSubpass companionSubpass;
std::vector<CompanionSubpass> companionSubpasses;
private: private:
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
@ -129,6 +130,7 @@ namespace SHADE
SHSubpass(const std::string& name, Handle<SHViewport> inViewport, Handle<SHRenderer> inRenderer, Handle<SHRenderGraphStorage> renderGraphStorage, Handle<SHRenderGraphNode> const& parent, uint32_t index, std::unordered_map<uint64_t, uint32_t> const* mapping) noexcept; SHSubpass(const std::string& name, Handle<SHViewport> inViewport, Handle<SHRenderer> inRenderer, Handle<SHRenderGraphStorage> renderGraphStorage, Handle<SHRenderGraphNode> const& parent, uint32_t index, std::unordered_map<uint64_t, uint32_t> const* mapping) noexcept;
SHSubpass(SHSubpass&& rhs) noexcept; SHSubpass(SHSubpass&& rhs) noexcept;
SHSubpass& operator=(SHSubpass&& rhs) noexcept; SHSubpass& operator=(SHSubpass&& rhs) noexcept;
~SHSubpass(void) noexcept;
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* PUBLIC MEMBER FUNCTIONS */ /* PUBLIC MEMBER FUNCTIONS */
@ -165,7 +167,7 @@ namespace SHADE
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* PUBLIC SETTERS AND GETTERS */ /* PUBLIC SETTERS AND GETTERS */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
void SetCompanionSubpass (Handle<SHSubpass> companion, Handle<SHVkPipeline> pipeline) noexcept; void AddCompanionSubpass (Handle<SHSubpass> companion, Handle<SHVkPipeline> pipeline) noexcept;
Handle<SHRenderGraphNode> GetParentNode(void) const noexcept; Handle<SHRenderGraphNode> GetParentNode(void) const noexcept;
SHSubPassIndex GetIndex() const noexcept; SHSubPassIndex GetIndex() const noexcept;

View File

@ -34,6 +34,7 @@ namespace SHADE
, flags { 0 } , flags { 0 }
, drag { 0.01f } , drag { 0.01f }
, angularDrag { 0.1f } , angularDrag { 0.1f }
, gravityScale{ 1.0f }
, rigidBody { nullptr } , rigidBody { nullptr }
{ {
// Default flags // Default flags