diff --git a/Assets/Shaders/DeferredComposite_CS.glsl b/Assets/Shaders/DeferredComposite_CS.glsl new file mode 100644 index 00000000..c1caf0aa --- /dev/null +++ b/Assets/Shaders/DeferredComposite_CS.glsl @@ -0,0 +1,83 @@ +#version 450 + +struct DirectionalLightStruct +{ + vec3 direction; + uint isActive; + uint cullingMask; + vec4 diffuseColor; +}; + +struct AmbientLightStruct +{ + vec4 ambientColor; + float strength; + uint isActive; + uint cullingMask; +}; + +layout(local_size_x = 16, local_size_y = 16) in; +layout(set = 4, binding = 0, rgba32f) uniform image2D positions; +layout(set = 4, binding = 1, rgba32f) uniform image2D normals; +layout(set = 4, binding = 2, rgba8) uniform image2D albedo; +layout(set = 4, binding = 3, r32ui) uniform uimage2D lightLayerData; +layout(set = 4, binding = 4, rgba8) uniform image2D targetImage; + +layout(set = 1, binding = 0) uniform LightCounts +{ + uint directionalLights; + uint pointLights; + uint spotLights; + uint ambientLights; + +} lightCounts; + +layout(std430, set = 1, binding = 1) buffer DirectionalLightData +{ + DirectionalLightStruct dLightData[]; +} DirLightData; + +layout(std430, set = 1, binding = 4) buffer AmbientLightData +{ + AmbientLightStruct aLightData[]; +} AmbLightData; + +void main() +{ + // convenient variables + ivec2 globalThread = ivec2(gl_GlobalInvocationID); + + // Get the diffuse color of the pixel + vec3 pixelDiffuse = imageLoad (albedo, globalThread).rgb; + + // Get position of fragment in world space + vec3 positionWorld = imageLoad (positions, globalThread).rgb; + + // normal of fragment + vec3 normalWorld = imageLoad(normals, globalThread).rgb; + + vec3 fragColor = vec3 (0.0f); + + for (int i = 0; i < lightCounts.directionalLights; ++i) + { + // get normalized direction of light + vec3 dLightNormalized = normalize (DirLightData.dLightData[i].direction); + + // Get diffuse strength + float diffuseStrength = max (0, dot (dLightNormalized, normalWorld)); + + // Calculate the fragment color + fragColor += DirLightData.dLightData[i].diffuseColor.rgb * diffuseStrength.rrr * pixelDiffuse; + } + + for (int i = 0; i < lightCounts.ambientLights; ++i) + { + // Just do some add + //fragColor += pixelDiffuse.rgb * AmbLightData.aLightData[i].ambientColor.rgb * vec3 (0.5f); + fragColor += pixelDiffuse.rgb * AmbLightData.aLightData[i].ambientColor.rgb * vec3 (AmbLightData.aLightData[i].strength); + } + + // store result into result image + imageStore(targetImage, ivec2(gl_GlobalInvocationID.xy), vec4(fragColor, 1.0f)); + +} \ No newline at end of file diff --git a/Assets/Shaders/DeferredComposite_CS.shshaderb b/Assets/Shaders/DeferredComposite_CS.shshaderb new file mode 100644 index 00000000..889de5fb Binary files /dev/null and b/Assets/Shaders/DeferredComposite_CS.shshaderb differ diff --git a/Assets/Shaders/DeferredComposite_CS.shshaderb.shmeta b/Assets/Shaders/DeferredComposite_CS.shshaderb.shmeta new file mode 100644 index 00000000..8f18b04a --- /dev/null +++ b/Assets/Shaders/DeferredComposite_CS.shshaderb.shmeta @@ -0,0 +1,3 @@ +Name: DeferredComposite_CS +ID: 42814284 +Type: 2 diff --git a/Assets/Shaders/Kirsch_CS.shshaderb.shmeta b/Assets/Shaders/Kirsch_CS.shshaderb.shmeta index 61c735f3..af092818 100644 --- a/Assets/Shaders/Kirsch_CS.shshaderb.shmeta +++ b/Assets/Shaders/Kirsch_CS.shshaderb.shmeta @@ -1,3 +1,3 @@ Name: Kirsch_CS -ID: 19931255 +ID: 39301863 Type: 2 diff --git a/Assets/Shaders/PureCopy_CS.shshaderb.shmeta b/Assets/Shaders/PureCopy_CS.shshaderb.shmeta index 8cb091d7..8c3d446d 100644 --- a/Assets/Shaders/PureCopy_CS.shshaderb.shmeta +++ b/Assets/Shaders/PureCopy_CS.shshaderb.shmeta @@ -1,3 +1,3 @@ Name: PureCopy_CS -ID: 29659779 +ID: 34987209 Type: 2 diff --git a/Assets/Shaders/TestCube_FS.glsl b/Assets/Shaders/TestCube_FS.glsl index 4dc6deca..c60da6ce 100644 --- a/Assets/Shaders/TestCube_FS.glsl +++ b/Assets/Shaders/TestCube_FS.glsl @@ -13,37 +13,38 @@ struct MatPropData layout(location = 0) in struct { - vec4 vertColor; - vec2 uv; + vec4 vertPos; // location 0 + vec2 uv; // location = 1 + vec4 normal; // location = 2 } In; // material stuff -layout(location = 2) flat in struct +layout(location = 3) flat in struct { int materialIndex; uint eid; uint lightLayerIndex; } In2; -//layout (set = 0, binding = ) - layout (set = 0, binding = 1) uniform sampler2D textures[]; // for textures (global) -layout (set = 3, binding = 0) buffer MaterialProperties // For materials +layout (std430, set = 3, binding = 0) buffer MaterialProperties // For materials { MatPropData data[]; } MatProp; -layout(location = 0) out vec4 outColor; +layout(location = 0) out vec4 position; layout(location = 1) out uint outEntityID; layout(location = 2) out uint lightLayerIndices; +layout(location = 3) out vec4 normals; +layout(location = 4) out vec4 albedo; void main() { - outColor = texture(textures[nonuniformEXT(MatProp.data[In2.materialIndex].textureIndex)], In.uv) + - MatProp.data[In2.materialIndex].color / MatProp.data[In2.materialIndex].alpha; + position = In.vertPos; + normals = In.normal; + albedo = texture(textures[nonuniformEXT(MatProp.data[In2.materialIndex].textureIndex)], In.uv) + MatProp.data[In2.materialIndex].color / MatProp.data[In2.materialIndex].alpha; outEntityID = In2.eid; lightLayerIndices = In2.lightLayerIndex; - //outColor = vec4 (1.0f); } \ No newline at end of file diff --git a/Assets/Shaders/TestCube_FS.shshaderb b/Assets/Shaders/TestCube_FS.shshaderb index 863287f6..b0113dc7 100644 Binary files a/Assets/Shaders/TestCube_FS.shshaderb and b/Assets/Shaders/TestCube_FS.shshaderb differ diff --git a/Assets/Shaders/TestCube_FS.shshaderb.shmeta b/Assets/Shaders/TestCube_FS.shshaderb.shmeta index 3a647313..42f270af 100644 --- a/Assets/Shaders/TestCube_FS.shshaderb.shmeta +++ b/Assets/Shaders/TestCube_FS.shshaderb.shmeta @@ -1,3 +1,3 @@ Name: TestCube_FS -ID: 18415057 +ID: 37450402 Type: 2 diff --git a/Assets/Shaders/TestCube_VS.glsl b/Assets/Shaders/TestCube_VS.glsl index 7b58d1cf..49f107dd 100644 --- a/Assets/Shaders/TestCube_VS.glsl +++ b/Assets/Shaders/TestCube_VS.glsl @@ -14,13 +14,14 @@ layout(location = 8) in uvec2 integerData; layout(location = 0) out struct { - vec4 vertColor; // location 0 + vec4 vertPos; // location 0 vec2 uv; // location = 1 + vec4 normal; // location = 2 } Out; // material stuff -layout(location = 2) out struct +layout(location = 3) out struct { int materialIndex; uint eid; @@ -36,10 +37,14 @@ layout(set = 2, binding = 0) uniform CameraData void main() { - Out.uv = aUV; + Out2.materialIndex = gl_InstanceIndex; Out2.eid = integerData[0]; Out2.lightLayerIndex = integerData[1]; + + Out.vertPos = worldTransform * vec4(aVertexPos, 1.0f); + Out.uv = aUV; + Out.normal.rgb = mat3(transpose(inverse(worldTransform))) * aNormal.rgb; + Out.normal.rgb = normalize (Out.normal.rgb); gl_Position = cameraData.vpMat * worldTransform * vec4 (aVertexPos, 1.0f); - Out.vertColor = vec4 (aVertexPos, 1.0f); } \ No newline at end of file diff --git a/Assets/Shaders/TestCube_VS.shshaderb b/Assets/Shaders/TestCube_VS.shshaderb index 3d12507b..03e23af3 100644 Binary files a/Assets/Shaders/TestCube_VS.shshaderb and b/Assets/Shaders/TestCube_VS.shshaderb differ diff --git a/Assets/Shaders/TestCube_VS.shshaderb.shmeta b/Assets/Shaders/TestCube_VS.shshaderb.shmeta index 23c5e30d..b133437b 100644 --- a/Assets/Shaders/TestCube_VS.shshaderb.shmeta +++ b/Assets/Shaders/TestCube_VS.shshaderb.shmeta @@ -1,3 +1,3 @@ Name: TestCube_VS -ID: 29315909 +ID: 41688429 Type: 2 diff --git a/SHADE_Application/src/Application/SBApplication.cpp b/SHADE_Application/src/Application/SBApplication.cpp index 24d0ca00..24f0a214 100644 --- a/SHADE_Application/src/Application/SBApplication.cpp +++ b/SHADE_Application/src/Application/SBApplication.cpp @@ -159,7 +159,7 @@ namespace Sandbox SHSceneManager::Exit(); SHSystemManager::Exit(); - SHAssetManager::Unload(); + SHAssetManager::Exit(); } } diff --git a/SHADE_Application/src/Scenes/SBTestScene.cpp b/SHADE_Application/src/Scenes/SBTestScene.cpp index 4cdac9dc..23b57dfc 100644 --- a/SHADE_Application/src/Scenes/SBTestScene.cpp +++ b/SHADE_Application/src/Scenes/SBTestScene.cpp @@ -158,12 +158,22 @@ namespace Sandbox SHComponentManager::AddComponent(0); SHComponentManager::RemoveComponent (0); SHComponentManager::RemoveComponent (0); + + auto ambientLight = SHEntityManager::CreateEntity(); + SHComponentManager::GetComponent(ambientLight)->SetColor(SHVec4(1.0f, 1.0f, 1.0f, 1.0f)); + SHComponentManager::GetComponent(ambientLight)->SetStrength(0.25f); + SHComponentManager::GetComponent(ambientLight)->SetType(SH_LIGHT_TYPE::AMBIENT); } void SBTestScene::Update(float dt) { static float rotation = 0.0f; + SHVec3 direction{0.0f, 0.0f, 1.0f}; + direction = SHVec3::RotateY(direction, rotation); + auto* lightComp =SHComponentManager::GetComponent(0); + lightComp->SetDirection (direction); + rotation += 0.005f; //auto& transform = *SHADE::SHComponentManager::GetComponent_s(testObj); //transform.SetWorldPosition({1.0f, 1.0f, -1.0f}); diff --git a/SHADE_CSharp/src/Events/CallbackAction.cs b/SHADE_CSharp/src/Events/CallbackAction.cs index 968302ed..623e4f59 100644 --- a/SHADE_CSharp/src/Events/CallbackAction.cs +++ b/SHADE_CSharp/src/Events/CallbackAction.cs @@ -61,8 +61,25 @@ namespace SHADE /// public CallbackAction() {} /// - /// Constructs a CallbackAction that represents a call to the specified method on the - /// specified target. + /// Constructs a CallbackAction that represents a call to the specified static + /// method. + /// + /// Method to call. + /// + /// Thrown if a method that is not compatible with the target is specified. The method's + /// source type must match the target's type. + /// + public CallbackAction(MethodInfo method) + { + // No errors, assign + targetMethod = method; + + // Create storage for parameters for calling + parameters = new Object[1]; + } + /// + /// Constructs a CallbackAction that represents a call to a specified member + /// method on the specified target. /// /// Object to call the method on. /// Method to call. @@ -86,7 +103,7 @@ namespace SHADE /// /// Constructs a Callback action based on an action. /// - /// + /// Action that wraps a function to be called. public CallbackAction(Action action) { targetAction = action; @@ -103,7 +120,7 @@ namespace SHADE { targetAction.Invoke(t1); } - else if (TargetObject != null && targetMethod != null) + else if (targetMethod != null) { parameters[0] = t1; _ = targetMethod.Invoke(TargetObject, parameters); @@ -138,8 +155,25 @@ namespace SHADE /// public CallbackAction() {} /// - /// Constructs a CallbackAction that represents a call to the specified method on the - /// specified target. + /// Constructs a CallbackAction that represents a call to the specified static + /// method. + /// + /// Method to call. + /// + /// Thrown if a method that is not compatible with the target is specified. The method's + /// source type must match the target's type. + /// + public CallbackAction(MethodInfo method) + { + // No errors, assign + targetMethod = method; + + // Create storage for parameters for calling + parameters = new Object[2]; + } + /// + /// Constructs a CallbackAction that represents a call to a specified member + /// method on the specified target. /// /// Object to call the method on. /// Method to call. @@ -158,12 +192,12 @@ namespace SHADE targetMethod = method; // Create storage for parameters for calling - parameters = new Object[1]; + parameters = new Object[2]; } /// /// Constructs a Callback action based on an action. /// - /// + /// Action that wraps a function to be called. public CallbackAction(Action action) { targetAction = action; @@ -180,7 +214,7 @@ namespace SHADE { targetAction.Invoke(t1, t2); } - else if (TargetObject != null && targetMethod != null) + else if (targetMethod != null) { parameters[0] = t1; parameters[1] = t2; @@ -216,8 +250,25 @@ namespace SHADE /// public CallbackAction() {} /// - /// Constructs a CallbackAction that represents a call to the specified method on the - /// specified target. + /// Constructs a CallbackAction that represents a call to the specified static + /// method. + /// + /// Method to call. + /// + /// Thrown if a method that is not compatible with the target is specified. The method's + /// source type must match the target's type. + /// + public CallbackAction(MethodInfo method) + { + // No errors, assign + targetMethod = method; + + // Create storage for parameters for calling + parameters = new Object[3]; + } + /// + /// Constructs a CallbackAction that represents a call to a specified member + /// method on the specified target. /// /// Object to call the method on. /// Method to call. @@ -236,12 +287,12 @@ namespace SHADE targetMethod = method; // Create storage for parameters for calling - parameters = new Object[1]; + parameters = new Object[3]; } /// /// Constructs a Callback action based on an action. /// - /// + /// Action that wraps a function to be called. public CallbackAction(Action action) { targetAction = action; @@ -258,7 +309,7 @@ namespace SHADE { targetAction.Invoke(t1, t2, t3); } - else if (TargetObject != null && targetMethod != null) + else if (targetMethod != null) { parameters[0] = t1; parameters[1] = t2; @@ -295,8 +346,25 @@ namespace SHADE /// public CallbackAction() {} /// - /// Constructs a CallbackAction that represents a call to the specified method on the - /// specified target. + /// Constructs a CallbackAction that represents a call to the specified static + /// method. + /// + /// Method to call. + /// + /// Thrown if a method that is not compatible with the target is specified. The method's + /// source type must match the target's type. + /// + public CallbackAction(MethodInfo method) + { + // No errors, assign + targetMethod = method; + + // Create storage for parameters for calling + parameters = new Object[4]; + } + /// + /// Constructs a CallbackAction that represents a call to a specified member + /// method on the specified target. /// /// Object to call the method on. /// Method to call. @@ -315,12 +383,12 @@ namespace SHADE targetMethod = method; // Create storage for parameters for calling - parameters = new Object[1]; + parameters = new Object[4]; } /// /// Constructs a Callback action based on an action. /// - /// + /// Action that wraps a function to be called. public CallbackAction(Action action) { targetAction = action; @@ -337,7 +405,7 @@ namespace SHADE { targetAction.Invoke(t1, t2, t3, t4); } - else if (TargetObject != null && targetMethod != null) + else if (targetMethod != null) { parameters[0] = t1; parameters[1] = t2; @@ -375,8 +443,25 @@ namespace SHADE /// public CallbackAction() {} /// - /// Constructs a CallbackAction that represents a call to the specified method on the - /// specified target. + /// Constructs a CallbackAction that represents a call to the specified static + /// method. + /// + /// Method to call. + /// + /// Thrown if a method that is not compatible with the target is specified. The method's + /// source type must match the target's type. + /// + public CallbackAction(MethodInfo method) + { + // No errors, assign + targetMethod = method; + + // Create storage for parameters for calling + parameters = new Object[5]; + } + /// + /// Constructs a CallbackAction that represents a call to a specified member + /// method on the specified target. /// /// Object to call the method on. /// Method to call. @@ -395,12 +480,12 @@ namespace SHADE targetMethod = method; // Create storage for parameters for calling - parameters = new Object[1]; + parameters = new Object[5]; } /// /// Constructs a Callback action based on an action. /// - /// + /// Action that wraps a function to be called. public CallbackAction(Action action) { targetAction = action; @@ -417,7 +502,7 @@ namespace SHADE { targetAction.Invoke(t1, t2, t3, t4, t5); } - else if (TargetObject != null && targetMethod != null) + else if (targetMethod != null) { parameters[0] = t1; parameters[1] = t2; @@ -456,8 +541,25 @@ namespace SHADE /// public CallbackAction() {} /// - /// Constructs a CallbackAction that represents a call to the specified method on the - /// specified target. + /// Constructs a CallbackAction that represents a call to the specified static + /// method. + /// + /// Method to call. + /// + /// Thrown if a method that is not compatible with the target is specified. The method's + /// source type must match the target's type. + /// + public CallbackAction(MethodInfo method) + { + // No errors, assign + targetMethod = method; + + // Create storage for parameters for calling + parameters = new Object[6]; + } + /// + /// Constructs a CallbackAction that represents a call to a specified member + /// method on the specified target. /// /// Object to call the method on. /// Method to call. @@ -476,12 +578,12 @@ namespace SHADE targetMethod = method; // Create storage for parameters for calling - parameters = new Object[1]; + parameters = new Object[6]; } /// /// Constructs a Callback action based on an action. /// - /// + /// Action that wraps a function to be called. public CallbackAction(Action action) { targetAction = action; @@ -498,7 +600,7 @@ namespace SHADE { targetAction.Invoke(t1, t2, t3, t4, t5, t6); } - else if (TargetObject != null && targetMethod != null) + else if (targetMethod != null) { parameters[0] = t1; parameters[1] = t2; @@ -538,8 +640,25 @@ namespace SHADE /// public CallbackAction() {} /// - /// Constructs a CallbackAction that represents a call to the specified method on the - /// specified target. + /// Constructs a CallbackAction that represents a call to the specified static + /// method. + /// + /// Method to call. + /// + /// Thrown if a method that is not compatible with the target is specified. The method's + /// source type must match the target's type. + /// + public CallbackAction(MethodInfo method) + { + // No errors, assign + targetMethod = method; + + // Create storage for parameters for calling + parameters = new Object[7]; + } + /// + /// Constructs a CallbackAction that represents a call to a specified member + /// method on the specified target. /// /// Object to call the method on. /// Method to call. @@ -558,12 +677,12 @@ namespace SHADE targetMethod = method; // Create storage for parameters for calling - parameters = new Object[1]; + parameters = new Object[7]; } /// /// Constructs a Callback action based on an action. /// - /// + /// Action that wraps a function to be called. public CallbackAction(Action action) { targetAction = action; @@ -580,7 +699,7 @@ namespace SHADE { targetAction.Invoke(t1, t2, t3, t4, t5, t6, t7); } - else if (TargetObject != null && targetMethod != null) + else if (targetMethod != null) { parameters[0] = t1; parameters[1] = t2; @@ -621,8 +740,25 @@ namespace SHADE /// public CallbackAction() {} /// - /// Constructs a CallbackAction that represents a call to the specified method on the - /// specified target. + /// Constructs a CallbackAction that represents a call to the specified static + /// method. + /// + /// Method to call. + /// + /// Thrown if a method that is not compatible with the target is specified. The method's + /// source type must match the target's type. + /// + public CallbackAction(MethodInfo method) + { + // No errors, assign + targetMethod = method; + + // Create storage for parameters for calling + parameters = new Object[8]; + } + /// + /// Constructs a CallbackAction that represents a call to a specified member + /// method on the specified target. /// /// Object to call the method on. /// Method to call. @@ -641,12 +777,12 @@ namespace SHADE targetMethod = method; // Create storage for parameters for calling - parameters = new Object[1]; + parameters = new Object[8]; } /// /// Constructs a Callback action based on an action. /// - /// + /// Action that wraps a function to be called. public CallbackAction(Action action) { targetAction = action; @@ -663,7 +799,7 @@ namespace SHADE { targetAction.Invoke(t1, t2, t3, t4, t5, t6, t7, t8); } - else if (TargetObject != null && targetMethod != null) + else if (targetMethod != null) { parameters[0] = t1; parameters[1] = t2; @@ -705,8 +841,25 @@ namespace SHADE /// public CallbackAction() {} /// - /// Constructs a CallbackAction that represents a call to the specified method on the - /// specified target. + /// Constructs a CallbackAction that represents a call to the specified static + /// method. + /// + /// Method to call. + /// + /// Thrown if a method that is not compatible with the target is specified. The method's + /// source type must match the target's type. + /// + public CallbackAction(MethodInfo method) + { + // No errors, assign + targetMethod = method; + + // Create storage for parameters for calling + parameters = new Object[9]; + } + /// + /// Constructs a CallbackAction that represents a call to a specified member + /// method on the specified target. /// /// Object to call the method on. /// Method to call. @@ -725,12 +878,12 @@ namespace SHADE targetMethod = method; // Create storage for parameters for calling - parameters = new Object[1]; + parameters = new Object[9]; } /// /// Constructs a Callback action based on an action. /// - /// + /// Action that wraps a function to be called. public CallbackAction(Action action) { targetAction = action; @@ -747,7 +900,7 @@ namespace SHADE { targetAction.Invoke(t1, t2, t3, t4, t5, t6, t7, t8, t9); } - else if (TargetObject != null && targetMethod != null) + else if (targetMethod != null) { parameters[0] = t1; parameters[1] = t2; @@ -790,8 +943,25 @@ namespace SHADE /// public CallbackAction() {} /// - /// Constructs a CallbackAction that represents a call to the specified method on the - /// specified target. + /// Constructs a CallbackAction that represents a call to the specified static + /// method. + /// + /// Method to call. + /// + /// Thrown if a method that is not compatible with the target is specified. The method's + /// source type must match the target's type. + /// + public CallbackAction(MethodInfo method) + { + // No errors, assign + targetMethod = method; + + // Create storage for parameters for calling + parameters = new Object[10]; + } + /// + /// Constructs a CallbackAction that represents a call to a specified member + /// method on the specified target. /// /// Object to call the method on. /// Method to call. @@ -810,12 +980,12 @@ namespace SHADE targetMethod = method; // Create storage for parameters for calling - parameters = new Object[1]; + parameters = new Object[10]; } /// /// Constructs a Callback action based on an action. /// - /// + /// Action that wraps a function to be called. public CallbackAction(Action action) { targetAction = action; @@ -832,7 +1002,7 @@ namespace SHADE { targetAction.Invoke(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10); } - else if (TargetObject != null && targetMethod != null) + else if (targetMethod != null) { parameters[0] = t1; parameters[1] = t2; diff --git a/SHADE_CSharp/src/Events/CallbackAction.tt b/SHADE_CSharp/src/Events/CallbackAction.tt index fffd4251..34789b67 100644 --- a/SHADE_CSharp/src/Events/CallbackAction.tt +++ b/SHADE_CSharp/src/Events/CallbackAction.tt @@ -78,8 +78,25 @@ namespace SHADE /// public CallbackAction() {} /// - /// Constructs a CallbackAction that represents a call to the specified method on the - /// specified target. + /// Constructs a CallbackAction that represents a call to the specified static + /// method. + /// + /// Method to call. + /// + /// Thrown if a method that is not compatible with the target is specified. The method's + /// source type must match the target's type. + /// + public CallbackAction(MethodInfo method) + { + // No errors, assign + targetMethod = method; + + // Create storage for parameters for calling + parameters = new Object[<#=i#>]; + } + /// + /// Constructs a CallbackAction that represents a call to a specified member + /// method on the specified target. /// /// Object to call the method on. /// Method to call. @@ -98,12 +115,12 @@ namespace SHADE targetMethod = method; // Create storage for parameters for calling - parameters = new Object[1]; + parameters = new Object[<#=i#>]; } /// /// Constructs a Callback action based on an action. /// - /// + /// Action that wraps a function to be called. public CallbackAction(Action<<# for (int t = 1; t < i + 1; ++t) { #>T<#=t#><# if (t != i) { #>, <# } #><# } #>> action) { targetAction = action; @@ -120,7 +137,7 @@ namespace SHADE { targetAction.Invoke(<# for (int t = 1; t < i + 1; ++t) { #>t<#=t#><# if (t != i) { #>, <# } #><# } #>); } - else if (TargetObject != null && targetMethod != null) + else if (targetMethod != null) { <# for (int t = 0; t < i; ++t) {#>parameters[<#=t#>] = t<#=t+1#>; <# } #>_ = targetMethod.Invoke(TargetObject, parameters); diff --git a/SHADE_Engine/src/Assets/Asset Types/SHMaterialAsset.h b/SHADE_Engine/src/Assets/Asset Types/SHMaterialAsset.h new file mode 100644 index 00000000..a130fc07 --- /dev/null +++ b/SHADE_Engine/src/Assets/Asset Types/SHMaterialAsset.h @@ -0,0 +1,23 @@ +/****************************************************************************** + * \file SHMaterialAsset.h + * \author Loh Xiao Qi + * \date 29 October 2022 + * \brief + * + * \copyright Copyright (c) 2021 Digipen Institute of Technology. Reproduction + * or disclosure of this file or its contents without the prior + * written consent of Digipen Institute of Technology is prohibited. + ******************************************************************************/ +#pragma once + +#include "Assets/Asset Types/SHAssetData.h" +#include + +namespace SHADE +{ + struct SHMaterialAsset : SHAssetData + { + std::string name; + std::string data; + }; +} diff --git a/SHADE_Engine/src/Assets/Asset Types/SHPrefabAsset.h b/SHADE_Engine/src/Assets/Asset Types/SHPrefabAsset.h new file mode 100644 index 00000000..0db299b2 --- /dev/null +++ b/SHADE_Engine/src/Assets/Asset Types/SHPrefabAsset.h @@ -0,0 +1,23 @@ +/****************************************************************************** + * \file SHPrefabAsset.h + * \author Loh Xiao Qi + * \date 28 October 2022 + * \brief + * + * \copyright Copyright (c) 2021 Digipen Institute of Technology. Reproduction + * or disclosure of this file or its contents without the prior + * written consent of Digipen Institute of Technology is prohibited. + ******************************************************************************/ +#pragma once + +#include "SHAssetData.h" +#include + +namespace SHADE +{ + struct SHPrefabAsset : SHAssetData + { + std::string name; + std::string data; + }; +} diff --git a/SHADE_Engine/src/Assets/Asset Types/SHSceneAsset.h b/SHADE_Engine/src/Assets/Asset Types/SHSceneAsset.h new file mode 100644 index 00000000..0f7061b1 --- /dev/null +++ b/SHADE_Engine/src/Assets/Asset Types/SHSceneAsset.h @@ -0,0 +1,23 @@ +/****************************************************************************** + * \file SHSceneAsset.h + * \author Loh Xiao Qi + * \date 28 October 2022 + * \brief + * + * \copyright Copyright (c) 2021 Digipen Institute of Technology. Reproduction + * or disclosure of this file or its contents without the prior + * written consent of Digipen Institute of Technology is prohibited. + ******************************************************************************/ +#pragma once + +#include "SHAssetData.h" +#include + +namespace SHADE +{ + struct SHSceneAsset : SHAssetData + { + std::string name; + std::string data; + }; +} diff --git a/SHADE_Engine/src/Assets/Libraries/Loaders/SHAssetLoader.h b/SHADE_Engine/src/Assets/Libraries/Loaders/SHAssetLoader.h index 63e081af..b6b7656b 100644 --- a/SHADE_Engine/src/Assets/Libraries/Loaders/SHAssetLoader.h +++ b/SHADE_Engine/src/Assets/Libraries/Loaders/SHAssetLoader.h @@ -18,5 +18,6 @@ namespace SHADE struct SHAssetLoader { virtual SHAssetData* Load(AssetPath path) = 0; + virtual void Write(SHAssetData const* data, AssetPath path) = 0; }; } diff --git a/SHADE_Engine/src/Assets/Libraries/Loaders/SHMeshLoader.cpp b/SHADE_Engine/src/Assets/Libraries/Loaders/SHMeshLoader.cpp index 90dd58d4..52134440 100644 --- a/SHADE_Engine/src/Assets/Libraries/Loaders/SHMeshLoader.cpp +++ b/SHADE_Engine/src/Assets/Libraries/Loaders/SHMeshLoader.cpp @@ -22,6 +22,7 @@ namespace SHADE if (!file.is_open()) { SHLOG_ERROR("Unable to open SHMesh File: {}", path.string()); + return; } const std::string name{ path.stem().string() }; @@ -75,4 +76,55 @@ namespace SHADE return result; } + + void SHMeshLoader::Write(SHAssetData const* data, AssetPath path) + { + std::ofstream file{ path, std::ios::out | std::ios::binary | std::ios::trunc }; + if (!file.is_open()) + { + SHLOG_ERROR("Unable to open file for writing mesh file: {}", path.string()); + } + + auto asset = *dynamic_cast(data); + + file.write( + reinterpret_cast(&(asset.header.vertexCount)), + sizeof(uint32_t) + ); + + file.write( + reinterpret_cast(&(asset.header.indexCount)), + sizeof(uint32_t) + ); + + auto const vertexVec3Byte{ sizeof(SHVec3) * asset.header.vertexCount }; + auto const vertexVec2Byte{ sizeof(SHVec2) * asset.header.vertexCount }; + + file.write( + reinterpret_cast(asset.vertexPosition.data()), + vertexVec3Byte + ); + + file.write( + reinterpret_cast(asset.vertexTangent.data()), + vertexVec3Byte + ); + + file.write( + reinterpret_cast(asset.vertexNormal.data()), + vertexVec3Byte + ); + + file.write( + reinterpret_cast(asset.texCoords.data()), + vertexVec2Byte + ); + + file.write( + reinterpret_cast(asset.indices.data()), + sizeof(uint32_t) * asset.header.indexCount + ); + + file.close(); + } } diff --git a/SHADE_Engine/src/Assets/Libraries/Loaders/SHMeshLoader.h b/SHADE_Engine/src/Assets/Libraries/Loaders/SHMeshLoader.h index bf65851a..03a111ce 100644 --- a/SHADE_Engine/src/Assets/Libraries/Loaders/SHMeshLoader.h +++ b/SHADE_Engine/src/Assets/Libraries/Loaders/SHMeshLoader.h @@ -10,7 +10,6 @@ * of DigiPen Institute of Technology is prohibited. *****************************************************************************/ #pragma once -#include "Assets/SHAssetMacros.h" #include "Assets/Asset Types/SHMeshAsset.h" #include "SHAssetLoader.h" @@ -20,5 +19,6 @@ namespace SHADE { void LoadSHMesh(AssetPath path, SHMeshAsset& meshes) noexcept; SHAssetData* Load(AssetPath path) override; + void Write(SHAssetData const* data, AssetPath path) override; }; } \ No newline at end of file diff --git a/SHADE_Engine/src/Assets/Libraries/Loaders/SHShaderSourceLoader.cpp b/SHADE_Engine/src/Assets/Libraries/Loaders/SHShaderSourceLoader.cpp index 824995d6..f0d9a29b 100644 --- a/SHADE_Engine/src/Assets/Libraries/Loaders/SHShaderSourceLoader.cpp +++ b/SHADE_Engine/src/Assets/Libraries/Loaders/SHShaderSourceLoader.cpp @@ -43,4 +43,27 @@ namespace SHADE return result; } + + void SHShaderSourceLoader::Write(SHAssetData const* data, AssetPath path) + { + std::ofstream file{ path, std::ios::binary | std::ios::out | std::ios::trunc }; + + auto asset = *dynamic_cast(data); + + file.write( + reinterpret_cast(&asset.shaderType), sizeof(uint8_t) + ); + + size_t const byteCount = sizeof(uint32_t) * asset.spirvBinary.size(); + + file.write( + reinterpret_cast(&byteCount), sizeof(size_t) + ); + + file.write( + reinterpret_cast(asset.spirvBinary.data()), byteCount + ); + + file.close(); + } } diff --git a/SHADE_Engine/src/Assets/Libraries/Loaders/SHShaderSourceLoader.h b/SHADE_Engine/src/Assets/Libraries/Loaders/SHShaderSourceLoader.h index befdade5..0a4b614f 100644 --- a/SHADE_Engine/src/Assets/Libraries/Loaders/SHShaderSourceLoader.h +++ b/SHADE_Engine/src/Assets/Libraries/Loaders/SHShaderSourceLoader.h @@ -11,12 +11,12 @@ #pragma once #include "Assets/Libraries/Loaders/SHAssetLoader.h" -#include "Assets/SHAssetMacros.h" namespace SHADE { struct SHShaderSourceLoader : SHAssetLoader { SHAssetData* Load(AssetPath path) override; + void Write(SHAssetData const* data, AssetPath path) override; }; } diff --git a/SHADE_Engine/src/Assets/Libraries/Loaders/SHTextBasedLoader.cpp b/SHADE_Engine/src/Assets/Libraries/Loaders/SHTextBasedLoader.cpp new file mode 100644 index 00000000..b23130f3 --- /dev/null +++ b/SHADE_Engine/src/Assets/Libraries/Loaders/SHTextBasedLoader.cpp @@ -0,0 +1,95 @@ +/****************************************************************************** + * \file SHTextBasedLoader.cpp + * \author Loh Xiao Qi + * \date 28 October 2022 + * \brief + * + * \copyright Copyright (c) 2021 Digipen Institute of Technology. Reproduction + * or disclosure of this file or its contents without the prior + * written consent of Digipen Institute of Technology is prohibited. + ******************************************************************************/ +#include "SHpch.h" +#include "SHTextBasedLoader.h" + +#include "Assets/Asset Types/SHSceneAsset.h" +#include "Assets/Asset Types/SHPrefabAsset.h" +#include "Assets/Asset Types/SHMaterialAsset.h" + +#include +#include + +namespace SHADE +{ + SHAssetData* SHTextBasedLoader::Load(AssetPath path) + { + std::ifstream file{ path, std::ios::in }; + + if (!file.is_open()) + { + SHLOG_ERROR("Unable to open text File: {}", path.string()); + return nullptr; + } + std::stringstream stream; + + stream << file.rdbuf(); + + std::string content = stream.str(); + + SHAssetData* result; + + if (path.extension().string() == SCENE_EXTENSION) + { + auto data = new SHSceneAsset(); + data->name = path.stem().string(); + data->data = std::move(content); + result = data; + } + else if (path.extension().string() == PREFAB_EXTENSION) + { + auto data = new SHPrefabAsset(); + data->name = path.stem().string(); + data->data = std::move(content); + result = data; + } + else if (path.extension().string() == MATERIAL_EXTENSION) + { + auto data = new SHMaterialAsset(); + data->name = path.stem().string(); + data->data = std::move(content); + result = data; + } + + file.close(); + + return result; + } + + void SHTextBasedLoader::Write(SHAssetData const* data, AssetPath path) + { + std::ofstream file{ path, std::ios::out | std::ios::trunc }; + + if (!file.is_open()) + { + SHLOG_ERROR("Unable to open text File: {}", path.string()); + return; + } + + if (path.extension().string() == SCENE_EXTENSION) + { + auto scene = dynamic_cast(data); + file << scene->data; + } + else if (path.extension().string() == PREFAB_EXTENSION) + { + auto prefab = dynamic_cast(data); + file << prefab->data; + } + else if (path.extension().string() == MATERIAL_EXTENSION) + { + auto material = dynamic_cast(data); + file << material->data; + } + + file.close(); + } +} diff --git a/SHADE_Engine/src/Assets/Libraries/Loaders/SHTextBasedLoader.h b/SHADE_Engine/src/Assets/Libraries/Loaders/SHTextBasedLoader.h new file mode 100644 index 00000000..80771058 --- /dev/null +++ b/SHADE_Engine/src/Assets/Libraries/Loaders/SHTextBasedLoader.h @@ -0,0 +1,21 @@ +/****************************************************************************** + * \file Header.h + * \author Loh Xiao Qi + * \date 28 October 2022 + * \brief + * + * \copyright Copyright (c) 2021 Digipen Institute of Technology. Reproduction + * or disclosure of this file or its contents without the prior + * written consent of Digipen Institute of Technology is prohibited. + ******************************************************************************/ +#pragma once +#include "SHAssetLoader.h" + +namespace SHADE +{ + struct SHTextBasedLoader : SHAssetLoader + { + SHAssetData* Load(AssetPath path) override; + void Write(SHAssetData const* data, AssetPath path) override; + }; +} diff --git a/SHADE_Engine/src/Assets/Libraries/Loaders/SHTextureLoader.cpp b/SHADE_Engine/src/Assets/Libraries/Loaders/SHTextureLoader.cpp index 74c08230..423301dd 100644 --- a/SHADE_Engine/src/Assets/Libraries/Loaders/SHTextureLoader.cpp +++ b/SHADE_Engine/src/Assets/Libraries/Loaders/SHTextureLoader.cpp @@ -17,42 +17,94 @@ namespace SHADE { - void SHTextureLoader::LoadSHTexture(AssetPath path, SHTextureAsset& asset) noexcept - { - std::ifstream file{ path.string(), std::ios::in | std::ios::binary }; - if (!file.is_open()) - { - SHLOG_ERROR("Error opening SHTexture file: {}", path.string()); - } + void SHTextureLoader::LoadSHTexture(AssetPath path, SHTextureAsset& asset) noexcept + { + std::ifstream file{ path.string(), std::ios::in | std::ios::binary }; + if (!file.is_open()) + { + SHLOG_ERROR("Error opening SHTexture file: {}", path.string()); + } - auto const intBytes{ sizeof(uint32_t) }; - uint32_t mipCount; + auto const intBytes{ sizeof(uint32_t) }; + uint32_t mipCount; - file.read(reinterpret_cast(&asset.numBytes), intBytes); - file.read(reinterpret_cast(&asset.width), intBytes); - file.read(reinterpret_cast(&asset.height), intBytes); - file.read(reinterpret_cast(&asset.format), sizeof(SHTexture::TextureFormat)); + file.read(reinterpret_cast(&asset.numBytes), intBytes); + file.read(reinterpret_cast(&asset.width), intBytes); + file.read(reinterpret_cast(&asset.height), intBytes); + file.read(reinterpret_cast(&asset.format), sizeof(SHTexture::TextureFormat)); - file.read(reinterpret_cast(&mipCount), intBytes); - std::vector mips(mipCount); - file.read(reinterpret_cast(mips.data()), intBytes * mipCount); + file.read(reinterpret_cast(&mipCount), intBytes); + std::vector mips(mipCount); + file.read(reinterpret_cast(mips.data()), intBytes * mipCount); - auto pixel = new SHTexture::PixelChannel[asset.numBytes]; - file.read(reinterpret_cast(pixel), asset.numBytes); + auto pixel = new SHTexture::PixelChannel[asset.numBytes]; + file.read(reinterpret_cast(pixel), asset.numBytes); - asset.mipOffsets = std::move(mips); - asset.pixelData = std::move(pixel); + asset.mipOffsets = std::move(mips); + asset.pixelData = std::move(pixel); - asset.compiled = true; - file.close(); - } + asset.compiled = true; + file.close(); + } - SHAssetData* SHTextureLoader::Load(AssetPath path) - { - auto result = new SHTextureAsset(); + SHAssetData* SHTextureLoader::Load(AssetPath path) + { + auto result = new SHTextureAsset(); - LoadSHTexture(path, *result); + LoadSHTexture(path, *result); - return result; - } + return result; + } + + void SHTextureLoader::Write(SHAssetData const* data, AssetPath path) + { + std::ofstream file{ path, std::ios::out | std::ios::binary }; + if (!file.is_open()) + { + SHLOG_ERROR("Unable to open file for writing texture file: {}", path.string()); + } + + auto asset = *dynamic_cast(data); + + constexpr auto intBytes{ sizeof(uint32_t) }; + + uint32_t const mipOffsetCount{ static_cast(asset.mipOffsets.size()) }; + + file.write( + reinterpret_cast(&asset.numBytes), + intBytes + ); + + file.write( + reinterpret_cast(&asset.width), + intBytes + ); + + file.write( + reinterpret_cast(&asset.height), + intBytes + ); + + file.write( + reinterpret_cast(&asset.format), + sizeof(SHTexture::TextureFormat) + ); + + file.write( + reinterpret_cast(&mipOffsetCount), + intBytes + ); + + file.write( + reinterpret_cast(asset.mipOffsets.data()), + intBytes * asset.mipOffsets.size() + ); + + file.write( + reinterpret_cast(asset.pixelData), + asset.numBytes + ); + + file.close(); + } } diff --git a/SHADE_Engine/src/Assets/Libraries/Loaders/SHTextureLoader.h b/SHADE_Engine/src/Assets/Libraries/Loaders/SHTextureLoader.h index 00b060ec..27f7b844 100644 --- a/SHADE_Engine/src/Assets/Libraries/Loaders/SHTextureLoader.h +++ b/SHADE_Engine/src/Assets/Libraries/Loaders/SHTextureLoader.h @@ -10,8 +10,6 @@ * of DigiPen Institute of Technology is prohibited. *****************************************************************************/ #pragma once - -#include "Assets/SHAssetMacros.h" #include "Assets/Asset Types/SHTextureAsset.h" #include "SHAssetLoader.h" @@ -21,5 +19,6 @@ namespace SHADE { void LoadSHTexture(AssetPath path, SHTextureAsset& asset) noexcept; SHAssetData* Load(AssetPath path) override; + void Write(SHAssetData const* data, AssetPath path) override; }; } diff --git a/SHADE_Engine/src/Assets/SHAsset.h b/SHADE_Engine/src/Assets/SHAsset.h index 86e8a722..a4e9847c 100644 --- a/SHADE_Engine/src/Assets/SHAsset.h +++ b/SHADE_Engine/src/Assets/SHAsset.h @@ -11,7 +11,6 @@ *****************************************************************************/ #pragma once -#include "Filesystem/SHFileSystem.h" #include "Assets/SHAssetMacros.h" #include "SH_API.h" @@ -23,6 +22,5 @@ namespace SHADE AssetID id; AssetType type; AssetPath path; - FolderLocation location; }; } \ No newline at end of file diff --git a/SHADE_Engine/src/Assets/SHAssetMacros.h b/SHADE_Engine/src/Assets/SHAssetMacros.h index 1df4e30b..a21a9840 100644 --- a/SHADE_Engine/src/Assets/SHAssetMacros.h +++ b/SHADE_Engine/src/Assets/SHAssetMacros.h @@ -47,17 +47,27 @@ enum class AssetType : AssetTypeMeta SHADER_BUILT_IN, TEXTURE, MESH, + SCENE, + PREFAB, + MATERIAL, MAX_COUNT }; constexpr size_t TYPE_COUNT{ static_cast(AssetType::MAX_COUNT) }; //Directory #ifdef _PUBLISH -constexpr std::string_view ASSET_ROOT {"Assets"}; +constexpr std::string_view ASSET_ROOT{ "Assets" }; +constexpr std::string_view BUILT_IN_ASSET_ROOT {"Built_In"}; #else constexpr std::string_view ASSET_ROOT {"../../Assets"}; +constexpr std::string_view BUILT_IN_ASSET_ROOT{ "../../Built_In" }; #endif +// INTERNAL ASSET PATHS +constexpr std::string_view SCENE_FOLDER{ "/Scenes/" }; +constexpr std::string_view PREFAB_FOLDER{ "/Prefabs/" }; +constexpr std::string_view MATERIAL_FOLDER{ "/Materials/" }; + // ASSET EXTENSIONS constexpr std::string_view META_EXTENSION {".shmeta"}; diff --git a/SHADE_Engine/src/Assets/SHAssetManager.cpp b/SHADE_Engine/src/Assets/SHAssetManager.cpp index 228f3fdc..682eb9ec 100644 --- a/SHADE_Engine/src/Assets/SHAssetManager.cpp +++ b/SHADE_Engine/src/Assets/SHAssetManager.cpp @@ -10,27 +10,33 @@ #include "SHpch.h" #include #include +#include #include "SHAssetManager.h" #include "SHAssetMetaHandler.h" -#include "Filesystem/SHFileSystem.h" #include "Libraries/Loaders/SHMeshLoader.h" #include "Libraries/Loaders/SHTextureLoader.h" #include "Libraries/Loaders/SHShaderSourceLoader.h" +#include "Libraries/Loaders/SHTextBasedLoader.h" #include "Libraries/Compilers/SHMeshCompiler.h" #include "Libraries/Compilers/SHTextureCompiler.h" #include "Libraries/Compilers/SHShaderSourceCompiler.h" +#include "Filesystem/SHFileSystem.h" + namespace SHADE { + FolderPointer SHAssetManager::folderRoot{ nullptr }; + FMOD::System* SHAssetManager::audioSystem; std::unordered_map* SHAssetManager::audioSoundList; std::vector SHAssetManager::loaders(TYPE_COUNT); - std::vector SHAssetManager::assetCollection; + std::unordered_map SHAssetManager::assetCollection; std::unordered_map SHAssetManager::assetData; + /**************************************************************************** * \brief Static function to generate asset ID. @@ -45,13 +51,7 @@ namespace SHADE result |= unique; - while (result == 0 || - std::ranges::any_of( - assetCollection.begin(), - assetCollection.end(), - [result](SHAsset const& asset) { return asset.id == result; } - ) - ) + while (result == 0 || assetCollection.contains(result)) { result = GenerateAssetID(type); } @@ -61,11 +61,6 @@ namespace SHADE /**************************************************************************** * \brief Deallocate all memory used by asset data ****************************************************************************/ - void SHAssetManager::Unload() noexcept - { - - } - void SHAssetManager::Unload(AssetID assetId) noexcept { // TODO @@ -73,14 +68,14 @@ namespace SHADE void SHAssetManager::Exit() noexcept { - for (auto const& loader : loaders) - { - delete loader; - } + delete loaders[static_cast(AssetType::SHADER)]; + delete loaders[static_cast(AssetType::TEXTURE)]; + delete loaders[static_cast(AssetType::MESH)]; + delete loaders[static_cast(AssetType::SCENE)]; - for (auto const& data : assetData) + for (auto const& data : std::ranges::views::values(assetData)) { - delete data.second; + delete data; } } @@ -113,8 +108,8 @@ namespace SHADE { case AssetType::SHADER: case AssetType::SHADER_BUILT_IN: - folder = "Shaders/"; - break; + folder = "Shaders/"; + break; default: folder = "/"; @@ -133,9 +128,17 @@ namespace SHADE * * \return const& to unordered_map ****************************************************************************/ - std::vector const& SHAssetManager::GetAllAssets() noexcept + std::vector SHAssetManager::GetAllAssets() noexcept { - return assetCollection; + std::vector result; + result.reserve(assetCollection.size()); + + for (auto const& asset : std::ranges::views::values(assetCollection)) + { + result.push_back(asset); + } + + return result; } /**************************************************************************** @@ -148,41 +151,113 @@ namespace SHADE ****************************************************************************/ AssetID SHAssetManager::CreateNewAsset(AssetType type, AssetName name) noexcept { - AssetID id{ GenerateAssetID(type) }; - SHAsset meta; - meta.id = id; - meta.type = type; + std::string newPath{ ASSET_ROOT }; + switch (type) + { + case AssetType::PREFAB: + newPath += PREFAB_FOLDER; + break; - std::string folder; - //TODO implement folder choosing - //switch (type) - //{ - //default: - // folder = ""; - // break; - //} - AssetPath path{ std::string{ASSET_ROOT} + folder + name + SHAssetMetaHandler::GetExtensionFromType(type) }; + case AssetType::SCENE: + newPath += SCENE_FOLDER; + break; - SHAssetMetaHandler::WriteMetaData(meta); + case AssetType::MATERIAL: + newPath += MATERIAL_FOLDER; + break; - assetCollection.push_back(meta); + default: + SHLOG_ERROR("Asset type of {} not an internal asset type, cannot be created", name); + return 0; + } + + auto id = GenerateAssetID(type); + SHAsset asset{ + name, + id, + type, + newPath + }; + + assetCollection.insert({ + id, + SHAsset( + name, + id, + type, + newPath + ) + }); return id; } - AssetID SHAssetManager::CreateAsset(AssetName name, AssetType type) noexcept - { - AssetID id = GenerateAssetID(type); + bool SHAssetManager::SaveAsset(AssetID id) noexcept + { + if (assetCollection.contains(id)) + { + auto const& asset = assetCollection[id]; + if ( + asset.type == AssetType::SCENE || + asset.type == AssetType::PREFAB || + asset.type == AssetType::MATERIAL + ) + { + if (assetData.contains(id)) + { + auto const data = assetData.at(id); + loaders[static_cast(asset.type)]->Write(data, asset.path); + SHAssetMetaHandler::WriteMetaData(asset); + + return true; + } + + SHLOG_ERROR("Asset data has not been written into, cannot be saved: {}", + asset.path.filename().string()); + + return false; + } + } + + SHLOG_WARNING("Asset id: {} not an internal asset type, save cannot be triggered", id); + return false; + } + + bool SHAssetManager::DeleteAsset(AssetID id) noexcept + { + + if (assetCollection.contains(id)) + { + auto const& asset = assetCollection[id]; + if ( + asset.type == AssetType::SCENE || + asset.type == AssetType::PREFAB || + asset.type == AssetType::MATERIAL + ) + { + return (DeleteLocalFile(asset.path) && DeleteLocalFile(asset.path.string() + META_EXTENSION.data())); + } + SHLOG_WARNING("Asset id: {} not an internal asset type, file deletion not allowed", id); + } + + SHLOG_WARNING("Asset id does not exist, nothing was deleted: {}", id); + return false; + } + + //AssetID SHAssetManager::CreateAsset(AssetName name, AssetType type) noexcept + //{ + // AssetID id = GenerateAssetID(type); + + // assetCollection.emplace_back( + // name, + // id, + // type, + // GenerateNewPath(name, type) + // ); + // return id; + //} + - assetCollection.emplace_back( - name, - id, - type, - GenerateNewPath(name, type), - 0 - ); - return id; - } /**************************************************************************** * \brief Import new asset from outside editor window. * @@ -205,7 +280,8 @@ namespace SHADE std::filesystem::copy(path, newPath); - assetCollection.push_back(CreateAssetFromPath(newPath)); + auto asset = CreateAssetFromPath(newPath); + assetCollection.insert({asset.id, asset}); return id; } @@ -235,7 +311,7 @@ namespace SHADE std::vector SHAssetManager::GetAllRecordOfType(AssetType type) noexcept { std::vector result; - for (auto const& asset : assetCollection) + for (auto const& asset : std::ranges::views::values(assetCollection)) { if (asset.type == type) { @@ -246,26 +322,30 @@ namespace SHADE return result; } - AssetID SHAssetManager::CompileAsset(AssetPath path) noexcept + AssetID SHAssetManager::CompileAsset(AssetPath const& path) noexcept + { + SHAsset newAsset + { + .name = path.stem().string() + }; + + auto const ext{ path.extension().string() }; + if (ext == GLSL_EXTENSION.data()) + { + newAsset.path = SHShaderSourceCompiler::LoadAndCompileShader(path).value(); + newAsset.id = GenerateAssetID(AssetType::SHADER_BUILT_IN); + newAsset.type = AssetType::SHADER_BUILT_IN; + } + + assetCollection.insert({ newAsset.id, newAsset }); + SHAssetMetaHandler::WriteMetaData(newAsset); + + return newAsset.id; + } + + FolderPointer SHAssetManager::GetRootFolder() noexcept { - SHAsset newAsset - { - .name = path.stem().string(), - .location = 0 - }; - - auto const ext{ path.extension().string() }; - if (ext == GLSL_EXTENSION.data()) - { - newAsset.path = SHShaderSourceCompiler::LoadAndCompileShader(path).value(); - newAsset.id = GenerateAssetID(AssetType::SHADER_BUILT_IN); - newAsset.type = AssetType::SHADER_BUILT_IN; - } - - assetCollection.push_back(newAsset); - SHAssetMetaHandler::WriteMetaData(newAsset); - - return newAsset.id; + return folderRoot; } bool SHAssetManager::IsRecognised(char const* ext) noexcept @@ -289,82 +369,88 @@ namespace SHADE result.type = SHAssetMetaHandler::GetTypeFromExtension(path.extension().string()); result.id = GenerateAssetID(result.type); result.path = path; - result.location = 0; return result; } - void SHAssetManager::CompileAll() noexcept + void SHAssetManager::CompileAll() noexcept + { + std::vector paths; + + for (auto const& dir : std::filesystem::recursive_directory_iterator{ ASSET_ROOT }) + { + if (dir.is_regular_file()) + { + for (auto const& ext : EXTERNALS) + { + if (dir.path().extension().string() == ext.data()) + { + paths.push_back(dir.path()); + } + } + } + } + + for (auto const& path : paths) + { + SHAsset newAsset + { + .name = path.stem().string() + }; + + auto const ext{ path.extension().string() }; + if (ext == GLSL_EXTENSION.data()) + { + newAsset.path = SHShaderSourceCompiler::LoadAndCompileShader(path).value(); + newAsset.id = GenerateAssetID(AssetType::SHADER_BUILT_IN); + newAsset.type = AssetType::SHADER_BUILT_IN; + } + else if (ext == DDS_EXTENSION.data()) + { + newAsset.path = SHTextureCompiler::CompileTextureAsset(path).value(); + newAsset.id = GenerateAssetID(AssetType::TEXTURE); + newAsset.type = AssetType::TEXTURE; + } + else if (ext == GLTF_EXTENSION.data() || ext == FBX_EXTENSION.data()) + { + std::vector meshes; + std::vector anims; + SHMeshCompiler::LoadFromFile(path, meshes, anims); + + for (auto const& mesh : meshes) + { + SHAsset meshAsset{ + .name = mesh->header.name + }; + meshAsset.path = SHMeshCompiler::CompileMeshBinary(*mesh, path).value(); + meshAsset.id = GenerateAssetID(AssetType::MESH); + meshAsset.type = AssetType::MESH; + assetCollection.insert({ meshAsset.id, meshAsset }); + SHAssetMetaHandler::WriteMetaData(meshAsset); + } + continue; + } + + assetCollection.insert({ newAsset.id, newAsset }); + SHAssetMetaHandler::WriteMetaData(newAsset); + } + } + + bool SHAssetManager::DeleteLocalFile(AssetPath path) noexcept { - std::vector paths; - - for (auto const& dir : std::filesystem::recursive_directory_iterator{ ASSET_ROOT }) - { - if (dir.is_regular_file()) - { - for (auto const& ext : EXTERNALS) - { - if (dir.path().extension().string() == ext.data()) - { - paths.push_back(dir.path()); - } - } - } - } - - for (auto const& path : paths) - { - SHAsset newAsset - { - .name = path.stem().string(), - .location = 0 - }; - - auto const ext{ path.extension().string() }; - if (ext == GLSL_EXTENSION.data()) - { - newAsset.path = SHShaderSourceCompiler::LoadAndCompileShader(path).value(); - newAsset.id = GenerateAssetID(AssetType::SHADER_BUILT_IN); - newAsset.type = AssetType::SHADER_BUILT_IN; - } - else if (ext == DDS_EXTENSION.data()) - { - newAsset.path = SHTextureCompiler::CompileTextureAsset(path).value(); - newAsset.id = GenerateAssetID(AssetType::TEXTURE); - newAsset.type = AssetType::TEXTURE; - } - else if (ext == GLTF_EXTENSION.data() || ext == FBX_EXTENSION.data()) - { - std::vector meshes; - std::vector anims; - SHMeshCompiler::LoadFromFile(path, meshes, anims); - - for (auto const& mesh : meshes) - { - SHAsset meshAsset{ - .name = mesh->header.name, - .location = 0 - }; - meshAsset.path = SHMeshCompiler::CompileMeshBinary(*mesh, path).value(); - meshAsset.id = GenerateAssetID(AssetType::MESH); - meshAsset.type = AssetType::MESH; - assetCollection.push_back(meshAsset); - SHAssetMetaHandler::WriteMetaData(meshAsset); - } - continue; - } - - assetCollection.push_back(newAsset); - SHAssetMetaHandler::WriteMetaData(newAsset); - } + //TODO Move this to dedicated library + return std::filesystem::remove(path); } - void SHAssetManager::InitLoaders() noexcept + void SHAssetManager:: InitLoaders() noexcept { loaders[static_cast(AssetType::SHADER)] = dynamic_cast(new SHShaderSourceLoader()); loaders[static_cast(AssetType::SHADER_BUILT_IN)] = loaders[static_cast(AssetType::SHADER)]; - loaders[static_cast(AssetType::TEXTURE)] = dynamic_cast(new SHTextureLoader()); - loaders[static_cast(AssetType::MESH)] = dynamic_cast(new SHMeshLoader()); + loaders[static_cast(AssetType::TEXTURE)] = dynamic_cast(new SHTextureLoader()); + loaders[static_cast(AssetType::MESH)] = dynamic_cast(new SHMeshLoader()); + loaders[static_cast(AssetType::SCENE)] = dynamic_cast(new SHTextBasedLoader()); + loaders[static_cast(AssetType::PREFAB)] = loaders[static_cast(AssetType::SCENE)]; + loaders[static_cast(AssetType::MATERIAL)] = loaders[static_cast(AssetType::SCENE)]; } /**************************************************************************** @@ -372,9 +458,9 @@ namespace SHADE ****************************************************************************/ void SHAssetManager::Load() noexcept { - //CompileAll(); + //CompileAll(); + BuildAssetCollection(); InitLoaders(); - BuildAssetCollection(); //LoadAllData(); } @@ -383,7 +469,7 @@ namespace SHADE ****************************************************************************/ void SHAssetManager::LoadAllData() noexcept { - for (auto const& asset : assetCollection) + for (auto const& asset : std::ranges::views::values(assetCollection)) { SHAssetData* data = loaders[static_cast(asset.type)]->Load(asset.path); assetData.emplace(asset.id, data); @@ -406,17 +492,8 @@ namespace SHADE return data; } - void SHAssetManager::BuildAssetCollection() noexcept - { - for (auto const& dir : std::filesystem::recursive_directory_iterator{ASSET_ROOT}) - { - if (dir.is_regular_file()) - { - if (dir.path().extension().string() == META_EXTENSION.data()) - { - assetCollection.push_back(SHAssetMetaHandler::RetrieveMetaData(dir.path())); - } - } - } - } + void SHAssetManager::BuildAssetCollection() noexcept + { + SHFileSystem::BuildDirectory(ASSET_ROOT.data(), folderRoot, assetCollection); + } } diff --git a/SHADE_Engine/src/Assets/SHAssetManager.h b/SHADE_Engine/src/Assets/SHAssetManager.h index bc6f8878..64527e01 100644 --- a/SHADE_Engine/src/Assets/SHAssetManager.h +++ b/SHADE_Engine/src/Assets/SHAssetManager.h @@ -10,10 +10,12 @@ ******************************************************************************/ #pragma once #include "tinyddsloader.h" + #include "SHAsset.h" #include "Asset Types/SHAssetData.h" #include "Assets/Libraries/Loaders/SHAssetLoader.h" -#include + +#include "Filesystem/SHFolder.h" #include "SH_API.h" @@ -26,19 +28,17 @@ namespace SHADE * \brief Static function to generate resource ID. ****************************************************************************/ static AssetID GenerateAssetID(AssetType type) noexcept; - static AssetPath GenerateLocalPath(AssetPath path) noexcept; - static AssetPath GenerateNewPath(AssetName name, AssetType type); /**************************************************************************** * \brief Deallocate all memory used by resource data ****************************************************************************/ - static void Unload() noexcept; - static void Unload(AssetID assetId) noexcept; - static void Exit() noexcept; + + static void Unload(AssetID assetId) noexcept; + /**************************************************************************** * \brief Load all resources that are in the folder ****************************************************************************/ @@ -49,7 +49,7 @@ namespace SHADE * * \return const& to unordered_map ****************************************************************************/ - static std::vector const& GetAllAssets() noexcept; + static std::vector GetAllAssets() noexcept; /**************************************************************************** * \brief Create record for new resource. CAN ONLY CREATE FOR CUSTOM @@ -59,8 +59,9 @@ namespace SHADE * \param name of resource * \return resource id generated for new asset ****************************************************************************/ - static AssetID CreateNewAsset(AssetType, AssetName) noexcept; - static AssetID CreateAsset(AssetName name, AssetType type) noexcept; + static AssetID CreateNewAsset(AssetType type, AssetName name) noexcept; + static bool SaveAsset(AssetID id) noexcept; + static bool DeleteAsset(AssetID id) noexcept; /**************************************************************************** * \brief Import new resource from outside editor window. @@ -78,12 +79,17 @@ namespace SHADE // -------------------------------------------------------------------------/ template - static std::enable_if_t, T const* const> GetData(AssetID id) noexcept; + static std::enable_if_t, T* const> GetData(AssetID id) noexcept; + + template + static std::enable_if_t, T const* const> GetConstData(AssetID id) noexcept; static std::vector GetAllDataOfType(AssetType type) noexcept; static std::vector GetAllRecordOfType(AssetType type) noexcept; - static AssetID CompileAsset(AssetPath path) noexcept; + static AssetID CompileAsset(AssetPath const& path) noexcept; + + static FolderPointer GetRootFolder() noexcept; private: @@ -98,13 +104,20 @@ namespace SHADE static void CompileAll() noexcept; + static bool DeleteLocalFile(AssetPath path) noexcept; + + //TODO use this function to create asset data internall at all calls to generate id + //static AssetID CreateAsset(AssetName name, AssetType type) noexcept; + + static FolderPointer folderRoot; + static FMOD::System* audioSystem; static std::unordered_map* audioSoundList; static std::vector loaders; // For all resources - static std::vector assetCollection; + static std::unordered_map assetCollection; static std::unordered_map assetData; }; } diff --git a/SHADE_Engine/src/Assets/SHAssetManager.hpp b/SHADE_Engine/src/Assets/SHAssetManager.hpp index 6c420778..4f372938 100644 --- a/SHADE_Engine/src/Assets/SHAssetManager.hpp +++ b/SHADE_Engine/src/Assets/SHAssetManager.hpp @@ -4,16 +4,16 @@ namespace SHADE { template - std::enable_if_t, T const* const> SHAssetManager::GetData(AssetID id) noexcept + std::enable_if_t, T* const> SHAssetManager::GetData(AssetID id) noexcept { if (!assetData.contains(id)) { - for (auto const& asset : assetCollection) + for (auto const& asset : std::ranges::views::values(assetCollection)) { if (asset.id == id) { assetData.emplace(id, LoadData(asset)); - return dynamic_cast(assetData[id]); + return dynamic_cast(assetData[id]); } } @@ -21,6 +21,27 @@ namespace SHADE return nullptr; } - return dynamic_cast(assetData[id]); + return dynamic_cast(assetData[id]); } + + template + std::enable_if_t, T const * const> SHAssetManager::GetConstData(AssetID id) noexcept + { + if (!assetData.contains(id)) + { + for (auto const& asset : std::ranges::views::values(assetCollection)) + { + if (asset.id == id) + { + assetData.emplace(id, LoadData(asset)); + return dynamic_cast(assetData[id]); + } + } + + SHLOG_ERROR("Asset ID provided does not exist: {}", id); + return nullptr; + } + + return dynamic_cast(assetData[id]); + } } diff --git a/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp b/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp index 44799c17..c4dfd674 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp +++ b/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp @@ -13,11 +13,25 @@ #include "Editor/IconsFontAwesome6.h" #include "ECS_Base/Components/SHComponent.h" #include "Editor/SHEditorWidgets.hpp" +#include "Graphics/MiddleEnd/Lights/SHLightComponent.h" #include "Physics/Components/SHColliderComponent.h" #include "Reflection/SHReflectionMetadata.h" namespace SHADE { + template + std::vector GetRTTREnumNames() + { + auto const rttrType = rttr::type::get(); + if(!rttrType.is_enumeration()) + return {}; + auto const enumAlign = rttrType.get_enumeration(); + auto const names = enumAlign.get_names(); + std::vector result; + std::transform(names.begin(), names.end(), std::back_inserter(result), [](rttr::string_view const& name){return name.data();}); + return result; + } + template::value, bool> = true> static void DrawContextMenu(T* component) { @@ -290,4 +304,34 @@ namespace SHADE } else DrawContextMenu(component); } + + template<> + static void DrawComponent(SHLightComponent* component) + { + if (!component) + return; + const auto componentType = rttr::type::get(*component); + SHEditorWidgets::CheckBox("##IsActive", [component]() {return component->isActive; }, [component](bool const& active) {component->isActive = active; }); + ImGui::SameLine(); + if (ImGui::CollapsingHeader(componentType.get_name().data())) + { + DrawContextMenu(component); + + static auto const enumAlign = rttr::type::get().get_enumeration(); + static std::vector list(GetRTTREnumNames()); + + SHEditorWidgets::ComboBox("Type", list, [component] {return static_cast(component->GetType()); }, [component](int const& idx) + { + component->SetType(static_cast(idx)); + }); + SHEditorWidgets::DragVec3("Position", {"X", "Y", "Z"}, [component](){return component->GetPosition();}, [component](SHVec3 const& vec){component->SetPosition(vec);}); + SHEditorWidgets::DragVec3("Direction", {"X", "Y", "Z"}, [component](){return component->GetDirection();}, [component](SHVec3 const& vec){component->SetDirection(vec);}); + SHEditorWidgets::ColorPicker("Color", [component](){return component->GetColor();}, [component](SHVec4 const& rgba){component->SetColor(rgba);}); + SHEditorWidgets::DragFloat("Strength", [component](){return component->GetStrength();}, [component](float const& value){component->SetStrength(value);}); + } + else + { + DrawContextMenu(component); + } + } } \ No newline at end of file diff --git a/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorInspector.cpp b/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorInspector.cpp index 8b532b7b..9a31da60 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorInspector.cpp +++ b/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorInspector.cpp @@ -100,6 +100,10 @@ namespace SHADE { DrawComponent(rigidbodyComponent); } + if(auto lightComponent = SHComponentManager::GetComponent_s(eid)) + { + DrawComponent(lightComponent); + } if (auto cameraComponent = SHComponentManager::GetComponent_s(eid)) { DrawComponent(cameraComponent); diff --git a/SHADE_Engine/src/Editor/SHEditorWidgets.hpp b/SHADE_Engine/src/Editor/SHEditorWidgets.hpp index d511c106..7a71c5f2 100644 --- a/SHADE_Engine/src/Editor/SHEditorWidgets.hpp +++ b/SHADE_Engine/src/Editor/SHEditorWidgets.hpp @@ -196,8 +196,8 @@ namespace SHADE ImGuiColors::colors[i], 4); ImGui::SameLine(0, g.Style.ItemInnerSpacing.x); - ImGui::PopID(); ImGui::PopItemWidth(); + ImGui::PopID(); } ImGui::EndColumns(); ImGui::PopID(); @@ -641,5 +641,43 @@ namespace SHADE } return edited; } + + static bool ColorPicker(const std::string_view& label, std::function get, std::function set, std::string_view const& tooltip = {}, float speed = 0.1f, const char* displayFormat = "%.3f", float valueMin = 0.0f, float valueMax = 0.0f, + ImGuiSliderFlags flags = 0) + { + bool changed = false; + ImGui::BeginGroup(); + ImGui::PushID(label.data()); + + SHVec4 values = get(); + //changed |= DragN(label.data(), {"R", "G", "B", "A"}, { &values.x, &values.y, &values.z, &values.w }, speed, displayFormat, valueMin, valueMax, flags); + //ImGui::SameLine(); + TextLabel(label); + changed = ImGui::ColorEdit4("##Col4", &values.x, ImGuiColorEditFlags_AlphaPreviewHalf | ImGuiColorEditFlags_AlphaBar | ImGuiColorEditFlags_DisplayRGB ); + static bool startRecording = false; + if(changed) + { + SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), values, set)), startRecording); + if(!startRecording) + startRecording = true; + } + if (startRecording && ImGui::IsMouseReleased(ImGuiMouseButton_Left)) + { + startRecording = false; + } + ImGui::PopID(); + ImGui::EndGroup(); + if (!tooltip.empty()) + { + if (ImGui::IsItemHovered()) + { + ImGui::BeginTooltip(); + ImGui::Text(tooltip.data()); + ImGui::EndTooltip(); + } + } + return changed; + } }; + }//namespace SHADE diff --git a/SHADE_Engine/src/Filesystem/SHFileSystem.cpp b/SHADE_Engine/src/Filesystem/SHFileSystem.cpp index bd34ed71..4c0971e6 100644 --- a/SHADE_Engine/src/Filesystem/SHFileSystem.cpp +++ b/SHADE_Engine/src/Filesystem/SHFileSystem.cpp @@ -1,159 +1,82 @@ +/*************************************************************************//** + * \file SHFileSystem.cpp + * \author Loh Xiao Qi + * \date 30 October 2022 + * \brief + * + * Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or + * disclosure of this file or its contents without the prior written consent + * of DigiPen Institute of Technology is prohibited. + *****************************************************************************/ #include "SHpch.h" #include "SHFileSystem.h" -#include "fileapi.h" #include #include +#include "Assets/SHAssetMetaHandler.h" + namespace SHADE { - char const FOLDER_MAX_COUNT {15}; - - std::unordered_map> SHFileSystem::folders; - FolderPointer SHFileSystem::root {nullptr}; - - SHFolder::SHFolder(FolderHandle id, FolderName name) - :id{ id }, name{ name }, subFolders(0), folded{ false }, path{""} - { - } - - FolderLocation SHFileSystem::CreateNewFolderHere(FolderName name, FolderLocation here) noexcept - { - if (here == 0) - { - if (!folders.contains(0)) - { - folders[0] = std::make_unique(0, "root"); - } - - auto const count = static_cast(folders[here]->subFolders.size()); - - if (count >= FOLDER_MAX_COUNT) - { - SHLOG_ERROR("Max subfolder reached: {}\n", name); - } - - auto const location = static_cast(count); - - CreateFolder(folders[0]->path, here, location, name); - - return location; - } - - if (!folders.contains(here)) - { - SHLOG_ERROR("Folder creation location does not exist/invalid: {}\n", here); - } - - auto const count = static_cast(folders[here]->subFolders.size()); - - FolderHandle location = here; - location <<= FOLDER_BIT_ALLOCATE; - location |= count; - - if (count >= FOLDER_MAX_COUNT) - { - SHLOG_ERROR("Max subfolder reached: {}\n", name); - } - - CreateFolder(folders[0]->path, here, location, name); - - return location; - } bool SHFileSystem::DeleteFolder(FolderPointer location) noexcept { - if (!folders.contains(location->id)) - { - SHLOG_ERROR("Delete target does not exist/invalid: {}\n", location->name); - } - - for (auto const& subFolder : folders[location->id]->subFolders) - { - DeleteFolder(subFolder); - } - - RemoveDirectoryA(folders[location->id]->path.c_str()); + //TODO IMPLEMENT return true; } - void SHFileSystem::StartupFillDirectories(FolderPath path) noexcept + void SHFileSystem::BuildDirectory(FolderPath path, FolderPointer& root, std::unordered_map& assetCollection) noexcept { std::queue folderQueue; - - folderQueue.push(RegisterFolder(path, 0, 0, "Root")); + root = new SHFolder("root"); + root->path = path; + folderQueue.push(root); while (!folderQueue.empty()) { - auto folder = folderQueue.front(); + auto const folder = folderQueue.front(); folderQueue.pop(); - FolderCounter count = 0; + + std::vector assets; for (auto const& dirEntry : std::filesystem::directory_iterator(folder->path)) { + auto const& path = dirEntry.path(); if (!dirEntry.is_directory()) { - folder->files.emplace_back( - dirEntry.path().filename().string(), - dirEntry.path().string(), - dirEntry.path().extension().string() - ); - - continue; + if (path.extension().string() == META_EXTENSION) + { + //auto asset = SHAssetMetaHandler::RetrieveMetaData(path); + //assetCollection.insert({ asset.id, asset }); + assets.push_back(SHAssetMetaHandler::RetrieveMetaData(path)); + } + else + { + folder->files.emplace_back( + path.stem().string(), + path.string(), + path.extension().string(), + nullptr + ); + } + continue; } - FolderLocation location = folder->id; - location <<= FOLDER_BIT_ALLOCATE; - location |= ++count; - - std::string name = dirEntry.path().string(); - name = name.substr(name.find_last_of('/') + 1, name.length() - name.find_last_of('/')); - - FolderPointer newFolder{ RegisterFolder( - dirEntry.path().string(), - folder->id, - location, - name) - }; - - folderQueue.push(newFolder); - folder->subFolders.push_back(newFolder); + auto newFolder{ folder->CreateSubFolderHere(path.stem().string()) }; + folderQueue.push(newFolder); } + + for (auto const& asset : assets) + { + assetCollection.emplace(asset.id, asset); + for(auto& file : folder->files) + { + if (file.name == asset.name) + { + file.assetMeta = &assetCollection[asset.id]; + break; + } + } + } } } - - FolderPointer SHFileSystem::GetRoot() noexcept - { - return root; - } - - FolderPointer SHFileSystem::CreateFolder(FolderPath path, FolderLocation parent, FolderHandle location, FolderName name) noexcept - { - - if (!CreateDirectoryA(path.c_str(), nullptr)) - { - SHLOG_ERROR("Failed to create folder: {}\n", path); - } - - folders[location] = std::make_unique(location, name); - folders[location]->path = path; - folders[parent]->subFolders.push_back(folders[location].get()); - - return FolderMakeHelper(path, parent, location, name); - } - - FolderPointer SHFileSystem::RegisterFolder(FolderPath path, FolderLocation parent, FolderHandle location, - FolderName name) noexcept - { - return FolderMakeHelper(path, parent, location, name); - } - - FolderPointer SHFileSystem::FolderMakeHelper(FolderPath path, FolderLocation parent, FolderHandle location, - FolderName name) noexcept - { - folders[location] = std::make_unique(location, name); - folders[location]->path = path; - folders[parent]->subFolders.push_back(folders[location].get()); - - return folders[location].get(); - } } diff --git a/SHADE_Engine/src/Filesystem/SHFileSystem.h b/SHADE_Engine/src/Filesystem/SHFileSystem.h index 8df794fd..956d3916 100644 --- a/SHADE_Engine/src/Filesystem/SHFileSystem.h +++ b/SHADE_Engine/src/Filesystem/SHFileSystem.h @@ -1,70 +1,28 @@ +/****************************************************************************** + * \file SHFileSystem.h + * \author Loh Xiao Qi + * \date 28 October 2022 + * \brief + * + * \copyright Copyright (c) 2021 Digipen Institute of Technology. Reproduction + * or disclosure of this file or its contents without the prior + * written consent of Digipen Institute of Technology is prohibited. + ******************************************************************************/ #pragma once -#include -#include -#include +#include "SHFolder.h" #include namespace SHADE { - class SHFolder; - - typedef unsigned char FolderCounter; - typedef unsigned char FileCounter; - typedef uint64_t FolderLocation; - typedef uint64_t FolderHandle; - typedef std::string FolderName; - typedef std::string FileName; - typedef std::string FolderPath; - typedef std::string FilePath; - typedef std::string FileExt; - typedef SHFolder* FolderPointer; - - constexpr char FOLDER_BIT_ALLOCATE{ 4 }; - constexpr char FOLDER_MAX_DEPTH{ 16 }; - - struct SHFile - { - FileName name; - FilePath path; - FileExt ext; - }; - - class SHFolder - { - public: - SHFolder(FolderHandle id, FolderName name); - - FolderHandle id; - FolderName name; - std::vector subFolders; - std::vector files; - - bool folded; - - private: - FolderPath path; - friend class SHFileSystem; - }; class SHFileSystem { public: - static FolderLocation CreateNewFolderHere(FolderName name, FolderLocation here = 0) noexcept; - - static bool DeleteFolder(FolderPointer location) noexcept; - - static void StartupFillDirectories(FolderPath path) noexcept; - - static FolderPointer GetRoot() noexcept; + static void BuildDirectory(FolderPath path, FolderPointer& root, std::unordered_map& assetCollection) noexcept; private: - static FolderPointer root; - - static std::unordered_map> folders; - - static FolderPointer CreateFolder(FolderPath path, FolderLocation parent, FolderHandle location, FolderName name) noexcept; - static FolderPointer RegisterFolder(FolderPath path, FolderLocation parent, FolderHandle location, FolderName name) noexcept; - static FolderPointer FolderMakeHelper(FolderPath path, FolderLocation parent, FolderHandle location, FolderName name) noexcept; + static bool DeleteFolder(FolderPointer location) noexcept; + }; } \ No newline at end of file diff --git a/SHADE_Engine/src/Filesystem/SHFolder.cpp b/SHADE_Engine/src/Filesystem/SHFolder.cpp new file mode 100644 index 00000000..716eec4b --- /dev/null +++ b/SHADE_Engine/src/Filesystem/SHFolder.cpp @@ -0,0 +1,38 @@ +/*************************************************************************//** + * \file SHFolder.cpp + * \author Loh Xiao Qi + * \date 30 October 2022 + * \brief + * + * Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or + * disclosure of this file or its contents without the prior written consent + * of DigiPen Institute of Technology is prohibited. + *****************************************************************************/ +#include "SHpch.h" +#include "SHFolder.h" + +namespace SHADE +{ + SHFolder::SHFolder(FolderName name) + :name{ name }, subFolders(0), folded{ false }, path{ "" } + { + } + + FolderPointer SHFolder::CreateSubFolderHere(FolderName name) + { + for (auto const& folder : subFolders) + { + if (name == folder->name) + { + SHLOG_ERROR("Unable to create subfolder {} at {} as it already exists", name, folder->name); + return nullptr; + } + } + + auto result = new SHFolder(name); + result->path = path + "/" + name; + subFolders.push_back(result); + + return result; + } +} diff --git a/SHADE_Engine/src/Filesystem/SHFolder.h b/SHADE_Engine/src/Filesystem/SHFolder.h new file mode 100644 index 00000000..54e95033 --- /dev/null +++ b/SHADE_Engine/src/Filesystem/SHFolder.h @@ -0,0 +1,52 @@ +/****************************************************************************** + * \file SHFolder.h + * \author Loh Xiao Qi + * \date 28 October 2022 + * \brief + * + * \copyright Copyright (c) 2021 Digipen Institute of Technology. Reproduction + * or disclosure of this file or its contents without the prior + * written consent of Digipen Institute of Technology is prohibited. + ******************************************************************************/ +#pragma once + +#include +#include +#include "Assets/SHAsset.h" + +namespace SHADE +{ + class SHFolder; + + typedef unsigned char FolderCounter; + typedef unsigned char FileCounter; + typedef std::string FolderName; + typedef std::string FileName; + typedef std::string FolderPath; + typedef std::string FilePath; + typedef std::string FileExt; + typedef SHFolder* FolderPointer; + + struct SHFile + { + FileName name; + FilePath path; + FileExt ext; + SHAsset const* assetMeta; + }; + + class SHFolder + { + public: + SHFolder(FolderName name); + + FolderName name; + std::vector subFolders; + std::vector files; + + bool folded; + + FolderPointer CreateSubFolderHere(FolderName name); + FolderPath path; + }; +} diff --git a/SHADE_Engine/src/Graphics/Devices/SHVkLogicalDevice.cpp b/SHADE_Engine/src/Graphics/Devices/SHVkLogicalDevice.cpp index a6b415a9..6bf2e731 100644 --- a/SHADE_Engine/src/Graphics/Devices/SHVkLogicalDevice.cpp +++ b/SHADE_Engine/src/Graphics/Devices/SHVkLogicalDevice.cpp @@ -186,9 +186,10 @@ namespace SHADE vk::PhysicalDeviceFeatures features{}; // ADD MORE FEATURES HERE IF NEEDED // point and lines fill mode - features.fillModeNonSolid = true; + features.fillModeNonSolid = VK_TRUE; features.samplerAnisotropy = VK_TRUE; - features.multiDrawIndirect = true; + features.multiDrawIndirect = VK_TRUE; + features.independentBlend = VK_TRUE; // for wide lines features.wideLines = true; diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.cpp index d07e0f06..1bda7c90 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.cpp @@ -194,7 +194,8 @@ namespace SHADE { SHLOG_WARNING("[SHBatch] Entity with a missing SHRenderable found!"); } - propsCurrPtr += singleMatPropAlignedSize; + //propsCurrPtr += singleMatPropAlignedSize; + propsCurrPtr += singleMatPropSize; } // Transfer to GPU @@ -316,7 +317,7 @@ namespace SHADE { singleMatPropSize = SHADER_INFO->GetBytesRequired(); singleMatPropAlignedSize = device->PadSSBOSize(static_cast(singleMatPropSize)); - matPropTotalBytes = numTotalElements * singleMatPropAlignedSize; + matPropTotalBytes = numTotalElements * singleMatPropSize; if (matPropsDataSize < matPropTotalBytes) { matPropsData.reset(new char[matPropTotalBytes]); @@ -375,7 +376,8 @@ namespace SHADE { SHLOG_WARNING("[SHBatch] Entity with a missing SHRenderable found!"); } - propsCurrPtr += singleMatPropAlignedSize; + //propsCurrPtr += singleMatPropAlignedSize; + propsCurrPtr += singleMatPropSize; } } } diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/GlobalData/SHGraphicsGlobalData.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/GlobalData/SHGraphicsGlobalData.cpp index 0f1658f3..d5fb81bd 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/GlobalData/SHGraphicsGlobalData.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/GlobalData/SHGraphicsGlobalData.cpp @@ -47,36 +47,35 @@ namespace SHADE // For global data (generic data and textures) Handle staticGlobalLayout = logicalDevice->CreateDescriptorSetLayout(SHGraphicsConstants::DescriptorSetIndex::STATIC_GLOBALS,{ genericDataBinding, texturesBinding }); + std::vector lightBindings{}; - for (uint32_t i = 0; i < SHUtilities::ToUnderlying(SH_LIGHT_TYPE::NUM_TYPES); ++i) + + // This is the binding we use to count the lights (binding 0) + lightBindings.push_back(SHVkDescriptorSetLayout::Binding + { + .Type = vk::DescriptorType::eUniformBufferDynamic, + .Stage = vk::ShaderStageFlagBits::eCompute, + .BindPoint = 0, + .DescriptorCount = 1, + + }); + + for (uint32_t i = 1; i <= SHUtilities::ToUnderlying(SH_LIGHT_TYPE::NUM_TYPES); ++i) { lightBindings.push_back (SHVkDescriptorSetLayout::Binding { .Type = vk::DescriptorType::eStorageBufferDynamic, - .Stage = vk::ShaderStageFlagBits::eFragment, + .Stage = vk::ShaderStageFlagBits::eCompute, .BindPoint = i, .DescriptorCount = 1, }); } - //SHVkDescriptorSetLayout::Binding pointLightBinding - //{ - // .Type = vk::DescriptorType::eStorageBufferDynamic, - // .Stage = vk::ShaderStageFlagBits::eFragment, - // .BindPoint = SHGraphicsConstants::DescriptorSetBindings::POINT_LIGHT_DATA, - // .DescriptorCount = 1, - //}; - //SHVkDescriptorSetLayout::Binding spotLightBinding - //{ - // .Type = vk::DescriptorType::eStorageBufferDynamic, - // .Stage = vk::ShaderStageFlagBits::eFragment, - // .BindPoint = SHGraphicsConstants::DescriptorSetBindings::SPOT_LIGHT_DATA, - // .DescriptorCount = 1, - //}; // For Dynamic global data (lights) Handle dynamicGlobalLayout = logicalDevice->CreateDescriptorSetLayout(SHGraphicsConstants::DescriptorSetIndex::DYNAMIC_GLOBALS, lightBindings); + SHVkDescriptorSetLayout::Binding cameraDataBinding { .Type = vk::DescriptorType::eUniformBufferDynamic, diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsConstants.h b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsConstants.h index 4c3ba7f9..a39ec10e 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsConstants.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsConstants.h @@ -94,32 +94,14 @@ namespace SHADE /***************************************************************************/ static constexpr uint32_t IMAGE_AND_SAMPLERS_DATA = 1; - ///***************************************************************************/ - ///*! - // \brief - // DescriptorSet binding for directional lights. + /***************************************************************************/ + /*! + \brief + DescriptorSet binding for combined image sampler data. - //*/ - ///***************************************************************************/ - //static constexpr uint32_t DIRECTIONAL_LIGHT_DATA = 0; - - ///***************************************************************************/ - ///*! - // \brief - // DescriptorSet binding for directional lights. - - //*/ - ///***************************************************************************/ - //static constexpr uint32_t POINT_LIGHT_DATA = 1; - - ///***************************************************************************/ - ///*! - // \brief - // DescriptorSet binding for directional lights. - - //*/ - ///***************************************************************************/ - //static constexpr uint32_t SPOT_LIGHT_DATA = 2; + */ + /***************************************************************************/ + static constexpr uint32_t LIGHTING_COUNT = 0; /***************************************************************************/ /*! diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp index 35942e7e..7391da2c 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp @@ -73,15 +73,7 @@ namespace SHADE if (width == 0 || height == 0) return; -#ifdef SHEDITOR - - //PrepareResize(1, 1, SHVec2(0, 0)); - -#else - - PrepareResize(resizeWidth, resizeHeight, SHVec2(0, 0)); - -#endif + PrepareResize(resizeWidth, resizeHeight); }); window->RegisterWindowCloseCallback([&](void) @@ -160,26 +152,45 @@ namespace SHADE // Initialize world render graph worldRenderGraph->Init(device, swapchain); - worldRenderGraph->AddResource("Scene Pre-Process", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second); - worldRenderGraph->AddResource("Scene", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second); + worldRenderGraph->AddResource("Position", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second, vk::Format::eR32G32B32A32Sfloat); + worldRenderGraph->AddResource("Normals", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second, vk::Format::eR32G32B32A32Sfloat); + worldRenderGraph->AddResource("Albedo", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second); worldRenderGraph->AddResource("Depth Buffer", { SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL }, windowDims.first, windowDims.second, vk::Format::eD32SfloatS8Uint); - worldRenderGraph->AddResource("Entity ID", { SH_ATT_DESC_TYPE_FLAGS::COLOR }, windowDims.first, windowDims.second, vk::Format::eR32Uint, 1, vk::ImageUsageFlagBits::eTransferSrc); - worldRenderGraph->AddResource("Light Layer Indices", { SH_ATT_DESC_TYPE_FLAGS::COLOR }, windowDims.first, windowDims.second, vk::Format::eR32Uint, 1, vk::ImageUsageFlagBits::eTransferSrc); + worldRenderGraph->AddResource("Entity ID", { SH_ATT_DESC_TYPE_FLAGS::COLOR }, windowDims.first, windowDims.second, vk::Format::eR32Uint, 1, vk::ImageUsageFlagBits::eTransferSrc); + worldRenderGraph->AddResource("Light Layer Indices", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second, vk::Format::eR32Uint, 1, vk::ImageUsageFlagBits::eTransferSrc); + worldRenderGraph->AddResource("Scene", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second); + + auto gBufferNode = worldRenderGraph->AddNode("G-Buffer", + { + "Position", + "Entity ID", + "Light Layer Indices", + "Normals", + "Albedo", + "Depth Buffer", + "Scene" + }, + {}); // no predecessors - auto gBufferNode = worldRenderGraph->AddNode("G-Buffer", { "Light Layer Indices", "Entity ID", "Depth Buffer", "Scene", "Scene Pre-Process"}, {}); // no predecessors auto gBufferSubpass = gBufferNode->AddSubpass("G-Buffer Write"); - gBufferSubpass->AddColorOutput("Scene Pre-Process"); + gBufferSubpass->AddColorOutput("Position"); gBufferSubpass->AddColorOutput("Entity ID"); gBufferSubpass->AddColorOutput("Light Layer Indices"); + gBufferSubpass->AddColorOutput("Normals"); + gBufferSubpass->AddColorOutput("Albedo"); gBufferSubpass->AddDepthOutput("Depth Buffer", SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL); //// kirsch - //auto kirschShader = shaderModuleLibrary.GetShaderModule("KirschCs"); - //gBufferNode->AddNodeCompute(kirschShader, { "Scene Pre-Process", "Scene" }); + //auto kirschShader = shaderModuleLibrary.GetShaderModule("KirschCs.glsl"); + //gBufferNode->AddNodeCompute(kirschShader, { "Position", "Scene" }); - // copy - auto pureCopyShader = shaderModuleLibrary.GetBuiltInShaderModule("PureCopy_CS"); - gBufferNode->AddNodeCompute(pureCopyShader, { "Scene Pre-Process", "Scene" }); + //// copy + //auto pureCopyShader = shaderModuleLibrary.GetShaderModule("PureCopyCs.glsl"); + //gBufferNode->AddNodeCompute(pureCopyShader, { "Position", "Scene" }); + + // deferred composite + auto deferredCompositeShader = shaderModuleLibrary.GetBuiltInShaderModule("DeferredComposite_CS"); + gBufferNode->AddNodeCompute(deferredCompositeShader, { "Position", "Normals", "Albedo", "Light Layer Indices", "Scene" }); auto dummyNode = worldRenderGraph->AddNode("Dummy Pass", { "Scene" }, {"G-Buffer"}); // no predecessors @@ -311,6 +322,12 @@ namespace SHADE void SHGraphicsSystem::Run(double) noexcept { if (window->IsMinimized() || renderContext.GetWindowIsDead()) + { + restoredFromMinimize = true; + return; + } + + if (restoredFromMinimize) return; // Frame data for the current frame @@ -362,6 +379,7 @@ namespace SHADE // Force set the pipeline layout currentCmdBuffer->ForceSetPipelineLayout(SHGraphicsGlobalData::GetDummyPipelineLayout(), SH_PIPELINE_TYPE::GRAPHICS); + currentCmdBuffer->ForceSetPipelineLayout(SHGraphicsGlobalData::GetDummyPipelineLayout(), SH_PIPELINE_TYPE::COMPUTE); // Bind all the buffers required for meshes for (auto& [buffer, bindingPoint] : MESH_DATA) @@ -444,7 +462,15 @@ namespace SHADE void SHGraphicsSystem::BeginRender() { if (window->IsMinimized() || renderContext.GetWindowIsDead()) + { + restoredFromMinimize = true; return; + } + + if (restoredFromMinimize) + { + return; + } // Finalise all batches for (auto vp : viewports) @@ -493,7 +519,17 @@ namespace SHADE void SHGraphicsSystem::EndRender() { if (window->IsMinimized() || renderContext.GetWindowIsDead()) + { + restoredFromMinimize = true; return; + } + + if (restoredFromMinimize) + { + restoredFromMinimize = false; + return; + } + const uint32_t CURR_FRAME_IDX = renderContext.GetCurrentFrame(); auto& currFrameData = renderContext.GetCurrentFrameData(); diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.h b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.h index f657965c..0f9d602a 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.h @@ -360,5 +360,7 @@ namespace SHADE uint32_t resizeWidth; uint32_t resizeHeight; + bool restoredFromMinimize = false; + }; } \ No newline at end of file diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterial.hpp b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterial.hpp index 8c205570..f81cfa5c 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterial.hpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterial.hpp @@ -58,7 +58,7 @@ namespace SHADE } // Get offset and return the memory directly - T* dataPtr = propMemory.get() + PROP_INFO->offset; + T* dataPtr = reinterpret_cast(propMemory.get() + PROP_INFO->offset); return *dataPtr; } template diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterialInstance.hpp b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterialInstance.hpp index 4621c273..e70631ea 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterialInstance.hpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterialInstance.hpp @@ -69,15 +69,15 @@ namespace SHADE // Search Override Data for the property uint32_t PROP_IDX = SHADER_INFO->GetVariableIndex(key); - auto prop = std::find(overrideData.begin(), overrideData.end(), [&](const OverrideData& data) - { - return PROP_IDX == data.Index; - }); + auto prop = std::find_if(overrideData.begin(), overrideData.end(), [&](const OverrideData& data) + { + return PROP_IDX == data.Index; + }); if (prop == overrideData.end()) throw std::invalid_argument("Attempted to get an property that was not set previously!"); // Get offset and return the memory directly - T* dataPtr = dataStore.get() + prop->StoredDataOffset; + T* dataPtr = reinterpret_cast(dataStore.get() + prop->StoredDataOffset); return *dataPtr; } template diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMeshLibrary.h b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMeshLibrary.h index 72ac1878..b0cbdce1 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMeshLibrary.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMeshLibrary.h @@ -17,7 +17,8 @@ of DigiPen Institute of Technology is prohibited. // Project Includes #include "Resource/SHHandle.h" #include "Resource/SHResourceLibrary.h" -#include "Math/SHMath.h" +#include "Math/Vector/SHVec2.h" +#include "Math/Vector/SHVec3.h" namespace SHADE { diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderable.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderable.cpp index 22de83b8..57762324 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderable.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderable.cpp @@ -28,7 +28,7 @@ namespace SHADE material = {}; oldMaterial = {}; - lightLayer = 0; + lightLayer = 1; } void SHRenderable::OnDestroy() diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightComponent.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightComponent.cpp index fd122334..fb8795fa 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightComponent.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightComponent.cpp @@ -10,7 +10,7 @@ namespace SHADE lightData.Reset(); SetType(SH_LIGHT_TYPE::DIRECTIONAL); indexInBuffer = std::numeric_limits::max(); - active = true; + isActive = true; Unbind(); } @@ -20,7 +20,7 @@ namespace SHADE } - void SHLightComponent::SetPosition(SHVec3 position) noexcept + void SHLightComponent::SetPosition(SHVec3 const& position) noexcept { lightData.position = position; MakeDirty(); @@ -34,20 +34,20 @@ namespace SHADE } - void SHLightComponent::SetDirection(SHVec3 direction) noexcept + void SHLightComponent::SetDirection(SHVec3 const& direction) noexcept { lightData.direction = direction; MakeDirty(); } - void SHLightComponent::SetDiffuseColor(SHVec4 diffuseColor) noexcept + void SHLightComponent::SetColor(SHVec4 const& color) noexcept { - lightData.diffuseColor = diffuseColor; + lightData.color = color; MakeDirty(); } - void SHLightComponent::ModifyLayer(uint8_t layerIndex, bool value) noexcept + void SHLightComponent::ModifyCullingMask(uint8_t layerIndex, bool value) noexcept { if (value) lightData.cullingMask |= (1u << layerIndex); @@ -57,6 +57,10 @@ namespace SHADE MakeDirty(); } + void SHLightComponent::SetCullingMask(uint32_t const& value) noexcept + { + lightData.cullingMask = value; + } void SHLightComponent::SetAllLayers(void) noexcept { @@ -93,11 +97,11 @@ namespace SHADE indexInBuffer = inIndexInBuffer; } - void SHLightComponent::SetActive(bool flag) noexcept - { - MakeDirty(); - active = flag; + void SHLightComponent::SetStrength(float value) noexcept + { + lightData.strength = value; + MakeDirty(); } SHLightData const& SHLightComponent::GetLightData(void) const noexcept @@ -105,6 +109,32 @@ namespace SHADE return lightData; } + SHVec3 const& SHLightComponent::GetPosition(void) const noexcept + { + return lightData.position; + } + + SH_LIGHT_TYPE SHLightComponent::GetType(void) const noexcept + { + return lightData.type; + } + + SHVec3 const& SHLightComponent::GetDirection(void) const noexcept + { + return lightData.direction; + } + + SHVec4 const& SHLightComponent::GetColor(void) const noexcept + { + return lightData.color; + } + + uint32_t const& SHLightComponent::GetCullingMask(void) const noexcept + { + return lightData.cullingMask; + } + + bool SHLightComponent::IsDirty(void) const noexcept { return dirty; @@ -120,4 +150,32 @@ namespace SHADE return indexInBuffer; } + float SHLightComponent::GetStrength(void) const noexcept + { + return lightData.strength; + } + +} + +RTTR_REGISTRATION +{ + using namespace SHADE; + using namespace rttr; + + registration::enumeration("Light Type") + ( + value("Directional", SH_LIGHT_TYPE::DIRECTIONAL), + value("Point", SH_LIGHT_TYPE::POINT), + value("Spot", SH_LIGHT_TYPE::SPOT), + value("Ambient", SH_LIGHT_TYPE::AMBIENT) + ); + + registration::class_("Light Component") + .property("Position", &SHLightComponent::GetPosition, &SHLightComponent::SetPosition) + .property("Type", &SHLightComponent::GetType, &SHLightComponent::SetType) + .property("Direction", &SHLightComponent::GetDirection, &SHLightComponent::SetDirection) + .property("Color", &SHLightComponent::GetColor, &SHLightComponent::SetColor) + .property("Layer", &SHLightComponent::GetCullingMask, &SHLightComponent::SetCullingMask) + .property("Strength", &SHLightComponent::GetStrength, &SHLightComponent::SetStrength) + ; } diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightComponent.h b/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightComponent.h index 20ae3892..81eb80f5 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightComponent.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightComponent.h @@ -1,5 +1,6 @@ #pragma once +#include #include "ECS_Base/Components/SHComponent.h" #include "SHLightData.h" @@ -24,8 +25,6 @@ namespace SHADE //! If the light's data is already in the buffers, this will be set to true. bool bound; - //! If the light is active, this is true. - bool active; public: /*-----------------------------------------------------------------------*/ @@ -37,24 +36,31 @@ namespace SHADE /*-----------------------------------------------------------------------*/ /* SETTERS AND GETTERS */ /*-----------------------------------------------------------------------*/ - void SetPosition (SHVec3 position) noexcept; - void SetType (SH_LIGHT_TYPE type) noexcept; - void SetDirection (SHVec3 direction) noexcept; - void SetDiffuseColor (SHVec4 diffuseColor) noexcept; - void ModifyLayer (uint8_t layerIndex, bool value) noexcept; - void SetAllLayers (void) noexcept; - void ClearAllLayers (void) noexcept; - void MakeDirty (void) noexcept; - void ClearDirtyFlag (void) noexcept; - void Unbind (void) noexcept; - void SetBound (uint32_t inIndexInBuffer) noexcept; - void SetActive (bool flag) noexcept; + void SetPosition (SHVec3 const& position) noexcept; // serialized + void SetType (SH_LIGHT_TYPE type) noexcept; // serialized + void SetDirection (SHVec3 const& direction) noexcept; // serialized + void SetColor (SHVec4 const& color) noexcept; // serialized + void ModifyCullingMask (uint8_t layerIndex, bool value) noexcept; // serialized + void SetCullingMask (uint32_t const& value) noexcept; + void SetAllLayers (void) noexcept; // serialized + void ClearAllLayers (void) noexcept; // serialized + void MakeDirty (void) noexcept; + void ClearDirtyFlag (void) noexcept; + void Unbind (void) noexcept; + void SetBound (uint32_t inIndexInBuffer) noexcept; + void SetStrength (float value) noexcept; // serialized - SHLightData const& GetLightData (void) const noexcept; + SHLightData const& GetLightData (void) const noexcept; + SHVec3 const& GetPosition (void) const noexcept; // serialized + SH_LIGHT_TYPE GetType (void) const noexcept; // serialized + SHVec3 const& GetDirection (void) const noexcept; // serialized + SHVec4 const& GetColor (void) const noexcept; // serialized + uint32_t const& GetCullingMask (void) const noexcept; // serialized bool IsDirty (void) const noexcept; bool GetBound (void) const noexcept; uint32_t GetIndexInBuffer (void) const noexcept; - + float GetStrength (void) const noexcept; + RTTR_ENABLE() }; } diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightData.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightData.cpp index ba910408..8e8f0783 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightData.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightData.cpp @@ -15,7 +15,7 @@ namespace SHADE direction = SHVec3::Forward; // Diffuse color set to 1 - diffuseColor = SHVec4::One; + color = SHVec4::One; } } \ No newline at end of file diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightData.h b/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightData.h index 607978a4..e9a02c1a 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightData.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightData.h @@ -10,6 +10,7 @@ namespace SHADE DIRECTIONAL = 0, POINT, SPOT, + AMBIENT, NUM_TYPES }; @@ -40,7 +41,11 @@ namespace SHADE uint32_t cullingMask; //! Diffuse color emitted by the light - SHVec4 diffuseColor; + SHVec4 color; + + //! Strength of the light + float strength; + void Reset (void) noexcept; //! TODO: diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightingSubSystem.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightingSubSystem.cpp index 8d9efe54..5ca879c4 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightingSubSystem.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightingSubSystem.cpp @@ -42,13 +42,23 @@ namespace SHADE lightPtr->cullingMask = lightData.cullingMask; lightPtr->direction = lightData.direction; - lightPtr->diffuseColor = lightData.diffuseColor; + lightPtr->diffuseColor = lightData.color; + lightPtr->active = lightComp->isActive; break; } case SH_LIGHT_TYPE::POINT: break; case SH_LIGHT_TYPE::SPOT: break; + case SH_LIGHT_TYPE::AMBIENT: + { + SHAmbientLightData* lightPtr = reinterpret_cast(address); + lightPtr->ambientColor = lightData.color; + lightPtr->strength = lightData.strength; + lightPtr->cullingMask = lightData.cullingMask; + lightPtr->active = lightComp->isActive; + break; + } case SH_LIGHT_TYPE::NUM_TYPES: break; default: @@ -57,6 +67,7 @@ namespace SHADE } } + /***************************************************************************/ /*! @@ -76,8 +87,9 @@ namespace SHADE // boilerplate intermediateData = nullptr; - // initialize alignment - lightDataAlignmentSize = logicalDevice->PadSSBOSize(GetLightTypeSize(type)); + // Get data required for struct + lightDataSize = GetLightTypeSize(type); + lightDataAlignedSize = logicalDevice->PadSSBOSize(lightDataSize); // So create some data! Expand(logicalDevice); @@ -94,7 +106,7 @@ namespace SHADE /***************************************************************************/ void SHLightingSubSystem::PerTypeData::Expand(Handle logicalDevice) noexcept { - if (lightDataAlignmentSize == 0) + if (lightDataSize == 0) { SHLOG_ERROR ("One of the types of lights have not been accounted for. Make sure lightDataAlignmentSize is not nullptr."); return; @@ -111,10 +123,12 @@ namespace SHADE numLights = 0; // Initialize the data for lights - intermediateData = std::make_unique(lightDataAlignmentSize * maxLights); + intermediateData = std::make_unique(lightDataSize * maxLights); + + lightDataTotalAlignedSize = logicalDevice->PadSSBOSize(lightDataAlignedSize * maxLights); // We want to initialize 3 times the amount of data required. - dataBuffer = logicalDevice->CreateBuffer(maxLights * lightDataAlignmentSize * SHGraphicsConstants::NUM_FRAME_BUFFERS, nullptr, maxLights * lightDataAlignmentSize * SHGraphicsConstants::NUM_FRAME_BUFFERS, vk::BufferUsageFlagBits::eStorageBuffer, VMA_MEMORY_USAGE_AUTO, VMA_ALLOCATION_CREATE_MAPPED_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT); + dataBuffer = logicalDevice->CreateBuffer(lightDataTotalAlignedSize * SHGraphicsConstants::NUM_FRAME_BUFFERS, nullptr, lightDataTotalAlignedSize * SHGraphicsConstants::NUM_FRAME_BUFFERS, vk::BufferUsageFlagBits::eStorageBuffer, VMA_MEMORY_USAGE_AUTO, VMA_ALLOCATION_CREATE_MAPPED_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT); } else { @@ -122,24 +136,27 @@ namespace SHADE uint32_t const OLD_MAX_LIGHTS = maxLights; // before we increase the number of lights, create space to store old data. - std::unique_ptr oldData = std::make_unique(lightDataAlignmentSize * OLD_MAX_LIGHTS); + std::unique_ptr oldData = std::make_unique(lightDataSize * OLD_MAX_LIGHTS); // copy data over. - std::memcpy (oldData.get(), intermediateData.get(), lightDataAlignmentSize * OLD_MAX_LIGHTS); + std::memcpy (oldData.get(), intermediateData.get(), lightDataSize * OLD_MAX_LIGHTS); // now we start to expand.... // double space for lights maxLights *= 2; + // calculate total + padding + lightDataTotalAlignedSize = logicalDevice->PadSSBOSize(lightDataAlignedSize * maxLights); + // destroy old data and initialize container for double the amount of data. - intermediateData = std::make_unique(lightDataAlignmentSize * maxLights); + intermediateData = std::make_unique(lightDataSize * maxLights); // copy old data to new container - std::memcpy(intermediateData.get(), oldData.get(), lightDataAlignmentSize * OLD_MAX_LIGHTS); + std::memcpy(intermediateData.get(), oldData.get(), lightDataSize * OLD_MAX_LIGHTS); // Resize the GPU buffer. TODO: Replace with Resize no copy here - dataBuffer->ResizeReplace(maxLights * lightDataAlignmentSize * SHGraphicsConstants::NUM_FRAME_BUFFERS, oldData.get(), lightDataAlignmentSize * OLD_MAX_LIGHTS); + dataBuffer->ResizeReplace(maxLights * lightDataTotalAlignedSize * SHGraphicsConstants::NUM_FRAME_BUFFERS, oldData.get(), lightDataTotalAlignedSize * OLD_MAX_LIGHTS); } @@ -171,6 +188,9 @@ namespace SHADE case SH_LIGHT_TYPE::SPOT: // TOOD: Change after creating spot light struct return 4; + case SH_LIGHT_TYPE::AMBIENT: + return sizeof(SHAmbientLightData); + return 4; case SH_LIGHT_TYPE::NUM_TYPES: default: return 4; @@ -187,7 +207,12 @@ namespace SHADE uint32_t SHLightingSubSystem::PerTypeData::GetAlignmentSize(void) const noexcept { - return lightDataAlignmentSize; + return lightDataTotalAlignedSize; + } + + uint32_t SHLightingSubSystem::PerTypeData::GetDataSize(void) const noexcept + { + return lightDataSize; } uint32_t SHLightingSubSystem::PerTypeData::GetNumLights(void) const noexcept @@ -231,7 +256,7 @@ namespace SHADE // Now that the container is big enough, bind the new light // Get address of write location - void* writeLocation = reinterpret_cast(intermediateData.get()) + (lightDataAlignmentSize * numLights); + void* writeLocation = reinterpret_cast(intermediateData.get()) + (lightDataAlignedSize * numLights); // Write the light data to address WriteLightToAddress(writeLocation, unboundLight); @@ -257,7 +282,7 @@ namespace SHADE /***************************************************************************/ void SHLightingSubSystem::PerTypeData::ModifyLight(SHLightComponent* lightComp) noexcept { - void* writeLocation = reinterpret_cast(intermediateData.get()) + (lightDataAlignmentSize * lightComp->GetIndexInBuffer()); + void* writeLocation = reinterpret_cast(intermediateData.get()) + (lightDataAlignedSize * lightComp->GetIndexInBuffer()); WriteLightToAddress(writeLocation, lightComp); } @@ -266,10 +291,15 @@ namespace SHADE if (intermediateData) { // we want to write to the offset of the current frame - dataBuffer->WriteToMemory(intermediateData.get(), lightDataAlignmentSize * numLights, 0, lightDataAlignmentSize * maxLights * frameIndex); + dataBuffer->WriteToMemory(intermediateData.get(), lightDataAlignedSize * numLights, 0, lightDataAlignedSize * maxLights * frameIndex); } } + void SHLightingSubSystem::PerTypeData::ResetNumLights(void) noexcept + { + numLights = 0; + } + /***************************************************************************/ /*! @@ -287,12 +317,12 @@ namespace SHADE // We bind the buffer with the correct desc set binding lightingDataDescSet->ModifyWriteDescBuffer(SHGraphicsConstants::DescriptorSetIndex::DYNAMIC_GLOBALS, - binding, + binding + 1, // we want to +1 here because the first binding is reserved for count { &buffer, 1 }, 0, - perTypeData[binding].GetAlignmentSize() * perTypeData[binding].GetMaxLights()); + perTypeData[binding].GetDataSize() * perTypeData[binding].GetMaxLights()); - lightingDataDescSet->UpdateDescriptorSetBuffer(SHGraphicsConstants::DescriptorSetIndex::DYNAMIC_GLOBALS, binding); + lightingDataDescSet->UpdateDescriptorSetBuffer(SHGraphicsConstants::DescriptorSetIndex::DYNAMIC_GLOBALS, binding + 1); // +1 here, same reason. see above } /***************************************************************************/ @@ -307,16 +337,27 @@ namespace SHADE { for (uint32_t i = 0; i < SHGraphicsConstants::NUM_FRAME_BUFFERS; ++i) { - for (uint32_t j = 0; j < dynamicOffsets.size(); ++j) + dynamicOffsets[i][0] = i * lightCountsAlignedSize; + // Even if the first binding is a count, we want to account for that too + for (uint32_t j = 0; j < static_cast(SH_LIGHT_TYPE::NUM_TYPES); ++j) { auto const& typeData = perTypeData[j]; { - dynamicOffsets[i][j] = j * typeData.GetAlignmentSize() * typeData.GetMaxLights(); + // +1 because 1st reserved for count + dynamicOffsets[i][j + 1] = i * typeData.GetAlignmentSize(); } } } } + void SHLightingSubSystem::ResetNumLights(void) noexcept + { + for (auto& data : perTypeData) + { + data.ResetNumLights(); + } + } + /***************************************************************************/ /*! @@ -346,12 +387,26 @@ namespace SHADE // initialize all the data first. We add more lights here as we add more types. perTypeData[i].InitializeData(logicalDevice, static_cast(i)); UpdateDescSet(i); + + // no lights at first + lightCountsData[i] = 0; } + + lightCountsAlignedSize = sizeof (uint32_t) * NUM_LIGHT_TYPES; + lightCountsAlignedSize = logicalDevice->PadUBOSize(lightCountsAlignedSize); + + // Create the GPU buffer to hold light count + lightCountsBuffer = logicalDevice->CreateBuffer(lightCountsAlignedSize * SHGraphicsConstants::NUM_FRAME_BUFFERS, nullptr, lightCountsAlignedSize * SHGraphicsConstants::NUM_FRAME_BUFFERS, vk::BufferUsageFlagBits::eUniformBuffer, VMA_MEMORY_USAGE_AUTO, VMA_ALLOCATION_CREATE_MAPPED_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT); + + lightingDataDescSet->ModifyWriteDescBuffer(SHGraphicsConstants::DescriptorSetIndex::DYNAMIC_GLOBALS, SHGraphicsConstants::DescriptorSetBindings::LIGHTING_COUNT, {&lightCountsBuffer, 1}, 0, sizeof (uint32_t) * NUM_LIGHT_TYPES); + lightingDataDescSet->UpdateDescriptorSetBuffer(SHGraphicsConstants::DescriptorSetIndex::DYNAMIC_GLOBALS, SHGraphicsConstants::DescriptorSetBindings::LIGHTING_COUNT); for (uint32_t i = 0; i < SHGraphicsConstants::NUM_FRAME_BUFFERS; ++i) { - dynamicOffsets[i].resize(NUM_LIGHT_TYPES); + dynamicOffsets[i].resize(NUM_LIGHT_TYPES + 1); // +1 for the count } + + numLightComponents = 0; } /***************************************************************************/ @@ -366,17 +421,32 @@ namespace SHADE /***************************************************************************/ void SHLightingSubSystem::Run(Handle cmdBuffer, uint32_t frameIndex) noexcept { + static uint32_t constexpr NUM_LIGHT_TYPES = SHUtilities::ToUnderlying(SH_LIGHT_TYPE::NUM_TYPES); + auto& lightComps = SHComponentManager::GetDense(); bool expanded = false; + bool rewrite = false; + + if (numLightComponents > lightComps.size()) + { + rewrite = true; + ResetNumLights(); + } + + numLightComponents = lightComps.size(); + for (auto& light : lightComps) { auto enumValue = SHUtilities::ToUnderlying(light.GetLightData().type); // First we want to make sure the light is already bound to the system. if it // isn't, we write it to the correct buffer. - if (!light.GetBound()) + if (!light.GetBound() || rewrite) { perTypeData[enumValue].AddLight(logicalDevice, &light, expanded); + + //// add to light count + //++lightCountsData[enumValue]; } // if there was modification to the light data @@ -396,6 +466,13 @@ namespace SHADE data.WriteToGPU(frameIndex); } + for (uint32_t i = 0; i < NUM_LIGHT_TYPES; ++i) + { + lightCountsData[i] = perTypeData[i].GetNumLights(); + } + + lightCountsBuffer->WriteToMemory(lightCountsData.data(), static_cast(lightCountsData.size()) * sizeof (uint32_t), 0, lightCountsAlignedSize * frameIndex); + // If any of the buffers got expanded, the descriptor set is invalid because the expanded buffer // is a new buffer. If some expansion was detected, update descriptor sets. if (expanded) @@ -412,7 +489,7 @@ namespace SHADE ComputeDynamicOffsets(); // Bind descriptor set (We bind at an offset because the buffer holds NUM_FRAME_BUFFERS sets of data). - cmdBuffer->BindDescriptorSet(lightingDataDescSet, SH_PIPELINE_TYPE::GRAPHICS, SHGraphicsConstants::DescriptorSetIndex::DYNAMIC_GLOBALS, {dynamicOffsets[frameIndex]}); + cmdBuffer->BindDescriptorSet(lightingDataDescSet, SH_PIPELINE_TYPE::COMPUTE, SHGraphicsConstants::DescriptorSetIndex::DYNAMIC_GLOBALS, {dynamicOffsets[frameIndex]}); } diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightingSubSystem.h b/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightingSubSystem.h index e5336b4e..fb7aa2de 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightingSubSystem.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightingSubSystem.h @@ -17,7 +17,7 @@ namespace SHADE class SHVkCommandBuffer; // Represents how the data will be interpreted in GPU. we want to copy to a container of these before passing to GPU. - struct SHDirectionalLightData + struct SHDirectionalLightData { //! Direction of the light SHVec3 direction; @@ -31,7 +31,27 @@ namespace SHADE uint32_t cullingMask; //! Diffuse color emitted by the light - SHVec4 diffuseColor; + alignas (16) SHVec4 diffuseColor; + + }; + + // Represents how the data will be interpreted in GPU. we want to copy to a container of these before passing to GPU. + struct SHAmbientLightData + { + //! Diffuse color emitted by the light + SHVec4 ambientColor; + + //! Strength of the ambient light + float strength; + + //! Represents if the light is active or not + uint32_t active; + + //! Each bit in this 32 bit field will represent a layer. If the bit is set, + //! when a fragment is being evaluated, the shader will use the fragment's + //! layer value to AND with the light's. If result is 1, do lighting calculations. + uint32_t cullingMask; + }; @@ -45,7 +65,7 @@ namespace SHADE /*-----------------------------------------------------------------------*/ /* STATIC MEMBER VARIABLES */ /*-----------------------------------------------------------------------*/ - static constexpr uint32_t STARTING_NUM_LIGHTS = 20; + static constexpr uint32_t STARTING_NUM_LIGHTS = 50; /*-----------------------------------------------------------------------*/ /* PRIVATE MEMBER VARIABLES */ @@ -53,8 +73,13 @@ namespace SHADE //! Capacity of the container. uint32_t maxLights; - //! SSBOs need to be aligned. This is to pad lighting structs - uint32_t lightDataAlignmentSize; + //! SSBOs need to be aligned. This is to pad descriptor offset + uint32_t lightDataTotalAlignedSize; + + //! size needed to store 1 struct object + uint32_t lightDataSize; + + uint32_t lightDataAlignedSize; //! type of the light. Will be used later when we want to expand SH_LIGHT_TYPE lightType; @@ -80,6 +105,7 @@ namespace SHADE void AddLight (Handle logicalDevice, SHLightComponent* unboundLight, bool expanded) noexcept; void ModifyLight (SHLightComponent* lightComp) noexcept; void WriteToGPU (uint32_t frameIndex) noexcept; + void ResetNumLights (void) noexcept; /*-----------------------------------------------------------------------*/ /* GETTERS */ @@ -87,6 +113,7 @@ namespace SHADE static uint32_t GetLightTypeSize (SH_LIGHT_TYPE type) noexcept; Handle GetDataBuffer (void) const noexcept; uint32_t GetAlignmentSize (void) const noexcept; + uint32_t GetDataSize (void) const noexcept; uint32_t GetNumLights (void) const noexcept; uint32_t GetMaxLights (void) const noexcept; }; @@ -105,11 +132,26 @@ namespace SHADE //! Container to store dynamic offsets for binding descriptor sets std::array, static_cast(SHGraphicsConstants::NUM_FRAME_BUFFERS)> dynamicOffsets; + //! holds the data that represents how many lights are in the scene + std::array(SH_LIGHT_TYPE::NUM_TYPES)> lightCountsData; + + //! GPU buffer to hold lightCountData + Handle lightCountsBuffer; + + //! For padding in the buffer + uint32_t lightCountsAlignedSize; + + //! Number of SHLightComponents recorded. If at the beginning of the run function the size returned by the dense + //! set is less than the size recorded, rewrite all light components into the its respective buffers. If its more, + //! don't do anything. + uint32_t numLightComponents; + /*-----------------------------------------------------------------------*/ /* PRIVATE MEMBER FUNCTIONS */ /*-----------------------------------------------------------------------*/ void UpdateDescSet (uint32_t binding) noexcept; void ComputeDynamicOffsets (void) noexcept; + void ResetNumLights (void) noexcept; public: diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/PerFrame/SHRenderContext.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/PerFrame/SHRenderContext.cpp index 8041adfd..45103819 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/PerFrame/SHRenderContext.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/PerFrame/SHRenderContext.cpp @@ -133,6 +133,7 @@ namespace SHADE { SHLOG_ERROR("Frame index retrieved from vkAcquireNextImageKHR is not the same as currentFrame."); } + currentFrame = frameIndex; } diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Textures/SHTextureLibrary.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Textures/SHTextureLibrary.cpp index 5c315ff6..8719458b 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Textures/SHTextureLibrary.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Textures/SHTextureLibrary.cpp @@ -214,66 +214,4 @@ namespace SHADE SHLOG_ERROR("Image layouts are invalid. "); } } - - vk::Format SHTextureLibrary::ddsLoaderToVkFormat(tinyddsloader::DDSFile::DXGIFormat format, bool isLinear) - { - switch (format) - { - case tinyddsloader::DDSFile::DXGIFormat::BC1_UNorm: - return vk::Format::eBc1RgbaUnormBlock; - case tinyddsloader::DDSFile::DXGIFormat::BC1_UNorm_SRGB: - return vk::Format::eBc1RgbaSrgbBlock; - case tinyddsloader::DDSFile::DXGIFormat::BC2_UNorm: - case tinyddsloader::DDSFile::DXGIFormat::BC2_UNorm_SRGB: - return isLinear ? vk::Format::eBc2UnormBlock : vk::Format::eBc2SrgbBlock; - case tinyddsloader::DDSFile::DXGIFormat::BC3_UNorm: - case tinyddsloader::DDSFile::DXGIFormat::BC3_UNorm_SRGB: - return isLinear ? vk::Format::eBc3UnormBlock : vk::Format::eBc3SrgbBlock; - case tinyddsloader::DDSFile::DXGIFormat::BC5_UNorm: - case tinyddsloader::DDSFile::DXGIFormat::BC5_SNorm: - return isLinear ? vk::Format::eBc5UnormBlock : vk::Format::eBc5SnormBlock; - case tinyddsloader::DDSFile::DXGIFormat::R8G8B8A8_UNorm: - case tinyddsloader::DDSFile::DXGIFormat::R8G8B8A8_UNorm_SRGB: - return isLinear ? vk::Format::eR8G8B8A8Unorm : vk::Format::eR8G8B8A8Srgb; - case tinyddsloader::DDSFile::DXGIFormat::R8G8B8A8_SNorm: - return vk::Format::eR8G8B8A8Snorm; - case tinyddsloader::DDSFile::DXGIFormat::B8G8R8A8_UNorm: - case tinyddsloader::DDSFile::DXGIFormat::B8G8R8A8_UNorm_SRGB: - return isLinear ? vk::Format::eB8G8R8A8Unorm : vk::Format::eB8G8R8A8Srgb; - case tinyddsloader::DDSFile::DXGIFormat::B8G8R8X8_UNorm: - case tinyddsloader::DDSFile::DXGIFormat::B8G8R8X8_UNorm_SRGB: - return isLinear ? vk::Format::eB8G8R8A8Unorm : vk::Format::eB8G8R8Srgb; - default: - throw std::runtime_error("Unsupported DDS format."); - } - - //switch (format) - //{ - //case tinyddsloader::DDSFile::DXGIFormat::R8G8B8A8_UNorm: - //case tinyddsloader::DDSFile::DXGIFormat::R8G8B8A8_UNorm_SRGB: - // return (isLinear) ? vk::Format::eR8G8B8A8Unorm : vk::Format::eR8G8B8A8Srgb; - // - - //case tinyddsloader::DDSFile::DXGIFormat::B8G8R8A8_UNorm: - //case tinyddsloader::DDSFile::DXGIFormat::B8G8R8A8_UNorm_SRGB: - // return (isLinear) ? vk::Format::eB8G8R8A8Unorm : vk::Format::eB8G8R8A8Srgb; - // - - //case tinyddsloader::DDSFile::DXGIFormat::BC1_UNorm: - //case tinyddsloader::DDSFile::DXGIFormat::BC1_UNorm_SRGB: - // return (isLinear) ? vk::Format::eBc1RgbaUnormBlock : vk::Format::eBc1RgbaSrgbBlock; - - //case tinyddsloader::DDSFile::DXGIFormat::BC2_UNorm: - //case tinyddsloader::DDSFile::DXGIFormat::BC2_UNorm_SRGB: - // return (isLinear) ? vk::Format::eBc2UnormBlock : vk::Format::eBc2SrgbBlock; - - //case tinyddsloader::DDSFile::DXGIFormat::BC3_UNorm: - //case tinyddsloader::DDSFile::DXGIFormat::BC3_UNorm_SRGB: - // return (isLinear) ? vk::Format::eBc3UnormBlock : vk::Format::eBc3SrgbBlock; - - //case tinyddsloader::DDSFile::DXGIFormat::BC5_UNorm: - // return (isLinear) ? vk::Format::eBc5UnormBlock : vk::Format::eBc5SnormBlock; - // - //} - } } diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Textures/SHTextureLibrary.h b/SHADE_Engine/src/Graphics/MiddleEnd/Textures/SHTextureLibrary.h index 935a7a4d..9357b0e0 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Textures/SHTextureLibrary.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Textures/SHTextureLibrary.h @@ -14,8 +14,6 @@ of DigiPen Institute of Technology is prohibited. // STL Includes #include -// External Dependencies -#include "tinyddsloader.h" // Project Includes #include "Resource/SHHandle.h" #include "Resource/SHResourceLibrary.h" @@ -169,6 +167,5 @@ namespace SHADE /* Helper Functions */ /*-----------------------------------------------------------------------------*/ void preparePipelineBarriers(vk::ImageLayout oldLayout, vk::ImageLayout newLayout, vk::PipelineStageFlagBits& srcStage, vk::PipelineStageFlagBits& dstStage, std::vector& barriers); - vk::Format ddsLoaderToVkFormat(tinyddsloader::DDSFile::DXGIFormat format, bool isLinear); }; } diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.cpp b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.cpp index 607c777a..aa9c7944 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.cpp +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.cpp @@ -276,7 +276,7 @@ namespace SHADE } // Create the subpass compute with the resources - auto nodeCompute = graphStorage->resourceManager->Create(graphStorage, computeShaderModule, std::move(nodeComputeResources)); + auto nodeCompute = graphStorage->resourceManager->Create(graphStorage, computeShaderModule, std::move(nodeComputeResources), nodeComputes.empty()); nodeComputes.push_back(nodeCompute); return nodeCompute; diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNodeCompute.cpp b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNodeCompute.cpp index a5208fcf..5323d706 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNodeCompute.cpp +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNodeCompute.cpp @@ -13,12 +13,13 @@ namespace SHADE { - SHRenderGraphNodeCompute::SHRenderGraphNodeCompute(Handle graphStorage, Handle computeShaderModule, std::vector>&& subpassComputeResources, float inNumWorkGroupScale/* = 1.0f*/) noexcept + SHRenderGraphNodeCompute::SHRenderGraphNodeCompute(Handle graphStorage, Handle computeShaderModule, std::vector>&& subpassComputeResources, bool followingEndRP, float inNumWorkGroupScale/* = 1.0f*/) noexcept : computePipeline{} , pipelineLayout{} , resources{} , groupSizeX{0} , groupSizeY{0} + , followingEndRenderpass {followingEndRP} , numWorkGroupScale {std::clamp(inNumWorkGroupScale, 0.0f, 1.0f)} { SHPipelineLayoutParams pipelineLayoutParams @@ -53,7 +54,6 @@ namespace SHADE descSetGroups[i] = graphStorage->descriptorPool->Allocate(layouts, variableCounts); } - HandleResize(); } @@ -68,8 +68,9 @@ namespace SHADE // dispatch compute cmdBuffer->ComputeDispatch(groupSizeX, groupSizeY, 1); - // TODO: barrier - + cmdBuffer->PipelineBarrier((followingEndRenderpass) ? vk::PipelineStageFlagBits::eFragmentShader : vk::PipelineStageFlagBits::eComputeShader, + vk::PipelineStageFlagBits::eFragmentShader, + {}, {}, {}, memoryBarriers[frameIndex]); } void SHRenderGraphNodeCompute::HandleResize(void) noexcept @@ -104,6 +105,36 @@ namespace SHADE groupSizeX = maxWidth / workGroupSizeX; groupSizeY = maxHeight / workGroupSizeY; + + for (uint32_t i = 0; auto& barriers : memoryBarriers) + { + barriers.clear(); + + for (auto& resource : resources) + { + vk::AccessFlags srcAccessMask = (followingEndRenderpass) ? vk::AccessFlagBits::eInputAttachmentRead : (vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eShaderWrite); + barriers.push_back(vk::ImageMemoryBarrier + { + .srcAccessMask = srcAccessMask, + .dstAccessMask = vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eShaderWrite, + .oldLayout = vk::ImageLayout::eGeneral, + .newLayout = vk::ImageLayout::eGeneral, + .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .image = resource->GetImage((resource->resourceTypeFlags & static_cast(SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT)) ? i : 0)->GetVkImage(), + .subresourceRange = vk::ImageSubresourceRange + { + .aspectMask = resource->imageAspectFlags, + .baseMipLevel = 0, + .levelCount = resource->mipLevels, + .baseArrayLayer = 0, + .layerCount = 1, + } + }); + } + + ++i; + } } } diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNodeCompute.h b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNodeCompute.h index ba4cf387..2cd3c948 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNodeCompute.h +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNodeCompute.h @@ -2,6 +2,7 @@ #include "Resource/SHHandle.h" #include "Graphics/MiddleEnd/Interface/SHGraphicsConstants.h" +#include "Graphics/SHVulkanIncludes.h" #include #include #include @@ -44,8 +45,12 @@ namespace SHADE float numWorkGroupScale; + bool followingEndRenderpass; + + std::array, SHGraphicsConstants::NUM_FRAME_BUFFERS> memoryBarriers; + public: - SHRenderGraphNodeCompute(Handle graphStorage, Handle computeShaderModule, std::vector>&& subpassComputeResources, float inNumWorkGroupScale = 1.0f) noexcept; + SHRenderGraphNodeCompute(Handle graphStorage, Handle computeShaderModule, std::vector>&& subpassComputeResources, bool followingEndRP, float inNumWorkGroupScale = 1.0f) noexcept; void Execute (Handle cmdBuffer, uint32_t frameIndex) noexcept; void HandleResize (void) noexcept; diff --git a/SHADE_Engine/src/Resource/SHHandle.h b/SHADE_Engine/src/Resource/SHHandle.h index 6acc85ed..49dd56b9 100644 --- a/SHADE_Engine/src/Resource/SHHandle.h +++ b/SHADE_Engine/src/Resource/SHHandle.h @@ -195,6 +195,11 @@ namespace SHADE template inline bool operator==(const Handle& rhs) const noexcept; + /*-----------------------------------------------------------------------------*/ + /* Query Functions */ + /*-----------------------------------------------------------------------------*/ + inline SHResourceLibraryBase* GetLibrary() const; + protected: /*-----------------------------------------------------------------------------*/ /* Data Members */ @@ -206,6 +211,7 @@ namespace SHADE /*-----------------------------------------------------------------------------*/ template friend class Handle; + friend class Convert; }; /// diff --git a/SHADE_Engine/src/Resource/SHHandle.hpp b/SHADE_Engine/src/Resource/SHHandle.hpp index c5d14132..ff544d3b 100644 --- a/SHADE_Engine/src/Resource/SHHandle.hpp +++ b/SHADE_Engine/src/Resource/SHHandle.hpp @@ -96,6 +96,11 @@ namespace SHADE return id.Raw == rhs.id.Raw && library == static_cast(rhs.library); } + SHResourceLibraryBase* SHADE::Handle::GetLibrary() const + { + return library; + } + /*---------------------------------------------------------------------------------*/ /* ISelfHandle - Constructors */ /*---------------------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Resource/SparseSet.hpp b/SHADE_Engine/src/Resource/SparseSet.hpp index 5afcdee7..816ca432 100644 --- a/SHADE_Engine/src/Resource/SparseSet.hpp +++ b/SHADE_Engine/src/Resource/SparseSet.hpp @@ -70,13 +70,13 @@ namespace SHADE } template - SparseSet::reference SparseSet::at(index_type idx) + typename SparseSet::reference SparseSet::at(index_type idx) { return const_cast(static_cast&>(*this).at(idx)); } template - SparseSet::const_reference SparseSet::at(index_type idx) const + typename SparseSet::const_reference SparseSet::at(index_type idx) const { // Range Check if (idx >= sparseArray.size() || !contains(idx)) @@ -84,7 +84,7 @@ namespace SHADE return denseArray[sparseArray[idx]]; } template - SparseSet::size_type SparseSet::size() const + typename SparseSet::size_type SparseSet::size() const { return denseArray.size(); } @@ -105,7 +105,7 @@ namespace SHADE } template template - SparseSet::reference SparseSet::insert(index_type idx, Args && ...args) + typename SparseSet::reference SparseSet::insert(index_type idx, Args && ...args) { // We need to resize the array if (idx >= sparseArray.size()) diff --git a/SHADE_Engine/src/Serialization/SHSerialization.cpp b/SHADE_Engine/src/Serialization/SHSerialization.cpp index 79c8308f..f8913d8d 100644 --- a/SHADE_Engine/src/Serialization/SHSerialization.cpp +++ b/SHADE_Engine/src/Serialization/SHSerialization.cpp @@ -14,6 +14,7 @@ #include "Math/Transform/SHTransformComponent.h" #include "Physics/Components/SHRigidBodyComponent.h" #include "ECS_Base/Managers/SHSystemManager.h" +#include "Graphics/MiddleEnd/Lights/SHLightComponent.h" #include "Scripting/SHScriptEngine.h" namespace SHADE @@ -192,6 +193,10 @@ namespace SHADE { components[rttr::type::get().get_name().data()] = SHSerializationHelper::SerializeComponentToNode(rigidbody); } + if(const auto light = SHComponentManager::GetComponent_s(eid)) + { + components[rttr::type::get().get_name().data()] = SHSerializationHelper::SerializeComponentToNode(light); + } node[ComponentsNode] = components; YAML::Node scripts; @@ -250,6 +255,10 @@ namespace SHADE if (id.has_value()) componentIDList.push_back(id.value()); + id = GetComponentID(componentsNode); + if(id.has_value()) + componentIDList.push_back(id.value()); + return componentIDList; } @@ -260,5 +269,6 @@ namespace SHADE return; SHSerializationHelper::InitializeComponentFromNode(componentsNode, eid); SHSerializationHelper::ConvertNodeToComponent(componentsNode, eid); + SHSerializationHelper::InitializeComponentFromNode(componentsNode, eid); } } diff --git a/SHADE_Engine/src/Serialization/SHSerializationHelper.hpp b/SHADE_Engine/src/Serialization/SHSerializationHelper.hpp index a8e46d88..047232a0 100644 --- a/SHADE_Engine/src/Serialization/SHSerializationHelper.hpp +++ b/SHADE_Engine/src/Serialization/SHSerializationHelper.hpp @@ -386,12 +386,12 @@ namespace SHADE return; auto rttrType = rttr::type::get(); auto componentNode = componentsNode[rttrType.get_name().data()]; - if (componentsNode.IsNull()) + if(!componentNode.IsDefined()) return; auto properties = rttrType.get_properties(); for (auto const& prop : properties) { - if (componentNode[prop.get_name().data()]) + if (componentNode[prop.get_name().data()].IsDefined()) { InitializeProperty(component, prop, componentNode[prop.get_name().data()]); } diff --git a/SHADE_Managed/src/Assets/Material.cxx b/SHADE_Managed/src/Assets/Material.cxx new file mode 100644 index 00000000..f4262c2a --- /dev/null +++ b/SHADE_Managed/src/Assets/Material.cxx @@ -0,0 +1,119 @@ +/************************************************************************************//*! +\file Material.cxx +\author Tng Kah Wei, kahwei.tng, 390009620 +\par email: kahwei.tng\@digipen.edu +\date Oct 28, 2022 +\brief Contains the implementation of the functions of the managed Material + class. + + Note: This file is written in C++17/CLI. + +Copyright (C) 2022 DigiPen Institute of Technology. +Reproduction or disclosure of this file or its contents without the prior written consent +of DigiPen Institute of Technology is prohibited. +*//*************************************************************************************/ +// Precompiled Headers +#include "SHpch.h" +// Primary Header +#include "Material.hxx" +// Standard Library +#include +// Project Includes +#include "Utility/Convert.hxx" + +namespace SHADE +{ + /*---------------------------------------------------------------------------------*/ + /* Macro Definitions */ + /*---------------------------------------------------------------------------------*/ + #define SET_PROP(NATIVE_TYPE, MANAGED_TYPE) \ + (T::typeid == MANAGED_TYPE::typeid) \ + { \ + const NATIVE_TYPE VAL = safe_cast(System::Convert::ChangeType(value, MANAGED_TYPE::typeid)); \ + NativeObject->SetProperty(PROP_NAME, VAL); \ + } \ + + #define SET_PROP_CONVERT(NATIVE_TYPE, MANAGED_TYPE) \ + (T::typeid == MANAGED_TYPE::typeid) \ + { \ + const NATIVE_TYPE VAL = Convert::ToNative(safe_cast(System::Convert::ChangeType(value, MANAGED_TYPE::typeid))); \ + NativeObject->SetProperty(PROP_NAME, VAL); \ + } \ + + #define GET_PROP(NATIVE_TYPE, MANAGED_TYPE) \ + (T::typeid == MANAGED_TYPE::typeid) \ + { \ + return safe_cast(NativeObject->GetProperty(PROP_NAME)); \ + } \ + + #define GET_PROP_CONVERT(NATIVE_TYPE, MANAGED_TYPE) \ + (T::typeid == MANAGED_TYPE::typeid) \ + { \ + return safe_cast(Convert::ToCLI(NativeObject->GetProperty(PROP_NAME))); \ + } + + /*---------------------------------------------------------------------------------*/ + /* Explicit Template Instantiation */ + /*---------------------------------------------------------------------------------*/ + template ref class NativeAsset; + + /*---------------------------------------------------------------------------------*/ + /* Constructors/Destructor */ + /*---------------------------------------------------------------------------------*/ + Material::Material(Handle material) + : NativeAsset{ material } + {} + + /*---------------------------------------------------------------------------------*/ + /* Material Properties Functions */ + /*---------------------------------------------------------------------------------*/ + generic + void Material::SetProperty(System::String^ name, T value) + { + if (!NativeObject) + throw gcnew System::InvalidOperationException("Attempted to set property on an invalid material!"); + + // Call the correct one based on type + const std::string PROP_NAME = Convert::ToNative(name); + try + { + if SET_PROP (int, System::Int32) + else if SET_PROP (int, System::Int64) + else if SET_PROP (float, float) + else if SET_PROP (double, double) + else if SET_PROP_CONVERT(SHVec2, Vector2) + else if SET_PROP_CONVERT(SHVec3, Vector3) + // TODO: Vector4 + } + catch (const std::invalid_argument&) + { + throw gcnew System::ArgumentException("Attempted to modify an invalid property on a material."); + } + } + + generic + T Material::GetProperty(System::String^ name) + { + if (!NativeObject) + throw gcnew System::InvalidOperationException("[Material] Attempted to get property of an invalid material!"); + + // Call the correct one based on type + const std::string PROP_NAME = Convert::ToNative(name); + try + { + if GET_PROP (int, System::Int32) + else if GET_PROP (int, System::Int64) + else if GET_PROP (float, float) + else if GET_PROP (double, double) + else if GET_PROP_CONVERT(SHVec2, Vector2) + else if GET_PROP_CONVERT(SHVec3, Vector3) + // TODO: Vector4 + } + catch (const std::invalid_argument&) + { + throw gcnew System::ArgumentException("Attempted to retrieve a property on a material with an invalid type."); + } + + throw gcnew System::ArgumentException("Attempted to retrieve an invalid property on a material."); + } +} diff --git a/SHADE_Managed/src/Assets/Material.hxx b/SHADE_Managed/src/Assets/Material.hxx new file mode 100644 index 00000000..25cc96a6 --- /dev/null +++ b/SHADE_Managed/src/Assets/Material.hxx @@ -0,0 +1,81 @@ +/************************************************************************************//*! +\file Material.hxx +\author Tng Kah Wei, kahwei.tng, 390009620 +\par email: kahwei.tng\@digipen.edu +\date Oct 28, 2022 +\brief Contains the definition of the managed Mesh class. + + Note: This file is written in C++17/CLI. + +Copyright (C) 2022 DigiPen Institute of Technology. +Reproduction or disclosure of this file or its contents without the prior written consent +of DigiPen Institute of Technology is prohibited. +*//*************************************************************************************/ +#pragma once + +// External Dependencies +#include "Resource/SHHandle.h" +#include "Graphics/MiddleEnd/Interface/SHMaterialInstance.h" +// Project Includes +#include "NativeAsset.hxx" +#include "Engine/GenericHandle.hxx" + +namespace SHADE +{ + /// + /// Managed counterpart of the native MaterialInstance object containing material + /// data that can be fed to Renderables for rendering. + /// + public ref class Material : public NativeAsset + { + internal: + /*-----------------------------------------------------------------------------*/ + /* Constructors/Destructor */ + /*-----------------------------------------------------------------------------*/ + /// + /// Constructor for the Material + /// + /// Handle to the native material object. + Material(Handle material); + + public: + /*-----------------------------------------------------------------------------*/ + /* Properties */ + /*-----------------------------------------------------------------------------*/ + // TODO: Change Shader + + /*-----------------------------------------------------------------------------*/ + /* Material Properties Functions */ + /*-----------------------------------------------------------------------------*/ + /// + /// Set the value of a specific property. + /// + /// Type of property to set. + /// Name of the property to set. + /// Value to set te property to. + /// + /// If this Material object is invalid. + /// + /// + /// If the name or type was specified that does not match the material's shader's + /// defined properties. + /// + generic + void SetProperty(System::String^ name, T value); + /// + /// Retrieves the value of a specified property on the material. + /// + /// Type of property to get. + /// Name of the property to get. + /// Value of that property on the material. + /// + /// If this Material object is invalid. + /// + /// + /// If the name or type was specified that does not match the material's shader's + /// defined properties. + /// + generic + T GetProperty(System::String^ name); + }; +} diff --git a/SHADE_Managed/src/Assets/Mesh.cxx b/SHADE_Managed/src/Assets/Mesh.cxx new file mode 100644 index 00000000..95a61ff6 --- /dev/null +++ b/SHADE_Managed/src/Assets/Mesh.cxx @@ -0,0 +1,34 @@ +/************************************************************************************//*! +\file Mesh.cxx +\author Tng Kah Wei, kahwei.tng, 390009620 +\par email: kahwei.tng\@digipen.edu +\date Oct 28, 2022 +\brief Contains the implementation of the functions of the managed Mesh class. + + Note: This file is written in C++17/CLI. + +Copyright (C) 2022 DigiPen Institute of Technology. +Reproduction or disclosure of this file or its contents without the prior written consent +of DigiPen Institute of Technology is prohibited. +*//*************************************************************************************/ +// Precompiled Headers +#include "SHpch.h" +// Primary Header +#include "Mesh.hxx" +// Project Headers +#include "Utility/Convert.hxx" + +namespace SHADE +{ + /*---------------------------------------------------------------------------------*/ + /* Explicit Template Instantiation */ + /*---------------------------------------------------------------------------------*/ + template ref class NativeAsset; + + /*---------------------------------------------------------------------------------*/ + /* Constructors/Destructor */ + /*---------------------------------------------------------------------------------*/ + Mesh::Mesh(Handle mesh) + : NativeAsset { mesh } + {} +} diff --git a/SHADE_Managed/src/Assets/Mesh.hxx b/SHADE_Managed/src/Assets/Mesh.hxx new file mode 100644 index 00000000..8cd356ba --- /dev/null +++ b/SHADE_Managed/src/Assets/Mesh.hxx @@ -0,0 +1,41 @@ +/************************************************************************************//*! +\file Mesh.hxx +\author Tng Kah Wei, kahwei.tng, 390009620 +\par email: kahwei.tng\@digipen.edu +\date Oct 28, 2022 +\brief Contains the definition of the managed Mesh class. + + Note: This file is written in C++17/CLI. + +Copyright (C) 2022 DigiPen Institute of Technology. +Reproduction or disclosure of this file or its contents without the prior written consent +of DigiPen Institute of Technology is prohibited. +*//*************************************************************************************/ +#pragma once + +// External Dependencies +#include "Resource/SHHandle.h" +#include "Graphics/MiddleEnd/Interface/SHMeshLibrary.h" +// Project Includes +#include "NativeAsset.hxx" +#include "Engine/GenericHandle.hxx" + +namespace SHADE +{ + /// + /// Managed counterpart of the native Mesh object containing vertex data that can + /// be fed to Renderables for rendering. + /// + public ref class Mesh : public NativeAsset + { + internal: + /*-----------------------------------------------------------------------------*/ + /* Constructors/Destructor */ + /*-----------------------------------------------------------------------------*/ + /// + /// Constructor for the Mesh + /// + /// Handle to the mesh object. + Mesh(Handle mesh); + }; +} diff --git a/SHADE_Managed/src/Assets/NativeAsset.cxx b/SHADE_Managed/src/Assets/NativeAsset.cxx new file mode 100644 index 00000000..674207a1 --- /dev/null +++ b/SHADE_Managed/src/Assets/NativeAsset.cxx @@ -0,0 +1,26 @@ +/************************************************************************************//*! +\file NativeAsset.cxx +\author Tng Kah Wei, kahwei.tng, 390009620 +\par email: kahwei.tng\@digipen.edu +\date Oct 28, 2022 +\brief Contains the explicit template instantiation for some types of the + templated managed NativeAsset class. + + Note: This file is written in C++17/CLI. + +Copyright (C) 2022 DigiPen Institute of Technology. +Reproduction or disclosure of this file or its contents without the prior written consent +of DigiPen Institute of Technology is prohibited. +*//*************************************************************************************/ +#include "SHpch.h" +// Primary Include +#include "NativeAsset.hxx" +// Project Includes +#include "Engine/GenericHandle.hxx" + +namespace SHADE +{ + /*---------------------------------------------------------------------------------*/ + /* Explicit Tempalte Instantiations */ + /*---------------------------------------------------------------------------------*/ +} \ No newline at end of file diff --git a/SHADE_Managed/src/Assets/NativeAsset.h++ b/SHADE_Managed/src/Assets/NativeAsset.h++ new file mode 100644 index 00000000..a4cd94b4 --- /dev/null +++ b/SHADE_Managed/src/Assets/NativeAsset.h++ @@ -0,0 +1,49 @@ +/************************************************************************************//*! +\file NativeAsset.h++ +\author Tng Kah Wei, kahwei.tng, 390009620 +\par email: kahwei.tng\@digipen.edu +\date Oct 28, 2022 +\brief Contains the definition of templated functions for the managed + NativeAsset classes. + + Note: This file is written in C++17/CLI. + +Copyright (C) 2022 DigiPen Institute of Technology. +Reproduction or disclosure of this file or its contents without the prior written consent +of DigiPen Institute of Technology is prohibited. +*//*************************************************************************************/ +#pragma once + +// Primary Include +#include "NativeAsset.hxx" + +namespace SHADE +{ + /*---------------------------------------------------------------------------------*/ + /* Properties */ + /*---------------------------------------------------------------------------------*/ + template + GenericHandle NativeAsset::NativeObjectHandle::get() + { + return nativeObjHandle; + } + template + Handle NativeAsset::NativeObject::get() + try + { + return Handle(Convert::ToNative(nativeObjHandle)); + } + catch (const BadHandleCastException&) + { + return Handle(); // Null handle + } + + /*---------------------------------------------------------------------------------*/ + /* Constructors */ + /*---------------------------------------------------------------------------------*/ + template + NativeAsset::NativeAsset(Handle nativeObj) + : nativeObjHandle{ Convert::ToCLI(Handle(nativeObj)) } + {} + +} diff --git a/SHADE_Managed/src/Assets/NativeAsset.hxx b/SHADE_Managed/src/Assets/NativeAsset.hxx new file mode 100644 index 00000000..68addb75 --- /dev/null +++ b/SHADE_Managed/src/Assets/NativeAsset.hxx @@ -0,0 +1,66 @@ +/************************************************************************************//*! +\file NativeAsset.hxx +\author Tng Kah Wei, kahwei.tng, 390009620 +\par email: kahwei.tng\@digipen.edu +\date Oct 28, 2022 +\brief Contains the template definition of the managed class that represents + native assets with a pointer to the corresponding native object. + + Note: This file is written in C++17/CLI. + +Copyright (C) 2021 DigiPen Institute of Technology. +Reproduction or disclosure of this file or its contents without the prior written consent +of DigiPen Institute of Technology is prohibited. +*//*************************************************************************************/ +#pragma once + +#include "Engine/GenericHandle.hxx" + +namespace SHADE +{ + /// + /// Generalised template class for a managed representation of a native asset + /// + /// + /// The type of the asset's native representation. + /// + template + public ref class NativeAsset + { + internal: + /*-----------------------------------------------------------------------------*/ + /* Properties */ + /*-----------------------------------------------------------------------------*/ + /// + /// Generic handle for the native object + /// + property GenericHandle NativeObjectHandle + { + GenericHandle get(); + } + /// + /// Copy of the Handle to the native object. + /// + property Handle NativeObject + { + Handle get(); + } + + /*-----------------------------------------------------------------------------*/ + /* Constructors/Destructor */ + /*-----------------------------------------------------------------------------*/ + /// + /// Constructor for the native asset + /// + /// Native asset object. + NativeAsset(Handle ptr); + + protected: + /*-----------------------------------------------------------------------------*/ + /* Data Members */ + /*-----------------------------------------------------------------------------*/ + GenericHandle nativeObjHandle; + }; +} + +#include "NativeAsset.h++" diff --git a/SHADE_Managed/src/Components/Collider.hxx b/SHADE_Managed/src/Components/Collider.hxx index 9555976f..dc17ae7f 100644 --- a/SHADE_Managed/src/Components/Collider.hxx +++ b/SHADE_Managed/src/Components/Collider.hxx @@ -27,7 +27,7 @@ namespace SHADE /// /// Base interface for all Collider Shapes. /// - public ref class CollisionShape + public ref class CollisionShape abstract { public: /*-----------------------------------------------------------------------------*/ @@ -194,7 +194,7 @@ namespace SHADE /* Properties */ /*-----------------------------------------------------------------------------*/ /// - /// Total number of ColliderBounds in the Collider component. + /// Total number of ColliderShapes in the Collider component. /// property int CollisionShapeCount { diff --git a/SHADE_Managed/src/Components/Renderable.cxx b/SHADE_Managed/src/Components/Renderable.cxx new file mode 100644 index 00000000..bc01bc03 --- /dev/null +++ b/SHADE_Managed/src/Components/Renderable.cxx @@ -0,0 +1,67 @@ +/************************************************************************************//*! +\file Renderable.cxx +\author Tng Kah Wei, kahwei.tng, 390009620 +\par email: kahwei.tng\@digipen.edu +\date Oct 28, 2022 +\brief Contains the definition of the functions of the managed Renderable class. + + Note: This file is written in C++17/CLI. + +Copyright (C) 2022 DigiPen Institute of Technology. +Reproduction or disclosure of this file or its contents without the prior written consent +of DigiPen Institute of Technology is prohibited. +*//*************************************************************************************/ +// Precompiled Headers +#include "SHpch.h" +// Primary Header +#include "Renderable.hxx" +#include "Assets/NativeAsset.hxx" +#include "Utility/Convert.hxx" + +namespace SHADE +{ + /*---------------------------------------------------------------------------------*/ + /* Constructors */ + /*---------------------------------------------------------------------------------*/ + Renderable::Renderable(Entity entity) + : Component(entity) + {} + + /*---------------------------------------------------------------------------------*/ + /* Properties */ + /*---------------------------------------------------------------------------------*/ + SHADE::Mesh^ Renderable::Mesh::get() + { + return gcnew SHADE::Mesh(GetNativeComponent()->GetMesh()); + } + void Renderable::Mesh::set(SHADE::Mesh^ value) + { + if (value == nullptr) + { + GetNativeComponent()->SetMesh(Handle()); + } + else + { + GetNativeComponent()->SetMesh(Handle(Convert::ToNative(value->NativeObjectHandle))); + } + } + SHADE::Material^ Renderable::Material::get() + { + return gcnew SHADE::Material(GetNativeComponent()->GetMaterial()); + } + void Renderable::Material::set(SHADE::Material^ value) + { + if (value == nullptr) + { + GetNativeComponent()->SetMaterial(Handle()); + } + else + { + GetNativeComponent()->SetMaterial(Handle(Convert::ToNative(value->NativeObjectHandle))); + } + } + System::Byte Renderable::LightLayer::get() + { + return GetNativeComponent()->GetLightLayer(); + } +} diff --git a/SHADE_Managed/src/Components/Renderable.hxx b/SHADE_Managed/src/Components/Renderable.hxx new file mode 100644 index 00000000..e8f11ef6 --- /dev/null +++ b/SHADE_Managed/src/Components/Renderable.hxx @@ -0,0 +1,73 @@ +/************************************************************************************//*! +\file Renderable.hxx +\author Tng Kah Wei, kahwei.tng, 390009620 +\par email: kahwei.tng\@digipen.edu +\date Oct 28, 2022 +\brief Contains the definition of the managed Renderable class with the + declaration of functions for working with it. + + Note: This file is written in C++17/CLI. + +Copyright (C) 2022 DigiPen Institute of Technology. +Reproduction or disclosure of this file or its contents without the prior written consent +of DigiPen Institute of Technology is prohibited. +*//*************************************************************************************/ +#pragma once + +// Project Includes +#include "Components/Component.hxx" +#include "Math/Vector3.hxx" +#include "Math/Quaternion.hxx" +// External Dependencies +#include "Graphics/MiddleEnd/Interface/SHRenderable.h" +#include "Assets/Mesh.hxx" +#include "Assets/Material.hxx" + +namespace SHADE +{ + /// + /// CLR version of the SHADE Engine's SHRenderableComponent. + /// + public ref class Renderable : public Component + { + internal: + /*-----------------------------------------------------------------------------*/ + /* Constructors */ + /*-----------------------------------------------------------------------------*/ + /// + /// Constructs a Renderable Component that represents a native Renderable + /// component tied to the specified Entity. + /// + /// Entity that this Component will be tied to. + Renderable(Entity entity); + + public: + /*-----------------------------------------------------------------------------*/ + /* Properties */ + /*-----------------------------------------------------------------------------*/ + /// + /// Mesh used to render this Renderable. + /// + property SHADE::Mesh^ Mesh + { + SHADE::Mesh^ get(); + void set(SHADE::Mesh^ value); + } + /// + /// Material used to render this Renderable. + /// + property SHADE::Material^ Material + { + SHADE::Material^ get(); + void set(SHADE::Material^ value); + } + /// + /// Material used to render this Renderable. + /// + property System::Byte LightLayer + { + System::Byte get(); + } + }; +} + diff --git a/SHADE_Managed/src/Engine/GenericHandle.cxx b/SHADE_Managed/src/Engine/GenericHandle.cxx new file mode 100644 index 00000000..41a69c18 --- /dev/null +++ b/SHADE_Managed/src/Engine/GenericHandle.cxx @@ -0,0 +1,47 @@ +/************************************************************************************//*! +\file Renderable.cxx +\author Tng Kah Wei, kahwei.tng, 390009620 +\par email: kahwei.tng\@digipen.edu +\date Oct 28, 2022 +\brief Contains the definition of the functions of the managed Renderable class. + + Note: This file is written in C++17/CLI. + +Copyright (C) 2022 DigiPen Institute of Technology. +Reproduction or disclosure of this file or its contents without the prior written consent +of DigiPen Institute of Technology is prohibited. +*//*************************************************************************************/ +#include "SHpch.h" +#include "GenericHandle.hxx" + +namespace SHADE +{ + /*---------------------------------------------------------------------------------*/ + /* Constructors */ + /*---------------------------------------------------------------------------------*/ + GenericHandle::GenericHandle(Handle handle) + : id { handle.GetId().Raw } + , library { reinterpret_cast(handle.GetLibrary()) } + {} + + /*---------------------------------------------------------------------------------*/ + /* Properties */ + /*---------------------------------------------------------------------------------*/ + System::UInt64 GenericHandle::Id::get() + { + return id; + } + System::IntPtr GenericHandle::Library::get() + { + return library; + } + + /*---------------------------------------------------------------------------------*/ + /* Overloaded Operators */ + /*---------------------------------------------------------------------------------*/ + GenericHandle::operator bool() + { + return library.ToPointer() != nullptr && id != System::UInt64::MaxValue; + } + +} diff --git a/SHADE_Managed/src/Engine/GenericHandle.hxx b/SHADE_Managed/src/Engine/GenericHandle.hxx new file mode 100644 index 00000000..3f8e395f --- /dev/null +++ b/SHADE_Managed/src/Engine/GenericHandle.hxx @@ -0,0 +1,68 @@ +/************************************************************************************//*! +\file Handle.hxx +\author Tng Kah Wei, kahwei.tng, 390009620 +\par email: kahwei.tng\@digipen.edu +\date Oct 28, 2022 +\brief Contains the definition of the managed GenericHandle struct. + + Note: This file is written in C++17/CLI. + +Copyright (C) 2022 DigiPen Institute of Technology. +Reproduction or disclosure of this file or its contents without the prior written consent +of DigiPen Institute of Technology is prohibited. +*//*************************************************************************************/ +#pragma once + +// External Dependencies +#include "Resource/SHHandle.h" + +namespace SHADE +{ + /// + /// Managed version of the generic Handle. + /// + public value struct GenericHandle + { + public: + /*-----------------------------------------------------------------------------*/ + /* Constructors */ + /*-----------------------------------------------------------------------------*/ + /// + /// Constructs a GenericHandle for a native generic Handle. + /// + /// Handle to create a GenericHandle from. + explicit GenericHandle(Handle handle); + + /*-----------------------------------------------------------------------------*/ + /* Properties */ + /*-----------------------------------------------------------------------------*/ + /// + /// The internal ID of the handle. + /// + property System::UInt64 Id + { + System::UInt64 get(); + } + /// + /// The library that the handle was issued by. + /// + property System::IntPtr Library + { + System::IntPtr get(); + } + + /*-----------------------------------------------------------------------------*/ + /* Overloaded Operators */ + /*-----------------------------------------------------------------------------*/ + /// + /// Converts to true if this is a valid Handle. + /// + inline operator bool(); + + /*-----------------------------------------------------------------------------*/ + /* Data Members */ + /*-----------------------------------------------------------------------------*/ + System::UInt64 id; + System::IntPtr library; + }; +} \ No newline at end of file diff --git a/SHADE_Managed/src/Graphics/Color.cxx b/SHADE_Managed/src/Graphics/Color.cxx new file mode 100644 index 00000000..cf1fff47 --- /dev/null +++ b/SHADE_Managed/src/Graphics/Color.cxx @@ -0,0 +1,154 @@ +/************************************************************************************//*! +\file Color.cxx +\author Tng Kah Wei, kahwei.tng, 390009620 +\par email: kahwei.tng\@digipen.edu +\date Nov 3, 2021 +\brief Contains the definition of the functions of the managed Color struct. + + Note: This file is written in C++17/CLI. + +Copyright (C) 2021 DigiPen Institute of Technology. +Reproduction or disclosure of this file or its contents without the prior written consent +of DigiPen Institute of Technology is prohibited. +*//*************************************************************************************/ +// Precompiled Headers +#include "SHpch.h" +// Primary Header +#include "Graphics/Color.hxx" +// Standard Libraries +#include +// Project Includes +#include "Math/Math.hxx" + +namespace SHADE +{ + /*---------------------------------------------------------------------------------*/ + /* Constructors */ + /*---------------------------------------------------------------------------------*/ + Color::Color(float _red) + : Color { _red, 0.0f, 0.0f, 1.0f } + {} + Color::Color(float _red, float _green) + : Color { _red, _green, 0.0f, 1.0f } + {} + Color::Color(float _red, float _green, float _blue) + : Color { _red, _green, _blue, 1.0f } + {} + Color::Color(float _red, float _green, float _blue, float _alpha) + : r { _red } + , g { _green } + , b { _blue } + , a { _alpha } + {} + + /*---------------------------------------------------------------------------------*/ + /* IEquatable */ + /*---------------------------------------------------------------------------------*/ + bool Color::Equals(Object^ o) + { + try + { + Color col = safe_cast(o); + return Equals(col); + } + catch (System::InvalidCastException^) + { + return false; + } + } + + /*---------------------------------------------------------------------------------*/ + /* Object Overrides */ + /*---------------------------------------------------------------------------------*/ + bool Color::Equals(Color other) + { + return Math::CompareFloat(this->r, other.r) + && + Math::CompareFloat(this->g, other.g) + && + Math::CompareFloat(this->b, other.b) + && + Math::CompareFloat(this->a, other.a); + } + int Color::GetHashCode() + { + const int HASH = 19; + const int HASH2 = 23; + const int HASH3 = 29; + return r.GetHashCode() * HASH + + g.GetHashCode() * HASH2 + + b.GetHashCode() * HASH3 + + a.GetHashCode(); + } + + /*---------------------------------------------------------------------------------*/ + /* Static Functions */ + /*---------------------------------------------------------------------------------*/ + Color Color::Lerp(Color colA, Color colB, float t) + { + return LerpUnclamped(colA, colB, std::clamp(t, 0.0f, 1.0f)); + } + + Color Color::LerpUnclamped(Color colA, Color colB, float t) + { + return colA + ((colB - colA) * t); + } + Color Color::operator+(Color lhs, Color rhs) + { + return Color + ( + lhs.r + rhs.r, + lhs.g + rhs.g, + lhs.b + rhs.b, + lhs.a + rhs.a + ); + } + Color Color::operator-(Color lhs, Color rhs) + { + return Color + ( + lhs.r - rhs.r, + lhs.g - rhs.g, + lhs.b - rhs.b, + lhs.a - rhs.a + ); + } + Color Color::operator*(Color lhs, Color rhs) + { + return Color + ( + lhs.r * rhs.r, + lhs.g * rhs.g, + lhs.b * rhs.b, + lhs.a * rhs.a + ); + } + Color Color::operator*(Color lhs, float rhs) + { + return Color + ( + lhs.r * rhs, + lhs.g * rhs, + lhs.b * rhs, + lhs.a * rhs + ); + } + Color Color::operator/(Color lhs, float rhs) + { + return Color + ( + lhs.r / rhs, + lhs.g / rhs, + lhs.b / rhs, + lhs.a / rhs + ); + } + bool Color::operator==(Color lhs, Color rhs) + { + return lhs.Equals(rhs); + } + bool Color::operator!=(Color lhs, Color rhs) + { + return !(lhs == rhs); + } +} diff --git a/SHADE_Managed/src/Graphics/Color.hxx b/SHADE_Managed/src/Graphics/Color.hxx new file mode 100644 index 00000000..d6a46216 --- /dev/null +++ b/SHADE_Managed/src/Graphics/Color.hxx @@ -0,0 +1,287 @@ +/************************************************************************************//*! +\file Color.hxx +\author Tng Kah Wei, kahwei.tng, 390009620 +\par email: kahwei.tng\@digipen.edu +\date Oct 28, 2022 +\brief Contains the definition of the managed Color struct with the + declaration of functions for working with it. + + Note: This file is written in C++17/CLI. + +Copyright (C) 2022 DigiPen Institute of Technology. +Reproduction or disclosure of this file or its contents without the prior written consent +of DigiPen Institute of Technology is prohibited. +*//*************************************************************************************/ +#pragma once + +namespace SHADE +{ + /// + /// CLR version of the the SHADE Engine's Color struct which describes a Color + /// encoded using floating point numbers that range from 0.0f to 1.0f. + /// + [System::Runtime::InteropServices::StructLayout(System::Runtime::InteropServices::LayoutKind::Sequential)] + public value struct Color : public System::IEquatable + { + public: + /*-----------------------------------------------------------------------------*/ + /* Type Definitions */ + /*-----------------------------------------------------------------------------*/ + /// + /// A static class that contains a set of default Colors. + /// + ref class Defaults abstract sealed + { + public: + /*-------------------------------------------------------------------------*/ + /* Properties */ + /*-------------------------------------------------------------------------*/ + /// + /// Pure black. + /// + static property Color Black + { + Color get() { return Color(0.0f, 0.0f, 0.0f); } + } + /// + /// Light Gray, lighter than gray. + /// + static property Color LightGray + { + Color get() { return Color(0.827451f, 0.827451f, 0.827451f); } + } + /// + /// Gray, halfway between black and white. + /// + static property Color Gray + { + Color get() { return Color(0.5f, 0.5f, 0.5f); } + } + /// + /// Dark Gray, darker than gray. + /// + static property Color DarkGray + { + Color get() { return Color(0.622f, 0.622f, 0.622f); } + } + /// + /// Pure white. + /// + static property Color White + { + Color get() { return Color(1.0f, 1.0f, 1.0f); } + } + /// + /// Pure red. + /// + static property Color Red + { + Color get() { return Color(1.0f, 0.0f, 0.0f); } + } + /// + /// Pure green. + /// + static property Color Green + { + Color get() { return Color(0.0f, 1.0f, 0.0f); } + } + /// + /// Pure blue. + /// + static property Color Blue + { + Color get() { return Color(0.0f, 0.0f, 1.0f); } + } + /// + /// Pure cyan, mix of pure green and blue. + /// + static property Color Cyan + { + Color get() { return Color(0.0f, 1.0f, 1.0f); } + } + /// + /// Pure magenta, mix of pure red and blue. + /// + static property Color Magenta + { + Color get() { return Color(1.0f, 0.0f, 1.0f); } + } + /// + /// Pure yellow, mix of pure red and green. + /// + static property Color Yellow + { + Color get() { return Color(1.0f, 1.0f, 0.0f); } + } + }; + + /*-----------------------------------------------------------------------------*/ + /* Constructors */ + /*-----------------------------------------------------------------------------*/ + /// + /// Constructor to construct a Color with the specified components with the + /// green, blue and alpha component set to 1.0f. + /// + /// Red component to set. + Color(float _red); + /// + /// Constructor to construct a Color with the specified components with the + /// blue and alpha component set to 1.0f. + /// + /// Red component to set. + /// Green component to set. + Color(float _red, float _green); + /// + /// Constructor to construct a Color with the specified components with the + /// alpha component set to 1.0f. + /// + /// Red component to set. + /// Green component to set. + /// Blue component to set. + Color(float _red, float _green, float _blue); + /// + /// Constructor to construct a Color with the specified components. + /// + /// Red component to set. + /// Green component to set. + /// Blue component to set. + /// Alpha component to set. + Color(float _red, float _green, float _blue, float _alpha); + + /*-----------------------------------------------------------------------------*/ + /* Public Members */ + /*-----------------------------------------------------------------------------*/ + /// + /// Red component of the colour. Ranges from 0.0f to 1.0f. + /// + float r; + /// + /// Green component of the colour. Ranges from 0.0f to 1.0f. + /// + float g; + /// + /// Blue component of the colour. Ranges from 0.0f to 1.0f. + /// + float b; + /// + /// Alpha component of the colour. Ranges from 0.0f to 1.0f. + /// + float a; + + /*-----------------------------------------------------------------------------*/ + /* IEquatable */ + /*-----------------------------------------------------------------------------*/ + /// + /// Compares equality with an object of the same type. + /// + /// The object to compare with. + /// True if both objects are the same. + virtual bool Equals(Color other); + + /*-----------------------------------------------------------------------------*/ + /* Object */ + /*-----------------------------------------------------------------------------*/ + /// + /// Compares equality with another unboxed object. + /// + /// The unboxed object to compare with. + /// True if both objects are the same. + bool Equals(Object^ o) override; + /// + /// Gets a unique hash for this object. + /// + /// Unique hash for this object. + int GetHashCode() override; + + + /*-----------------------------------------------------------------------------*/ + /* Static Functions */ + /*-----------------------------------------------------------------------------*/ + /// + /// Linearly interpolates between two specified points. + /// This is most commonly used to find a point some fraction of the way along a + /// line between two endpoints. + /// + /// The start Color, returned when t = 0.0. + /// The end Color, returned when t = 1.0. + /// + /// Value used to interpolate between a and b which is clamped to + /// the range[0, 1]. + /// + /// The interpolated Vector3. + static Color Lerp(Color colA, Color colB, float t); + /// + /// Linearly interpolates between two specified points. + /// This is most commonly used to find a point some fraction of the way along a + /// line between two endpoints. + /// Unlike Lerp(), t is not clamped to a range at all. + /// + /// The start Color, returned when t = 0.0. + /// The end Color, returned when t = 1.0. + /// Value used to interpolate between a and b. + /// The interpolated Color. + static Color LerpUnclamped(Color colA, Color colB, float t); + + /*-----------------------------------------------------------------------------*/ + /* Overloaded Operators */ + /*-----------------------------------------------------------------------------*/ + /// + /// Adds two Colors together and returns the result. + /// + /// Color to add. + /// Another Color to add. + /// The result of lhs added to rhs + static Color operator+(Color lhs, Color rhs); + /// + /// Subtracts a Color from another Color and returns the result. + /// + /// Color to subtract from. + /// Another Color to subtract. + /// The result of rhs subtracted from lhs. + static Color operator-(Color lhs, Color rhs); + /// + /// Calculates the component-wise multiplication of two Colors and returns the + /// result. + /// + /// Color to multiply with. + /// Another Color to multiply with. + /// The result of rhs subtracted from lhs. + static Color operator*(Color lhs, Color rhs); + /// + /// Calculates the multiplication of a Color with a scalar value and returns + /// the result. + /// + /// Color to multiply with. + /// Scalar to multiply with. + /// The result of the scalar multiplication. + static Color operator*(Color lhs, float rhs); + /// + /// Calculates the division of a Color with a scalar value and returns + /// the result. + /// + /// Scalar to divide with. + /// Color to divide with. + /// The result of the scalar division. + static Color operator/(Color lhs, float rhs); + /// + /// Checks if two Colors are approximately equal. + /// + /// Color to compare. + /// Another Color to compare. + /// + /// True if all components are approximately equal within the default + /// tolerance value. + /// + static bool operator==(Color lhs, Color rhs); + /// + /// Checks if two Colors are not approximately equal. + /// + /// Color to compare. + /// Another Color to compare. + /// + /// True if all components are not approximately equal within the default + /// tolerance value. + /// + static bool operator!=(Color lhs, Color rhs); + }; +} diff --git a/SHADE_Managed/src/Math/Math.cxx b/SHADE_Managed/src/Math/Math.cxx index fa72e2b6..bc625f5b 100644 --- a/SHADE_Managed/src/Math/Math.cxx +++ b/SHADE_Managed/src/Math/Math.cxx @@ -54,4 +54,15 @@ namespace SHADE { return (value - a) / (b - a); } + + bool Math::CompareFloat(float a, float b) + { + return CompareFloat(a, b, Epsilon); + } + + bool Math::CompareFloat(float a, float b, float tolerance) + { + return System::MathF::Abs(a - b) < tolerance; + } + } diff --git a/SHADE_Managed/src/Math/Math.hxx b/SHADE_Managed/src/Math/Math.hxx index 1578d97c..c6b8394e 100644 --- a/SHADE_Managed/src/Math/Math.hxx +++ b/SHADE_Managed/src/Math/Math.hxx @@ -81,12 +81,30 @@ namespace SHADE /// The interpolated float result between the two float values. static float LerpUnclamped(float a, float b, float t); /// - /// Calculates the linear parameter t that produces the interpolant value within the range [a, b]. + /// Calculates the linear parameter t that produces the interpolant value within + /// the range [a, b]. /// /// Start value. /// End value. /// Value between start and end. /// Percentage of value between start and end. static float InverseLerp(float a, float b, float value); + /// + /// Compares if two float values are close enough to be the same with a tolerance + /// of Epsilon. + /// + /// One of the values to compare. + /// The other value to compare. + /// True if a and b are practically the same. + static bool CompareFloat(float a, float b); + /// + /// Compares if two float values are close enough to be the same with the + /// specified tolerance value. + /// + /// One of the values to compare. + /// The other value to compare. + /// Tolerance for floating point comparison. + /// True if a and b are practically the same. + static bool CompareFloat(float a, float b, float tolerance); }; } diff --git a/SHADE_Managed/src/Utility/Convert.cxx b/SHADE_Managed/src/Utility/Convert.cxx index cb4815aa..1d89569f 100644 --- a/SHADE_Managed/src/Utility/Convert.cxx +++ b/SHADE_Managed/src/Utility/Convert.cxx @@ -84,4 +84,20 @@ namespace SHADE { return msclr::interop::marshal_as(str); } + + /*---------------------------------------------------------------------------------*/ + /* Handle Conversions */ + /*---------------------------------------------------------------------------------*/ + Handle Convert::ToNative(GenericHandle handle) + { + Handle nativeHandle; + nativeHandle.id.Raw = handle.Id; + nativeHandle.library = reinterpret_cast(handle.Library.ToPointer()); + return nativeHandle; + } + + GenericHandle Convert::ToCLI(Handle handle) + { + return GenericHandle(handle); + } } diff --git a/SHADE_Managed/src/Utility/Convert.hxx b/SHADE_Managed/src/Utility/Convert.hxx index 19faffde..d3dca740 100644 --- a/SHADE_Managed/src/Utility/Convert.hxx +++ b/SHADE_Managed/src/Utility/Convert.hxx @@ -20,6 +20,7 @@ of DigiPen Institute of Technology is prohibited. #include "Math/Vector/SHVec3.h" #include "Math/SHQuaternion.h" #include "Math/SHRay.h" +#include "Resource/SHHandle.h" // Project Includes #include "Engine/Entity.hxx" @@ -27,6 +28,7 @@ of DigiPen Institute of Technology is prohibited. #include "Math/Vector3.hxx" #include "Math/Quaternion.hxx" #include "Math/Ray.hxx" +#include "Engine/GenericHandle.hxx" namespace SHADE { @@ -118,6 +120,23 @@ namespace SHADE /// The native std::string to convert from. /// Managed copy of a native std::string. static System::String^ ToCLI(const std::string& str); + + /*-----------------------------------------------------------------------------*/ + /* Handle Conversions */ + /*-----------------------------------------------------------------------------*/ + /// + /// Converts from a managed GenericHandle to a Handle. + /// + /// GenericHandle to convert from. + /// Native generic Handle. + static Handle ToNative(GenericHandle handle); + /// + /// Converts from a native generic Handle to a managed GenericHandle. + /// + /// The native handle to convert. + /// Managed copy of the native Handle. + static GenericHandle ToCLI(Handle handle); + }; /// diff --git a/TempScriptsFolder/PhysicsTest.cs b/TempScriptsFolder/PhysicsTest.cs index 6f9774c9..add5971d 100644 --- a/TempScriptsFolder/PhysicsTest.cs +++ b/TempScriptsFolder/PhysicsTest.cs @@ -28,7 +28,7 @@ public class PhysicsTest : Script Debug.LogError("Collider is NULL!"); } - var subColider = Collider.ColliderBoundsCount; + var subColider = Collider.CollisionShapeCount; Debug.Log($"There are {subColider} colliders."); } protected override void update() diff --git a/TempShaderFolder/DeferredCompositeCs.glsl b/TempShaderFolder/DeferredCompositeCs.glsl new file mode 100644 index 00000000..c1caf0aa --- /dev/null +++ b/TempShaderFolder/DeferredCompositeCs.glsl @@ -0,0 +1,83 @@ +#version 450 + +struct DirectionalLightStruct +{ + vec3 direction; + uint isActive; + uint cullingMask; + vec4 diffuseColor; +}; + +struct AmbientLightStruct +{ + vec4 ambientColor; + float strength; + uint isActive; + uint cullingMask; +}; + +layout(local_size_x = 16, local_size_y = 16) in; +layout(set = 4, binding = 0, rgba32f) uniform image2D positions; +layout(set = 4, binding = 1, rgba32f) uniform image2D normals; +layout(set = 4, binding = 2, rgba8) uniform image2D albedo; +layout(set = 4, binding = 3, r32ui) uniform uimage2D lightLayerData; +layout(set = 4, binding = 4, rgba8) uniform image2D targetImage; + +layout(set = 1, binding = 0) uniform LightCounts +{ + uint directionalLights; + uint pointLights; + uint spotLights; + uint ambientLights; + +} lightCounts; + +layout(std430, set = 1, binding = 1) buffer DirectionalLightData +{ + DirectionalLightStruct dLightData[]; +} DirLightData; + +layout(std430, set = 1, binding = 4) buffer AmbientLightData +{ + AmbientLightStruct aLightData[]; +} AmbLightData; + +void main() +{ + // convenient variables + ivec2 globalThread = ivec2(gl_GlobalInvocationID); + + // Get the diffuse color of the pixel + vec3 pixelDiffuse = imageLoad (albedo, globalThread).rgb; + + // Get position of fragment in world space + vec3 positionWorld = imageLoad (positions, globalThread).rgb; + + // normal of fragment + vec3 normalWorld = imageLoad(normals, globalThread).rgb; + + vec3 fragColor = vec3 (0.0f); + + for (int i = 0; i < lightCounts.directionalLights; ++i) + { + // get normalized direction of light + vec3 dLightNormalized = normalize (DirLightData.dLightData[i].direction); + + // Get diffuse strength + float diffuseStrength = max (0, dot (dLightNormalized, normalWorld)); + + // Calculate the fragment color + fragColor += DirLightData.dLightData[i].diffuseColor.rgb * diffuseStrength.rrr * pixelDiffuse; + } + + for (int i = 0; i < lightCounts.ambientLights; ++i) + { + // Just do some add + //fragColor += pixelDiffuse.rgb * AmbLightData.aLightData[i].ambientColor.rgb * vec3 (0.5f); + fragColor += pixelDiffuse.rgb * AmbLightData.aLightData[i].ambientColor.rgb * vec3 (AmbLightData.aLightData[i].strength); + } + + // store result into result image + imageStore(targetImage, ivec2(gl_GlobalInvocationID.xy), vec4(fragColor, 1.0f)); + +} \ No newline at end of file diff --git a/TempShaderFolder/DeferredCompositeCs.spv b/TempShaderFolder/DeferredCompositeCs.spv new file mode 100644 index 00000000..03ef7ac5 Binary files /dev/null and b/TempShaderFolder/DeferredCompositeCs.spv differ diff --git a/TempShaderFolder/TestCubeFs.spv b/TempShaderFolder/TestCubeFs.spv new file mode 100644 index 00000000..2381b834 Binary files /dev/null and b/TempShaderFolder/TestCubeFs.spv differ diff --git a/TempShaderFolder/TestCubeVs.spv b/TempShaderFolder/TestCubeVs.spv new file mode 100644 index 00000000..d8c3c3d0 Binary files /dev/null and b/TempShaderFolder/TestCubeVs.spv differ