Added open by default for component inspector toggle headers, Added drag/drop receiving for all uint32_t fields #315
|
@ -1,4 +1,4 @@
|
|||
Start in Fullscreen: false
|
||||
Starting Scene ID: 97158628
|
||||
Starting Scene ID: 87244611
|
||||
Window Size: {x: 1920, y: 1080}
|
||||
Window Title: SHADE Engine
|
|
@ -0,0 +1 @@
|
|||
0
|
|
@ -0,0 +1,4 @@
|
|||
Start Maximized: true
|
||||
Working Scene ID: 97161771
|
||||
Window Size: {x: 1920, y: 1080}
|
||||
Style: 0
|
|
@ -7,6 +7,7 @@
|
|||
Translate: {x: 0, y: 0.304069757, z: 1.73034382}
|
||||
Rotate: {x: 0, y: 0, z: 0}
|
||||
Scale: {x: 1, y: 1, z: 1}
|
||||
IsActive: true
|
||||
Camera Component:
|
||||
Position: {x: 0, y: 0.304069757, z: 1.73034382}
|
||||
Pitch: 0
|
||||
|
@ -17,6 +18,7 @@
|
|||
Near: 0.00999999978
|
||||
Far: 10000
|
||||
Perspective: true
|
||||
IsActive: true
|
||||
Scripts: ~
|
||||
- EID: 1
|
||||
Name: Raccoon
|
||||
|
@ -24,12 +26,14 @@
|
|||
NumberOfChildren: 1
|
||||
Components:
|
||||
Transform Component:
|
||||
Translate: {x: 0, y: 0, z: 0}
|
||||
Rotate: {x: 0, y: 0, z: 0}
|
||||
Translate: {x: -1.86388135, y: 0.0544953719, z: 0}
|
||||
Rotate: {x: -0, y: 0, z: -0}
|
||||
Scale: {x: 1, y: 1, z: 1}
|
||||
IsActive: true
|
||||
Renderable Component:
|
||||
Mesh: 149697411
|
||||
Material: 126974645
|
||||
IsActive: true
|
||||
Scripts: ~
|
||||
- EID: 3
|
||||
Name: Bag
|
||||
|
@ -40,9 +44,11 @@
|
|||
Translate: {x: 0.006237939, y: -0.000393368304, z: 0}
|
||||
Rotate: {x: -0, y: 2.79945588, z: 0}
|
||||
Scale: {x: 1.0000881, y: 1, z: 1.0000881}
|
||||
IsActive: true
|
||||
Renderable Component:
|
||||
Mesh: 144838771
|
||||
Material: 123745521
|
||||
IsActive: true
|
||||
Scripts: ~
|
||||
- EID: 2
|
||||
Name: DirectionalLight
|
||||
|
@ -50,12 +56,13 @@
|
|||
NumberOfChildren: 0
|
||||
Components:
|
||||
Light Component:
|
||||
Position: {x: 0, y: 0, z: 0}
|
||||
Position: {x: 3, y: 4.5, z: 7}
|
||||
Type: Directional
|
||||
Direction: {x: 0, y: 0, z: 1}
|
||||
Direction: {x: -0.298000008, y: 0.522498012, z: 0.798600018}
|
||||
Color: {x: 1, y: 1, z: 1, w: 1}
|
||||
Layer: 4294967295
|
||||
Strength: 0
|
||||
IsActive: true
|
||||
Scripts: ~
|
||||
- EID: 4
|
||||
Name: AmbientLight
|
||||
|
@ -69,4 +76,20 @@
|
|||
Color: {x: 1, y: 1, z: 1, w: 1}
|
||||
Layer: 4294967295
|
||||
Strength: 0.600000024
|
||||
IsActive: true
|
||||
Scripts: ~
|
||||
- EID: 5
|
||||
Name: Floor
|
||||
IsActive: true
|
||||
NumberOfChildren: 0
|
||||
Components:
|
||||
Transform Component:
|
||||
Translate: {x: 0, y: 0.0810000002, z: 0}
|
||||
Rotate: {x: -1.57079637, y: 0, z: 0}
|
||||
Scale: {x: 50, y: 50, z: 50}
|
||||
IsActive: true
|
||||
Renderable Component:
|
||||
Mesh: 141771688
|
||||
Material: 124370424
|
||||
IsActive: true
|
||||
Scripts: ~
|
|
@ -1,7 +1,7 @@
|
|||
- EID: 0
|
||||
Name: Canvas
|
||||
IsActive: true
|
||||
NumberOfChildren: 1
|
||||
NumberOfChildren: 2
|
||||
Components:
|
||||
Canvas Component:
|
||||
Canvas Width: 10
|
||||
|
@ -28,6 +28,26 @@
|
|||
Clicked Texture: 0
|
||||
IsActive: true
|
||||
Scripts: ~
|
||||
- EID: 5
|
||||
Name: Default
|
||||
IsActive: true
|
||||
NumberOfChildren: 0
|
||||
Components:
|
||||
Transform Component:
|
||||
Translate: {x: 0, y: -3.9000001, z: 0}
|
||||
Rotate: {x: 0, y: 0, z: 0}
|
||||
Scale: {x: 1, y: 1, z: 1}
|
||||
IsActive: true
|
||||
Renderable Component:
|
||||
Mesh: 141771688
|
||||
Material: 129340704
|
||||
IsActive: true
|
||||
Toggle Button Component:
|
||||
Non Toggled Texture: 0
|
||||
Toggled Texture: 0
|
||||
Value: true
|
||||
IsActive: true
|
||||
Scripts: ~
|
||||
- EID: 1
|
||||
Name: Camera
|
||||
IsActive: true
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
Name: UI_Test
|
||||
ID: 87707373
|
||||
ID: 87244611
|
||||
Type: 5
|
||||
|
|
|
@ -6,6 +6,8 @@ struct DirectionalLightStruct
|
|||
uint isActive;
|
||||
uint cullingMask;
|
||||
vec4 diffuseColor;
|
||||
mat4 pvMatrix;
|
||||
uint shadowData;
|
||||
};
|
||||
|
||||
struct AmbientLightStruct
|
||||
|
@ -22,7 +24,10 @@ layout(set = 3, binding = 1, rgba32f) uniform image2D normals;
|
|||
layout(set = 3, binding = 2, rgba8) uniform image2D albedo;
|
||||
layout(set = 3, binding = 3, r32ui) uniform uimage2D lightLayerData;
|
||||
layout(set = 3, binding = 4, r8) uniform image2D ssaoBlurredImage;
|
||||
layout(set = 3, binding = 5, rgba8) uniform image2D targetImage;
|
||||
layout(set = 3, binding = 5, rgba8) uniform image2D positionWorldSpace;
|
||||
layout(set = 3, binding = 6, rgba8) uniform image2D targetImage;
|
||||
|
||||
layout (set = 4, binding = 0) uniform sampler2D shadowMaps[]; // for textures (global)
|
||||
|
||||
layout(set = 1, binding = 0) uniform LightCounts
|
||||
{
|
||||
|
@ -43,6 +48,25 @@ layout(std430, set = 1, binding = 4) buffer AmbientLightData
|
|||
AmbientLightStruct aLightData[];
|
||||
} AmbLightData;
|
||||
|
||||
float CalcShadowValue (sampler2D shadowMap, vec4 worldSpaceFragPos, mat4 lightPV)
|
||||
{
|
||||
vec4 fragPosLightPOV = lightPV * worldSpaceFragPos;
|
||||
vec3 converted = (fragPosLightPOV.xyz / fragPosLightPOV.w) * vec3(0.5f) + vec3(0.5f);
|
||||
|
||||
float sampledDepth = texture(shadowMap, converted.xy).r;
|
||||
|
||||
if (converted.x < 0.0f || converted.x > 1.0f || converted.y < 0.0f || converted.y > 1.0f)
|
||||
return 1.0f;
|
||||
|
||||
if (fragPosLightPOV.z > sampledDepth && fragPosLightPOV.w > 0.0f)
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
else
|
||||
return 1.0f;
|
||||
// return step (fragPosLightPOV.z, );
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
// convenient variables
|
||||
|
@ -52,6 +76,9 @@ void main()
|
|||
vec3 pixelDiffuse = imageLoad (albedo, globalThread).rgb;
|
||||
|
||||
// Get position of fragment in world space
|
||||
vec4 positionWorld = vec4 (imageLoad (positionWorldSpace, globalThread).rgb, 1.0f);
|
||||
|
||||
// Get position of fragment in view spacee
|
||||
vec3 positionView = imageLoad (positions, globalThread).rgb;
|
||||
|
||||
// normal of fragment
|
||||
|
@ -62,6 +89,18 @@ void main()
|
|||
|
||||
vec3 fragColor = vec3 (0.0f);
|
||||
|
||||
vec4 shadowMapColor = vec4 (1.0f);
|
||||
|
||||
for (int i = 0; i < lightCounts.ambientLights; ++i)
|
||||
{
|
||||
if ((lightLayer & AmbLightData.aLightData[i].cullingMask) != 0)
|
||||
{
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < lightCounts.directionalLights; ++i)
|
||||
{
|
||||
if ((lightLayer & DirLightData.dLightData[i].cullingMask) != 0)
|
||||
|
@ -74,16 +113,13 @@ void main()
|
|||
|
||||
// Calculate the fragment color
|
||||
fragColor += DirLightData.dLightData[i].diffuseColor.rgb * diffuseStrength.rrr * pixelDiffuse;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < lightCounts.ambientLights; ++i)
|
||||
{
|
||||
if ((lightLayer & AmbLightData.aLightData[i].cullingMask) != 0)
|
||||
{
|
||||
// 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);
|
||||
// If the shadow map is enabled (test the bit)
|
||||
if ((DirLightData.dLightData[i].shadowData & uint(1)) == 1)
|
||||
{
|
||||
// calculate shadow map here
|
||||
fragColor *= CalcShadowValue (shadowMaps[0], positionWorld, DirLightData.dLightData[i].pvMatrix).xxx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -92,6 +128,12 @@ void main()
|
|||
|
||||
// store result into result image
|
||||
imageStore(targetImage, ivec2(gl_GlobalInvocationID.xy), vec4(fragColor.rgb, 1.0f));
|
||||
//imageStore(targetImage, ivec2(gl_GlobalInvocationID.xy), vec4(ssaoVal.rrr, 1.0f));
|
||||
|
||||
// vec2 normTexCoords = vec2 (gl_GlobalInvocationID.xy) / vec2 (1024.0f);
|
||||
// vec4 shadowMapVal = texture(shadowMaps[0], normTexCoords);
|
||||
// if (normTexCoords.x > 1.0f || normTexCoords.y > 1.0f)
|
||||
// shadowMapVal = vec4(0.0f);
|
||||
|
||||
// imageStore(targetImage, ivec2(gl_GlobalInvocationID.xy), shadowMapVal.xxxx);
|
||||
|
||||
}
|
Binary file not shown.
|
@ -0,0 +1,22 @@
|
|||
#version 450
|
||||
#extension GL_KHR_vulkan_glsl : enable
|
||||
|
||||
//#include "ShaderDescriptorDefinitions.glsl"
|
||||
|
||||
|
||||
layout(location = 0) in vec3 aVertexPos;
|
||||
layout(location = 4) in mat4 worldTransform;
|
||||
|
||||
layout(set = 1, binding = 0) uniform CameraData
|
||||
{
|
||||
vec4 position;
|
||||
mat4 vpMat;
|
||||
mat4 viewMat;
|
||||
mat4 projMat;
|
||||
} cameraData;
|
||||
|
||||
void main()
|
||||
{
|
||||
// clip space for rendering
|
||||
gl_Position = cameraData.vpMat * worldTransform * vec4 (aVertexPos, 1.0f);
|
||||
}
|
Binary file not shown.
|
@ -0,0 +1,3 @@
|
|||
Name: ShadowMap_VS
|
||||
ID: 44646107
|
||||
Type: 2
|
|
@ -16,11 +16,12 @@ layout(location = 0) in struct
|
|||
vec4 vertPos; // location 0
|
||||
vec2 uv; // location = 1
|
||||
vec4 normal; // location = 2
|
||||
vec4 worldPos; // location = 3
|
||||
|
||||
} In;
|
||||
|
||||
// material stuff
|
||||
layout(location = 3) flat in struct
|
||||
layout(location = 4) flat in struct
|
||||
{
|
||||
int materialIndex;
|
||||
uint eid;
|
||||
|
@ -38,12 +39,14 @@ layout(location = 1) out uint outEntityID;
|
|||
layout(location = 2) out uint lightLayerIndices;
|
||||
layout(location = 3) out vec4 normals;
|
||||
layout(location = 4) out vec4 albedo;
|
||||
layout(location = 5) out vec4 worldSpacePosition;
|
||||
|
||||
void main()
|
||||
{
|
||||
position = In.vertPos;
|
||||
normals = In.normal;
|
||||
albedo = texture(textures[nonuniformEXT(MatProp.data[In2.materialIndex].textureIndex)], In.uv) * MatProp.data[In2.materialIndex].color;
|
||||
worldSpacePosition = In.worldPos;
|
||||
|
||||
outEntityID = In2.eid;
|
||||
lightLayerIndices = In2.lightLayerIndex;
|
||||
|
|
Binary file not shown.
|
@ -17,11 +17,12 @@ layout(location = 0) out struct
|
|||
vec4 vertPos; // location 0
|
||||
vec2 uv; // location = 1
|
||||
vec4 normal; // location = 2
|
||||
vec4 worldPos; // location = 3
|
||||
|
||||
} Out;
|
||||
|
||||
// material stuff
|
||||
layout(location = 3) out struct
|
||||
layout(location = 4) out struct
|
||||
{
|
||||
int materialIndex;
|
||||
uint eid;
|
||||
|
@ -49,6 +50,8 @@ void main()
|
|||
// gBuffer position will be in view space
|
||||
Out.vertPos = modelViewMat * vec4(aVertexPos, 1.0f);
|
||||
|
||||
Out.worldPos = worldTransform * vec4 (aVertexPos, 1.0f);
|
||||
|
||||
// uvs for texturing in fragment shader
|
||||
Out.uv = aUV;
|
||||
|
||||
|
|
Binary file not shown.
|
@ -270,8 +270,12 @@ namespace SHADE
|
|||
camera.viewMatrix(1, 3) = -UP.Dot(camera.position + camera.offset);
|
||||
camera.viewMatrix(2, 3) = -view.Dot(camera.position + camera.offset);
|
||||
|
||||
|
||||
|
||||
//SHVec3 target{ 0.0f,0.0f,-1.0f };
|
||||
//target = SHVec3::RotateX(target, SHMath::DegreesToRadians(camera.pitch));
|
||||
//target = SHVec3::RotateY(target, SHMath::DegreesToRadians(camera.yaw));
|
||||
//target += camera.position;
|
||||
|
||||
//camera.viewMatrix = SHMatrix::Transpose(SHMatrix::LookAtLH(camera.position, target, SHVec3(0.0f, -1.0f, 0.0f)));
|
||||
|
||||
camera.dirtyView = false;
|
||||
}
|
||||
|
@ -309,7 +313,9 @@ namespace SHADE
|
|||
camera.orthoProjMatrix(2, 3) = -n / (f-n);
|
||||
camera.orthoProjMatrix(3, 3) = 1.0f;
|
||||
|
||||
//camera.orthoProjMatrix = SHMatrix::OrthographicRH(camera.GetWidth(), camera.GetHeight(), camera.GetNear(), camera.GetFar());
|
||||
//camera.perspProjMatrix = SHMatrix::OrthographicLH(9.0f, 9.0f, 0.1f, 20.0f);
|
||||
camera.orthoProjMatrix = SHMatrix::OrthographicRH(camera.GetWidth(), camera.GetHeight(), camera.GetNear(), camera.GetFar());
|
||||
//camera.perspProjMatrix = SHMatrix::OrthographicLH(5.0f, 5.0f, 0.1f, 20.0f);
|
||||
//camera.projMatrix.Transpose();
|
||||
|
||||
camera.dirtyProj = false;
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
#include "UI/SHCanvasComponent.h"
|
||||
#include "UI/SHButtonComponent.h"
|
||||
#include "UI/SHUIComponent.h"
|
||||
#include "UI/SHToggleButtonComponent.h"
|
||||
#include "UI/SHSliderComponent.h"
|
||||
#include "Graphics/MiddleEnd/Lights/SHLightComponent.h"
|
||||
#include "Graphics/MiddleEnd/Interface/SHRenderable.h"
|
||||
#include "Physics/Interface/SHColliderComponent.h"
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
#include "SH_API.h"
|
||||
#include "Events/SHEventManager.hpp"
|
||||
|
||||
|
||||
#include <tuple>
|
||||
#include <cassert>
|
||||
|
||||
namespace SHADE
|
||||
|
@ -151,6 +151,32 @@ namespace SHADE
|
|||
return (componentSet.GetSparseSet<T>()->GetElement_s(EntityHandleGenerator::GetIndex(entityID)));
|
||||
}
|
||||
|
||||
/*!*************************************************************************
|
||||
* \brief
|
||||
* Gets the Component of the entity with the specified entityID
|
||||
*
|
||||
* This is the safe version of GetComponent_s which does a HasComponent to make
|
||||
* sure that the entity has such a component and returns nullptr if it doesn't
|
||||
*
|
||||
* This safe version also checks if the sparse set of this component type
|
||||
* has been created in SHComponentManager and creates one if it doesn't
|
||||
*
|
||||
* @tparam T...
|
||||
* Pack of Types for all the Components to get.
|
||||
* \param entityID
|
||||
* EntityID of the entity that we are trying to get the component of.
|
||||
* \return
|
||||
* A tuple of pointers to all the components specified.
|
||||
* Returns nullptr if the entity does not contain such a component.
|
||||
***************************************************************************/
|
||||
|
||||
template<typename ...T>
|
||||
static std::enable_if_t<(... && std::is_base_of_v<SHComponent, T>), std::tuple<T*...>> GetComponents(EntityID entityID) noexcept
|
||||
{
|
||||
return std::make_tuple<T*...>(GetComponent_s<T>(entityID)...);
|
||||
}
|
||||
|
||||
|
||||
/*!*************************************************************************
|
||||
* \brief
|
||||
* Gets the Component of the entity with the specified entityID
|
||||
|
|
|
@ -259,6 +259,13 @@ namespace SHADE
|
|||
}
|
||||
}
|
||||
|
||||
if (ImGui::IsItemHovered())
|
||||
{
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::Text("AssetID: %zu | Path: %s", asset->id, asset->path.c_str());
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
|
||||
//TODO: Combine Draw asset and Draw Folder recursive drawing
|
||||
const ImColor treeLineColor = ImGui::GetColorU32(ImGuiCol_CheckMark);
|
||||
const float horizontalOffset = 0.0f;
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "UI/SHUIComponent.h"
|
||||
#include "UI/SHCanvasComponent.h"
|
||||
#include "UI/SHButtonComponent.h"
|
||||
#include "UI/SHToggleButtonComponent.h"
|
||||
#include "SHEditorComponentView.h"
|
||||
#include "AudioSystem/SHAudioListenerComponent.h"
|
||||
#include "Graphics/MiddleEnd/TextRendering/SHTextRenderableComponent.h"
|
||||
|
@ -153,6 +154,10 @@ namespace SHADE
|
|||
{
|
||||
DrawComponent(buttonComponent);
|
||||
}
|
||||
if (auto toggleButton = SHComponentManager::GetComponent_s<SHToggleButtonComponent>(eid))
|
||||
{
|
||||
DrawComponent(toggleButton);
|
||||
}
|
||||
ImGui::Separator();
|
||||
// Render Scripts
|
||||
SHScriptEngine* scriptEngine = static_cast<SHScriptEngine*>(SHSystemManager::GetSystem<SHScriptEngine>());
|
||||
|
@ -166,6 +171,7 @@ namespace SHADE
|
|||
DrawAddComponentButton<SHLightComponent>(eid);
|
||||
DrawAddComponentButton<SHCanvasComponent>(eid);
|
||||
DrawAddComponentButton<SHButtonComponent>(eid);
|
||||
DrawAddComponentButton<SHToggleButtonComponent>(eid);
|
||||
|
||||
// Components that require Transforms
|
||||
|
||||
|
|
|
@ -468,7 +468,7 @@ namespace SHADE
|
|||
|
||||
//auto const& renderers = gfxSystem->GetDefaultViewport()->GetRenderers();
|
||||
auto renderGraph = gfxSystem->GetRenderGraph();
|
||||
auto renderPass = renderGraph->GetNode("ImGui Node")->GetRenderpass();
|
||||
auto renderPass = renderGraph->GetNode(SHGraphicsConstants::RenderGraphEntityNames::IMGUI_PASS.data())->GetRenderpass();
|
||||
|
||||
if(ImGui_ImplVulkan_Init(&initInfo, renderPass->GetVkRenderpass()) == false)
|
||||
{
|
||||
|
@ -487,7 +487,7 @@ namespace SHADE
|
|||
|
||||
ImGui_ImplVulkan_DestroyFontUploadObjects();
|
||||
|
||||
renderGraph->GetNode("ImGui Node")->GetSubpass("ImGui Draw")->AddExteriorDrawCalls([](Handle<SHVkCommandBuffer> cmd, Handle<SHRenderer> renderer, uint32_t frameIndex)
|
||||
renderGraph->GetNode(SHGraphicsConstants::RenderGraphEntityNames::IMGUI_PASS.data())->GetSubpass("ImGui Draw")->AddExteriorDrawCalls([](Handle<SHVkCommandBuffer> cmd, Handle<SHRenderer> renderer, uint32_t frameIndex)
|
||||
{
|
||||
cmd->BeginLabeledSegment("ImGui Draw");
|
||||
ImGui_ImplVulkan_RenderDrawData(ImGui::GetDrawData(), cmd->GetVkCommandBuffer());
|
||||
|
|
|
@ -23,4 +23,5 @@ constexpr SHEventIdentifier SH_SCENE_INIT_POST { 14 };
|
|||
constexpr SHEventIdentifier SH_SCENE_EXIT_PRE { 15 };
|
||||
constexpr SHEventIdentifier SH_SCENE_EXIT_POST { 16 };
|
||||
constexpr SHEventIdentifier SH_GRAPHICS_LIGHT_ENABLE_SHADOW_EVENT { 17 };
|
||||
constexpr SHEventIdentifier SH_BUTTON_CLICK_EVENT { 18 };
|
||||
|
||||
|
|
|
@ -175,6 +175,27 @@ namespace SHADE
|
|||
writeInfo.descImageInfos[i].sampler = sampler ? sampler->GetVkSampler() : nullptr;
|
||||
writeInfo.descImageInfos[i].imageLayout = layout;
|
||||
}
|
||||
|
||||
// Rest is not used, so it doesn't matter what's in them, we just want to pacify Vulkan
|
||||
for (uint32_t i = imageViewsAndSamplers.size(); i < writeInfo.descImageInfos.size(); ++i)
|
||||
{
|
||||
writeInfo.descImageInfos[i].sampler = std::get<Handle<SHVkSampler>>(imageViewsAndSamplers.back())->GetVkSampler();
|
||||
}
|
||||
}
|
||||
|
||||
void SHVkDescriptorSetGroup::ModifyWriteDescImage(uint32_t set, uint32_t binding, std::tuple<Handle<SHVkImageView>, Handle<SHVkSampler>, vk::ImageLayout> const& imageViewAndSampler, uint32_t descIndex) noexcept
|
||||
{
|
||||
// Find the target writeDescSet
|
||||
BindingAndSetHash writeHash = binding;
|
||||
writeHash |= static_cast<uint64_t>(set) << 32;
|
||||
auto& writeInfo = updater.writeInfos[updater.writeHashMap.at(writeHash)];
|
||||
|
||||
// write sampler and image view
|
||||
auto& [view, sampler, layout] = imageViewAndSampler;
|
||||
writeInfo.descImageInfos[descIndex].imageView = view->GetImageView();
|
||||
writeInfo.descImageInfos[descIndex].sampler = sampler ? sampler->GetVkSampler() : nullptr;
|
||||
writeInfo.descImageInfos[descIndex].imageLayout = layout;
|
||||
|
||||
}
|
||||
|
||||
void SHVkDescriptorSetGroup::ModifyWriteDescBuffer(uint32_t set, uint32_t binding, std::span<Handle<SHVkBuffer>> const& buffers, uint32_t offset, uint32_t range) noexcept
|
||||
|
@ -200,6 +221,28 @@ namespace SHADE
|
|||
|
||||
}
|
||||
|
||||
void SHVkDescriptorSetGroup::UpdateDescriptorSetImage(uint32_t set, uint32_t binding, uint32_t descArrayIndex) noexcept
|
||||
{
|
||||
vk::WriteDescriptorSet writeDescSet{};
|
||||
|
||||
// Get binding + set hash
|
||||
BindingAndSetHash bsHash = SHVkUtil::GenBindingSetHash(set, binding);
|
||||
|
||||
// to index a write for a binding
|
||||
uint32_t writeInfoIndex = updater.writeHashMap[bsHash];
|
||||
|
||||
// Initialize info for write
|
||||
writeDescSet.descriptorType = layoutsUsed[set]->GetBindings()[binding].Type;
|
||||
writeDescSet.dstArrayElement = descArrayIndex;
|
||||
writeDescSet.dstSet = descSets[set];
|
||||
writeDescSet.dstBinding = binding;
|
||||
|
||||
writeDescSet.pImageInfo = updater.writeInfos[writeInfoIndex].descImageInfos.data() + descArrayIndex;
|
||||
writeDescSet.descriptorCount = 1u;
|
||||
|
||||
device->UpdateDescriptorSet(writeDescSet);
|
||||
}
|
||||
|
||||
void SHVkDescriptorSetGroup::UpdateDescriptorSetImages(uint32_t set, uint32_t binding) noexcept
|
||||
{
|
||||
vk::WriteDescriptorSet writeDescSet{};
|
||||
|
|
|
@ -63,10 +63,12 @@ namespace SHADE
|
|||
/*-----------------------------------------------------------------------------*/
|
||||
/* Public member functions */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
void UpdateDescriptorSetImage (uint32_t set, uint32_t binding, uint32_t descArrayIndex) noexcept;
|
||||
void UpdateDescriptorSetImages(uint32_t set, uint32_t binding) noexcept;
|
||||
void UpdateDescriptorSetBuffer(uint32_t set, uint32_t binding) noexcept;
|
||||
|
||||
void ModifyWriteDescImage(uint32_t set, uint32_t binding, std::span<std::tuple<Handle<SHVkImageView>, Handle<SHVkSampler>, vk::ImageLayout>> const& imageViewsAndSamplers) noexcept;
|
||||
void ModifyWriteDescImage(uint32_t set, uint32_t binding, std::tuple<Handle<SHVkImageView>, Handle<SHVkSampler>, vk::ImageLayout> const& imageViewAndSampler, uint32_t descIndex) noexcept;
|
||||
void ModifyWriteDescBuffer (uint32_t set, uint32_t binding, std::span<Handle<SHVkBuffer>> const& buffers, uint32_t offset, uint32_t range) noexcept;
|
||||
|
||||
|
||||
|
|
|
@ -183,33 +183,43 @@ namespace SHADE
|
|||
/*if (!extensionsSupported)
|
||||
SHUtil::ReportWarning("Some of the required extensions cannot be found on the physical device. ");*/
|
||||
|
||||
vk::PhysicalDeviceFeatures features{}; // ADD MORE FEATURES HERE IF NEEDED
|
||||
vk::PhysicalDeviceDescriptorIndexingFeatures descIndexingFeature
|
||||
{
|
||||
.shaderSampledImageArrayNonUniformIndexing = VK_TRUE,
|
||||
.descriptorBindingPartiallyBound = VK_TRUE,
|
||||
.descriptorBindingVariableDescriptorCount = VK_TRUE,
|
||||
.runtimeDescriptorArray = VK_TRUE,
|
||||
};
|
||||
|
||||
vk::PhysicalDeviceRobustness2FeaturesEXT robustFeatures
|
||||
{
|
||||
.nullDescriptor = VK_TRUE,
|
||||
};
|
||||
|
||||
robustFeatures.pNext = &descIndexingFeature;
|
||||
|
||||
vk::PhysicalDeviceFeatures2 features{}; // ADD MORE FEATURES HERE IF NEEDED
|
||||
|
||||
// point and lines fill mode
|
||||
features.fillModeNonSolid = VK_TRUE;
|
||||
features.samplerAnisotropy = VK_TRUE;
|
||||
features.multiDrawIndirect = VK_TRUE;
|
||||
features.independentBlend = VK_TRUE;
|
||||
features.features.fillModeNonSolid = VK_TRUE;
|
||||
features.features.samplerAnisotropy = VK_TRUE;
|
||||
features.features.multiDrawIndirect = VK_TRUE;
|
||||
features.features.independentBlend = VK_TRUE;
|
||||
features.features.wideLines = VK_TRUE;
|
||||
|
||||
// for wide lines
|
||||
features.wideLines = true;
|
||||
|
||||
vk::PhysicalDeviceDescriptorIndexingFeatures descIndexingFeature{};
|
||||
descIndexingFeature.descriptorBindingVariableDescriptorCount = true;
|
||||
descIndexingFeature.shaderSampledImageArrayNonUniformIndexing = true;
|
||||
descIndexingFeature.runtimeDescriptorArray = true;
|
||||
features.pNext = &robustFeatures;
|
||||
|
||||
// Prepare to create the device
|
||||
vk::DeviceCreateInfo deviceCreateInfo
|
||||
{
|
||||
.pNext = &descIndexingFeature,
|
||||
.pNext = &features,
|
||||
.queueCreateInfoCount = static_cast<uint32_t>(queueCreateInfos.size()),
|
||||
.pQueueCreateInfos = queueCreateInfos.data(),
|
||||
.enabledLayerCount = 0, // deprecated and ignored
|
||||
.ppEnabledLayerNames = nullptr, // deprecated and ignored
|
||||
.enabledExtensionCount = !extensionsSupported ? 0 : static_cast<uint32_t>(requiredExtensions.size()),
|
||||
.ppEnabledExtensionNames = !extensionsSupported ? nullptr : requiredExtensions.data(),
|
||||
.pEnabledFeatures = &features
|
||||
//.pEnabledFeatures = &features
|
||||
};
|
||||
|
||||
// Actually create the device
|
||||
|
|
|
@ -10,5 +10,8 @@ namespace SHADE
|
|||
{
|
||||
//! We need to get the light component and initialize the relevant variables.
|
||||
EntityID lightEntity;
|
||||
|
||||
//! Generate a renderer for the light component
|
||||
bool generateRenderer;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@ namespace SHADE
|
|||
.maxAnisotropy = 1.0f,
|
||||
.minLod = params.minLod,
|
||||
.maxLod = params.maxLod,
|
||||
.borderColor = vk::BorderColor::eFloatOpaqueWhite
|
||||
};
|
||||
|
||||
// Create the sampler
|
||||
|
|
|
@ -551,7 +551,7 @@ namespace SHADE
|
|||
/*---------------------------------------------------------------------------------*/
|
||||
/* SHBatch - Usage Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
void SHBatch::Draw(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex)
|
||||
void SHBatch::Draw(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex, bool bindBatchPipeline/* = true*/)
|
||||
{
|
||||
if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS)
|
||||
{
|
||||
|
@ -566,7 +566,10 @@ namespace SHADE
|
|||
// Bind all required objects before drawing
|
||||
static std::array<uint32_t, 1> dynamicOffset{ 0 };
|
||||
cmdBuffer->BeginLabeledSegment("SHBatch for Pipeline #" + std::to_string(pipeline.GetId().Data.Index));
|
||||
cmdBuffer->BindPipeline(pipeline);
|
||||
|
||||
if (bindBatchPipeline)
|
||||
cmdBuffer->BindPipeline(pipeline);
|
||||
|
||||
cmdBuffer->BindVertexBuffer(SHGraphicsConstants::VertexBufferBindings::TRANSFORM, transformDataBuffer[frameIndex], 0);
|
||||
cmdBuffer->BindVertexBuffer(SHGraphicsConstants::VertexBufferBindings::INTEGER_DATA, instancedIntegerBuffer[frameIndex], 0);
|
||||
if (matPropsDescSet[frameIndex])
|
||||
|
|
|
@ -87,7 +87,7 @@ namespace SHADE
|
|||
void UpdateTransformBuffer(uint32_t frameIndex);
|
||||
void UpdateInstancedIntegerBuffer(uint32_t frameIndex);
|
||||
void Build(Handle<SHVkLogicalDevice> device, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) ;
|
||||
void Draw(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex);
|
||||
void Draw(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex, bool bindBatchPipeline = true);
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Getter Functions */
|
||||
|
|
|
@ -107,12 +107,12 @@ namespace SHADE
|
|||
}
|
||||
}
|
||||
|
||||
void SHSuperBatch::Draw(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept
|
||||
void SHSuperBatch::Draw(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex, bool bindBatchPipeline /*= true*/) noexcept
|
||||
{
|
||||
// Build all batches
|
||||
for (auto& batch : batches)
|
||||
{
|
||||
batch.Draw(cmdBuffer, frameIndex);
|
||||
batch.Draw(cmdBuffer, frameIndex, bindBatchPipeline);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -57,7 +57,7 @@ namespace SHADE
|
|||
void Clear() noexcept;
|
||||
void UpdateBuffers(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool);
|
||||
void Build(Handle<SHVkLogicalDevice> device, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) noexcept;
|
||||
void Draw(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept;
|
||||
void Draw(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex, bool bindBatchPipeline = true) noexcept;
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Getter Functions */
|
||||
|
|
|
@ -13,6 +13,8 @@ namespace SHADE
|
|||
/*-----------------------------------------------------------------------------------*/
|
||||
std::vector<Handle<SHVkDescriptorSetLayout>> SHGraphicsPredefinedData::predefinedLayouts;
|
||||
SHVertexInputState SHGraphicsPredefinedData::defaultVertexInputState;
|
||||
SHVertexInputState SHGraphicsPredefinedData::shadowMapVertexInputState;
|
||||
|
||||
std::vector<SHGraphicsPredefinedData::PerSystem> SHGraphicsPredefinedData::perSystemData;
|
||||
|
||||
//SHGraphicsPredefinedData::PerSystem SHGraphicsPredefinedData::batchingSystemData;
|
||||
|
@ -150,12 +152,26 @@ namespace SHADE
|
|||
Handle<SHVkDescriptorSetLayout> fontDataDescSetLayout = logicalDevice->CreateDescriptorSetLayout({ fontBitmapBinding, fontMatrixBinding });
|
||||
SET_VK_OBJ_NAME(logicalDevice, vk::ObjectType::eDescriptorSetLayout, fontDataDescSetLayout->GetVkHandle(), "[Descriptor Set Layout] Font Data");
|
||||
|
||||
// descriptor binding for storing shadow maps
|
||||
SHVkDescriptorSetLayout::Binding shadowMapBinding
|
||||
{
|
||||
.Type = vk::DescriptorType::eCombinedImageSampler,
|
||||
.Stage = vk::ShaderStageFlagBits::eVertex | vk::ShaderStageFlagBits::eFragment | vk::ShaderStageFlagBits::eCompute,
|
||||
.BindPoint = SHGraphicsConstants::DescriptorSetBindings::IMAGE_AND_SAMPLERS_DATA,
|
||||
.DescriptorCount = 200, // we can have up to 200 textures for now
|
||||
.flags = vk::DescriptorBindingFlagBits::eVariableDescriptorCount,
|
||||
};
|
||||
|
||||
// For global data (generic data and textures)
|
||||
Handle<SHVkDescriptorSetLayout> shadowMapDescLayout = logicalDevice->CreateDescriptorSetLayout({ shadowMapBinding });
|
||||
SET_VK_OBJ_NAME(logicalDevice, vk::ObjectType::eDescriptorSetLayout, shadowMapDescLayout->GetVkHandle(), "[Descriptor Set Layout] Shadow Maps");
|
||||
|
||||
predefinedLayouts.push_back(staticGlobalLayout);
|
||||
predefinedLayouts.push_back(lightDataDescSetLayout);
|
||||
predefinedLayouts.push_back(cameraDataGlobalLayout);
|
||||
predefinedLayouts.push_back(materialDataPerInstanceLayout);
|
||||
predefinedLayouts.push_back(fontDataDescSetLayout);
|
||||
predefinedLayouts.push_back(shadowMapDescLayout);
|
||||
|
||||
perSystemData[SHUtilities::ConvertEnum(SystemType::BATCHING)].descSetLayouts = GetPredefinedDescSetLayouts
|
||||
(
|
||||
|
@ -179,7 +195,7 @@ namespace SHADE
|
|||
);
|
||||
}
|
||||
|
||||
void SHGraphicsPredefinedData::InitDefaultVertexInputState(void) noexcept
|
||||
void SHGraphicsPredefinedData::InitPredefinedVertexInputState(void) noexcept
|
||||
{
|
||||
defaultVertexInputState.AddBinding(false, false, { SHVertexAttribute(SHAttribFormat::FLOAT_3D) }); // positions at binding 0
|
||||
defaultVertexInputState.AddBinding(false, false, { SHVertexAttribute(SHAttribFormat::FLOAT_2D) }); // UVs at binding 1
|
||||
|
@ -187,13 +203,16 @@ namespace SHADE
|
|||
defaultVertexInputState.AddBinding(false, false, { SHVertexAttribute(SHAttribFormat::FLOAT_3D) }); // Tangents at binding 3
|
||||
defaultVertexInputState.AddBinding(true, true, { SHVertexAttribute(SHAttribFormat::MAT_4D) }); // Transform at binding 4 - 7 (4 slots)
|
||||
defaultVertexInputState.AddBinding(true, true, { SHVertexAttribute(SHAttribFormat::UINT32_2D) }); // Instanced integer data at index 8
|
||||
|
||||
shadowMapVertexInputState.AddBinding(false, false, { SHVertexAttribute(SHAttribFormat::FLOAT_3D)});
|
||||
shadowMapVertexInputState.AddBinding(true, true, { SHVertexAttribute(SHAttribFormat::MAT_4D) }, 4, 4); // Transform at binding 4 - 7 (4 slots)
|
||||
}
|
||||
|
||||
void SHGraphicsPredefinedData::Init(Handle<SHVkLogicalDevice> logicalDevice) noexcept
|
||||
{
|
||||
perSystemData.resize(SHUtilities::ConvertEnum(SystemType::NUM_TYPES));
|
||||
InitDescSetLayouts(logicalDevice);
|
||||
InitDefaultVertexInputState();
|
||||
InitPredefinedVertexInputState();
|
||||
InitDescMappings();
|
||||
InitDummyPipelineLayouts (logicalDevice);
|
||||
}
|
||||
|
@ -217,6 +236,11 @@ namespace SHADE
|
|||
}
|
||||
|
||||
|
||||
SHVertexInputState const& SHGraphicsPredefinedData::GetShadowMapViState(void) noexcept
|
||||
{
|
||||
return shadowMapVertexInputState;
|
||||
}
|
||||
|
||||
SHGraphicsPredefinedData::PerSystem const& SHGraphicsPredefinedData::GetSystemData(SystemType systemType) noexcept
|
||||
{
|
||||
return perSystemData[static_cast<uint32_t>(systemType)];
|
||||
|
|
|
@ -28,6 +28,7 @@ namespace SHADE
|
|||
CAMERA = 0x04,
|
||||
MATERIALS = 0x08,
|
||||
FONT = 0x10,
|
||||
SHADOW = 0x20,
|
||||
};
|
||||
|
||||
enum class SystemType
|
||||
|
@ -57,6 +58,9 @@ namespace SHADE
|
|||
//! Default vertex input state (used by everything).
|
||||
static SHVertexInputState defaultVertexInputState;
|
||||
|
||||
//! vertex input state for shadow mapping
|
||||
static SHVertexInputState shadowMapVertexInputState;
|
||||
|
||||
//! Predefined data for each type of system
|
||||
static std::vector<PerSystem> perSystemData;
|
||||
|
||||
|
@ -72,7 +76,7 @@ namespace SHADE
|
|||
static void InitDescMappings (void) noexcept;
|
||||
static void InitDummyPipelineLayouts (Handle<SHVkLogicalDevice> logicalDevice) noexcept;
|
||||
static void InitDescSetLayouts (Handle<SHVkLogicalDevice> logicalDevice) noexcept;
|
||||
static void InitDefaultVertexInputState (void) noexcept;
|
||||
static void InitPredefinedVertexInputState (void) noexcept;
|
||||
|
||||
public:
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
@ -90,6 +94,7 @@ namespace SHADE
|
|||
/*-----------------------------------------------------------------------*/
|
||||
static std::vector<Handle<SHVkDescriptorSetLayout>> GetPredefinedDescSetLayouts (SHGraphicsPredefinedData::PredefinedDescSetLayoutTypes types) noexcept;
|
||||
static SHVertexInputState const& GetDefaultViState (void) noexcept;
|
||||
static SHVertexInputState const& GetShadowMapViState (void) noexcept;
|
||||
static PerSystem const& GetSystemData (SystemType systemType) noexcept;
|
||||
static SHDescriptorMappings::MapType const& GetMappings (SystemType systemType) noexcept;
|
||||
//static PerSystem const& GetBatchingSystemData(void) noexcept;
|
||||
|
|
|
@ -13,7 +13,7 @@ namespace SHADE
|
|||
CAMERA,
|
||||
MATERIALS,
|
||||
FONT,
|
||||
RENDER_GRAPH_RESOURCE,
|
||||
RENDER_GRAPH_NODE_COMPUTE_RESOURCE,
|
||||
RENDER_GRAPH_RESOURCE,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -101,9 +101,13 @@ namespace SHADE
|
|||
// Register function for subpass
|
||||
//auto const& RENDERERS = gfxSystem->GetDefaultViewport()->GetRenderers();
|
||||
auto renderGraph = gfxSystem->GetRenderGraph();
|
||||
auto subPass = renderGraph->GetNode("Debug Draw")->GetSubpass("Debug Draw");
|
||||
auto subPass = renderGraph->GetNode(SHGraphicsConstants::RenderGraphEntityNames::DEBUG_DRAW.data())->GetSubpass("Debug Draw");
|
||||
subPass->AddExteriorDrawCalls([this](Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHRenderer> renderer, uint32_t frameIndex)
|
||||
{
|
||||
// Set line width first
|
||||
cmdBuffer->SetLineWidth(LineWidth);
|
||||
|
||||
// Draw
|
||||
const uint32_t FRAME_IDX = gfxSystem->GetCurrentFrameIndex();
|
||||
cmdBuffer->BeginLabeledSegment("SHDebugDraw (No Depth Test)");
|
||||
{
|
||||
|
@ -125,9 +129,13 @@ namespace SHADE
|
|||
}
|
||||
cmdBuffer->EndLabeledSegment();
|
||||
});
|
||||
auto subPassWithDepth = renderGraph->GetNode("Debug Draw with Depth")->GetSubpass("Debug Draw with Depth");
|
||||
auto subPassWithDepth = renderGraph->GetNode(SHGraphicsConstants::RenderGraphEntityNames::DEBUG_DRAW_DEPTH_PASS.data())->GetSubpass("Debug Draw with Depth");
|
||||
subPassWithDepth->AddExteriorDrawCalls([this](Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHRenderer> renderer, uint32_t frameIndex)
|
||||
{
|
||||
// Set line width first
|
||||
cmdBuffer->SetLineWidth(LineWidth);
|
||||
|
||||
// Draw
|
||||
const uint32_t FRAME_IDX = gfxSystem->GetCurrentFrameIndex();
|
||||
cmdBuffer->BeginLabeledSegment("SHDebugDraw (Depth Tested)");
|
||||
{
|
||||
|
@ -207,6 +215,11 @@ namespace SHADE
|
|||
drawSphere(getMeshBatch(true, depthTested), matrix, color);
|
||||
}
|
||||
|
||||
void SHDebugDrawSystem::DrawWireCapsule(const SHVec3& position, const SHQuaternion& rotation, float height, float radius, const SHColour& color, bool depthTested)
|
||||
{
|
||||
drawWireCapsule(getLineBatch(depthTested), getMeshBatch(false, depthTested), position, rotation, height, radius, color);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Persistent Draw Functions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
@ -264,6 +277,12 @@ namespace SHADE
|
|||
markPersistentDrawsDirty();
|
||||
}
|
||||
|
||||
void SHDebugDrawSystem::DrawPersistentWireCapsule(const SHVec3& position, const SHQuaternion& rotation, float height, float radius, const SHColour& color, bool depthTested)
|
||||
{
|
||||
drawWireCapsule(getPersistentLineBatch(depthTested), getPersistentMeshBatch(false, depthTested), position, rotation, height, radius, color);
|
||||
markPersistentDrawsDirty();
|
||||
}
|
||||
|
||||
void SHDebugDrawSystem::ClearPersistentDraws()
|
||||
{
|
||||
for (auto& batch : persistentLineBatches)
|
||||
|
@ -348,6 +367,53 @@ namespace SHADE
|
|||
);
|
||||
}
|
||||
|
||||
void SHDebugDrawSystem::drawWireCapsule(LinesBatch& lineBatch, MeshBatch& meshBatch, const SHVec3& position, const SHQuaternion& rotation, float height, float radius, const SHColour& color)
|
||||
{
|
||||
// Get local axis vectors
|
||||
const SHVec3 LOCAL_UP = SHVec3::Rotate(SHVec3::Up, rotation);
|
||||
const SHVec3 LOCAL_RIGHT = SHVec3::Rotate(SHVec3::Right, rotation);
|
||||
const SHVec3 LOCAL_FORWARD = SHVec3::Rotate(SHVec3::Forward, rotation);
|
||||
|
||||
// Rotate the circle
|
||||
SHQuaternion circleOrientation = SHQuaternion::FromEuler(SHVec3(SHMath::DegreesToRadians(90.0), 0.0f, 0.0f)) * rotation;
|
||||
|
||||
// Compute top and bottom of the cylinder
|
||||
const SHVec3 HALF_UP = LOCAL_UP * (height * 0.5f - radius);
|
||||
const SHVec3 TOP_POS = position + HALF_UP;
|
||||
const SHVec3 BOT_POS = position - HALF_UP;
|
||||
|
||||
// Render circles
|
||||
const SHVec3 CIRCLE_SCALE = SHVec3(radius * 2.0f, radius * 2.0, radius * 2.0);
|
||||
drawCircle(meshBatch, SHMatrix::Transform(TOP_POS, circleOrientation, CIRCLE_SCALE), color);
|
||||
drawCircle(meshBatch, SHMatrix::Transform(BOT_POS, circleOrientation, CIRCLE_SCALE), color);
|
||||
|
||||
// Render connecting lines
|
||||
drawLine(lineBatch, TOP_POS + LOCAL_RIGHT * radius, BOT_POS + LOCAL_RIGHT * radius, color);
|
||||
drawLine(lineBatch, TOP_POS - LOCAL_RIGHT * radius, BOT_POS - LOCAL_RIGHT * radius, color);
|
||||
drawLine(lineBatch, TOP_POS + LOCAL_FORWARD * radius, BOT_POS + LOCAL_FORWARD * radius, color);
|
||||
drawLine(lineBatch, TOP_POS - LOCAL_FORWARD * radius, BOT_POS - LOCAL_FORWARD * radius, color);
|
||||
|
||||
// Render caps
|
||||
const SHVec3 RADIUS_SCALE = SHVec3(radius * 2.0, radius * 2.0f, radius * 2.0);
|
||||
const SHMatrix TOP_CAP_MAT = SHMatrix::Transform(TOP_POS, rotation, RADIUS_SCALE);
|
||||
drawMesh
|
||||
(
|
||||
gfxSystem->GetMeshPrimitive(PrimitiveType::LineCapsuleCap),
|
||||
meshBatch, TOP_CAP_MAT, color
|
||||
);
|
||||
const SHMatrix BOT_CAP_MAT = SHMatrix::Transform
|
||||
(
|
||||
BOT_POS,
|
||||
SHQuaternion::FromEuler(SHVec3(SHMath::DegreesToRadians(180.0), 0.0f, 0.0f)) * rotation,
|
||||
RADIUS_SCALE
|
||||
);
|
||||
drawMesh
|
||||
(
|
||||
gfxSystem->GetMeshPrimitive(PrimitiveType::LineCapsuleCap),
|
||||
meshBatch, BOT_CAP_MAT, color
|
||||
);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Helper Batch Functions - Lines */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
@ -448,7 +514,6 @@ namespace SHADE
|
|||
if (batch.NumPoints[frameIndex] > 0)
|
||||
{
|
||||
cmdBuffer->BindPipeline(batch.Pipeline);
|
||||
cmdBuffer->SetLineWidth(LineWidth);
|
||||
cmdBuffer->BindVertexBuffer(0, batch.VertexBuffers[frameIndex], 0);
|
||||
cmdBuffer->DrawArrays(batch.NumPoints[frameIndex], 1, 0, 0);
|
||||
}
|
||||
|
|
|
@ -163,6 +163,17 @@ namespace SHADE
|
|||
/// <param name="color">Colour to draw with.</param>
|
||||
/// <param name="depthTested">Whether or not drawn object will be occluded.</param>
|
||||
void DrawSphere(const SHMatrix& matrix, const SHColour& color = SHColour::WHITE, bool depthTested = false);
|
||||
/// <summary>
|
||||
/// Draws the outline of a capsule.
|
||||
/// </summary>
|
||||
/// <param name="position">Position of the wireframe capsule.</param>
|
||||
/// <param name="rotation">Rotation of the capsule.</param>
|
||||
/// <param name="height">Height of the overall capsule.</param>
|
||||
/// <param name="radius">Radius of the capsule.</param>
|
||||
/// <param name="color"></param>
|
||||
/// <param name="color">Colour to draw with.</param>
|
||||
/// <param name="depthTested">Whether or not drawn object will be occluded.</param>
|
||||
void DrawWireCapsule(const SHVec3& position, const SHQuaternion& rotation, float height, float radius, const SHColour& color = SHColour::WHITE, bool depthTested = false);
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Persistent Draw Functions */
|
||||
|
@ -269,6 +280,17 @@ namespace SHADE
|
|||
/// <param name="depthTested">Whether or not drawn object will be occluded.</param>
|
||||
void DrawPersistentSphere(const SHMatrix& matrix, const SHColour& color = SHColour::WHITE, bool depthTested = false);
|
||||
/// <summary>
|
||||
/// Draws a persistent outline of a capsule.
|
||||
/// </summary>
|
||||
/// <param name="position">Position of the wireframe capsule.</param>
|
||||
/// <param name="rotation">Rotation of the capsule.</param>
|
||||
/// <param name="height">Height of the overall capsule.</param>
|
||||
/// <param name="radius">Radius of the capsule.</param>
|
||||
/// <param name="color"></param>
|
||||
/// <param name="color">Colour to draw with.</param>
|
||||
/// <param name="depthTested">Whether or not drawn object will be occluded.</param>
|
||||
void DrawPersistentWireCapsule(const SHVec3& position, const SHQuaternion& rotation, float height, float radius, const SHColour& color = SHColour::WHITE, bool depthTested = false);
|
||||
/// <summary>
|
||||
/// Clears any persistent drawn debug primitives.
|
||||
/// </summary>
|
||||
void ClearPersistentDraws();
|
||||
|
@ -386,6 +408,7 @@ namespace SHADE
|
|||
void drawCube(MeshBatch& batch, const SHMatrix& transformMatrix, const SHColour& color);
|
||||
void drawSphere(MeshBatch& batch, const SHMatrix& transformMatrix, const SHColour& color);
|
||||
void drawCircle(MeshBatch& batch, const SHMatrix& transformMatrix, const SHColour& color);
|
||||
void drawWireCapsule(LinesBatch& lineBatch, MeshBatch& meshBatch, const SHVec3& position, const SHQuaternion& rotation, float height, float radius, const SHColour& color);
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Helper Batch Functions - Lines */
|
||||
|
|
|
@ -31,68 +31,91 @@ namespace SHADE
|
|||
static constexpr uint32_t EDITOR = 0;
|
||||
};
|
||||
|
||||
//struct DescriptorSetIndex
|
||||
//{
|
||||
// /***************************************************************************/
|
||||
// /*!
|
||||
// \brief
|
||||
// DescriptorSet Index for static global values like generic data, and
|
||||
// texture samplers
|
||||
// */
|
||||
// /***************************************************************************/
|
||||
// static constexpr uint32_t STATIC_GLOBALS = 0;
|
||||
// /***************************************************************************/
|
||||
// /*!
|
||||
// \brief
|
||||
// DescriptorSet Index for dynamic global values like lights.
|
||||
// */
|
||||
// /***************************************************************************/
|
||||
// static constexpr uint32_t DYNAMIC_GLOBALS = 1;
|
||||
// /***************************************************************************/
|
||||
// /*!
|
||||
// \brief
|
||||
// DescriptorSet Index for high frequency changing global values like
|
||||
// camera matrices.
|
||||
// */
|
||||
// /***************************************************************************/
|
||||
// static constexpr uint32_t HIGH_FREQUENCY_GLOBALS = 2;
|
||||
// /***************************************************************************/
|
||||
// /*!
|
||||
// \brief
|
||||
// DescriptorSet Index for per-instance/material changing values.
|
||||
// */
|
||||
// /***************************************************************************/
|
||||
// static constexpr uint32_t PER_INSTANCE = 3;
|
||||
// /***************************************************************************/
|
||||
// /*!
|
||||
// \brief
|
||||
// DescriptorSet Index for render graph resources. Unlike the sets from
|
||||
// 1 to 3 and 6, this set index does not have hard coded bindings and is
|
||||
// NOT part of the layouts included in the global data.
|
||||
// */
|
||||
// /***************************************************************************/
|
||||
// static constexpr uint32_t RENDERGRAPH_RESOURCE = 4;
|
||||
// /***************************************************************************/
|
||||
// /*!
|
||||
// \brief
|
||||
// DescriptorSet Index for render graph node compute resources. For data
|
||||
// that we wish to pass to compute shaders in the render graph, this is
|
||||
// the set to use. Unlike the sets from 1 to 3 and 6, this set index does not have
|
||||
// hard coded bindings and is NOT part of the layouts included in the global
|
||||
// data.
|
||||
// */
|
||||
// /***************************************************************************/
|
||||
// static constexpr uint32_t RENDERGRAPH_NODE_COMPUTE_RESOURCE = 5;
|
||||
struct RenderGraphEntityNames
|
||||
{
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
\brief
|
||||
Name of G-Buffer render graph node.
|
||||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
static constexpr std::string_view GBUFFER_PASS = "G-Buffer";
|
||||
|
||||
// /***************************************************************************/
|
||||
// /*!
|
||||
// \brief
|
||||
// To store font data.
|
||||
//
|
||||
// */
|
||||
// /***************************************************************************/
|
||||
// static constexpr uint32_t FONT_DATA = 4;
|
||||
//};
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
\brief
|
||||
Name of shadow map render graph node.
|
||||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
static constexpr std::string_view SHADOW_MAP_PASS = "Shadow Map Pass";
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
\brief
|
||||
Name of deferred composite render graph node.
|
||||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
static constexpr std::string_view DEFERRED_COMPOSITE_PASS = "Deferred Comp Pass";
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
\brief
|
||||
Name of Debug Draw with Depth render graph node.
|
||||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
static constexpr std::string_view DEBUG_DRAW_DEPTH_PASS = "Debug Draw with Depth Pass";
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
\brief
|
||||
Name of Debug Draw render graph node.
|
||||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
static constexpr std::string_view DEBUG_DRAW = "Debug Draw Pass";
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
\brief
|
||||
Name of screen space pass render graph node.
|
||||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
static constexpr std::string_view SCREEN_SPACE_PASS = "Screen Space Pass";
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
\brief
|
||||
Name of ImGui pass render graph node.
|
||||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
static constexpr std::string_view IMGUI_PASS = "ImGui Pass";
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
\brief
|
||||
Name of deferred composite compute.
|
||||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
static constexpr std::string_view DEFERRED_COMPOSITE_COMPUTE = "Deferred Composite";
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
struct DescriptorSetBindings
|
||||
{
|
||||
|
@ -158,6 +181,16 @@ namespace SHADE
|
|||
/***************************************************************************/
|
||||
static constexpr uint32_t FONT_MATRIX_DATA = 1;
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
\brief
|
||||
Descriptor set binding for shadow map images.
|
||||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
static constexpr uint32_t SHADOW_MAP_IMAGE_SAMPLER_DATA = 0;
|
||||
|
||||
|
||||
};
|
||||
|
||||
struct VertexBufferBindings
|
||||
|
|
|
@ -44,6 +44,9 @@ of DigiPen Institute of Technology is prohibited.
|
|||
#include "Graphics/MiddleEnd/TextRendering/SHFreetypeInstance.h"
|
||||
#include "Graphics/MiddleEnd/TextRendering/SHTextRenderingSubSystem.h"
|
||||
#include "Graphics/MiddleEnd/GlobalData/SHGlobalDescriptorSets.h"
|
||||
#include "Events/SHEvent.h"
|
||||
#include "Graphics/MiddleEnd/Lights/SHLightComponent.h"
|
||||
#include "Input/SHInputManager.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
@ -124,6 +127,13 @@ namespace SHADE
|
|||
|
||||
SHFreetypeInstance::Init();
|
||||
|
||||
SHAssetManager::CompileAsset("../../Assets/Shaders/DeferredComposite_CS.glsl", false);
|
||||
SHAssetManager::CompileAsset("../../Assets/Shaders/SSAO_CS.glsl", false);
|
||||
SHAssetManager::CompileAsset("../../Assets/Shaders/SSAOBlur_CS.glsl", false);
|
||||
SHAssetManager::CompileAsset("../../Assets/Shaders/PureCopy_CS.glsl", false);
|
||||
SHAssetManager::CompileAsset("../../Assets/Shaders/TestCube_VS.glsl", false);
|
||||
SHAssetManager::CompileAsset("../../Assets/Shaders/TestCube_FS.glsl", false);
|
||||
|
||||
// Load Built In Shaders
|
||||
static constexpr AssetID VS_DEFAULT = 39210065; defaultVertShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(VS_DEFAULT);
|
||||
static constexpr AssetID FS_DEFAULT = 46377769; defaultFragShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(FS_DEFAULT);
|
||||
|
@ -137,6 +147,8 @@ namespace SHADE
|
|||
static constexpr AssetID TEXT_FS = 38024754; textFS = SHResourceManager::LoadOrGet<SHVkShaderModule>(TEXT_FS);
|
||||
static constexpr AssetID RENDER_SC_VS = 48082949; renderToSwapchainVS = SHResourceManager::LoadOrGet<SHVkShaderModule>(RENDER_SC_VS);
|
||||
static constexpr AssetID RENDER_SC_FS = 36869006; renderToSwapchainFS = SHResourceManager::LoadOrGet<SHVkShaderModule>(RENDER_SC_FS);
|
||||
static constexpr AssetID SHADOW_MAP_VS = 44646107; shadowMapVS = SHResourceManager::LoadOrGet<SHVkShaderModule>(SHADOW_MAP_VS);
|
||||
|
||||
}
|
||||
|
||||
void SHGraphicsSystem::InitRenderGraph(void) noexcept
|
||||
|
@ -169,6 +181,8 @@ namespace SHADE
|
|||
// Create Default Viewport
|
||||
worldViewport = AddViewport(vk::Viewport(0.0f, 0.0f, static_cast<float>(window->GetWindowSize().first), static_cast<float>(window->GetWindowSize().second), 0.0f, 1.0f));
|
||||
|
||||
shadowMapViewport = AddViewport(vk::Viewport(0.0f, 0.0f, static_cast<float>(SHLightingSubSystem::SHADOW_MAP_WIDTH), static_cast<float>(SHLightingSubSystem::SHADOW_MAP_HEIGHT), 0.0f, 1.0f));
|
||||
|
||||
std::vector<Handle<SHVkCommandPool>> renderContextCmdPools{ swapchain->GetNumImages() };
|
||||
for (uint32_t i = 0; i < renderContextCmdPools.size(); ++i)
|
||||
{
|
||||
|
@ -183,22 +197,24 @@ namespace SHADE
|
|||
/*-----------------------------------------------------------------------*/
|
||||
// Initialize world render graph
|
||||
renderGraph->Init("World Render Graph", device, swapchain, &resourceManager, renderContextCmdPools);
|
||||
renderGraph->AddResource("Position", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE }, windowDims.first, windowDims.second, vk::Format::eR32G32B32A32Sfloat);
|
||||
renderGraph->AddResource("Normals", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE }, windowDims.first, windowDims.second, vk::Format::eR32G32B32A32Sfloat);
|
||||
renderGraph->AddResource("Position", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE }, true, windowDims.first, windowDims.second, vk::Format::eR32G32B32A32Sfloat);
|
||||
renderGraph->AddResource("Position World Space", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE }, true, windowDims.first, windowDims.second, vk::Format::eR32G32B32A32Sfloat);
|
||||
renderGraph->AddResource("Normals", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE }, true, windowDims.first, windowDims.second, vk::Format::eR32G32B32A32Sfloat);
|
||||
//worldRenderGraph->AddResource("Tangents", { 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);
|
||||
renderGraph->AddResource("Albedo", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE }, windowDims.first, windowDims.second);
|
||||
renderGraph->AddResource("Depth Buffer", { SH_RENDER_GRAPH_RESOURCE_FLAGS::DEPTH_STENCIL }, windowDims.first, windowDims.second, vk::Format::eD32SfloatS8Uint);
|
||||
renderGraph->AddResource("Entity ID", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::SHARED }, windowDims.first, windowDims.second, vk::Format::eR32Uint, 1, vk::ImageUsageFlagBits::eTransferSrc);
|
||||
renderGraph->AddResource("Light Layer Indices", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE }, windowDims.first, windowDims.second, vk::Format::eR32Uint, 1, vk::ImageUsageFlagBits::eTransferSrc);
|
||||
renderGraph->AddResource("Scene", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE, SH_RENDER_GRAPH_RESOURCE_FLAGS::SHARED }, windowDims.first, windowDims.second);
|
||||
renderGraph->AddResource("SSAO", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE }, windowDims.first, windowDims.second, vk::Format::eR8Unorm);
|
||||
renderGraph->AddResource("SSAO Blur", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE }, windowDims.first, windowDims.second, vk::Format::eR8Unorm);
|
||||
renderGraph->AddResource("Present", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR_PRESENT }, windowDims.first, windowDims.second);
|
||||
renderGraph->AddResource("Albedo", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE }, true, windowDims.first, windowDims.second);
|
||||
renderGraph->AddResource("Depth Buffer", { SH_RENDER_GRAPH_RESOURCE_FLAGS::DEPTH_STENCIL }, true, windowDims.first, windowDims.second, vk::Format::eD32SfloatS8Uint);
|
||||
renderGraph->AddResource("Entity ID", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::SHARED }, true, windowDims.first, windowDims.second, vk::Format::eR32Uint, 1, vk::ImageUsageFlagBits::eTransferSrc);
|
||||
renderGraph->AddResource("Light Layer Indices", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE }, true, windowDims.first, windowDims.second, vk::Format::eR32Uint, 1, vk::ImageUsageFlagBits::eTransferSrc);
|
||||
renderGraph->AddResource("Scene", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE, SH_RENDER_GRAPH_RESOURCE_FLAGS::SHARED }, true, windowDims.first, windowDims.second);
|
||||
renderGraph->AddResource("SSAO", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE }, true, windowDims.first, windowDims.second, vk::Format::eR8Unorm);
|
||||
renderGraph->AddResource("SSAO Blur", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE }, true, windowDims.first, windowDims.second, vk::Format::eR8Unorm);
|
||||
renderGraph->AddResource("Present", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR_PRESENT }, true, windowDims.first, windowDims.second);
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* MAIN NODE */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
auto gBufferNode = renderGraph->AddNode("G-Buffer",
|
||||
auto gBufferNode = renderGraph->AddNode(SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_PASS.data(),
|
||||
//auto gBufferNode = renderGraph->AddNode(SHGraphicsConstants::RenderGraphNodeNames::GBUFFER_PASS.data()
|
||||
{
|
||||
"Position",
|
||||
"Entity ID",
|
||||
|
@ -207,7 +223,8 @@ namespace SHADE
|
|||
"Albedo",
|
||||
"Depth Buffer",
|
||||
"SSAO",
|
||||
"SSAO Blur"
|
||||
"SSAO Blur",
|
||||
"Position World Space"
|
||||
},
|
||||
{}); // no predecessors
|
||||
|
||||
|
@ -220,6 +237,7 @@ namespace SHADE
|
|||
gBufferSubpass->AddColorOutput("Light Layer Indices");
|
||||
gBufferSubpass->AddColorOutput("Normals");
|
||||
gBufferSubpass->AddColorOutput("Albedo");
|
||||
gBufferSubpass->AddColorOutput("Position World Space");
|
||||
gBufferSubpass->AddDepthOutput("Depth Buffer", SH_RENDER_GRAPH_RESOURCE_FLAGS::DEPTH_STENCIL);
|
||||
|
||||
|
||||
|
@ -254,53 +272,52 @@ namespace SHADE
|
|||
// Add another pass to blur SSAO
|
||||
Handle<SHRenderGraphNodeCompute> ssaoBlurPass = gBufferNode->AddNodeCompute("SSAO Blur Step", ssaoBlurShader, { "SSAO", "SSAO Blur" });
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* SHADOW MAP PASS */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
// Shadow map pass will have no resources bound at first. Lighting system will add resources to the node.
|
||||
// It will initially also not have any subpasses since they will be added for each light that casts shadows.
|
||||
//auto shadowMapPass = renderGraph->AddNode("Shadow Map Pass", {}, {});
|
||||
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* DEFERRED COMPOSITE NODE */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
// This pass will facilitate both lighting and shadows in 1 single pass.
|
||||
auto deferredCompositeNode = renderGraph->AddNode("Deferred Comp Pass",
|
||||
auto deferredCompositeNode = renderGraph->AddNode(SHGraphicsConstants::RenderGraphEntityNames::DEFERRED_COMPOSITE_PASS.data(),
|
||||
{
|
||||
"Position",
|
||||
"Light Layer Indices",
|
||||
"Normals",
|
||||
"Albedo",
|
||||
"Scene",
|
||||
"SSAO Blur"
|
||||
"SSAO Blur",
|
||||
"Position World Space"
|
||||
},
|
||||
{"G-Buffer"});
|
||||
{ SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_PASS .data()});
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* DEFERRED COMPOSITE SUBPASS INIT */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
deferredCompositeNode->AddNodeCompute("Deferred Composite", deferredCompositeShader, { "Position", "Normals", "Albedo", "Light Layer Indices", "SSAO Blur", "Scene" });
|
||||
auto deferredCompositeCompute = deferredCompositeNode->AddNodeCompute(SHGraphicsConstants::RenderGraphEntityNames::DEFERRED_COMPOSITE_COMPUTE.data(), deferredCompositeShader, {"Position", "Normals", "Albedo", "Light Layer Indices", "SSAO Blur", "Position World Space", "Scene"}, {}, SHLightingSubSystem::MAX_SHADOWS);
|
||||
deferredCompositeCompute->AddPreComputeFunction([=](Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex)
|
||||
{
|
||||
lightingSubSystem->PrepareShadowMapsForRead(cmdBuffer);
|
||||
});
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* DEBUG DRAW PASS INIT */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
// Set up Debug Draw Passes
|
||||
// - Depth Tested
|
||||
auto debugDrawNodeDepth = renderGraph->AddNode("Debug Draw with Depth", { "Scene", "Depth Buffer" }, {"G-Buffer", "Deferred Comp Pass"});
|
||||
auto debugDrawNodeDepth = renderGraph->AddNode(SHGraphicsConstants::RenderGraphEntityNames::DEBUG_DRAW_DEPTH_PASS.data(), {"Scene", "Depth Buffer"}, {SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_PASS.data(), SHGraphicsConstants::RenderGraphEntityNames::DEFERRED_COMPOSITE_PASS.data()});
|
||||
auto debugDrawDepthSubpass = debugDrawNodeDepth->AddSubpass("Debug Draw with Depth", worldViewport, worldRenderer);
|
||||
debugDrawDepthSubpass->AddColorOutput("Scene");
|
||||
debugDrawDepthSubpass->AddDepthOutput("Depth Buffer");
|
||||
// - No Depth Test
|
||||
auto debugDrawNode = renderGraph->AddNode("Debug Draw", { "Scene" }, { "Debug Draw with Depth" });
|
||||
auto debugDrawNode = renderGraph->AddNode(SHGraphicsConstants::RenderGraphEntityNames::DEBUG_DRAW.data(), {"Scene"}, {SHGraphicsConstants::RenderGraphEntityNames::DEBUG_DRAW_DEPTH_PASS.data()});
|
||||
auto debugDrawSubpass = debugDrawNode->AddSubpass("Debug Draw", worldViewport, worldRenderer);
|
||||
debugDrawSubpass->AddColorOutput("Scene");
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* SCREEN SPACE PASS */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
auto screenSpaceNode = renderGraph->AddNode("Screen Space Pass", { "Scene", "Entity ID" }, {"Deferred Comp Pass", "G-Buffer", "Debug Draw" });
|
||||
auto screenSpaceNode = renderGraph->AddNode(SHGraphicsConstants::RenderGraphEntityNames::SCREEN_SPACE_PASS.data(), {"Scene", "Entity ID"}, {SHGraphicsConstants::RenderGraphEntityNames::DEFERRED_COMPOSITE_PASS.data(), SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_PASS.data(), SHGraphicsConstants::RenderGraphEntityNames::DEBUG_DRAW.data()});
|
||||
auto uiSubpass = screenSpaceNode->AddSubpass("UI", worldViewport, screenRenderer);
|
||||
uiSubpass->AddColorOutput("Scene");
|
||||
uiSubpass->AddColorOutput("Entity ID");
|
||||
|
@ -315,16 +332,16 @@ namespace SHADE
|
|||
#ifdef SHEDITOR
|
||||
{
|
||||
// Dummy Node to transition scene render graph resource
|
||||
auto dummyNode = renderGraph->AddNode("Dummy Pass", { "Scene" }, { "Screen Space Pass" });
|
||||
auto dummyNode = renderGraph->AddNode("Dummy Pass", { "Scene" }, { SHGraphicsConstants::RenderGraphEntityNames::SCREEN_SPACE_PASS .data()});
|
||||
auto dummySubpass = dummyNode->AddSubpass("Dummy Subpass", {}, {});
|
||||
dummySubpass->AddInput("Scene");
|
||||
|
||||
auto imGuiNode = renderGraph->AddNode("ImGui Node", { "Present" }, {});
|
||||
auto imGuiNode = renderGraph->AddNode(SHGraphicsConstants::RenderGraphEntityNames::IMGUI_PASS.data(), {"Present"}, {});
|
||||
auto imGuiSubpass = imGuiNode->AddSubpass("ImGui Draw", {}, {});
|
||||
imGuiSubpass->AddColorOutput("Present");
|
||||
}
|
||||
#else
|
||||
renderGraph->AddRenderToSwapchainNode("Scene", "Present", { "Screen Space Pass" }, { renderToSwapchainVS, renderToSwapchainFS });
|
||||
renderGraph->AddRenderToSwapchainNode("Scene", "Present", { SHGraphicsConstants::RenderGraphEntityNames::SCREEN_SPACE_PASS .data()}, {renderToSwapchainVS, renderToSwapchainFS});
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -393,12 +410,16 @@ namespace SHADE
|
|||
postOffscreenRenderSubSystem->Init(device, renderGraph->GetRenderGraphResource("Scene"), descPool);
|
||||
|
||||
lightingSubSystem = resourceManager.Create<SHLightingSubSystem>();
|
||||
lightingSubSystem->Init(device, descPool);
|
||||
lightingSubSystem->Init(device, descPool, &resourceManager, samplerCache.GetSampler (device, SHVkSamplerParams
|
||||
{
|
||||
.addressMode = vk::SamplerAddressMode::eClampToBorder,
|
||||
})
|
||||
);
|
||||
|
||||
textRenderingSubSystem = resourceManager.Create<SHTextRenderingSubSystem>();
|
||||
|
||||
// initialize the text renderer
|
||||
auto uiNode = renderGraph->GetNode("Screen Space Pass");
|
||||
auto uiNode = renderGraph->GetNode(SHGraphicsConstants::RenderGraphEntityNames::SCREEN_SPACE_PASS.data());
|
||||
textRenderingSubSystem->Init(device, uiNode->GetRenderpass(), uiNode->GetSubpass("UI"), descPool, textVS, textFS);
|
||||
|
||||
SHGlobalDescriptorSets::SetLightingSubSystem(lightingSubSystem);
|
||||
|
@ -419,13 +440,14 @@ namespace SHADE
|
|||
primitiveMeshes[static_cast<int>(PrimitiveType::Sphere)] = SHPrimitiveGenerator::Sphere(meshLibrary);
|
||||
primitiveMeshes[static_cast<int>(PrimitiveType::LineCube)] = SHPrimitiveGenerator::LineCube(meshLibrary);
|
||||
primitiveMeshes[static_cast<int>(PrimitiveType::LineCircle)] = SHPrimitiveGenerator::LineCircle(meshLibrary);
|
||||
primitiveMeshes[static_cast<int>(PrimitiveType::LineCapsuleCap)] = SHPrimitiveGenerator::LineCapsuleCap(meshLibrary);
|
||||
BuildMeshBuffers();
|
||||
|
||||
// Create default materials
|
||||
defaultMaterial = AddMaterial
|
||||
(
|
||||
defaultVertShader, defaultFragShader,
|
||||
renderGraph->GetNode("G-Buffer")->GetSubpass("G-Buffer Write")
|
||||
renderGraph->GetNode(SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_PASS.data())->GetSubpass("G-Buffer Write")
|
||||
);
|
||||
defaultMaterial->SetProperty("data.textureIndex", defaultTexture->TextureArrayIndex);
|
||||
}
|
||||
|
@ -450,6 +472,7 @@ namespace SHADE
|
|||
InitMiddleEnd();
|
||||
InitSubsystems();
|
||||
InitBuiltInResources();
|
||||
InitEvents();
|
||||
}
|
||||
|
||||
void SHGraphicsSystem::Exit(void)
|
||||
|
@ -545,6 +568,15 @@ namespace SHADE
|
|||
#endif
|
||||
}
|
||||
|
||||
if (SHInputManager::GetKeyDown(SHInputManager::SH_KEYCODE::B))
|
||||
{
|
||||
auto& lightComps = SHComponentManager::GetDense<SHLightComponent>();
|
||||
for (auto& comp : lightComps)
|
||||
{
|
||||
comp.SetEnableShadow(true);
|
||||
}
|
||||
}
|
||||
|
||||
renderGraph->Begin(frameIndex);
|
||||
auto cmdBuffer = renderGraph->GetCommandBuffer(frameIndex);
|
||||
|
||||
|
@ -725,16 +757,61 @@ namespace SHADE
|
|||
renderers.erase(iter);
|
||||
}
|
||||
|
||||
SHEventHandle SHGraphicsSystem::ReceiveLightEnableShadowEvent(SHEventPtr event) noexcept
|
||||
SHEventHandle SHGraphicsSystem::ReceiveLightEnableShadowEvent(SHEventPtr eventPtr) noexcept
|
||||
{
|
||||
// we need to wait for the device to finish using the graph first
|
||||
device->WaitIdle();
|
||||
|
||||
auto const& EVENT_DATA = reinterpret_cast<const SHEventSpec<SHLightEnableShadowEvent>*>(eventPtr.get())->data;
|
||||
auto* lightComp = SHComponentManager::GetComponent<SHLightComponent>(EVENT_DATA->lightEntity);
|
||||
std::string resourceName = "ShadowMap " + std::to_string(EVENT_DATA->lightEntity);
|
||||
Handle<SHSubpass> companionSubpass = renderGraph->GetNode(SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_PASS.data())->GetSubpass("G-Buffer Write");
|
||||
|
||||
if (EVENT_DATA->generateRenderer)
|
||||
{
|
||||
// Create new renderer for the light component and give it to the light component
|
||||
Handle<SHRenderer> newRenderer = resourceManager.Create<SHRenderer>(device, swapchain->GetNumImages(), descPool, SHRenderer::PROJECTION_TYPE::ORTHOGRAPHIC);
|
||||
lightComp->SetRenderer (newRenderer);
|
||||
|
||||
// assign shadow map index to light component
|
||||
lightComp->SetShadowMapIndex (lightingSubSystem->GetNumShadowMaps());
|
||||
}
|
||||
|
||||
// Add the shadow map resource to the graph
|
||||
renderGraph->AddResource(resourceName, {SH_RENDER_GRAPH_RESOURCE_FLAGS::DEPTH, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT}, false, SHLightingSubSystem::SHADOW_MAP_WIDTH, SHLightingSubSystem::SHADOW_MAP_HEIGHT, vk::Format::eD32Sfloat);
|
||||
|
||||
// link resource to node. This means linking the resource and regenerating the node's renderpass and framebuffer.
|
||||
auto shadowMapNode = renderGraph->AddNodeAfter(SHGraphicsConstants::RenderGraphEntityNames::SHADOW_MAP_PASS.data() + resourceName, {resourceName.c_str()}, SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_PASS.data());
|
||||
|
||||
// Add a subpass to render to that shadow map
|
||||
auto newSubpass = shadowMapNode->RuntimeAddSubpass(resourceName + " Subpass", shadowMapViewport, lightComp->GetRenderer());
|
||||
newSubpass->AddDepthOutput(resourceName, SH_RENDER_GRAPH_RESOURCE_FLAGS::DEPTH);
|
||||
|
||||
// regenerate the node
|
||||
shadowMapNode->RuntimeStandaloneRegenerate();
|
||||
|
||||
// Create pipeline from new renderpass and subpass if it's not created yet
|
||||
if (!shadowMapPipeline)
|
||||
{
|
||||
SHPipelineLibrary tempLibrary{};
|
||||
Handle<SHRenderGraphNode> rgNode = renderGraph->GetNode(SHGraphicsConstants::RenderGraphEntityNames::SHADOW_MAP_PASS.data());
|
||||
|
||||
SHRasterizationState rasterState{};
|
||||
rasterState.cull_mode = vk::CullModeFlagBits::eBack;
|
||||
|
||||
tempLibrary.Init(device);
|
||||
tempLibrary.CreateGraphicsPipelines({ shadowMapVS, {} }, shadowMapNode->GetRenderpass(), newSubpass, SHGraphicsPredefinedData::GetShadowMapViState(), rasterState);
|
||||
shadowMapPipeline = tempLibrary.GetGraphicsPipeline({ shadowMapVS, {} });
|
||||
}
|
||||
newSubpass->SetCompanionSubpass(companionSubpass, shadowMapPipeline); // set companion subpass and pipeline
|
||||
|
||||
//renderGraph->GetNode ();
|
||||
return event->handle;
|
||||
// add the shadow map to the lighting system
|
||||
uint32_t const NEW_SHADOW_MAP_INDEX = lightingSubSystem->AddShadowMap(renderGraph->GetRenderGraphResource(resourceName), EVENT_DATA->lightEntity);
|
||||
|
||||
auto nodeCompute = renderGraph->GetNode(SHGraphicsConstants::RenderGraphEntityNames::DEFERRED_COMPOSITE_PASS.data())->GetNodeCompute(SHGraphicsConstants::RenderGraphEntityNames::DEFERRED_COMPOSITE_COMPUTE.data());
|
||||
nodeCompute->ModifyWriteDescImageComputeResource(SHGraphicsConstants::DescriptorSetBindings::SHADOW_MAP_IMAGE_SAMPLER_DATA, lightingSubSystem->GetViewSamplerLayout(NEW_SHADOW_MAP_INDEX), NEW_SHADOW_MAP_INDEX);
|
||||
|
||||
return eventPtr->handle;
|
||||
}
|
||||
|
||||
Handle<SHMaterial> SHGraphicsSystem::AddMaterial(Handle<SHVkShaderModule> vertShader, Handle<SHVkShaderModule> fragShader, Handle<SHSubpass> subpass)
|
||||
|
@ -819,6 +896,7 @@ namespace SHADE
|
|||
case PrimitiveType::Sphere:
|
||||
case PrimitiveType::LineCube:
|
||||
case PrimitiveType::LineCircle:
|
||||
case PrimitiveType::LineCapsuleCap:
|
||||
return primitiveMeshes[static_cast<int>(type)];
|
||||
default:
|
||||
return {};
|
||||
|
@ -1045,6 +1123,7 @@ namespace SHADE
|
|||
|
||||
mousePickSubSystem->HandleResize();
|
||||
postOffscreenRenderSubSystem->HandleResize();
|
||||
//lightingSubSystem->HandleResize(renderGraph->GetNode(SHGraphicsConstants::RenderGraphEntityNames::DEFERRED_COMPOSITE_PASS.data())->GetNodeCompute(SHGraphicsConstants::RenderGraphEntityNames::DEFERRED_COMPOSITE_COMPUTE.data()));
|
||||
|
||||
worldViewport->SetWidth(static_cast<float>(resizeWidth));
|
||||
worldViewport->SetHeight(static_cast<float>(resizeHeight));
|
||||
|
@ -1077,7 +1156,7 @@ namespace SHADE
|
|||
|
||||
Handle<SHRenderGraphNode> SHGraphicsSystem::GetPrimaryRenderpass() const noexcept
|
||||
{
|
||||
return renderGraph->GetNode(G_BUFFER_RENDER_GRAPH_NODE_NAME.data());
|
||||
return renderGraph->GetNode(SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_PASS.data());
|
||||
}
|
||||
|
||||
Handle<SHVkPipeline> SHGraphicsSystem::GetDebugDrawPipeline(DebugDrawPipelineType type) const noexcept
|
||||
|
|
|
@ -72,9 +72,10 @@ namespace SHADE
|
|||
Cube,
|
||||
Sphere,
|
||||
LineCube,
|
||||
LineCircle
|
||||
LineCircle,
|
||||
LineCapsuleCap
|
||||
};
|
||||
static constexpr int MAX_PRIMITIVE_TYPES = 4;
|
||||
static constexpr int MAX_PRIMITIVE_TYPES = 5;
|
||||
enum class DebugDrawPipelineType
|
||||
{
|
||||
LineNoDepthTest,
|
||||
|
@ -177,7 +178,7 @@ namespace SHADE
|
|||
/*-----------------------------------------------------------------------*/
|
||||
/* Light functions */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
SHEventHandle ReceiveLightEnableShadowEvent (SHEventPtr event) noexcept;
|
||||
SHEventHandle ReceiveLightEnableShadowEvent (SHEventPtr eventPtr) noexcept;
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Material Functions */
|
||||
|
@ -405,10 +406,6 @@ namespace SHADE
|
|||
SHWindow* GetWindow() noexcept { return window; }
|
||||
|
||||
private:
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Constants */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
static constexpr std::string_view G_BUFFER_RENDER_GRAPH_NODE_NAME = "G-Buffer";
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Data Members */
|
||||
|
@ -445,6 +442,7 @@ namespace SHADE
|
|||
#endif
|
||||
|
||||
Handle<SHViewport> worldViewport; // Whole screen
|
||||
Handle<SHViewport> shadowMapViewport;
|
||||
std::vector<Handle<SHViewport>> viewports; // Additional viewports
|
||||
|
||||
// Renderers
|
||||
|
@ -468,6 +466,7 @@ namespace SHADE
|
|||
Handle<SHVkShaderModule> textFS;
|
||||
Handle<SHVkShaderModule> renderToSwapchainVS;
|
||||
Handle<SHVkShaderModule> renderToSwapchainFS;
|
||||
Handle<SHVkShaderModule> shadowMapVS;
|
||||
|
||||
// Fonts
|
||||
Handle<SHFont> testFont;
|
||||
|
@ -482,6 +481,7 @@ namespace SHADE
|
|||
Handle<SHVkPipeline> debugDrawWireMeshDepthPipeline;
|
||||
Handle<SHVkPipeline> debugDrawFilledPipeline;
|
||||
Handle<SHVkPipeline> debugDrawFilledDepthPipeline;
|
||||
Handle<SHVkPipeline> shadowMapPipeline; // initialized only when a shadow map is needed
|
||||
|
||||
// Built-In Textures
|
||||
Handle<SHTexture> defaultTexture;
|
||||
|
|
|
@ -122,4 +122,9 @@ namespace SHADE
|
|||
return cameraDirector;
|
||||
}
|
||||
|
||||
SHShaderCameraData SHRenderer::GetCPUCameraData(void) const noexcept
|
||||
{
|
||||
return cpuCameraData;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -18,9 +18,9 @@ of DigiPen Institute of Technology is prohibited.
|
|||
// Project Includes
|
||||
#include "SHCamera.h"
|
||||
#include "Resource/SHHandle.h"
|
||||
#include "Graphics/RenderGraph/SHRenderGraph.h"
|
||||
#include "Math/SHMath.h"
|
||||
#include <vector>
|
||||
#include "Graphics/Pipeline/SHPipelineType.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
@ -93,6 +93,7 @@ namespace SHADE
|
|||
/* Setters and Getters */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
Handle<SHCameraDirector> GetCameraDirector (void) const noexcept;
|
||||
SHShaderCameraData GetCPUCameraData (void) const noexcept;
|
||||
|
||||
private:
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include "SHLightComponent.h"
|
||||
#include "Graphics/Events/SHGraphicsEvents.h"
|
||||
#include "Events/SHEventManager.hpp"
|
||||
#include "Graphics/MiddleEnd/Interface/SHRenderer.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
@ -14,6 +15,7 @@ namespace SHADE
|
|||
//indexInBuffer = std::numeric_limits<uint32_t>::max();
|
||||
isActive = true;
|
||||
//Unbind();
|
||||
renderer = {};
|
||||
}
|
||||
|
||||
|
||||
|
@ -116,11 +118,22 @@ namespace SHADE
|
|||
// Create new event and broadcast it
|
||||
SHLightEnableShadowEvent newEvent;
|
||||
newEvent.lightEntity = GetEID();
|
||||
newEvent.generateRenderer = static_cast<bool>(!renderer);
|
||||
|
||||
SHEventManager::BroadcastEvent<SHLightEnableShadowEvent>(newEvent, SH_GRAPHICS_LIGHT_ENABLE_SHADOW_EVENT);
|
||||
}
|
||||
}
|
||||
|
||||
void SHLightComponent::SetRenderer(Handle<SHRenderer> newRenderer) noexcept
|
||||
{
|
||||
renderer = newRenderer;
|
||||
}
|
||||
|
||||
void SHLightComponent::SetShadowMapIndex(uint32_t index) noexcept
|
||||
{
|
||||
lightData.shadowMapIndex = index;
|
||||
}
|
||||
|
||||
SHLightData const& SHLightComponent::GetLightData(void) const noexcept
|
||||
{
|
||||
return lightData;
|
||||
|
@ -172,6 +185,11 @@ namespace SHADE
|
|||
return lightData.strength;
|
||||
}
|
||||
|
||||
Handle<SHRenderer> SHLightComponent::GetRenderer(void) const noexcept
|
||||
{
|
||||
return renderer;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
RTTR_REGISTRATION
|
||||
|
|
|
@ -3,9 +3,11 @@
|
|||
#include <rttr/registration>
|
||||
#include "ECS_Base/Components/SHComponent.h"
|
||||
#include "SHLightData.h"
|
||||
#include "Resource/SHHandle.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
class SHRenderer;
|
||||
|
||||
class SH_API SHLightComponent final : public SHComponent
|
||||
{
|
||||
|
@ -14,6 +16,9 @@ namespace SHADE
|
|||
//! GPU depends on the type of the light.
|
||||
SHLightData lightData;
|
||||
|
||||
//! Renderer to calculate light world to projection matrix
|
||||
Handle<SHRenderer> renderer;
|
||||
|
||||
//! Since the lighting system is gonna be self contained and light weight, we store this
|
||||
//! so that we only write this to the CPU buffer when this light component change, we don't
|
||||
//! rewrite everything. However we still write to the GPU buffer when everything changes.
|
||||
|
@ -49,6 +54,8 @@ namespace SHADE
|
|||
//void SetBound (uint32_t inIndexInBuffer) noexcept;
|
||||
void SetStrength (float value) noexcept; // serialized
|
||||
void SetEnableShadow (bool flag) noexcept;
|
||||
void SetRenderer (Handle<SHRenderer> newRenderer) noexcept;
|
||||
void SetShadowMapIndex (uint32_t index) noexcept;
|
||||
|
||||
|
||||
SHLightData const& GetLightData (void) const noexcept;
|
||||
|
@ -61,6 +68,7 @@ namespace SHADE
|
|||
//bool GetBound (void) const noexcept;
|
||||
//uint32_t GetIndexInBuffer (void) const noexcept;
|
||||
float GetStrength (void) const noexcept;
|
||||
Handle<SHRenderer> GetRenderer (void) const noexcept;
|
||||
RTTR_ENABLE()
|
||||
};
|
||||
}
|
||||
|
|
|
@ -10,6 +10,13 @@
|
|||
#include "SHLightComponent.h"
|
||||
#include "Math/Vector/SHVec4.h"
|
||||
#include "Math/SHMatrix.h"
|
||||
#include "Graphics/Images/SHVkImageView.h"
|
||||
#include "Graphics/MiddleEnd/Textures/SHVkSamplerCache.h"
|
||||
#include "Graphics/Images/SHVkSampler.h"
|
||||
#include "Graphics/Events/SHGraphicsEvents.h"
|
||||
#include "Graphics/MiddleEnd/Interface/SHRenderer.h"
|
||||
#include "Math/Transform/SHTransformComponent.h"
|
||||
#include "Graphics/RenderGraph/SHRenderGraphNodeCompute.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
@ -50,6 +57,19 @@ namespace SHADE
|
|||
//lightPtr->direction = lightData.direction;
|
||||
lightPtr->diffuseColor = lightData.color;
|
||||
lightPtr->active = lightComp->isActive;
|
||||
|
||||
// write view projection matrix if renderer is available
|
||||
auto lightRenderer = lightComp->GetRenderer();
|
||||
if (lightRenderer)
|
||||
{
|
||||
lightPtr->pvMatrix = lightRenderer->GetCPUCameraData().viewProjectionMatrix;
|
||||
|
||||
// Boolean to cast shadows in first 8 bits (1 byte)
|
||||
lightPtr->shadowData = lightData.castShadows;
|
||||
|
||||
// Next 24 bits for shadow map index
|
||||
lightPtr->shadowData |= (lightData.shadowMapIndex << 8);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SH_LIGHT_TYPE::POINT:
|
||||
|
@ -365,6 +385,32 @@ namespace SHADE
|
|||
}
|
||||
}
|
||||
|
||||
void SHLightingSubSystem::UpdateShadowMapDesc(void) noexcept
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
SHMatrix SHLightingSubSystem::GetViewMatrix(SHLightComponent* lightComp) noexcept
|
||||
{
|
||||
switch (lightComp->GetLightData().type)
|
||||
{
|
||||
case SH_LIGHT_TYPE::DIRECTIONAL:
|
||||
return SHMatrix::Transpose(SHMatrix::LookAtLH(lightComp->GetLightData().position, SHVec3::Normalise (lightComp->GetLightData().direction), SHVec3(0.0f, -1.0f, 0.0f)));
|
||||
//return SHMatrix::Transpose(SHMatrix::LookAtLH(/*lightComp->GetLightData().position*/SHVec3(1.27862f, 4.78952f, 4.12811f), SHVec3(-0.280564f, -0.66262f, -0.69422f), SHVec3(0.0f, -1.0f, 0.0f)));
|
||||
case SH_LIGHT_TYPE::POINT:
|
||||
return {};
|
||||
case SH_LIGHT_TYPE::SPOT:
|
||||
return {};
|
||||
case SH_LIGHT_TYPE::AMBIENT:
|
||||
return {};
|
||||
case SH_LIGHT_TYPE::NUM_TYPES:
|
||||
return {};
|
||||
default:
|
||||
return {};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
|
@ -375,13 +421,15 @@ namespace SHADE
|
|||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
void SHLightingSubSystem::Init(Handle<SHVkLogicalDevice> device, Handle<SHVkDescriptorPool> descPool) noexcept
|
||||
void SHLightingSubSystem::Init(Handle<SHVkLogicalDevice> device, Handle<SHVkDescriptorPool> descPool, SHResourceHub* rh, Handle<SHVkSampler> inShadowMapSampler) noexcept
|
||||
{
|
||||
SHComponentManager::CreateComponentSparseSet<SHLightComponent>();
|
||||
|
||||
logicalDevice = device;
|
||||
resourceHub = rh;
|
||||
uint32_t constexpr NUM_LIGHT_TYPES = SHUtilities::ConvertEnum(SH_LIGHT_TYPE::NUM_TYPES);
|
||||
|
||||
#pragma region LIGHTING
|
||||
std::vector<uint32_t> variableSizes{ NUM_LIGHT_TYPES };
|
||||
std::fill (variableSizes.begin(), variableSizes.end(), 1);
|
||||
|
||||
|
@ -418,7 +466,22 @@ namespace SHADE
|
|||
dynamicOffsets[i].resize(NUM_LIGHT_TYPES + 1); // +1 for the count
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region SHADOWS
|
||||
//std::vector<uint32_t> shadowDescVariableSizes{ MAX_SHADOWS };
|
||||
//shadowMapDescriptorSet = descPool->Allocate({SHGraphicsPredefinedData::GetPredefinedDescSetLayouts(SHGraphicsPredefinedData::PredefinedDescSetLayoutTypes::SHADOW)}, shadowDescVariableSizes);
|
||||
|
||||
//#ifdef _DEBUG
|
||||
// const auto& SHADOW_MAP_DESC_SETS = shadowMapDescriptorSet->GetVkHandle();
|
||||
// for (int i = 0; i < static_cast<int>(SHADOW_MAP_DESC_SETS.size()); ++i)
|
||||
// SET_VK_OBJ_NAME(logicalDevice, vk::ObjectType::eDescriptorSet, SHADOW_MAP_DESC_SETS[i], "[Descriptor Set] Shadow Map Data Frame #" + std::to_string(i));
|
||||
//#endif
|
||||
|
||||
shadowMapSampler = inShadowMapSampler;
|
||||
shadowMaps.clear();
|
||||
//numLightComponents = 0;
|
||||
#pragma endregion
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
@ -452,6 +515,12 @@ namespace SHADE
|
|||
|
||||
for (auto& light : lightComps)
|
||||
{
|
||||
if (auto renderer = light.GetRenderer())
|
||||
{
|
||||
//SHMatrix orthoMatrix = SHMatrix::OrthographicRH()
|
||||
renderer->UpdateDataManual(frameIndex, GetViewMatrix(&light), SHMatrix::OrthographicLH(10.0f, 10.0f, 1.0f, 50.0f));
|
||||
}
|
||||
|
||||
auto enumValue = SHUtilities::ConvertEnum(light.GetLightData().type);
|
||||
|
||||
// First we want to make sure the light is already bound to the system. if it
|
||||
|
@ -503,7 +572,6 @@ namespace SHADE
|
|||
// so we do it anyway. #NoteToSelf: if at any point it affects performance, do a check before computing.
|
||||
ComputeDynamicOffsets();
|
||||
|
||||
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
@ -526,9 +594,101 @@ namespace SHADE
|
|||
|
||||
}
|
||||
|
||||
uint32_t SHLightingSubSystem::AddShadowMap(Handle<SHRenderGraphResource> newShadowMap, EntityID lightEntity) noexcept
|
||||
{
|
||||
// Add to container of shadow maps
|
||||
shadowMapIndexing.emplace(lightEntity, static_cast<uint32_t> (shadowMaps.size()));
|
||||
shadowMaps.emplace_back(newShadowMap);
|
||||
|
||||
// Just use the image view stored in the resource
|
||||
Handle<SHVkImageView> const NEW_IMAGE_VIEW = newShadowMap->GetImageView();
|
||||
|
||||
// Prepare to write to descriptor
|
||||
shadowMapImageSamplers.emplace_back(NEW_IMAGE_VIEW, shadowMapSampler, vk::ImageLayout::eShaderReadOnlyOptimal);
|
||||
|
||||
// Update descriptor set
|
||||
//static constexpr uint32_t SHADOW_MAP_DESC_SET_INDEX = 0;
|
||||
//uint32_t const SHADOW_MAP_DESC_ARRAY_INDEX = static_cast<uint32_t>(shadowMapImageSamplers.size()) - 1u;
|
||||
//shadowMapDescriptorSet->ModifyWriteDescImage
|
||||
//(
|
||||
// SHADOW_MAP_DESC_SET_INDEX,
|
||||
// SHGraphicsConstants::DescriptorSetBindings::SHADOW_MAP_IMAGE_SAMPLER_DATA,
|
||||
// shadowMapImageSamplers[SHADOW_MAP_DESC_ARRAY_INDEX],
|
||||
// SHADOW_MAP_DESC_ARRAY_INDEX
|
||||
//);
|
||||
|
||||
//// TODO: Definitely can be optimized by writing a function that modifies a specific descriptor in the array
|
||||
//shadowMapDescriptorSet->UpdateDescriptorSetImages
|
||||
//(
|
||||
// SHADOW_MAP_DESC_SET_INDEX,
|
||||
// SHGraphicsConstants::DescriptorSetBindings::SHADOW_MAP_IMAGE_SAMPLER_DATA
|
||||
//);
|
||||
|
||||
// add to barriers
|
||||
shadowMapMemoryBarriers.push_back (vk::ImageMemoryBarrier
|
||||
{
|
||||
.srcAccessMask = vk::AccessFlagBits::eDepthStencilAttachmentWrite,
|
||||
.dstAccessMask = vk::AccessFlagBits::eShaderRead,
|
||||
.oldLayout = vk::ImageLayout::eDepthAttachmentOptimal,
|
||||
.newLayout = vk::ImageLayout::eShaderReadOnlyOptimal,
|
||||
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.image = newShadowMap->GetImage()->GetVkImage(),
|
||||
.subresourceRange = vk::ImageSubresourceRange
|
||||
{
|
||||
.aspectMask = vk::ImageAspectFlagBits::eDepth,
|
||||
.baseMipLevel = 0,
|
||||
.levelCount = 1,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = 1,
|
||||
}
|
||||
});
|
||||
|
||||
// return new index of shadow map
|
||||
return static_cast<uint32_t>(shadowMapImageSamplers.size()) - 1u;
|
||||
}
|
||||
|
||||
void SHLightingSubSystem::PrepareShadowMapsForRead(Handle<SHVkCommandBuffer> cmdBuffer) noexcept
|
||||
{
|
||||
// Issue barrier to transition shadow maps for reading in compute shader
|
||||
cmdBuffer->PipelineBarrier(vk::PipelineStageFlagBits::eEarlyFragmentTests | vk::PipelineStageFlagBits::eLateFragmentTests, vk::PipelineStageFlagBits::eComputeShader, {}, {}, {}, shadowMapMemoryBarriers);
|
||||
}
|
||||
|
||||
//void SHLightingSubSystem::HandleResize(Handle<SHRenderGraphNodeCompute> compute) noexcept
|
||||
//{
|
||||
// uint32_t const NUM_SHADOW_MAPS = static_cast<uint32_t>(shadowMaps.size());
|
||||
// for (uint32_t i = 0; i < NUM_SHADOW_MAPS; ++i)
|
||||
// {
|
||||
// // Just use the image view stored in the resource
|
||||
// Handle<SHVkImageView> const NEW_IMAGE_VIEW = shadowMaps[i]->GetImageView();
|
||||
|
||||
// // set new image view
|
||||
// std::get<Handle<SHVkImageView>>(shadowMapImageSamplers[i]) = NEW_IMAGE_VIEW;
|
||||
|
||||
// // Set image for barrier
|
||||
// shadowMapMemoryBarriers[i].image = shadowMaps[i]->GetImage()->GetVkImage();
|
||||
// }
|
||||
|
||||
// if (NUM_SHADOW_MAPS > 0)
|
||||
// {
|
||||
// // modify descriptors in render graph node compute
|
||||
// compute->ModifyWriteDescImageComputeResource (SHGraphicsConstants::DescriptorSetBindings::SHADOW_MAP_IMAGE_SAMPLER_DATA, shadowMapImageSamplers);
|
||||
// }
|
||||
//}
|
||||
|
||||
Handle<SHVkDescriptorSetGroup> SHLightingSubSystem::GetLightDataDescriptorSet(void) const noexcept
|
||||
{
|
||||
return lightingDataDescSet;
|
||||
}
|
||||
|
||||
std::tuple<Handle<SHVkImageView>, Handle<SHVkSampler>, vk::ImageLayout> const& SHLightingSubSystem::GetViewSamplerLayout(uint32_t index) const noexcept
|
||||
{
|
||||
return shadowMapImageSamplers[index];
|
||||
}
|
||||
|
||||
uint32_t SHLightingSubSystem::GetNumShadowMaps(void) const noexcept
|
||||
{
|
||||
return static_cast<uint32_t>(shadowMaps.size());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -3,9 +3,13 @@
|
|||
#include "Resource/SHHandle.h"
|
||||
#include "Math/Vector/SHVec3.h"
|
||||
#include "Math/Vector/SHVec4.h"
|
||||
#include "Math/SHMatrix.h"
|
||||
#include "SHLightData.h"
|
||||
#include <array>
|
||||
#include "Graphics/MiddleEnd/Interface/SHGraphicsConstants.h"
|
||||
#include "Graphics/RenderGraph/SHRenderGraphResource.h"
|
||||
#include "ECS_Base/SHECSMacros.h"
|
||||
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
@ -16,6 +20,10 @@ namespace SHADE
|
|||
class SHVkBuffer;
|
||||
class SHLightComponent;
|
||||
class SHVkCommandBuffer;
|
||||
class SHSamplerCache;
|
||||
class SHVkImageView;
|
||||
class SHVkSampler;
|
||||
class SHRenderGraphNodeCompute;
|
||||
|
||||
// Represents how the data will be interpreted in GPU. we want to copy to a container of these before passing to GPU.
|
||||
struct SHDirectionalLightData
|
||||
|
@ -34,6 +42,12 @@ namespace SHADE
|
|||
//! Diffuse color emitted by the light
|
||||
alignas (16) SHVec4 diffuseColor;
|
||||
|
||||
//! Matrix for world to projection from light's perspective
|
||||
SHMatrix pvMatrix;
|
||||
|
||||
//! Represents boolean for casting shadows in first byte and shadow map index in the other 3.
|
||||
uint32_t shadowData;
|
||||
|
||||
};
|
||||
|
||||
// Represents how the data will be interpreted in GPU. we want to copy to a container of these before passing to GPU.
|
||||
|
@ -52,24 +66,27 @@ namespace SHADE
|
|||
//! 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;
|
||||
|
||||
|
||||
};
|
||||
|
||||
class SH_API SHLightingSubSystem
|
||||
{
|
||||
public:
|
||||
using DynamicOffsetArray = std::array<std::vector<uint32_t>, static_cast<uint32_t>(SHGraphicsConstants::NUM_FRAME_BUFFERS)>;
|
||||
|
||||
static constexpr uint32_t MAX_SHADOWS = 200;
|
||||
static constexpr uint32_t SHADOW_MAP_WIDTH = 1024;
|
||||
static constexpr uint32_t SHADOW_MAP_HEIGHT = 1024;
|
||||
|
||||
private:
|
||||
class PerTypeData
|
||||
{
|
||||
public:
|
||||
|
||||
|
||||
private:
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* STATIC MEMBER VARIABLES */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
static constexpr uint32_t STARTING_NUM_LIGHTS = 50;
|
||||
static constexpr uint32_t STARTING_NUM_LIGHTS = 50;
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* PRIVATE MEMBER VARIABLES */
|
||||
|
@ -123,51 +140,90 @@ namespace SHADE
|
|||
};
|
||||
|
||||
private:
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* STATIC MEMBER VARIABLES */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
|
||||
//! logical device used for creation
|
||||
Handle<SHVkLogicalDevice> logicalDevice;
|
||||
Handle<SHVkLogicalDevice> logicalDevice;
|
||||
|
||||
//! The descriptor set that will hold the lighting data. Each binding will hold a buffer, NUM_FRAMES times the size required.
|
||||
Handle<SHVkDescriptorSetGroup> lightingDataDescSet;
|
||||
|
||||
//! Each type will have some data associated with it for processing
|
||||
std::array<PerTypeData, static_cast<uint32_t>(SH_LIGHT_TYPE::NUM_TYPES)> perTypeData;
|
||||
|
||||
//! Container to store dynamic offsets for binding descriptor sets
|
||||
DynamicOffsetArray dynamicOffsets;
|
||||
|
||||
//! holds the data that represents how many lights are in the scene
|
||||
std::array<uint32_t, static_cast<uint32_t>(SH_LIGHT_TYPE::NUM_TYPES)> lightCountsData;
|
||||
|
||||
//! GPU buffer to hold lightCountData
|
||||
Handle<SHVkBuffer> lightCountsBuffer;
|
||||
|
||||
//! For padding in the buffer
|
||||
uint32_t lightCountsAlignedSize;
|
||||
Handle<SHVkDescriptorSetGroup> lightingDataDescSet;
|
||||
|
||||
//! Each type will have some data associated with it for processing
|
||||
std::array<PerTypeData, static_cast<uint32_t>(SH_LIGHT_TYPE::NUM_TYPES)> perTypeData;
|
||||
|
||||
//! Container to store dynamic offsets for binding descriptor sets
|
||||
DynamicOffsetArray dynamicOffsets;
|
||||
|
||||
//! holds the data that represents how many lights are in the scene
|
||||
std::array<uint32_t, static_cast<uint32_t>(SH_LIGHT_TYPE::NUM_TYPES)> lightCountsData;
|
||||
|
||||
//! GPU buffer to hold lightCountData
|
||||
Handle<SHVkBuffer> 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;
|
||||
|
||||
//! Handle to sampler that all shadow map descriptors will use
|
||||
Handle<SHVkSampler> shadowMapSampler;
|
||||
|
||||
//! For indexing shadow maps
|
||||
std::unordered_map<EntityID, uint32_t> shadowMapIndexing;
|
||||
|
||||
//! Shadow maps for every light that casts a shadow Order here doesn't matter. We just want to store it
|
||||
std::vector<Handle<SHRenderGraphResource>> shadowMaps;
|
||||
|
||||
//! Descriptor sets required to be given to the compute shader for shadow calculation. This will be a descriptor array.
|
||||
//! It will also be preallocated.
|
||||
//Handle<SHVkDescriptorSetGroup> shadowMapDescriptorSet;
|
||||
|
||||
//! Combined image samplers for the texture descriptors
|
||||
std::vector<std::tuple<Handle<SHVkImageView>, Handle<SHVkSampler>, vk::ImageLayout>> shadowMapImageSamplers;
|
||||
|
||||
//! Barriers required to transition the resources from whatever layout they are in (probably from VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL)
|
||||
//! to VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
|
||||
std::vector<vk::ImageMemoryBarrier> shadowMapMemoryBarriers;
|
||||
|
||||
//! Resource hub from Graphics System
|
||||
SHResourceHub* resourceHub;
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* PRIVATE MEMBER FUNCTIONS */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
void UpdateDescSet (uint32_t binding) noexcept;
|
||||
void ComputeDynamicOffsets (void) noexcept;
|
||||
void ResetNumLights (void) noexcept;
|
||||
void UpdateShadowMapDesc (void) noexcept;
|
||||
SHMatrix GetViewMatrix (SHLightComponent* lightComp) noexcept;
|
||||
|
||||
public:
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* PUBLIC MEMBER FUNCTIONS */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
void Init (Handle<SHVkLogicalDevice> device, Handle<SHVkDescriptorPool> descPool) noexcept;
|
||||
void Run (SHMatrix const& viewMat, uint32_t frameIndex) noexcept;
|
||||
void Exit (void) noexcept;
|
||||
void Init (Handle<SHVkLogicalDevice> device, Handle<SHVkDescriptorPool> descPool, SHResourceHub* rh, Handle<SHVkSampler> inShadowMapSampler) noexcept;
|
||||
void Run (SHMatrix const& viewMat, uint32_t frameIndex) noexcept;
|
||||
void Exit (void) noexcept;
|
||||
void BindDescSet (Handle<SHVkCommandBuffer> cmdBuffer, uint32_t setIndex, uint32_t frameIndex) noexcept;
|
||||
uint32_t AddShadowMap (Handle<SHRenderGraphResource> newShadowMap, EntityID lightEntity) noexcept;
|
||||
void PrepareShadowMapsForRead (Handle<SHVkCommandBuffer> cmdBuffer) noexcept;
|
||||
//void HandleResize (Handle<SHRenderGraphNodeCompute> compute) noexcept;
|
||||
//void RemoveShadowMap (uint32_t index) noexcept;
|
||||
|
||||
void BindDescSet (Handle<SHVkCommandBuffer> cmdBuffer, uint32_t setIndex, uint32_t frameIndex) noexcept;
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* SETTERS AND GETTERS */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
Handle<SHVkDescriptorSetGroup> GetLightDataDescriptorSet (void) const noexcept;
|
||||
std::tuple<Handle<SHVkImageView>, Handle<SHVkSampler>, vk::ImageLayout> const& GetViewSamplerLayout (uint32_t index) const noexcept;
|
||||
uint32_t GetNumShadowMaps (void) const noexcept;
|
||||
|
||||
};
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ namespace SHADE
|
|||
SHMeshData SHPrimitiveGenerator::sphereMesh;
|
||||
SHMeshData SHPrimitiveGenerator::lineCubeMesh;
|
||||
SHMeshData SHPrimitiveGenerator::lineCircleMesh;
|
||||
SHMeshData SHPrimitiveGenerator::lineCapsuleCapMesh;
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Primitive Generation Functions */
|
||||
|
@ -392,6 +393,64 @@ namespace SHADE
|
|||
return addMeshDataTo(lineCircleMesh, gfxSystem);
|
||||
}
|
||||
|
||||
SHADE::SHMeshData SHPrimitiveGenerator::LineCapsuleCap() noexcept
|
||||
{
|
||||
SHMeshData mesh;
|
||||
|
||||
// Have multiple semi-circles for the cap
|
||||
static constexpr int SPLITS = 36;
|
||||
static constexpr float ANGLE_INCREMENTS = (std::numbers::pi_v<float> * 2.0f) / static_cast<float>(SPLITS);
|
||||
|
||||
/* X-Axis */
|
||||
// Generate points of the circle
|
||||
for (int i = 0; i <= SPLITS / 2; ++i)
|
||||
{
|
||||
const float ANGLE = ANGLE_INCREMENTS * i;
|
||||
mesh.VertexPositions.emplace_back(cos(ANGLE) * 0.5f, sin(ANGLE) * 0.5f, 0.0f);
|
||||
}
|
||||
|
||||
// Generate lines of the circle
|
||||
for (int i = 1; i <= SPLITS / 2; ++i)
|
||||
{
|
||||
mesh.Indices.emplace_back(static_cast<uint32_t>(i - 1));
|
||||
mesh.Indices.emplace_back(static_cast<uint32_t>(i));
|
||||
}
|
||||
|
||||
/* Z-Axis */
|
||||
// Generate points of the circle
|
||||
for (int i = 0; i <= SPLITS / 2; ++i)
|
||||
{
|
||||
const float ANGLE = ANGLE_INCREMENTS * i;
|
||||
mesh.VertexPositions.emplace_back(0.0f, sin(ANGLE) * 0.5f, cos(ANGLE) * 0.5f);
|
||||
}
|
||||
|
||||
// Generate lines of the circle
|
||||
for (int i = 2 + SPLITS / 2; i <= SPLITS + 1; ++i)
|
||||
{
|
||||
mesh.Indices.emplace_back(static_cast<uint32_t>(i - 1));
|
||||
mesh.Indices.emplace_back(static_cast<uint32_t>(i));
|
||||
}
|
||||
|
||||
mesh.VertexNormals.resize(mesh.VertexPositions.size());
|
||||
mesh.VertexTangents.resize(mesh.VertexPositions.size());
|
||||
mesh.VertexTexCoords.resize(mesh.VertexPositions.size());
|
||||
|
||||
return mesh;
|
||||
}
|
||||
Handle<SHADE::SHMesh> SHPrimitiveGenerator::LineCapsuleCap(SHMeshLibrary& meshLibrary) noexcept
|
||||
{
|
||||
if (lineCapsuleCapMesh.VertexPositions.empty())
|
||||
lineCapsuleCapMesh = LineCapsuleCap();
|
||||
|
||||
return addMeshDataTo(lineCapsuleCapMesh, meshLibrary);
|
||||
}
|
||||
Handle<SHADE::SHMesh> SHPrimitiveGenerator::LineCapsuleCap(SHGraphicsSystem& gfxSystem) noexcept
|
||||
{
|
||||
if (lineCapsuleCapMesh.VertexPositions.empty())
|
||||
lineCapsuleCapMesh = LineCapsuleCap();
|
||||
|
||||
return addMeshDataTo(lineCapsuleCapMesh, gfxSystem);
|
||||
}
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Helper Functions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
|
|
@ -194,6 +194,46 @@ namespace SHADE
|
|||
*/
|
||||
/***********************************************************************************/
|
||||
[[nodiscard]] static Handle<SHMesh> LineCircle(SHGraphicsSystem& gfxSystem) noexcept;
|
||||
/***********************************************************************************/
|
||||
/*!
|
||||
\brief
|
||||
Produces a cap of a wireframe capsule that is comprised only of lines and
|
||||
store the data in a SHMeshData object.
|
||||
|
||||
\return
|
||||
SHMeshData object containing vertex data for the line circle.
|
||||
*/
|
||||
/***********************************************************************************/
|
||||
[[nodiscard]] static SHMeshData LineCapsuleCap() noexcept;
|
||||
/***********************************************************************************/
|
||||
/*!
|
||||
\brief
|
||||
Produces a cap of a wireframe capsule that is comprised only of lines and
|
||||
constructs a SHMesh using the SHGraphicsSystem provided.
|
||||
|
||||
\param meshLibrary
|
||||
Reference to the SHMeshLibrary to produce and store a line circle mesh in.
|
||||
|
||||
\return
|
||||
SHMesh object that points to the generated line circle mesh in the SHMeshLibrary.
|
||||
*/
|
||||
/***********************************************************************************/
|
||||
[[nodiscard]] static Handle<SHMesh> LineCapsuleCap(SHMeshLibrary& meshLibrary) noexcept;
|
||||
/***********************************************************************************/
|
||||
/*!
|
||||
\brief
|
||||
Produces a cap of a wireframe capsule that is comprised only of lines and
|
||||
constructs a SHMesh using the SHGraphicsSystem provided.
|
||||
|
||||
\param gfxSystem
|
||||
Reference to the SHGraphicsSystem to produce and store a line circle mesh in.
|
||||
|
||||
\return
|
||||
SHMesh object that points to the generated line circle mesh in the
|
||||
SHGraphicsSystem.
|
||||
*/
|
||||
/***********************************************************************************/
|
||||
[[nodiscard]] static Handle<SHMesh> LineCapsuleCap(SHGraphicsSystem& gfxSystem) noexcept;
|
||||
|
||||
private:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
@ -209,5 +249,6 @@ namespace SHADE
|
|||
static SHMeshData sphereMesh;
|
||||
static SHMeshData lineCubeMesh;
|
||||
static SHMeshData lineCircleMesh;
|
||||
static SHMeshData lineCapsuleCapMesh;
|
||||
};
|
||||
}
|
|
@ -1,18 +1,23 @@
|
|||
#include "SHpch.h"
|
||||
#include "SHPipelineLibrary.h"
|
||||
#include "Graphics/Devices/SHVkLogicalDevice.h"
|
||||
#include "Graphics/MiddleEnd/GlobalData/SHGraphicsPredefinedData.h"
|
||||
#include "Graphics/RenderGraph/SHSubpass.h"
|
||||
#include "Graphics/SHVkUtil.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
||||
Handle<SHVkPipeline> SHPipelineLibrary::CreateGraphicsPipelines(std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair, Handle<SHVkRenderpass> renderpass, Handle<SHSubpass> subpass) noexcept
|
||||
Handle<SHVkPipeline> SHPipelineLibrary::CreateGraphicsPipelines(std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair, Handle<SHVkRenderpass> renderpass, Handle<SHSubpass> subpass, SHVertexInputState const& viState/* = SHGraphicsPredefinedData::GetDefaultViState()*/, SHRasterizationState const& rasterState) noexcept
|
||||
{
|
||||
std::vector<Handle<SHVkShaderModule>> modules{};
|
||||
if (vsFsPair.first)
|
||||
modules.push_back(vsFsPair.first);
|
||||
if (vsFsPair.second)
|
||||
modules.push_back(vsFsPair.second);
|
||||
|
||||
SHPipelineLayoutParams params
|
||||
{
|
||||
.shaderModules = {vsFsPair.first, vsFsPair.second},
|
||||
.shaderModules = std::move(modules),
|
||||
.predefinedDescSetLayouts = SHGraphicsPredefinedData::GetSystemData(SHGraphicsPredefinedData::SystemType::BATCHING).descSetLayouts
|
||||
};
|
||||
|
||||
|
@ -21,7 +26,7 @@ namespace SHADE
|
|||
|
||||
// Create the pipeline and configure the default vertex input state
|
||||
auto newPipeline = logicalDevice->CreateGraphicsPipeline(pipelineLayout, nullptr, renderpass, subpass);
|
||||
newPipeline->GetPipelineState().SetVertexInputState(SHGraphicsPredefinedData::GetDefaultViState());
|
||||
newPipeline->GetPipelineState().SetVertexInputState(viState);
|
||||
|
||||
SHColorBlendState colorBlendState{};
|
||||
colorBlendState.logic_op_enable = VK_FALSE;
|
||||
|
@ -30,6 +35,7 @@ namespace SHADE
|
|||
auto const& subpassColorReferences = subpass->GetColorAttachmentReferences();
|
||||
colorBlendState.attachments.reserve(subpassColorReferences.size());
|
||||
|
||||
|
||||
for (auto& att : subpassColorReferences)
|
||||
{
|
||||
colorBlendState.attachments.push_back(vk::PipelineColorBlendAttachmentState
|
||||
|
@ -47,6 +53,8 @@ namespace SHADE
|
|||
}
|
||||
|
||||
newPipeline->GetPipelineState().SetColorBlenState(colorBlendState);
|
||||
|
||||
newPipeline->GetPipelineState().SetRasterizationState(rasterState);
|
||||
|
||||
// Actually construct the pipeline
|
||||
newPipeline->ConstructPipeline();
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include <unordered_map>
|
||||
#include "Graphics/Shaders/SHVkShaderModule.h"
|
||||
#include "Graphics/Pipeline/SHVkPipeline.h"
|
||||
#include "Graphics/MiddleEnd/GlobalData/SHGraphicsPredefinedData.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
@ -32,7 +33,9 @@ namespace SHADE
|
|||
Handle<SHVkPipeline> CreateGraphicsPipelines (
|
||||
std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair,
|
||||
Handle<SHVkRenderpass> renderpass,
|
||||
Handle<SHSubpass> subpass
|
||||
Handle<SHSubpass> subpass,
|
||||
SHVertexInputState const& viState = SHGraphicsPredefinedData::GetDefaultViState(),
|
||||
SHRasterizationState const& rasterState = SHRasterizationState{}
|
||||
) noexcept;
|
||||
Handle<SHVkPipeline> GetGraphicsPipeline (std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair) noexcept;
|
||||
bool CheckGraphicsPipelineExistence (std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair) noexcept;
|
||||
|
|
|
@ -195,7 +195,7 @@ namespace SHADE
|
|||
return *this;
|
||||
}
|
||||
|
||||
void SHVertexInputState::AddBinding(bool instanced, bool calcOffset, std::initializer_list<SHVertexAttribute> inAttribs) noexcept
|
||||
void SHVertexInputState::AddBinding(bool instanced, bool calcOffset, std::initializer_list<SHVertexAttribute> inAttribs, uint32_t fixedBinding /*= static_cast<uint32_t>(-1)*/, uint32_t fixedAttributeLocation/* = static_cast<uint32_t>(-1)*/) noexcept
|
||||
{
|
||||
// add a binding and get ref to it
|
||||
bindings.emplace_back();
|
||||
|
@ -210,7 +210,7 @@ namespace SHADE
|
|||
// Offset is 0 at first (for first element)
|
||||
uint32_t offset = 0;
|
||||
|
||||
binding.binding = static_cast<uint32_t>(bindings.size() - 1);
|
||||
binding.binding = (fixedBinding != static_cast<uint32_t>(-1)) ? fixedBinding : static_cast<uint32_t>(bindings.size() - 1);
|
||||
|
||||
// for every attribute passed in
|
||||
for (auto const& attrib : inAttribs)
|
||||
|
@ -226,10 +226,11 @@ namespace SHADE
|
|||
auto& vertexAttrib = attributes.back();
|
||||
|
||||
// The binding for that attribute description is index of the new binding created earlier in this function
|
||||
vertexAttrib.binding = static_cast<uint32_t>(bindings.size() - 1);
|
||||
vertexAttrib.binding = (fixedBinding != static_cast<uint32_t>(-1)) ? fixedBinding : static_cast<uint32_t>(bindings.size() - 1);
|
||||
|
||||
// Attribute location. New index is simply + 1 of the previous. Starts from 0 obviously
|
||||
vertexAttrib.location = static_cast<uint32_t>(attributes.size () - 1);
|
||||
//Attribute location. New index is simply + 1 of the previous. Starts from 0 obviously
|
||||
vertexAttrib.location = (fixedAttributeLocation != static_cast<uint32_t>(-1)) ? fixedAttributeLocation + i : static_cast<uint32_t>(attributes.size () - 1);
|
||||
//vertexAttrib.location = static_cast<uint32_t>(attributes.size() - 1);
|
||||
|
||||
// Get the vkFormat associated with the SHAttribFormat
|
||||
vertexAttrib.format = format;
|
||||
|
|
|
@ -34,7 +34,7 @@ namespace SHADE
|
|||
SHVertexInputState& operator= (SHVertexInputState const& rhs) noexcept;
|
||||
SHVertexInputState& operator= (SHVertexInputState&& rhs) noexcept;
|
||||
|
||||
void AddBinding(bool instanced, bool calcOffset, std::initializer_list<SHVertexAttribute> inAttribs) noexcept;
|
||||
void AddBinding(bool instanced, bool calcOffset, std::initializer_list<SHVertexAttribute> inAttribs, uint32_t fixedBinding = static_cast<uint32_t>(-1), uint32_t fixedAttributeLocation = static_cast<uint32_t>(-1)) noexcept;
|
||||
|
||||
friend class SHVkPipelineState;
|
||||
friend class SHVkPipeline;
|
||||
|
|
|
@ -19,69 +19,71 @@ namespace SHADE
|
|||
|
||||
for (auto& shaderModule : shaderModules)
|
||||
{
|
||||
// References for convenience
|
||||
auto const& reflectedData = shaderModule->GetReflectedData();
|
||||
auto const& pcInfo = reflectedData.GetPushConstantInfo();
|
||||
|
||||
// If a push constant block exists for the shader module
|
||||
if (pcInfo.memberCount != 0)
|
||||
if (shaderModule)
|
||||
{
|
||||
bool exists = false;
|
||||
// References for convenience
|
||||
auto const& reflectedData = shaderModule->GetReflectedData();
|
||||
auto const& pcInfo = reflectedData.GetPushConstantInfo();
|
||||
|
||||
// Check if push constant block already exists
|
||||
for (uint32_t i = 0; i < pcInfos.size(); ++i)
|
||||
// If a push constant block exists for the shader module
|
||||
if (pcInfo.memberCount != 0)
|
||||
{
|
||||
// If there is a block with the same name, member count and size
|
||||
if (std::strcmp(pcInfos[i]->name, pcInfo.name) == 0 && pcInfos[i]->memberCount == pcInfo.memberCount && pcInfos[i]->size == pcInfo.size)
|
||||
bool exists = false;
|
||||
|
||||
// Check if push constant block already exists
|
||||
for (uint32_t i = 0; i < pcInfos.size(); ++i)
|
||||
{
|
||||
// We just take the existing pc range we built earlier, and allow it to be accessed in potentially other shader stages
|
||||
vkPcRanges[i].stageFlags |= shaderModule->GetShaderStageFlagBits();
|
||||
// If there is a block with the same name, member count and size
|
||||
if (std::strcmp(pcInfos[i]->name, pcInfo.name) == 0 && pcInfos[i]->memberCount == pcInfo.memberCount && pcInfos[i]->size == pcInfo.size)
|
||||
{
|
||||
// We just take the existing pc range we built earlier, and allow it to be accessed in potentially other shader stages
|
||||
vkPcRanges[i].stageFlags |= shaderModule->GetShaderStageFlagBits();
|
||||
|
||||
// Set flag and stop checking
|
||||
exists = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If the block doesn't exist yet
|
||||
if (!exists)
|
||||
{
|
||||
// Loop through all member variables of the new push constant block
|
||||
for (uint32_t i = 0; i < pcInfo.memberCount; ++i)
|
||||
{
|
||||
std::string variableName;
|
||||
variableName.reserve(50);
|
||||
variableName += pcInfo.name;
|
||||
variableName += ".";
|
||||
variableName += pcInfo.members[i].name;
|
||||
|
||||
// Add the variable's offset info to the interface
|
||||
pushConstantInterface.AddOffset(std::move(variableName), startOffset + pcInfo.members[i].offset);
|
||||
// Set flag and stop checking
|
||||
exists = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// New push constant range
|
||||
vk::PushConstantRange newRange;
|
||||
// If the block doesn't exist yet
|
||||
if (!exists)
|
||||
{
|
||||
// Loop through all member variables of the new push constant block
|
||||
for (uint32_t i = 0; i < pcInfo.memberCount; ++i)
|
||||
{
|
||||
std::string variableName;
|
||||
variableName.reserve(50);
|
||||
variableName += pcInfo.name;
|
||||
variableName += ".";
|
||||
variableName += pcInfo.members[i].name;
|
||||
|
||||
// set offset and size
|
||||
newRange.offset = startOffset;
|
||||
newRange.size = pcInfo.size;
|
||||
// Add the variable's offset info to the interface
|
||||
pushConstantInterface.AddOffset(std::move(variableName), startOffset + pcInfo.members[i].offset);
|
||||
}
|
||||
|
||||
// Stage flags will be whatever shader stage of the shader that contains the push constant block
|
||||
newRange.stageFlags = shaderModule->GetShaderStageFlagBits();
|
||||
// New push constant range
|
||||
vk::PushConstantRange newRange;
|
||||
|
||||
// Add to the list foe checking later
|
||||
pcInfos.push_back(&pcInfo);
|
||||
// set offset and size
|
||||
newRange.offset = startOffset;
|
||||
newRange.size = pcInfo.size;
|
||||
|
||||
// For pipeline layout to consume
|
||||
vkPcRanges.push_back(newRange);
|
||||
// Stage flags will be whatever shader stage of the shader that contains the push constant block
|
||||
newRange.stageFlags = shaderModule->GetShaderStageFlagBits();
|
||||
|
||||
// Next push constant block will start next to the previous push constant block
|
||||
startOffset += pcInfo.size;
|
||||
// Add to the list foe checking later
|
||||
pcInfos.push_back(&pcInfo);
|
||||
|
||||
// For pipeline layout to consume
|
||||
vkPcRanges.push_back(newRange);
|
||||
|
||||
// Next push constant block will start next to the previous push constant block
|
||||
startOffset += pcInfo.size;
|
||||
}
|
||||
|
||||
stageFlags |= shaderModule->GetShaderStageFlagBits();
|
||||
}
|
||||
|
||||
stageFlags |= shaderModule->GetShaderStageFlagBits();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// After all the sizes of the push constant blocks have been added, record the size in the interface
|
||||
|
@ -132,6 +134,9 @@ namespace SHADE
|
|||
//! Now we take descriptor set info from all shaders and prepare some bindings for the descriptor set
|
||||
for (auto& shaderModule : shaderModules)
|
||||
{
|
||||
if (!shaderModule)
|
||||
continue;
|
||||
|
||||
auto const& descBindingInfo = shaderModule->GetReflectedData().GetDescriptorBindingInfo();
|
||||
auto const& reflectedSets = descBindingInfo.GetReflectedSets();
|
||||
|
||||
|
@ -200,10 +205,12 @@ namespace SHADE
|
|||
newBinding.DescriptorCount = SHVkDescriptorSetLayout::Binding::VARIABLE_DESCRIPTOR_UPPER_BOUND;
|
||||
|
||||
// Set the flags for variable bindings
|
||||
newBinding.flags = vk::DescriptorBindingFlagBits::eVariableDescriptorCount;
|
||||
newBinding.flags = vk::DescriptorBindingFlagBits::eVariableDescriptorCount | vk::DescriptorBindingFlagBits::ePartiallyBound;
|
||||
}
|
||||
else
|
||||
{
|
||||
SHLOG_ERROR("Variable size binding is detected, but the binding is not the last binding of the set and is therefore invalid. ");
|
||||
}
|
||||
}
|
||||
|
||||
setsWithBindings[CURRENT_SET].emplace_back(newBinding);
|
||||
|
@ -326,11 +333,10 @@ namespace SHADE
|
|||
{
|
||||
for (auto& mod : shaderModules)
|
||||
{
|
||||
mod->AddCallback([this]()
|
||||
{
|
||||
RecreateIfNeeded();
|
||||
}
|
||||
);
|
||||
if (mod)
|
||||
{
|
||||
mod->AddCallback([this]() { RecreateIfNeeded(); });
|
||||
}
|
||||
}
|
||||
|
||||
RecreateIfNeeded ();
|
||||
|
|
|
@ -54,7 +54,7 @@ namespace SHADE
|
|||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
void SHRenderGraph::AddResource(std::string resourceName, std::initializer_list<SH_RENDER_GRAPH_RESOURCE_FLAGS> typeFlags, uint32_t w /*= static_cast<uint32_t>(-1)*/, uint32_t h /*= static_cast<uint32_t>(-1)*/, vk::Format format/* = vk::Format::eB8G8R8A8Unorm*/, uint8_t levels /*= 1*/, vk::ImageUsageFlagBits usageFlags/* = {}*/, vk::ImageCreateFlagBits createFlags /*= {}*/)
|
||||
void SHRenderGraph::AddResource(std::string resourceName, std::initializer_list<SH_RENDER_GRAPH_RESOURCE_FLAGS> typeFlags, bool resizeWithWindow, uint32_t w /*= static_cast<uint32_t>(-1)*/, uint32_t h /*= static_cast<uint32_t>(-1)*/, vk::Format format/* = vk::Format::eB8G8R8A8Unorm*/, uint8_t levels /*= 1*/, vk::ImageUsageFlagBits usageFlags/* = {}*/, vk::ImageCreateFlagBits createFlags /*= {}*/)
|
||||
{
|
||||
// If we set to
|
||||
if (w == static_cast<uint32_t>(-1) && h == static_cast<uint32_t>(-1))
|
||||
|
@ -64,7 +64,7 @@ namespace SHADE
|
|||
format = renderGraphStorage->swapchain->GetSurfaceFormatKHR().format;
|
||||
}
|
||||
|
||||
auto resource = renderGraphStorage->resourceHub->Create<SHRenderGraphResource>(renderGraphStorage, resourceName, typeFlags, format, w, h, levels, usageFlags, createFlags);
|
||||
auto resource = renderGraphStorage->resourceHub->Create<SHRenderGraphResource>(renderGraphStorage, resourceName, typeFlags, format, w, h, levels, usageFlags, createFlags, resizeWithWindow);
|
||||
renderGraphStorage->graphResources->try_emplace(resourceName, resource);
|
||||
}
|
||||
|
||||
|
@ -106,6 +106,9 @@ namespace SHADE
|
|||
|
||||
for (auto& affectedNode : affectedNodes)
|
||||
nodes[affectedNode]->CreateFramebuffer();
|
||||
|
||||
renderGraphStorage->graphResources->at(resourceName).Free();
|
||||
renderGraphStorage->graphResources->erase (resourceName);
|
||||
/*
|
||||
* IMPORTANT NOTES
|
||||
*
|
||||
|
@ -166,68 +169,7 @@ namespace SHADE
|
|||
|
||||
for (uint32_t i = 0; auto& node : nodes)
|
||||
{
|
||||
// key is handle ID, value is final layout.
|
||||
std::unordered_map<uint32_t, vk::ImageLayout> resourceAttFinalLayouts;
|
||||
if (node->subpasses.empty())
|
||||
{
|
||||
SHLOG_ERROR("Node does not contain a subpass. Cannot configure attachment descriptions as a result. ");
|
||||
return;
|
||||
}
|
||||
|
||||
// We first want to take all resources track their layout as undefined at the start of the node/renderpass
|
||||
auto const resources = node->GetResources();
|
||||
for (auto& resource : resources)
|
||||
{
|
||||
resource->GetInfoTracker()->TrackLayout(node, {}, vk::ImageLayout::eUndefined);
|
||||
}
|
||||
|
||||
// attempt to get all final layouts for all resources
|
||||
for (auto& subpass : node->subpasses)
|
||||
{
|
||||
for (auto& color : subpass->colorReferences)
|
||||
{
|
||||
// If final renderpass and attachment is a COLOR_PRESENT resource, make resource transition to present after last subpass
|
||||
if (i == nodes.size() - 1 && (node->attResources[color.attachment]->resourceTypeFlags & static_cast<uint32_t>(SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR_PRESENT)))
|
||||
resourceAttFinalLayouts[color.attachment] = vk::ImageLayout::ePresentSrcKHR;
|
||||
else
|
||||
resourceAttFinalLayouts[color.attachment] = color.layout;
|
||||
|
||||
node->attResources[color.attachment]->infoTracker->TrackLayout(node, subpass, color.layout);
|
||||
}
|
||||
|
||||
for (auto& depth : subpass->depthReferences)
|
||||
{
|
||||
resourceAttFinalLayouts[depth.attachment] = depth.layout;
|
||||
node->attResources[depth.attachment]->infoTracker->TrackLayout(node, subpass, depth.layout);
|
||||
}
|
||||
|
||||
for (auto& input : subpass->inputReferences)
|
||||
{
|
||||
resourceAttFinalLayouts[input.attachment] = input.layout;
|
||||
node->attResources[input.attachment]->infoTracker->TrackLayout(node, subpass, input.layout);
|
||||
}
|
||||
}
|
||||
|
||||
for (uint32_t j = 0; j < node->attachmentDescriptions.size(); ++j)
|
||||
{
|
||||
auto& att = node->attachmentDescriptions[j];
|
||||
auto& resource = node->attResources[j];
|
||||
|
||||
// If resource is from another render graph, use the final layout it had when it was last used in that graph. This is initialized in LinkNonOwningResource.
|
||||
// We also want to load the attachment, not "don't care".
|
||||
if (resource->resourceTypeFlags & SHUtilities::ConvertEnum(SH_RENDER_GRAPH_RESOURCE_FLAGS::SHARED) &&
|
||||
renderGraphStorage->nonOwningResourceInitialLayouts.contains(resource.GetId().Raw))
|
||||
{
|
||||
att.initialLayout = renderGraphStorage->nonOwningResourceInitialLayouts.at (resource.GetId().Raw);
|
||||
att.loadOp = vk::AttachmentLoadOp::eLoad;
|
||||
att.stencilLoadOp = vk::AttachmentLoadOp::eLoad;
|
||||
}
|
||||
else
|
||||
att.initialLayout = vk::ImageLayout::eUndefined;
|
||||
|
||||
att.finalLayout = resourceAttFinalLayouts[j];
|
||||
resource->GetInfoTracker()->TrackLayout(node, {}, att.finalLayout);
|
||||
}
|
||||
node->StandaloneConfigureAttDesc(i == nodes.size() - 1);
|
||||
++i;
|
||||
}
|
||||
|
||||
|
@ -333,6 +275,17 @@ namespace SHADE
|
|||
}
|
||||
}
|
||||
|
||||
void SHRenderGraph::ReindexNodes(void) noexcept
|
||||
{
|
||||
nodeIndexing.clear();
|
||||
uint32_t i = 0;
|
||||
for (auto& node : nodes)
|
||||
{
|
||||
nodeIndexing.emplace (node->name, i);
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
|
@ -473,6 +426,65 @@ namespace SHADE
|
|||
return node;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
\brief
|
||||
This function is purely used for dynamic nodes (if such a thing were to
|
||||
exist in our architecture). In other words, don't use this function unless
|
||||
the new node is fully standalone and does not rely or is a prereq of
|
||||
other nodes.
|
||||
|
||||
\param nodeName
|
||||
Name of new node
|
||||
|
||||
\param resourceInstruction
|
||||
Resources for the node
|
||||
|
||||
\param nodeToAddAfter
|
||||
The node to add the new node after.
|
||||
|
||||
\return
|
||||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
Handle<SHRenderGraphNode> SHRenderGraph::AddNodeAfter(std::string nodeName, std::initializer_list<ResourceInstruction> resourceInstruction, std::string nodeToAddAfter) noexcept
|
||||
{
|
||||
if (nodeIndexing.contains(nodeName))
|
||||
{
|
||||
SHLOG_ERROR("Node already exists, cannot add node. ");
|
||||
return {};
|
||||
}
|
||||
|
||||
std::vector<SHAttachmentDescInitParams> descInitParams;
|
||||
for (auto const& instruction : resourceInstruction)
|
||||
{
|
||||
// If the resource that the new node is requesting for exists, allow the graph to reference it
|
||||
if (renderGraphStorage->graphResources->contains(instruction.resourceName))
|
||||
{
|
||||
descInitParams.push_back(
|
||||
{
|
||||
.resourceHdl = renderGraphStorage->graphResources->at(instruction.resourceName),
|
||||
.dontClearOnLoad = instruction.dontClearOnLoad,
|
||||
}
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
SHLOG_ERROR("Resource doesn't exist in graph yet. Cannot create new node.");
|
||||
return{};
|
||||
}
|
||||
}
|
||||
|
||||
// get target node
|
||||
auto targetNode = nodes.begin() + nodeIndexing.at(nodeToAddAfter);
|
||||
|
||||
auto node = nodes.insert(targetNode, renderGraphStorage->resourceHub->Create<SHRenderGraphNode>(nodeName, renderGraphStorage, std::move(descInitParams), std::vector<Handle<SHRenderGraphNode>>()));
|
||||
ReindexNodes ();
|
||||
return *node;
|
||||
|
||||
}
|
||||
|
||||
void SHRenderGraph::AddRenderToSwapchainNode(std::string toSwapchainResource, std::string swapchainResource, std::initializer_list<std::string> predecessorNodes, std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> shaderModules) noexcept
|
||||
{
|
||||
for (auto& node : predecessorNodes)
|
||||
|
@ -532,10 +544,6 @@ namespace SHADE
|
|||
ConfigureSubSystems();
|
||||
}
|
||||
|
||||
void SHRenderGraph::Regenerate(void) noexcept
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
@ -572,10 +580,13 @@ namespace SHADE
|
|||
|
||||
for (auto& node : nodes)
|
||||
{
|
||||
// bind static global data
|
||||
SHGlobalDescriptorSets::BindStaticGlobalData(cmdBuffer, SH_PIPELINE_TYPE::GRAPHICS, descMappings.at(SHPredefinedDescriptorTypes::STATIC_DATA));
|
||||
if (node->renderpass)
|
||||
{
|
||||
// bind static global data
|
||||
SHGlobalDescriptorSets::BindStaticGlobalData(cmdBuffer, SH_PIPELINE_TYPE::GRAPHICS, descMappings.at(SHPredefinedDescriptorTypes::STATIC_DATA));
|
||||
|
||||
node->Execute(cmdBuffer, descPool, frameIndex);
|
||||
node->Execute(cmdBuffer, descPool, frameIndex);
|
||||
}
|
||||
}
|
||||
|
||||
cmdBuffer->EndLabeledSegment();
|
||||
|
@ -605,8 +616,11 @@ namespace SHADE
|
|||
// resize resources
|
||||
for (auto& [name, resource] : *renderGraphStorage->graphResources)
|
||||
{
|
||||
if (!renderGraphStorage->nonOwningResourceInitialLayouts.contains (resource.GetId().Raw))
|
||||
resource->HandleResize(newWidth, newHeight);
|
||||
if (resource->resizeWithWindow)
|
||||
{
|
||||
if (!renderGraphStorage->nonOwningResourceInitialLayouts.contains (resource.GetId().Raw))
|
||||
resource->HandleResize(newWidth, newHeight);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& node : nodes)
|
||||
|
|
|
@ -55,6 +55,7 @@ namespace SHADE
|
|||
void ConfigureRenderpasses (void) noexcept;
|
||||
void ConfigureSubSystems (void) noexcept;
|
||||
void ConfigureFramebuffers (void) noexcept;
|
||||
void ReindexNodes (void) noexcept;
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* PRIVATE MEMBER VARIABLES */
|
||||
|
@ -101,6 +102,7 @@ namespace SHADE
|
|||
(
|
||||
std::string resourceName,
|
||||
std::initializer_list<SH_RENDER_GRAPH_RESOURCE_FLAGS> typeFlags,
|
||||
bool resizeWithWindow = true,
|
||||
uint32_t w = static_cast<uint32_t>(-1),
|
||||
uint32_t h = static_cast<uint32_t>(-1),
|
||||
vk::Format format = vk::Format::eB8G8R8A8Unorm,
|
||||
|
@ -123,6 +125,12 @@ namespace SHADE
|
|||
std::initializer_list<ResourceInstruction> resourceInstruction,
|
||||
std::initializer_list<std::string> predecessorNodes
|
||||
) noexcept;
|
||||
Handle<SHRenderGraphNode> AddNodeAfter
|
||||
(
|
||||
std::string nodeName,
|
||||
std::initializer_list<ResourceInstruction> resourceInstruction,
|
||||
std::string nodeToAddAfter
|
||||
) noexcept;
|
||||
|
||||
void AddRenderToSwapchainNode
|
||||
(
|
||||
|
@ -134,7 +142,6 @@ namespace SHADE
|
|||
) noexcept;
|
||||
|
||||
void Generate (void) noexcept;
|
||||
void Regenerate (void) noexcept;
|
||||
void CheckForNodeComputes (void) noexcept;
|
||||
void Execute (uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool) noexcept;
|
||||
void Begin (uint32_t frameIndex) noexcept;
|
||||
|
@ -165,7 +172,14 @@ namespace SHADE
|
|||
* that manage the resources instead and can facilitate such linking of resources. Either that, or we allow only 1 render graph,
|
||||
* but different matrices (SHRenderer) can be used in different nodes.
|
||||
* - There are also way too many hash maps created for ease of access. This definitely can be cut down.
|
||||
* -
|
||||
* - In hindsight there should have been a distinction between static and dynamic nodes. Static nodes are the ones that are accounted
|
||||
* for in the generation of the render graph. Dynamic nodes begin with nothing at first, but allows for linking of resources and subpasses
|
||||
* while the render graph is executing. The resources here should also be dynamic, which means it should never be used in anywhere else other
|
||||
* than in the node that is using it. This would mean its initial layouts are always specified as undefined and final layouts specified as
|
||||
* whatever the last subpass that is using that resource specifies in the node. Dynamic nodes are meant to render to resources that would later
|
||||
* be used externally, as descriptors for example (the descriptors can be used in a render graph node compute for example). Dynamic nodes run as
|
||||
* if they are the only nodes in the graph, because their resources are not used in other nodes and are thus not predecessors or successors of any
|
||||
* other node.
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
|
@ -32,8 +32,11 @@ namespace SHADE
|
|||
renderpass.Free();
|
||||
}
|
||||
|
||||
renderpass = graphStorage->logicalDevice->CreateRenderpass(attachmentDescriptions, spDescs, spDeps);
|
||||
SET_VK_OBJ_NAME(graphStorage->logicalDevice, vk::ObjectType::eRenderPass, renderpass->GetVkRenderpass(), "[RenderPass] " + name);
|
||||
if (!spDescs.empty())
|
||||
{
|
||||
renderpass = graphStorage->logicalDevice->CreateRenderpass(attachmentDescriptions, spDescs, spDeps);
|
||||
SET_VK_OBJ_NAME(graphStorage->logicalDevice, vk::ObjectType::eRenderPass, renderpass->GetVkRenderpass(), "[RenderPass] " + name);
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
@ -46,91 +49,105 @@ namespace SHADE
|
|||
/***************************************************************************/
|
||||
void SHRenderGraphNode::CreateFramebuffer(void) noexcept
|
||||
{
|
||||
if (!framebuffers.empty())
|
||||
if (renderpass)
|
||||
{
|
||||
for (auto fbo : framebuffers)
|
||||
if (!framebuffers.empty())
|
||||
{
|
||||
if (fbo)
|
||||
fbo.Free();
|
||||
}
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < framebuffers.size(); ++i)
|
||||
{
|
||||
std::vector<Handle<SHVkImageView>> imageViews(attResources.size());
|
||||
uint32_t fbWidth = std::numeric_limits<uint32_t>::max();
|
||||
uint32_t fbHeight = std::numeric_limits<uint32_t>::max();
|
||||
|
||||
for (uint32_t j = 0; j < attResources.size(); ++j)
|
||||
{
|
||||
uint32_t imageViewIndex = (attResources[j]->resourceTypeFlags & static_cast<uint32_t>(SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR_PRESENT)) ? i : 0;
|
||||
imageViews[j] = attResources[j]->imageViews[imageViewIndex];
|
||||
|
||||
// We want the minimum dimensions for the framebuffer because the image attachments referenced cannot have dimensions smaller than the framebuffer's
|
||||
if (fbWidth > attResources[j]->width)
|
||||
fbWidth = attResources[j]->width;
|
||||
if (fbHeight > attResources[j]->height)
|
||||
fbHeight = attResources[j]->height;
|
||||
for (auto fbo : framebuffers)
|
||||
{
|
||||
if (fbo)
|
||||
fbo.Free();
|
||||
}
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < framebuffers.size(); ++i)
|
||||
{
|
||||
std::vector<Handle<SHVkImageView>> imageViews(attResources.size());
|
||||
uint32_t fbWidth = std::numeric_limits<uint32_t>::max();
|
||||
uint32_t fbHeight = std::numeric_limits<uint32_t>::max();
|
||||
|
||||
framebuffers[i] = graphStorage->logicalDevice->CreateFramebuffer(renderpass, imageViews, fbWidth, fbHeight);
|
||||
SET_VK_OBJ_NAME(graphStorage->logicalDevice, vk::ObjectType::eFramebuffer, framebuffers[i]->GetVkFramebuffer(), "[Framebuffer] " + name + std::to_string(i));
|
||||
for (uint32_t j = 0; j < attResources.size(); ++j)
|
||||
{
|
||||
uint32_t imageViewIndex = (attResources[j]->resourceTypeFlags & static_cast<uint32_t>(SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR_PRESENT)) ? i : 0;
|
||||
imageViews[j] = attResources[j]->imageViews[imageViewIndex];
|
||||
|
||||
// We want the minimum dimensions for the framebuffer because the image attachments referenced cannot have dimensions smaller than the framebuffer's
|
||||
if (fbWidth > attResources[j]->width)
|
||||
fbWidth = attResources[j]->width;
|
||||
if (fbHeight > attResources[j]->height)
|
||||
fbHeight = attResources[j]->height;
|
||||
}
|
||||
|
||||
|
||||
framebuffers[i] = graphStorage->logicalDevice->CreateFramebuffer(renderpass, imageViews, fbWidth, fbHeight);
|
||||
SET_VK_OBJ_NAME(graphStorage->logicalDevice, vk::ObjectType::eFramebuffer, framebuffers[i]->GetVkFramebuffer(), "[Framebuffer] " + name + std::to_string(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SHRenderGraphNode::HandleResize(void) noexcept
|
||||
{
|
||||
renderpass->HandleResize();
|
||||
|
||||
for (uint32_t i = 0; i < framebuffers.size(); ++i)
|
||||
if (renderpass)
|
||||
{
|
||||
std::vector<Handle<SHVkImageView>> imageViews(attResources.size());
|
||||
uint32_t fbWidth = std::numeric_limits<uint32_t>::max();
|
||||
uint32_t fbHeight = std::numeric_limits<uint32_t>::max();
|
||||
renderpass->HandleResize();
|
||||
|
||||
for (uint32_t j = 0; j < attResources.size(); ++j)
|
||||
for (uint32_t i = 0; i < framebuffers.size(); ++i)
|
||||
{
|
||||
uint32_t imageViewIndex = (attResources[j]->resourceTypeFlags & static_cast<uint32_t>(SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR_PRESENT)) ? i : 0;
|
||||
imageViews[j] = attResources[j]->imageViews[imageViewIndex];
|
||||
std::vector<Handle<SHVkImageView>> imageViews(attResources.size());
|
||||
uint32_t fbWidth = std::numeric_limits<uint32_t>::max();
|
||||
uint32_t fbHeight = std::numeric_limits<uint32_t>::max();
|
||||
|
||||
// We want the minimum dimensions for the framebuffer because the image attachments referenced cannot have dimensions smaller than the framebuffer's
|
||||
if (fbWidth > attResources[j]->width)
|
||||
fbWidth = attResources[j]->width;
|
||||
if (fbHeight > attResources[j]->height)
|
||||
fbHeight = attResources[j]->height;
|
||||
for (uint32_t j = 0; j < attResources.size(); ++j)
|
||||
{
|
||||
uint32_t imageViewIndex = (attResources[j]->resourceTypeFlags & static_cast<uint32_t>(SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR_PRESENT)) ? i : 0;
|
||||
imageViews[j] = attResources[j]->imageViews[imageViewIndex];
|
||||
|
||||
// We want the minimum dimensions for the framebuffer because the image attachments referenced cannot have dimensions smaller than the framebuffer's
|
||||
if (fbWidth > attResources[j]->width)
|
||||
fbWidth = attResources[j]->width;
|
||||
if (fbHeight > attResources[j]->height)
|
||||
fbHeight = attResources[j]->height;
|
||||
}
|
||||
|
||||
framebuffers[i]->HandleResize(renderpass, imageViews, fbWidth, fbHeight);
|
||||
}
|
||||
|
||||
framebuffers[i]->HandleResize(renderpass, imageViews, fbWidth, fbHeight);
|
||||
}
|
||||
for (auto& subpass : subpasses)
|
||||
{
|
||||
subpass->HandleResize();
|
||||
}
|
||||
|
||||
for (auto& subpass : subpasses)
|
||||
{
|
||||
subpass->HandleResize();
|
||||
}
|
||||
|
||||
for (auto& nodeCompute : nodeComputes)
|
||||
{
|
||||
nodeCompute->HandleResize();
|
||||
for (auto& nodeCompute : nodeComputes)
|
||||
{
|
||||
nodeCompute->HandleResize();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SHRenderGraphNode::ConfigureSubpasses(void) noexcept
|
||||
{
|
||||
if (subpasses.empty())
|
||||
return;
|
||||
|
||||
uint32_t numValidSubpasses = std::count_if(subpasses.begin(), subpasses.end(), [](Handle<SHSubpass> subpass) {return !subpass->HasNoAttachments();});
|
||||
|
||||
// Create subpass description and dependencies based on number of subpasses
|
||||
spDescs.resize(subpasses.size());
|
||||
spDeps.resize(subpasses.size());
|
||||
spDescs.resize(numValidSubpasses);
|
||||
spDeps.resize(numValidSubpasses);
|
||||
|
||||
// Now we want to loop through all attachments in all subpasses in the node and query
|
||||
// the resources being used. For each resource we want to query the type and record it
|
||||
// in bit fields (1 bit for each subpass).
|
||||
uint32_t colorRead = 0, colorWrite = 0, depthRead = 0, depthWrite = 0, inputDependencies = 0;
|
||||
|
||||
uint32_t i = 0;
|
||||
|
||||
// For all subpasses (see above description about bit field for this).
|
||||
for (auto& subpass : subpasses)
|
||||
for (uint32_t i = 0; auto& subpass : subpasses)
|
||||
{
|
||||
// skip if subpass is not valid
|
||||
if (subpass->HasNoAttachments())
|
||||
continue;
|
||||
|
||||
// Configure subpass description
|
||||
auto& desc = spDescs[i];
|
||||
desc.pColorAttachments = subpass->colorReferences.data();
|
||||
|
@ -186,8 +203,11 @@ namespace SHADE
|
|||
|
||||
// Loop through all subpasses again but this time we use the bit field to initialize
|
||||
// the dependencies.
|
||||
for (i = 0; i < subpasses.size(); ++i)
|
||||
for (uint32_t i = 0; auto & subpass : subpasses)
|
||||
{
|
||||
if (subpass->HasNoAttachments())
|
||||
continue;
|
||||
|
||||
vk::PipelineStageFlags srcStage;
|
||||
vk::PipelineStageFlags dstStage;
|
||||
vk::AccessFlags srcAccess;
|
||||
|
@ -245,6 +265,8 @@ namespace SHADE
|
|||
|
||||
// initialize input descriptors
|
||||
subpasses[i]->CreateInputDescriptors();
|
||||
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -343,6 +365,7 @@ namespace SHADE
|
|||
, spDeps{ std::move(rhs.spDeps) }
|
||||
, nodeComputes{ std::move(rhs.nodeComputes) }
|
||||
, name { std::move(rhs.name) }
|
||||
, ISelfHandle<SHRenderGraphNode>{std::move(rhs)}
|
||||
|
||||
{
|
||||
rhs.renderpass = {};
|
||||
|
@ -419,7 +442,7 @@ namespace SHADE
|
|||
return subpass;
|
||||
}
|
||||
|
||||
Handle<SHRenderGraphNodeCompute> SHRenderGraphNode::AddNodeCompute(std::string nodeName, Handle<SHVkShaderModule> computeShaderModule, std::initializer_list<std::string> resources, std::unordered_set<BindingAndSetHash>&& dynamicBufferBindings, float numWorkGroupScale/* = 1.0f*/) noexcept
|
||||
Handle<SHRenderGraphNodeCompute> SHRenderGraphNode::AddNodeCompute(std::string nodeName, Handle<SHVkShaderModule> computeShaderModule, std::initializer_list<std::string> resources, std::unordered_set<BindingAndSetHash>&& dynamicBufferBindings, uint32_t variableDescCount/* = 0*/, float numWorkGroupScale/* = 1.0f*/) noexcept
|
||||
{
|
||||
// Look for the required resources in the graph
|
||||
std::vector<Handle<SHRenderGraphResource>> nodeComputeResources{};
|
||||
|
@ -435,7 +458,7 @@ namespace SHADE
|
|||
std::vector<Handle<SHRenderGraphResource>> temp (nodeComputeResources);
|
||||
|
||||
// Create the subpass compute with the resources
|
||||
auto nodeCompute = graphStorage->resourceHub->Create<SHRenderGraphNodeCompute>(std::move(nodeName), graphStorage, computeShaderModule, std::move(nodeComputeResources), std::move (dynamicBufferBindings), nodeComputes.empty());
|
||||
auto nodeCompute = graphStorage->resourceHub->Create<SHRenderGraphNodeCompute>(std::move(nodeName), graphStorage, computeShaderModule, std::move(nodeComputeResources), std::move (dynamicBufferBindings), nodeComputes.empty(), variableDescCount);
|
||||
nodeComputes.push_back(nodeCompute);
|
||||
|
||||
for (auto& resource : temp)
|
||||
|
@ -483,6 +506,68 @@ namespace SHADE
|
|||
}
|
||||
}
|
||||
|
||||
void SHRenderGraphNode::StandaloneConfigureAttDesc(bool isLastNode) noexcept
|
||||
{
|
||||
// key is handle ID, value is final layout.
|
||||
std::unordered_map<uint32_t, vk::ImageLayout> resourceAttFinalLayouts;
|
||||
if (!subpasses.empty())
|
||||
{
|
||||
// We first want to take all resources track their layout as undefined at the start of the node/renderpass
|
||||
for (auto& resource : attResources)
|
||||
{
|
||||
resource->GetInfoTracker()->TrackLayout(GetHandle(), {}, vk::ImageLayout::eUndefined);
|
||||
}
|
||||
|
||||
// attempt to get all final layouts for all resources
|
||||
for (auto& subpass : subpasses)
|
||||
{
|
||||
for (auto& color : subpass->colorReferences)
|
||||
{
|
||||
// If final renderpass and attachment is a COLOR_PRESENT resource, make resource transition to present after last subpass
|
||||
if (isLastNode && (attResources[color.attachment]->resourceTypeFlags & static_cast<uint32_t>(SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR_PRESENT)))
|
||||
resourceAttFinalLayouts[color.attachment] = vk::ImageLayout::ePresentSrcKHR;
|
||||
else
|
||||
resourceAttFinalLayouts[color.attachment] = color.layout;
|
||||
|
||||
attResources[color.attachment]->infoTracker->TrackLayout(GetHandle(), subpass, color.layout);
|
||||
}
|
||||
|
||||
for (auto& depth : subpass->depthReferences)
|
||||
{
|
||||
resourceAttFinalLayouts[depth.attachment] = depth.layout;
|
||||
attResources[depth.attachment]->infoTracker->TrackLayout(GetHandle(), subpass, depth.layout);
|
||||
}
|
||||
|
||||
for (auto& input : subpass->inputReferences)
|
||||
{
|
||||
resourceAttFinalLayouts[input.attachment] = input.layout;
|
||||
attResources[input.attachment]->infoTracker->TrackLayout(GetHandle(), subpass, input.layout);
|
||||
}
|
||||
}
|
||||
|
||||
for (uint32_t j = 0; j < attachmentDescriptions.size(); ++j)
|
||||
{
|
||||
auto& att = attachmentDescriptions[j];
|
||||
auto& resource = attResources[j];
|
||||
|
||||
// If resource is from another render graph, use the final layout it had when it was last used in that graph. This is initialized in LinkNonOwningResource.
|
||||
// We also want to load the attachment, not "don't care".
|
||||
if (resource->resourceTypeFlags & SHUtilities::ConvertEnum(SH_RENDER_GRAPH_RESOURCE_FLAGS::SHARED) &&
|
||||
graphStorage->nonOwningResourceInitialLayouts.contains(resource.GetId().Raw))
|
||||
{
|
||||
att.initialLayout = graphStorage->nonOwningResourceInitialLayouts.at(resource.GetId().Raw);
|
||||
att.loadOp = vk::AttachmentLoadOp::eLoad;
|
||||
att.stencilLoadOp = vk::AttachmentLoadOp::eLoad;
|
||||
}
|
||||
else
|
||||
att.initialLayout = vk::ImageLayout::eUndefined;
|
||||
|
||||
att.finalLayout = resourceAttFinalLayouts[j];
|
||||
resource->GetInfoTracker()->TrackLayout(GetHandle(), {}, att.finalLayout);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
|
@ -509,14 +594,14 @@ namespace SHADE
|
|||
// remove attachment reference
|
||||
attachmentDescriptions.erase (attachmentDescriptions.begin() + index);
|
||||
|
||||
// erase from mapping as well
|
||||
resourceAttachmentMapping->erase(resourceHandleID);
|
||||
|
||||
// Remove footprint of attachment from all subpasses as well
|
||||
for (auto it = subpasses.begin(); it != subpasses.end(); ++it)
|
||||
{
|
||||
// attempt to detach resource from subpass
|
||||
(*it)->DetachResource(resourceName, index);
|
||||
|
||||
// If the subpass ends up having no attachments after, erase it from the node
|
||||
if ((*it)->HasNoAttachments())
|
||||
// If the subpass uses the resource, just remove the subpass since the subpass will be invalid
|
||||
if ((*it)->UsesResource(index))
|
||||
{
|
||||
// erase from indexing
|
||||
subpassIndexing.erase((*it)->GetName());
|
||||
|
@ -530,6 +615,24 @@ namespace SHADE
|
|||
for (uint32_t i = 0; i < subpasses.size(); ++i)
|
||||
subpasses[i]->SetIndex(i);
|
||||
|
||||
// remove node computes using the resource
|
||||
for (auto it = nodeComputes.begin(); it != nodeComputes.end(); ++it)
|
||||
{
|
||||
if ((*it)->UsesResource(resourceHandleID))
|
||||
{
|
||||
it = nodeComputes.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
// recompute the barriers for the other computes
|
||||
for (auto it = nodeComputes.begin(); it != nodeComputes.end(); ++it)
|
||||
{
|
||||
if (it == nodeComputes.begin())
|
||||
(*it)->SetFollowingEndRenderpass(true);
|
||||
|
||||
(*it)->InitializeBarriers();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -537,37 +640,40 @@ namespace SHADE
|
|||
|
||||
void SHRenderGraphNode::Execute(Handle<SHVkCommandBuffer> commandBuffer, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) noexcept
|
||||
{
|
||||
uint32_t framebufferIndex = (framebuffers.size() > 1) ? frameIndex : 0;
|
||||
commandBuffer->BeginRenderpass(renderpass, framebuffers[framebufferIndex]);
|
||||
|
||||
for (uint32_t i = 0; i < subpasses.size(); ++i)
|
||||
if (renderpass)
|
||||
{
|
||||
subpasses[i]->Execute(commandBuffer, descPool, frameIndex);
|
||||
uint32_t framebufferIndex = (framebuffers.size() > 1) ? frameIndex : 0;
|
||||
commandBuffer->BeginRenderpass(renderpass, framebuffers[framebufferIndex]);
|
||||
|
||||
// Go to next subpass if not last subpass
|
||||
if (i != static_cast<uint32_t>(subpasses.size()) - 1u)
|
||||
commandBuffer->NextSubpass();
|
||||
for (uint32_t i = 0; i < subpasses.size(); ++i)
|
||||
{
|
||||
subpasses[i]->Execute(commandBuffer, descPool, frameIndex);
|
||||
|
||||
// Go to next subpass if not last subpass
|
||||
if (i != static_cast<uint32_t>(subpasses.size()) - 1u && !subpasses[i]->HasNoAttachments())
|
||||
commandBuffer->NextSubpass();
|
||||
}
|
||||
|
||||
commandBuffer->EndRenderpass();
|
||||
|
||||
auto const& descMappings = SHGraphicsPredefinedData::GetMappings(SHGraphicsPredefinedData::SystemType::RENDER_GRAPH_NODE_COMPUTE);
|
||||
|
||||
// We bind these 2 descriptor sets here because they apply to all node computes
|
||||
if (!nodeComputes.empty())
|
||||
{
|
||||
commandBuffer->ForceSetPipelineLayout(SHGraphicsPredefinedData::GetSystemData(SHGraphicsPredefinedData::SystemType::RENDER_GRAPH_NODE_COMPUTE).dummyPipelineLayout, SH_PIPELINE_TYPE::COMPUTE);
|
||||
|
||||
// bind static global data
|
||||
SHGlobalDescriptorSets::BindStaticGlobalData(commandBuffer, SH_PIPELINE_TYPE::COMPUTE, descMappings.at(SHPredefinedDescriptorTypes::STATIC_DATA));
|
||||
|
||||
// bind lighting data
|
||||
SHGlobalDescriptorSets::BindLightingData(commandBuffer, SH_PIPELINE_TYPE::COMPUTE, descMappings.at(SHPredefinedDescriptorTypes::LIGHTS), frameIndex);
|
||||
}
|
||||
|
||||
// Execute all subpass computes
|
||||
for (auto& sbCompute : nodeComputes)
|
||||
sbCompute->Execute(commandBuffer, frameIndex);
|
||||
}
|
||||
|
||||
commandBuffer->EndRenderpass();
|
||||
|
||||
auto const& descMappings = SHGraphicsPredefinedData::GetMappings(SHGraphicsPredefinedData::SystemType::RENDER_GRAPH_NODE_COMPUTE);
|
||||
|
||||
// We bind these 2 descriptor sets here because they apply to all node computes
|
||||
if (!nodeComputes.empty())
|
||||
{
|
||||
commandBuffer->ForceSetPipelineLayout(SHGraphicsPredefinedData::GetSystemData(SHGraphicsPredefinedData::SystemType::RENDER_GRAPH_NODE_COMPUTE).dummyPipelineLayout, SH_PIPELINE_TYPE::COMPUTE);
|
||||
|
||||
// bind static global data
|
||||
SHGlobalDescriptorSets::BindStaticGlobalData(commandBuffer, SH_PIPELINE_TYPE::COMPUTE, descMappings.at(SHPredefinedDescriptorTypes::STATIC_DATA));
|
||||
|
||||
// bind lighting data
|
||||
SHGlobalDescriptorSets::BindLightingData(commandBuffer, SH_PIPELINE_TYPE::COMPUTE, descMappings.at(SHPredefinedDescriptorTypes::LIGHTS), frameIndex);
|
||||
}
|
||||
|
||||
// Execute all subpass computes
|
||||
for (auto& sbCompute : nodeComputes)
|
||||
sbCompute->Execute(commandBuffer, frameIndex);
|
||||
}
|
||||
|
||||
Handle<SHVkPipeline> SHRenderGraphNode::GetOrCreatePipeline(std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair, Handle<SHSubpass> subpass) noexcept
|
||||
|
@ -599,6 +705,77 @@ namespace SHADE
|
|||
batcher.FinaliseBatches(graphStorage->logicalDevice, descPool, frameIndex);
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
\brief
|
||||
This function simply appends to the container of VkAttachmentDescription
|
||||
and attResources. It will assume the resource is used standalone in the
|
||||
node and will not account for its usage in other nodes. As such its
|
||||
initialLayout will always be UNDEFINED and its finalLayout will be
|
||||
whatever is calculated if the node is regenerated using
|
||||
StandaloneRegnerate. This function also does not affect the render graph
|
||||
while its running since the 2 containers above have already been copied
|
||||
to the GPU.
|
||||
|
||||
\param resourceName
|
||||
The name of the resource for getting the resource.
|
||||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
void SHRenderGraphNode::RuntimeLinkResource(std::string resourceName) noexcept
|
||||
{
|
||||
// Get new resource
|
||||
Handle<SHRenderGraphResource> newResource = graphStorage->graphResources->at(resourceName);
|
||||
|
||||
// append new resource to container
|
||||
attResources.push_back(newResource);
|
||||
|
||||
attachmentDescriptions.push_back(vk::AttachmentDescription
|
||||
{
|
||||
.format = newResource->GetResourceFormat(),
|
||||
.samples = vk::SampleCountFlagBits::e1,
|
||||
.loadOp = vk::AttachmentLoadOp::eClear,
|
||||
.storeOp = vk::AttachmentStoreOp::eStore,
|
||||
.stencilLoadOp = vk::AttachmentLoadOp::eClear,
|
||||
.stencilStoreOp = vk::AttachmentStoreOp::eStore,
|
||||
});
|
||||
|
||||
resourceAttachmentMapping->try_emplace(newResource.GetId().Raw, attachmentDescriptions.size() - 1);
|
||||
}
|
||||
|
||||
Handle<SHSubpass> SHRenderGraphNode::RuntimeAddSubpass(std::string subpassName, Handle<SHViewport> viewport, Handle<SHRenderer> renderer) noexcept
|
||||
{
|
||||
return AddSubpass(std::move (subpassName), viewport, renderer);
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
\brief
|
||||
USE WITH CAUTION because the function does not reevaluate resource
|
||||
layouts in attachment descriptions. All resources here will start at
|
||||
UNDEFINED and end at whatever the last subpass using the attachment
|
||||
specifies. It will also not support render graph node computes given its
|
||||
complexity if it has to be accounted for.
|
||||
|
||||
IN SHORT, IT GENERATES A RENDERPASS AS IF ITS THE ONLY NODE
|
||||
IN THE RENDER GRAPH. SEE NOTES IN SHRenderGraph.h
|
||||
|
||||
This function is mainly meant for nodes that are dynamic (in hindsight,
|
||||
there really should have been a distinction between static and dynamic
|
||||
nodes).
|
||||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
void SHRenderGraphNode::RuntimeStandaloneRegenerate(void) noexcept
|
||||
{
|
||||
StandaloneConfigureAttDesc(false);
|
||||
ConfigureSubpasses();
|
||||
CreateRenderpass();
|
||||
CreateFramebuffer();
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
|
@ -633,4 +810,15 @@ namespace SHADE
|
|||
return attResources;
|
||||
}
|
||||
|
||||
Handle<SHRenderGraphNodeCompute> SHRenderGraphNode::GetNodeCompute(std::string nodeComputeName) const noexcept
|
||||
{
|
||||
for (auto nc : nodeComputes)
|
||||
{
|
||||
if (nc->name == nodeComputeName)
|
||||
return nc;
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
}
|
|
@ -93,6 +93,9 @@ namespace SHADE
|
|||
void CreateFramebuffer(void) noexcept;
|
||||
void HandleResize (void) noexcept;
|
||||
void ConfigureSubpasses (void) noexcept;
|
||||
bool DetachResource(std::string const& resourceName, uint64_t resourceHandleID) noexcept;
|
||||
void AddDummySubpassIfNeeded(void) noexcept;
|
||||
void StandaloneConfigureAttDesc (bool isLastNode) noexcept;
|
||||
|
||||
public:
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
@ -105,15 +108,17 @@ namespace SHADE
|
|||
/*-----------------------------------------------------------------------*/
|
||||
/* PUBLIC MEMBER FUNCTIONS */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
Handle<SHSubpass> AddSubpass(std::string subpassName, Handle<SHViewport> viewport, Handle<SHRenderer> renderer) noexcept;
|
||||
Handle<SHRenderGraphNodeCompute> AddNodeCompute(std::string nodeName, Handle<SHVkShaderModule> computeShaderModule, std::initializer_list<std::string> resources, std::unordered_set<BindingAndSetHash>&& dynamicBufferBindings = {}, float numWorkGroupScale = 1.0f) noexcept;
|
||||
void AddDummySubpassIfNeeded (void) noexcept;
|
||||
bool DetachResource (std::string const& resourceName, uint64_t resourceHandleID) noexcept;
|
||||
Handle<SHSubpass> AddSubpass(std::string subpassName, Handle<SHViewport> viewport, Handle<SHRenderer> renderer) noexcept;
|
||||
Handle<SHRenderGraphNodeCompute> AddNodeCompute(std::string nodeName, Handle<SHVkShaderModule> computeShaderModule, std::initializer_list<std::string> resources, std::unordered_set<BindingAndSetHash>&& dynamicBufferBindings = {}, uint32_t variableDescCount = 0, float numWorkGroupScale = 1.0f) noexcept;
|
||||
|
||||
void Execute(Handle<SHVkCommandBuffer> commandBuffer, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) noexcept;
|
||||
Handle<SHVkPipeline> GetOrCreatePipeline(std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair, Handle<SHSubpass> subpass) noexcept;
|
||||
void FinaliseBatch(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool);
|
||||
|
||||
// TODO: RemoveSubpass()
|
||||
void Execute(Handle<SHVkCommandBuffer> commandBuffer, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) noexcept;
|
||||
Handle<SHVkPipeline> GetOrCreatePipeline(std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair, Handle<SHSubpass> subpass) noexcept;
|
||||
void FinaliseBatch(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool);
|
||||
// Runtime functions that don't affect the renderpass
|
||||
void RuntimeLinkResource(std::string resourceName) noexcept;
|
||||
Handle<SHSubpass> RuntimeAddSubpass(std::string subpassName, Handle<SHViewport> viewport, Handle<SHRenderer> renderer) noexcept;
|
||||
void RuntimeStandaloneRegenerate (void) noexcept;
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* SETTERS AND GETTERS */
|
||||
|
@ -122,6 +127,7 @@ namespace SHADE
|
|||
Handle<SHSubpass> GetSubpass(std::string_view subpassName) const noexcept;
|
||||
Handle<SHRenderGraphResource> GetResource (uint32_t resourceIndex) const noexcept;
|
||||
std::vector<Handle<SHRenderGraphResource>> const& GetResources (void) const noexcept;
|
||||
Handle<SHRenderGraphNodeCompute> GetNodeCompute (std::string nodeComputeName) const noexcept;
|
||||
friend class SHRenderGraph;
|
||||
};
|
||||
|
||||
|
|
|
@ -14,7 +14,56 @@
|
|||
|
||||
namespace SHADE
|
||||
{
|
||||
SHRenderGraphNodeCompute::SHRenderGraphNodeCompute(std::string nodeName, Handle<SHRenderGraphStorage> graphStorage, Handle<SHVkShaderModule> computeShaderModule, std::vector<Handle<SHRenderGraphResource>>&& subpassComputeResources, std::unordered_set<BindingAndSetHash>&& dynamicBufferBindings, bool followingEndRP, float inNumWorkGroupScale/* = 1.0f*/) noexcept
|
||||
|
||||
bool SHRenderGraphNodeCompute::UsesResource(uint64_t resourceHandleID) const noexcept
|
||||
{
|
||||
for (auto& resource : resources)
|
||||
{
|
||||
if (resource.GetId().Raw == resourceHandleID)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void SHRenderGraphNodeCompute::InitializeBarriers(void) noexcept
|
||||
{
|
||||
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<uint32_t>(SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR_PRESENT)) ? i : 0)->GetVkImage(),
|
||||
.subresourceRange = vk::ImageSubresourceRange
|
||||
{
|
||||
.aspectMask = resource->imageAspectFlags,
|
||||
.baseMipLevel = 0,
|
||||
.levelCount = resource->mipLevels,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = 1,
|
||||
}
|
||||
});
|
||||
}
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
void SHRenderGraphNodeCompute::SetFollowingEndRenderpass(uint32_t flag) noexcept
|
||||
{
|
||||
followingEndRenderpass = flag;
|
||||
}
|
||||
|
||||
|
||||
SHRenderGraphNodeCompute::SHRenderGraphNodeCompute(std::string nodeName, Handle<SHRenderGraphStorage> graphStorage, Handle<SHVkShaderModule> computeShaderModule, std::vector<Handle<SHRenderGraphResource>>&& subpassComputeResources, std::unordered_set<BindingAndSetHash>&& dynamicBufferBindings, bool followingEndRP, uint32_t variableDescCount, float inNumWorkGroupScale/* = 1.0f*/) noexcept
|
||||
: computePipeline{}
|
||||
, pipelineLayout{}
|
||||
, resources{}
|
||||
|
@ -68,10 +117,12 @@ namespace SHADE
|
|||
// check if all layouts are there
|
||||
if (layouts.size() == descMappings.at(SHPredefinedDescriptorTypes::RENDER_GRAPH_NODE_COMPUTE_RESOURCE) + 1)
|
||||
{
|
||||
Handle<SHVkDescriptorSetLayout> computeResourceLayout = {};
|
||||
computeResourceLayout = layouts[descMappings.at(SHPredefinedDescriptorTypes::RENDER_GRAPH_NODE_COMPUTE_RESOURCE)];
|
||||
|
||||
// create compute resources
|
||||
computeResource = graphStorage->resourceHub->Create<ComputeResource>();
|
||||
auto computeResourceLayout = layouts[descMappings.at(SHPredefinedDescriptorTypes::RENDER_GRAPH_NODE_COMPUTE_RESOURCE)];
|
||||
computeResource->descSet = graphStorage->descriptorPool->Allocate({ computeResourceLayout }, { 1 });
|
||||
computeResource->descSet = graphStorage->descriptorPool->Allocate({ computeResourceLayout }, {variableDescCount});
|
||||
#ifdef _DEBUG
|
||||
for (auto set : computeResource->descSet->GetVkHandle())
|
||||
SET_VK_OBJ_NAME(graphStorage->logicalDevice, vk::ObjectType::eDescriptorSet, set, "[Descriptor Set] " + name + " Resources");
|
||||
|
@ -91,6 +142,11 @@ namespace SHADE
|
|||
|
||||
void SHRenderGraphNodeCompute::Execute(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept
|
||||
{
|
||||
for (auto& fn : preComputeFunctions)
|
||||
{
|
||||
fn (cmdBuffer, frameIndex);
|
||||
}
|
||||
|
||||
// bind the compute pipeline
|
||||
cmdBuffer->BindPipeline(computePipeline);
|
||||
|
||||
|
@ -157,35 +213,7 @@ 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<uint32_t>(SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR_PRESENT)) ? i : 0)->GetVkImage(),
|
||||
.subresourceRange = vk::ImageSubresourceRange
|
||||
{
|
||||
.aspectMask = resource->imageAspectFlags,
|
||||
.baseMipLevel = 0,
|
||||
.levelCount = resource->mipLevels,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = 1,
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
++i;
|
||||
}
|
||||
InitializeBarriers();
|
||||
}
|
||||
|
||||
void SHRenderGraphNodeCompute::SetDynamicOffsets(std::span<uint32_t> perFrameSizes) noexcept
|
||||
|
@ -219,4 +247,17 @@ namespace SHADE
|
|||
|
||||
}
|
||||
|
||||
void SHRenderGraphNodeCompute::ModifyWriteDescImageComputeResource(uint32_t binding, SHVkDescriptorSetGroup::viewSamplerLayout const& viewSamplerLayout, uint32_t descArrayIndex) noexcept
|
||||
{
|
||||
static constexpr uint32_t COMPUTE_RESOURCE_SET_INDEX = 0;
|
||||
computeResource->descSet->ModifyWriteDescImage(COMPUTE_RESOURCE_SET_INDEX, binding, viewSamplerLayout, descArrayIndex);
|
||||
computeResource->descSet->UpdateDescriptorSetImage(COMPUTE_RESOURCE_SET_INDEX, binding, descArrayIndex);
|
||||
|
||||
}
|
||||
|
||||
void SHRenderGraphNodeCompute::AddPreComputeFunction(PreComputeFunction const& fn) noexcept
|
||||
{
|
||||
preComputeFunctions.push_back(fn);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -25,6 +25,10 @@ namespace SHADE
|
|||
|
||||
class SHRenderGraphNodeCompute
|
||||
{
|
||||
public:
|
||||
using PreComputeFunction = std::function<void(Handle<SHVkCommandBuffer>, uint32_t)>;
|
||||
|
||||
|
||||
private:
|
||||
// Binding of set SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_NODE_COMPUTE_RESOURCE
|
||||
struct ComputeResource
|
||||
|
@ -73,8 +77,23 @@ namespace SHADE
|
|||
//! Name of this node
|
||||
std::string name;
|
||||
|
||||
std::vector<PreComputeFunction> preComputeFunctions;
|
||||
|
||||
|
||||
private:
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* PRIVATE MEMBER FUNCTIONS */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
bool UsesResource (uint64_t resourceHandleID) const noexcept;
|
||||
void InitializeBarriers (void) noexcept;
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* PRIVATE SETTERS AND GETTERS */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
void SetFollowingEndRenderpass (uint32_t flag) noexcept;
|
||||
|
||||
public:
|
||||
SHRenderGraphNodeCompute(std::string nodeName, Handle<SHRenderGraphStorage> graphStorage, Handle<SHVkShaderModule> computeShaderModule, std::vector<Handle<SHRenderGraphResource>>&& subpassComputeResources, std::unordered_set<BindingAndSetHash>&& dynamicBufferBindings, bool followingEndRP, float inNumWorkGroupScale = 1.0f) noexcept;
|
||||
SHRenderGraphNodeCompute(std::string nodeName, Handle<SHRenderGraphStorage> graphStorage, Handle<SHVkShaderModule> computeShaderModule, std::vector<Handle<SHRenderGraphResource>>&& subpassComputeResources, std::unordered_set<BindingAndSetHash>&& dynamicBufferBindings, bool followingEndRP, uint32_t variableDescCount, float inNumWorkGroupScale = 1.0f) noexcept;
|
||||
|
||||
void Execute (Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept;
|
||||
void HandleResize (void) noexcept;
|
||||
|
@ -84,7 +103,9 @@ namespace SHADE
|
|||
|
||||
void ModifyWriteDescBufferComputeResource (uint32_t binding, std::span<Handle<SHVkBuffer>> const& buffers, uint32_t offset, uint32_t range) noexcept;
|
||||
void ModifyWriteDescImageComputeResource(uint32_t binding, std::span<SHVkDescriptorSetGroup::viewSamplerLayout> const& viewSamplerLayouts) noexcept;
|
||||
void ModifyWriteDescImageComputeResource(uint32_t binding, SHVkDescriptorSetGroup::viewSamplerLayout const& viewSamplerLayout, uint32_t descArrayIndex) noexcept;
|
||||
|
||||
void AddPreComputeFunction (PreComputeFunction const& fn) noexcept;
|
||||
|
||||
friend class SHRenderGraph;
|
||||
friend class SHRenderGraphNode;
|
||||
|
|
|
@ -78,7 +78,7 @@ namespace SHADE
|
|||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
SHRenderGraphResource::SHRenderGraphResource(Handle<SHRenderGraphStorage> renderGraphStorage, std::string const& name, std::initializer_list<SH_RENDER_GRAPH_RESOURCE_FLAGS> typeFlags, vk::Format format, uint32_t w, uint32_t h, uint8_t levels, vk::ImageUsageFlagBits usageFlags, vk::ImageCreateFlagBits createFlags) noexcept
|
||||
SHRenderGraphResource::SHRenderGraphResource(Handle<SHRenderGraphStorage> renderGraphStorage, std::string const& name, std::initializer_list<SH_RENDER_GRAPH_RESOURCE_FLAGS> typeFlags, vk::Format format, uint32_t w, uint32_t h, uint8_t levels, vk::ImageUsageFlagBits usageFlags, vk::ImageCreateFlagBits createFlags, bool inResizeWithWindow) noexcept
|
||||
: graphStorage{renderGraphStorage}
|
||||
, resourceTypeFlags{ }
|
||||
, resourceFormat{ format }
|
||||
|
@ -88,6 +88,7 @@ namespace SHADE
|
|||
, height{ h }
|
||||
, mipLevels{ levels }
|
||||
, resourceName{ name }
|
||||
, resizeWithWindow { inResizeWithWindow }
|
||||
{
|
||||
// If the resource type is an arbitrary image and not swapchain image
|
||||
if (typeFlags.size() == 1 && *typeFlags.begin() == SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR_PRESENT)
|
||||
|
@ -210,6 +211,7 @@ namespace SHADE
|
|||
, imageAspectFlags{ rhs.imageAspectFlags }
|
||||
, graphStorage{rhs.graphStorage}
|
||||
, infoTracker {std::move (rhs.infoTracker)}
|
||||
, resizeWithWindow{rhs.resizeWithWindow}
|
||||
{
|
||||
|
||||
}
|
||||
|
@ -242,7 +244,8 @@ namespace SHADE
|
|||
mipLevels = rhs.mipLevels;
|
||||
imageAspectFlags = rhs.imageAspectFlags;
|
||||
graphStorage = rhs.graphStorage;
|
||||
infoTracker = std::move(infoTracker);
|
||||
infoTracker = std::move(rhs.infoTracker);
|
||||
resizeWithWindow = rhs.resizeWithWindow;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
|
|
@ -96,11 +96,14 @@ namespace SHADE
|
|||
//! For tracking resource states in stages of the render graphs
|
||||
Handle<InfoTracker> infoTracker;
|
||||
|
||||
//! Whether or not to resize (recreate vulkan image) when window resizes
|
||||
bool resizeWithWindow;
|
||||
|
||||
public:
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* CTORS AND DTORS */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
SHRenderGraphResource(Handle<SHRenderGraphStorage> renderGraphStorage, std::string const& name, std::initializer_list<SH_RENDER_GRAPH_RESOURCE_FLAGS> typeFlags, vk::Format format, uint32_t w, uint32_t h, uint8_t levels, vk::ImageUsageFlagBits usageFlags, vk::ImageCreateFlagBits createFlags) noexcept;
|
||||
SHRenderGraphResource(Handle<SHRenderGraphStorage> renderGraphStorage, std::string const& name, std::initializer_list<SH_RENDER_GRAPH_RESOURCE_FLAGS> typeFlags, vk::Format format, uint32_t w, uint32_t h, uint8_t levels, vk::ImageUsageFlagBits usageFlags, vk::ImageCreateFlagBits createFlags, bool inResizeWithWindow) noexcept;
|
||||
SHRenderGraphResource(SHRenderGraphResource&& rhs) noexcept;
|
||||
SHRenderGraphResource& operator=(SHRenderGraphResource&& rhs) noexcept;
|
||||
~SHRenderGraphResource(void) noexcept;
|
||||
|
|
|
@ -77,6 +77,7 @@ namespace SHADE
|
|||
, name { rhs.name }
|
||||
, viewport {rhs.viewport}
|
||||
, renderer {rhs.renderer}
|
||||
, companionSubpass {rhs.companionSubpass}
|
||||
{
|
||||
|
||||
}
|
||||
|
@ -113,6 +114,7 @@ namespace SHADE
|
|||
name = std::move(rhs.name);
|
||||
renderer = rhs.renderer;
|
||||
viewport = rhs.viewport;
|
||||
companionSubpass = rhs.companionSubpass;
|
||||
|
||||
|
||||
return *this;
|
||||
|
@ -162,7 +164,7 @@ namespace SHADE
|
|||
switch (attachmentDescriptionType)
|
||||
{
|
||||
case SH_RENDER_GRAPH_RESOURCE_FLAGS::DEPTH:
|
||||
imageLayout = vk::ImageLayout::eDepthAttachmentOptimal;
|
||||
imageLayout = vk::ImageLayout::eDepthStencilAttachmentOptimal;
|
||||
break;
|
||||
case SH_RENDER_GRAPH_RESOURCE_FLAGS::STENCIL:
|
||||
imageLayout = vk::ImageLayout::eStencilAttachmentOptimal;
|
||||
|
@ -211,25 +213,38 @@ namespace SHADE
|
|||
{
|
||||
commandBuffer->BeginLabeledSegment(name);
|
||||
|
||||
// Ensure correct transforms are provided
|
||||
superBatch->UpdateBuffers(frameIndex, descPool);
|
||||
|
||||
if (viewport)
|
||||
if (!HasNoAttachments())
|
||||
{
|
||||
// set viewport and scissor
|
||||
uint32_t w = static_cast<uint32_t>(viewport->GetWidth());
|
||||
uint32_t h = static_cast<uint32_t>(viewport->GetHeight());
|
||||
commandBuffer->SetViewportScissor(static_cast<float>(w), static_cast<float>(h), w, h);
|
||||
// Ensure correct transforms are provided
|
||||
superBatch->UpdateBuffers(frameIndex, descPool);
|
||||
|
||||
if (viewport)
|
||||
{
|
||||
// set viewport and scissor
|
||||
uint32_t w = static_cast<uint32_t>(viewport->GetWidth());
|
||||
uint32_t h = static_cast<uint32_t>(viewport->GetHeight());
|
||||
commandBuffer->SetViewportScissor(static_cast<float>(w), static_cast<float>(h), w, h);
|
||||
}
|
||||
|
||||
auto const& descMappings = SHGraphicsPredefinedData::GetMappings(SHGraphicsPredefinedData::SystemType::BATCHING);
|
||||
|
||||
if (renderer)
|
||||
renderer->BindDescriptorSet(commandBuffer, SH_PIPELINE_TYPE::GRAPHICS, descMappings.at(SHPredefinedDescriptorTypes::CAMERA), frameIndex);
|
||||
|
||||
// If companion subpass is not a valid handle, render super batch normally
|
||||
if (!companionSubpass.companion)
|
||||
{
|
||||
// Draw all the batches
|
||||
superBatch->Draw(commandBuffer, frameIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
// if not bind pipeline for companion and and execute draw command
|
||||
commandBuffer->BindPipeline(companionSubpass.pipeline);
|
||||
companionSubpass.companion->superBatch->Draw(commandBuffer, frameIndex, false);
|
||||
}
|
||||
}
|
||||
|
||||
auto const& descMappings = SHGraphicsPredefinedData::GetMappings(SHGraphicsPredefinedData::SystemType::BATCHING);
|
||||
|
||||
if (renderer)
|
||||
renderer->BindDescriptorSet(commandBuffer, SH_PIPELINE_TYPE::GRAPHICS, descMappings.at(SHPredefinedDescriptorTypes::CAMERA), frameIndex);
|
||||
|
||||
// Draw all the batches
|
||||
superBatch->Draw(commandBuffer, frameIndex);
|
||||
|
||||
// Draw all the exterior draw calls
|
||||
for (auto& drawCall : exteriorDrawCalls)
|
||||
{
|
||||
|
@ -265,43 +280,27 @@ namespace SHADE
|
|||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
void SHSubpass::DetachResource(std::string const& resourceName, uint32_t attachmentIndex) noexcept
|
||||
bool SHSubpass::UsesResource(uint32_t attachmentIndex) noexcept
|
||||
{
|
||||
for (uint32_t i = 0; i < colorReferences.size(); ++i)
|
||||
{
|
||||
if (colorReferences[i].attachment == attachmentIndex)
|
||||
{
|
||||
colorReferences.erase (colorReferences.begin() + i);
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < depthReferences.size(); ++i)
|
||||
{
|
||||
if (depthReferences[i].attachment == attachmentIndex)
|
||||
{
|
||||
depthReferences.erase(depthReferences.begin() + i);
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < inputReferences.size(); ++i)
|
||||
{
|
||||
if (inputReferences[i].attachment == attachmentIndex)
|
||||
{
|
||||
inputReferences.erase(inputReferences.begin() + i);
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < inputNames.size(); ++i)
|
||||
{
|
||||
if (inputNames[i] == resourceName)
|
||||
{
|
||||
inputNames.erase(inputNames.begin() + i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SHSubpass::HasNoAttachments(void) const noexcept
|
||||
|
@ -458,6 +457,12 @@ namespace SHADE
|
|||
subpassIndex = index;
|
||||
}
|
||||
|
||||
void SHSubpass::SetCompanionSubpass(Handle<SHSubpass> companion, Handle<SHVkPipeline> pipeline) noexcept
|
||||
{
|
||||
companionSubpass.companion = companion;
|
||||
companionSubpass.pipeline = pipeline;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
|
|
|
@ -21,12 +21,23 @@ namespace SHADE
|
|||
class SHVkSampler;
|
||||
class SHRenderer;
|
||||
class SHViewport;
|
||||
class SHVkPipeline;
|
||||
|
||||
class SH_API SHSubpass : public ISelfHandle<SHSubpass>
|
||||
{
|
||||
public:
|
||||
using ExteriorDrawCallFunction = std::function<void(Handle<SHVkCommandBuffer>, Handle<SHRenderer>, uint32_t)>;
|
||||
|
||||
// Allows for subpasses to run using a companions data
|
||||
struct CompanionSubpass
|
||||
{
|
||||
// subpass whose data will be borrowed to draw
|
||||
Handle<SHSubpass> companion;
|
||||
|
||||
// Pipeline that will be used for all the draw calls from all batches of the companion subpass
|
||||
Handle<SHVkPipeline> pipeline;
|
||||
};
|
||||
|
||||
private:
|
||||
/*---------------------------------------------------------------------*/
|
||||
/* PRIVATE MEMBER VARIABLES */
|
||||
|
@ -94,6 +105,15 @@ namespace SHADE
|
|||
// For identifying subpasses
|
||||
std::string name;
|
||||
|
||||
//! Optional component to a companion subpass. If the subpass handle of this object
|
||||
//! is valid, the subpass will be drawn using this companion's data.
|
||||
CompanionSubpass companionSubpass;
|
||||
|
||||
private:
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* PRIVATE MEMBER FUNCTIONS */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
bool UsesResource(uint32_t attachmentIndex) noexcept;
|
||||
|
||||
public:
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
@ -119,7 +139,6 @@ namespace SHADE
|
|||
void Execute(Handle<SHVkCommandBuffer> commandBuffer, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) noexcept;
|
||||
void HandleResize (void) noexcept;
|
||||
void BindInputDescriptorSets (Handle<SHVkCommandBuffer> cmdBuffer, uint32_t setIndex, uint32_t frameIndex) const noexcept;
|
||||
void DetachResource (std::string const& resourceName, uint32_t attachmentIndex) noexcept;
|
||||
bool HasNoAttachments (void) const noexcept;
|
||||
|
||||
void Init(SHResourceHub& resourceManager) noexcept;
|
||||
|
@ -128,19 +147,24 @@ namespace SHADE
|
|||
void CreateInputDescriptors (void) noexcept;
|
||||
void UpdateWriteDescriptors (void) noexcept;
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* GETTERS AND SETTERS */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
private:
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* PRIVATE GETTERS AND SETTERS */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
void SetIndex (uint32_t index) noexcept;
|
||||
|
||||
public:
|
||||
Handle<SHRenderGraphNode> const& GetParentNode(void) const noexcept;
|
||||
SHSubPassIndex GetIndex() const noexcept;
|
||||
Handle<SHSuperBatch> GetSuperBatch(void) const noexcept;
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* PUBLIC SETTERS AND GETTERS */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
void SetCompanionSubpass (Handle<SHSubpass> companion, Handle<SHVkPipeline> pipeline) noexcept;
|
||||
|
||||
Handle<SHRenderGraphNode> const& GetParentNode(void) const noexcept;
|
||||
SHSubPassIndex GetIndex() const noexcept;
|
||||
Handle<SHSuperBatch> GetSuperBatch(void) const noexcept;
|
||||
std::vector<vk::AttachmentReference> const& GetColorAttachmentReferences (void) const noexcept;
|
||||
vk::Format GetFormatFromAttachmentReference (uint32_t attachmentReference) const noexcept;
|
||||
const std::string& GetName() const;
|
||||
vk::Format GetFormatFromAttachmentReference (uint32_t attachmentReference) const noexcept;
|
||||
const std::string& GetName() const;
|
||||
|
||||
friend class SHRenderGraphNode;
|
||||
friend class SHRenderGraph;
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
#pragma once
|
||||
#include <SHpch.h>
|
||||
#include <fstream>
|
||||
#include "SHInputManager.h"
|
||||
#include "../Tools/SHException.h"
|
||||
|
||||
|
@ -99,6 +100,161 @@ namespace SHADE
|
|||
}
|
||||
}
|
||||
|
||||
//The Binding File format presently goes as such:
|
||||
/*
|
||||
* Binding count
|
||||
* (For each binding:)
|
||||
* Name
|
||||
Binding Type Enum
|
||||
Inverted Bool
|
||||
Gravity Double
|
||||
Dead Double
|
||||
Sensitivity Double
|
||||
Snap Bool
|
||||
PositiveKeyCode count
|
||||
PositiveKeyCodes
|
||||
NegativeKeyCode count
|
||||
NegativeKeyCodes
|
||||
PositiveControllerCode Count
|
||||
PositiveControllerCodes
|
||||
NegativeControllerCode Count
|
||||
NegativeControllerCodes
|
||||
*/
|
||||
void SHInputManager::SaveBindings(std::string const& targetFile) noexcept
|
||||
{
|
||||
std::ofstream file;
|
||||
file.open(targetFile);
|
||||
|
||||
//File cannot be written to
|
||||
if (!file) return;
|
||||
|
||||
//First write the number of bindings
|
||||
file << bindings.size() << std::endl;
|
||||
|
||||
for (auto& b : bindings)
|
||||
{
|
||||
//Name
|
||||
file << b.first << std::endl;
|
||||
|
||||
//Data
|
||||
auto& lbd = b.second;
|
||||
|
||||
file << static_cast<int>(lbd.bindingType) << std::endl;
|
||||
file << static_cast<int>(lbd.inverted) << std::endl;
|
||||
file << lbd.gravity << std::endl;
|
||||
file << lbd.dead << std::endl;
|
||||
file << lbd.sensitivity << std::endl;
|
||||
file << static_cast<int>(lbd.snap) << std::endl;
|
||||
|
||||
//Bindings
|
||||
file << lbd.positiveKeyCodes.size() << std::endl;
|
||||
for (auto kc : lbd.positiveKeyCodes)
|
||||
file << static_cast<int>(kc) << std::endl;
|
||||
file << lbd.negativeKeyCodes.size() << std::endl;
|
||||
for (auto kc : lbd.negativeKeyCodes)
|
||||
file << static_cast<int>(kc) << std::endl;
|
||||
file << lbd.positiveControllerCodes.size() << std::endl;
|
||||
for (auto cc : lbd.positiveControllerCodes)
|
||||
file << static_cast<int>(cc) << std::endl;
|
||||
file << lbd.negativeControllerCodes.size() << std::endl;
|
||||
for (auto cc : lbd.negativeControllerCodes)
|
||||
file << static_cast<int>(cc) << std::endl;
|
||||
}
|
||||
|
||||
file.close();
|
||||
}
|
||||
|
||||
void SHInputManager::LoadBindings(std::string const& sourceFile) noexcept
|
||||
{
|
||||
std::ifstream file;
|
||||
file.open(sourceFile);
|
||||
|
||||
//Check
|
||||
if (!file) return;
|
||||
|
||||
//Erase
|
||||
ClearBindings();
|
||||
|
||||
//Read
|
||||
std::string read;
|
||||
|
||||
int count = 0;
|
||||
std::getline(file, read);
|
||||
count = std::stoi(read);
|
||||
|
||||
std::string bindingName;
|
||||
for (int b = 0; b < count; ++b)
|
||||
{
|
||||
//Name
|
||||
std::getline(file, read);
|
||||
bindingName = read;
|
||||
AddBinding(bindingName);
|
||||
|
||||
//Type
|
||||
std::getline(file, read);
|
||||
SetBindingType(bindingName, static_cast<SH_BINDINGTYPE>(std::stoi(read)));
|
||||
|
||||
//Inversion
|
||||
std::getline(file, read);
|
||||
SetBindingInverted(bindingName, static_cast<bool>(std::stoi(read)));
|
||||
|
||||
//Gravity
|
||||
std::getline(file, read);
|
||||
SetBindingGravity(bindingName, std::stod(read));
|
||||
|
||||
//Dead
|
||||
std::getline(file, read);
|
||||
SetBindingDead(bindingName, std::stod(read));
|
||||
|
||||
//Sensitivity
|
||||
std::getline(file, read);
|
||||
SetBindingSensitivity(bindingName, std::stod(read));
|
||||
|
||||
//Snap
|
||||
std::getline(file, read);
|
||||
SetBindingSnap(bindingName, static_cast<bool>(std::stoi(read)));
|
||||
|
||||
int count = 0;
|
||||
//Positive Key Codes
|
||||
std::getline(file, read);
|
||||
count = std::stoi(read);
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
std::getline(file, read);
|
||||
AddBindingPositiveKeyCode(bindingName, static_cast<SH_KEYCODE>(std::stoi(read)));
|
||||
}
|
||||
|
||||
//Negative Key Codes
|
||||
std::getline(file, read);
|
||||
count = std::stoi(read);
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
std::getline(file, read);
|
||||
AddBindingNegativeKeyCode(bindingName, static_cast<SH_KEYCODE>(std::stoi(read)));
|
||||
}
|
||||
|
||||
//Positive Controller Codes
|
||||
std::getline(file, read);
|
||||
count = std::stoi(read);
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
std::getline(file, read);
|
||||
AddBindingPositiveControllerCode(bindingName, static_cast<SH_CONTROLLERCODE>(std::stoi(read)));
|
||||
}
|
||||
|
||||
//Negative Controller Codes
|
||||
std::getline(file, read);
|
||||
count = std::stoi(read);
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
std::getline(file, read);
|
||||
AddBindingNegativeControllerCode(bindingName, static_cast<SH_CONTROLLERCODE>(std::stoi(read)));
|
||||
}
|
||||
}
|
||||
|
||||
file.close();
|
||||
}
|
||||
|
||||
void SHInputManager::UpdateInput(double dt) noexcept
|
||||
{
|
||||
//Keyboard and Mouse Buttons////////////////////////////////////////////////
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include <map>
|
||||
#include <set>
|
||||
#include "../../SHADE_Managed/src/SHpch.h"
|
||||
#include "../../SHADE_Engine/src/Assets/SHAssetMacros.h"
|
||||
#include "SH_API.h"
|
||||
#pragma comment(lib, "xinput.lib")
|
||||
|
||||
|
@ -681,6 +682,17 @@ namespace SHADE
|
|||
return controllersReleasedTime[controllerNum][static_cast<size_t>(code)];
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* Binding I/O */
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
//Save bindings registered into a file
|
||||
static void SaveBindings(std::string const& targetFile = std::string(ASSET_ROOT) + "/Bindings.SHConfig") noexcept;
|
||||
|
||||
//Load and register bindings from a file
|
||||
//If specified file exists, the current list of bindings will be overwritten, so save them somewhere else before loading
|
||||
static void LoadBindings(std::string const& sourceFile = std::string(ASSET_ROOT) + "/Bindings.SHConfig") noexcept;
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* Binding Functions */
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
|
|
@ -35,7 +35,17 @@ namespace SHADE
|
|||
: position { pos }
|
||||
, orientation { SHQuaternion::FromEuler(rot) }
|
||||
, scale { scl }
|
||||
{}
|
||||
{
|
||||
ComputeTRS();
|
||||
}
|
||||
|
||||
SHTransform::SHTransform(const SHVec3& pos, const SHQuaternion& quat, const SHVec3& scl) noexcept
|
||||
: position { pos }
|
||||
, orientation { quat }
|
||||
, scale { scl }
|
||||
{
|
||||
ComputeTRS();
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Operator Overload Definitions */
|
||||
|
|
|
@ -201,6 +201,7 @@ namespace SHADE
|
|||
|
||||
AddComponentToComponentNode<SHCanvasComponent>(components, eid);
|
||||
AddComponentToComponentNode<SHButtonComponent>(components, eid);
|
||||
AddComponentToComponentNode<SHToggleButtonComponent>(components, eid);
|
||||
|
||||
AddComponentToComponentNode<SHTextRenderableComponent>(components, eid);
|
||||
|
||||
|
@ -258,6 +259,7 @@ namespace SHADE
|
|||
|
||||
AddComponentID<SHCanvasComponent>(componentIDList, componentsNode);
|
||||
AddComponentID<SHButtonComponent>(componentIDList, componentsNode);
|
||||
AddComponentID<SHToggleButtonComponent>(componentIDList, componentsNode);
|
||||
AddComponentID<SHTextRenderableComponent>(componentIDList, componentsNode);
|
||||
|
||||
return componentIDList;
|
||||
|
@ -339,6 +341,7 @@ namespace SHADE
|
|||
|
||||
SHSerializationHelper::InitializeComponentFromNode<SHCanvasComponent>(componentsNode, eid);
|
||||
SHSerializationHelper::InitializeComponentFromNode<SHButtonComponent>(componentsNode, eid);
|
||||
SHSerializationHelper::InitializeComponentFromNode<SHToggleButtonComponent>(componentsNode, eid);
|
||||
SHSerializationHelper::InitializeComponentFromNode<SHTextRenderableComponent>(componentsNode, eid);
|
||||
SHSerializationHelper::InitializeComponentFromNode<SHLightComponent>(componentsNode, eid);
|
||||
}
|
||||
|
|
|
@ -128,6 +128,10 @@ namespace SHADE
|
|||
dbgDrawSys->DrawWireSphere(SHMatrix::Transform(center, SHQuaternion(), scale), color, depthTested);
|
||||
}
|
||||
|
||||
void SHDebugDraw::WireCapsule(const SHVec3& position, const SHQuaternion& rotation, float height, float radius, const SHColour& color, bool depthTested)
|
||||
{
|
||||
dbgDrawSys->DrawWireCapsule(position, rotation, height, radius, color, depthTested);
|
||||
}
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Persistent Draw Functions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
@ -216,6 +220,10 @@ namespace SHADE
|
|||
dbgDrawSys->DrawPersistentWireSphere(SHMatrix::Transform(center, SHQuaternion(), scale), color, depthTested);
|
||||
}
|
||||
|
||||
void SHDebugDraw::Persistent::WireCapsule(const SHVec3& position, const SHQuaternion& rotation, float height, float radius, const SHColour& color, bool depthTested)
|
||||
{
|
||||
dbgDrawSys->DrawPersistentWireCapsule(position, rotation, height, radius, color, depthTested);
|
||||
}
|
||||
void SHDebugDraw::Persistent::ClearDraws()
|
||||
{
|
||||
dbgDrawSys->ClearPersistentDraws();
|
||||
|
|
|
@ -194,6 +194,18 @@ namespace SHADE
|
|||
/// <param name="color">Colour to draw with.</param>
|
||||
/// <param name="depthTested">Whether or not drawn object will be occluded.</param>
|
||||
static void WireSphere(const SHVec3& center, const SHVec3& scale, const SHVec4& color = SHColour::WHITE, bool depthTested = false);
|
||||
/// <summary>
|
||||
/// Draws the outline of a capsule.
|
||||
/// This will remain drawn until ClearDraws() is called.
|
||||
/// </summary>
|
||||
/// <param name="position">Position of the wireframe capsule.</param>
|
||||
/// <param name="rotation">Rotation of the capsule.</param>
|
||||
/// <param name="height">Height of the overall capsule.</param>
|
||||
/// <param name="radius">Radius of the capsule.</param>
|
||||
/// <param name="color"></param>
|
||||
/// <param name="color">Colour to draw with.</param>
|
||||
/// <param name="depthTested">Whether or not drawn object will be occluded.</param>
|
||||
static void WireCapsule(const SHVec3& position, const SHQuaternion& rotation, float height, float radius, const SHColour& color = SHColour::WHITE, bool depthTested = false);
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Persistent Draw Function Class "Folder" */
|
||||
|
@ -366,6 +378,18 @@ namespace SHADE
|
|||
/// <param name="depthTested">Whether or not drawn object will be occluded.</param>
|
||||
static void WireSphere(const SHVec3& center, const SHVec3& scale, const SHVec4& color = SHColour::WHITE, bool depthTested = false);
|
||||
/// <summary>
|
||||
/// Draws the outline of a capsule.
|
||||
/// This will remain drawn until ClearDraws() is called.
|
||||
/// </summary>
|
||||
/// <param name="position">Position of the wireframe capsule.</param>
|
||||
/// <param name="rotation">Rotation of the capsule.</param>
|
||||
/// <param name="height">Height of the overall capsule.</param>
|
||||
/// <param name="radius">Radius of the capsule.</param>
|
||||
/// <param name="color"></param>
|
||||
/// <param name="color">Colour to draw with.</param>
|
||||
/// <param name="depthTested">Whether or not drawn object will be occluded.</param>
|
||||
static void WireCapsule(const SHVec3& position, const SHQuaternion& rotation, float height, float radius, const SHColour& color = SHColour::WHITE, bool depthTested = false);
|
||||
/// <summary>
|
||||
/// Clears any persistent drawn debug primitives.
|
||||
/// </summary>
|
||||
static void ClearDraws();
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
#pragma once
|
||||
|
||||
|
||||
#include "ECS_Base/SHECSMacros.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
struct SHButtonClickEvent
|
||||
{
|
||||
EntityID EID;
|
||||
// value of the toggle button, default to false if its a button and not a toggle button
|
||||
bool value{false};
|
||||
};
|
||||
|
||||
|
||||
}
|
|
@ -5,7 +5,7 @@
|
|||
namespace SHADE
|
||||
{
|
||||
SHButtonComponent::SHButtonComponent()
|
||||
:size(1.0f), offset(0.0f), isHovered(false), isClicked(false),
|
||||
:size(1.0f), isHovered(false), isClicked(false),
|
||||
defaultTexture(0), hoveredTexture(0), clickedTexture(0)
|
||||
{
|
||||
}
|
||||
|
|
|
@ -18,7 +18,6 @@ namespace SHADE
|
|||
virtual ~SHButtonComponent() = default;
|
||||
|
||||
SHVec2 size;
|
||||
SHVec2 offset;
|
||||
|
||||
AssetID GetClickedTexture() const noexcept;
|
||||
AssetID GetDefaultTexture() const noexcept;
|
||||
|
@ -33,8 +32,10 @@ namespace SHADE
|
|||
|
||||
friend class SHUISystem;
|
||||
private:
|
||||
|
||||
//Set to true when mouse is hovering over the button.
|
||||
bool isHovered;
|
||||
//This is set to true when the mouse clicks down, and set back to false when mouse releases.
|
||||
//The event for the button click will be broadcasted when mouse release.
|
||||
bool isClicked;
|
||||
AssetID defaultTexture;
|
||||
AssetID hoveredTexture;
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
#include "SHpch.h"
|
||||
#include "SHSliderComponent.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
SHSliderComponent::SHSliderComponent()
|
||||
:size(1.0f), isHovered(false), isClicked(false), value(0.0f)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
float SHSliderComponent::GetValue() const noexcept
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
void SHSliderComponent::SetValue(float value) noexcept
|
||||
{
|
||||
this->value = value;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
RTTR_REGISTRATION
|
||||
{
|
||||
using namespace SHADE;
|
||||
using namespace rttr;
|
||||
|
||||
registration::class_<SHSliderComponent>("Slider Component")
|
||||
.property("Slider Value", &SHSliderComponent::GetValue, &SHSliderComponent::SetValue)
|
||||
|
||||
;
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
#pragma once
|
||||
|
||||
#include <rttr/registration>
|
||||
|
||||
#include "SH_API.h"
|
||||
#include "ECS_Base/Components/SHComponent.h"
|
||||
#include "Math/Vector/SHVec3.h"
|
||||
#include "Math/Vector/SHVec2.h"
|
||||
#include "Assets/SHAssetMacros.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
||||
class SH_API SHSliderComponent final: public SHComponent
|
||||
{
|
||||
public:
|
||||
SHSliderComponent();
|
||||
virtual ~SHSliderComponent() = default;
|
||||
|
||||
SHVec2 size;
|
||||
|
||||
|
||||
float GetValue() const noexcept;
|
||||
|
||||
|
||||
void SetValue(float value) noexcept;
|
||||
|
||||
|
||||
friend class SHUISystem;
|
||||
private:
|
||||
|
||||
bool isHovered;
|
||||
bool isClicked;
|
||||
|
||||
float value;
|
||||
|
||||
RTTR_ENABLE()
|
||||
};
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
#include "SHpch.h"
|
||||
#include "SHToggleButtonComponent.h"
|
||||
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
SHToggleButtonComponent::SHToggleButtonComponent()
|
||||
:size(1.0f), isHovered(false), isClicked(false), value(false),
|
||||
defaultTexture(0), toggledTexture(0)
|
||||
{
|
||||
}
|
||||
|
||||
AssetID SHToggleButtonComponent::GetDefaultTexture() const noexcept
|
||||
{
|
||||
return defaultTexture;
|
||||
}
|
||||
|
||||
AssetID SHToggleButtonComponent::GetToggledTexture() const noexcept
|
||||
{
|
||||
return toggledTexture;
|
||||
}
|
||||
|
||||
bool SHToggleButtonComponent::GetValue() const noexcept
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
void SHToggleButtonComponent::SetDefaultTexture(AssetID texture) noexcept
|
||||
{
|
||||
defaultTexture = texture;
|
||||
}
|
||||
|
||||
void SHToggleButtonComponent::SetToggledTexture(AssetID texture) noexcept
|
||||
{
|
||||
toggledTexture = texture;
|
||||
}
|
||||
|
||||
void SHToggleButtonComponent::SetValue(bool value) noexcept
|
||||
{
|
||||
this->value = value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
RTTR_REGISTRATION
|
||||
{
|
||||
using namespace SHADE;
|
||||
using namespace rttr;
|
||||
|
||||
registration::class_<SHToggleButtonComponent>("Toggle Button Component")
|
||||
.property("Non Toggled Texture", &SHToggleButtonComponent::GetDefaultTexture, &SHToggleButtonComponent::SetDefaultTexture)
|
||||
.property("Toggled Texture", &SHToggleButtonComponent::GetToggledTexture, &SHToggleButtonComponent::SetToggledTexture)
|
||||
.property("Value", &SHToggleButtonComponent::GetValue, &SHToggleButtonComponent::SetValue)
|
||||
;
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
#pragma once
|
||||
|
||||
#include <rttr/registration>
|
||||
|
||||
#include "SH_API.h"
|
||||
#include "ECS_Base/Components/SHComponent.h"
|
||||
#include "Math/Vector/SHVec3.h"
|
||||
#include "Math/Vector/SHVec2.h"
|
||||
#include "Assets/SHAssetMacros.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
||||
class SH_API SHToggleButtonComponent final: public SHComponent
|
||||
{
|
||||
public:
|
||||
SHToggleButtonComponent();
|
||||
virtual ~SHToggleButtonComponent() = default;
|
||||
|
||||
SHVec2 size;
|
||||
|
||||
AssetID GetToggledTexture() const noexcept;
|
||||
AssetID GetDefaultTexture() const noexcept;
|
||||
bool GetValue() const noexcept;
|
||||
|
||||
|
||||
void SetDefaultTexture(AssetID texture) noexcept;
|
||||
void SetToggledTexture(AssetID texture) noexcept;
|
||||
void SetValue(bool value) noexcept;
|
||||
|
||||
|
||||
|
||||
friend class SHUISystem;
|
||||
private:
|
||||
|
||||
//Set to true when mouse is hovering over the button.
|
||||
bool isHovered;
|
||||
//This is set to true when the mouse clicks down, and set back to false when mouse releases.
|
||||
//The event for the button click will be broadcasted when mouse release.
|
||||
bool isClicked;
|
||||
bool value;
|
||||
AssetID defaultTexture;
|
||||
AssetID toggledTexture;
|
||||
|
||||
|
||||
|
||||
RTTR_ENABLE()
|
||||
};
|
||||
|
||||
|
||||
}
|
|
@ -9,7 +9,15 @@
|
|||
#include "Editor/EditorWindow/ViewportWindow/SHEditorViewport.h"
|
||||
#include "Editor/SHEditor.h"
|
||||
#include "Resource/SHResourceManager.h"
|
||||
#include "Assets/SHAssetManager.h"
|
||||
#include "Input/SHInputManager.h"
|
||||
#include "SHUIComponent.h"
|
||||
#include "SHButtonComponent.h"
|
||||
#include "SHToggleButtonComponent.h"
|
||||
#include "SHSliderComponent.h"
|
||||
#include "SHCanvasComponent.h"
|
||||
#include "Events/SHEventManager.hpp"
|
||||
#include "Events/SHButtonClickEvent.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
@ -103,7 +111,7 @@ namespace SHADE
|
|||
{
|
||||
auto transform = SHComponentManager::GetComponent<SHTransformComponent>(comp.GetEID());
|
||||
if (canvasComp != nullptr)
|
||||
comp.localToCanvasMatrix = canvasComp->GetMatrix()* transform->GetTRS();
|
||||
comp.localToCanvasMatrix = transform->GetTRS() * canvasComp->GetMatrix();
|
||||
else
|
||||
comp.localToCanvasMatrix = transform->GetTRS();
|
||||
}
|
||||
|
@ -139,77 +147,235 @@ namespace SHADE
|
|||
|
||||
void SHUISystem::UpdateButtonComponent(SHButtonComponent& comp) noexcept
|
||||
{
|
||||
if (!SHComponentManager::HasComponent<SHTransformComponent>(comp.GetEID()) || !SHComponentManager::HasComponent<SHUIComponent>(comp.GetEID()))
|
||||
if (!SHComponentManager::HasComponent<SHUIComponent>(comp.GetEID()))
|
||||
{
|
||||
return;
|
||||
}
|
||||
auto cameraSystem = SHSystemManager::GetSystem<SHCameraSystem>();
|
||||
auto uiComp = SHComponentManager::GetComponent<SHUIComponent>(comp.GetEID());
|
||||
//auto canvasComp = SHComponentManager::GetComponent_s<SHCanvasComponent>(uiComp->canvasID);
|
||||
|
||||
SHVec4 topExtent4 = SHMatrix::Translate(-comp.size.x * 0.5f, comp.size.y * 0.5f, 0.0f) * uiComp->GetMatrix() * SHVec4(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
SHVec4 btmExtent4 = SHMatrix::Translate(comp.size.x * 0.5f, -comp.size.y * 0.5f, 0.0f) * uiComp->GetMatrix() * SHVec4(0.0f,0.0f, 0.0f,1.0f);
|
||||
|
||||
|
||||
SHVec2 topExtent{ topExtent4.x,topExtent4.y };
|
||||
SHVec2 btmExtent{ btmExtent4.x,btmExtent4.y };
|
||||
|
||||
|
||||
SHVec2 mousePos;
|
||||
SHVec2 windowSize;
|
||||
#ifdef SHEDITOR
|
||||
windowSize = SHEditorWindowManager::GetEditorWindow<SHEditorViewport>()->beginContentRegionAvailable;
|
||||
mousePos = SHEditorWindowManager::GetEditorWindow<SHEditorViewport>()->viewportMousePos;
|
||||
//mousePos.y = windowSize.y - mousePos.y;
|
||||
//SHLOG_INFO("mouse pos: {}, {}", mousePos.x, mousePos.y)
|
||||
mousePos /= windowSize;
|
||||
//SHLOG_INFO("mouse pos normalized: {}, {}", mousePos.x, mousePos.y)
|
||||
|
||||
|
||||
|
||||
#else
|
||||
|
||||
int x, y;
|
||||
SHInputManager::GetMouseScreenPosition(&x, &y);
|
||||
mousePos.x = x;
|
||||
mousePos.y = y;
|
||||
auto ws = SHSystemManager::GetSystem<SHGraphicsSystem>()->GetWindow()->GetWindowSize();
|
||||
windowSize = { ws.first,ws.second };
|
||||
mousePos /= windowSize;
|
||||
#endif
|
||||
|
||||
SHVec2 camSize{ cameraSystem->GetCameraWidthHeight(0)};
|
||||
//SHLOG_INFO("TopExtent: {}, {}", topExtent.x, topExtent.y)
|
||||
|
||||
topExtent = CanvasToScreenPoint(topExtent,true);
|
||||
btmExtent = CanvasToScreenPoint(btmExtent,true);
|
||||
//SHLOG_INFO("TopExtent: {}, {} Btm Extent: {}, {}", topExtent.x, topExtent.y, btmExtent.x, btmExtent.y)
|
||||
|
||||
|
||||
//comp.isClicked = false;
|
||||
if (mousePos.x >= topExtent.x && mousePos.x <= btmExtent.x
|
||||
&& mousePos.y >= topExtent.y && mousePos.y <= btmExtent.y)
|
||||
{
|
||||
comp.isHovered = true;
|
||||
#ifdef SHEDITOR
|
||||
//if (SHSystemManager::GetSystem<SHEditor>()->editorState == SHEditor::State::PLAY)
|
||||
{
|
||||
if (SHInputManager::GetKeyDown(SHInputManager::SH_KEYCODE::LMB))
|
||||
{
|
||||
comp.isClicked = true;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (SHInputManager::GetKeyDown(SHInputManager::SH_KEYCODE::LMB))
|
||||
{
|
||||
comp.isClicked = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
//SHLOG_INFO("HOVERED")
|
||||
}
|
||||
else
|
||||
{
|
||||
comp.isHovered = false;
|
||||
//SHLOG_INFO("NOT HOVERED")
|
||||
}
|
||||
if (comp.isClicked && SHInputManager::GetKeyUp(SHInputManager::SH_KEYCODE::LMB))
|
||||
{
|
||||
comp.isClicked = false;
|
||||
SHButtonClickEvent clickEvent;
|
||||
clickEvent.EID = comp.GetEID();
|
||||
SHEventManager::BroadcastEvent(clickEvent, SH_BUTTON_CLICK_EVENT);
|
||||
}
|
||||
|
||||
if (SHComponentManager::HasComponent<SHRenderable>(comp.GetEID()))
|
||||
{
|
||||
auto renderable = SHComponentManager::GetComponent_s<SHRenderable>(comp.GetEID());
|
||||
//auto texture = SHResourceManager::Get<SHTexture>(comp.GetDefaultTexture());
|
||||
|
||||
auto material = renderable->GetModifiableMaterial();
|
||||
if(!comp.isHovered && !comp.isClicked)
|
||||
if (comp.GetDefaultTexture() != 0 && SHAssetManager::GetType(comp.GetDefaultTexture()) == AssetType::TEXTURE)
|
||||
{
|
||||
material->SetProperty("data.textureIndex", comp.GetDefaultTexture());
|
||||
//SHLOG_INFO("SETTING DEFAULT TEXTURE")
|
||||
}
|
||||
else if (comp.isClicked)
|
||||
{
|
||||
if (comp.GetClickedTexture() != 0 && SHAssetManager::GetType(comp.GetClickedTexture()) == AssetType::TEXTURE)
|
||||
{
|
||||
material->SetProperty("data.textureIndex", comp.GetClickedTexture());
|
||||
//SHLOG_INFO("SETTING CLICKED TEXTURE")
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (comp.GetHoveredTexture() != 0 && SHAssetManager::GetType(comp.GetHoveredTexture()) == AssetType::TEXTURE)
|
||||
{
|
||||
material->SetProperty("data.textureIndex", comp.GetHoveredTexture());
|
||||
//SHLOG_INFO("SETTING HOVERED TEXTURE")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SHUISystem::UpdateToggleButtonComponent(SHToggleButtonComponent& comp) noexcept
|
||||
{
|
||||
if (!SHComponentManager::HasComponent<SHUIComponent>(comp.GetEID()))
|
||||
{
|
||||
return;
|
||||
}
|
||||
auto cameraSystem = SHSystemManager::GetSystem<SHCameraSystem>();
|
||||
auto uiComp = SHComponentManager::GetComponent<SHUIComponent>(comp.GetEID());
|
||||
|
||||
SHVec4 topExtent4 = uiComp->GetMatrix() * SHVec4(-comp.size.x * 0.5f, comp.size.y * 0.5f , 0.0f,1.0f);
|
||||
SHVec4 btmExtent4 = uiComp->GetMatrix() * SHVec4(comp.size.x * 0.5f , -comp.size.y * 0.5f , 0.0f, 1.0f);
|
||||
SHVec4 topExtent4 = SHMatrix::Translate(-comp.size.x * 0.5f, comp.size.y * 0.5f, 0.0f) * uiComp->GetMatrix() * SHVec4(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
SHVec4 btmExtent4 = SHMatrix::Translate(comp.size.x * 0.5f, -comp.size.y * 0.5f, 0.0f) * uiComp->GetMatrix() * SHVec4(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
|
||||
SHVec2 topExtent{ topExtent4.x,-topExtent4.y };
|
||||
SHVec2 btmExtent{ btmExtent4.x,-btmExtent4.y };
|
||||
|
||||
|
||||
SHVec2 topExtent{ topExtent4.x,topExtent4.y };
|
||||
SHVec2 btmExtent{ btmExtent4.x,btmExtent4.y };
|
||||
|
||||
SHVec2 windowSize;
|
||||
SHVec2 mousePos;
|
||||
SHVec2 windowSize;
|
||||
|
||||
#ifdef SHEDITOR
|
||||
|
||||
windowSize = SHEditorWindowManager::GetEditorWindow<SHEditorViewport>()->windowSize;
|
||||
windowSize = SHEditorWindowManager::GetEditorWindow<SHEditorViewport>()->beginContentRegionAvailable;
|
||||
mousePos = SHEditorWindowManager::GetEditorWindow<SHEditorViewport>()->viewportMousePos;
|
||||
//mousePos.y = windowSize.y - mousePos.y;
|
||||
//SHLOG_INFO("mouse pos: {}, {}", mousePos.x, mousePos.y)
|
||||
mousePos /= windowSize;
|
||||
//SHLOG_INFO("mouse pos normalized: {}, {}", mousePos.x, mousePos.y)
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
SHVec2 camSize{ cameraSystem->GetCameraWidthHeight(0).x , cameraSystem->GetCameraWidthHeight(0).y };
|
||||
|
||||
topExtent += camSize * 0.5f;
|
||||
btmExtent += camSize * 0.5f;
|
||||
|
||||
//Convert everything to using ratios
|
||||
topExtent /= camSize;
|
||||
btmExtent /= camSize;
|
||||
#else
|
||||
|
||||
int x, y;
|
||||
SHInputManager::GetMouseScreenPosition(&x, &y);
|
||||
mousePos.x = x;
|
||||
mousePos.y = y;
|
||||
auto ws = SHSystemManager::GetSystem<SHGraphicsSystem>()->GetWindow()->GetWindowSize();
|
||||
windowSize = { ws.first,ws.second };
|
||||
mousePos /= windowSize;
|
||||
#endif
|
||||
|
||||
SHVec2 camSize{ cameraSystem->GetCameraWidthHeight(0) };
|
||||
|
||||
|
||||
|
||||
topExtent = CanvasToScreenPoint(topExtent,true);
|
||||
btmExtent = CanvasToScreenPoint(btmExtent, true);
|
||||
|
||||
|
||||
|
||||
//SHLOG_INFO("mousePos: {} , {}", mousePos.x, mousePos.y);
|
||||
comp.isClicked = false;
|
||||
if (mousePos.x >= topExtent.x && mousePos.x <= btmExtent.x
|
||||
&& mousePos.y >= topExtent.y && mousePos.y <= btmExtent.y)
|
||||
{
|
||||
comp.isHovered = true;
|
||||
if (SHInputManager::GetKeyUp(SHInputManager::SH_KEYCODE::LMB))
|
||||
#ifdef SHEDITOR
|
||||
if (SHSystemManager::GetSystem<SHEditor>()->editorState == SHEditor::State::PLAY)
|
||||
{
|
||||
if (SHInputManager::GetKeyDown(SHInputManager::SH_KEYCODE::LMB))
|
||||
{
|
||||
comp.isClicked = true;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (SHInputManager::GetKeyDown(SHInputManager::SH_KEYCODE::LMB))
|
||||
{
|
||||
comp.isClicked = true;
|
||||
}
|
||||
//SHLOG_INFO("BUTTON HOVERED");
|
||||
|
||||
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
comp.isHovered = false;
|
||||
|
||||
//SHLOG_INFO("BUTTON NOT HOVERED")
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
if (comp.isClicked && SHInputManager::GetKeyUp(SHInputManager::SH_KEYCODE::LMB))
|
||||
{
|
||||
comp.isClicked = false;
|
||||
comp.value = !comp.value;
|
||||
SHButtonClickEvent clickEvent;
|
||||
clickEvent.EID = comp.GetEID();
|
||||
clickEvent.value = comp.value;
|
||||
SHEventManager::BroadcastEvent(clickEvent, SH_BUTTON_CLICK_EVENT);
|
||||
}
|
||||
|
||||
if (SHComponentManager::HasComponent<SHRenderable>(comp.GetEID()))
|
||||
{
|
||||
//auto renderable = SHComponentManager::GetComponent_s<SHRenderable>(comp.GetEID());
|
||||
auto renderable = SHComponentManager::GetComponent_s<SHRenderable>(comp.GetEID());
|
||||
//auto texture = SHResourceManager::Get<SHTexture>(comp.GetDefaultTexture());
|
||||
|
||||
//auto material = renderable->GetModifiableMaterial();
|
||||
//material->SetProperty("texture", comp.GetDefaultTexture());
|
||||
auto material = renderable->GetModifiableMaterial();
|
||||
if (comp.GetValue() == false)
|
||||
{
|
||||
if (comp.GetDefaultTexture()!= 0 && SHAssetManager::GetType(comp.GetDefaultTexture()) == AssetType::TEXTURE)
|
||||
{
|
||||
material->SetProperty("data.textureIndex", comp.GetDefaultTexture());
|
||||
//SHLOG_INFO("SETTING DEFAULT TEXTURE")
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (comp.GetToggledTexture() != 0 && SHAssetManager::GetType(comp.GetToggledTexture()) == AssetType::TEXTURE)
|
||||
{
|
||||
material->SetProperty("data.textureIndex", comp.GetToggledTexture());
|
||||
//SHLOG_INFO("SETTING DEFAULT TEXTURE")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SHUISystem::UpdateButtonsRoutine::Execute(double dt) noexcept
|
||||
{
|
||||
SHUISystem* system = (SHUISystem*)GetSystem();
|
||||
|
@ -219,6 +385,34 @@ namespace SHADE
|
|||
if (SHSceneManager::CheckNodeAndComponentsActive<SHButtonComponent>(comp.GetEID()))
|
||||
system->UpdateButtonComponent(comp);
|
||||
}
|
||||
|
||||
auto& toggleButtonDense = SHComponentManager::GetDense<SHToggleButtonComponent>();
|
||||
for (auto& comp : toggleButtonDense)
|
||||
{
|
||||
if (SHSceneManager::CheckNodeAndComponentsActive<SHToggleButtonComponent>(comp.GetEID()))
|
||||
system->UpdateToggleButtonComponent(comp);
|
||||
}
|
||||
}
|
||||
|
||||
SHVec2 SHUISystem::CanvasToScreenPoint(SHVec2& const canvasPoint, bool normalized) noexcept
|
||||
{
|
||||
SHVec2 result{canvasPoint};
|
||||
|
||||
auto cameraSystem = SHSystemManager::GetSystem<SHCameraSystem>();
|
||||
|
||||
SHVec2 camSize{ cameraSystem->GetCameraWidthHeight(0) };
|
||||
//camSize.y *= -1.0f;
|
||||
|
||||
result.y *= -1.0f;
|
||||
result += camSize * 0.5f;
|
||||
|
||||
if (normalized)
|
||||
return result / camSize;
|
||||
else
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}//end namespace
|
||||
|
|
|
@ -3,14 +3,20 @@
|
|||
#include "SH_API.h"
|
||||
#include "ECS_Base/System/SHSystem.h"
|
||||
#include "ECS_Base/System/SHSystemRoutine.h"
|
||||
#include "SHUIComponent.h"
|
||||
#include "SHButtonComponent.h"
|
||||
#include "SHCanvasComponent.h"
|
||||
|
||||
#include "Scene/SHSceneGraph.h"
|
||||
#include "Scene/SHSceneManager.h"
|
||||
#include "Math/Vector/SHVec2.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
||||
class SHButtonComponent;
|
||||
class SHUIComponent;
|
||||
class SHToggleButtonComponent;
|
||||
class SHSliderComponent;
|
||||
class SHCanvasComponent;
|
||||
|
||||
class SH_API SHUISystem final: public SHSystem
|
||||
{
|
||||
public:
|
||||
|
@ -64,7 +70,11 @@ namespace SHADE
|
|||
private:
|
||||
void UpdateUIComponent(SHUIComponent& comp) noexcept;
|
||||
void UpdateButtonComponent(SHButtonComponent& comp) noexcept;
|
||||
void UpdateToggleButtonComponent(SHToggleButtonComponent& comp) noexcept;
|
||||
void UpdateCanvasComponent(SHCanvasComponent& comp) noexcept;
|
||||
|
||||
SHVec2 CanvasToScreenPoint(SHVec2& const canvasPoint, bool normalized) noexcept;
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
|
|
@ -107,8 +107,7 @@ namespace SHADE
|
|||
|
||||
Vector3 Transform::Forward::get()
|
||||
{
|
||||
const SHVec3 DIRECTION = SHVec3::Rotate(-SHVec3::UnitZ, Convert::ToNative(GlobalRotation));
|
||||
return Convert::ToCLI(DIRECTION);
|
||||
return Vector3::Rotate(Vector3::Forward, GlobalRotation);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
|
|
@ -167,6 +167,10 @@ namespace SHADE
|
|||
{
|
||||
return Convert::ToCLI(SHVec3::Rotate(Convert::ToNative(vec), Convert::ToNative(axis), radians));
|
||||
}
|
||||
Vector3 Vector3::Rotate(Vector3 vec, Quaternion quat)
|
||||
{
|
||||
return Convert::ToCLI(SHVec3::Rotate(Convert::ToNative(vec), Convert::ToNative(quat)));
|
||||
}
|
||||
Vector3 Vector3::Min(Vector3 lhs, Vector3 rhs)
|
||||
{
|
||||
float lx = lhs.x, rx = rhs.x;
|
||||
|
|
|
@ -19,10 +19,17 @@ of DigiPen Institute of Technology is prohibited.
|
|||
// Project Includes
|
||||
#include "Vector2.hxx"
|
||||
|
||||
value struct Quaternion;
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Forward Declarations */
|
||||
/*-------------------------------------------------------------------------- --- */
|
||||
value struct Quaternion;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Type Definitions */
|
||||
/*-------------------------------------------------------------------------- --- */
|
||||
|
||||
///<summary>
|
||||
/// CLR version of SHADE Engine's Vector3 class that represents a 3-Dimensional Vector.
|
||||
/// Designed to closely match Unity's Vector3 struct.
|
||||
|
@ -308,6 +315,12 @@ namespace SHADE
|
|||
/// <returns>The Vector3 that represents the rotated vector.</returns>
|
||||
static Vector3 Rotate(Vector3 vec, Vector3 axis, float radians);
|
||||
/// <summary>
|
||||
/// Rotates a Vector3 using a Quaternion.
|
||||
/// </summary>
|
||||
/// <param name="vec">A Vector3 to rotate.</param>
|
||||
/// <param name="quat">A Quaternion to rotate the vector with.</param>
|
||||
static Vector3 Rotate(Vector3 vec, Quaternion quat);
|
||||
/// <summary>
|
||||
/// Computes and returns a Vector3 that is made from the smallest components of
|
||||
/// the two specified Vector3s.
|
||||
/// </summary>
|
||||
|
|
Loading…
Reference in New Issue