Implemented Animation Clip asset and animation controller #410
|
@ -1,4 +1,4 @@
|
|||
Start in Fullscreen: false
|
||||
Starting Scene ID: 86098106
|
||||
Starting Scene ID: 91478134
|
||||
Window Size: {x: 1920, y: 1080}
|
||||
Window Title: SHADE Engine
|
|
@ -0,0 +1,3 @@
|
|||
Name: Master
|
||||
ID: 187131295
|
||||
Type: 11
|
|
@ -0,0 +1,3 @@
|
|||
Name: Master.strings
|
||||
ID: 184993030
|
||||
Type: 11
|
|
@ -0,0 +1,3 @@
|
|||
Name: Music
|
||||
ID: 187337426
|
||||
Type: 11
|
|
@ -0,0 +1,3 @@
|
|||
Name: SFX
|
||||
ID: 200039123
|
||||
Type: 11
|
|
@ -0,0 +1,3 @@
|
|||
Name: UI
|
||||
ID: 185075145
|
||||
Type: 11
|
|
@ -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}
|
|
@ -0,0 +1,3 @@
|
|||
Name: AnimatedHomeowner
|
||||
ID: 121518381
|
||||
Type: 7
|
|
@ -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}
|
|
@ -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.
|
@ -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
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
|
@ -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: ~
|
|
@ -0,0 +1,3 @@
|
|||
Name: anim
|
||||
ID: 91478134
|
||||
Type: 5
|
|
@ -20,10 +20,11 @@ layout(location = 0) out struct
|
|||
vec2 uv; // location = 1
|
||||
vec4 normal; // location = 2
|
||||
vec4 worldPos; // location = 3
|
||||
vec3 worldNormal; // location = 4
|
||||
} Out;
|
||||
|
||||
// material stuff
|
||||
layout(location = 4) out struct
|
||||
layout(location = 5) out struct
|
||||
{
|
||||
int materialIndex;
|
||||
uint eid;
|
||||
|
@ -61,11 +62,13 @@ void main()
|
|||
// uvs for texturing in fragment shader
|
||||
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
|
||||
Out.normal.rgb = transposeInv * aNormal.rgb;
|
||||
Out.normal.rgb = mvTransInv * aNormal.rgb;
|
||||
Out.normal.rgb = normalize (Out.normal.rgb);
|
||||
Out.worldNormal = normalize (modelTransInv * aNormal);
|
||||
|
||||
// Compute bone matrix
|
||||
mat4 boneMatrix = BoneMatrices.data[firstBoneIndex + aBoneIndices[0]] * aBoneWeights[0];
|
||||
|
|
Binary file not shown.
|
@ -2,6 +2,7 @@
|
|||
|
||||
struct DirectionalLightStruct
|
||||
{
|
||||
vec4 directionWorld;
|
||||
vec3 direction;
|
||||
uint isActive;
|
||||
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 = 1, rgba32f) uniform image2D normals;
|
||||
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 = 5, rgba8) uniform image2D positionWorldSpace;
|
||||
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);
|
||||
}
|
||||
|
||||
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
|
||||
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)
|
||||
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)
|
||||
{
|
||||
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 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)
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
else
|
||||
return 0.3f;
|
||||
// return step (fragPosLightPOV.z, );
|
||||
|
||||
return 1.0f;
|
||||
|
||||
}
|
||||
|
||||
void main()
|
||||
|
@ -104,8 +116,12 @@ void main()
|
|||
// normal of fragment
|
||||
vec3 normalView = imageLoad(normals, globalThread).rgb;
|
||||
|
||||
uvec4 lightLayerAndNormal = imageLoad (lightLayerData, globalThread);
|
||||
|
||||
// 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);
|
||||
|
||||
|
@ -138,7 +154,7 @@ void main()
|
|||
if ((DirLightData.dLightData[i].shadowData & uint(1)) == 1)
|
||||
{
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Binary file not shown.
|
@ -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.
|
@ -0,0 +1,3 @@
|
|||
Name: ShadowMapBlur_CS
|
||||
ID: 38004013
|
||||
Type: 2
|
|
@ -7,6 +7,12 @@ layout(location = 0) out vec4 shadowMap;
|
|||
|
||||
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 (gl_FragCoord.z, gl_FragCoord.z * gl_FragCoord.z, 0.0f, 1.0f);
|
||||
shadowMap = vec4 (gl_FragCoord.z, moment2, 0.0f, 1.0f);
|
||||
}
|
Binary file not shown.
|
@ -32,10 +32,11 @@ layout(location = 0) in struct
|
|||
vec2 uv; // location = 1
|
||||
vec4 normal; // location = 2
|
||||
vec4 worldPos; // location = 3
|
||||
vec3 worldNormal; // location = 4
|
||||
} In;
|
||||
|
||||
// material stuff
|
||||
layout(location = 4) flat in struct
|
||||
layout(location = 5) flat in struct
|
||||
{
|
||||
int materialIndex;
|
||||
uint eid;
|
||||
|
@ -57,7 +58,7 @@ layout (std430, set = 2, binding = 0) buffer MaterialProperties // For mater
|
|||
|
||||
layout(location = 0) out vec4 position;
|
||||
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 = 4) out vec4 albedo;
|
||||
layout(location = 5) out vec4 worldSpacePosition;
|
||||
|
@ -72,11 +73,11 @@ void main()
|
|||
{
|
||||
position = In.vertPos;
|
||||
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;
|
||||
|
||||
outEntityID = In2.eid;
|
||||
lightLayerIndices = In2.lightLayerIndex;
|
||||
lightLayerIndices = uvec4 (In2.lightLayerIndex, 0, 0, 1);
|
||||
|
||||
// float vpHeight = float (In2.screenSpacePos.y) - MatProp.data[In2.materialIndex].highlightPosition;
|
||||
// bring the frame of reference to the object's screen space pos
|
||||
|
@ -101,4 +102,6 @@ void main()
|
|||
}
|
||||
else
|
||||
objectVFX = vec4(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
|
||||
objectVFX.a = 1.0f;
|
||||
}
|
Binary file not shown.
|
@ -17,6 +17,7 @@ layout(location = 0) out struct
|
|||
vec2 uv; // location = 1
|
||||
vec4 normal; // location = 2
|
||||
vec4 worldPos; // location = 3
|
||||
vec3 worldNormal; // location = 4
|
||||
|
||||
} Out;
|
||||
|
||||
|
@ -36,7 +37,7 @@ struct GenericData
|
|||
};
|
||||
|
||||
// material stuff
|
||||
layout(location = 4) out struct
|
||||
layout(location = 5) out struct
|
||||
{
|
||||
int materialIndex;
|
||||
uint eid;
|
||||
|
@ -76,11 +77,13 @@ void main()
|
|||
// uvs for texturing in fragment shader
|
||||
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
|
||||
Out.normal.rgb = transposeInv * aNormal.rgb;
|
||||
Out.normal.rgb = mvTransInv * aNormal.rgb;
|
||||
Out.normal.rgb = normalize (Out.normal.rgb);
|
||||
Out.worldNormal = normalize (modelTransInv * aNormal);
|
||||
|
||||
// Get center of object in world position
|
||||
vec4 worldPos = vec4(worldTransform[3][0], worldTransform[3][1], worldTransform[3][2], 1.0f);
|
||||
|
|
Binary file not shown.
|
@ -17,10 +17,11 @@ layout(location = 0) in struct
|
|||
vec2 uv; // location = 1
|
||||
vec4 normal; // location = 2
|
||||
vec4 worldPos; // location = 3
|
||||
vec3 worldNormal; // location = 4
|
||||
} In;
|
||||
|
||||
// material stuff
|
||||
layout(location = 4) flat in struct
|
||||
layout(location = 5) flat in struct
|
||||
{
|
||||
int materialIndex;
|
||||
uint eid;
|
||||
|
@ -35,7 +36,7 @@ layout (std430, set = 2, binding = 0) buffer MaterialProperties // For mater
|
|||
|
||||
layout(location = 0) out vec4 position;
|
||||
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 = 4) out vec4 albedo;
|
||||
layout(location = 5) out vec4 worldSpacePosition;
|
||||
|
@ -48,5 +49,5 @@ void main()
|
|||
worldSpacePosition = In.worldPos;
|
||||
|
||||
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.
|
@ -20,11 +20,12 @@ layout(location = 0) out struct
|
|||
vec2 uv; // location = 1
|
||||
vec4 normal; // location = 2
|
||||
vec4 worldPos; // location = 3
|
||||
vec3 worldNormal; // location = 4
|
||||
|
||||
} Out;
|
||||
|
||||
// material stuff
|
||||
layout(location = 4) out struct
|
||||
layout(location = 5) out struct
|
||||
{
|
||||
int materialIndex;
|
||||
uint eid;
|
||||
|
@ -57,11 +58,13 @@ void main()
|
|||
// uvs for texturing in fragment shader
|
||||
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
|
||||
Out.normal.rgb = transposeInv * aNormal.rgb;
|
||||
Out.normal.rgb = mvTransInv * aNormal.rgb;
|
||||
Out.normal.rgb = normalize (Out.normal.rgb);
|
||||
Out.worldNormal = normalize (modelTransInv * aNormal);
|
||||
|
||||
// clip space for rendering
|
||||
gl_Position = cameraData.vpMat * worldTransform * vec4 (aVertexPos, 1.0f);
|
||||
|
|
Binary file not shown.
|
@ -62,7 +62,6 @@ if %_e%==3 (goto :done) else (goto :ModelCompiler)
|
|||
echo -----------------------ModelCompiler----------------------------
|
||||
rmdir "Dependencies/ModelCompiler" /S /Q
|
||||
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)
|
||||
|
||||
@REM :ktx
|
||||
|
|
|
@ -55,14 +55,11 @@ namespace SHADE
|
|||
// Set accordingly
|
||||
currClip = clip;
|
||||
currPlaybackTime = 0.0f;
|
||||
channelMaps.clear();
|
||||
auto RAW_ANIM = clip->GetRawAnimation();
|
||||
|
||||
// Set up if valid
|
||||
if (currClip && RAW_ANIM)
|
||||
{
|
||||
// Create channel maps
|
||||
channelMaps.emplace(RAW_ANIM, createChannelMap(RAW_ANIM));
|
||||
// Calculate secs for the clip
|
||||
secsPerTick = 1.0f / RAW_ANIM->GetTicksPerSecond();
|
||||
|
||||
|
@ -202,12 +199,6 @@ namespace SHADE
|
|||
// Store
|
||||
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);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* 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 */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
@ -283,31 +261,25 @@ namespace SHADE
|
|||
}
|
||||
void SHAnimatorComponent::updatePoseWithClip(Handle<SHAnimationClip> clip, float poseTime)
|
||||
{
|
||||
// Get closest frame index
|
||||
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);
|
||||
updatePoseWithClip(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
|
||||
const std::string& BONE_NAME = rig->GetName(node);
|
||||
SHMatrix transformMatrix = node->TransformMatrix;
|
||||
|
||||
if (channelMaps.contains(rawAnimData))
|
||||
const int BONE_IDX = rig->GetNodeIndex(node);
|
||||
const auto& CHANNELS = rawAnimData->GetChannels();
|
||||
if (BONE_IDX < CHANNELS.size())
|
||||
{
|
||||
auto channelMap = channelMaps[rawAnimData];
|
||||
if (channelMap.contains(BONE_NAME))
|
||||
{
|
||||
const auto CHANNEL = channelMap[BONE_NAME];
|
||||
const auto& CHANNEL = CHANNELS[BONE_IDX];
|
||||
transformMatrix = SHMatrix::Transform
|
||||
(
|
||||
getInterpolatedValue(CHANNEL->PositionKeyFrames, closestFrameIndex, poseTime),
|
||||
getInterpolatedValue(CHANNEL->RotationKeyFrames, closestFrameIndex, poseTime),
|
||||
getInterpolatedValue(CHANNEL->ScaleKeyFrames, closestFrameIndex, poseTime)
|
||||
getInterpolatedValue(CHANNEL.PositionKeyFrames, poseTime),
|
||||
getInterpolatedValue(CHANNEL.RotationKeyFrames, poseTime),
|
||||
getInterpolatedValue(CHANNEL.ScaleKeyFrames, poseTime)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Apply parent's transformation
|
||||
transformMatrix = transformMatrix * parentMatrix;
|
||||
|
@ -323,7 +295,7 @@ namespace SHADE
|
|||
// Apply pose to children
|
||||
for (auto& child : node->Children)
|
||||
{
|
||||
updatePoseWithClip(closestFrameIndex, poseTime, rawAnimData, child, transformMatrix);
|
||||
updatePoseWithClip(poseTime, rawAnimData, node, transformMatrix);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -190,22 +190,17 @@ namespace SHADE
|
|||
float secsPerTick = 0.0f;
|
||||
// Buffer
|
||||
std::vector<SHMatrix> boneMatrices;
|
||||
// Caches
|
||||
std::unordered_map<Handle<SHRawAnimation>, ChannelMap> channelMaps;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Helper Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
// Loading
|
||||
ChannelMap createChannelMap(Handle<SHRawAnimation> rawAnimData);
|
||||
// Update
|
||||
void updateAnimController(float dt);
|
||||
void updateManualClipState(float dt);
|
||||
void updateCurrentAnimatorState(Handle<SHAnimationClip> clip, float playbackTime);
|
||||
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>
|
||||
T getInterpolatedValue(const std::vector<SHAnimationKeyFrame<T>>& keyframes, int closestFrameIndex, float poseTime);
|
||||
T getInterpolatedValue(const std::vector<SHAnimationKeyFrame<T>>& keyframes, float poseTime);
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* RTTR */
|
||||
|
|
|
@ -44,7 +44,7 @@ namespace SHADE
|
|||
/* Helper Functions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
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
|
||||
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;
|
||||
|
||||
if (KEYFRAME.FrameIndex <= closestFrameIndex)
|
||||
if (KEYFRAME.TimeStamp <= poseTime)
|
||||
{
|
||||
firstKeyFrame = iter;
|
||||
}
|
||||
else // KEYFRAME.FrameIndex > closestFrameIndex
|
||||
else // KEYFRAME.FrameIndex > poseTime
|
||||
{
|
||||
nextKeyFrame = iter;
|
||||
break;
|
||||
|
@ -84,8 +84,8 @@ namespace SHADE
|
|||
}
|
||||
|
||||
// Get interpolated vector
|
||||
const float PREV_FRAME_TIME = firstKeyFrame->FrameIndex * secsPerTick;
|
||||
const float NEXT_FRAME_TIME = nextKeyFrame->FrameIndex * secsPerTick;
|
||||
const float PREV_FRAME_TIME = firstKeyFrame->TimeStamp;
|
||||
const float NEXT_FRAME_TIME = nextKeyFrame->TimeStamp;
|
||||
const float NORMALISED_TIME = (poseTime - PREV_FRAME_TIME) / (NEXT_FRAME_TIME - PREV_FRAME_TIME);
|
||||
|
||||
if constexpr (std::is_same_v<T, SHQuaternion>)
|
||||
|
|
|
@ -20,16 +20,14 @@ namespace SHADE
|
|||
/* Constructors */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
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
|
||||
int maxFrames = 0;
|
||||
totalTime = 0.0f;
|
||||
for (const auto& channel : asset.nodeChannels)
|
||||
{
|
||||
// Create a channel
|
||||
Channel newChannel;
|
||||
newChannel.Name = std::string(channel.name);
|
||||
newChannel.PositionKeyFrames.reserve(channel.positionKeys.size());
|
||||
newChannel.RotationKeyFrames.reserve(channel.rotationKeys.size());
|
||||
newChannel.ScaleKeyFrames.reserve(channel.scaleKeys.size());
|
||||
|
@ -37,21 +35,30 @@ namespace SHADE
|
|||
// Populate Keyframes
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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() });
|
||||
|
||||
// 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
|
||||
channels.emplace_back(std::move(newChannel));
|
||||
|
||||
// Compute fps
|
||||
ticksPerSecond = static_cast<int>(maxFrames / totalTime);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ namespace SHADE
|
|||
template<typename T>
|
||||
struct SHAnimationKeyFrame
|
||||
{
|
||||
int FrameIndex;
|
||||
float TimeStamp;
|
||||
T Data;
|
||||
};
|
||||
|
||||
|
@ -45,7 +45,6 @@ namespace SHADE
|
|||
/// </summary>
|
||||
struct Channel
|
||||
{
|
||||
std::string Name;
|
||||
std::vector<SHAnimationKeyFrame<SHVec3>> PositionKeyFrames;
|
||||
std::vector<SHAnimationKeyFrame<SHQuaternion>> RotationKeyFrames;
|
||||
std::vector<SHAnimationKeyFrame<SHVec3>> ScaleKeyFrames;
|
||||
|
|
|
@ -120,8 +120,10 @@ namespace SHADE
|
|||
|
||||
// Fill the node with data
|
||||
const auto& NODE_DATA = asset.nodeDataCollection.at(sourceNode->idRef);
|
||||
newNode->OffsetMatrix = SHMatrix::Transpose(NODE_DATA.offset);
|
||||
newNode->TransformMatrix = SHMatrix::Transpose(NODE_DATA.transform);
|
||||
//newNode->OffsetMatrix = SHMatrix::Transpose(NODE_DATA.inverseBindMatrix);
|
||||
//newNode->TransformMatrix = SHMatrix::Transpose(NODE_DATA.transform);
|
||||
newNode->OffsetMatrix = NODE_DATA.inverseBindMatrix;
|
||||
newNode->TransformMatrix = NODE_DATA.transform;
|
||||
|
||||
// Populate maps
|
||||
if (!NODE_DATA.name.empty())
|
||||
|
|
|
@ -20,69 +20,61 @@
|
|||
|
||||
namespace SHADE
|
||||
{
|
||||
enum class SHAnimationBehaviour : uint8_t
|
||||
enum class AnimationInterpolation : uint8_t
|
||||
{
|
||||
DEFAULT = 0x0,
|
||||
CONSTANT = 0x1,
|
||||
LINEAR = 0x2,
|
||||
REPEAT = 0x3
|
||||
DEFAULT = 0x1,
|
||||
LINEAR = 0x1,
|
||||
STEP = 0x2,
|
||||
CUBICSPLINE = 0x3
|
||||
};
|
||||
|
||||
// Base
|
||||
struct KeyBase
|
||||
{
|
||||
float time;
|
||||
};
|
||||
|
||||
// Smallest data containers
|
||||
struct PositionKey
|
||||
struct PositionKey :KeyBase
|
||||
{
|
||||
float time;
|
||||
SHVec3 value;
|
||||
};
|
||||
|
||||
struct RotationKey
|
||||
struct RotationKey : KeyBase
|
||||
{
|
||||
float time;
|
||||
SHVec4 value;
|
||||
};
|
||||
|
||||
struct ScaleKey
|
||||
struct ScaleKey :KeyBase
|
||||
{
|
||||
float time;
|
||||
SHVec3 value;
|
||||
};
|
||||
|
||||
// Headers for read/write
|
||||
struct SHAnimNodeInfo
|
||||
{
|
||||
uint32_t charCount;
|
||||
uint32_t posKeyCount;
|
||||
uint32_t rotKeyCount;
|
||||
uint32_t scaKeyCount;
|
||||
};
|
||||
|
||||
struct SHAnimDataHeader
|
||||
{
|
||||
uint32_t charCount;
|
||||
uint32_t animNodeCount;
|
||||
std::vector<SHAnimNodeInfo> nodeHeaders;
|
||||
uint32_t frameCount;
|
||||
};
|
||||
|
||||
// Main data containers
|
||||
struct SHAnimData
|
||||
struct SHAnimNode
|
||||
{
|
||||
std::string name;
|
||||
SHAnimationBehaviour pre;
|
||||
SHAnimationBehaviour post;
|
||||
|
||||
std::vector<PositionKey> positionKeys;
|
||||
std::vector<RotationKey> rotationKeys;
|
||||
std::vector<ScaleKey> scaleKeys;
|
||||
AnimationInterpolation interpolation;
|
||||
|
||||
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;
|
||||
|
||||
double duration;
|
||||
double ticksPerSecond;
|
||||
double duration{};
|
||||
double ticksPerSecond{};
|
||||
|
||||
std::vector<SHAnimData> nodeChannels;
|
||||
std::vector<SHAnimNode> nodeChannels{};
|
||||
};
|
||||
}
|
|
@ -19,45 +19,28 @@
|
|||
|
||||
namespace SHADE
|
||||
{
|
||||
constexpr int BONE_INDEX_ALIGHTMENT = 4;
|
||||
|
||||
struct SHMeshDataHeader
|
||||
{
|
||||
uint32_t vertexCount;
|
||||
uint32_t indexCount;
|
||||
uint32_t charCount;
|
||||
uint32_t boneCount;
|
||||
};
|
||||
|
||||
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;
|
||||
bool hasWeights;
|
||||
};
|
||||
|
||||
struct SH_API SHMeshAsset : SHAssetData
|
||||
{
|
||||
std::string name;
|
||||
std::vector<SHVec3> VertexPositions;
|
||||
std::vector<SHVec3> VertexTangents;
|
||||
std::vector<SHVec3> VertexNormals;
|
||||
std::vector<SHVec2> VertexTexCoords;
|
||||
std::vector<uint32_t> Indices;
|
||||
std::vector<SHVec4U> VertexBoneIndices;
|
||||
std::vector<SHVec4> VertexBoneWeights;
|
||||
std::vector<SHVec3> VertexPositions{};
|
||||
std::vector<SHVec3> VertexTangents{};
|
||||
std::vector<SHVec3> VertexNormals{};
|
||||
std::vector<SHVec2> VertexTexCoords{};
|
||||
std::vector<uint32_t> Indices{};
|
||||
|
||||
//Variables
|
||||
std::vector<SHVec4> VertexBoneWeights{};
|
||||
std::vector<SHVec4U> VertexBoneIndices{};
|
||||
|
||||
uint32_t BoneCount;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
#include "SHpch.h"
|
||||
#include "SHRigAsset.h"
|
||||
|
||||
#include <queue>
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
SHRigAsset::~SHRigAsset()
|
||||
|
|
|
@ -17,17 +17,30 @@
|
|||
|
||||
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
|
||||
{
|
||||
uint32_t nodeCount;
|
||||
std::vector<uint32_t> charCounts;
|
||||
uint32_t nodeCount{};
|
||||
uint32_t startNode{};
|
||||
std::vector<uint32_t> charCounts{};
|
||||
};
|
||||
|
||||
struct SHRigNodeData
|
||||
{
|
||||
std::string name;
|
||||
SHMatrix transform;
|
||||
SHMatrix offset;
|
||||
SHMatrix inverseBindMatrix;
|
||||
};
|
||||
|
||||
struct SHRigNodeAsset
|
||||
|
@ -39,9 +52,8 @@ namespace SHADE
|
|||
struct SH_API SHRigAsset : SHAssetData
|
||||
{
|
||||
~SHRigAsset();
|
||||
|
||||
SHRigDataHeader header;
|
||||
std::vector<SHRigNodeData> nodeDataCollection;
|
||||
std::vector<SHRigNodeData> nodeDataCollection{};
|
||||
SHRigNodeAsset* root;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
}
|
|
@ -17,6 +17,52 @@
|
|||
|
||||
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)
|
||||
{
|
||||
file.read(
|
||||
|
@ -36,29 +82,12 @@ namespace SHADE
|
|||
if (asset.header.animCount > 0)
|
||||
{
|
||||
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(
|
||||
reinterpret_cast<char*>(&animHeader.charCount),
|
||||
sizeof(uint32_t)
|
||||
reinterpret_cast<char*>(&animHeader),
|
||||
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);
|
||||
ReadRigData(file, asset.rig.header, asset.rig.nodeDataCollection);
|
||||
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(
|
||||
data.name.data(),
|
||||
info.charCount
|
||||
reinterpret_cast<char*>(&data.interpolation),
|
||||
1
|
||||
);
|
||||
|
||||
file.read(
|
||||
reinterpret_cast<char*>(&data.pre),
|
||||
sizeof(SHAnimationBehaviour)
|
||||
);
|
||||
|
||||
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);
|
||||
data.positionKeys.resize(frameCount);
|
||||
data.rotationKeys.resize(frameCount);
|
||||
data.scaleKeys.resize(frameCount);
|
||||
|
||||
file.read(
|
||||
reinterpret_cast<char*>(data.positionKeys.data()),
|
||||
sizeof(PositionKey) * keySize
|
||||
sizeof(PositionKey) * frameCount
|
||||
);
|
||||
|
||||
file.read(
|
||||
reinterpret_cast<char*>(data.rotationKeys.data()),
|
||||
sizeof(RotationKey) * keySize
|
||||
sizeof(RotationKey) * frameCount
|
||||
);
|
||||
|
||||
file.read(
|
||||
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)
|
||||
{
|
||||
file.read(
|
||||
|
@ -128,6 +167,11 @@ namespace SHADE
|
|||
sizeof(uint32_t)
|
||||
);
|
||||
|
||||
file.read(
|
||||
reinterpret_cast<char*>(&header.startNode),
|
||||
sizeof(uint32_t)
|
||||
);
|
||||
|
||||
header.charCounts.resize(header.nodeCount);
|
||||
file.read(
|
||||
reinterpret_cast<char*>(header.charCounts.data()),
|
||||
|
@ -141,21 +185,72 @@ namespace SHADE
|
|||
|
||||
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(
|
||||
data[i].name.data(),
|
||||
node.name.data(),
|
||||
header.charCounts[i]
|
||||
);
|
||||
|
||||
file.read(
|
||||
reinterpret_cast<char*>(&data[i].transform),
|
||||
reinterpret_cast<char*>(&node.inverseBindMatrix),
|
||||
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(
|
||||
reinterpret_cast<char*>(&data[i].offset),
|
||||
sizeof(SHMatrix)
|
||||
reinterpret_cast<char*>(carrier.data()),
|
||||
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++);
|
||||
}
|
||||
}
|
||||
|
||||
delete[] dst;
|
||||
}
|
||||
|
||||
void SHModelLoader::ReadMeshData(FileReference file, std::vector<SHMeshDataHeader> const& headers,
|
||||
|
@ -221,7 +314,6 @@ namespace SHADE
|
|||
data.VertexNormals.resize(header.vertexCount);
|
||||
data.VertexTexCoords.resize(header.vertexCount);
|
||||
data.Indices.resize(header.indexCount);
|
||||
data.BoneCount = header.boneCount;
|
||||
|
||||
file.read(data.name.data(), header.charCount);
|
||||
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.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.VertexBoneWeights.resize(header.vertexCount);
|
||||
|
||||
for (uint32_t boneIndex{0}; boneIndex < bones.size(); ++boneIndex)
|
||||
{
|
||||
auto const& bone = bones[boneIndex];
|
||||
for (auto const& weight : bone.weights)
|
||||
{
|
||||
auto& boneIndices = data.VertexBoneIndices[weight.index];
|
||||
auto& boneWeight = data.VertexBoneWeights[weight.index];
|
||||
file.read(
|
||||
reinterpret_cast<char*>(data.VertexBoneWeights.data()),
|
||||
sizeof(SHVec4) * header.vertexCount
|
||||
);
|
||||
|
||||
for (auto j{0}; j < BONE_INDEX_ALIGHTMENT; ++j)
|
||||
{
|
||||
if (boneWeight[j] == 0.f)
|
||||
{
|
||||
boneIndices[j] = boneIndex;
|
||||
boneWeight[j] = weight.weight;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
file.read(
|
||||
reinterpret_cast<char*>(data.VertexBoneIndices.data()),
|
||||
sizeof(SHVec4U) * header.vertexCount
|
||||
);
|
||||
}
|
||||
|
||||
meshes[i] = &data;
|
||||
|
@ -306,7 +370,7 @@ namespace SHADE
|
|||
animAsset.nodeChannels.resize(header.animNodeCount);
|
||||
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;
|
||||
|
|
|
@ -20,7 +20,6 @@ namespace SHADE
|
|||
{
|
||||
using FileReference = std::ifstream&;
|
||||
|
||||
void ReadAnimNode(FileReference file, SHAnimNodeInfo const& info, SHAnimData& data);
|
||||
|
||||
void ReadRigHeader(FileReference file, SHRigDataHeader& header);
|
||||
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 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 ReadData(FileReference file, SHModelAsset& asset);
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "Assets/Asset Types/SHSceneAsset.h"
|
||||
#include "Assets/Asset Types/SHPrefabAsset.h"
|
||||
#include "Assets/Asset Types/SHMaterialAsset.h"
|
||||
#include "Assets/Asset Types/SHAudioBankAsset.h"
|
||||
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
|
@ -22,6 +23,14 @@ namespace SHADE
|
|||
{
|
||||
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 };
|
||||
|
||||
if (!file.is_open())
|
||||
|
|
|
@ -57,6 +57,7 @@ enum class AssetType : AssetTypeMeta
|
|||
MESH,
|
||||
SCRIPT,
|
||||
FONT,
|
||||
AUDIO_BANK,
|
||||
ANIM_CONTAINER,
|
||||
ANIM_CLIP,
|
||||
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 AUDIO_EXTENSION {".ogg"};
|
||||
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_BUILT_IN_EXTENSION{ ".shshaderb" };
|
||||
constexpr std::string_view FONT_EXTENSION{ ".shfont" };
|
||||
|
@ -111,7 +113,7 @@ constexpr std::string_view EXTENSIONS[] = {
|
|||
FILLER_EXTENSION,
|
||||
SCRIPT_EXTENSION,
|
||||
FONT_EXTENSION,
|
||||
AUDIO_WAV_EXTENSION,
|
||||
AUDIO_BANK_EXTENSION,
|
||||
ANIM_CONTAINER_EXTENSION,
|
||||
FILLER_EXTENSION
|
||||
};
|
||||
|
|
|
@ -499,6 +499,10 @@ namespace SHADE
|
|||
fontPath += FONT_EXTENSION;
|
||||
newPath = fontPath;
|
||||
}
|
||||
else if (ext == AUDIO_BANK_EXTENSION.data())
|
||||
{
|
||||
newPath = path.string();
|
||||
}
|
||||
else
|
||||
{
|
||||
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::SCRIPT)] = nullptr;
|
||||
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_CLIP)] = nullptr;
|
||||
}
|
||||
|
@ -752,6 +757,20 @@ namespace SHADE
|
|||
|
||||
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)
|
||||
{
|
||||
SHAsset newAsset{
|
||||
|
|
|
@ -486,6 +486,7 @@ namespace SHADE
|
|||
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::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
|
||||
{
|
||||
|
|
|
@ -30,4 +30,5 @@ constexpr SHEventIdentifier SH_BUTTON_RELEASE_EVENT { 21 };
|
|||
constexpr SHEventIdentifier SH_BUTTON_HOVER_ENTER_EVENT { 22 };
|
||||
constexpr SHEventIdentifier SH_BUTTON_HOVER_EXIT_EVENT { 23 };
|
||||
constexpr SHEventIdentifier SH_ASSET_COMPILE_EVENT { 24 };
|
||||
constexpr SHEventIdentifier SH_GRAPHICS_LIGHT_DELETE_EVENT { 25 };
|
||||
|
||||
|
|
|
@ -162,6 +162,7 @@ namespace SHADE
|
|||
{
|
||||
assetCollection.emplace(asset.id, asset);
|
||||
}
|
||||
|
||||
if (file.name == asset.name)
|
||||
{
|
||||
AssetPath path{ file.path };
|
||||
|
|
|
@ -6,13 +6,16 @@
|
|||
|
||||
namespace SHADE
|
||||
{
|
||||
struct SHLightEnableShadowEvent
|
||||
struct SHLightShadowEvent
|
||||
{
|
||||
//! We need to get the light component and initialize the relevant variables.
|
||||
EntityID lightEntity;
|
||||
|
||||
//! Generate a renderer for the light component
|
||||
bool generateRenderer;
|
||||
bool firstEnable;
|
||||
|
||||
//! True when light is set enable shadow
|
||||
bool enableShadow;
|
||||
};
|
||||
|
||||
struct SHWindowResizeEvent
|
||||
|
@ -23,4 +26,10 @@ namespace SHADE
|
|||
// New height when window resizes
|
||||
uint32_t resizeHeight;
|
||||
};
|
||||
|
||||
struct SHDeleteLightEvent
|
||||
{
|
||||
//! Entity of the light we are deleting
|
||||
EntityID lightEntity;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -128,7 +128,7 @@ namespace SHADE
|
|||
|
||||
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/SSAO_CS.glsl", false);
|
||||
|
@ -141,6 +141,8 @@ namespace SHADE
|
|||
//SHAssetManager::CompileAsset("../../Assets/Shaders/Text_VS.glsl", false);
|
||||
//SHAssetManager::CompileAsset("../../Assets/Shaders/Trajectory_VS.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
|
||||
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 TRAJECTORY_VS = 41042628; trajectoryVS = SHResourceManager::LoadOrGet<SHVkShaderModule>(TRAJECTORY_VS);
|
||||
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("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("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("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);
|
||||
|
@ -231,7 +234,7 @@ namespace SHADE
|
|||
{
|
||||
"Position",
|
||||
"Entity ID",
|
||||
"Light Layer Indices",
|
||||
"Light Layer Indices And World Normals",
|
||||
"Normals",
|
||||
"Albedo",
|
||||
"Depth Buffer",
|
||||
|
@ -248,7 +251,7 @@ namespace SHADE
|
|||
auto gBufferSubpass = gBufferNode->AddSubpass(SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_WRITE_SUBPASS.data(), worldViewport, worldRenderer);
|
||||
gBufferSubpass->AddColorOutput("Position");
|
||||
gBufferSubpass->AddColorOutput("Entity ID");
|
||||
gBufferSubpass->AddColorOutput("Light Layer Indices");
|
||||
gBufferSubpass->AddColorOutput("Light Layer Indices And World Normals");
|
||||
gBufferSubpass->AddColorOutput("Normals");
|
||||
gBufferSubpass->AddColorOutput("Albedo");
|
||||
gBufferSubpass->AddColorOutput("Position World Space");
|
||||
|
@ -258,7 +261,7 @@ namespace SHADE
|
|||
auto gBufferVfxSubpass = gBufferNode->AddSubpass(SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_WRITE_VFX_SUBPASS.data(), worldViewport, worldRenderer);
|
||||
gBufferVfxSubpass->AddColorOutput("Position");
|
||||
gBufferVfxSubpass->AddColorOutput("Entity ID");
|
||||
gBufferVfxSubpass->AddColorOutput("Light Layer Indices");
|
||||
gBufferVfxSubpass->AddColorOutput("Light Layer Indices And World Normals");
|
||||
gBufferVfxSubpass->AddColorOutput("Normals");
|
||||
gBufferVfxSubpass->AddColorOutput("Albedo");
|
||||
gBufferVfxSubpass->AddColorOutput("Position World Space");
|
||||
|
@ -314,7 +317,7 @@ namespace SHADE
|
|||
auto deferredCompositeNode = renderGraph->AddNode(SHGraphicsConstants::RenderGraphEntityNames::DEFERRED_COMPOSITE_PASS.data(),
|
||||
{
|
||||
"Position",
|
||||
"Light Layer Indices",
|
||||
"Light Layer Indices And World Normals",
|
||||
"Normals",
|
||||
"Albedo",
|
||||
"Scene",
|
||||
|
@ -327,7 +330,7 @@ namespace SHADE
|
|||
/*-----------------------------------------------------------------------*/
|
||||
/* 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)
|
||||
{
|
||||
lightingSubSystem->PrepareShadowMapsForRead(cmdBuffer);
|
||||
|
@ -534,12 +537,21 @@ namespace SHADE
|
|||
ReceiverPtr lightEnableShadowReceivePtr = std::dynamic_pointer_cast<SHEventReceiver>(lightEnableShadowReceiver);
|
||||
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::make_shared<SHEventReceiverSpec<SHGraphicsSystem>>(this, &SHGraphicsSystem::ReceiveCompileAssetEvent)
|
||||
};
|
||||
ReceiverPtr compileAssetReceivePtr = std::dynamic_pointer_cast<SHEventReceiver>(compileAssetReceiever);
|
||||
SHEventManager::SubscribeTo(SH_ASSET_COMPILE_EVENT, compileAssetReceivePtr);
|
||||
|
||||
}
|
||||
|
||||
void SHGraphicsSystem::InitGenericDataAndTexturesDescSet(void) noexcept
|
||||
|
@ -674,22 +686,6 @@ namespace SHADE
|
|||
#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);
|
||||
auto cmdBuffer = renderGraph->GetCommandBuffer(frameIndex);
|
||||
|
||||
|
@ -864,36 +860,47 @@ namespace SHADE
|
|||
|
||||
SHEventHandle SHGraphicsSystem::ReceiveLightEnableShadowEvent(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<SHLightEnableShadowEvent>*>(eventPtr.get())->data;
|
||||
auto const& EVENT_DATA = reinterpret_cast<const SHEventSpec<SHLightShadowEvent>*>(eventPtr.get())->data;
|
||||
auto* lightComp = SHComponentManager::GetComponent<SHLightComponent>(EVENT_DATA->lightEntity);
|
||||
std::string depthResourceName = "ShadowMap_Depth " + 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
|
||||
Handle<SHRenderer> newRenderer = resourceManager.Create<SHRenderer>(device, swapchain->GetNumImages(), descPool, SHRenderer::PROJECTION_TYPE::ORTHOGRAPHIC);
|
||||
lightComp->SetRenderer(newRenderer);
|
||||
|
||||
// assign shadow map index to light component
|
||||
lightComp->SetShadowMapIndex(lightingSubSystem->GetNumShadowMaps());
|
||||
}
|
||||
|
||||
|
||||
// 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(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.
|
||||
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
|
||||
auto newSubpass = shadowMapNode->RuntimeAddSubpass(shadowMapResourceName + " Subpass", shadowMapViewport, lightComp->GetRenderer());
|
||||
newSubpass->AddColorOutput(shadowMapResourceName);
|
||||
newSubpass->AddDepthOutput(depthResourceName, SH_RENDER_GRAPH_RESOURCE_FLAGS::DEPTH);
|
||||
auto shadowMapDrawSubpass = shadowMapNode->RuntimeAddSubpass(shadowMapResourceName + " Subpass", shadowMapViewport, lightComp->GetRenderer());
|
||||
shadowMapDrawSubpass->AddColorOutput(shadowMapResourceName);
|
||||
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
|
||||
shadowMapNode->RuntimeStandaloneRegenerate();
|
||||
|
@ -910,19 +917,63 @@ namespace SHADE
|
|||
tempLibrary.Init(device);
|
||||
tempLibrary.CreateGraphicsPipelines
|
||||
(
|
||||
{ shadowMapVS, shadowMapFS }, shadowMapNode->GetRenderpass(), newSubpass,
|
||||
{ shadowMapVS, shadowMapFS }, shadowMapNode->GetRenderpass(), shadowMapDrawSubpass,
|
||||
SHGraphicsPredefinedData::SystemType::BATCHING,
|
||||
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
|
||||
uint32_t const NEW_SHADOW_MAP_INDEX = lightingSubSystem->AddShadowMap(renderGraph->GetRenderGraphResource(shadowMapResourceName), EVENT_DATA->lightEntity);
|
||||
// add the shadow map and the blurred version to the lighting system
|
||||
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());
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -182,6 +182,7 @@ namespace SHADE
|
|||
/* Light functions */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
SHEventHandle ReceiveLightEnableShadowEvent (SHEventPtr eventPtr) noexcept;
|
||||
SHEventHandle ReceiveLightDeleteEvent (SHEventPtr eventPtr) noexcept;
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* Asset Events */
|
||||
|
@ -481,6 +482,7 @@ namespace SHADE
|
|||
Handle<SHVkShaderModule> shadowMapFS;
|
||||
Handle<SHVkShaderModule> trajectoryVS;
|
||||
Handle<SHVkShaderModule> trajectoryFS;
|
||||
Handle<SHVkShaderModule> shadowMapBlurCS;
|
||||
|
||||
// Fonts
|
||||
Handle<SHFont> testFont;
|
||||
|
|
|
@ -21,6 +21,14 @@ namespace SHADE
|
|||
|
||||
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;
|
||||
|
||||
// If the flag is true
|
||||
if (flag && lightData.shadowMapIndex == SHLightData::INVALID_SHADOW_MAP_INDEX)
|
||||
if (flag)
|
||||
{
|
||||
// Create new event and broadcast it
|
||||
SHLightEnableShadowEvent newEvent;
|
||||
SHLightShadowEvent newEvent;
|
||||
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
|
||||
|
@ -190,6 +204,16 @@ namespace SHADE
|
|||
return renderer;
|
||||
}
|
||||
|
||||
bool SHLightComponent::GetEnableShadow(void) const noexcept
|
||||
{
|
||||
return lightData.castShadows;
|
||||
}
|
||||
|
||||
uint32_t SHLightComponent::GetShadowMapIndex(void) const noexcept
|
||||
{
|
||||
return lightData.shadowMapIndex;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
RTTR_REGISTRATION
|
||||
|
@ -212,5 +236,6 @@ RTTR_REGISTRATION
|
|||
.property("Color", &SHLightComponent::GetColor, &SHLightComponent::SetColor)
|
||||
.property("Layer", &SHLightComponent::GetCullingMask, &SHLightComponent::SetCullingMask)
|
||||
.property("Strength", &SHLightComponent::GetStrength, &SHLightComponent::SetStrength)
|
||||
.property("Casting Shadows", &SHLightComponent::GetEnableShadow, &SHLightComponent::SetEnableShadow)
|
||||
;
|
||||
}
|
||||
|
|
|
@ -69,6 +69,9 @@ namespace SHADE
|
|||
//uint32_t GetIndexInBuffer (void) const noexcept;
|
||||
float GetStrength (void) const noexcept;
|
||||
Handle<SHRenderer> GetRenderer (void) const noexcept;
|
||||
bool GetEnableShadow (void) const noexcept;
|
||||
uint32_t GetShadowMapIndex (void) const noexcept;
|
||||
|
||||
RTTR_ENABLE()
|
||||
};
|
||||
}
|
||||
|
|
|
@ -53,6 +53,7 @@ namespace SHADE
|
|||
SHVec4 transformedDir = SHMatrix::Transpose(viewMat) * SHVec4(lightData.direction[0], lightData.direction[1], lightData.direction[2], 0.0f);
|
||||
|
||||
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 = lightData.direction;
|
||||
lightPtr->diffuseColor = lightData.color;
|
||||
|
@ -525,7 +526,7 @@ namespace SHADE
|
|||
if (auto renderer = light.GetRenderer())
|
||||
{
|
||||
//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);
|
||||
|
@ -598,49 +599,25 @@ namespace SHADE
|
|||
{
|
||||
//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] });
|
||||
|
||||
}
|
||||
|
||||
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
|
||||
shadowMapIndexing.emplace(lightEntity, static_cast<uint32_t> (shadowMaps.size()));
|
||||
shadowMaps.emplace_back(newShadowMap);
|
||||
uint32_t usedIndex = 0;
|
||||
|
||||
// Just use the image view stored in the resource
|
||||
Handle<SHVkImageView> const NEW_IMAGE_VIEW = newShadowMap->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
|
||||
//);
|
||||
Handle<SHVkImageView> const NEW_IMAGE_VIEW = newShadowMapBlurred->GetImageView();
|
||||
|
||||
// add to barriers
|
||||
shadowMapMemoryBarriers.push_back (vk::ImageMemoryBarrier
|
||||
{
|
||||
.srcAccessMask = vk::AccessFlagBits::eColorAttachmentWrite | vk::AccessFlagBits::eColorAttachmentRead,
|
||||
.srcAccessMask = vk::AccessFlagBits::eShaderWrite,
|
||||
.dstAccessMask = vk::AccessFlagBits::eShaderRead,
|
||||
.oldLayout = vk::ImageLayout::eColorAttachmentOptimal,
|
||||
.newLayout = vk::ImageLayout::eShaderReadOnlyOptimal,
|
||||
.oldLayout = vk::ImageLayout::eGeneral,
|
||||
.newLayout = vk::ImageLayout::eGeneral,
|
||||
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.image = newShadowMap->GetImage()->GetVkImage(),
|
||||
.image = newShadowMapBlurred->GetImage()->GetVkImage(),
|
||||
.subresourceRange = vk::ImageSubresourceRange
|
||||
{
|
||||
.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 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
|
||||
{
|
||||
// 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
|
||||
{
|
||||
return lightingDataDescSet;
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "Graphics/MiddleEnd/Interface/SHGraphicsConstants.h"
|
||||
#include "Graphics/RenderGraph/SHRenderGraphResource.h"
|
||||
#include "ECS_Base/SHECSMacros.h"
|
||||
#include <stack>
|
||||
|
||||
|
||||
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.
|
||||
struct SHDirectionalLightData
|
||||
{
|
||||
//! Direction of the light
|
||||
SHVec4 directionWorld;
|
||||
|
||||
//! Direction of the light
|
||||
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
|
||||
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
|
||||
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)
|
||||
std::vector<vk::ImageMemoryBarrier> shadowMapMemoryBarriers;
|
||||
|
||||
//! recycled indices after deleting lights with shadows
|
||||
std::stack<uint32_t> recyclableIndices;
|
||||
|
||||
//! Resource hub from Graphics System
|
||||
SHResourceHub* resourceHub;
|
||||
|
||||
|
@ -213,7 +216,9 @@ namespace SHADE
|
|||
void Run (SHMatrix const& viewMat, uint32_t frameIndex) noexcept;
|
||||
void Exit (void) 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 HandleResize (Handle<SHRenderGraphNodeCompute> compute) noexcept;
|
||||
//void RemoveShadowMap (uint32_t index) noexcept;
|
||||
|
|
|
@ -81,7 +81,8 @@ namespace SHADE
|
|||
|
||||
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
|
||||
std::vector<uint32_t> affectedNodes{};
|
||||
|
@ -89,7 +90,7 @@ namespace SHADE
|
|||
// Detach resource from all nodes if applicable
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -109,6 +110,8 @@ namespace SHADE
|
|||
|
||||
renderGraphStorage->graphResources->at(resourceName).Free();
|
||||
renderGraphStorage->graphResources->erase (resourceName);
|
||||
|
||||
resourceHdl.Free ();
|
||||
/*
|
||||
* 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
|
||||
{
|
||||
// resource to link
|
||||
|
@ -479,7 +497,7 @@ namespace SHADE
|
|||
// get target node
|
||||
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 ();
|
||||
return *node;
|
||||
|
||||
|
@ -583,6 +601,10 @@ namespace SHADE
|
|||
|
||||
for (auto& node : nodes)
|
||||
{
|
||||
// if node is dynamic check for active flag
|
||||
if ((node->isDynamic) ? !node->dynamicIsActive : false)
|
||||
continue;
|
||||
|
||||
if (node->renderpass)
|
||||
{
|
||||
// bind static global data
|
||||
|
|
|
@ -112,6 +112,7 @@ namespace SHADE
|
|||
);
|
||||
|
||||
void RemoveResource (std::string resourceName) noexcept;
|
||||
void RemoveNode (std::string nodeName) noexcept;
|
||||
|
||||
void LinkNonOwningResource
|
||||
(
|
||||
|
|
|
@ -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}
|
||||
, renderpass{}
|
||||
, framebuffers{}
|
||||
|
@ -305,6 +305,8 @@ namespace SHADE
|
|||
, configured{ false }
|
||||
, nodeComputes{}
|
||||
, name { std::move(nodeName) }
|
||||
, dynamicIsActive {true} // default set to true
|
||||
, isDynamic{inIsDynamic}
|
||||
{
|
||||
// pipeline library initialization
|
||||
pipelineLibrary.Init(graphStorage->logicalDevice);
|
||||
|
@ -368,6 +370,8 @@ namespace SHADE
|
|||
, nodeComputes{ std::move(rhs.nodeComputes) }
|
||||
, name { std::move(rhs.name) }
|
||||
, ISelfHandle<SHRenderGraphNode>{std::move(rhs)}
|
||||
, dynamicIsActive {rhs.dynamicIsActive}
|
||||
, isDynamic {rhs.isDynamic}
|
||||
|
||||
{
|
||||
rhs.renderpass = {};
|
||||
|
@ -393,12 +397,30 @@ namespace SHADE
|
|||
spDeps = std::move(rhs.spDeps);
|
||||
nodeComputes = std::move(rhs.nodeComputes);
|
||||
name = std::move(rhs.name);
|
||||
dynamicIsActive = rhs.dynamicIsActive;
|
||||
isDynamic = rhs.isDynamic;
|
||||
|
||||
rhs.renderpass = {};
|
||||
|
||||
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
|
||||
{
|
||||
AddDummySubpassIfNeeded();
|
||||
StandaloneConfigureAttDesc(false);
|
||||
ConfigureSubpasses();
|
||||
CreateRenderpass();
|
||||
CreateFramebuffer();
|
||||
}
|
||||
|
||||
void SHRenderGraphNode::SetDynamicActive(bool active) noexcept
|
||||
{
|
||||
dynamicIsActive = active;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
|
@ -849,4 +877,9 @@ namespace SHADE
|
|||
return {};
|
||||
}
|
||||
|
||||
bool SHRenderGraphNode::GetDynamicActive(void) const noexcept
|
||||
{
|
||||
return dynamicIsActive;
|
||||
}
|
||||
|
||||
}
|
|
@ -80,6 +80,13 @@ namespace SHADE
|
|||
//! Whether or not the node has been configured already or not
|
||||
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
|
||||
SHBatcher batcher;
|
||||
|
||||
|
@ -101,9 +108,10 @@ namespace SHADE
|
|||
/*-----------------------------------------------------------------------*/
|
||||
/* 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& operator= (SHRenderGraphNode&& rhs) noexcept;
|
||||
~SHRenderGraphNode (void) noexcept;
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* PUBLIC MEMBER FUNCTIONS */
|
||||
|
@ -123,11 +131,15 @@ namespace SHADE
|
|||
/*-----------------------------------------------------------------------*/
|
||||
/* SETTERS AND GETTERS */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
void SetDynamicActive(bool active) noexcept;
|
||||
|
||||
Handle<SHVkRenderpass> GetRenderpass(void) const noexcept;
|
||||
Handle<SHSubpass> GetSubpass(std::string_view subpassName) const noexcept;
|
||||
Handle<SHRenderGraphResource> GetResource (uint32_t resourceIndex) const noexcept;
|
||||
std::vector<Handle<SHRenderGraphResource>> const& GetResources (void) const noexcept;
|
||||
Handle<SHRenderGraphNodeCompute> GetNodeCompute (std::string nodeComputeName) const noexcept;
|
||||
bool GetDynamicActive (void) const noexcept;
|
||||
|
||||
friend class SHRenderGraph;
|
||||
};
|
||||
|
||||
|
|
|
@ -77,9 +77,17 @@ namespace SHADE
|
|||
, name { rhs.name }
|
||||
, viewport {rhs.viewport}
|
||||
, renderer {rhs.renderer}
|
||||
, companionSubpass {rhs.companionSubpass}
|
||||
, companionSubpasses {std::move (rhs.companionSubpasses)}
|
||||
, 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);
|
||||
parentNode = std::move(rhs.parentNode);
|
||||
superBatch = std::move(rhs.superBatch);
|
||||
colorReferences = std::move(rhs.colorReferences);
|
||||
depthReferences = std::move(rhs.depthReferences);
|
||||
inputReferences = std::move(rhs.inputReferences);
|
||||
|
@ -115,13 +122,39 @@ namespace SHADE
|
|||
name = std::move(rhs.name);
|
||||
renderer = rhs.renderer;
|
||||
viewport = rhs.viewport;
|
||||
companionSubpass = rhs.companionSubpass;
|
||||
companionSubpasses = rhs.companionSubpasses;
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
// If companion subpass is not a valid handle, render super batch normally
|
||||
if (!companionSubpass.companion)
|
||||
if (companionSubpasses.empty())
|
||||
{
|
||||
// Draw all the batches
|
||||
superBatch->Draw(commandBuffer, frameIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (auto& companion : companionSubpasses)
|
||||
{
|
||||
// if not bind pipeline for companion and and execute draw command
|
||||
commandBuffer->BindPipeline(companionSubpass.pipeline);
|
||||
companionSubpass.companion->superBatch->Draw(commandBuffer, frameIndex, false);
|
||||
commandBuffer->BindPipeline(companion.pipeline);
|
||||
companion.subpass->superBatch->Draw(commandBuffer, frameIndex, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -493,10 +528,11 @@ namespace SHADE
|
|||
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;
|
||||
companionSubpass.pipeline = pipeline;
|
||||
companionSubpasses.push_back(CompanionSubpass{companion, pipeline});
|
||||
//companionSubpass.companion = companion;
|
||||
//companionSubpass.pipeline = pipeline;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
|
|
@ -33,7 +33,7 @@ namespace SHADE
|
|||
struct CompanionSubpass
|
||||
{
|
||||
// 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
|
||||
Handle<SHVkPipeline> pipeline;
|
||||
|
@ -114,7 +114,8 @@ namespace SHADE
|
|||
|
||||
//! 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.
|
||||
CompanionSubpass companionSubpass;
|
||||
//CompanionSubpass companionSubpass;
|
||||
std::vector<CompanionSubpass> companionSubpasses;
|
||||
|
||||
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(SHSubpass&& rhs) noexcept;
|
||||
SHSubpass& operator=(SHSubpass&& rhs) noexcept;
|
||||
~SHSubpass(void) noexcept;
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* PUBLIC MEMBER FUNCTIONS */
|
||||
|
@ -165,7 +167,7 @@ namespace SHADE
|
|||
/*-----------------------------------------------------------------------*/
|
||||
/* 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;
|
||||
SHSubPassIndex GetIndex() const noexcept;
|
||||
|
|
|
@ -34,6 +34,7 @@ namespace SHADE
|
|||
, flags { 0 }
|
||||
, drag { 0.01f }
|
||||
, angularDrag { 0.1f }
|
||||
, gravityScale{ 1.0f }
|
||||
, rigidBody { nullptr }
|
||||
{
|
||||
// Default flags
|
||||
|
|
Loading…
Reference in New Issue