Merge pull request #406 from SHADE-DP/SP3-1-Rendering

Implemented shadows. Light components can enable shadows through editor.
This commit is contained in:
XiaoQiDigipen 2023-03-08 14:17:15 +08:00 committed by GitHub
commit ef7cd4c0c0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
32 changed files with 529 additions and 215 deletions

View File

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

Binary file not shown.

View File

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

View File

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

Binary file not shown.

View File

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

View File

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

View File

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

View File

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

View File

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

Binary file not shown.

View File

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

Binary file not shown.

View File

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

View File

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

View File

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

View File

@ -128,7 +128,7 @@ namespace SHADE
SHFreetypeInstance::Init(); SHFreetypeInstance::Init();
//SHAssetManager::CompileAsset("../../Assets/Shaders/DeferredComposite_CS.glsl", false); SHAssetManager::CompileAsset("../../Assets/Shaders/DeferredComposite_CS.glsl", false);
//SHAssetManager::CompileAsset("../../Assets/Shaders/ShadowMap_FS.glsl", false); //SHAssetManager::CompileAsset("../../Assets/Shaders/ShadowMap_FS.glsl", false);
//SHAssetManager::CompileAsset("../../Assets/Shaders/ShadowMap_FS.glsl", false); //SHAssetManager::CompileAsset("../../Assets/Shaders/ShadowMap_FS.glsl", false);
//SHAssetManager::CompileAsset("../../Assets/Shaders/SSAO_CS.glsl", false); //SHAssetManager::CompileAsset("../../Assets/Shaders/SSAO_CS.glsl", false);
@ -141,25 +141,28 @@ namespace SHADE
//SHAssetManager::CompileAsset("../../Assets/Shaders/Text_VS.glsl", false); //SHAssetManager::CompileAsset("../../Assets/Shaders/Text_VS.glsl", false);
//SHAssetManager::CompileAsset("../../Assets/Shaders/Trajectory_VS.glsl", false); //SHAssetManager::CompileAsset("../../Assets/Shaders/Trajectory_VS.glsl", false);
//SHAssetManager::CompileAsset("../../Assets/Shaders/Trajectory_FS.glsl", false); //SHAssetManager::CompileAsset("../../Assets/Shaders/Trajectory_FS.glsl", false);
//SHAssetManager::CompileAsset("../../Assets/Shaders/ShadowMapBlur_CS.glsl", false);
//SHAssetManager::CompileAsset("../../Assets/Shaders/Anim_VS.glsl", false);
// Load Built In Shaders // Load Built In Shaders
static constexpr AssetID VS_DEFAULT = 39210065; defaultVertShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(VS_DEFAULT); static constexpr AssetID VS_DEFAULT = 39210065; defaultVertShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(VS_DEFAULT);
static constexpr AssetID VS_ANIM = 47911992; animtVertShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(VS_ANIM); static constexpr AssetID VS_ANIM = 47911992; animtVertShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(VS_ANIM);
static constexpr AssetID FS_DEFAULT = 46377769; defaultFragShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(FS_DEFAULT); static constexpr AssetID FS_DEFAULT = 46377769; defaultFragShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(FS_DEFAULT);
static constexpr AssetID VS_DEBUG = 48002439; debugVertShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(VS_DEBUG); static constexpr AssetID VS_DEBUG = 48002439; debugVertShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(VS_DEBUG);
static constexpr AssetID FS_DEBUG = 36671027; debugFragShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(FS_DEBUG); static constexpr AssetID FS_DEBUG = 36671027; debugFragShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(FS_DEBUG);
static constexpr AssetID VS_DEBUG_MESH = 42127043; debugMeshVertShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(VS_DEBUG_MESH); static constexpr AssetID VS_DEBUG_MESH = 42127043; debugMeshVertShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(VS_DEBUG_MESH);
static constexpr AssetID CS_COMPOSITE = 45072428; deferredCompositeShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(CS_COMPOSITE); static constexpr AssetID CS_COMPOSITE = 45072428; deferredCompositeShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(CS_COMPOSITE);
static constexpr AssetID SSAO = 38430899; ssaoShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(SSAO); static constexpr AssetID SSAO = 38430899; ssaoShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(SSAO);
static constexpr AssetID SSAO_BLUR = 39760835; ssaoBlurShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(SSAO_BLUR); static constexpr AssetID SSAO_BLUR = 39760835; ssaoBlurShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(SSAO_BLUR);
static constexpr AssetID TEXT_VS = 39816727; textVS = SHResourceManager::LoadOrGet<SHVkShaderModule>(TEXT_VS); static constexpr AssetID TEXT_VS = 39816727; textVS = SHResourceManager::LoadOrGet<SHVkShaderModule>(TEXT_VS);
static constexpr AssetID TEXT_FS = 38024754; textFS = SHResourceManager::LoadOrGet<SHVkShaderModule>(TEXT_FS); static constexpr AssetID TEXT_FS = 38024754; textFS = SHResourceManager::LoadOrGet<SHVkShaderModule>(TEXT_FS);
static constexpr AssetID RENDER_SC_VS = 48082949; renderToSwapchainVS = SHResourceManager::LoadOrGet<SHVkShaderModule>(RENDER_SC_VS); static constexpr AssetID RENDER_SC_VS = 48082949; renderToSwapchainVS = SHResourceManager::LoadOrGet<SHVkShaderModule>(RENDER_SC_VS);
static constexpr AssetID RENDER_SC_FS = 36869006; renderToSwapchainFS = SHResourceManager::LoadOrGet<SHVkShaderModule>(RENDER_SC_FS); static constexpr AssetID RENDER_SC_FS = 36869006; renderToSwapchainFS = SHResourceManager::LoadOrGet<SHVkShaderModule>(RENDER_SC_FS);
static constexpr AssetID SHADOW_MAP_VS = 44646107; shadowMapVS = SHResourceManager::LoadOrGet<SHVkShaderModule>(SHADOW_MAP_VS); static constexpr AssetID SHADOW_MAP_VS = 44646107; shadowMapVS = SHResourceManager::LoadOrGet<SHVkShaderModule>(SHADOW_MAP_VS);
static constexpr AssetID SHADOW_MAP_FS = 45925790; shadowMapFS = SHResourceManager::LoadOrGet<SHVkShaderModule>(SHADOW_MAP_FS); static constexpr AssetID SHADOW_MAP_FS = 45925790; shadowMapFS = SHResourceManager::LoadOrGet<SHVkShaderModule>(SHADOW_MAP_FS);
static constexpr AssetID TRAJECTORY_VS = 41042628; trajectoryVS = SHResourceManager::LoadOrGet<SHVkShaderModule>(TRAJECTORY_VS); static constexpr AssetID TRAJECTORY_VS = 41042628; trajectoryVS = SHResourceManager::LoadOrGet<SHVkShaderModule>(TRAJECTORY_VS);
static constexpr AssetID TRAJECTORY_FS = 45635685; trajectoryFS = SHResourceManager::LoadOrGet<SHVkShaderModule>(TRAJECTORY_FS); static constexpr AssetID TRAJECTORY_FS = 45635685; trajectoryFS = SHResourceManager::LoadOrGet<SHVkShaderModule>(TRAJECTORY_FS);
static constexpr AssetID SHADOW_BLUR_CS = 38004013; shadowMapBlurCS = SHResourceManager::LoadOrGet<SHVkShaderModule>(SHADOW_BLUR_CS);
} }
@ -217,7 +220,7 @@ namespace SHADE
renderGraph->AddResource("Albedo", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE }, true, windowDims.first, windowDims.second); renderGraph->AddResource("Albedo", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE }, true, windowDims.first, windowDims.second);
renderGraph->AddResource("Depth Buffer", { SH_RENDER_GRAPH_RESOURCE_FLAGS::DEPTH, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT }, true, windowDims.first, windowDims.second, vk::Format::eD32SfloatS8Uint); renderGraph->AddResource("Depth Buffer", { SH_RENDER_GRAPH_RESOURCE_FLAGS::DEPTH, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT }, true, windowDims.first, windowDims.second, vk::Format::eD32SfloatS8Uint);
renderGraph->AddResource("Entity ID", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::SHARED }, true, windowDims.first, windowDims.second, vk::Format::eR32Uint, 1, vk::ImageUsageFlagBits::eTransferSrc); renderGraph->AddResource("Entity ID", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::SHARED }, true, windowDims.first, windowDims.second, vk::Format::eR32Uint, 1, vk::ImageUsageFlagBits::eTransferSrc);
renderGraph->AddResource("Light Layer Indices", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE }, true, windowDims.first, windowDims.second, vk::Format::eR32Uint, 1, vk::ImageUsageFlagBits::eTransferSrc); renderGraph->AddResource("Light Layer Indices And World Normals", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE }, true, windowDims.first, windowDims.second, vk::Format::eR32G32B32A32Uint, 1, vk::ImageUsageFlagBits::eTransferSrc);
renderGraph->AddResource("Scene", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE, SH_RENDER_GRAPH_RESOURCE_FLAGS::SHARED }, true, windowDims.first, windowDims.second); renderGraph->AddResource("Scene", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE, SH_RENDER_GRAPH_RESOURCE_FLAGS::SHARED }, true, windowDims.first, windowDims.second);
renderGraph->AddResource("SSAO", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE }, true, windowDims.first, windowDims.second, vk::Format::eR8Unorm); renderGraph->AddResource("SSAO", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE }, true, windowDims.first, windowDims.second, vk::Format::eR8Unorm);
renderGraph->AddResource("SSAO Blur", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE }, true, windowDims.first, windowDims.second, vk::Format::eR8Unorm); renderGraph->AddResource("SSAO Blur", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE }, true, windowDims.first, windowDims.second, vk::Format::eR8Unorm);
@ -231,7 +234,7 @@ namespace SHADE
{ {
"Position", "Position",
"Entity ID", "Entity ID",
"Light Layer Indices", "Light Layer Indices And World Normals",
"Normals", "Normals",
"Albedo", "Albedo",
"Depth Buffer", "Depth Buffer",
@ -248,7 +251,7 @@ namespace SHADE
auto gBufferSubpass = gBufferNode->AddSubpass(SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_WRITE_SUBPASS.data(), worldViewport, worldRenderer); auto gBufferSubpass = gBufferNode->AddSubpass(SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_WRITE_SUBPASS.data(), worldViewport, worldRenderer);
gBufferSubpass->AddColorOutput("Position"); gBufferSubpass->AddColorOutput("Position");
gBufferSubpass->AddColorOutput("Entity ID"); gBufferSubpass->AddColorOutput("Entity ID");
gBufferSubpass->AddColorOutput("Light Layer Indices"); gBufferSubpass->AddColorOutput("Light Layer Indices And World Normals");
gBufferSubpass->AddColorOutput("Normals"); gBufferSubpass->AddColorOutput("Normals");
gBufferSubpass->AddColorOutput("Albedo"); gBufferSubpass->AddColorOutput("Albedo");
gBufferSubpass->AddColorOutput("Position World Space"); gBufferSubpass->AddColorOutput("Position World Space");
@ -258,7 +261,7 @@ namespace SHADE
auto gBufferVfxSubpass = gBufferNode->AddSubpass(SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_WRITE_VFX_SUBPASS.data(), worldViewport, worldRenderer); auto gBufferVfxSubpass = gBufferNode->AddSubpass(SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_WRITE_VFX_SUBPASS.data(), worldViewport, worldRenderer);
gBufferVfxSubpass->AddColorOutput("Position"); gBufferVfxSubpass->AddColorOutput("Position");
gBufferVfxSubpass->AddColorOutput("Entity ID"); gBufferVfxSubpass->AddColorOutput("Entity ID");
gBufferVfxSubpass->AddColorOutput("Light Layer Indices"); gBufferVfxSubpass->AddColorOutput("Light Layer Indices And World Normals");
gBufferVfxSubpass->AddColorOutput("Normals"); gBufferVfxSubpass->AddColorOutput("Normals");
gBufferVfxSubpass->AddColorOutput("Albedo"); gBufferVfxSubpass->AddColorOutput("Albedo");
gBufferVfxSubpass->AddColorOutput("Position World Space"); gBufferVfxSubpass->AddColorOutput("Position World Space");
@ -314,7 +317,7 @@ namespace SHADE
auto deferredCompositeNode = renderGraph->AddNode(SHGraphicsConstants::RenderGraphEntityNames::DEFERRED_COMPOSITE_PASS.data(), auto deferredCompositeNode = renderGraph->AddNode(SHGraphicsConstants::RenderGraphEntityNames::DEFERRED_COMPOSITE_PASS.data(),
{ {
"Position", "Position",
"Light Layer Indices", "Light Layer Indices And World Normals",
"Normals", "Normals",
"Albedo", "Albedo",
"Scene", "Scene",
@ -327,7 +330,7 @@ namespace SHADE
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* DEFERRED COMPOSITE SUBPASS INIT */ /* DEFERRED COMPOSITE SUBPASS INIT */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
auto deferredCompositeCompute = deferredCompositeNode->AddNodeCompute(SHGraphicsConstants::RenderGraphEntityNames::DEFERRED_COMPOSITE_COMPUTE.data(), deferredCompositeShader, {"Position", "Normals", "Albedo", "Light Layer Indices", "SSAO Blur", "Position World Space", "Scene", "Object VFX"}, {}, SHLightingSubSystem::MAX_SHADOWS); auto deferredCompositeCompute = deferredCompositeNode->AddNodeCompute(SHGraphicsConstants::RenderGraphEntityNames::DEFERRED_COMPOSITE_COMPUTE.data(), deferredCompositeShader, {"Position", "Normals", "Albedo", "Light Layer Indices And World Normals", "SSAO Blur", "Position World Space", "Scene", "Object VFX"}, {}, SHLightingSubSystem::MAX_SHADOWS);
deferredCompositeCompute->AddPreComputeFunction([=](Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) deferredCompositeCompute->AddPreComputeFunction([=](Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex)
{ {
lightingSubSystem->PrepareShadowMapsForRead(cmdBuffer); lightingSubSystem->PrepareShadowMapsForRead(cmdBuffer);
@ -534,12 +537,21 @@ namespace SHADE
ReceiverPtr lightEnableShadowReceivePtr = std::dynamic_pointer_cast<SHEventReceiver>(lightEnableShadowReceiver); ReceiverPtr lightEnableShadowReceivePtr = std::dynamic_pointer_cast<SHEventReceiver>(lightEnableShadowReceiver);
SHEventManager::SubscribeTo(SH_GRAPHICS_LIGHT_ENABLE_SHADOW_EVENT, lightEnableShadowReceivePtr); SHEventManager::SubscribeTo(SH_GRAPHICS_LIGHT_ENABLE_SHADOW_EVENT, lightEnableShadowReceivePtr);
std::shared_ptr<SHEventReceiverSpec<SHGraphicsSystem>> lightDeleteEvent
{
std::make_shared<SHEventReceiverSpec<SHGraphicsSystem>>(this, &SHGraphicsSystem::ReceiveLightDeleteEvent)
};
ReceiverPtr lightDeleteReceivePtr = std::dynamic_pointer_cast<SHEventReceiver>(lightDeleteEvent);
SHEventManager::SubscribeTo(SH_GRAPHICS_LIGHT_DELETE_EVENT, lightDeleteReceivePtr);
std::shared_ptr<SHEventReceiverSpec<SHGraphicsSystem>> compileAssetReceiever std::shared_ptr<SHEventReceiverSpec<SHGraphicsSystem>> compileAssetReceiever
{ {
std::make_shared<SHEventReceiverSpec<SHGraphicsSystem>>(this, &SHGraphicsSystem::ReceiveCompileAssetEvent) std::make_shared<SHEventReceiverSpec<SHGraphicsSystem>>(this, &SHGraphicsSystem::ReceiveCompileAssetEvent)
}; };
ReceiverPtr compileAssetReceivePtr = std::dynamic_pointer_cast<SHEventReceiver>(compileAssetReceiever); ReceiverPtr compileAssetReceivePtr = std::dynamic_pointer_cast<SHEventReceiver>(compileAssetReceiever);
SHEventManager::SubscribeTo(SH_ASSET_COMPILE_EVENT, compileAssetReceivePtr); SHEventManager::SubscribeTo(SH_ASSET_COMPILE_EVENT, compileAssetReceivePtr);
} }
void SHGraphicsSystem::InitGenericDataAndTexturesDescSet(void) noexcept void SHGraphicsSystem::InitGenericDataAndTexturesDescSet(void) noexcept
@ -674,22 +686,6 @@ namespace SHADE
#endif #endif
} }
//static bool shadowAdded = false;
//if (shadowAdded == false && SHInputManager::GetKey(SHInputManager::SH_KEYCODE::B))
//{
// shadowAdded = true;
// auto& lightComps = SHComponentManager::GetDense<SHLightComponent>();
// //if (lightComps.size() > 2)
// //{
// // lightComps[2].SetEnableShadow(true);
// //}
// for (auto& comp : lightComps)
// {
// comp.SetEnableShadow(true);
// }
//}
renderGraph->Begin(frameIndex); renderGraph->Begin(frameIndex);
auto cmdBuffer = renderGraph->GetCommandBuffer(frameIndex); auto cmdBuffer = renderGraph->GetCommandBuffer(frameIndex);
@ -863,66 +859,121 @@ namespace SHADE
} }
SHEventHandle SHGraphicsSystem::ReceiveLightEnableShadowEvent(SHEventPtr eventPtr) noexcept SHEventHandle SHGraphicsSystem::ReceiveLightEnableShadowEvent(SHEventPtr eventPtr) noexcept
{
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);
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->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, 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(), shadowMapBlurredResourceName.c_str() }, SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_PASS.data());
// Add a subpass to render to that shadow map
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();
// Create pipeline from new renderpass and subpass if it's not created yet
if (!shadowMapPipeline)
{
SHPipelineLibrary tempLibrary{};
Handle<SHRenderGraphNode> rgNode = renderGraph->GetNode(SHGraphicsConstants::RenderGraphEntityNames::SHADOW_MAP_PASS.data());
SHRasterizationState rasterState{};
rasterState.cull_mode = vk::CullModeFlagBits::eBack;
tempLibrary.Init(device);
tempLibrary.CreateGraphicsPipelines
(
{ shadowMapVS, shadowMapFS }, shadowMapNode->GetRenderpass(), shadowMapDrawSubpass,
SHGraphicsPredefinedData::SystemType::BATCHING,
SHGraphicsPredefinedData::GetShadowMapViState(), rasterState
);
shadowMapPipeline = tempLibrary.GetGraphicsPipeline({ shadowMapVS, shadowMapFS, shadowMapDrawSubpass });
}
shadowMapDrawSubpass->AddCompanionSubpass(gBufferWriteSubpass, shadowMapPipeline); // set companion subpass and pipeline
shadowMapDrawSubpass->AddCompanionSubpass(gBufferWriteVfxSubpass, shadowMapPipeline); // set companion subpass and pipeline
// 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 // we need to wait for the device to finish using the graph first
device->WaitIdle(); 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); 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);
if (EVENT_DATA->generateRenderer)
{
// 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);
// 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());
// 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);
// regenerate the node
shadowMapNode->RuntimeStandaloneRegenerate();
// Create pipeline from new renderpass and subpass if it's not created yet
if (!shadowMapPipeline)
{
SHPipelineLibrary tempLibrary{};
Handle<SHRenderGraphNode> rgNode = renderGraph->GetNode(SHGraphicsConstants::RenderGraphEntityNames::SHADOW_MAP_PASS.data());
SHRasterizationState rasterState{};
rasterState.cull_mode = vk::CullModeFlagBits::eBack;
tempLibrary.Init(device);
tempLibrary.CreateGraphicsPipelines
(
{ shadowMapVS, shadowMapFS }, shadowMapNode->GetRenderpass(), newSubpass,
SHGraphicsPredefinedData::SystemType::BATCHING,
SHGraphicsPredefinedData::GetShadowMapViState(), rasterState
);
shadowMapPipeline = tempLibrary.GetGraphicsPipeline({ shadowMapVS, shadowMapFS, newSubpass });
}
newSubpass->SetCompanionSubpass(companionSubpass, shadowMapPipeline); // set companion subpass and pipeline
// add the shadow map to the lighting system if (lightComp && lightComp->GetShadowMapIndex() != SHLightData::INVALID_SHADOW_MAP_INDEX)
uint32_t const NEW_SHADOW_MAP_INDEX = lightingSubSystem->AddShadowMap(renderGraph->GetRenderGraphResource(shadowMapResourceName), EVENT_DATA->lightEntity); {
std::string depthResourceName = "ShadowMap_Depth " + std::to_string(EVENT_DATA->lightEntity);
std::string shadowMapResourceName = "ShadowMap " + std::to_string(EVENT_DATA->lightEntity);
std::string 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);
}
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);
return eventPtr->handle; return eventPtr->handle;
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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