From 19f9b67550a53b8e2f660e59053a86a42882c64c Mon Sep 17 00:00:00 2001 From: Brandon Mak Date: Fri, 6 Jan 2023 10:40:19 +0800 Subject: [PATCH] Shadow map WIP - Added companion subpass object to subpass - Lighting sub system updates a light's renderer when it is a valid handle - Light component's renderer will be created in the graphics system event when a light's shadow is enabled --- Assets/Shaders/ShadowMap_VS.glsl | 21 +++++++++++ .../src/Graphics/Events/SHGraphicsEvents.h | 3 ++ .../MiddleEnd/Interface/SHGraphicsSystem.cpp | 26 +++++++++++-- .../Graphics/MiddleEnd/Interface/SHRenderer.h | 2 +- .../MiddleEnd/Lights/SHLightComponent.cpp | 13 +++++++ .../MiddleEnd/Lights/SHLightComponent.h | 7 ++++ .../MiddleEnd/Lights/SHLightingSubSystem.cpp | 37 ++++++++++++++++++- .../MiddleEnd/Lights/SHLightingSubSystem.h | 7 +++- .../RenderGraph/SHRenderGraphNode.cpp | 4 +- .../Graphics/RenderGraph/SHRenderGraphNode.h | 2 +- .../src/Graphics/RenderGraph/SHSubpass.cpp | 6 +++ .../src/Graphics/RenderGraph/SHSubpass.h | 35 ++++++++++++++---- 12 files changed, 144 insertions(+), 19 deletions(-) create mode 100644 Assets/Shaders/ShadowMap_VS.glsl diff --git a/Assets/Shaders/ShadowMap_VS.glsl b/Assets/Shaders/ShadowMap_VS.glsl new file mode 100644 index 00000000..bf353eb5 --- /dev/null +++ b/Assets/Shaders/ShadowMap_VS.glsl @@ -0,0 +1,21 @@ +#version 450 +#extension GL_KHR_vulkan_glsl : enable + +//#include "ShaderDescriptorDefinitions.glsl" + + +layout(location = 0) in vec3 aVertexPos; + +layout(set = 1, binding = 0) uniform CameraData +{ + vec4 position; + mat4 vpMat; + mat4 viewMat; + mat4 projMat; +} cameraData; + +void main() +{ + // clip space for rendering + gl_Position = cameraData.vpMat * worldTransform * vec4 (aVertexPos, 1.0f); +} \ No newline at end of file diff --git a/SHADE_Engine/src/Graphics/Events/SHGraphicsEvents.h b/SHADE_Engine/src/Graphics/Events/SHGraphicsEvents.h index ab120a1f..06c480ef 100644 --- a/SHADE_Engine/src/Graphics/Events/SHGraphicsEvents.h +++ b/SHADE_Engine/src/Graphics/Events/SHGraphicsEvents.h @@ -10,5 +10,8 @@ namespace SHADE { //! We need to get the light component and initialize the relevant variables. EntityID lightEntity; + + //! Generate a renderer for the light component + bool generateRenderer; }; } diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp index 19a24e0c..19ad5473 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp @@ -46,6 +46,7 @@ of DigiPen Institute of Technology is prohibited. #include "Graphics/MiddleEnd/GlobalData/SHGlobalDescriptorSets.h" #include "Events/SHEvent.h" #include "Graphics/MiddleEnd/Lights/SHLightComponent.h" +#include "Input/SHInputManager.h" namespace SHADE { @@ -400,7 +401,7 @@ namespace SHADE postOffscreenRenderSubSystem->Init(device, renderGraph->GetRenderGraphResource("Scene"), descPool); lightingSubSystem = resourceManager.Create(); - lightingSubSystem->Init(device, descPool, samplerCache.GetSampler (device, SHVkSamplerParams + lightingSubSystem->Init(device, descPool, &resourceManager, samplerCache.GetSampler (device, SHVkSamplerParams { // nothing for now }) @@ -557,6 +558,15 @@ namespace SHADE #endif } + if (SHInputManager::GetKeyDown(SHInputManager::SH_KEYCODE::B)) + { + auto& lightComps = SHComponentManager::GetDense(); + for (auto& comp : lightComps) + { + comp.SetEnableShadow(true); + } + } + renderGraph->Begin(frameIndex); auto cmdBuffer = renderGraph->GetCommandBuffer(frameIndex); @@ -746,18 +756,26 @@ namespace SHADE auto* lightComp = SHComponentManager::GetComponent(EVENT_DATA->lightEntity); std::string resourceName = "ShadowMap " + std::to_string(EVENT_DATA->lightEntity); + 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); + } + // Add the shadow map resource to the graph - renderGraph->AddResource(resourceName, {SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE}, resizeWidth, resizeHeight, vk::Format::eD24UnormS8Uint); + renderGraph->AddResource(resourceName, {SH_RENDER_GRAPH_RESOURCE_FLAGS::DEPTH_STENCIL, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT}, resizeWidth, resizeHeight, vk::Format::eD24UnormS8Uint); // link resource to node. This means linking the resource and regenerating the node's renderpass and framebuffer. auto shadowMapNode = renderGraph->GetNode(SHGraphicsConstants::RenderGraphNodeNames::SHADOW_MAP_PASS.data()); shadowMapNode->RuntimeLinkResource(resourceName); // Add a subpass to render to that shadow map - shadowMapNode->RuntimeAddSubpass(resourceName + " Subpass", worldViewport, worldRenderer); + auto newSubpass = shadowMapNode->RuntimeAddSubpass(resourceName + " Subpass", worldViewport, lightComp->GetRenderer()); + newSubpass->AddDepthOutput(resourceName, SH_RENDER_GRAPH_RESOURCE_FLAGS::DEPTH_STENCIL); // regenerate the node - //shadowMapNode->RuntimeStandaloneRegenerate(); + shadowMapNode->RuntimeStandaloneRegenerate(); return eventPtr->handle; } diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderer.h b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderer.h index baf76187..a17ab1a9 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderer.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderer.h @@ -18,9 +18,9 @@ of DigiPen Institute of Technology is prohibited. // Project Includes #include "SHCamera.h" #include "Resource/SHHandle.h" -#include "Graphics/RenderGraph/SHRenderGraph.h" #include "Math/SHMath.h" #include +#include "Graphics/Pipeline/SHPipelineType.h" namespace SHADE { diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightComponent.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightComponent.cpp index 362b0e8f..4dc6e83e 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightComponent.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightComponent.cpp @@ -2,6 +2,7 @@ #include "SHLightComponent.h" #include "Graphics/Events/SHGraphicsEvents.h" #include "Events/SHEventManager.hpp" +#include "Graphics/MiddleEnd/Interface/SHRenderer.h" namespace SHADE { @@ -14,6 +15,7 @@ namespace SHADE //indexInBuffer = std::numeric_limits::max(); isActive = true; //Unbind(); + renderer = {}; } @@ -116,11 +118,17 @@ namespace SHADE // Create new event and broadcast it SHLightEnableShadowEvent newEvent; newEvent.lightEntity = GetEID(); + newEvent.generateRenderer = static_cast(!renderer); SHEventManager::BroadcastEvent(newEvent, SH_GRAPHICS_LIGHT_ENABLE_SHADOW_EVENT); } } + void SHLightComponent::SetRenderer(Handle newRenderer) noexcept + { + renderer = newRenderer; + } + SHLightData const& SHLightComponent::GetLightData(void) const noexcept { return lightData; @@ -172,6 +180,11 @@ namespace SHADE return lightData.strength; } + Handle SHLightComponent::GetRenderer(void) const noexcept + { + return renderer; + } + } RTTR_REGISTRATION diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightComponent.h b/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightComponent.h index 1d636595..4019d2f4 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightComponent.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightComponent.h @@ -3,9 +3,11 @@ #include #include "ECS_Base/Components/SHComponent.h" #include "SHLightData.h" +#include "Resource/SHHandle.h" namespace SHADE { + class SHRenderer; class SH_API SHLightComponent final : public SHComponent { @@ -14,6 +16,9 @@ namespace SHADE //! GPU depends on the type of the light. SHLightData lightData; + //! Renderer to calculate light world to projection matrix + Handle renderer; + //! Since the lighting system is gonna be self contained and light weight, we store this //! so that we only write this to the CPU buffer when this light component change, we don't //! rewrite everything. However we still write to the GPU buffer when everything changes. @@ -49,6 +54,7 @@ namespace SHADE //void SetBound (uint32_t inIndexInBuffer) noexcept; void SetStrength (float value) noexcept; // serialized void SetEnableShadow (bool flag) noexcept; + void SetRenderer (Handle newRenderer) noexcept; SHLightData const& GetLightData (void) const noexcept; @@ -61,6 +67,7 @@ namespace SHADE //bool GetBound (void) const noexcept; //uint32_t GetIndexInBuffer (void) const noexcept; float GetStrength (void) const noexcept; + Handle GetRenderer (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 997fe68a..31512f9b 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightingSubSystem.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightingSubSystem.cpp @@ -13,6 +13,9 @@ #include "Graphics/Images/SHVkImageView.h" #include "Graphics/MiddleEnd/Textures/SHVkSamplerCache.h" #include "Graphics/Images/SHVkSampler.h" +#include "Graphics/Events/SHGraphicsEvents.h" +#include "Graphics/MiddleEnd/Interface/SHRenderer.h" +#include "Math/Transform/SHTransformComponent.h" namespace SHADE { @@ -373,6 +376,27 @@ namespace SHADE } + SHMatrix SHLightingSubSystem::GetViewMatrix(SHLightComponent* lightComp) noexcept + { + SHTransformComponent* transform = SHComponentManager::GetComponent(lightComp->GetEID()); + switch (lightComp->GetLightData().type) + { + case SH_LIGHT_TYPE::DIRECTIONAL: + return SHMatrix::LookAtRH(transform->GetLocalPosition(), lightComp->GetLightData().position, SHVec3(0.0f, 1.0f, 0.0f)); + case SH_LIGHT_TYPE::POINT: + return {}; + case SH_LIGHT_TYPE::SPOT: + return {}; + case SH_LIGHT_TYPE::AMBIENT: + return {}; + case SH_LIGHT_TYPE::NUM_TYPES: + return {}; + default: + return {}; + + } + } + /***************************************************************************/ /*! @@ -383,11 +407,12 @@ namespace SHADE */ /***************************************************************************/ - void SHLightingSubSystem::Init(Handle device, Handle descPool, Handle inShadowMapSampler) noexcept + void SHLightingSubSystem::Init(Handle device, Handle descPool, SHResourceHub* rh, Handle inShadowMapSampler) noexcept { SHComponentManager::CreateComponentSparseSet(); logicalDevice = device; + resourceHub = rh; uint32_t constexpr NUM_LIGHT_TYPES = SHUtilities::ConvertEnum(SH_LIGHT_TYPE::NUM_TYPES); #pragma region LIGHTING @@ -496,6 +521,14 @@ namespace SHADE // Light is now updated in the container //light.ClearDirtyFlag(); } + + + if (auto renderer = light.GetRenderer()) + { + //SHMatrix orthoMatrix = SHMatrix::OrthographicRH() + renderer->UpdateDataManual (frameIndex, GetViewMatrix(&light), SHMatrix::OrthographicRH(80.0f, 80.0f, 0.01f, 10000.0f)); + + } } // Write data to GPU @@ -561,7 +594,7 @@ namespace SHADE // Update descriptor set static constexpr uint32_t SHADOW_MAP_DESC_SET_INDEX = 0; - uint32_t const SHADOW_MAP_DESC_ARRAY_INDEX = shadowMapImageSamplers.size() - 1; + uint32_t const SHADOW_MAP_DESC_ARRAY_INDEX = static_cast(shadowMapImageSamplers.size()) - 1u; shadowMapDescriptorSet->ModifyWriteDescImage ( SHADOW_MAP_DESC_SET_INDEX, diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightingSubSystem.h b/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightingSubSystem.h index 65b58174..320c18b7 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightingSubSystem.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightingSubSystem.h @@ -178,6 +178,10 @@ namespace SHADE //! to VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) std::vector shadowMapMemoryBarriers; + //! Resource hub from Graphics System + SHResourceHub* resourceHub; + + /*-----------------------------------------------------------------------*/ /* PRIVATE MEMBER FUNCTIONS */ /*-----------------------------------------------------------------------*/ @@ -185,13 +189,14 @@ namespace SHADE void ComputeDynamicOffsets (void) noexcept; void ResetNumLights (void) noexcept; void UpdateShadowMapDesc (void) noexcept; + SHMatrix GetViewMatrix (SHLightComponent* lightComp) noexcept; public: /*-----------------------------------------------------------------------*/ /* PUBLIC MEMBER FUNCTIONS */ /*-----------------------------------------------------------------------*/ - void Init (Handle device, Handle descPool, Handle inShadowMapSampler) 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; diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.cpp b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.cpp index cf4623e6..2f498d5a 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.cpp +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.cpp @@ -743,9 +743,9 @@ namespace SHADE resourceAttachmentMapping->try_emplace(newResource.GetId().Raw, attachmentDescriptions.size() - 1); } - void SHRenderGraphNode::RuntimeAddSubpass(std::string subpassName, Handle viewport, Handle renderer) noexcept + Handle SHRenderGraphNode::RuntimeAddSubpass(std::string subpassName, Handle viewport, Handle renderer) noexcept { - AddSubpass(std::move (subpassName), viewport, renderer); + return AddSubpass(std::move (subpassName), viewport, renderer); } /***************************************************************************/ diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.h b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.h index 8744184f..27fdaa19 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.h +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.h @@ -117,7 +117,7 @@ namespace SHADE // Runtime functions that don't affect the renderpass void RuntimeLinkResource(std::string resourceName) noexcept; - void RuntimeAddSubpass(std::string subpassName, Handle viewport, Handle renderer) noexcept; + Handle RuntimeAddSubpass(std::string subpassName, Handle viewport, Handle renderer) noexcept; void RuntimeStandaloneRegenerate (void) noexcept; /*-----------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.cpp b/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.cpp index c7982906..cd5bae58 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.cpp +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.cpp @@ -443,6 +443,12 @@ namespace SHADE subpassIndex = index; } + void SHSubpass::SetCompanionSubpass(Handle companion, Handle pipeline) noexcept + { + 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 7f1bd3da..f84d4dee 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.h +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.h @@ -21,12 +21,23 @@ namespace SHADE class SHVkSampler; class SHRenderer; class SHViewport; + class SHVkPipeline; class SH_API SHSubpass : public ISelfHandle { public: using ExteriorDrawCallFunction = std::function, Handle, uint32_t)>; + // Allows for subpasses to run using a companions data + struct CompanionSubpass + { + // subpass whose data will be borrowed to draw + Handle companion; + + // Pipeline that will be used for all the draw calls from all batches of the companion subpass + Handle pipeline; + }; + private: /*---------------------------------------------------------------------*/ /* PRIVATE MEMBER VARIABLES */ @@ -94,6 +105,9 @@ namespace SHADE // For identifying subpasses std::string name; + //! 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; private: /*-----------------------------------------------------------------------*/ @@ -133,19 +147,24 @@ namespace SHADE void CreateInputDescriptors (void) noexcept; void UpdateWriteDescriptors (void) noexcept; - /*-----------------------------------------------------------------------*/ - /* GETTERS AND SETTERS */ - /*-----------------------------------------------------------------------*/ private: + /*-----------------------------------------------------------------------*/ + /* PRIVATE GETTERS AND SETTERS */ + /*-----------------------------------------------------------------------*/ void SetIndex (uint32_t index) noexcept; public: - Handle const& GetParentNode(void) const noexcept; - SHSubPassIndex GetIndex() const noexcept; - Handle GetSuperBatch(void) const noexcept; + /*-----------------------------------------------------------------------*/ + /* PUBLIC SETTERS AND GETTERS */ + /*-----------------------------------------------------------------------*/ + void SetCompanionSubpass (Handle companion, Handle pipeline) noexcept; + + Handle const& GetParentNode(void) const noexcept; + SHSubPassIndex GetIndex() const noexcept; + Handle GetSuperBatch(void) const noexcept; std::vector const& GetColorAttachmentReferences (void) const noexcept; - vk::Format GetFormatFromAttachmentReference (uint32_t attachmentReference) const noexcept; - const std::string& GetName() const; + vk::Format GetFormatFromAttachmentReference (uint32_t attachmentReference) const noexcept; + const std::string& GetName() const; friend class SHRenderGraphNode; friend class SHRenderGraph;