diff --git a/Assets/Shaders/Anim_VS.glsl b/Assets/Shaders/Anim_VS.glsl index 2213b2fd..5282f062 100644 --- a/Assets/Shaders/Anim_VS.glsl +++ b/Assets/Shaders/Anim_VS.glsl @@ -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]; diff --git a/Assets/Shaders/Anim_VS.shshaderb b/Assets/Shaders/Anim_VS.shshaderb index 63185558..41ddaec3 100644 Binary files a/Assets/Shaders/Anim_VS.shshaderb and b/Assets/Shaders/Anim_VS.shshaderb differ diff --git a/Assets/Shaders/DeferredComposite_CS.glsl b/Assets/Shaders/DeferredComposite_CS.glsl index 12352d4d..18f53de4 100644 --- a/Assets/Shaders/DeferredComposite_CS.glsl +++ b/Assets/Shaders/DeferredComposite_CS.glsl @@ -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; } } } diff --git a/Assets/Shaders/DeferredComposite_CS.shshaderb b/Assets/Shaders/DeferredComposite_CS.shshaderb index a5197b3b..57401b13 100644 Binary files a/Assets/Shaders/DeferredComposite_CS.shshaderb and b/Assets/Shaders/DeferredComposite_CS.shshaderb differ diff --git a/Assets/Shaders/ShadowMapBlur_CS.glsl b/Assets/Shaders/ShadowMapBlur_CS.glsl new file mode 100644 index 00000000..eabb655f --- /dev/null +++ b/Assets/Shaders/ShadowMapBlur_CS.glsl @@ -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); +} \ No newline at end of file diff --git a/Assets/Shaders/ShadowMapBlur_CS.shshaderb b/Assets/Shaders/ShadowMapBlur_CS.shshaderb new file mode 100644 index 00000000..d02afaf1 Binary files /dev/null and b/Assets/Shaders/ShadowMapBlur_CS.shshaderb differ diff --git a/Assets/Shaders/ShadowMapBlur_CS.shshaderb.shmeta b/Assets/Shaders/ShadowMapBlur_CS.shshaderb.shmeta new file mode 100644 index 00000000..cc90d5c9 --- /dev/null +++ b/Assets/Shaders/ShadowMapBlur_CS.shshaderb.shmeta @@ -0,0 +1,3 @@ +Name: ShadowMapBlur_CS +ID: 38004013 +Type: 2 diff --git a/Assets/Shaders/ShadowMap_FS.glsl b/Assets/Shaders/ShadowMap_FS.glsl index b19a32a6..59904b5e 100644 --- a/Assets/Shaders/ShadowMap_FS.glsl +++ b/Assets/Shaders/ShadowMap_FS.glsl @@ -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); } \ No newline at end of file diff --git a/Assets/Shaders/ShadowMap_FS.shshaderb b/Assets/Shaders/ShadowMap_FS.shshaderb index 709a2ecc..78d304c1 100644 Binary files a/Assets/Shaders/ShadowMap_FS.shshaderb and b/Assets/Shaders/ShadowMap_FS.shshaderb differ diff --git a/Assets/Shaders/ShinyHighlight_FS.glsl b/Assets/Shaders/ShinyHighlight_FS.glsl index bb41a0fb..18f979fe 100644 --- a/Assets/Shaders/ShinyHighlight_FS.glsl +++ b/Assets/Shaders/ShinyHighlight_FS.glsl @@ -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; } \ No newline at end of file diff --git a/Assets/Shaders/ShinyHighlight_FS.shshaderb b/Assets/Shaders/ShinyHighlight_FS.shshaderb index b1ac22bb..a3a6230d 100644 Binary files a/Assets/Shaders/ShinyHighlight_FS.shshaderb and b/Assets/Shaders/ShinyHighlight_FS.shshaderb differ diff --git a/Assets/Shaders/ShinyHighlight_VS.glsl b/Assets/Shaders/ShinyHighlight_VS.glsl index c0268737..483af1f0 100644 --- a/Assets/Shaders/ShinyHighlight_VS.glsl +++ b/Assets/Shaders/ShinyHighlight_VS.glsl @@ -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); diff --git a/Assets/Shaders/ShinyHighlight_VS.shshaderb b/Assets/Shaders/ShinyHighlight_VS.shshaderb index 98187085..95eac304 100644 Binary files a/Assets/Shaders/ShinyHighlight_VS.shshaderb and b/Assets/Shaders/ShinyHighlight_VS.shshaderb differ diff --git a/Assets/Shaders/TestCube_FS.glsl b/Assets/Shaders/TestCube_FS.glsl index 90b1922c..678ffb0e 100644 --- a/Assets/Shaders/TestCube_FS.glsl +++ b/Assets/Shaders/TestCube_FS.glsl @@ -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); } \ No newline at end of file diff --git a/Assets/Shaders/TestCube_FS.shshaderb b/Assets/Shaders/TestCube_FS.shshaderb index 2974523d..5374023a 100644 Binary files a/Assets/Shaders/TestCube_FS.shshaderb and b/Assets/Shaders/TestCube_FS.shshaderb differ diff --git a/Assets/Shaders/TestCube_VS.glsl b/Assets/Shaders/TestCube_VS.glsl index 1b45c333..07b89b6b 100644 --- a/Assets/Shaders/TestCube_VS.glsl +++ b/Assets/Shaders/TestCube_VS.glsl @@ -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); diff --git a/Assets/Shaders/TestCube_VS.shshaderb b/Assets/Shaders/TestCube_VS.shshaderb index 1bb76ec4..e607761c 100644 Binary files a/Assets/Shaders/TestCube_VS.shshaderb and b/Assets/Shaders/TestCube_VS.shshaderb differ diff --git a/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp b/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp index b671baf4..c655ff60 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp +++ b/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp @@ -485,6 +485,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 { diff --git a/SHADE_Engine/src/Events/SHEventDefines.h b/SHADE_Engine/src/Events/SHEventDefines.h index a7447be0..cdef68b9 100644 --- a/SHADE_Engine/src/Events/SHEventDefines.h +++ b/SHADE_Engine/src/Events/SHEventDefines.h @@ -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 }; diff --git a/SHADE_Engine/src/Graphics/Events/SHGraphicsEvents.h b/SHADE_Engine/src/Graphics/Events/SHGraphicsEvents.h index 51cd7aa2..e8f00c8a 100644 --- a/SHADE_Engine/src/Graphics/Events/SHGraphicsEvents.h +++ b/SHADE_Engine/src/Graphics/Events/SHGraphicsEvents.h @@ -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; + }; } diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp index a3573c15..bf2f1ec2 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp @@ -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,25 +141,28 @@ 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(VS_DEFAULT); - static constexpr AssetID VS_ANIM = 47911992; animtVertShader = SHResourceManager::LoadOrGet(VS_ANIM); - static constexpr AssetID FS_DEFAULT = 46377769; defaultFragShader = SHResourceManager::LoadOrGet(FS_DEFAULT); - static constexpr AssetID VS_DEBUG = 48002439; debugVertShader = SHResourceManager::LoadOrGet(VS_DEBUG); - static constexpr AssetID FS_DEBUG = 36671027; debugFragShader = SHResourceManager::LoadOrGet(FS_DEBUG); - static constexpr AssetID VS_DEBUG_MESH = 42127043; debugMeshVertShader = SHResourceManager::LoadOrGet(VS_DEBUG_MESH); - static constexpr AssetID CS_COMPOSITE = 45072428; deferredCompositeShader = SHResourceManager::LoadOrGet(CS_COMPOSITE); - static constexpr AssetID SSAO = 38430899; ssaoShader = SHResourceManager::LoadOrGet(SSAO); - static constexpr AssetID SSAO_BLUR = 39760835; ssaoBlurShader = SHResourceManager::LoadOrGet(SSAO_BLUR); - static constexpr AssetID TEXT_VS = 39816727; textVS = SHResourceManager::LoadOrGet(TEXT_VS); - static constexpr AssetID TEXT_FS = 38024754; textFS = SHResourceManager::LoadOrGet(TEXT_FS); - static constexpr AssetID RENDER_SC_VS = 48082949; renderToSwapchainVS = SHResourceManager::LoadOrGet(RENDER_SC_VS); - static constexpr AssetID RENDER_SC_FS = 36869006; renderToSwapchainFS = SHResourceManager::LoadOrGet(RENDER_SC_FS); - static constexpr AssetID SHADOW_MAP_VS = 44646107; shadowMapVS = SHResourceManager::LoadOrGet(SHADOW_MAP_VS); - static constexpr AssetID SHADOW_MAP_FS = 45925790; shadowMapFS = SHResourceManager::LoadOrGet(SHADOW_MAP_FS); - static constexpr AssetID TRAJECTORY_VS = 41042628; trajectoryVS = SHResourceManager::LoadOrGet(TRAJECTORY_VS); - static constexpr AssetID TRAJECTORY_FS = 45635685; trajectoryFS = SHResourceManager::LoadOrGet(TRAJECTORY_FS); + static constexpr AssetID VS_DEFAULT = 39210065; defaultVertShader = SHResourceManager::LoadOrGet(VS_DEFAULT); + static constexpr AssetID VS_ANIM = 47911992; animtVertShader = SHResourceManager::LoadOrGet(VS_ANIM); + static constexpr AssetID FS_DEFAULT = 46377769; defaultFragShader = SHResourceManager::LoadOrGet(FS_DEFAULT); + static constexpr AssetID VS_DEBUG = 48002439; debugVertShader = SHResourceManager::LoadOrGet(VS_DEBUG); + static constexpr AssetID FS_DEBUG = 36671027; debugFragShader = SHResourceManager::LoadOrGet(FS_DEBUG); + static constexpr AssetID VS_DEBUG_MESH = 42127043; debugMeshVertShader = SHResourceManager::LoadOrGet(VS_DEBUG_MESH); + static constexpr AssetID CS_COMPOSITE = 45072428; deferredCompositeShader = SHResourceManager::LoadOrGet(CS_COMPOSITE); + static constexpr AssetID SSAO = 38430899; ssaoShader = SHResourceManager::LoadOrGet(SSAO); + static constexpr AssetID SSAO_BLUR = 39760835; ssaoBlurShader = SHResourceManager::LoadOrGet(SSAO_BLUR); + static constexpr AssetID TEXT_VS = 39816727; textVS = SHResourceManager::LoadOrGet(TEXT_VS); + static constexpr AssetID TEXT_FS = 38024754; textFS = SHResourceManager::LoadOrGet(TEXT_FS); + static constexpr AssetID RENDER_SC_VS = 48082949; renderToSwapchainVS = SHResourceManager::LoadOrGet(RENDER_SC_VS); + static constexpr AssetID RENDER_SC_FS = 36869006; renderToSwapchainFS = SHResourceManager::LoadOrGet(RENDER_SC_FS); + static constexpr AssetID SHADOW_MAP_VS = 44646107; shadowMapVS = SHResourceManager::LoadOrGet(SHADOW_MAP_VS); + static constexpr AssetID SHADOW_MAP_FS = 45925790; shadowMapFS = SHResourceManager::LoadOrGet(SHADOW_MAP_FS); + static constexpr AssetID TRAJECTORY_VS = 41042628; trajectoryVS = SHResourceManager::LoadOrGet(TRAJECTORY_VS); + static constexpr AssetID TRAJECTORY_FS = 45635685; trajectoryFS = SHResourceManager::LoadOrGet(TRAJECTORY_FS); + static constexpr AssetID SHADOW_BLUR_CS = 38004013; shadowMapBlurCS = SHResourceManager::LoadOrGet(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 cmdBuffer, uint32_t frameIndex) { lightingSubSystem->PrepareShadowMapsForRead(cmdBuffer); @@ -534,12 +537,21 @@ namespace SHADE ReceiverPtr lightEnableShadowReceivePtr = std::dynamic_pointer_cast(lightEnableShadowReceiver); SHEventManager::SubscribeTo(SH_GRAPHICS_LIGHT_ENABLE_SHADOW_EVENT, lightEnableShadowReceivePtr); + std::shared_ptr> lightDeleteEvent + { + std::make_shared>(this, &SHGraphicsSystem::ReceiveLightDeleteEvent) + }; + ReceiverPtr lightDeleteReceivePtr = std::dynamic_pointer_cast(lightDeleteEvent); + SHEventManager::SubscribeTo(SH_GRAPHICS_LIGHT_DELETE_EVENT, lightDeleteReceivePtr); + + std::shared_ptr> compileAssetReceiever { std::make_shared>(this, &SHGraphicsSystem::ReceiveCompileAssetEvent) }; ReceiverPtr compileAssetReceivePtr = std::dynamic_pointer_cast(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(); - // //if (lightComps.size() > 2) - // //{ - // // lightComps[2].SetEnableShadow(true); - // //} - // for (auto& comp : lightComps) - // { - // comp.SetEnableShadow(true); - // } - //} - renderGraph->Begin(frameIndex); auto cmdBuffer = renderGraph->GetCommandBuffer(frameIndex); @@ -863,66 +859,121 @@ namespace SHADE } SHEventHandle SHGraphicsSystem::ReceiveLightEnableShadowEvent(SHEventPtr eventPtr) noexcept + { + auto const& EVENT_DATA = reinterpret_cast*>(eventPtr.get())->data; + auto* lightComp = SHComponentManager::GetComponent(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 gBufferWriteSubpass = renderGraph->GetNode(SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_PASS.data())->GetSubpass(SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_WRITE_SUBPASS); + Handle 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 newRenderer = resourceManager.Create(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 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 device->WaitIdle(); - auto const& EVENT_DATA = reinterpret_cast*>(eventPtr.get())->data; - auto* lightComp = SHComponentManager::GetComponent(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 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 newRenderer = resourceManager.Create(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 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 + auto const& EVENT_DATA = reinterpret_cast*>(eventPtr.get())->data; + auto* lightComp = SHComponentManager::GetComponent(EVENT_DATA->lightEntity); - // add the shadow map to the lighting system - uint32_t const NEW_SHADOW_MAP_INDEX = lightingSubSystem->AddShadowMap(renderGraph->GetRenderGraphResource(shadowMapResourceName), 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); + } - 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; } diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.h b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.h index 0b98f843..68752a6e 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.h @@ -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 shadowMapFS; Handle trajectoryVS; Handle trajectoryFS; + Handle shadowMapBlurCS; // Fonts Handle testFont; diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightComponent.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightComponent.cpp index 6943ec09..f8578647 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightComponent.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightComponent.cpp @@ -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(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(!renderer); - SHEventManager::BroadcastEvent(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(newEvent, SH_GRAPHICS_LIGHT_ENABLE_SHADOW_EVENT); } + } void SHLightComponent::SetRenderer(Handle 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) ; } diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightComponent.h b/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightComponent.h index 4974f3f5..a24b5ede 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightComponent.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightComponent.h @@ -69,6 +69,9 @@ namespace SHADE //uint32_t GetIndexInBuffer (void) const noexcept; float GetStrength (void) const noexcept; Handle GetRenderer (void) const noexcept; + bool GetEnableShadow (void) const noexcept; + uint32_t GetShadowMapIndex (void) const noexcept; + RTTR_ENABLE() }; } diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightingSubSystem.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightingSubSystem.cpp index cace495c..27685d69 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightingSubSystem.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightingSubSystem.cpp @@ -53,7 +53,8 @@ namespace SHADE SHVec4 transformedDir = SHMatrix::Transpose(viewMat) * SHVec4(lightData.direction[0], lightData.direction[1], lightData.direction[2], 0.0f); 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->diffuseColor = lightData.color; lightPtr->active = lightComp->isActive; @@ -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 newShadowMap, EntityID lightEntity) noexcept + uint32_t SHLightingSubSystem::AddShadowMap(Handle newShadowMapBlurred, EntityID lightEntity) noexcept { - // Add to container of shadow maps - shadowMapIndexing.emplace(lightEntity, static_cast (shadowMaps.size())); - shadowMaps.emplace_back(newShadowMap); + uint32_t usedIndex = 0; // Just use the image view stored in the resource - Handle 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(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 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 (shadowMaps.size())); + + usedIndex = static_cast(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(shadowMapImageSamplers.size()) - 1u; + return usedIndex; + } + + void SHLightingSubSystem::RemoveShadowMap(EntityID lightEntity) noexcept + { + auto* lightComp = SHComponentManager::GetComponent(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 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 compute) noexcept - //{ - // uint32_t const NUM_SHADOW_MAPS = static_cast(shadowMaps.size()); - // for (uint32_t i = 0; i < NUM_SHADOW_MAPS; ++i) - // { - // // Just use the image view stored in the resource - // Handle const NEW_IMAGE_VIEW = shadowMaps[i]->GetImageView(); - - // // set new image view - // std::get>(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 SHLightingSubSystem::GetLightDataDescriptorSet(void) const noexcept { return lightingDataDescSet; diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightingSubSystem.h b/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightingSubSystem.h index 69b00f2c..652b8226 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightingSubSystem.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightingSubSystem.h @@ -9,6 +9,7 @@ #include "Graphics/MiddleEnd/Interface/SHGraphicsConstants.h" #include "Graphics/RenderGraph/SHRenderGraphResource.h" #include "ECS_Base/SHECSMacros.h" +#include 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> 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 shadowMapDescriptorSet; - //! Combined image samplers for the texture descriptors std::vector, Handle, vk::ImageLayout>> shadowMapImageSamplers; @@ -191,6 +191,9 @@ namespace SHADE //! to VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) std::vector shadowMapMemoryBarriers; + //! recycled indices after deleting lights with shadows + std::stack recyclableIndices; + //! Resource hub from Graphics System SHResourceHub* resourceHub; @@ -209,12 +212,14 @@ namespace SHADE /*-----------------------------------------------------------------------*/ /* PUBLIC MEMBER FUNCTIONS */ /*-----------------------------------------------------------------------*/ - void Init (Handle device, Handle descPool, SHResourceHub* rh, Handle inShadowMapSampler) noexcept; - void Run (SHMatrix const& viewMat, uint32_t frameIndex) noexcept; - void Exit (void) noexcept; - void BindDescSet (Handle cmdBuffer, uint32_t setIndex, uint32_t frameIndex) noexcept; - uint32_t AddShadowMap (Handle newShadowMap, EntityID lightEntity) noexcept; - void PrepareShadowMapsForRead (Handle cmdBuffer) noexcept; + void Init (Handle device, Handle descPool, SHResourceHub* rh, Handle inShadowMapSampler) noexcept; + void Run (SHMatrix const& viewMat, uint32_t frameIndex) noexcept; + void Exit (void) noexcept; + void BindDescSet (Handle cmdBuffer, uint32_t setIndex, uint32_t frameIndex) noexcept; + uint32_t AddShadowMap (Handle newShadowMapBlurred, EntityID lightEntity) noexcept; + void RemoveShadowMap (EntityID lightEntity) noexcept; + void RecycleShadowMapIndex (SHLightComponent* lightComp) noexcept; + void PrepareShadowMapsForRead (Handle cmdBuffer) noexcept; //void HandleResize (Handle compute) noexcept; //void RemoveShadowMap (uint32_t index) noexcept; diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp index e4e6889c..34206e5b 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp @@ -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 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 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(nodeName, renderGraphStorage, std::move(descInitParams), std::vector>())); + auto node = nodes.insert(targetNode, renderGraphStorage->resourceHub->Create(nodeName, renderGraphStorage, std::move(descInitParams), std::vector>(), 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 diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.h b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.h index 0ae30015..42d829b0 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.h +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.h @@ -112,6 +112,7 @@ namespace SHADE ); void RemoveResource (std::string resourceName) noexcept; + void RemoveNode (std::string nodeName) noexcept; void LinkNonOwningResource ( diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.cpp b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.cpp index 34bfe8cd..53363a63 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.cpp +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.cpp @@ -292,7 +292,7 @@ namespace SHADE */ /***************************************************************************/ - SHRenderGraphNode::SHRenderGraphNode(std::string nodeName, Handle renderGraphStorage, std::vector attDescInitParams, std::vector> predecessors) noexcept + SHRenderGraphNode::SHRenderGraphNode(std::string nodeName, Handle renderGraphStorage, std::vector attDescInitParams, std::vector> 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{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; + } + } \ No newline at end of file diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.h b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.h index b070b8fa..971a84ae 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.h +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.h @@ -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 renderGraphStorage, std::vector attDescInitParams, std::vector> predecessors) noexcept; + SHRenderGraphNode(std::string nodeName, Handle renderGraphStorage, std::vector attDescInitParams, std::vector> 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 */ /*-----------------------------------------------------------------------*/ - Handle GetRenderpass(void) const noexcept; - Handle GetSubpass(std::string_view subpassName) const noexcept; - Handle GetResource (uint32_t resourceIndex) const noexcept; + void SetDynamicActive(bool active) noexcept; + + Handle GetRenderpass(void) const noexcept; + Handle GetSubpass(std::string_view subpassName) const noexcept; + Handle GetResource (uint32_t resourceIndex) const noexcept; std::vector> const& GetResources (void) const noexcept; - Handle GetNodeCompute (std::string nodeComputeName) const noexcept; + Handle GetNodeCompute (std::string nodeComputeName) const noexcept; + bool GetDynamicActive (void) const noexcept; + friend class SHRenderGraph; }; diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.cpp b/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.cpp index 14a5d864..ca13155d 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.cpp +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.cpp @@ -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 { - // if not bind pipeline for companion and and execute draw command - commandBuffer->BindPipeline(companionSubpass.pipeline); - companionSubpass.companion->superBatch->Draw(commandBuffer, frameIndex, false); + for (auto& companion : companionSubpasses) + { + // 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; } - void SHSubpass::SetCompanionSubpass(Handle companion, Handle pipeline) noexcept + void SHSubpass::AddCompanionSubpass(Handle companion, Handle pipeline) noexcept { - companionSubpass.companion = companion; - companionSubpass.pipeline = pipeline; + companionSubpasses.push_back(CompanionSubpass{companion, pipeline}); + //companionSubpass.companion = companion; + //companionSubpass.pipeline = pipeline; } /***************************************************************************/ diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.h b/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.h index 1300ee2b..7f843773 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.h +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.h @@ -33,7 +33,7 @@ namespace SHADE struct CompanionSubpass { // subpass whose data will be borrowed to draw - Handle companion; + Handle subpass; // Pipeline that will be used for all the draw calls from all batches of the companion subpass Handle 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 companionSubpasses; private: /*-----------------------------------------------------------------------*/ @@ -129,6 +130,7 @@ namespace SHADE SHSubpass(const std::string& name, Handle inViewport, Handle inRenderer, Handle renderGraphStorage, Handle const& parent, uint32_t index, std::unordered_map 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 companion, Handle pipeline) noexcept; + void AddCompanionSubpass (Handle companion, Handle pipeline) noexcept; Handle GetParentNode(void) const noexcept; SHSubPassIndex GetIndex() const noexcept;