diff --git a/Assets/Scenes/MainGame.shade b/Assets/Scenes/MainGame.shade index 53b5a0a0..f1b16c1b 100644 --- a/Assets/Scenes/MainGame.shade +++ b/Assets/Scenes/MainGame.shade @@ -8440,6 +8440,11 @@ IsActive: true NumberOfChildren: 0 Components: + Transform Component: + Translate: {x: 0, y: 0, z: 0} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true Light Component: Position: {x: 0, y: 0, z: 0} Type: Directional @@ -8469,14 +8474,14 @@ NumberOfChildren: 0 Components: Transform Component: - Translate: {x: 2, y: 1.5, z: -5.5999999} + Translate: {x: 0.242245644, y: 1.56757355, z: -6.07086945} Rotate: {x: -0, y: 0, z: -0} Scale: {x: 1, y: 1, z: 1} IsActive: true Light Component: Position: {x: 2, y: 1.5, z: -5.5999999} Type: Directional - Direction: {x: -0.245000005, y: 0, z: 0} + Direction: {x: 0, y: 0, z: -1} Color: {x: 0, y: 0, z: 0, w: 1} Layer: 4294967295 Strength: 1 diff --git a/Assets/Scripts/StaticTest.cs b/Assets/Scripts/StaticTest.cs new file mode 100644 index 00000000..a382a96e --- /dev/null +++ b/Assets/Scripts/StaticTest.cs @@ -0,0 +1,37 @@ +using SHADE; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SHADE_Scripting +{ + public class StaticTest + { + public static int x; + + static StaticTest() + { + x = 5; + Debug.Log("Static Constructor!"); + } + } + + public class ImplicitStaticTest : Script + { + public static int x = 5; + + static ImplicitStaticTest() + { + Debug.Log("Static Constructor!"); + } + + protected override void awake() + { + Debug.LogWarning($"Before Add: x = {x}"); + ++x; + Debug.LogWarning($"After Add: x = {x}"); + } + } +} diff --git a/Assets/Scripts/StaticTest.cs.shmeta b/Assets/Scripts/StaticTest.cs.shmeta new file mode 100644 index 00000000..2da681fa --- /dev/null +++ b/Assets/Scripts/StaticTest.cs.shmeta @@ -0,0 +1,3 @@ +Name: StaticTest +ID: 159057282 +Type: 9 diff --git a/Assets/Shaders/DeferredComposite_CS.glsl b/Assets/Shaders/DeferredComposite_CS.glsl index 50a269ac..745b93e0 100644 --- a/Assets/Shaders/DeferredComposite_CS.glsl +++ b/Assets/Shaders/DeferredComposite_CS.glsl @@ -48,19 +48,34 @@ layout(std430, set = 1, binding = 4) buffer AmbientLightData AmbientLightStruct aLightData[]; } AmbLightData; +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) { + // clip space for fragment from light view space vec4 fragPosLightPOV = lightPV * worldSpaceFragPos; + + // Perform perspective division and convert to 0 to 1 range vec3 converted = (fragPosLightPOV.xyz / fragPosLightPOV.w) * vec3(0.5f) + vec3(0.5f); - float sampledDepth = texture(shadowMap, converted.xy).r; + // float sampledDepth = texture(shadowMap, converted.xy).r; + // float sampledDepth = texture(shadowMap, converted.xy).z; + vec2 moments = texture(shadowMap, converted.xy).xy; if (converted.x < 0.0f || converted.x > 1.0f || converted.y < 0.0f || converted.y > 1.0f) return 1.0f; - if (fragPosLightPOV.z > sampledDepth && fragPosLightPOV.w > 0.0f) + if (fragPosLightPOV.z > moments.x && fragPosLightPOV.w > 0.0f) { - return 0.7f; + float p = step (fragPosLightPOV.z, moments.x); + float variance = max (moments.y - (moments.x * moments.x), 0.00002f); + + float d = fragPosLightPOV.z - moments.x; + float pMax = LinStep (variance / (variance + (d * d)), 0.9f, 1.0f); + return min (max (p, pMax), 1.0f); } else return 1.0f; diff --git a/Assets/Shaders/DeferredComposite_CS.shshaderb b/Assets/Shaders/DeferredComposite_CS.shshaderb index 7f06b471..ff474e27 100644 Binary files a/Assets/Shaders/DeferredComposite_CS.shshaderb and b/Assets/Shaders/DeferredComposite_CS.shshaderb differ diff --git a/Assets/Shaders/ShadowMap_FS.glsl b/Assets/Shaders/ShadowMap_FS.glsl index f514c70b..b19a32a6 100644 --- a/Assets/Shaders/ShadowMap_FS.glsl +++ b/Assets/Shaders/ShadowMap_FS.glsl @@ -3,8 +3,10 @@ #extension GL_ARB_shading_language_420pack : enable #extension GL_EXT_nonuniform_qualifier : require +layout(location = 0) out vec4 shadowMap; void main() { - + // 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); } \ No newline at end of file diff --git a/Assets/Shaders/ShadowMap_FS.shshaderb b/Assets/Shaders/ShadowMap_FS.shshaderb index 45304832..709a2ecc 100644 Binary files a/Assets/Shaders/ShadowMap_FS.shshaderb and b/Assets/Shaders/ShadowMap_FS.shshaderb differ diff --git a/Assets/Shaders/Trajectory_FS.glsl b/Assets/Shaders/Trajectory_FS.glsl new file mode 100644 index 00000000..4e36dfd9 --- /dev/null +++ b/Assets/Shaders/Trajectory_FS.glsl @@ -0,0 +1,22 @@ +#version 450 +#extension GL_ARB_separate_shader_objects : enable +#extension GL_ARB_shading_language_420pack : enable +#extension GL_EXT_nonuniform_qualifier : require + + +layout(location = 0) in struct +{ + vec4 vertPos; // location 0 + vec2 uv; // location = 1 + vec4 color; // location = 2 + +} In; + +layout(location = 0) out vec4 fragColor; + + +void main() +{ + // default red first + fragColor = In.color; +} \ No newline at end of file diff --git a/Assets/Shaders/Trajectory_FS.shshaderb b/Assets/Shaders/Trajectory_FS.shshaderb new file mode 100644 index 00000000..9e641866 Binary files /dev/null and b/Assets/Shaders/Trajectory_FS.shshaderb differ diff --git a/Assets/Shaders/Trajectory_FS.shshaderb.shmeta b/Assets/Shaders/Trajectory_FS.shshaderb.shmeta new file mode 100644 index 00000000..296c38c9 --- /dev/null +++ b/Assets/Shaders/Trajectory_FS.shshaderb.shmeta @@ -0,0 +1,3 @@ +Name: Trajectory_FS +ID: 45635685 +Type: 2 diff --git a/Assets/Shaders/Trajectory_VS.glsl b/Assets/Shaders/Trajectory_VS.glsl new file mode 100644 index 00000000..86be6b7e --- /dev/null +++ b/Assets/Shaders/Trajectory_VS.glsl @@ -0,0 +1,36 @@ +#version 450 +#extension GL_KHR_vulkan_glsl : enable + +// vertex inputs +layout(location = 0) in vec3 aPos; +layout(location = 1) in vec2 aUV; +layout(location = 2) in vec4 aColor; +layout(location = 3) in mat4 aTransform; + +// between shader stages +layout(location = 0) out struct +{ + vec4 vertPos; // location 0 + vec2 uv; // location = 1 + vec4 color; // location = 2 + +} Out; + + +// Camera data +layout(set = 1, binding = 0) uniform CameraData +{ + vec4 position; + mat4 vpMat; + mat4 viewMat; + mat4 projMat; +} cameraData; + + +void main() +{ + Out.uv = aUV; + Out.color = aColor; + + gl_Position = cameraData.projMat * aTransform * vec4(aPos, 1.0f); +} \ No newline at end of file diff --git a/Assets/Shaders/Trajectory_VS.shshaderb b/Assets/Shaders/Trajectory_VS.shshaderb new file mode 100644 index 00000000..6f509f5c Binary files /dev/null and b/Assets/Shaders/Trajectory_VS.shshaderb differ diff --git a/Assets/Shaders/Trajectory_VS.shshaderb.shmeta b/Assets/Shaders/Trajectory_VS.shshaderb.shmeta new file mode 100644 index 00000000..74584b44 --- /dev/null +++ b/Assets/Shaders/Trajectory_VS.shshaderb.shmeta @@ -0,0 +1,3 @@ +Name: Trajectory_VS +ID: 41042628 +Type: 2 diff --git a/SHADE_Engine/src/Camera/SHCameraComponent.cpp b/SHADE_Engine/src/Camera/SHCameraComponent.cpp index 8b2f50d9..17378d79 100644 --- a/SHADE_Engine/src/Camera/SHCameraComponent.cpp +++ b/SHADE_Engine/src/Camera/SHCameraComponent.cpp @@ -254,7 +254,8 @@ RTTR_REGISTRATION .property("Height", &SHCameraComponent::GetHeight, &SHCameraComponent::SetHeight) .property("Near", &SHCameraComponent::GetNear, &SHCameraComponent::SetNear) .property("Far", &SHCameraComponent::GetFar, &SHCameraComponent::SetFar) - .property("Perspective", &SHCameraComponent::GetIsPerspective, &SHCameraComponent::SetIsPerspective); + .property("Perspective", &SHCameraComponent::GetIsPerspective, &SHCameraComponent::SetIsPerspective) + .property("FOV",&SHCameraComponent::GetFOV, &SHCameraComponent::SetFOV); } diff --git a/SHADE_Engine/src/Camera/SHCameraSystem.cpp b/SHADE_Engine/src/Camera/SHCameraSystem.cpp index d508fc09..59ba7ce9 100644 --- a/SHADE_Engine/src/Camera/SHCameraSystem.cpp +++ b/SHADE_Engine/src/Camera/SHCameraSystem.cpp @@ -12,6 +12,7 @@ #include "Editor/SHEditor.h" #include "Math/SHRay.h" #include "Physics/System/SHPhysicsSystem.h" +#include "Graphics/Events/SHGraphicsEvents.h" namespace SHADE @@ -122,6 +123,13 @@ namespace SHADE SHComponentManager::CreateComponentSparseSet(); SHComponentManager::CreateComponentSparseSet(); + + std::shared_ptr> thisReceiver + { + std::make_shared>(this, &SHCameraSystem::ReceiveWindowResizeEvent) + }; + ReceiverPtr receiver = std::dynamic_pointer_cast(thisReceiver); + SHEventManager::SubscribeTo(SH_WINDOW_RESIZE_EVENT, receiver); } @@ -130,6 +138,29 @@ namespace SHADE } + SHEventHandle SHCameraSystem::ReceiveWindowResizeEvent(SHEventPtr eventPtr) noexcept + { + auto const& EVENT_DATA = reinterpret_cast*>(eventPtr.get())->data; + + //std::cout << EVENT_DATA->resizeWidth << std::endl; + //std::cout << EVENT_DATA->resizeHeight << std::endl; + + + for (auto director : directorHandleList) + { + auto camera = SHComponentManager::GetComponent_s(director->mainCameraEID); + if (camera) + { + camera->SetWidth(EVENT_DATA->resizeWidth); + camera->SetHeight(EVENT_DATA->resizeHeight); + } + + } + + + return eventPtr->handle; + } + SHCameraComponent* SHCameraSystem::GetEditorCamera(void) noexcept { return &editorCamera; @@ -204,8 +235,8 @@ namespace SHADE //SHLOG_INFO("CAMERA COLLISION HIT, {} armlength: {}, true armlength: {}", hitResult.distance, hitResult.distance, (cameraPos - camera->position).Length()); //SHLOG_INFO("Racoon Position {}, {}, {}, Camera Position: {}, {}, {}, Distance {}", cameraTarget.x, cameraTarget.y, cameraTarget.z, cameraPos.x, cameraPos.y, cameraPos.z, SHVec3::Distance(cameraTarget, cameraPos)); //SHLOG_INFO("Camera Position: {}, {}, {}", cameraPos.x, cameraPos.y, cameraPos.z); - auto otherTransform = SHComponentManager::GetComponent_s(hitResult.entityHit); - SHVec3 otherPos = hitResult.position; + //auto otherTransform = SHComponentManager::GetComponent_s(hitResult.entityHit); + //SHVec3 otherPos = hitResult.position; diff --git a/SHADE_Engine/src/Camera/SHCameraSystem.h b/SHADE_Engine/src/Camera/SHCameraSystem.h index baf0ed09..4d6476bf 100644 --- a/SHADE_Engine/src/Camera/SHCameraSystem.h +++ b/SHADE_Engine/src/Camera/SHCameraSystem.h @@ -46,6 +46,11 @@ namespace SHADE }; friend class CameraSystemUpdate; + /*-----------------------------------------------------------------------*/ + /* Light functions */ + /*-----------------------------------------------------------------------*/ + SHEventHandle ReceiveWindowResizeEvent(SHEventPtr eventPtr) noexcept; + SHCameraComponent* GetEditorCamera (void) noexcept; void GetCameraAxis(SHCameraComponent const& camera, SHVec3& forward, SHVec3& right, SHVec3& up) const noexcept; diff --git a/SHADE_Engine/src/Events/SHEventDefines.h b/SHADE_Engine/src/Events/SHEventDefines.h index e2fcba10..fa5bcafb 100644 --- a/SHADE_Engine/src/Events/SHEventDefines.h +++ b/SHADE_Engine/src/Events/SHEventDefines.h @@ -25,4 +25,5 @@ constexpr SHEventIdentifier SH_SCENE_EXIT_POST { 16 }; constexpr SHEventIdentifier SH_GRAPHICS_LIGHT_ENABLE_SHADOW_EVENT { 17 }; constexpr SHEventIdentifier SH_BUTTON_CLICK_EVENT { 18 }; constexpr SHEventIdentifier SH_PHYSICS_COLLIDER_DRAW_EVENT { 19 }; +constexpr SHEventIdentifier SH_WINDOW_RESIZE_EVENT { 20 }; diff --git a/SHADE_Engine/src/Graphics/Events/SHGraphicsEvents.h b/SHADE_Engine/src/Graphics/Events/SHGraphicsEvents.h index 06c480ef..51cd7aa2 100644 --- a/SHADE_Engine/src/Graphics/Events/SHGraphicsEvents.h +++ b/SHADE_Engine/src/Graphics/Events/SHGraphicsEvents.h @@ -14,4 +14,13 @@ namespace SHADE //! Generate a renderer for the light component bool generateRenderer; }; + + struct SHWindowResizeEvent + { + // New width when window resizes + uint32_t resizeWidth; + + // New height when window resizes + uint32_t resizeHeight; + }; } diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/GlobalData/SHGraphicsPredefinedData.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/GlobalData/SHGraphicsPredefinedData.cpp index e65f5c8f..63b39c9f 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/GlobalData/SHGraphicsPredefinedData.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/GlobalData/SHGraphicsPredefinedData.cpp @@ -52,6 +52,12 @@ namespace SHADE {SHPredefinedDescriptorTypes::RENDER_GRAPH_RESOURCE, 3}, {SHPredefinedDescriptorTypes::RENDER_GRAPH_NODE_COMPUTE_RESOURCE, 4}, }); + + perSystemData[SHUtilities::ConvertEnum(SystemType::TRAJECTORY_RENDERING)].descMappings.AddMappings + ({ + {SHPredefinedDescriptorTypes::STATIC_DATA, 0}, + {SHPredefinedDescriptorTypes::CAMERA, 1}, + }); } void SHGraphicsPredefinedData::InitDummyPipelineLayouts(Handle logicalDevice) noexcept @@ -222,6 +228,12 @@ namespace SHADE SHGraphicsPredefinedData::PredefinedDescSetLayoutTypes::CAMERA | SHGraphicsPredefinedData::PredefinedDescSetLayoutTypes::LIGHTS ); + + perSystemData[SHUtilities::ConvertEnum(SystemType::TRAJECTORY_RENDERING)].descSetLayouts = GetPredefinedDescSetLayouts + ( + SHGraphicsPredefinedData::PredefinedDescSetLayoutTypes::STATIC_DATA | + SHGraphicsPredefinedData::PredefinedDescSetLayoutTypes::CAMERA + ); } void SHGraphicsPredefinedData::InitPredefinedVertexInputState(void) noexcept diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/GlobalData/SHGraphicsPredefinedData.h b/SHADE_Engine/src/Graphics/MiddleEnd/GlobalData/SHGraphicsPredefinedData.h index 43a4a55c..77307f57 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/GlobalData/SHGraphicsPredefinedData.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/GlobalData/SHGraphicsPredefinedData.h @@ -38,6 +38,7 @@ namespace SHADE BATCHING_ANIM, TEXT_RENDERING, RENDER_GRAPH_NODE_COMPUTE, + TRAJECTORY_RENDERING, NUM_TYPES }; static constexpr int SYSTEM_TYPE_COUNT = static_cast(SystemType::NUM_TYPES); diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsConstants.h b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsConstants.h index fdad3584..38fe9aa3 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsConstants.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsConstants.h @@ -64,6 +64,17 @@ namespace SHADE /***************************************************************************/ static constexpr std::string_view DEFERRED_COMPOSITE_PASS = "Deferred Comp Pass"; + /***************************************************************************/ + /*! + + \brief + Name of vfx render graph node. + + */ + /***************************************************************************/ + static constexpr std::string_view VFX_PASS = "Vfx Pass"; + + /***************************************************************************/ /*! @@ -117,6 +128,7 @@ namespace SHADE static constexpr std::string_view GBUFFER_WRITE_SUBPASS = "G-Buffer Write"; static constexpr std::string_view UI_SUBPASS = "UI"; + static constexpr std::string_view VFX_SUBPASS = "VFX"; static constexpr std::array USABLE_SUBPASSES = { @@ -282,6 +294,13 @@ namespace SHADE */ /***************************************************************************/ static constexpr uint32_t BONE_MATRIX_FIRST_INDEX = 8; + /***************************************************************************/ + /*! + \brief + Vertex buffer bindings for color + */ + /***************************************************************************/ + static constexpr uint32_t TRAJECTORY_COLOR = 2; static constexpr uint32_t CALCULATED_GLYPH_POSITION = 0; static constexpr uint32_t GLYPH_INDEX = 1; diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp index 5ebc6487..297a86ae 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp @@ -129,6 +129,7 @@ namespace SHADE //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); //SHAssetManager::CompileAsset("../../Assets/Shaders/SSAOBlur_CS.glsl", false); //SHAssetManager::CompileAsset("../../Assets/Shaders/PureCopy_CS.glsl", false); @@ -137,7 +138,8 @@ namespace SHADE //SHAssetManager::CompileAsset("../../Assets/Shaders/UI_VS.glsl", false); //SHAssetManager::CompileAsset("../../Assets/Shaders/UI_FS.glsl", false); //SHAssetManager::CompileAsset("../../Assets/Shaders/Text_VS.glsl", false); - + //SHAssetManager::CompileAsset("../../Assets/Shaders/Trajectory_VS.glsl", false); + //SHAssetManager::CompileAsset("../../Assets/Shaders/Trajectory_FS.glsl", false); // Load Built In Shaders static constexpr AssetID VS_DEFAULT = 39210065; defaultVertShader = SHResourceManager::LoadOrGet(VS_DEFAULT); @@ -153,8 +155,10 @@ namespace SHADE 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 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); } @@ -307,13 +311,24 @@ namespace SHADE lightingSubSystem->PrepareShadowMapsForRead(cmdBuffer); }); + /*-----------------------------------------------------------------------*/ + /* VFX PASS */ + /*-----------------------------------------------------------------------*/ + auto vfxPass = renderGraph->AddNode(SHGraphicsConstants::RenderGraphEntityNames::VFX_PASS.data(), { "Scene", "Depth Buffer" }, { SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_PASS.data(), SHGraphicsConstants::RenderGraphEntityNames::DEFERRED_COMPOSITE_PASS.data() }); + auto vfxSubpass = vfxPass->AddSubpass("Vfx Subpass", worldViewport, worldRenderer); + vfxSubpass->AddColorOutput("Scene"); + vfxSubpass->AddDepthOutput("Depth Buffer"); + vfxSubpass->AddExteriorDrawCalls([=](Handle cmdBuffer, Handle renderer, uint32_t frameIndex) + { + trajectoryRenderingSubSystem->Render(cmdBuffer, renderer, frameIndex); + }); /*-----------------------------------------------------------------------*/ /* DEBUG DRAW PASS INIT */ /*-----------------------------------------------------------------------*/ // Set up Debug Draw Passes // - Depth Tested - auto debugDrawNodeDepth = renderGraph->AddNode(SHGraphicsConstants::RenderGraphEntityNames::DEBUG_DRAW_DEPTH_PASS.data(), {"Scene", "Depth Buffer"}, {SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_PASS.data(), SHGraphicsConstants::RenderGraphEntityNames::DEFERRED_COMPOSITE_PASS.data()}); + auto debugDrawNodeDepth = renderGraph->AddNode(SHGraphicsConstants::RenderGraphEntityNames::DEBUG_DRAW_DEPTH_PASS.data(), {"Scene", "Depth Buffer"}, { SHGraphicsConstants::RenderGraphEntityNames::VFX_PASS.data()/*, SHGraphicsConstants::RenderGraphEntityNames::DEFERRED_COMPOSITE_PASS.data()*/}); auto debugDrawDepthSubpass = debugDrawNodeDepth->AddSubpass("Debug Draw with Depth", worldViewport, worldRenderer); debugDrawDepthSubpass->AddColorOutput("Scene"); debugDrawDepthSubpass->AddDepthOutput("Depth Buffer"); @@ -432,6 +447,11 @@ namespace SHADE auto uiNode = renderGraph->GetNode(SHGraphicsConstants::RenderGraphEntityNames::SCREEN_SPACE_PASS.data()); textRenderingSubSystem->Init(device, uiNode->GetRenderpass(), uiNode->GetSubpass(SHGraphicsConstants::RenderGraphEntityNames::UI_SUBPASS), descPool, textVS, textFS); + trajectoryRenderingSubSystem = resourceManager.Create(); + + auto vfxNode = renderGraph->GetNode(SHGraphicsConstants::RenderGraphEntityNames::SCREEN_SPACE_PASS.data()); + trajectoryRenderingSubSystem->Init(device, vfxNode->GetRenderpass(), vfxNode->GetSubpass(SHGraphicsConstants::RenderGraphEntityNames::UI_SUBPASS), trajectoryVS, trajectoryFS); + SHGlobalDescriptorSets::SetLightingSubSystem(lightingSubSystem); } @@ -566,6 +586,7 @@ namespace SHADE } textRenderingSubSystem->Run(frameIndex); + trajectoryRenderingSubSystem->Run(frameIndex); for (auto renderer : renderers) @@ -588,19 +609,19 @@ namespace SHADE 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); - //} - } + //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); @@ -779,10 +800,11 @@ namespace SHADE // 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 resourceName = "ShadowMap " + std::to_string(EVENT_DATA->lightEntity); - Handle companionSubpass = renderGraph->GetNode(SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_PASS.data())->GetSubpass(SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_WRITE_SUBPASS); + 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) { @@ -795,14 +817,16 @@ namespace SHADE } // Add the shadow map resource to the graph - renderGraph->AddResource(resourceName, {SH_RENDER_GRAPH_RESOURCE_FLAGS::DEPTH, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT}, false, SHLightingSubSystem::SHADOW_MAP_WIDTH, SHLightingSubSystem::SHADOW_MAP_HEIGHT, vk::Format::eD32Sfloat); + renderGraph->AddResource(depthResourceName, {SH_RENDER_GRAPH_RESOURCE_FLAGS::DEPTH}, false, SHLightingSubSystem::SHADOW_MAP_WIDTH, SHLightingSubSystem::SHADOW_MAP_HEIGHT, vk::Format::eD32Sfloat); + renderGraph->AddResource(shadowMapResourceName, { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT }, false, SHLightingSubSystem::SHADOW_MAP_WIDTH, SHLightingSubSystem::SHADOW_MAP_HEIGHT, vk::Format::eR32G32B32A32Sfloat); // 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() + resourceName, {resourceName.c_str()}, SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_PASS.data()); + 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(resourceName + " Subpass", shadowMapViewport, lightComp->GetRenderer()); - newSubpass->AddDepthOutput(resourceName, SH_RENDER_GRAPH_RESOURCE_FLAGS::DEPTH); + 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(); @@ -828,7 +852,7 @@ namespace SHADE newSubpass->SetCompanionSubpass(companionSubpass, shadowMapPipeline); // set companion subpass and pipeline // add the shadow map to the lighting system - uint32_t const NEW_SHADOW_MAP_INDEX = lightingSubSystem->AddShadowMap(renderGraph->GetRenderGraphResource(resourceName), EVENT_DATA->lightEntity); + uint32_t const NEW_SHADOW_MAP_INDEX = lightingSubSystem->AddShadowMap(renderGraph->GetRenderGraphResource(shadowMapResourceName), 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); @@ -1154,6 +1178,14 @@ namespace SHADE #ifdef SHEDITOR cameraSystem->GetEditorCamera()->SetWidth(static_cast(resizeWidth)); cameraSystem->GetEditorCamera()->SetHeight(static_cast(resizeHeight)); + + // Create new event and broadcast it + SHWindowResizeEvent newEvent; + newEvent.resizeWidth = resizeWidth; + newEvent.resizeHeight = resizeHeight; + + SHEventManager::BroadcastEvent(newEvent, SH_WINDOW_RESIZE_EVENT); + #else #endif diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.h b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.h index a35065bd..21d18be1 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.h @@ -36,6 +36,7 @@ of DigiPen Institute of Technology is prohibited. #include "Graphics/MiddleEnd/TextRendering/SHFontLibrary.h" #include "Graphics/MiddleEnd/Interface/SHRenderer.h" #include "Graphics/Events/SHGraphicsEvents.h" +#include "Graphics/MiddleEnd/TrajectoryRendering/SHTrajectoryRenderingSubSystem.h" namespace SHADE { @@ -470,6 +471,8 @@ namespace SHADE Handle renderToSwapchainFS; Handle shadowMapVS; Handle shadowMapFS; + Handle trajectoryVS; + Handle trajectoryFS; // Fonts Handle testFont; @@ -505,6 +508,7 @@ namespace SHADE Handle postOffscreenRenderSubSystem; Handle lightingSubSystem; Handle textRenderingSubSystem; + Handle trajectoryRenderingSubSystem; Handle ssaoStorage; uint32_t resizeWidth = 1; diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightingSubSystem.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightingSubSystem.cpp index 9acdfed0..6f8a9030 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightingSubSystem.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightingSubSystem.cpp @@ -395,7 +395,11 @@ namespace SHADE switch (lightComp->GetLightData().type) { case SH_LIGHT_TYPE::DIRECTIONAL: - return SHMatrix::Transpose(SHMatrix::LookAtLH(lightComp->GetLightData().position, SHVec3::Normalise (lightComp->GetLightData().direction), SHVec3(0.0f, -1.0f, 0.0f))); + { + SHTransformComponent* transform = SHComponentManager::GetComponent(lightComp->GetEID()); + + return SHMatrix::Transpose(SHMatrix::LookAtLH(transform->GetWorldPosition(), SHVec3::Normalise(lightComp->GetLightData().direction), SHVec3(0.0f, -1.0f, 0.0f))); + } //return SHMatrix::Transpose(SHMatrix::LookAtLH(/*lightComp->GetLightData().position*/SHVec3(1.27862f, 4.78952f, 4.12811f), SHVec3(-0.280564f, -0.66262f, -0.69422f), SHVec3(0.0f, -1.0f, 0.0f))); case SH_LIGHT_TYPE::POINT: return {}; @@ -518,7 +522,7 @@ namespace SHADE if (auto renderer = light.GetRenderer()) { //SHMatrix orthoMatrix = SHMatrix::OrthographicRH() - renderer->UpdateDataManual(frameIndex, GetViewMatrix(&light), SHMatrix::OrthographicLH(10.0f, 10.0f, 1.0f, 50.0f)); + renderer->UpdateDataManual(frameIndex, GetViewMatrix(&light), SHMatrix::OrthographicLH(12.0f, 12.0f, 1.0f, 80.0f)); } auto enumValue = SHUtilities::ConvertEnum(light.GetLightData().type); @@ -627,16 +631,16 @@ namespace SHADE // add to barriers shadowMapMemoryBarriers.push_back (vk::ImageMemoryBarrier { - .srcAccessMask = vk::AccessFlagBits::eDepthStencilAttachmentWrite, + .srcAccessMask = vk::AccessFlagBits::eColorAttachmentWrite | vk::AccessFlagBits::eColorAttachmentRead, .dstAccessMask = vk::AccessFlagBits::eShaderRead, - .oldLayout = vk::ImageLayout::eDepthAttachmentOptimal, + .oldLayout = vk::ImageLayout::eColorAttachmentOptimal, .newLayout = vk::ImageLayout::eShaderReadOnlyOptimal, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .image = newShadowMap->GetImage()->GetVkImage(), .subresourceRange = vk::ImageSubresourceRange { - .aspectMask = vk::ImageAspectFlagBits::eDepth, + .aspectMask = vk::ImageAspectFlagBits::eColor, .baseMipLevel = 0, .levelCount = 1, .baseArrayLayer = 0, @@ -651,7 +655,7 @@ namespace SHADE void SHLightingSubSystem::PrepareShadowMapsForRead(Handle cmdBuffer) noexcept { // Issue barrier to transition shadow maps for reading in compute shader - cmdBuffer->PipelineBarrier(vk::PipelineStageFlagBits::eEarlyFragmentTests | vk::PipelineStageFlagBits::eLateFragmentTests, vk::PipelineStageFlagBits::eComputeShader, {}, {}, {}, shadowMapMemoryBarriers); + cmdBuffer->PipelineBarrier(vk::PipelineStageFlagBits::eColorAttachmentOutput, vk::PipelineStageFlagBits::eComputeShader, {}, {}, {}, shadowMapMemoryBarriers); } //void SHLightingSubSystem::HandleResize(Handle compute) noexcept diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Particles/SHParticleSubSustem.h b/SHADE_Engine/src/Graphics/MiddleEnd/Particles/SHParticleSubSustem.h new file mode 100644 index 00000000..da806480 --- /dev/null +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Particles/SHParticleSubSustem.h @@ -0,0 +1,41 @@ +#pragma once + +#include "Resource/SHHandle.h" +#include "Graphics/Pipeline/SHPipelineState.h" +#include "Math/SHMatrix.h" + +namespace SHADE +{ + class SHVkLogicalDevice; + class SHVkDescriptorPool; + class SHVkDescriptorSetGroup; + class SHVkDescriptorSetLayout; + class SHVkBuffer; + class SHLightComponent; + class SHVkCommandBuffer; + class SHVkPipeline; + class SHVkPipelineLayout; + class SHVkRenderpass; + class SHSubpass; + class SHVkShaderModule; + class SHRenderer; + + + + class SHParticleSubSystem + { + private: + + Handle logicalDevice; + + + public: + void Init(Handle device, Handle compatibleRenderpass, Handle subpass) noexcept; + + void Run(uint32_t frameIndex) noexcept; + + void Render(Handle cmdBuffer, Handle renderer, uint32_t frameIndex) noexcept; + void Exit(void) noexcept; + + }; +} diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Particles/SHParticleSubSystem.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Particles/SHParticleSubSystem.cpp new file mode 100644 index 00000000..eb3c4f1a --- /dev/null +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Particles/SHParticleSubSystem.cpp @@ -0,0 +1,7 @@ +#include "SHpch.h" +#include "SHParticleSubSustem.h" + +namespace SHADE +{ + +} \ No newline at end of file diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/TrajectoryRendering/SHTrajectoryRenderableComponent.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/TrajectoryRendering/SHTrajectoryRenderableComponent.cpp new file mode 100644 index 00000000..77dd66c8 --- /dev/null +++ b/SHADE_Engine/src/Graphics/MiddleEnd/TrajectoryRendering/SHTrajectoryRenderableComponent.cpp @@ -0,0 +1,96 @@ +#include "SHpch.h" +#include "SHTrajectoryRenderableComponent.h" + +namespace SHADE +{ + + /***************************************************************************/ + /*! + + \brief + On create the text has nothing. + + */ + /***************************************************************************/ + void SHTrajectoryRenderableComponent::OnCreate(void) + { + } + + void SHTrajectoryRenderableComponent::OnDestroy(void) + { + + } + + + void SHTrajectoryRenderableComponent::ClearPositions(void) noexcept + { + positions.clear(); + } + + bool SHTrajectoryRenderableComponent::HasPositions(void) const noexcept + { + return !positions.empty(); + } + + std::vector SHTrajectoryRenderableComponent::GetPositions(void) const noexcept + { + return positions; + } + + Handle SHTrajectoryRenderableComponent::GetMesh(void) const noexcept + { + return mesh; + } + + SHVec4 const& SHTrajectoryRenderableComponent::GetStartColor(void) const noexcept + { + return startColor; + } + + SHVec4 const& SHTrajectoryRenderableComponent::GetEndColor(void) const noexcept + { + return endColor; + } + + float SHTrajectoryRenderableComponent::GetColorEvolveRate(void) const noexcept + { + return colorEvolveRate; + } + + void SHTrajectoryRenderableComponent::SetMesh(Handle newMesh) noexcept + { + mesh = newMesh; + } + + void SHTrajectoryRenderableComponent::SetPositions(std::vector const& inPositions) noexcept + { + positions = inPositions; + } + + void SHTrajectoryRenderableComponent::SetStartColor(SHVec4 color) noexcept + { + startColor = color; + } + + void SHTrajectoryRenderableComponent::SetEndColor(SHVec4 color) noexcept + { + endColor = color; + + } + + void SHTrajectoryRenderableComponent::SetColorEvolveRate(float rate) noexcept + { + colorEvolveRate = rate; + } + +} + +namespace rttr +{ + RTTR_REGISTRATION + { + using namespace SHADE; + + registration::class_("Trajectory Renderer Component"); + }; +} diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/TrajectoryRendering/SHTrajectoryRenderableComponent.h b/SHADE_Engine/src/Graphics/MiddleEnd/TrajectoryRendering/SHTrajectoryRenderableComponent.h new file mode 100644 index 00000000..d6f7be12 --- /dev/null +++ b/SHADE_Engine/src/Graphics/MiddleEnd/TrajectoryRendering/SHTrajectoryRenderableComponent.h @@ -0,0 +1,58 @@ +#pragma once + +#include "Math/Vector/SHVec3.h" +#include "Math/Vector/SHVec4.h" +#include "Resource/SHHandle.h" +#include "ECS_Base/Components/SHComponent.h" +#include + +namespace SHADE +{ + class SHMesh; + + class SHTrajectoryRenderableComponent : public SHComponent + { + private: + + //! Mesh used to render the trajectory + Handle mesh; + + //! positions to plot for rendering. Will be cleared every frame. + std::vector positions; + + //! Starting color of the trajectory + SHVec4 startColor; + + //! Color the trajectory should evolve to the longer it is + SHVec4 endColor; + + //! evolving rate of the color + float colorEvolveRate; + + public: + /*-----------------------------------------------------------------------*/ + /* PRIVATE MEMBER FUNCTIONS */ + /*-----------------------------------------------------------------------*/ + void SetMesh(Handle newMesh) noexcept; + void SetPositions (std::vector const& inPositions) noexcept; + void SetStartColor(SHVec4 startColor) noexcept; + void SetEndColor (SHVec4 endColor) noexcept; + void SetColorEvolveRate (float rate) noexcept; + + std::vector GetPositions (void) const noexcept; + Handle GetMesh (void) const noexcept; + SHVec4 const& GetStartColor (void) const noexcept; + SHVec4 const& GetEndColor (void) const noexcept; + float GetColorEvolveRate (void) const noexcept; + + void OnCreate(void) override final; + void OnDestroy(void) override final; + + void ClearPositions(void) noexcept; + bool HasPositions(void) const noexcept; + + + RTTR_ENABLE() + + }; +} diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/TrajectoryRendering/SHTrajectoryRenderingSubSystem.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/TrajectoryRendering/SHTrajectoryRenderingSubSystem.cpp new file mode 100644 index 00000000..740ffa92 --- /dev/null +++ b/SHADE_Engine/src/Graphics/MiddleEnd/TrajectoryRendering/SHTrajectoryRenderingSubSystem.cpp @@ -0,0 +1,191 @@ +#include "SHpch.h" +#include "SHTrajectoryRenderingSubSystem.h" +#include "ECS_Base/Managers/SHComponentManager.h" +#include "Graphics/MiddleEnd/TrajectoryRendering/SHTrajectoryRenderableComponent.h" +#include "Graphics/Devices/SHVkLogicalDevice.h" +#include "Math/Transform/SHTransformComponent.h" +#include "Graphics\MiddleEnd\Interface\SHMeshLibrary.h" +#include "Graphics/SHVkUtil.h" +#include "Graphics/MiddleEnd/GlobalData/SHGraphicsPredefinedData.h" +#include "Graphics/Pipeline/SHVkPipeline.h" +#include "Graphics/RenderGraph/SHSubpass.h" +#include "Graphics/MiddleEnd/GlobalData/SHGlobalDescriptorSets.h" +#include "Graphics/MiddleEnd/Interface/SHRenderer.h" + +namespace SHADE +{ + + + void SHTrajectoryRenderingSubSystem::Init(Handle device, Handle compatibleRenderpass, Handle subpass, Handle trajectoryVS, Handle trajectoryFS) noexcept + { + logicalDevice = device; + + SHComponentManager::CreateComponentSparseSet(); + + // prepare pipeline layout params + SHPipelineLayoutParams plParams + { + .shaderModules = {trajectoryVS, trajectoryFS}, + .predefinedDescSetLayouts = SHGraphicsPredefinedData::GetSystemData(SHGraphicsPredefinedData::SystemType::TRAJECTORY_RENDERING).descSetLayouts + }; + + pipelineLayout = logicalDevice->CreatePipelineLayout(plParams); + + // Create pipeline + pipeline = logicalDevice->CreateGraphicsPipeline(pipelineLayout, nullptr, compatibleRenderpass, subpass); + + // vertex input state of the pipeline + SHVertexInputState vertexInputState; + vertexInputState.AddBinding(false, false, { SHVertexAttribute(SHAttribFormat::FLOAT_3D) }); // Attribute positions at binding 0 + vertexInputState.AddBinding(false, false, { SHVertexAttribute(SHAttribFormat::FLOAT_2D) }); // Attribute uv at binding 1 + vertexInputState.AddBinding(true, true, { SHVertexAttribute(SHAttribFormat::FLOAT_4D) }); // Instanced attribute color at binding 2 + vertexInputState.AddBinding(true, true, { SHVertexAttribute(SHAttribFormat::MAT_4D) }); // Instanced Transform at binding 3 - 6 (4 slots) + + pipeline->GetPipelineState().SetVertexInputState(vertexInputState); + + SHColorBlendState colorBlendState{}; + colorBlendState.logic_op_enable = VK_FALSE; + colorBlendState.logic_op = vk::LogicOp::eCopy; + + + auto const& subpassColorReferences = subpass->GetColorAttachmentReferences(); + colorBlendState.attachments.reserve(static_cast(subpassColorReferences.size())); + + for (auto& att : subpassColorReferences) + { + colorBlendState.attachments.push_back(vk::PipelineColorBlendAttachmentState + { + .blendEnable = SHVkUtil::IsBlendCompatible(subpass->GetFormatFromAttachmentReference(att.attachment)) ? true : false, + .srcColorBlendFactor = vk::BlendFactor::eSrcAlpha, + .dstColorBlendFactor = vk::BlendFactor::eOneMinusSrcAlpha, + .colorBlendOp = vk::BlendOp::eAdd, + .srcAlphaBlendFactor = vk::BlendFactor::eOne, + .dstAlphaBlendFactor = vk::BlendFactor::eZero, + .alphaBlendOp = vk::BlendOp::eAdd, + .colorWriteMask = vk::ColorComponentFlagBits::eR | vk::ColorComponentFlagBits::eG | vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eA, + } + ); + } + + pipeline->GetPipelineState().SetColorBlenState(colorBlendState); + } + + void SHTrajectoryRenderingSubSystem::Run(uint32_t frameIndex) noexcept + { + auto& comps = SHComponentManager::GetDense(); + for (auto& comp : comps) + { + comp.SetPositions(std::vector + { + SHVec3 {}, + SHVec3 {} + }); + + // If has positions, feed data to buffer. + if (comp.HasPositions()) + { + SHTransformComponent* transform = SHComponentManager::GetComponent_s(comp.GetEID()); + if (transform) + { + // convenient variable + SHVec4 const& startColor = comp.GetStartColor(); + SHVec4 const& endColor = comp.GetEndColor(); + float colorEvolveRate = comp.GetColorEvolveRate(); + + // trs to be reused + SHMatrix trs = transform->GetTRS(); + + // starting color of trajectory + SHVec4 currentColor = comp.GetStartColor(); + + // Start from 0 and slowly evolve to 1 + float lerpValue = 0.0f; + + // Will be used for baseInstance later + uint32_t oldTransformDataSize = transformData.size(); + + auto meshHandle = comp.GetMesh(); + + auto const& positions = comp.GetPositions(); + for (auto& pos : positions) + { + // modify position and reuse matrix + trs.m[3][0] = pos.x; + trs.m[3][1] = pos.y; + trs.m[3][2] = pos.z; + + transformData.push_back(trs); + colorData.push_back(currentColor); + + // evolve color + currentColor = SHVec4::Lerp(startColor, endColor, lerpValue); + + // evolve lerp value and clamp to 1 + lerpValue = std::max (1.0f, lerpValue + colorEvolveRate); + } + + // add draw data for this trajectory + drawData.push_back(vk::DrawIndexedIndirectCommand + { + .indexCount = meshHandle->IndexCount, + .instanceCount = static_cast(transformData.size()) - oldTransformDataSize, + .firstIndex = meshHandle->FirstIndex, + .vertexOffset = meshHandle->FirstVertex, + .firstInstance = oldTransformDataSize + }); + } + } + + // clear at the end of every frame since data is already in buffers + comp.ClearPositions(); + } + + if (!transformData.empty()) + { + // read transform data to buffer + // read draw data to buffer + SHVkUtil::EnsureBufferAndCopyHostVisibleData(logicalDevice, transformBuffer, transformData.data(), sizeof (SHMatrix) * transformData.size(), vk::BufferUsageFlagBits::eVertexBuffer, "Trajectory System Transform Buffer"); + + SHVkUtil::EnsureBufferAndCopyHostVisibleData(logicalDevice, drawDataBuffer, drawData.data(), sizeof(vk::DrawIndexedIndirectCommand) * drawData.size(), vk::BufferUsageFlagBits::eIndirectBuffer, "Trajectory System Draw Data Buffer"); + + SHVkUtil::EnsureBufferAndCopyHostVisibleData(logicalDevice, colorBuffer, colorData.data(), sizeof(SHVec4) * colorData.size(), vk::BufferUsageFlagBits::eVertexBuffer, "Trajectory System Color Data Buffer"); + } + + } + + void SHTrajectoryRenderingSubSystem::Render(Handle cmdBuffer, Handle renderer, uint32_t frameIndex) noexcept + { + if (!transformData.empty()) + { + auto const& mappings = SHGraphicsPredefinedData::GetMappings(SHGraphicsPredefinedData::SystemType::TRAJECTORY_RENDERING); + uint32_t staticGlobalSetIndex = mappings.at(SHPredefinedDescriptorTypes::STATIC_DATA); + uint32_t cameraSetIndex = mappings.at(SHPredefinedDescriptorTypes::CAMERA); + + cmdBuffer->BindPipeline(pipeline); + + // Bind global data + SHGlobalDescriptorSets::BindStaticGlobalData(cmdBuffer, SH_PIPELINE_TYPE::GRAPHICS, staticGlobalSetIndex); + + // Bind camera data + renderer->BindDescriptorSet(cmdBuffer, SH_PIPELINE_TYPE::GRAPHICS, cameraSetIndex, frameIndex); + + // Bind color vertex buffer + cmdBuffer->BindVertexBuffer(SHGraphicsConstants::VertexBufferBindings::TRAJECTORY_COLOR, colorBuffer, 0); + + // call draw call + cmdBuffer->DrawMultiIndirect(drawDataBuffer, drawData.size()); + + // clear CPU transform and draw data + transformData.clear(); + drawData.clear(); + colorData.clear(); + } + + } + + void SHTrajectoryRenderingSubSystem::Exit(void) noexcept + { + + } + +} \ No newline at end of file diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/TrajectoryRendering/SHTrajectoryRenderingSubSystem.h b/SHADE_Engine/src/Graphics/MiddleEnd/TrajectoryRendering/SHTrajectoryRenderingSubSystem.h new file mode 100644 index 00000000..12db99a0 --- /dev/null +++ b/SHADE_Engine/src/Graphics/MiddleEnd/TrajectoryRendering/SHTrajectoryRenderingSubSystem.h @@ -0,0 +1,66 @@ +#pragma once + +#include "Resource/SHHandle.h" +#include "Graphics/Pipeline/SHPipelineState.h" +#include "Math/SHMatrix.h" + +namespace SHADE +{ + class SHVkLogicalDevice; + class SHVkDescriptorPool; + class SHVkDescriptorSetGroup; + class SHVkDescriptorSetLayout; + class SHVkBuffer; + class SHLightComponent; + class SHVkCommandBuffer; + class SHVkPipeline; + class SHVkPipelineLayout; + class SHVkRenderpass; + class SHSubpass; + class SHVkShaderModule; + class SHRenderer; + + + + class SHTrajectoryRenderingSubSystem + { + private: + + Handle logicalDevice; + + //! Every trajectory renderable will have one of these + std::vector drawData; + + //! For the MDI call + Handle drawDataBuffer; + + //! matrix data to copy into buffer + std::vector transformData; + + //! All trajectory renderables will use this transform buffer + Handle transformBuffer; + + //! Each object will have their own color data + std::vector colorData; + + //! buffer to hold color data for objects + Handle colorBuffer; + + //! Pipeline for rendering the trajectories + Handle pipeline; + + //! Pipeline layout for the pipeline + Handle pipelineLayout; + + + + public: + void Init (Handle device, Handle compatibleRenderpass, Handle subpass, Handle textVS, Handle textFS) noexcept; + + void Run(uint32_t frameIndex) noexcept; + + void Render(Handle cmdBuffer, Handle renderer, uint32_t frameIndex) noexcept; + void Exit(void) noexcept; + + }; +} diff --git a/SHADE_Engine/src/Scripting/SHScriptEngine.cpp b/SHADE_Engine/src/Scripting/SHScriptEngine.cpp index 2bdeaa5c..22c7c12e 100644 --- a/SHADE_Engine/src/Scripting/SHScriptEngine.cpp +++ b/SHADE_Engine/src/Scripting/SHScriptEngine.cpp @@ -387,6 +387,7 @@ namespace SHADE { auto eventData = reinterpret_cast*>(eventPtr.get()); csScriptRemoveAllForAllNow(true); + csEngineReloadScripts(); return eventData->handle; } @@ -569,7 +570,7 @@ namespace SHADE SHEventManager::SubscribeTo(SH_ENTITY_DESTROYED_EVENT, std::dynamic_pointer_cast(destroyedEventReceiver)); /* Editor */ - // Register for editor state change event + // Register for editor state change events std::shared_ptr> destroyedSceneEventReceiver { std::make_shared>(this, &SHScriptEngine::onSceneDestroyed) diff --git a/SHADE_Engine/src/Scripting/SHScriptEngine.h b/SHADE_Engine/src/Scripting/SHScriptEngine.h index fd88a283..9b234d04 100644 --- a/SHADE_Engine/src/Scripting/SHScriptEngine.h +++ b/SHADE_Engine/src/Scripting/SHScriptEngine.h @@ -233,6 +233,10 @@ namespace SHADE /// /// void OpenFile(const std::filesystem::path& path); + /// + /// Resets all static data in the loaded assemblies to their default values. + /// + static void ResetStaticDataInLoadedAssembly(); private: /*-----------------------------------------------------------------------------*/ diff --git a/SHADE_Managed/src/Editor/Editor.cxx b/SHADE_Managed/src/Editor/Editor.cxx index 8b53db1b..e10111c3 100644 --- a/SHADE_Managed/src/Editor/Editor.cxx +++ b/SHADE_Managed/src/Editor/Editor.cxx @@ -81,7 +81,8 @@ namespace SHADE // Add the script Script^ script; ScriptStore::AddScriptViaNameWithRef(entity, type->Name, script); - registerUndoScriptAddAction(entity, script); + // TODO: Re-enable when undo-redo is fixed + // registerUndoScriptAddAction(entity, script); break; } } @@ -374,8 +375,9 @@ namespace SHADE if (SHEditorUI::Selectable("Delete Script", ICON_MD_DELETE)) { // Mark script for removal - ScriptStore::RemoveScript(entity, script); - registerUndoScriptRemoveAction(entity, script, scriptIndex); + ScriptStore::RemoveScript(entity, script); + // TODO: Re-enable when undo-redo is fixed + // registerUndoScriptRemoveAction(entity, script, scriptIndex); } SHEditorUI::EndPopup(); } diff --git a/SHADE_Managed/src/Editor/UndoRedoStack.cxx b/SHADE_Managed/src/Editor/UndoRedoStack.cxx index 3d1f04e9..5b39f879 100644 --- a/SHADE_Managed/src/Editor/UndoRedoStack.cxx +++ b/SHADE_Managed/src/Editor/UndoRedoStack.cxx @@ -22,6 +22,7 @@ of DigiPen Institute of Technology is prohibited. #include "Utility/Debug.hxx" #include "Utility/Convert.hxx" #include "Scripts/ScriptStore.hxx" +#include "Serialisation/SerialisationUtilities.hxx" namespace SHADE { @@ -266,8 +267,10 @@ namespace SHADE /* ScriptAddCommand - Constructor */ /*---------------------------------------------------------------------------------*/ ScriptAddCommand::ScriptAddCommand(EntityID id, Script^ script) - : entity { id } - , addedScript { script } + : entity { id } + , typeName { script->GetType()->FullName } + , serialisedScript { SerialisationUtilities::Serialise(script) } + , insertedIndex { ScriptStore::GetScriptIndex(script) } {} /*---------------------------------------------------------------------------------*/ @@ -275,12 +278,20 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ bool ScriptAddCommand::Execute() { - return ScriptStore::AddScript(entity, addedScript) != nullptr; + Script^ script = nullptr; + if (ScriptStore::AddScriptViaNameWithRef(entity, typeName, script)) + { + SerialisationUtilities::Deserialise(script, serialisedScript); + insertedIndex = ScriptStore::GetScriptIndex(script); + return true; + } + + return false; } bool ScriptAddCommand::Unexceute() { - return ScriptStore::RemoveScript(entity, addedScript); + return ScriptStore::RemoveScript(entity, insertedIndex); } bool ScriptAddCommand::Merge(ICommand^) @@ -293,8 +304,9 @@ namespace SHADE /* ScriptRemoveCommand - Constructor */ /*---------------------------------------------------------------------------------*/ ScriptRemoveCommand::ScriptRemoveCommand(EntityID id, Script^ script, int index) - : entity { id } - , removedScript { script } + : entity{ id } + , typeName{ script->GetType()->FullName } + , serialisedScript{ SerialisationUtilities::Serialise(script) } , originalIndex { index } {} @@ -303,12 +315,19 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ bool ScriptRemoveCommand::Execute() { - return ScriptStore::RemoveScript(entity, removedScript); + return ScriptStore::RemoveScript(entity, originalIndex); } bool ScriptRemoveCommand::Unexceute() { - return ScriptStore::AddScript(entity, removedScript, originalIndex) != nullptr; + Script^ script = nullptr; + if (ScriptStore::AddScriptViaNameWithRef(entity, typeName, script, originalIndex)) + { + SerialisationUtilities::Deserialise(script, serialisedScript); + return true; + } + + return false; } bool ScriptRemoveCommand::Merge(ICommand^) diff --git a/SHADE_Managed/src/Editor/UndoRedoStack.hxx b/SHADE_Managed/src/Editor/UndoRedoStack.hxx index c377e2b7..b46da020 100644 --- a/SHADE_Managed/src/Editor/UndoRedoStack.hxx +++ b/SHADE_Managed/src/Editor/UndoRedoStack.hxx @@ -114,7 +114,9 @@ namespace SHADE private: EntityID entity; - Script^ addedScript; + System::String^ typeName; + System::String^ serialisedScript; + int insertedIndex; }; private ref class ScriptRemoveCommand sealed : public ICommand @@ -126,9 +128,10 @@ namespace SHADE bool Unexceute() override; bool Merge(ICommand^ command) override; - private: + private: EntityID entity; - Script^ removedScript; + System::String^ typeName; + System::String^ serialisedScript; int originalIndex; }; diff --git a/SHADE_Managed/src/Scripts/ScriptStore.cxx b/SHADE_Managed/src/Scripts/ScriptStore.cxx index c1747852..62bfc383 100644 --- a/SHADE_Managed/src/Scripts/ScriptStore.cxx +++ b/SHADE_Managed/src/Scripts/ScriptStore.cxx @@ -100,9 +100,14 @@ namespace SHADE } bool ScriptStore::AddScriptViaNameWithRef(Entity entity, System::String^ scriptName, Script^% createdScript) + { + return AddScriptViaNameWithRef(entity, scriptName, createdScript, System::Int32::MaxValue); + } + + bool ScriptStore::AddScriptViaNameWithRef(Entity entity, System::String^ scriptName, [System::Runtime::InteropServices::Out] Script^% createdScript, int index) { // Check if we are set up to get scripts - if (addScriptMethod == nullptr) + if (addScriptMethod == nullptr) { Debug::LogError("[ScriptStore] Native AddScript() was not loaded. Unable to add scripts."); return false; @@ -120,17 +125,18 @@ namespace SHADE return false; } - // Otherwise, add the script + // Add the script System::Reflection::MethodInfo^ method = addScriptMethod->MakeGenericMethod(scriptType); try { - array^ params = gcnew array{entity}; - createdScript = safe_cast(method->Invoke(nullptr, params)); + // Create the script and add it in + createdScript = safe_cast(System::Activator::CreateInstance(scriptType)); + AddScript(entity, createdScript, index); } catch (System::Exception^ e) { std::ostringstream oss; - oss << "[ScriptStore] Failed to add Script named \"" << Convert::ToNative(scriptName) + oss << "[ScriptStore] Failed to add Script named \"" << Convert::ToNative(scriptType->Name) << "\" to Entity #" << entity << "! (" << Convert::ToNative(e->GetType()->Name) << ")"; oss << Convert::ToNative(e->ToString()); Debug::LogError(oss.str()); @@ -321,6 +327,19 @@ namespace SHADE } return nullptr; } + + int ScriptStore::GetScriptIndex(Script^ script) + { + // Check if entity exists in the script storage + if (!scripts.ContainsKey(script->Owner.EntityId)) + { + Debug::LogError("[ScriptStore] Attempted to query a Script that does not belong to the ScriptStore."); + return -1; + } + + return scripts[script->Owner.EntityId]->IndexOf(script); + } + generic void ScriptStore::RemoveScript(Entity entity) { @@ -376,6 +395,35 @@ namespace SHADE removeScript(script); return true; } + + bool ScriptStore::RemoveScript(Entity entity, int index) + { + // Check if entity exists + if (!EntityUtils::IsValid(entity)) + { + Debug::LogError("[ScriptStore] Attempted to remove a Script from an invalid Entity!"); + return false; + } + + // Check if entity exists in the script storage + if (!scripts.ContainsKey(entity)) + { + Debug::LogError("[ScriptStore] Attempted to remove a Script that does not belong to the specified Entity!"); + return false; + } + + // Check if the script index is out of bounds + if (index < 0 || index >= scripts[entity]->Count) + { + Debug::LogError("[ScriptStore] Attempted to remove a Script from an out of range index!"); + return false; + } + + // Script found, queue it for deletion + removeScript((*scripts[entity])[index]); + return true; + } + void ScriptStore::RemoveAllScripts(Entity entity) { SAFE_NATIVE_CALL_BEGIN diff --git a/SHADE_Managed/src/Scripts/ScriptStore.hxx b/SHADE_Managed/src/Scripts/ScriptStore.hxx index bac58a77..e59e3a7f 100644 --- a/SHADE_Managed/src/Scripts/ScriptStore.hxx +++ b/SHADE_Managed/src/Scripts/ScriptStore.hxx @@ -82,9 +82,9 @@ namespace SHADE /// /// Adds a Script to a specified Entity. ///
- /// This function is meant for consumption from native code or for serialisation - /// purposes. If you are writing in C# or C++/CLI and not doing serialisation, - /// use AddScript<T>() instead as it is faster. + /// This function is meant for deserialisation purposes. If you are writing in + /// C# or C++/CLI and not doing serialisation, use AddScript<T>() instead + /// as it is faster. ///
/// The entity to add a script to. /// The entity to add a script to. @@ -96,6 +96,7 @@ namespace SHADE /// console. /// static bool AddScriptViaNameWithRef(Entity entity, System::String^ scriptName, [System::Runtime::InteropServices::Out] Script^% createdScript); + static bool AddScriptViaNameWithRef(Entity entity, System::String^ scriptName, [System::Runtime::InteropServices::Out] Script^% createdScript, int index); /// /// Retrieves the first Script from the specified Entity that matches the /// specified type. @@ -190,6 +191,12 @@ namespace SHADE /// static System::Collections::Generic::IEnumerable^ GetAllScripts(Entity entity); /// + /// Retrieves the index of a Script within the list of it's Entity's script list. + /// + /// Script to get the index of. + /// Script index if valid. Otherwise -1. + static int GetScriptIndex(Script^ script); + /// /// Removes all Scripts of the specified type from the specified Entity. /// /// @@ -201,7 +208,7 @@ namespace SHADE /// If the specified Entity is invalid. /// generic where T : ref class, Script - static void RemoveScript(Entity entity); + static void RemoveScript(Entity entity); /// /// Removes a specific script from the specified entity. /// @@ -210,6 +217,13 @@ namespace SHADE /// True if successfully removed. False otherwise. static bool RemoveScript(Entity entity, Script^ script); /// + /// Removes a script at a specified index from the specified entity. + /// + /// The entity to remove the script from. + /// Index of the script to remove. + /// True if successfully removed. False otherwise. + static bool RemoveScript(Entity entity, int index); + /// /// Removes all Scripts attached to the specified Entity. Does not do anything /// if the specified Entity is invalid or does not have any Scripts /// attached. diff --git a/SHADE_Managed/src/Serialisation/SerialisationUtilities.cxx b/SHADE_Managed/src/Serialisation/SerialisationUtilities.cxx index 83da64b8..b31209c1 100644 --- a/SHADE_Managed/src/Serialisation/SerialisationUtilities.cxx +++ b/SHADE_Managed/src/Serialisation/SerialisationUtilities.cxx @@ -22,6 +22,7 @@ of DigiPen Institute of Technology is prohibited. #include "Assets/MaterialAsset.hxx" #include "Assets/MeshAsset.hxx" #include "Scripts/Script.hxx" +#include "Scripts/ScriptStore.hxx" /*-------------------------------------------------------------------------------------*/ /* File-Level Constants */ @@ -79,6 +80,19 @@ namespace SHADE scriptListNode.push_back(scriptNode); } + + System::String^ SerialisationUtilities::Serialise(Script^ script) + { + YAML::Node node; + node.SetStyle(YAML::EmitterStyle::Block); + Serialise(script, node); + YAML::Emitter emitter; + emitter << YAML::BeginMap; + emitter << node; + emitter << YAML::EndMap; + return Convert::ToCLI(emitter.c_str()); + } + void SerialisationUtilities::Deserialise(Object^ object, YAML::Node& yamlNode) { using namespace System::Reflection; @@ -135,6 +149,12 @@ namespace SHADE } } } + + void SerialisationUtilities::Deserialise(Script^ script, System::String^ yamlString) + { + Deserialise(script, YAML::Load(Convert::ToNative(yamlString))); + } + /*---------------------------------------------------------------------------------*/ /* Serialization Helper Functions */ /*---------------------------------------------------------------------------------*/ diff --git a/SHADE_Managed/src/Serialisation/SerialisationUtilities.hxx b/SHADE_Managed/src/Serialisation/SerialisationUtilities.hxx index 5b6fc69e..9d927d53 100644 --- a/SHADE_Managed/src/Serialisation/SerialisationUtilities.hxx +++ b/SHADE_Managed/src/Serialisation/SerialisationUtilities.hxx @@ -39,6 +39,7 @@ namespace SHADE /// /// The object to serialise. static void Serialise(System::Object^ object, YAML::Node& yamlNode); + static System::String^ Serialise(Script^ script); /// /// Deserialises a YAML node that contains a map of Scripts and copies the /// deserialised data into the specified object if there are matching fields. @@ -48,6 +49,7 @@ namespace SHADE /// /// The object to copy deserialised data into. static void Deserialise(System::Object^ object, YAML::Node& yamlNode); + static void Deserialise(Script^ script, System::String^ yamlString); private: /*-----------------------------------------------------------------------------*/