PlayerController and PickAndThrow #167

Merged
glencelow merged 21 commits from PlayerController into main 2022-11-02 17:40:51 +08:00
54 changed files with 1599 additions and 279 deletions
Showing only changes of commit 4f70b543b2 - Show all commits

View File

@ -21,7 +21,8 @@ layout(set = 4, binding = 0, rgba32f) uniform image2D positions;
layout(set = 4, binding = 1, rgba32f) uniform image2D normals; layout(set = 4, binding = 1, rgba32f) uniform image2D normals;
layout(set = 4, binding = 2, rgba8) uniform image2D albedo; layout(set = 4, binding = 2, rgba8) uniform image2D albedo;
layout(set = 4, binding = 3, r32ui) uniform uimage2D lightLayerData; layout(set = 4, binding = 3, r32ui) uniform uimage2D lightLayerData;
layout(set = 4, binding = 4, rgba8) uniform image2D targetImage; layout(set = 4, binding = 4, r8) uniform image2D ssaoBlurredImage;
layout(set = 4, binding = 5, rgba8) uniform image2D targetImage;
layout(set = 1, binding = 0) uniform LightCounts layout(set = 1, binding = 0) uniform LightCounts
{ {
@ -51,33 +52,46 @@ void main()
vec3 pixelDiffuse = imageLoad (albedo, globalThread).rgb; vec3 pixelDiffuse = imageLoad (albedo, globalThread).rgb;
// Get position of fragment in world space // Get position of fragment in world space
vec3 positionWorld = imageLoad (positions, globalThread).rgb; vec3 positionView = imageLoad (positions, globalThread).rgb;
// normal of fragment // normal of fragment
vec3 normalWorld = imageLoad(normals, globalThread).rgb; vec3 normalView = imageLoad(normals, globalThread).rgb;
// light layer index
uint lightLayer = imageLoad (lightLayerData, globalThread).r;
vec3 fragColor = vec3 (0.0f); vec3 fragColor = vec3 (0.0f);
for (int i = 0; i < lightCounts.directionalLights; ++i) for (int i = 0; i < lightCounts.directionalLights; ++i)
{
if ((lightLayer & DirLightData.dLightData[i].cullingMask) != 0)
{ {
// get normalized direction of light // get normalized direction of light
vec3 dLightNormalized = normalize (DirLightData.dLightData[i].direction); vec3 dLightNormalized = normalize (DirLightData.dLightData[i].direction);
// Get diffuse strength // Get diffuse strength
float diffuseStrength = max (0, dot (dLightNormalized, normalWorld)); float diffuseStrength = max (0, dot (dLightNormalized, normalView));
// Calculate the fragment color // Calculate the fragment color
fragColor += DirLightData.dLightData[i].diffuseColor.rgb * diffuseStrength.rrr * pixelDiffuse; fragColor += DirLightData.dLightData[i].diffuseColor.rgb * diffuseStrength.rrr * pixelDiffuse;
} }
}
for (int i = 0; i < lightCounts.ambientLights; ++i) for (int i = 0; i < lightCounts.ambientLights; ++i)
{
if ((lightLayer & AmbLightData.aLightData[i].cullingMask) != 0)
{ {
// Just do some add // Just do some add
//fragColor += pixelDiffuse.rgb * AmbLightData.aLightData[i].ambientColor.rgb * vec3 (0.5f); //fragColor += pixelDiffuse.rgb * AmbLightData.aLightData[i].ambientColor.rgb * vec3 (0.5f);
fragColor += pixelDiffuse.rgb * AmbLightData.aLightData[i].ambientColor.rgb * vec3 (AmbLightData.aLightData[i].strength); fragColor += pixelDiffuse.rgb * AmbLightData.aLightData[i].ambientColor.rgb * vec3 (AmbLightData.aLightData[i].strength);
} }
}
float ssaoVal = imageLoad (ssaoBlurredImage, globalThread).r;
fragColor *= ssaoVal;
// store result into result image // store result into result image
imageStore(targetImage, ivec2(gl_GlobalInvocationID.xy), vec4(fragColor, 1.0f)); imageStore(targetImage, ivec2(gl_GlobalInvocationID.xy), vec4(fragColor.rgb, 1.0f));
//imageStore(targetImage, ivec2(gl_GlobalInvocationID.xy), vec4(ssaoVal.rrr, 1.0f));
} }

View File

@ -0,0 +1,58 @@
#version 450
#define BLUR_WIDTH 5
#define BLUR_HALF_WIDTH BLUR_WIDTH / 2
#define SHM_WIDTH BLUR_WIDTH + 16 - 1
layout(local_size_x = 16, local_size_y = 16) in;
layout(set = 4, binding = 0, r8) uniform image2D ssaoImage;
layout(set = 4, binding = 1, r8) uniform image2D ssaoBlurImage;
float GetSSAOValue(ivec2 uv, ivec2 imageSize)
{
if (uv.x >= 0 && uv.y >= 0 && uv.x < imageSize.x && uv.y < imageSize.y)
{
return imageLoad (ssaoImage, uv).r;
}
return 0.0f;
}
shared float sharedPixels[16 + BLUR_WIDTH - 1][16 + BLUR_WIDTH - 1];
void main()
{
ivec2 globalThread = ivec2 (gl_GlobalInvocationID.xy);
ivec2 localThread = ivec2 (gl_LocalInvocationID.xy);
ivec2 inputImageSize = imageSize(ssaoImage);
// Load color into shared memory
ivec2 start = ivec2 (gl_WorkGroupID) * ivec2 (gl_WorkGroupSize) - (BLUR_HALF_WIDTH);
for (int i = localThread.x; i < SHM_WIDTH; i += int (gl_WorkGroupSize.x))
{
for (int j = localThread.y; j < SHM_WIDTH; j += int (gl_WorkGroupSize.y))
{
float value = GetSSAOValue (start + ivec2 (i, j), inputImageSize);
sharedPixels[i][j] = value;
}
}
// wait for all shared memory to load
barrier();
ivec2 shmStart = ivec2 (localThread + (BLUR_HALF_WIDTH));
float sum = 0;
for (int i = -BLUR_HALF_WIDTH; i <= BLUR_HALF_WIDTH; ++i)
{
for (int j = -BLUR_HALF_WIDTH; j <= BLUR_HALF_WIDTH; ++j)
{
float sharedVal = sharedPixels[shmStart.x + i][shmStart.y + j];
sum += sharedVal;
}
}
sum /= (BLUR_WIDTH * BLUR_WIDTH);
imageStore(ssaoBlurImage, globalThread, vec4(sum.rrr, 1.0f));
}

Binary file not shown.

View File

@ -0,0 +1,3 @@
Name: SSAOBlur_CS
ID: 39760835
Type: 2

104
Assets/Shaders/SSAO_CS.glsl Normal file
View File

@ -0,0 +1,104 @@
#version 450
const uint NUM_SAMPLES = 64;
const uint NUM_ROTATIONS = 16;
const int ROTATION_KERNEL_W = 4;
const int ROTATION_KERNEL_H = 4;
// can perhaps pass in as push constant.
const float RADIUS = 0.5f;
const float BIAS = 0.025f;
layout(local_size_x = 16, local_size_y = 16) in;
layout(set = 4, binding = 0, rgba32f) uniform image2D positions;
layout(set = 4, binding = 1, rgba32f) uniform image2D normals;
layout(set = 4, binding = 2, rgba32f) uniform image2D outputImage;
// SSAO data
layout(std430, set = 5, binding = 0) buffer SSAOData
{
vec4 samples[NUM_SAMPLES];
} ssaoData;
layout (set = 5, binding = 1) uniform sampler2D noiseTexture;
layout(set = 2, binding = 0) uniform CameraData
{
vec4 position;
mat4 vpMat;
mat4 viewMat;
mat4 projMat;
} cameraData;
void main()
{
// image size of the SSAO image
ivec2 ssaoSize = imageSize (outputImage);
// global thread
ivec2 globalThread = ivec2 (gl_GlobalInvocationID.xy);
// load all the necessary variables
vec3 viewSpacePos = imageLoad (positions, globalThread).rgb;
vec3 viewSpaceNormal = normalize (imageLoad (normals, globalThread).rgb);
// Get the noise dimension. This should be 4x4
vec2 noiseDim = vec2 (textureSize(noiseTexture, 0));
// Get normlized thread UV coordinates
vec2 threadUV = (vec2(globalThread)) / vec2(ssaoSize);
vec2 noiseUVMult = vec2 (vec2(ssaoSize) / noiseDim);
noiseUVMult *= threadUV;
// sample from the noise
vec3 randomVec = texture(noiseTexture, noiseUVMult).rgb;
// Gram schmidt
vec3 tangent = normalize (randomVec - (viewSpaceNormal * dot(viewSpaceNormal, randomVec)));
vec3 bitangent = normalize (cross (tangent, viewSpaceNormal));
// matrix for tangent space to view space
mat3 TBN = mat3(tangent, bitangent, viewSpaceNormal);
float occlusion = 0.0f;
for (int i = 0; i < NUM_SAMPLES; ++i)
{
// We want to get a position at an offset from the view space position. Offset scaled by radius.
vec3 displacementVector = TBN * ssaoData.samples[i].rgb;
// Why are we adding positions?
displacementVector = viewSpacePos + displacementVector * RADIUS;
// Now we take that offset position and bring it to clip space
vec4 offsetPos = vec4 (displacementVector, 1.0f);
offsetPos = cameraData.projMat * offsetPos;
// then we do perspective division
offsetPos.xyz /= offsetPos.w;
// and bring it from [-1, 1] to screen coordinates
offsetPos.xyz = ((offsetPos.xyz * 0.5f) + 0.5f);
offsetPos.xy *= vec2(ssaoSize.xy);
// Now we attempt to get a position at that point.
float sampleDepth = imageLoad (positions, ivec2 (offsetPos.xy)).z;
// skip checks
if (sampleDepth == 0.0f)
continue;
// if sampled fragment is in front of current fragment, just occlude
float rangeCheck = smoothstep (0.0f, 1.0f, RADIUS / abs (viewSpacePos.z - sampleDepth));
occlusion += (sampleDepth <= displacementVector.z - BIAS ? 1.0f : 0.0f) * rangeCheck;
}
occlusion = 1.0f - (occlusion / float(NUM_SAMPLES));
// store result into result image
imageStore(outputImage, globalThread, occlusion.rrrr);
}

Binary file not shown.

View File

@ -0,0 +1,3 @@
Name: SSAO_CS
ID: 38430899
Type: 2

View File

@ -33,18 +33,31 @@ layout(set = 2, binding = 0) uniform CameraData
{ {
vec4 position; vec4 position;
mat4 vpMat; mat4 vpMat;
mat4 viewMat;
mat4 projMat;
} cameraData; } cameraData;
void main() void main()
{ {
Out2.materialIndex = gl_InstanceIndex; Out2.materialIndex = gl_InstanceIndex;
Out2.eid = integerData[0]; Out2.eid = integerData[0];
Out2.lightLayerIndex = integerData[1]; Out2.lightLayerIndex = integerData[1];
Out.vertPos = worldTransform * vec4(aVertexPos, 1.0f); // for transforming gBuffer position and normal data
mat4 modelViewMat = cameraData.viewMat * worldTransform;
// gBuffer position will be in view space
Out.vertPos = modelViewMat * vec4(aVertexPos, 1.0f);
// uvs for texturing in fragment shader
Out.uv = aUV; Out.uv = aUV;
Out.normal.rgb = mat3(transpose(inverse(worldTransform))) * aNormal.rgb;
mat3 transposeInv = mat3 (transpose(inverse(modelViewMat)));
// normals are also in view space
Out.normal.rgb = transposeInv * aNormal.rgb;
Out.normal.rgb = normalize (Out.normal.rgb); Out.normal.rgb = normalize (Out.normal.rgb);
// clip space for rendering
gl_Position = cameraData.vpMat * worldTransform * vec4 (aVertexPos, 1.0f); gl_Position = cameraData.vpMat * worldTransform * vec4 (aVertexPos, 1.0f);
} }

Binary file not shown.

View File

@ -73,6 +73,9 @@ namespace Sandbox
SHSystemManager::CreateSystem<SHCameraSystem>(); SHSystemManager::CreateSystem<SHCameraSystem>();
SHSystemManager::CreateSystem<SHDebugDrawSystem>(); SHSystemManager::CreateSystem<SHDebugDrawSystem>();
// Link up SHDebugDraw
SHDebugDraw::Init(SHSystemManager::GetSystem<SHDebugDrawSystem>());
#ifdef SHEDITOR #ifdef SHEDITOR
SDL_Init(SDL_INIT_VIDEO); SDL_Init(SDL_INIT_VIDEO);
sdlWindow = SDL_CreateWindowFrom(window.GetHWND()); sdlWindow = SDL_CreateWindowFrom(window.GetHWND());
@ -91,6 +94,7 @@ namespace Sandbox
SHSystemManager::RegisterRoutine<SHPhysicsSystem, SHPhysicsSystem::PhysicsPreUpdate>(); SHSystemManager::RegisterRoutine<SHPhysicsSystem, SHPhysicsSystem::PhysicsPreUpdate>();
SHSystemManager::RegisterRoutine<SHPhysicsSystem, SHPhysicsSystem::PhysicsFixedUpdate>(); SHSystemManager::RegisterRoutine<SHPhysicsSystem, SHPhysicsSystem::PhysicsFixedUpdate>();
SHSystemManager::RegisterRoutine<SHPhysicsSystem, SHPhysicsSystem::PhysicsPostUpdate>(); SHSystemManager::RegisterRoutine<SHPhysicsSystem, SHPhysicsSystem::PhysicsPostUpdate>();
SHSystemManager::RegisterRoutine<SHPhysicsSystem, SHPhysicsSystem::PhysicsDebugDraw>();
SHSystemManager::RegisterRoutine<SHTransformSystem, SHTransformSystem::TransformPostPhysicsUpdate>(); SHSystemManager::RegisterRoutine<SHTransformSystem, SHTransformSystem::TransformPostPhysicsUpdate>();
SHSystemManager::RegisterRoutine<SHDebugDrawSystem, SHDebugDrawSystem::ProcessPointsRoutine>(); SHSystemManager::RegisterRoutine<SHDebugDrawSystem, SHDebugDrawSystem::ProcessPointsRoutine>();
@ -148,6 +152,13 @@ namespace Sandbox
#endif #endif
SHSystemManager::RunRoutines(editor->editorState != SHEditor::State::PLAY, 0.016f); SHSystemManager::RunRoutines(editor->editorState != SHEditor::State::PLAY, 0.016f);
editor->PollPicking(); editor->PollPicking();
static bool drawColliders = false;
if (SHInputManager::GetKeyDown(SHInputManager::SH_KEYCODE::SPACE))
{
drawColliders = !drawColliders;
SHSystemManager::GetSystem<SHPhysicsSystem>()->SetDrawColliders(drawColliders);
}
} }
// Finish all graphics jobs first // Finish all graphics jobs first
graphicsSystem->AwaitGraphicsExecution(); graphicsSystem->AwaitGraphicsExecution();

View File

@ -269,7 +269,7 @@ namespace SHADE
{ {
const SHVec3& TF_WORLD_SCALE = transformComponent->GetWorldScale(); const SHVec3& TF_WORLD_SCALE = transformComponent->GetWorldScale();
const float MAX_SCALE = SHMath::Max({ TF_WORLD_SCALE.x, TF_WORLD_SCALE.y, TF_WORLD_SCALE.z }); const float MAX_SCALE = SHMath::Max({ TF_WORLD_SCALE.x, TF_WORLD_SCALE.y, TF_WORLD_SCALE.z });
return sphere->GetRadius() / MAX_SCALE; return (sphere->GetRadius() / MAX_SCALE) * 2.0f;
}, },
[collider](float const& value) { collider->SetBoundingSphere(value); }); [collider](float const& value) { collider->SetBoundingSphere(value); });
} }
@ -277,6 +277,7 @@ namespace SHADE
{ {
} }
{ {
SHEditorWidgets::BeginPanel("Offsets",{ ImGui::GetContentRegionAvail().x, 30.0f }); SHEditorWidgets::BeginPanel("Offsets",{ ImGui::GetContentRegionAvail().x, 30.0f });
SHEditorWidgets::DragVec3("Position", { "X", "Y", "Z" }, [&collider] {return collider->GetPositionOffset(); }, [&collider](SHVec3 const& vec) {collider->SetPositionOffset(vec); }); SHEditorWidgets::DragVec3("Position", { "X", "Y", "Z" }, [&collider] {return collider->GetPositionOffset(); }, [&collider](SHVec3 const& vec) {collider->SetPositionOffset(vec); });
@ -301,6 +302,9 @@ namespace SHADE
}); });
SHEditorWidgets::EndPanel(); SHEditorWidgets::EndPanel();
} }
SHEditorWidgets::CheckBox("Is Trigger", [collider] { return collider->IsTrigger(); }, [collider](bool value) { collider->SetIsTrigger(value); });
if (ImGui::Button(std::format("{} Remove Collider #{}", ICON_MD_REMOVE, i).data())) if (ImGui::Button(std::format("{} Remove Collider #{}", ICON_MD_REMOVE, i).data()))
{ {
colliderToDelete = i; colliderToDelete = i;

View File

@ -46,6 +46,7 @@
#include <backends/imgui_impl_vulkan.h> #include <backends/imgui_impl_vulkan.h>
#include "Graphics/MiddleEnd/Interface/SHMousePickSystem.h" #include "Graphics/MiddleEnd/Interface/SHMousePickSystem.h"
#include "Tools/SHDebugDraw.h"
RTTR_REGISTRATION RTTR_REGISTRATION
{ {
@ -77,7 +78,6 @@ namespace SHADE
//#==============================================================# //#==============================================================#
void SHEditor::Init() void SHEditor::Init()
{ {
IMGUI_CHECKVERSION(); IMGUI_CHECKVERSION();
if(auto context = ImGui::CreateContext()) if(auto context = ImGui::CreateContext())
{ {
@ -120,6 +120,17 @@ namespace SHADE
window->Init(); window->Init();
} }
/* Editor View Gridlines */
SetUpGridLines(true, true);
// Handle state changes so that we only show in edit mode
std::shared_ptr<SHEventReceiverSpec<SHEditor>> stateChangeEventReceiver
{
std::make_shared<SHEventReceiverSpec<SHEditor>>(this, &SHEditor::onEditorStateChanged)
};
SHEventManager::SubscribeTo(SH_EDITOR_ON_PLAY_EVENT, std::dynamic_pointer_cast<SHEventReceiver>(stateChangeEventReceiver));
SHEventManager::SubscribeTo(SH_EDITOR_ON_PAUSE_EVENT, std::dynamic_pointer_cast<SHEventReceiver>(stateChangeEventReceiver));
SHEventManager::SubscribeTo(SH_EDITOR_ON_STOP_EVENT, std::dynamic_pointer_cast<SHEventReceiver>(stateChangeEventReceiver));
SHLOG_INFO("Successfully initialised SHADE Engine Editor") SHLOG_INFO("Successfully initialised SHADE Engine Editor")
} }
@ -180,6 +191,97 @@ namespace SHADE
io->Fonts->Build(); io->Fonts->Build();
} }
void SHEditor::SetUpGridLines(bool drawGrid, bool drawAxes)
{
// Clear existing lines
SHDebugDraw::ClearPersistentDraws();
static constexpr float DELTA = 1.0f;
static constexpr int EXTENT_COUNT = static_cast<int>(500.0f /* TODO: Remove hard code */ / DELTA);
static constexpr float LINE_HALF_LENGTH = (DELTA * static_cast<float>(EXTENT_COUNT)) * 0.5f;
// Render Grid
static const SHColour GRID_COL = { 0.2f, 0.2f, 0.2f, 1.0f };
if (drawGrid)
{
for (int i = 1; i < EXTENT_COUNT; ++i)
{
// X-Axis Lines
SHDebugDraw::PersistentLine
(
GRID_COL,
SHVec3 { -LINE_HALF_LENGTH, 0.0f, i * DELTA },
SHVec3 { LINE_HALF_LENGTH, 0.0f, i * DELTA }
);
SHDebugDraw::PersistentLine
(
GRID_COL,
SHVec3 { -LINE_HALF_LENGTH, 0.0f, i * -DELTA },
SHVec3 { LINE_HALF_LENGTH, 0.0f, i * -DELTA }
);
// Y-Axis Lines
SHDebugDraw::PersistentLine
(
GRID_COL,
SHVec3 { i * DELTA, 0.0f, -LINE_HALF_LENGTH },
SHVec3 { i * DELTA, 0.0f, LINE_HALF_LENGTH }
);
SHDebugDraw::PersistentLine
(
GRID_COL,
SHVec3 { -i * DELTA, 0.0f, -LINE_HALF_LENGTH },
SHVec3 { -i * DELTA, 0.0f, LINE_HALF_LENGTH }
);
}
}
// Render World Axes
if (drawAxes || drawGrid)
{
const SHColour X_AXIS_COL = drawAxes ? SHColour::RED : GRID_COL;
const SHColour Y_AXIS_COL = drawAxes ? SHColour::GREEN : GRID_COL;
const SHColour Z_AXIS_COL = drawAxes ? SHColour::BLUE : GRID_COL;
// X
SHDebugDraw::PersistentLine
(
X_AXIS_COL,
SHVec3 { -LINE_HALF_LENGTH, 0.0f, 0.0f },
SHVec3 { LINE_HALF_LENGTH, 0.0f, 0.0f }
);
// Y
SHDebugDraw::PersistentLine
(
Y_AXIS_COL,
SHVec3 { 0.0f, -LINE_HALF_LENGTH, 0.0f },
SHVec3 { 0.0f, LINE_HALF_LENGTH, 0.0f }
);
// Z
SHDebugDraw::PersistentLine
(
Z_AXIS_COL,
SHVec3 { 0.0f, 0.0f, -LINE_HALF_LENGTH },
SHVec3 { 0.0f, 0.0f, LINE_HALF_LENGTH }
);
}
}
SHEventHandle SHEditor::onEditorStateChanged(SHEventPtr eventPtr)
{
auto eventData = reinterpret_cast<const SHEventSpec<SHEditorStateChangeEvent>*>(eventPtr.get());
switch (editorState)
{
case State::PAUSE:
case State::STOP:
SetUpGridLines(true, true);
break;
case State::PLAY:
default:
SHDebugDraw::ClearPersistentDraws();
break;
}
return eventData->handle;
}
void SHEditor::Exit() void SHEditor::Exit()
{ {
for (const auto& window : SHEditorWindowManager::editorWindows | std::views::values) for (const auto& window : SHEditorWindowManager::editorWindows | std::views::values)

View File

@ -16,8 +16,9 @@
#include "Resource/SHHandle.h" #include "Resource/SHHandle.h"
#include "EditorWindow/SHEditorWindow.h" #include "EditorWindow/SHEditorWindow.h"
#include "Tools/SHLog.h" #include "Tools/SHLog.h"
#include "Gizmos/SHTransformGizmo.h" #include "Gizmos/SHTransformGizmo.h"`
#include "Events/SHEventDefines.h"
#include "Events/SHEvent.h"
//#==============================================================# //#==============================================================#
//|| Library Includes || //|| Library Includes ||
@ -194,6 +195,10 @@ namespace SHADE
void InitFonts() noexcept; void InitFonts() noexcept;
void SetUpGridLines(bool drawGrid, bool drawAxes);
SHEventHandle onEditorStateChanged(SHEventPtr eventPtr);
// Handle to command pool used for ImGui Vulkan Backend // Handle to command pool used for ImGui Vulkan Backend
Handle<SHVkCommandPool> imguiCommandPool; Handle<SHVkCommandPool> imguiCommandPool;
// Handle to command buffer used for ImGui Vulkan Backend // Handle to command buffer used for ImGui Vulkan Backend

View File

@ -157,7 +157,7 @@ namespace SHADE
if (isHovered) if (isHovered)
*isHovered = ImGui::IsItemHovered(); *isHovered = ImGui::IsItemHovered();
ImGui::SameLine(); ImGui::SameLine();
return ImGui::Checkbox("#", &value); return ImGui::Checkbox("##", &value);
} }
bool SHEditorUI::InputInt(const std::string& label, int& value, bool* isHovered) bool SHEditorUI::InputInt(const std::string& label, int& value, bool* isHovered)
{ {
@ -165,7 +165,7 @@ namespace SHADE
if (isHovered) if (isHovered)
*isHovered = ImGui::IsItemHovered(); *isHovered = ImGui::IsItemHovered();
ImGui::SameLine(); ImGui::SameLine();
return ImGui::InputInt("#", &value, return ImGui::InputInt("##", &value,
1, 10, 1, 10,
ImGuiInputTextFlags_EnterReturnsTrue); ImGuiInputTextFlags_EnterReturnsTrue);
} }
@ -176,7 +176,7 @@ namespace SHADE
if (isHovered) if (isHovered)
*isHovered = ImGui::IsItemHovered(); *isHovered = ImGui::IsItemHovered();
ImGui::SameLine(); ImGui::SameLine();
const bool CHANGED = InputInt("#", signedVal); const bool CHANGED = InputInt("##", signedVal);
if (CHANGED) if (CHANGED)
{ {
signedVal = std::clamp(signedVal, 0, std::numeric_limits<int>::max()); signedVal = std::clamp(signedVal, 0, std::numeric_limits<int>::max());
@ -190,7 +190,7 @@ namespace SHADE
if (isHovered) if (isHovered)
*isHovered = ImGui::IsItemHovered(); *isHovered = ImGui::IsItemHovered();
ImGui::SameLine(); ImGui::SameLine();
return ImGui::InputFloat("#", &value, return ImGui::InputFloat("##", &value,
0.1f, 1.0f, "%.3f", 0.1f, 1.0f, "%.3f",
ImGuiInputTextFlags_EnterReturnsTrue); ImGuiInputTextFlags_EnterReturnsTrue);
} }
@ -200,7 +200,7 @@ namespace SHADE
if (isHovered) if (isHovered)
*isHovered = ImGui::IsItemHovered(); *isHovered = ImGui::IsItemHovered();
ImGui::SameLine(); ImGui::SameLine();
return ImGui::InputDouble("#", &value, return ImGui::InputDouble("##", &value,
0.1, 1.0, "%.3f", 0.1, 1.0, "%.3f",
ImGuiInputTextFlags_EnterReturnsTrue); ImGuiInputTextFlags_EnterReturnsTrue);
} }
@ -210,7 +210,7 @@ namespace SHADE
if (isHovered) if (isHovered)
*isHovered = ImGui::IsItemHovered(); *isHovered = ImGui::IsItemHovered();
ImGui::SameLine(); ImGui::SameLine();
return ImGui::InputDouble("#", &value, return ImGui::InputDouble("##", &value,
1.0, 45.0, "%.3f", 1.0, 45.0, "%.3f",
ImGuiInputTextFlags_EnterReturnsTrue); ImGuiInputTextFlags_EnterReturnsTrue);
} }
@ -280,7 +280,7 @@ namespace SHADE
if (isHovered) if (isHovered)
*isHovered = ImGui::IsItemHovered(); *isHovered = ImGui::IsItemHovered();
ImGui::SameLine(); ImGui::SameLine();
const bool CHANGED = ImGui::InputText("#", &buffer[0], TEXT_FIELD_MAX_LENGTH); const bool CHANGED = ImGui::InputText("##", &buffer[0], TEXT_FIELD_MAX_LENGTH);
if (CHANGED) if (CHANGED)
{ {
value = std::string(buffer.data(), buffer.data() + TEXT_FIELD_MAX_LENGTH); value = std::string(buffer.data(), buffer.data() + TEXT_FIELD_MAX_LENGTH);
@ -327,7 +327,7 @@ namespace SHADE
if (isHovered) if (isHovered)
*isHovered = ImGui::IsItemHovered(); *isHovered = ImGui::IsItemHovered();
ImGui::SameLine(); ImGui::SameLine();
if (ImGui::BeginCombo("#", INITIAL_NAME.c_str(), ImGuiComboFlags_None)) if (ImGui::BeginCombo("##", INITIAL_NAME.c_str(), ImGuiComboFlags_None))
{ {
for (int i = 0; i < enumNames.size(); ++i) for (int i = 0; i < enumNames.size(); ++i)
{ {

View File

@ -64,6 +64,11 @@ namespace SHADE
return bufferUsageFlags; return bufferUsageFlags;
} }
uint32_t SHVkBuffer::GetSizeStored(void) const noexcept
{
return sizeStored;
}
/***************************************************************************/ /***************************************************************************/
/*! /*!

View File

@ -104,6 +104,7 @@ namespace SHADE
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
vk::Buffer GetVkBuffer (void) const noexcept; vk::Buffer GetVkBuffer (void) const noexcept;
vk::BufferUsageFlags GetUsageBits(void) const noexcept; vk::BufferUsageFlags GetUsageBits(void) const noexcept;
uint32_t GetSizeStored (void) const noexcept;
template <typename T> template <typename T>
T GetDataFromMappedPointer(uint32_t index) const noexcept T GetDataFromMappedPointer(uint32_t index) const noexcept

View File

@ -119,6 +119,18 @@ namespace SHADE
return setIndex; return setIndex;
} }
uint32_t SHVkDescriptorSetLayout::GetNumDynamicOffsetsRequired(void) const noexcept
{
uint32_t numDynamicBindings = 0;
for (auto& binding : layoutDesc)
{
if (binding.Type == vk::DescriptorType::eUniformBufferDynamic || binding.Type == vk::DescriptorType::eStorageBufferDynamic)
++numDynamicBindings;
}
return numDynamicBindings;
}
SHVkDescriptorSetLayout& SHVkDescriptorSetLayout::operator=(SHVkDescriptorSetLayout&& rhs) noexcept SHVkDescriptorSetLayout& SHVkDescriptorSetLayout::operator=(SHVkDescriptorSetLayout&& rhs) noexcept
{ {
if (&rhs == this) if (&rhs == this)

View File

@ -99,6 +99,7 @@ namespace SHADE
inline const vk::DescriptorSetLayout& GetVkHandle() const { return setLayout; } inline const vk::DescriptorSetLayout& GetVkHandle() const { return setLayout; }
std::vector<Binding> const& GetBindings (void) const noexcept; std::vector<Binding> const& GetBindings (void) const noexcept;
SetIndex GetSetIndex (void) const noexcept; SetIndex GetSetIndex (void) const noexcept;
uint32_t GetNumDynamicOffsetsRequired (void) const noexcept;
private: private:
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/

View File

@ -79,7 +79,7 @@ namespace SHADE
SHVkDescriptorSetLayout::Binding cameraDataBinding SHVkDescriptorSetLayout::Binding cameraDataBinding
{ {
.Type = vk::DescriptorType::eUniformBufferDynamic, .Type = vk::DescriptorType::eUniformBufferDynamic,
.Stage = vk::ShaderStageFlagBits::eVertex, .Stage = vk::ShaderStageFlagBits::eVertex | vk::ShaderStageFlagBits::eCompute,
.BindPoint = SHGraphicsConstants::DescriptorSetBindings::CAMERA_DATA, .BindPoint = SHGraphicsConstants::DescriptorSetBindings::CAMERA_DATA,
.DescriptorCount = 1, .DescriptorCount = 1,
}; };

View File

@ -43,11 +43,14 @@ namespace SHADE
return; return;
} }
// Get the system
SHDebugDrawSystem* system = static_cast<SHDebugDrawSystem*>(GetSystem());
// Get current frame index // Get current frame index
const uint32_t FRAME_IDX = gfxSys->GetCurrentFrameIndex(); const uint32_t FRAME_IDX = gfxSys->GetCurrentFrameIndex();
// Create the buffer if it doesn't exist or just update it /* Non-Persistent Buffer */
SHDebugDrawSystem* system = static_cast<SHDebugDrawSystem*>(GetSystem()); // Update the buffer
system->numPoints[FRAME_IDX] = system->points.size(); system->numPoints[FRAME_IDX] = system->points.size();
const uint32_t DATA_SIZE = sizeof(PointVertex) * system->points.size(); const uint32_t DATA_SIZE = sizeof(PointVertex) * system->points.size();
if (DATA_SIZE > 0) if (DATA_SIZE > 0)
@ -57,6 +60,24 @@ namespace SHADE
// Reset for next frame // Reset for next frame
system->points.clear(); system->points.clear();
/* Persistent Buffer */
// Check if there are changes
if (system->persistentBuffersCleared[FRAME_IDX]
||
system->numPersistentPoints[FRAME_IDX] != system->persistentPoints.size())
{
// Update Buffer
system->numPersistentPoints[FRAME_IDX] = system->persistentPoints.size();
const uint32_t DATA_SIZE = sizeof(PointVertex) * system->persistentPoints.size();
if (DATA_SIZE > 0)
{
system->persistentVertexBuffers[FRAME_IDX]->WriteToMemory(system->persistentPoints.data(), DATA_SIZE, 0, 0);
}
// Reset Flag
system->persistentBuffersCleared[FRAME_IDX] = false;
}
} }
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
@ -75,19 +96,38 @@ namespace SHADE
const uint32_t FRAME_IDX = GFX_SYSTEM->GetCurrentFrameIndex(); const uint32_t FRAME_IDX = GFX_SYSTEM->GetCurrentFrameIndex();
// Don't draw if no points // Don't draw if no points
if (numPoints[FRAME_IDX] <= 0) if (numPoints[FRAME_IDX] > 0)
return; {
cmdBuffer->BindPipeline(GFX_SYSTEM->GetDebugDrawPipeline()); cmdBuffer->BindPipeline(GFX_SYSTEM->GetDebugDrawPipeline());
cmdBuffer->SetLineWidth(LineWidth); cmdBuffer->SetLineWidth(LineWidth);
cmdBuffer->BindVertexBuffer(0, vertexBuffers[FRAME_IDX], 0); cmdBuffer->BindVertexBuffer(0, vertexBuffers[FRAME_IDX], 0);
cmdBuffer->DrawArrays(numPoints[FRAME_IDX], 1, 0, 0); cmdBuffer->DrawArrays(numPoints[FRAME_IDX], 1, 0, 0);
}
});
auto subPassWithDepth = renderGraph->GetNode("Debug Draw with Depth")->GetSubpass("Debug Draw with Depth");
subPassWithDepth->AddExteriorDrawCalls([this, GFX_SYSTEM](Handle<SHVkCommandBuffer>& cmdBuffer)
{
// Get Current frame index
const uint32_t FRAME_IDX = GFX_SYSTEM->GetCurrentFrameIndex();
// Don't draw if no points
if (numPersistentPoints[FRAME_IDX] > 0)
{
cmdBuffer->BindPipeline(GFX_SYSTEM->GetDebugDrawDepthPipeline());
cmdBuffer->SetLineWidth(LineWidth);
cmdBuffer->BindVertexBuffer(0, persistentVertexBuffers[FRAME_IDX], 0);
cmdBuffer->DrawArrays(numPersistentPoints[FRAME_IDX], 1, 0, 0);
}
}); });
// Reset trackers // Reset trackers
std::fill_n(numPoints.begin(), numPoints.size(), 0); std::fill_n(numPoints.begin(), numPoints.size(), 0);
std::fill_n(numPersistentPoints.begin(), numPersistentPoints.size(), 0);
for (bool& cleared : persistentBuffersCleared)
cleared = true;
// Allocate buffers // Allocate buffers
// - Non-Persistent Draws
static constexpr uint32_t BUFFER_SIZE = MAX_POINTS * sizeof(PointVertex); static constexpr uint32_t BUFFER_SIZE = MAX_POINTS * sizeof(PointVertex);
for (Handle<SHVkBuffer>& bufHandle : vertexBuffers) for (Handle<SHVkBuffer>& bufHandle : vertexBuffers)
{ {
@ -101,6 +141,19 @@ namespace SHADE
VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_MAPPED_BIT VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_MAPPED_BIT
); );
} }
// - Persistent Draws
for (Handle<SHVkBuffer>& bufHandle : persistentVertexBuffers)
{
bufHandle = GFX_SYSTEM->GetDevice()->CreateBuffer
(
BUFFER_SIZE,
nullptr,
0,
vk::BufferUsageFlagBits::eVertexBuffer,
VmaMemoryUsage::VMA_MEMORY_USAGE_AUTO,
VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_MAPPED_BIT
);
}
} }
void SHDebugDrawSystem::Exit() void SHDebugDrawSystem::Exit()
@ -110,6 +163,11 @@ namespace SHADE
if (vertexBuffer) if (vertexBuffer)
vertexBuffer.Free(); vertexBuffer.Free();
} }
for (auto vertexBuffer : persistentVertexBuffers)
{
if (vertexBuffer)
vertexBuffer.Free();
}
} }
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
@ -117,42 +175,107 @@ namespace SHADE
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
void SHDebugDrawSystem::DrawLine(const SHVec4& color, const SHVec3& startPt, const SHVec3& endPt) void SHDebugDrawSystem::DrawLine(const SHVec4& color, const SHVec3& startPt, const SHVec3& endPt)
{ {
if (points.size() > MAX_POINTS) drawLine(points, color, startPt, endPt);
}
void SHDebugDrawSystem::DrawTri(const SHVec4& color, const SHVec3& pt1, const SHVec3& pt2, const SHVec3& pt3)
{
drawPoly(points, color, { pt1, pt2, pt3 });
}
void SHDebugDrawSystem::DrawQuad(const SHVec4& color, const SHVec3& pt1, const SHVec3& pt2, const SHVec3& pt3, const SHVec3& pt4)
{
drawPoly(points, color, { pt1, pt2, pt3, pt4 });
}
void SHDebugDrawSystem::DrawPoly(const SHVec4& color, std::initializer_list<SHVec3> pointList)
{
drawPoly(points, color, pointList.begin(), pointList.end());
}
void SHDebugDrawSystem::DrawCube(const SHVec4& color, const SHVec3& pos, const SHVec3& size)
{
drawCube(points, color, pos, size);
}
void SHDebugDrawSystem::DrawSphere(const SHVec4& color, const SHVec3& pos, double radius)
{
drawSphere(points, color, pos, radius);
}
/*---------------------------------------------------------------------------------*/
/* Persistent Draw Functions */
/*---------------------------------------------------------------------------------*/
void SHDebugDrawSystem::DrawPersistentLine(const SHVec4& color, const SHVec3& startPt, const SHVec3& endPt)
{
drawLine(persistentPoints, color, startPt, endPt);
}
void SHDebugDrawSystem::DrawPersistentTri(const SHVec4& color, const SHVec3& pt1, const SHVec3& pt2, const SHVec3& pt3)
{
drawPoly(persistentPoints, color, { pt1, pt2, pt3 });
}
void SHDebugDrawSystem::DrawPersistentQuad(const SHVec4& color, const SHVec3& pt1, const SHVec3& pt2, const SHVec3& pt3, const SHVec3& pt4)
{
drawPoly(persistentPoints, color, { pt1, pt2, pt3, pt4 });
}
void SHDebugDrawSystem::DrawPersistentPoly(const SHVec4& color, std::initializer_list<SHVec3> pointList)
{
drawPoly(persistentPoints, color, pointList.begin(), pointList.end());
}
void SHDebugDrawSystem::DrawPersistentCube(const SHVec4& color, const SHVec3& pos, const SHVec3& size)
{
drawCube(persistentPoints, color, pos, size);
}
void SHDebugDrawSystem::DrawPersistentSphere(const SHVec4& color, const SHVec3& pos, double radius)
{
drawSphere(persistentPoints, color, pos, radius);
}
void SHDebugDrawSystem::ClearPersistentDraws()
{
persistentPoints.clear();
for (bool& cleared : persistentBuffersCleared)
cleared = true;
}
void SHDebugDrawSystem::drawLine(std::vector<PointVertex>& storage, const SHVec4& color, const SHVec3& startPt, const SHVec3& endPt)
{
if (storage.size() > MAX_POINTS)
{ {
SHLOG_WARNING("[DebugDraw] Exceeded maximum size of drawable debug elements."); SHLOG_WARNING("[DebugDraw] Exceeded maximum size of drawable debug elements.");
return; return;
} }
points.emplace_back(PointVertex{ startPt, color }); storage.emplace_back(PointVertex{ startPt, color });
points.emplace_back(PointVertex{ endPt, color }); storage.emplace_back(PointVertex{ endPt, color });
} }
void SHDebugDrawSystem::DrawTri(const SHVec4& color, const SHVec3& pt1, const SHVec3& pt2, const SHVec3& pt3) void SHDebugDrawSystem::drawLineSet(std::vector<PointVertex>& storage, const SHVec4& color, std::initializer_list<SHVec3> pointList)
{ {
DrawPoly(color, { pt1, pt2, pt3 }); drawLineSet(storage, color, pointList.begin(), pointList.end());
} }
void SHDebugDrawSystem::DrawQuad(const SHVec4& color, const SHVec3& pt1, const SHVec3& pt2, const SHVec3& pt3, const SHVec3& pt4) void SHDebugDrawSystem::drawPoly(std::vector<PointVertex>& storage, const SHVec4& color, std::initializer_list<SHVec3> pointList)
{ {
DrawPoly(color, { pt1, pt2, pt3, pt4 }); drawPoly(storage, color, pointList.begin(), pointList.end());
} }
void SHDebugDrawSystem::DrawPoly(const SHVec4& color, std::initializer_list<SHVec3> pointList) void SHDebugDrawSystem::drawCube(std::vector<PointVertex>& storage, const SHVec4& color, const SHVec3& pos, const SHVec3& size)
{ {
DrawPoly(color, pointList.begin(), pointList.end()); static const SHVec3 EXTENTS = SHVec3{ 0.5f, 0.5f, 0.5f };
} static const SHVec3 UNIT_BOT_LEFT_FRONT = SHVec3{ pos - EXTENTS };
static const SHVec3 UNIT_BOT_RIGHT_FRONT = SHVec3{ pos + SHVec3 { EXTENTS.x, -EXTENTS.y, -EXTENTS.z } };
void SHDebugDrawSystem::DrawCube(const SHVec4& color, const SHVec3& pos, const SHVec3& size) static const SHVec3 UNIT_BOT_RIGHT_BACK = SHVec3{ pos + SHVec3 { EXTENTS.x, -EXTENTS.y, EXTENTS.z } };
{ static const SHVec3 UNIT_BOT_LEFT_BACK = SHVec3{ pos + SHVec3 { -EXTENTS.x, -EXTENTS.y, EXTENTS.z } };
static const SHVec3 EXTENTS = SHVec3 { 0.5f, 0.5f, 0.5f }; static const SHVec3 UNIT_TOP_LEFT_BACK = SHVec3{ pos + SHVec3 { -EXTENTS.x, EXTENTS.y, EXTENTS.z } };
static const SHVec3 UNIT_BOT_LEFT_FRONT = SHVec3 { pos - EXTENTS }; static const SHVec3 UNIT_TOP_RIGHT_FRONT = SHVec3{ pos + SHVec3 { EXTENTS.x, EXTENTS.y, -EXTENTS.z } };
static const SHVec3 UNIT_BOT_RIGHT_FRONT = SHVec3 { pos + SHVec3 { EXTENTS.x, -EXTENTS.y, -EXTENTS.z } }; static const SHVec3 UNIT_TOP_LEFT_FRONT = SHVec3{ pos + SHVec3 { -EXTENTS.x, EXTENTS.y, -EXTENTS.z } };
static const SHVec3 UNIT_BOT_RIGHT_BACK = SHVec3 { pos + SHVec3 { EXTENTS.x, -EXTENTS.y, EXTENTS.z } }; static const SHVec3 UNIT_TOP_RIGHT_BACK = SHVec3{ pos + EXTENTS };
static const SHVec3 UNIT_BOT_LEFT_BACK = SHVec3 { pos + SHVec3 { -EXTENTS.x, -EXTENTS.y, EXTENTS.z } };
static const SHVec3 UNIT_TOP_LEFT_BACK = SHVec3 { pos + SHVec3 { -EXTENTS.x, EXTENTS.y, EXTENTS.z } };
static const SHVec3 UNIT_TOP_RIGHT_FRONT = SHVec3 { pos + SHVec3 { EXTENTS.x, EXTENTS.y, -EXTENTS.z } };
static const SHVec3 UNIT_TOP_LEFT_FRONT = SHVec3 { pos + SHVec3 { -EXTENTS.x, EXTENTS.y, -EXTENTS.z } };
static const SHVec3 UNIT_TOP_RIGHT_BACK = SHVec3 { pos + EXTENTS };
const SHVec3 BOT_LEFT_BACK = UNIT_BOT_LEFT_BACK * size; const SHVec3 BOT_LEFT_BACK = UNIT_BOT_LEFT_BACK * size;
const SHVec3 BOT_RIGHT_BACK = UNIT_BOT_RIGHT_BACK * size; const SHVec3 BOT_RIGHT_BACK = UNIT_BOT_RIGHT_BACK * size;
@ -163,8 +286,9 @@ namespace SHADE
const SHVec3 TOP_LEFT_FRONT = UNIT_TOP_LEFT_FRONT * size; const SHVec3 TOP_LEFT_FRONT = UNIT_TOP_LEFT_FRONT * size;
const SHVec3 TOP_RIGHT_FRONT = UNIT_TOP_RIGHT_FRONT * size; const SHVec3 TOP_RIGHT_FRONT = UNIT_TOP_RIGHT_FRONT * size;
DrawPoly drawLineSet
( (
storage,
color, color,
{ {
// Bottom Square // Bottom Square
@ -186,7 +310,7 @@ namespace SHADE
); );
} }
void SHDebugDrawSystem::DrawSphere(const SHVec4& color, const SHVec3& pos, double radius) void SHDebugDrawSystem::drawSphere(std::vector<PointVertex>& storage, const SHVec4& color, const SHVec3& pos, double radius)
{ {
if (spherePoints.empty()) if (spherePoints.empty())
{ {
@ -197,6 +321,6 @@ namespace SHADE
spherePoints.emplace_back(SPHERE.VertexPositions[idx]); spherePoints.emplace_back(SPHERE.VertexPositions[idx]);
} }
} }
DrawPoly(color, spherePoints.begin(), spherePoints.end()); drawLineSet(storage, color, spherePoints.begin(), spherePoints.end());
} }
} }

View File

@ -126,6 +126,82 @@ namespace SHADE
/// <param name="size">Size of the rendered sphere.</param> /// <param name="size">Size of the rendered sphere.</param>
void DrawSphere(const SHVec4& color, const SHVec3& pos, double radius); void DrawSphere(const SHVec4& color, const SHVec3& pos, double radius);
/*---------------------------------------------------------------------------------*/
/* Persistent Draw Functions */
/*---------------------------------------------------------------------------------*/
/// <summary>
/// Renders a line between two points in world space that will persist until
/// ClearPersistentDraws() is called. These lines are depth tested.
/// </summary>
/// <param name="color">Colour of the line.</param>
/// <param name="startPt">First point of the line.</param>
/// <param name="endPt">Second point of the line.</param>
void DrawPersistentLine(const SHVec4& color, const SHVec3& startPt, const SHVec3& endPt);
/// <summary>
/// Renders a triangle indicated by three points in world space that will persist
/// until ClearPersistentDraws() is called. These lines are depth tested.
/// </summary>
/// <param name="color">Colour of the triangle.</param>
/// <param name="pt1">First point of the triangle.</param>
/// <param name="pt2">Second point of the triangle.</param>
/// <param name="pt3">Third point of the triangle.</param>
void DrawPersistentTri(const SHVec4& color, const SHVec3& pt1, const SHVec3& pt2, const SHVec3& pt3);
/// <summary>
/// Renders a quadrilateral indicated by four points in world space that will persist
/// until ClearPersistentDraws() is called. These lines are depth tested.
/// </summary>
/// <param name="color">Colour of the quadrilateral.</param>
/// <param name="pt1">First point of the triangle.</param>
/// <param name="pt2">Second point of the quadrilateral.</param>
/// <param name="pt3">Third point of the quadrilateral.</param>
/// <param name="pt4">Third point of the quadrilateral.</param>
void DrawPersistentQuad(const SHVec4& color, const SHVec3& pt1, const SHVec3& pt2, const SHVec3& pt3, const SHVec3& pt4);
/// <summary>
/// Renders a polygon indicated by the specified set of points in world space that
/// will persist until ClearPersistentDraws() is called. These lines are depth
/// tested.
/// </summary>
/// <param name="color">Colour of the polygon.</param>
/// <param name="pointList">List of points for the polygon.</param>
void DrawPersistentPoly(const SHVec4& color, std::initializer_list<SHVec3> pointList);
/// <summary>
/// Renders a polygon indicated by the specified set of points in world space that
/// will persist until ClearPersistentDraws() is called. These lines are depth
/// tested.
/// </summary>
/// <typeparam name="IterType">Iterator for a STL-like container.</typeparam>
/// <param name="color">Colour of the polygon.</param>
/// <param name="pointListBegin">
/// Iterator to the first point of the point container.
/// </param>
/// <param name="pointListEnd">
/// One past last iterator of the point container.
/// </param>
template<typename IterType>
void DrawPersistentPoly(const SHVec4& color, IterType pointListBegin, IterType pointListEnd);
/// <summary>
/// Renders a wireframe cube centered around the position specified in world space
/// that will persist until ClearPersistentDraws() is called. These lines are depth
/// tested.
/// </summary>
/// <param name="color">Colour of the cube.</param>
/// <param name="pos">Position where the cube wil be centered at.</param>
/// <param name="size">Size of the rendered cube.</param>
void DrawPersistentCube(const SHVec4& color, const SHVec3& pos, const SHVec3& size);
/// <summary>
/// Renders a wireframe sphere centered around the position specified in world space
/// that will persist until ClearPersistentDraws() is called. These lines are depth
/// tested.
/// </summary>
/// <param name="color">Colour of the sphere.</param>
/// <param name="pos">Position where the sphere wil be centered at.</param>
/// <param name="size">Size of the rendered sphere.</param>
void DrawPersistentSphere(const SHVec4& color, const SHVec3& pos, double radius);
/// <summary>
/// Clears any persistent drawn debug primitives.
/// </summary>
void ClearPersistentDraws();
private: private:
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Type Definitions */ /* Type Definitions */
@ -136,7 +212,8 @@ namespace SHADE
SHVec4 Color; SHVec4 Color;
}; };
using TripleBuffer = std::array<Handle<SHVkBuffer>, SHGraphicsConstants::NUM_FRAME_BUFFERS>; using TripleBuffer = std::array<Handle<SHVkBuffer>, SHGraphicsConstants::NUM_FRAME_BUFFERS>;
using TripleUInt = std::array<uint32_t, SHGraphicsConstants::NUM_FRAME_BUFFERS>; using TripleUInt = std::array<uint32_t , SHGraphicsConstants::NUM_FRAME_BUFFERS>;
using TripleBool = std::array<bool , SHGraphicsConstants::NUM_FRAME_BUFFERS>;
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Constants */ /* Constants */
@ -148,11 +225,28 @@ namespace SHADE
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
// CPU Buffers // CPU Buffers
std::vector<PointVertex> points; std::vector<PointVertex> points;
std::vector<PointVertex> persistentPoints;
// GPU Buffers // GPU Buffers
TripleBuffer vertexBuffers; TripleBuffer vertexBuffers;
TripleUInt numPoints; TripleUInt numPoints;
TripleBuffer persistentVertexBuffers;
TripleUInt numPersistentPoints;
TripleBool persistentBuffersCleared;
// Cached Points for polygon drawing // Cached Points for polygon drawing
std::vector<SHVec3> spherePoints; std::vector<SHVec3> spherePoints;
/*---------------------------------------------------------------------------------*/
/* Helper Draw Functions */
/*---------------------------------------------------------------------------------*/
void drawLine(std::vector<PointVertex>& storage, const SHVec4& color, const SHVec3& startPt, const SHVec3& endPt);
void drawLineSet(std::vector<PointVertex>& storage, const SHVec4& color, std::initializer_list<SHVec3> pointList);
template<typename IterType>
void drawLineSet(std::vector<PointVertex>& storage, const SHVec4& color, IterType pointListBegin, IterType pointListEnd);
void drawPoly(std::vector<PointVertex>& storage, const SHVec4& color, std::initializer_list<SHVec3> pointList);
template<typename IterType>
void drawPoly(std::vector<PointVertex>& storage, const SHVec4& color, IterType pointListBegin, IterType pointListEnd);
void drawCube(std::vector<PointVertex>& storage, const SHVec4& color, const SHVec3& pos, const SHVec3& size);
void drawSphere(std::vector<PointVertex>& storage, const SHVec4& color, const SHVec3& pos, double radius);
}; };
} }

View File

@ -20,12 +20,21 @@ namespace SHADE
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
template<typename IterType> template<typename IterType>
void SHDebugDrawSystem::DrawPoly(const SHVec4& color, IterType pointListBegin, IterType pointListEnd) void SHDebugDrawSystem::DrawPoly(const SHVec4& color, IterType pointListBegin, IterType pointListEnd)
{
drawPoly(points, color, pointListBegin, pointListEnd);
}
/*-----------------------------------------------------------------------------------*/
/* Helper Draw Functions */
/*-----------------------------------------------------------------------------------*/
template<typename IterType>
void SHDebugDrawSystem::drawLineSet(std::vector<PointVertex>& storage, const SHVec4& color, IterType pointListBegin, IterType pointListEnd)
{ {
// Ensure dereferenced type is SHVec3 // Ensure dereferenced type is SHVec3
static_assert(std::is_same_v<SHVec3, std::remove_cvref_t<decltype(*pointListBegin)>>, "Parameters to DrawPoly must be SHVec3."); static_assert(std::is_same_v<SHVec3, std::remove_cvref_t<decltype(*pointListBegin)>>, "Parameters to DrawPoly must be SHVec3.");
// Check if points exceeded max // Check if points exceeded max
if (points.size() > MAX_POINTS) if (storage.size() > MAX_POINTS)
{ {
SHLOG_WARNING("[DebugDraw] Exceeded maximum size of drawable debug elements."); SHLOG_WARNING("[DebugDraw] Exceeded maximum size of drawable debug elements.");
return; return;
@ -42,7 +51,39 @@ namespace SHADE
const size_t POINTS_ROUNDED_COUNT = POINTS_COUNT / 2 * 2; const size_t POINTS_ROUNDED_COUNT = POINTS_COUNT / 2 * 2;
for (auto pointIter = pointListBegin; pointIter != (pointListBegin + POINTS_ROUNDED_COUNT); ++pointIter) for (auto pointIter = pointListBegin; pointIter != (pointListBegin + POINTS_ROUNDED_COUNT); ++pointIter)
{ {
points.emplace_back(PointVertex{ *pointIter, color }); storage.emplace_back(PointVertex{ *pointIter, color });
} }
} }
template<typename IterType>
void SHDebugDrawSystem::drawPoly(std::vector<PointVertex>& storage, const SHVec4& color, IterType pointListBegin, IterType pointListEnd)
{
// Ensure dereferenced type is SHVec3
static_assert(std::is_same_v<SHVec3, std::remove_cvref_t<decltype(*pointListBegin)>>, "Parameters to DrawPoly must be SHVec3.");
// Check if points exceeded max
if (storage.size() > MAX_POINTS)
{
SHLOG_WARNING("[DebugDraw] Exceeded maximum size of drawable debug elements.");
return;
}
const size_t POINTS_COUNT = pointListEnd - pointListBegin;
// Invalid polygon
if (POINTS_COUNT < 2)
{
SHLOG_WARNING("[SHDebugDraw] Invalid polygon provided to DrawPoly().");
return;
}
// Trace the polygon
for (auto pointIter = pointListBegin + 1; pointIter != pointListEnd; ++pointIter)
{
storage.emplace_back(PointVertex{ *(pointIter - 1), color });
storage.emplace_back(PointVertex{ *pointIter , color });
}
// Close the line loop
storage.emplace_back(PointVertex{ *(pointListEnd - 1), color });
storage.emplace_back(PointVertex{ *pointListBegin , color });
}
} }

View File

@ -70,7 +70,17 @@ namespace SHADE
*/ */
/***************************************************************************/ /***************************************************************************/
static constexpr uint32_t RENDERGRAPH_RESOURCE = 4; 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, 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;
}; };
@ -119,6 +129,7 @@ namespace SHADE
*/ */
/***************************************************************************/ /***************************************************************************/
static constexpr uint32_t BATCHED_PER_INST_DATA = 0; static constexpr uint32_t BATCHED_PER_INST_DATA = 0;
}; };
struct VertexBufferBindings struct VertexBufferBindings

View File

@ -40,6 +40,7 @@ of DigiPen Institute of Technology is prohibited.
#include "Assets/SHAssetManager.h" #include "Assets/SHAssetManager.h"
#include "Resource/SHResourceManager.h" #include "Resource/SHResourceManager.h"
#include "Graphics/SHVkUtil.h" #include "Graphics/SHVkUtil.h"
#include "Graphics/RenderGraph/SHRenderGraphNodeCompute.h"
namespace SHADE namespace SHADE
{ {
@ -115,6 +116,8 @@ namespace SHADE
static constexpr AssetID VS_DEBUG = 48002439; debugVertShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(VS_DEBUG); static constexpr AssetID VS_DEBUG = 48002439; debugVertShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(VS_DEBUG);
static constexpr AssetID FS_DEBUG = 36671027; debugFragShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(FS_DEBUG); static constexpr AssetID FS_DEBUG = 36671027; debugFragShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(FS_DEBUG);
static constexpr AssetID CS_COMPOSITE = 45072428; deferredCompositeShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(CS_COMPOSITE); static constexpr AssetID CS_COMPOSITE = 45072428; deferredCompositeShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(CS_COMPOSITE);
static constexpr AssetID SSAO = 38430899; ssaoShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(SSAO);
static constexpr AssetID SSAO_BLUR = 39760835; ssaoBlurShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(SSAO_BLUR);
} }
void SHGraphicsSystem::InitSceneRenderGraph(void) noexcept void SHGraphicsSystem::InitSceneRenderGraph(void) noexcept
@ -153,52 +156,109 @@ namespace SHADE
renderContextCmdPools[i] = renderContext.GetFrameData(i).cmdPoolHdls[0]; renderContextCmdPools[i] = renderContext.GetFrameData(i).cmdPoolHdls[0];
} }
/*-----------------------------------------------------------------------*/
/* SCENE RENDER GRAPH RESOURCES */
/*-----------------------------------------------------------------------*/
// Initialize world render graph // Initialize world render graph
worldRenderGraph->Init(device, swapchain); worldRenderGraph->Init(device, swapchain);
worldRenderGraph->AddResource("Position", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second, vk::Format::eR32G32B32A32Sfloat); worldRenderGraph->AddResource("Position", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second, vk::Format::eR32G32B32A32Sfloat);
worldRenderGraph->AddResource("Normals", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second, vk::Format::eR32G32B32A32Sfloat); worldRenderGraph->AddResource("Normals", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second, vk::Format::eR32G32B32A32Sfloat);
//worldRenderGraph->AddResource("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);
worldRenderGraph->AddResource("Albedo", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second); worldRenderGraph->AddResource("Albedo", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second);
worldRenderGraph->AddResource("Depth Buffer", { SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL }, windowDims.first, windowDims.second, vk::Format::eD32SfloatS8Uint); worldRenderGraph->AddResource("Depth Buffer", { SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL }, windowDims.first, windowDims.second, vk::Format::eD32SfloatS8Uint);
worldRenderGraph->AddResource("Entity ID", { SH_ATT_DESC_TYPE_FLAGS::COLOR }, windowDims.first, windowDims.second, vk::Format::eR32Uint, 1, vk::ImageUsageFlagBits::eTransferSrc); worldRenderGraph->AddResource("Entity ID", { SH_ATT_DESC_TYPE_FLAGS::COLOR }, windowDims.first, windowDims.second, vk::Format::eR32Uint, 1, vk::ImageUsageFlagBits::eTransferSrc);
worldRenderGraph->AddResource("Light Layer Indices", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second, vk::Format::eR32Uint, 1, vk::ImageUsageFlagBits::eTransferSrc); worldRenderGraph->AddResource("Light Layer Indices", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second, vk::Format::eR32Uint, 1, vk::ImageUsageFlagBits::eTransferSrc);
worldRenderGraph->AddResource("Scene", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second); worldRenderGraph->AddResource("Scene", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second);
worldRenderGraph->AddResource("SSAO", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second, vk::Format::eR8Unorm);
worldRenderGraph->AddResource("SSAO Blur", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second, vk::Format::eR8Unorm);
/*-----------------------------------------------------------------------*/
/* MAIN NODE */
/*-----------------------------------------------------------------------*/
auto gBufferNode = worldRenderGraph->AddNode("G-Buffer", auto gBufferNode = worldRenderGraph->AddNode("G-Buffer",
{ {
"Position", "Position",
"Entity ID", "Entity ID",
"Light Layer Indices", "Light Layer Indices",
"Normals", "Normals",
//"Tangents",
"Albedo", "Albedo",
"Depth Buffer", "Depth Buffer",
"Scene" "Scene",
"SSAO",
"SSAO Blur"
}, },
{}); // no predecessors {}); // no predecessors
/*-----------------------------------------------------------------------*/
/* G-BUFFER SUBPASS INIT */
/*-----------------------------------------------------------------------*/
auto gBufferSubpass = gBufferNode->AddSubpass("G-Buffer Write"); auto gBufferSubpass = gBufferNode->AddSubpass("G-Buffer Write");
gBufferSubpass->AddColorOutput("Position"); gBufferSubpass->AddColorOutput("Position");
gBufferSubpass->AddColorOutput("Entity ID"); gBufferSubpass->AddColorOutput("Entity ID");
gBufferSubpass->AddColorOutput("Light Layer Indices"); gBufferSubpass->AddColorOutput("Light Layer Indices");
gBufferSubpass->AddColorOutput("Normals"); gBufferSubpass->AddColorOutput("Normals");
//gBufferSubpass->AddColorOutput("Tangents");
gBufferSubpass->AddColorOutput("Albedo"); gBufferSubpass->AddColorOutput("Albedo");
gBufferSubpass->AddDepthOutput("Depth Buffer", SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL); gBufferSubpass->AddDepthOutput("Depth Buffer", SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL);
// deferred composite /*-----------------------------------------------------------------------*/
gBufferNode->AddNodeCompute(deferredCompositeShader, { "Position", "Normals", "Albedo", "Light Layer Indices", "Scene" }); /* SSAO PASS AND DATA INIT */
/*-----------------------------------------------------------------------*/
ssaoStorage = resourceManager.Create<SHSSAO>();
// Set up Debug Draw Pass ssaoTransferCmdBuffer = graphicsCmdPool->RequestCommandBuffer(SH_CMD_BUFFER_TYPE::PRIMARY);
auto debugDrawNode = worldRenderGraph->AddNode("Debug Draw", { "Scene" }, {"G-Buffer"}); ssaoTransferCmdBuffer->BeginRecording();
ssaoStorage->Init(device, ssaoTransferCmdBuffer);
ssaoTransferCmdBuffer->EndRecording();
graphicsQueue->SubmitCommandBuffer({ ssaoTransferCmdBuffer });
// Set up Debug Draw Passes
// - Depth Tested
auto debugDrawNodeDepth = worldRenderGraph->AddNode("Debug Draw with Depth", { "Scene", "Depth Buffer" }, {"G-Buffer"});
auto debugDrawDepthSubpass = debugDrawNodeDepth->AddSubpass("Debug Draw with Depth");
debugDrawDepthSubpass->AddColorOutput("Scene");
debugDrawDepthSubpass->AddDepthOutput("Depth Buffer");
// - No Depth Test
auto debugDrawNode = worldRenderGraph->AddNode("Debug Draw", { "Scene" }, { "Debug Draw with Depth" });
auto debugDrawSubpass = debugDrawNode->AddSubpass("Debug Draw"); auto debugDrawSubpass = debugDrawNode->AddSubpass("Debug Draw");
debugDrawSubpass->AddColorOutput("Scene"); debugDrawSubpass->AddColorOutput("Scene");
graphicsQueue->WaitIdle();
ssaoStorage->PrepareRotationVectorsVkData(device);
Handle<SHRenderGraphNodeCompute> ssaoPass = gBufferNode->AddNodeCompute(ssaoShader, {"Position", "Normals", "SSAO"});
auto ssaoDataBuffer = ssaoStorage->GetBuffer();
ssaoPass->ModifyWriteDescBufferComputeResource(SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_NODE_COMPUTE_RESOURCE, SHSSAO::DESC_SET_BUFFER_BINDING, { &ssaoDataBuffer, 1 }, 0, ssaoStorage->GetBuffer()->GetSizeStored());
auto viewSamplerLayout = ssaoStorage->GetViewSamplerLayout();
ssaoPass->ModifyWriteDescImageComputeResource(SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_NODE_COMPUTE_RESOURCE, SHSSAO::DESC_SET_IMAGE_BINDING, {&viewSamplerLayout, 1});
Handle<SHRenderGraphNodeCompute> ssaoBlurPass = gBufferNode->AddNodeCompute(ssaoBlurShader, { "SSAO", "SSAO Blur"});
/*-----------------------------------------------------------------------*/
/* DEFERRED COMPOSITE SUBPASS INIT */
/*-----------------------------------------------------------------------*/
gBufferNode->AddNodeCompute(deferredCompositeShader, { "Position", "Normals", "Albedo", "Light Layer Indices", "SSAO Blur", "Scene" });
// Dummy Node // Dummy Node
auto dummyNode = worldRenderGraph->AddNode("Dummy Pass", { "Scene" }, { "Debug Draw" }); // no predecessors auto dummyNode = worldRenderGraph->AddNode("Dummy Pass", { "Scene" }, { "Debug Draw" }); // no predecessors
auto dummySubpass = dummyNode->AddSubpass("Dummy Subpass"); auto dummySubpass = dummyNode->AddSubpass("Dummy Subpass");
dummySubpass->AddInput("Scene"); dummySubpass->AddInput("Scene");
/*-----------------------------------------------------------------------*/
/* GENERATE RENDER GRAPH */
/*-----------------------------------------------------------------------*/
// Generate world render graph // Generate world render graph
worldRenderGraph->Generate(); worldRenderGraph->Generate();
/*-----------------------------------------------------------------------*/
/* BIND RENDER GRAPH TO RENDERER */
/*-----------------------------------------------------------------------*/
// Add world renderer to default viewport // Add world renderer to default viewport
worldRenderer = worldViewport->AddRenderer(resourceManager, swapchain->GetNumImages(), renderContextCmdPools, descPool, SHGraphicsGlobalData::GetDescSetLayouts()[SHGraphicsConstants::DescriptorSetIndex::HIGH_FREQUENCY_GLOBALS], worldRenderGraph); worldRenderer = worldViewport->AddRenderer(resourceManager, swapchain->GetNumImages(), renderContextCmdPools, descPool, SHGraphicsGlobalData::GetDescSetLayouts()[SHGraphicsConstants::DescriptorSetIndex::HIGH_FREQUENCY_GLOBALS], worldRenderGraph);
worldRenderer->SetCamera(worldCamera); worldRenderer->SetCamera(worldCamera);
@ -209,53 +269,8 @@ namespace SHADE
defaultMaterial = AddMaterial(defaultVertShader, defaultFragShader, gBufferSubpass); defaultMaterial = AddMaterial(defaultVertShader, defaultFragShader, gBufferSubpass);
// Create debug draw pipeline // Create debug draw pipeline
auto debugDrawPipelineLayout = resourceManager.Create<SHVkPipelineLayout> debugDrawPipeline = createDebugDrawPipeline(debugDrawNode->GetRenderpass(), debugDrawSubpass);
( debugDrawDepthPipeline = createDebugDrawPipeline(debugDrawNodeDepth->GetRenderpass(), debugDrawDepthSubpass);
device, SHPipelineLayoutParams
{
.shaderModules = { debugVertShader, debugFragShader },
.globalDescSetLayouts = SHGraphicsGlobalData::GetDescSetLayouts()
}
);
debugDrawPipeline = resourceManager.Create<SHVkPipeline>(device, debugDrawPipelineLayout, nullptr, debugDrawNode->GetRenderpass(), debugDrawSubpass);
debugDrawPipeline->GetPipelineState().SetRasterizationState(SHRasterizationState
{
.polygonMode = vk::PolygonMode::eLine,
.cull_mode = vk::CullModeFlagBits::eNone
});
debugDrawPipeline->GetPipelineState().SetInputAssemblyState(SHInputAssemblyState
{
.topology = vk::PrimitiveTopology::eLineList
});
SHVertexInputState debugDrawVertexInputState;
debugDrawVertexInputState.AddBinding(false, true, { SHVertexAttribute(SHAttribFormat::FLOAT_4D), SHVertexAttribute(SHAttribFormat::FLOAT_4D) });
debugDrawPipeline->GetPipelineState().SetVertexInputState(debugDrawVertexInputState);
SHColorBlendState colorBlendState{};
colorBlendState.logic_op_enable = VK_FALSE;
colorBlendState.logic_op = vk::LogicOp::eCopy;
auto const& subpassColorReferences = debugDrawSubpass->GetColorAttachmentReferences();
colorBlendState.attachments.reserve(subpassColorReferences.size());
for (auto& att : subpassColorReferences)
{
colorBlendState.attachments.push_back(vk::PipelineColorBlendAttachmentState
{
.blendEnable = SHVkUtil::IsBlendCompatible(debugDrawSubpass->GetFormatFromAttachmentReference(att.attachment)),
.srcColorBlendFactor = vk::BlendFactor::eSrcAlpha,
.dstColorBlendFactor = vk::BlendFactor::eOneMinusSrcAlpha,
.colorBlendOp = vk::BlendOp::eAdd,
.srcAlphaBlendFactor = vk::BlendFactor::eOne,
.dstAlphaBlendFactor = vk::BlendFactor::eZero,
.alphaBlendOp = vk::BlendOp::eAdd,
.colorWriteMask = vk::ColorComponentFlagBits::eR | vk::ColorComponentFlagBits::eG | vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eA,
}
);
}
debugDrawPipeline->GetPipelineState().SetColorBlenState(colorBlendState);
debugDrawPipeline->ConstructPipeline();
} }
void SHGraphicsSystem::InitMiddleEnd(void) noexcept void SHGraphicsSystem::InitMiddleEnd(void) noexcept
@ -294,6 +309,7 @@ namespace SHADE
lightingSubSystem = resourceManager.Create<SHLightingSubSystem>(); lightingSubSystem = resourceManager.Create<SHLightingSubSystem>();
lightingSubSystem->Init(device, descPool); lightingSubSystem->Init(device, descPool);
} }
#ifdef SHEDITOR #ifdef SHEDITOR
@ -399,6 +415,17 @@ namespace SHADE
auto cameraSystem = SHSystemManager::GetSystem<SHCameraSystem>(); auto cameraSystem = SHSystemManager::GetSystem<SHCameraSystem>();
{
#ifdef SHEDITOR
auto editorSystem = SHSystemManager::GetSystem<SHEditor>();
if (editorSystem->editorState != SHEditor::State::PLAY)
lightingSubSystem->Run(cameraSystem->GetEditorCamera()->GetViewMatrix(), frameIndex);
else
lightingSubSystem->Run(worldRenderer->GetCameraDirector()->GetViewMatrix(), frameIndex);
#else
lightingSubSystem->Run(worldRenderer->GetCameraDirector()->GetViewMatrix(), frameIndex);
#endif
}
// For every viewport // For every viewport
for (int vpIndex = 0; vpIndex < static_cast<int>(viewports.size()); ++vpIndex) for (int vpIndex = 0; vpIndex < static_cast<int>(viewports.size()); ++vpIndex)
@ -435,8 +462,7 @@ namespace SHADE
currentCmdBuffer->BindIndexBuffer(buffer, 0); currentCmdBuffer->BindIndexBuffer(buffer, 0);
} }
// Bind the descriptor set for lights lightingSubSystem->BindDescSet(currentCmdBuffer, frameIndex);
lightingSubSystem->Run(currentCmdBuffer, frameIndex);
// Bind textures // Bind textures
auto textureDescSet = texLibrary.GetTextureDescriptorSetGroup(); auto textureDescSet = texLibrary.GetTextureDescriptorSetGroup();
@ -460,7 +486,7 @@ namespace SHADE
{ {
auto editorSystem = SHSystemManager::GetSystem<SHEditor>(); auto editorSystem = SHSystemManager::GetSystem<SHEditor>();
if (editorSystem->editorState != SHEditor::State::PLAY) if (editorSystem->editorState != SHEditor::State::PLAY)
worldRenderer->UpdateDataAndBind(currentCmdBuffer, frameIndex, SHMatrix::Transpose(cameraSystem->GetEditorCamera()->GetProjMatrix() * cameraSystem->GetEditorCamera()->GetViewMatrix())); worldRenderer->UpdateDataAndBind(currentCmdBuffer, frameIndex, cameraSystem->GetEditorCamera()->GetViewMatrix(), cameraSystem->GetEditorCamera()->GetProjMatrix());
else else
renderers[renIndex]->UpdateDataAndBind(currentCmdBuffer, frameIndex); renderers[renIndex]->UpdateDataAndBind(currentCmdBuffer, frameIndex);
} }
@ -867,5 +893,57 @@ namespace SHADE
return worldRenderGraph->GetNode(G_BUFFER_RENDER_GRAPH_NODE_NAME.data()); return worldRenderGraph->GetNode(G_BUFFER_RENDER_GRAPH_NODE_NAME.data());
} }
Handle<SHVkPipeline> SHGraphicsSystem::createDebugDrawPipeline(Handle<SHVkRenderpass> renderPass, Handle<SHSubpass> subpass)
{
auto pipelineLayout = resourceManager.Create<SHVkPipelineLayout>
(
device, SHPipelineLayoutParams
{
.shaderModules = { debugVertShader, debugFragShader },
.globalDescSetLayouts = SHGraphicsGlobalData::GetDescSetLayouts()
}
);
auto pipeline = resourceManager.Create<SHVkPipeline>(device, pipelineLayout, nullptr, renderPass, subpass);
pipeline->GetPipelineState().SetRasterizationState(SHRasterizationState
{
.polygonMode = vk::PolygonMode::eLine,
.cull_mode = vk::CullModeFlagBits::eNone
});
pipeline->GetPipelineState().SetInputAssemblyState(SHInputAssemblyState
{
.topology = vk::PrimitiveTopology::eLineList
});
SHVertexInputState debugDrawVertexInputState;
debugDrawVertexInputState.AddBinding(false, true, { SHVertexAttribute(SHAttribFormat::FLOAT_4D), SHVertexAttribute(SHAttribFormat::FLOAT_4D) });
pipeline->GetPipelineState().SetVertexInputState(debugDrawVertexInputState);
SHColorBlendState colorBlendState{};
colorBlendState.logic_op_enable = VK_FALSE;
colorBlendState.logic_op = vk::LogicOp::eCopy;
auto const& subpassColorReferences = subpass->GetColorAttachmentReferences();
colorBlendState.attachments.reserve(subpassColorReferences.size());
for (auto& att : subpassColorReferences)
{
colorBlendState.attachments.push_back(vk::PipelineColorBlendAttachmentState
{
.blendEnable = SHVkUtil::IsBlendCompatible(subpass->GetFormatFromAttachmentReference(att.attachment)),
.srcColorBlendFactor = vk::BlendFactor::eSrcAlpha,
.dstColorBlendFactor = vk::BlendFactor::eOneMinusSrcAlpha,
.colorBlendOp = vk::BlendOp::eAdd,
.srcAlphaBlendFactor = vk::BlendFactor::eOne,
.dstAlphaBlendFactor = vk::BlendFactor::eZero,
.alphaBlendOp = vk::BlendOp::eAdd,
.colorWriteMask = vk::ColorComponentFlagBits::eR | vk::ColorComponentFlagBits::eG | vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eA,
});
}
pipeline->GetPipelineState().SetColorBlenState(colorBlendState);
pipeline->ConstructPipeline();
return pipeline;
}
#pragma endregion MISC #pragma endregion MISC
} }

View File

@ -31,6 +31,7 @@ of DigiPen Institute of Technology is prohibited.
#include "../Textures/SHVkSamplerCache.h" #include "../Textures/SHVkSamplerCache.h"
#include "Graphics/MiddleEnd/Interface/SHPostOffscreenRenderSystem.h" #include "Graphics/MiddleEnd/Interface/SHPostOffscreenRenderSystem.h"
#include "Graphics/MiddleEnd/Lights/SHLightingSubSystem.h" #include "Graphics/MiddleEnd/Lights/SHLightingSubSystem.h"
#include "Graphics/MiddleEnd/PostProcessing/SHSSAO.h"
namespace SHADE namespace SHADE
{ {
@ -289,6 +290,7 @@ namespace SHADE
Handle<SHPostOffscreenRenderSystem> GetPostOffscreenRenderSystem(void) const noexcept {return postOffscreenRender;}; Handle<SHPostOffscreenRenderSystem> GetPostOffscreenRenderSystem(void) const noexcept {return postOffscreenRender;};
Handle<SHRenderGraphNode> GetPrimaryRenderpass() const noexcept; Handle<SHRenderGraphNode> GetPrimaryRenderpass() const noexcept;
Handle<SHVkPipeline> GetDebugDrawPipeline(void) const noexcept { return debugDrawPipeline; } Handle<SHVkPipeline> GetDebugDrawPipeline(void) const noexcept { return debugDrawPipeline; }
Handle<SHVkPipeline> GetDebugDrawDepthPipeline(void) const noexcept { return debugDrawDepthPipeline; }
uint32_t GetCurrentFrameIndex(void) const noexcept { return renderContext.GetCurrentFrame(); } uint32_t GetCurrentFrameIndex(void) const noexcept { return renderContext.GetCurrentFrame(); }
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
@ -315,6 +317,7 @@ namespace SHADE
Handle<SHVkDescriptorPool> descPool; Handle<SHVkDescriptorPool> descPool;
Handle<SHVkCommandPool> graphicsCmdPool; Handle<SHVkCommandPool> graphicsCmdPool;
Handle<SHVkCommandBuffer> transferCmdBuffer; Handle<SHVkCommandBuffer> transferCmdBuffer;
Handle<SHVkCommandBuffer> ssaoTransferCmdBuffer;
Handle<SHVkCommandBuffer> graphicsTexCmdBuffer; Handle<SHVkCommandBuffer> graphicsTexCmdBuffer;
SHRenderContext renderContext; SHRenderContext renderContext;
std::array<Handle<SHVkSemaphore>, 2> graphSemaphores; std::array<Handle<SHVkSemaphore>, 2> graphSemaphores;
@ -351,10 +354,14 @@ namespace SHADE
Handle<SHVkShaderModule> debugVertShader; Handle<SHVkShaderModule> debugVertShader;
Handle<SHVkShaderModule> debugFragShader; Handle<SHVkShaderModule> debugFragShader;
Handle<SHVkShaderModule> deferredCompositeShader; Handle<SHVkShaderModule> deferredCompositeShader;
Handle<SHVkShaderModule> ssaoShader;
Handle<SHVkShaderModule> ssaoBlurShader;
// Built-In Materials // Built-In Materials
Handle<SHMaterial> defaultMaterial; Handle<SHMaterial> defaultMaterial;
Handle<SHVkPipeline> debugDrawPipeline; Handle<SHVkPipeline> debugDrawPipeline;
Handle<SHVkPipeline> debugDrawDepthPipeline;
Handle<SHRenderGraph> worldRenderGraph; Handle<SHRenderGraph> worldRenderGraph;
@ -362,10 +369,15 @@ namespace SHADE
Handle<SHMousePickSystem> mousePickSystem; Handle<SHMousePickSystem> mousePickSystem;
Handle<SHPostOffscreenRenderSystem> postOffscreenRender; Handle<SHPostOffscreenRenderSystem> postOffscreenRender;
Handle<SHLightingSubSystem> lightingSubSystem; Handle<SHLightingSubSystem> lightingSubSystem;
Handle<SHSSAO> ssaoStorage;
uint32_t resizeWidth; uint32_t resizeWidth = 1;
uint32_t resizeHeight; uint32_t resizeHeight = 1;
bool restoredFromMinimize = false; bool restoredFromMinimize = false;
/*---------------------------------------------------------------------------------*/
/* Helper Functions */
/*---------------------------------------------------------------------------------*/
Handle<SHVkPipeline> createDebugDrawPipeline(Handle<SHVkRenderpass> renderPass, Handle<SHSubpass> subpass);
}; };
} }

View File

@ -83,13 +83,14 @@ namespace SHADE
{ {
if (camera && cameraDirector) if (camera && cameraDirector)
{ {
UpdateDataAndBind(cmdBuffer, frameIndex, SHMatrix::Transpose(cameraDirector->GetVPMatrix())); //UpdateDataAndBind(cmdBuffer, frameIndex, SHMatrix::Transpose(cameraDirector->GetVPMatrix()));
UpdateDataAndBind(cmdBuffer, frameIndex, cameraDirector->GetViewMatrix(), cameraDirector->GetProjMatrix());
} }
} }
void SHRenderer::UpdateDataAndBind(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex, SHMatrix exteriorMatrix) noexcept void SHRenderer::UpdateDataAndBind(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex, SHMatrix const& viewMatrix, SHMatrix const& projMatrix) noexcept
{ {
SetViewProjectionMatrix(exteriorMatrix); SetViewProjectionMatrix(viewMatrix, projMatrix);
//cpuCameraData.viewProjectionMatrix = camera->GetViewProjectionMatrix(); //cpuCameraData.viewProjectionMatrix = camera->GetViewProjectionMatrix();
cameraBuffer->WriteToMemory(&cpuCameraData, sizeof(SHShaderCameraData), 0, cameraDataAlignedSize * frameIndex); cameraBuffer->WriteToMemory(&cpuCameraData, sizeof(SHShaderCameraData), 0, cameraDataAlignedSize * frameIndex);
@ -97,16 +98,19 @@ namespace SHADE
std::array<uint32_t, 1> dynamicOffsets{ frameIndex * cameraDataAlignedSize }; std::array<uint32_t, 1> dynamicOffsets{ frameIndex * cameraDataAlignedSize };
cmdBuffer->BindDescriptorSet(cameraDescriptorSet, SH_PIPELINE_TYPE::GRAPHICS, SHGraphicsConstants::DescriptorSetIndex::HIGH_FREQUENCY_GLOBALS, std::span{ dynamicOffsets.data(), 1 }); cmdBuffer->BindDescriptorSet(cameraDescriptorSet, SH_PIPELINE_TYPE::GRAPHICS, SHGraphicsConstants::DescriptorSetIndex::HIGH_FREQUENCY_GLOBALS, std::span{ dynamicOffsets.data(), 1 });
cmdBuffer->BindDescriptorSet(cameraDescriptorSet, SH_PIPELINE_TYPE::COMPUTE, SHGraphicsConstants::DescriptorSetIndex::HIGH_FREQUENCY_GLOBALS, std::span{ dynamicOffsets.data(), 1 });
} }
void SHRenderer::UpdateCameraDataToBuffer(void) noexcept void SHRenderer::UpdateCameraDataToBuffer(void) noexcept
{ {
} }
void SHRenderer::SetViewProjectionMatrix(SHMatrix const& vpMatrix) noexcept void SHRenderer::SetViewProjectionMatrix(SHMatrix const& viewMatrix, SHMatrix const& projMatrix) noexcept
{ {
//cpuCameraData.viewProjectionMatrix = camera->GetViewMatrix() * camera->GetProjectionMatrix(); //cpuCameraData.viewProjectionMatrix = camera->GetViewMatrix() * camera->GetProjectionMatrix();
cpuCameraData.viewProjectionMatrix = vpMatrix; cpuCameraData.viewProjectionMatrix = SHMatrix::Transpose(projMatrix * viewMatrix);
cpuCameraData.viewMatrix = SHMatrix::Transpose(viewMatrix);
cpuCameraData.projectionMatrix = SHMatrix::Transpose(projMatrix);
} }
Handle<SHRenderGraph> SHRenderer::GetRenderGraph(void) const noexcept Handle<SHRenderGraph> SHRenderer::GetRenderGraph(void) const noexcept
@ -119,4 +123,9 @@ namespace SHADE
return commandBuffers[frameIndex]; return commandBuffers[frameIndex];
} }
Handle<SHCameraDirector> SHRenderer::GetCameraDirector(void) const noexcept
{
return cameraDirector;
}
} }

View File

@ -46,6 +46,8 @@ namespace SHADE
{ {
SHVec4 cameraPosition; SHVec4 cameraPosition;
SHMatrix viewProjectionMatrix; SHMatrix viewProjectionMatrix;
SHMatrix viewMatrix;
SHMatrix projectionMatrix;
}; };
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
@ -79,15 +81,16 @@ namespace SHADE
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
void Draw(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool) noexcept; void Draw(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool) noexcept;
void UpdateDataAndBind(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept; void UpdateDataAndBind(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept;
void UpdateDataAndBind(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex, SHMatrix exteriorMatrix) noexcept; void UpdateDataAndBind(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex, SHMatrix const& viewMatrix, SHMatrix const& projMatrix) noexcept;
void UpdateCameraDataToBuffer (void) noexcept; void UpdateCameraDataToBuffer (void) noexcept;
void SetViewProjectionMatrix (SHMatrix const& vpMatrix) noexcept; void SetViewProjectionMatrix (SHMatrix const& viewMatrix, SHMatrix const& projMatrix) noexcept;
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* Setters and Getters */ /* Setters and Getters */
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
Handle<SHRenderGraph> GetRenderGraph (void) const noexcept; Handle<SHRenderGraph> GetRenderGraph (void) const noexcept;
Handle<SHVkCommandBuffer> GetCommandBuffer(uint32_t frameIndex) const noexcept; Handle<SHVkCommandBuffer> GetCommandBuffer(uint32_t frameIndex) const noexcept;
Handle<SHCameraDirector> GetCameraDirector (void) const noexcept;
private: private:
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/

View File

@ -9,9 +9,9 @@ namespace SHADE
{ {
lightData.Reset(); lightData.Reset();
SetType(SH_LIGHT_TYPE::DIRECTIONAL); SetType(SH_LIGHT_TYPE::DIRECTIONAL);
indexInBuffer = std::numeric_limits<uint32_t>::max(); //indexInBuffer = std::numeric_limits<uint32_t>::max();
isActive = true; isActive = true;
Unbind(); //Unbind();
} }
@ -23,28 +23,28 @@ namespace SHADE
void SHLightComponent::SetPosition(SHVec3 const& position) noexcept void SHLightComponent::SetPosition(SHVec3 const& position) noexcept
{ {
lightData.position = position; lightData.position = position;
MakeDirty(); //MakeDirty();
} }
void SHLightComponent::SetType(SH_LIGHT_TYPE type) noexcept void SHLightComponent::SetType(SH_LIGHT_TYPE type) noexcept
{ {
lightData.type = type; lightData.type = type;
MakeDirty(); //MakeDirty();
} }
void SHLightComponent::SetDirection(SHVec3 const& direction) noexcept void SHLightComponent::SetDirection(SHVec3 const& direction) noexcept
{ {
lightData.direction = direction; lightData.direction = direction;
MakeDirty(); //MakeDirty();
} }
void SHLightComponent::SetColor(SHVec4 const& color) noexcept void SHLightComponent::SetColor(SHVec4 const& color) noexcept
{ {
lightData.color = color; lightData.color = color;
MakeDirty(); //MakeDirty();
} }
void SHLightComponent::ModifyCullingMask(uint8_t layerIndex, bool value) noexcept void SHLightComponent::ModifyCullingMask(uint8_t layerIndex, bool value) noexcept
@ -54,7 +54,7 @@ namespace SHADE
else else
lightData.cullingMask &= ~(1u << layerIndex); lightData.cullingMask &= ~(1u << layerIndex);
MakeDirty(); //MakeDirty();
} }
void SHLightComponent::SetCullingMask(uint32_t const& value) noexcept void SHLightComponent::SetCullingMask(uint32_t const& value) noexcept
@ -65,43 +65,43 @@ namespace SHADE
void SHLightComponent::SetAllLayers(void) noexcept void SHLightComponent::SetAllLayers(void) noexcept
{ {
lightData.cullingMask = std::numeric_limits<uint32_t>::max(); lightData.cullingMask = std::numeric_limits<uint32_t>::max();
MakeDirty(); //MakeDirty();
} }
void SHLightComponent::ClearAllLayers(void) noexcept void SHLightComponent::ClearAllLayers(void) noexcept
{ {
lightData.cullingMask = 0; lightData.cullingMask = 0;
MakeDirty(); //MakeDirty();
} }
void SHLightComponent::MakeDirty(void) noexcept //void SHLightComponent::MakeDirty(void) noexcept
{ //{
dirty = true; // dirty = true;
} //}
void SHLightComponent::ClearDirtyFlag(void) noexcept //void SHLightComponent::ClearDirtyFlag(void) noexcept
{ //{
dirty = false; // dirty = false;
} //}
void SHLightComponent::Unbind(void) noexcept // void SHLightComponent::Unbind(void) noexcept
{ // {
bound = false; // bound = false;
MakeDirty(); // MakeDirty();
} // }
//
void SHLightComponent::SetBound(uint32_t inIndexInBuffer) noexcept // void SHLightComponent::SetBound(uint32_t inIndexInBuffer) noexcept
{ //{
bound = true; // bound = true;
indexInBuffer = inIndexInBuffer; // indexInBuffer = inIndexInBuffer;
} // }
void SHLightComponent::SetStrength(float value) noexcept void SHLightComponent::SetStrength(float value) noexcept
{ {
lightData.strength = value; lightData.strength = value;
MakeDirty(); //MakeDirty();
} }
SHLightData const& SHLightComponent::GetLightData(void) const noexcept SHLightData const& SHLightComponent::GetLightData(void) const noexcept
@ -135,20 +135,20 @@ namespace SHADE
} }
bool SHLightComponent::IsDirty(void) const noexcept //bool SHLightComponent::IsDirty(void) const noexcept
{ //{
return dirty; // return dirty;
} //}
bool SHLightComponent::GetBound(void) const noexcept //bool SHLightComponent::GetBound(void) const noexcept
{ //{
return bound; // return bound;
} //}
uint32_t SHLightComponent::GetIndexInBuffer(void) const noexcept //uint32_t SHLightComponent::GetIndexInBuffer(void) const noexcept
{ //{
return indexInBuffer; // return indexInBuffer;
} //}
float SHLightComponent::GetStrength(void) const noexcept float SHLightComponent::GetStrength(void) const noexcept
{ {

View File

@ -17,13 +17,13 @@ namespace SHADE
//! Since the lighting system is gonna be self contained and light weight, we store this //! 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 //! 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. //! rewrite everything. However we still write to the GPU buffer when everything changes.
uint32_t indexInBuffer; //uint32_t indexInBuffer;
//! If the light component changed some value we mark this true. ////! If the light component changed some value we mark this true.
bool dirty; //bool dirty;
//! If the light's data is already in the buffers, this will be set to true. ////! If the light's data is already in the buffers, this will be set to true.
bool bound; //bool bound;
public: public:
@ -44,10 +44,10 @@ namespace SHADE
void SetCullingMask (uint32_t const& value) noexcept; void SetCullingMask (uint32_t const& value) noexcept;
void SetAllLayers (void) noexcept; // serialized void SetAllLayers (void) noexcept; // serialized
void ClearAllLayers (void) noexcept; // serialized void ClearAllLayers (void) noexcept; // serialized
void MakeDirty (void) noexcept; //void MakeDirty (void) noexcept;
void ClearDirtyFlag (void) noexcept; //void ClearDirtyFlag (void) noexcept;
void Unbind (void) noexcept; //void Unbind (void) noexcept;
void SetBound (uint32_t inIndexInBuffer) noexcept; //void SetBound (uint32_t inIndexInBuffer) noexcept;
void SetStrength (float value) noexcept; // serialized void SetStrength (float value) noexcept; // serialized
@ -57,8 +57,8 @@ namespace SHADE
SHVec3 const& GetDirection (void) const noexcept; // serialized SHVec3 const& GetDirection (void) const noexcept; // serialized
SHVec4 const& GetColor (void) const noexcept; // serialized SHVec4 const& GetColor (void) const noexcept; // serialized
uint32_t const& GetCullingMask (void) const noexcept; // serialized uint32_t const& GetCullingMask (void) const noexcept; // serialized
bool IsDirty (void) const noexcept; //bool IsDirty (void) const noexcept;
bool GetBound (void) const noexcept; //bool GetBound (void) const noexcept;
uint32_t GetIndexInBuffer (void) const noexcept; uint32_t GetIndexInBuffer (void) const noexcept;
float GetStrength (void) const noexcept; float GetStrength (void) const noexcept;
RTTR_ENABLE() RTTR_ENABLE()

View File

@ -8,6 +8,8 @@
#include "SHLightComponent.h" #include "SHLightComponent.h"
#include "ECS_Base/Managers/SHComponentManager.h" #include "ECS_Base/Managers/SHComponentManager.h"
#include "SHLightComponent.h" #include "SHLightComponent.h"
#include "Math/Vector/SHVec4.h"
#include "Math/SHMatrix.h"
namespace SHADE namespace SHADE
{ {
@ -31,7 +33,7 @@ namespace SHADE
*/ */
/***************************************************************************/ /***************************************************************************/
void SHLightingSubSystem::PerTypeData::WriteLightToAddress(void* address, SHLightComponent* lightComp) noexcept void SHLightingSubSystem::PerTypeData::WriteLightToAddress(void* address, SHMatrix const& viewMat, SHLightComponent* lightComp) noexcept
{ {
auto const& lightData = lightComp->GetLightData(); auto const& lightData = lightComp->GetLightData();
switch (lightData.type) switch (lightData.type)
@ -40,8 +42,12 @@ namespace SHADE
{ {
SHDirectionalLightData* lightPtr = reinterpret_cast<SHDirectionalLightData*>(address); SHDirectionalLightData* lightPtr = reinterpret_cast<SHDirectionalLightData*>(address);
// #NoteToSelf: NEED TO TRANSPOSE HERE BECAUSE MULTIPLICATION IS ROW MAJOR.
SHVec4 transformedDir = SHMatrix::Transpose(viewMat) * SHVec4(lightData.direction[0], lightData.direction[1], lightData.direction[2], 0.0f);
lightPtr->cullingMask = lightData.cullingMask; lightPtr->cullingMask = lightData.cullingMask;
lightPtr->direction = lightData.direction; lightPtr->direction = SHVec3 (transformedDir.x, transformedDir.y, transformedDir.z);
//lightPtr->direction = lightData.direction;
lightPtr->diffuseColor = lightData.color; lightPtr->diffuseColor = lightData.color;
lightPtr->active = lightComp->isActive; lightPtr->active = lightComp->isActive;
break; break;
@ -240,7 +246,7 @@ namespace SHADE
*/ */
/***************************************************************************/ /***************************************************************************/
void SHLightingSubSystem::PerTypeData::AddLight(Handle<SHVkLogicalDevice> logicalDevice, SHLightComponent* unboundLight, bool expanded) noexcept void SHLightingSubSystem::PerTypeData::AddLight(Handle<SHVkLogicalDevice> logicalDevice, SHLightComponent* unboundLight, SHMatrix const& viewMat, bool& expanded) noexcept
{ {
if (unboundLight) if (unboundLight)
{ {
@ -259,10 +265,10 @@ namespace SHADE
void* writeLocation = reinterpret_cast<uint8_t*>(intermediateData.get()) + (lightDataAlignedSize * numLights); void* writeLocation = reinterpret_cast<uint8_t*>(intermediateData.get()) + (lightDataAlignedSize * numLights);
// Write the light data to address // Write the light data to address
WriteLightToAddress(writeLocation, unboundLight); WriteLightToAddress(writeLocation, viewMat, unboundLight);
// Set the light component to be bound to that location // Set the light component to be bound to that location
unboundLight->SetBound(numLights); //unboundLight->SetBound(numLights);
// Increase light count // Increase light count
++numLights; ++numLights;
@ -280,11 +286,11 @@ namespace SHADE
*/ */
/***************************************************************************/ /***************************************************************************/
void SHLightingSubSystem::PerTypeData::ModifyLight(SHLightComponent* lightComp) noexcept //void SHLightingSubSystem::PerTypeData::ModifyLight(SHLightComponent* lightComp) noexcept
{ //{
void* writeLocation = reinterpret_cast<uint8_t*>(intermediateData.get()) + (lightDataAlignedSize * lightComp->GetIndexInBuffer()); // void* writeLocation = reinterpret_cast<uint8_t*>(intermediateData.get()) + (lightDataAlignedSize * lightComp->GetIndexInBuffer());
WriteLightToAddress(writeLocation, lightComp); // WriteLightToAddress(writeLocation, lightComp);
} //}
void SHLightingSubSystem::PerTypeData::WriteToGPU(uint32_t frameIndex) noexcept void SHLightingSubSystem::PerTypeData::WriteToGPU(uint32_t frameIndex) noexcept
{ {
@ -406,7 +412,7 @@ namespace SHADE
dynamicOffsets[i].resize(NUM_LIGHT_TYPES + 1); // +1 for the count dynamicOffsets[i].resize(NUM_LIGHT_TYPES + 1); // +1 for the count
} }
numLightComponents = 0; //numLightComponents = 0;
} }
/***************************************************************************/ /***************************************************************************/
@ -419,21 +425,25 @@ namespace SHADE
*/ */
/***************************************************************************/ /***************************************************************************/
void SHLightingSubSystem::Run(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept void SHLightingSubSystem::Run(SHMatrix const& viewMat, uint32_t frameIndex) noexcept
{ {
static uint32_t constexpr NUM_LIGHT_TYPES = SHUtilities::ToUnderlying(SH_LIGHT_TYPE::NUM_TYPES); static uint32_t constexpr NUM_LIGHT_TYPES = SHUtilities::ToUnderlying(SH_LIGHT_TYPE::NUM_TYPES);
auto& lightComps = SHComponentManager::GetDense<SHLightComponent>(); auto& lightComps = SHComponentManager::GetDense<SHLightComponent>();
bool expanded = false; bool expanded = false;
bool rewrite = false;
if (numLightComponents > lightComps.size()) // First we reset the number of lights. We do this every frame so that we can count how many lights we have
{
rewrite = true;
ResetNumLights(); ResetNumLights();
}
numLightComponents = lightComps.size(); //bool rewrite = false;
//if (numLightComponents > lightComps.size())
//{
// rewrite = true;
// ResetNumLights();
//}
//numLightComponents = lightComps.size();
for (auto& light : lightComps) for (auto& light : lightComps)
{ {
@ -441,22 +451,22 @@ namespace SHADE
// First we want to make sure the light is already bound to the system. if it // First we want to make sure the light is already bound to the system. if it
// isn't, we write it to the correct buffer. // isn't, we write it to the correct buffer.
if (!light.GetBound() || rewrite) //if (!light.GetBound() || rewrite)
{ {
perTypeData[enumValue].AddLight(logicalDevice, &light, expanded); perTypeData[enumValue].AddLight(logicalDevice, &light, viewMat, expanded);
//// add to light count // add to light count
//++lightCountsData[enumValue]; //++lightCountsData[enumValue];
} }
// if there was modification to the light data // if there was modification to the light data
if (light.IsDirty()) //if (light.IsDirty())
{ {
// Write the data to the CPU // Write the data to the CPU
perTypeData[enumValue].ModifyLight(&light); //perTypeData[enumValue].ModifyLight(&light);
// Light is now updated in the container // Light is now updated in the container
light.ClearDirtyFlag(); //light.ClearDirtyFlag();
} }
} }
@ -488,8 +498,6 @@ namespace SHADE
// so we do it anyway. #NoteToSelf: if at any point it affects performance, do a check before computing. // so we do it anyway. #NoteToSelf: if at any point it affects performance, do a check before computing.
ComputeDynamicOffsets(); ComputeDynamicOffsets();
// Bind descriptor set (We bind at an offset because the buffer holds NUM_FRAME_BUFFERS sets of data).
cmdBuffer->BindDescriptorSet(lightingDataDescSet, SH_PIPELINE_TYPE::COMPUTE, SHGraphicsConstants::DescriptorSetIndex::DYNAMIC_GLOBALS, {dynamicOffsets[frameIndex]});
} }
@ -505,4 +513,12 @@ namespace SHADE
{ {
} }
void SHLightingSubSystem::BindDescSet(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept
{
//Bind descriptor set(We bind at an offset because the buffer holds NUM_FRAME_BUFFERS sets of data).
cmdBuffer->BindDescriptorSet(lightingDataDescSet, SH_PIPELINE_TYPE::COMPUTE, SHGraphicsConstants::DescriptorSetIndex::DYNAMIC_GLOBALS, { dynamicOffsets[frameIndex] });
}
} }

View File

@ -95,15 +95,15 @@ namespace SHADE
//! to the GPU that stores NUM_FRAME_BUFFERS copies. //! to the GPU that stores NUM_FRAME_BUFFERS copies.
std::unique_ptr<uint8_t[]> intermediateData; std::unique_ptr<uint8_t[]> intermediateData;
void WriteLightToAddress (void* address, SHLightComponent* lightComp) noexcept; void WriteLightToAddress (void* address, SHMatrix const& viewMat, SHLightComponent* lightComp) noexcept;
public: public:
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* PUBLIC MEMBER FUNCTIONS */ /* PUBLIC MEMBER FUNCTIONS */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
void InitializeData (Handle<SHVkLogicalDevice> logicalDevice, SH_LIGHT_TYPE type) noexcept; void InitializeData (Handle<SHVkLogicalDevice> logicalDevice, SH_LIGHT_TYPE type) noexcept;
void Expand (Handle<SHVkLogicalDevice> logicalDevice) noexcept; void Expand (Handle<SHVkLogicalDevice> logicalDevice) noexcept;
void AddLight (Handle<SHVkLogicalDevice> logicalDevice, SHLightComponent* unboundLight, bool expanded) noexcept; void AddLight (Handle<SHVkLogicalDevice> logicalDevice, SHLightComponent* unboundLight, SHMatrix const& viewMat, bool& expanded) noexcept;
void ModifyLight (SHLightComponent* lightComp) noexcept; //void ModifyLight (SHLightComponent* lightComp) noexcept;
void WriteToGPU (uint32_t frameIndex) noexcept; void WriteToGPU (uint32_t frameIndex) noexcept;
void ResetNumLights (void) noexcept; void ResetNumLights (void) noexcept;
@ -144,7 +144,7 @@ namespace SHADE
//! Number of SHLightComponents recorded. If at the beginning of the run function the size returned by the dense //! 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, //! set is less than the size recorded, rewrite all light components into the its respective buffers. If its more,
//! don't do anything. //! don't do anything.
uint32_t numLightComponents; //uint32_t numLightComponents;
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* PRIVATE MEMBER FUNCTIONS */ /* PRIVATE MEMBER FUNCTIONS */
@ -159,8 +159,10 @@ namespace SHADE
/* PUBLIC MEMBER FUNCTIONS */ /* PUBLIC MEMBER FUNCTIONS */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
void Init (Handle<SHVkLogicalDevice> device, Handle<SHVkDescriptorPool> descPool) noexcept; void Init (Handle<SHVkLogicalDevice> device, Handle<SHVkDescriptorPool> descPool) noexcept;
void Run (Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept; void Run (SHMatrix const& viewMat, uint32_t frameIndex) noexcept;
void Exit (void) noexcept; void Exit (void) noexcept;
void BindDescSet (Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept;
}; };
} }

View File

@ -0,0 +1,138 @@
#include "SHpch.h"
#include "SHSSAO.h"
#include "Graphics/Devices/SHVkLogicalDevice.h"
#include "Graphics/Buffers/SHVkBuffer.h"
#include "Graphics/Images/SHVkImage.h"
#include "Graphics/Images/SHVkSampler.h"
#include <random>
namespace SHADE
{
void SHSSAO::Init(Handle<SHVkLogicalDevice> logicalDevice, Handle<SHVkCommandBuffer> cmdBuffer) noexcept
{
// Initialize a distribution to get values from 0 to 1
std::uniform_real_distribution<float> distrib{0.0f, 1.0f};
// generator for random number
std::default_random_engine generator;
// generate samples
for (uint32_t i = 0; i < NUM_SAMPLES; ++i)
{
//SHVec3 temp
//{
// distrib(generator) * 2.0f - 1.0f, // -1.0f - 1.0f
// distrib(generator) * 2.0f - 1.0f, // -1.0f - 1.0f
// distrib(generator), // 0.0f - 1.0f so that sample space is a hemisphere
//};
//temp = SHVec3::Normalise(temp);
//temp *= distrib(generator);
//// This makes sure that most points are closer to fragment's position
//float scale = 1.0f / static_cast<float>(NUM_SAMPLES);
//scale = std::lerp(0.1f, 1.0f, scale * scale);
//temp *= scale;
//samples[i] = SHVec4 (temp.x, temp.y, temp.z, 0.0f);
samples[i] = SHVec4
{
distrib(generator) * 2.0f - 1.0f, // -1.0f - 1.0f
distrib(generator) * 2.0f - 1.0f, // -1.0f - 1.0f
distrib(generator), // 0.0f - 1.0f so that sample space is a hemisphere
0.0f
};
// This makes sure that most points are closer to fragment's position
float scale = 1.0f / static_cast<float>(NUM_SAMPLES);
scale = std::lerp(0.1f, 1.0f, scale * scale);
samples[i] *= scale;
}
// generate rotation vector
for (uint32_t i = 0; i < NUM_ROTATION_VECTORS; ++i)
{
rotationVectors[i] = SHVec4
{
distrib(generator) * 2.0f - 1.0f, // -1.0f - 1.0f
distrib(generator) * 2.0f - 1.0f, // -1.0f - 1.0f
0.0f, // we want to rotate about the z axis in tangent space
0.0f
};
}
SHImageCreateParams imageDetails =
{
.imageType = vk::ImageType::e2D,
.width = NUM_ROTATION_VECTORS_W,
.height = NUM_ROTATION_VECTORS_H,
.depth = 1,
.levels = 1,
.arrayLayers = 1,
.imageFormat = vk::Format::eR32G32B32A32Sfloat,
.usageFlags = vk::ImageUsageFlagBits::eSampled | vk::ImageUsageFlagBits::eTransferDst,
.createFlags = {}
};
uint32_t mipOffset = 0;
rotationVectorsImage = logicalDevice->CreateImage(imageDetails, reinterpret_cast<unsigned char*>( rotationVectors.data()), static_cast<uint32_t>(sizeof(rotationVectors)), {&mipOffset, 1}, VMA_MEMORY_USAGE_AUTO, {});
vk::ImageMemoryBarrier transferBarrier{};
rotationVectorsImage->PrepareImageTransitionInfo(vk::ImageLayout::eUndefined, vk::ImageLayout::eTransferDstOptimal, transferBarrier);
cmdBuffer->PipelineBarrier(vk::PipelineStageFlagBits::eTopOfPipe, vk::PipelineStageFlagBits::eTransfer, {}, {}, {}, {transferBarrier});
rotationVectorsImage->TransferToDeviceResource(cmdBuffer);
vk::ImageMemoryBarrier shaderReadBarrier{};
rotationVectorsImage->PrepareImageTransitionInfo(vk::ImageLayout::eTransferDstOptimal, vk::ImageLayout::eShaderReadOnlyOptimal, shaderReadBarrier);
cmdBuffer->PipelineBarrier(vk::PipelineStageFlagBits::eTransfer, vk::PipelineStageFlagBits::eComputeShader, {}, {}, {}, { shaderReadBarrier });
// Get aligned size for buffer
uint32_t alignedSize = logicalDevice->PadSSBOSize(sizeof (samples));
// Create buffer
ssaoDataBuffer = logicalDevice->CreateBuffer(alignedSize, samples.data(), alignedSize, vk::BufferUsageFlagBits::eStorageBuffer | vk::BufferUsageFlagBits::eTransferDst, VMA_MEMORY_USAGE_AUTO, {});
ssaoDataBuffer->TransferToDeviceResource(cmdBuffer);
}
void SHSSAO::PrepareRotationVectorsVkData(Handle<SHVkLogicalDevice> logicalDevice) noexcept
{
SHImageViewDetails DETAILS =
{
.viewType = vk::ImageViewType::e2D,
.format = vk::Format::eR32G32B32A32Sfloat,
.imageAspectFlags = vk::ImageAspectFlagBits::eColor,
.baseMipLevel = 0,
.mipLevelCount = 1,
.baseArrayLayer = 0,
.layerCount = 1
};
rotationVectorsImageView = rotationVectorsImage->CreateImageView(logicalDevice, rotationVectorsImage, DETAILS);
SHVkSamplerParams samplerParams
{
.minFilter = vk::Filter::eNearest,
.magFilter = vk::Filter::eNearest,
.addressMode = vk::SamplerAddressMode::eRepeat,
.mipmapMode = vk::SamplerMipmapMode::eNearest,
.maxLod = 1u
};
rotationVectorsSampler = logicalDevice->CreateSampler(samplerParams);
}
SHVkDescriptorSetGroup::viewSamplerLayout SHSSAO::GetViewSamplerLayout(void) const noexcept
{
return std::make_tuple(rotationVectorsImageView, rotationVectorsSampler, vk::ImageLayout::eShaderReadOnlyOptimal);
}
Handle<SHVkBuffer> SHSSAO::GetBuffer(void) const noexcept
{
return ssaoDataBuffer;
}
}

View File

@ -0,0 +1,49 @@
#pragma once
#include "Resource/SHHandle.h"
#include "Graphics/SHVulkanIncludes.h"
#include "Math/Vector/SHVec4.h"
#include "Graphics/Descriptors/SHVkDescriptorSetGroup.h"
namespace SHADE
{
class SHVkBuffer;
class SHVkLogicalDevice;
class SHVkCommandBuffer;
class SHVkImage;
class SHVkImageView;
class SHVkSampler;
class SHSSAO
{
public:
static constexpr uint32_t DESC_SET_BUFFER_BINDING = 0;
static constexpr uint32_t DESC_SET_IMAGE_BINDING = 1;
private:
static constexpr uint32_t NUM_SAMPLES = 64;
static constexpr uint32_t NUM_ROTATION_VECTORS_W = 4;
static constexpr uint32_t NUM_ROTATION_VECTORS_H = 4;
static constexpr uint32_t NUM_ROTATION_VECTORS = NUM_ROTATION_VECTORS_W * NUM_ROTATION_VECTORS_H;
private:
//! distances from a pixel we want to sample
std::array<SHVec4, NUM_SAMPLES> samples;
//! For passing SSAO samples and kernel to GPU
Handle<SHVkBuffer> ssaoDataBuffer;
std::array<SHVec4, NUM_ROTATION_VECTORS> rotationVectors;
Handle<SHVkImage> rotationVectorsImage;
Handle<SHVkImageView> rotationVectorsImageView;
Handle<SHVkSampler> rotationVectorsSampler;
public:
void Init (Handle<SHVkLogicalDevice> logicalDevice, Handle<SHVkCommandBuffer> cmdBuffer) noexcept;
void PrepareRotationVectorsVkData (Handle<SHVkLogicalDevice> logicalDevice) noexcept;
SHVkDescriptorSetGroup::viewSamplerLayout GetViewSamplerLayout (void) const noexcept;
Handle<SHVkBuffer> GetBuffer (void) const noexcept;
};
}

View File

@ -2,8 +2,10 @@
#define SH_PIPELINE_LAYOUT_PARAMS_H #define SH_PIPELINE_LAYOUT_PARAMS_H
#include "Graphics/SHVulkanIncludes.h" #include "Graphics/SHVulkanIncludes.h"
#include "Graphics/SHVulkanDefines.h"
#include "Resource/SHHandle.h" #include "Resource/SHHandle.h"
#include "Graphics/Descriptors/SHVkDescriptorSetLayout.h" #include "Graphics/Descriptors/SHVkDescriptorSetLayout.h"
#include <unordered_set>
namespace SHADE namespace SHADE
{ {
@ -24,6 +26,12 @@ namespace SHADE
//! want to use the layout to initialize the pipeline layout but we do not //! want to use the layout to initialize the pipeline layout but we do not
//! want to use it for allocating descriptor sets. //! want to use it for allocating descriptor sets.
std::vector<Handle<SHVkDescriptorSetLayout>> const& globalDescSetLayouts = {}; std::vector<Handle<SHVkDescriptorSetLayout>> const& globalDescSetLayouts = {};
//! Since both SPIRV-Reflect and GLSL don't provide ways to describe UBOs or
//! SSBOs as dynamic, we need to do it ourselves. This will store bindings
//! which we will use when parsing for descriptor set layouts. If a parsed
//! binding is in this container, we make that binding's descriptor dynamic.
std::unordered_set<BindingAndSetHash> dynamicBufferBindings;
}; };
struct SHPipelineLayoutParamsDummy struct SHPipelineLayoutParamsDummy

View File

@ -165,6 +165,28 @@ namespace SHADE
newBinding.Stage = shaderModule->GetShaderStageFlagBits(); newBinding.Stage = shaderModule->GetShaderStageFlagBits();
newBinding.Type = descBindingInfo.ConvertFromReflectDescType(reflectedBinding->descriptor_type); newBinding.Type = descBindingInfo.ConvertFromReflectDescType(reflectedBinding->descriptor_type);
// Here we want to check if a binding is supposed to be dynamic. If it is, make it dynamic.
if (newBinding.Type == vk::DescriptorType::eUniformBuffer || newBinding.Type == vk::DescriptorType::eStorageBuffer)
{
for (auto& bsHash : dynamicBufferBindings)
{
uint32_t set = static_cast<uint32_t>(bsHash >> 32);
uint32_t binding = static_cast<uint32_t>(bsHash & 0xFFFFFFFF);
if (set == CURRENT_SET && binding == newBinding.BindPoint)
{
switch (newBinding.Type)
{
case vk::DescriptorType::eUniformBuffer:
newBinding.Type = vk::DescriptorType::eUniformBufferDynamic;
break;
case vk::DescriptorType::eStorageBuffer:
newBinding.Type = vk::DescriptorType::eStorageBufferDynamic;
break;
}
}
}
}
// In reality, the check for variable descriptor sets do not exists in spirv-reflect. Fortunately, when a shader // In reality, the check for variable descriptor sets do not exists in spirv-reflect. Fortunately, when a shader
// defines a boundless descriptor binding in the shader, the information reflected makes the array dimensions // defines a boundless descriptor binding in the shader, the information reflected makes the array dimensions
// contain a 1 element of value 1. Knowing that having an array [1] doesn't make sense, we can use this to // contain a 1 element of value 1. Knowing that having an array [1] doesn't make sense, we can use this to
@ -300,6 +322,7 @@ namespace SHADE
, vkDescriptorSetLayoutsAllocate{} , vkDescriptorSetLayoutsAllocate{}
, descriptorSetLayoutsPipeline{} , descriptorSetLayoutsPipeline{}
, vkDescriptorSetLayoutsPipeline{} , vkDescriptorSetLayoutsPipeline{}
, dynamicBufferBindings{std::move (pipelineLayoutParams.dynamicBufferBindings)}
{ {
for (auto& mod : shaderModules) for (auto& mod : shaderModules)
{ {

View File

@ -29,6 +29,9 @@ namespace SHADE
//! Push constant interface //! Push constant interface
SHPushConstantInterface pushConstantInterface; SHPushConstantInterface pushConstantInterface;
//! See SHPipelineLayoutParams for details
std::unordered_set<BindingAndSetHash> dynamicBufferBindings;
//! Push constant ranges //! Push constant ranges
std::vector<vk::PushConstantRange> vkPcRanges; std::vector<vk::PushConstantRange> vkPcRanges;

View File

@ -129,4 +129,9 @@ namespace SHADE
return vkQueue; return vkQueue;
} }
void SHVkQueue::WaitIdle(void) const noexcept
{
vkQueue.waitIdle();
}
} }

View File

@ -50,6 +50,8 @@ namespace SHADE
void SubmitCommandBuffer (std::initializer_list<Handle<SHVkCommandBuffer>> cmdBuffers, std::initializer_list<Handle<SHVkSemaphore>> signalSems = {}, std::initializer_list<Handle<SHVkSemaphore>> waitSems = {}, vk::PipelineStageFlags waitDstStageMask = {}, Handle<SHVkFence> const& fence = {}) noexcept; void SubmitCommandBuffer (std::initializer_list<Handle<SHVkCommandBuffer>> cmdBuffers, std::initializer_list<Handle<SHVkSemaphore>> signalSems = {}, std::initializer_list<Handle<SHVkSemaphore>> waitSems = {}, vk::PipelineStageFlags waitDstStageMask = {}, Handle<SHVkFence> const& fence = {}) noexcept;
vk::Result Present (Handle<SHVkSwapchain> const& swapchain, std::initializer_list<Handle<SHVkSemaphore>> waitSems, uint32_t frameIndex) noexcept; vk::Result Present (Handle<SHVkSwapchain> const& swapchain, std::initializer_list<Handle<SHVkSemaphore>> waitSems, uint32_t frameIndex) noexcept;
vk::Queue GetVkQueue() noexcept; vk::Queue GetVkQueue() noexcept;
void WaitIdle (void) const noexcept;
}; };
} }

View File

@ -263,7 +263,7 @@ namespace SHADE
return subpass; return subpass;
} }
Handle<SHRenderGraphNodeCompute> SHRenderGraphNode::AddNodeCompute(Handle<SHVkShaderModule> computeShaderModule, std::initializer_list<std::string> resources, float numWorkGroupScale/* = 1.0f*/) noexcept Handle<SHRenderGraphNodeCompute> SHRenderGraphNode::AddNodeCompute(Handle<SHVkShaderModule> computeShaderModule, std::initializer_list<std::string> resources, std::unordered_set<BindingAndSetHash>&& dynamicBufferBindings, float numWorkGroupScale/* = 1.0f*/) noexcept
{ {
// Look for the required resources in the graph // Look for the required resources in the graph
std::vector<Handle<SHRenderGraphResource>> nodeComputeResources{}; std::vector<Handle<SHRenderGraphResource>> nodeComputeResources{};
@ -276,7 +276,7 @@ namespace SHADE
} }
// Create the subpass compute with the resources // Create the subpass compute with the resources
auto nodeCompute = graphStorage->resourceManager->Create<SHRenderGraphNodeCompute>(graphStorage, computeShaderModule, std::move(nodeComputeResources), nodeComputes.empty()); auto nodeCompute = graphStorage->resourceManager->Create<SHRenderGraphNodeCompute>(graphStorage, computeShaderModule, std::move(nodeComputeResources), std::move (dynamicBufferBindings), nodeComputes.empty());
nodeComputes.push_back(nodeCompute); nodeComputes.push_back(nodeCompute);
return nodeCompute; return nodeCompute;

View File

@ -100,7 +100,7 @@ namespace SHADE
/* PUBLIC MEMBER FUNCTIONS */ /* PUBLIC MEMBER FUNCTIONS */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
Handle<SHSubpass> AddSubpass(std::string subpassName) noexcept; Handle<SHSubpass> AddSubpass(std::string subpassName) noexcept;
Handle<SHRenderGraphNodeCompute> AddNodeCompute(Handle<SHVkShaderModule> computeShaderModule, std::initializer_list<std::string> resources, float numWorkGroupScale = 1.0f) noexcept; Handle<SHRenderGraphNodeCompute> AddNodeCompute(Handle<SHVkShaderModule> computeShaderModule, std::initializer_list<std::string> resources, std::unordered_set<BindingAndSetHash>&& dynamicBufferBindings = {}, float numWorkGroupScale = 1.0f) noexcept;
void AddDummySubpassIfNeeded (void) noexcept; void AddDummySubpassIfNeeded (void) noexcept;
// TODO: RemoveSubpass() // TODO: RemoveSubpass()

View File

@ -13,7 +13,7 @@
namespace SHADE namespace SHADE
{ {
SHRenderGraphNodeCompute::SHRenderGraphNodeCompute(Handle<SHRenderGraphStorage> graphStorage, Handle<SHVkShaderModule> computeShaderModule, std::vector<Handle<SHRenderGraphResource>>&& subpassComputeResources, bool followingEndRP, float inNumWorkGroupScale/* = 1.0f*/) noexcept SHRenderGraphNodeCompute::SHRenderGraphNodeCompute(Handle<SHRenderGraphStorage> graphStorage, Handle<SHVkShaderModule> computeShaderModule, std::vector<Handle<SHRenderGraphResource>>&& subpassComputeResources, std::unordered_set<BindingAndSetHash>&& dynamicBufferBindings, bool followingEndRP, float inNumWorkGroupScale/* = 1.0f*/) noexcept
: computePipeline{} : computePipeline{}
, pipelineLayout{} , pipelineLayout{}
, resources{} , resources{}
@ -21,11 +21,13 @@ namespace SHADE
, groupSizeY{0} , groupSizeY{0}
, followingEndRenderpass {followingEndRP} , followingEndRenderpass {followingEndRP}
, numWorkGroupScale {std::clamp(inNumWorkGroupScale, 0.0f, 1.0f)} , numWorkGroupScale {std::clamp(inNumWorkGroupScale, 0.0f, 1.0f)}
, computeResource{}
{ {
SHPipelineLayoutParams pipelineLayoutParams SHPipelineLayoutParams pipelineLayoutParams
{ {
.shaderModules = {computeShaderModule}, .shaderModules = {computeShaderModule},
.globalDescSetLayouts = SHGraphicsGlobalData::GetDescSetLayouts() .globalDescSetLayouts = SHGraphicsGlobalData::GetDescSetLayouts(),
.dynamicBufferBindings = std::move(dynamicBufferBindings),
}; };
// Create pipeline layout from parameters // Create pipeline layout from parameters
@ -42,16 +44,31 @@ namespace SHADE
//Get the descriptor set layouts required to allocate. We only want the ones for allocate because //Get the descriptor set layouts required to allocate. We only want the ones for allocate because
//global descriptors are already bound in the main system. //global descriptors are already bound in the main system.
auto const& layouts = computePipeline->GetPipelineLayout()->GetDescriptorSetLayoutsAllocate(); auto const& graphResourceLayout = computePipeline->GetPipelineLayout()->GetDescriptorSetLayoutsPipeline()[SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_RESOURCE];
//Variable counts for the descriptor sets (all should be 1).
std::vector<uint32_t> variableCounts{ static_cast<uint32_t>(layouts.size()) };
std::fill(variableCounts.begin(), variableCounts.end(), 0);
// Allocate descriptor sets to hold the images for reading (STORAGE_IMAGE) // Allocate descriptor sets to hold the images for reading (STORAGE_IMAGE)
for (uint32_t i = 0; i < SHGraphicsConstants::NUM_FRAME_BUFFERS; ++i) for (uint32_t i = 0; i < SHGraphicsConstants::NUM_FRAME_BUFFERS; ++i)
{ {
descSetGroups[i] = graphStorage->descriptorPool->Allocate(layouts, variableCounts); graphResourceDescSets[i] = graphStorage->descriptorPool->Allocate({graphResourceLayout}, { 1 });
}
auto const& layouts = computePipeline->GetPipelineLayout()->GetDescriptorSetLayoutsPipeline();
if (layouts.size() == SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_NODE_COMPUTE_RESOURCE + 1)
{
// create compute resources
computeResource = graphStorage->resourceManager->Create<ComputeResource>();
auto computeResourceLayout = layouts[SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_NODE_COMPUTE_RESOURCE];
computeResource->descSet = graphStorage->descriptorPool->Allocate({ computeResourceLayout }, { 1 });
// Allocate for descriptor offsets
for (uint32_t i = 0; i < SHGraphicsConstants::NUM_FRAME_BUFFERS; ++i)
computeResource->dynamicOffsets[i].resize(computeResourceLayout->GetNumDynamicOffsetsRequired());
// 1st set all start at 0
for (auto& index : computeResource->dynamicOffsets[0])
index = 0;
} }
HandleResize(); HandleResize();
@ -63,7 +80,12 @@ namespace SHADE
cmdBuffer->BindPipeline(computePipeline); cmdBuffer->BindPipeline(computePipeline);
// bind descriptor sets // bind descriptor sets
cmdBuffer->BindDescriptorSet(descSetGroups[frameIndex], SH_PIPELINE_TYPE::COMPUTE, SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_RESOURCE, {}); cmdBuffer->BindDescriptorSet(graphResourceDescSets[frameIndex], SH_PIPELINE_TYPE::COMPUTE, SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_RESOURCE, {});
if (computeResource)
{
cmdBuffer->BindDescriptorSet(computeResource->descSet, SH_PIPELINE_TYPE::COMPUTE, SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_NODE_COMPUTE_RESOURCE, computeResource->dynamicOffsets[frameIndex]);
}
// dispatch compute // dispatch compute
cmdBuffer->ComputeDispatch(groupSizeX, groupSizeY, 1); cmdBuffer->ComputeDispatch(groupSizeX, groupSizeY, 1);
@ -89,8 +111,8 @@ namespace SHADE
uint32_t imageIndex = (resources[i]->resourceTypeFlags & static_cast<uint32_t>(SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT)) ? frameIndex : 0; uint32_t imageIndex = (resources[i]->resourceTypeFlags & static_cast<uint32_t>(SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT)) ? frameIndex : 0;
SHVkDescriptorSetGroup::viewSamplerLayout vsl = std::make_tuple(resources[i]->GetImageView(imageIndex), Handle<SHVkSampler>{}, vk::ImageLayout::eGeneral); SHVkDescriptorSetGroup::viewSamplerLayout vsl = std::make_tuple(resources[i]->GetImageView(imageIndex), Handle<SHVkSampler>{}, vk::ImageLayout::eGeneral);
descSetGroups[frameIndex]->ModifyWriteDescImage(SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_RESOURCE, binding.BindPoint, { &vsl, 1 }); graphResourceDescSets[frameIndex]->ModifyWriteDescImage(SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_RESOURCE, binding.BindPoint, { &vsl, 1 });
descSetGroups[frameIndex]->UpdateDescriptorSetImages(SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_RESOURCE, binding.BindPoint); graphResourceDescSets[frameIndex]->UpdateDescriptorSetImages(SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_RESOURCE, binding.BindPoint);
++i; ++i;
} }
} }
@ -137,4 +159,27 @@ namespace SHADE
} }
} }
void SHRenderGraphNodeCompute::SetDynamicOffsets(std::span<uint32_t> perFrameSizes) noexcept
{
for (uint32_t i = 0; i < SHGraphicsConstants::NUM_FRAME_BUFFERS; ++i)
{
auto dynamicOffsets = computeResource->dynamicOffsets[i];
for (uint32_t j = 0; j < perFrameSizes.size(); ++j)
dynamicOffsets[j] = perFrameSizes[j] * i;
}
}
void SHRenderGraphNodeCompute::ModifyWriteDescBufferComputeResource(uint32_t set, uint32_t binding, std::span<Handle<SHVkBuffer>> const& buffers, uint32_t offset, uint32_t range) noexcept
{
computeResource->descSet->ModifyWriteDescBuffer(set, binding, buffers, offset, range);
computeResource->descSet->UpdateDescriptorSetBuffer(set, binding);
}
void SHRenderGraphNodeCompute::ModifyWriteDescImageComputeResource(uint32_t set, uint32_t binding, std::span<SHVkDescriptorSetGroup::viewSamplerLayout> const& viewSamplerLayouts) noexcept
{
computeResource->descSet->ModifyWriteDescImage(set, binding, viewSamplerLayouts);
computeResource->descSet->UpdateDescriptorSetImages(set, binding);
}
} }

View File

@ -2,6 +2,7 @@
#include "Resource/SHHandle.h" #include "Resource/SHHandle.h"
#include "Graphics/MiddleEnd/Interface/SHGraphicsConstants.h" #include "Graphics/MiddleEnd/Interface/SHGraphicsConstants.h"
#include "Graphics/Descriptors/SHVkDescriptorSetGroup.h"
#include "Graphics/SHVulkanIncludes.h" #include "Graphics/SHVulkanIncludes.h"
#include <initializer_list> #include <initializer_list>
#include <string> #include <string>
@ -10,7 +11,6 @@
namespace SHADE namespace SHADE
{ {
class SHVkPipeline; class SHVkPipeline;
class SHVkDescriptorSetGroup;
class SHVkDescriptorPool; class SHVkDescriptorPool;
class SHVkLogicalDevice; class SHVkLogicalDevice;
class SHVkPipelineLayout; class SHVkPipelineLayout;
@ -18,9 +18,22 @@ namespace SHADE
class SHRenderGraphResource; class SHRenderGraphResource;
class SHVkShaderModule; class SHVkShaderModule;
class SHVkCommandBuffer; class SHVkCommandBuffer;
class SHVkBuffer;
class SHRenderGraphNodeCompute class SHRenderGraphNodeCompute
{ {
private:
// Binding of set SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_NODE_COMPUTE_RESOURCE
struct ComputeResource
{
//! Descriptor set (initialized by parent class)
Handle<SHVkDescriptorSetGroup> descSet {};
//! Dynamic offsets into these resources (initialized from the outside).
std::array<std::vector<uint32_t>, SHGraphicsConstants::NUM_FRAME_BUFFERS> dynamicOffsets {};
};
private: private:
static constexpr uint32_t workGroupSizeX = 16; static constexpr uint32_t workGroupSizeX = 16;
static constexpr uint32_t workGroupSizeY = 16; static constexpr uint32_t workGroupSizeY = 16;
@ -32,7 +45,10 @@ namespace SHADE
Handle<SHVkPipelineLayout> pipelineLayout; Handle<SHVkPipelineLayout> pipelineLayout;
//! Descriptor set group to hold the images for reading (STORAGE_IMAGE) //! Descriptor set group to hold the images for reading (STORAGE_IMAGE)
std::array<Handle<SHVkDescriptorSetGroup>, SHGraphicsConstants::NUM_FRAME_BUFFERS> descSetGroups; std::array<Handle<SHVkDescriptorSetGroup>, SHGraphicsConstants::NUM_FRAME_BUFFERS> graphResourceDescSets;
//! Compute resources
Handle<ComputeResource> computeResource;
//! vector of resources needed by the subpass compute //! vector of resources needed by the subpass compute
std::vector<Handle<SHRenderGraphResource>> resources; std::vector<Handle<SHRenderGraphResource>> resources;
@ -50,11 +66,17 @@ namespace SHADE
std::array<std::vector<vk::ImageMemoryBarrier>, SHGraphicsConstants::NUM_FRAME_BUFFERS> memoryBarriers; std::array<std::vector<vk::ImageMemoryBarrier>, SHGraphicsConstants::NUM_FRAME_BUFFERS> memoryBarriers;
public: public:
SHRenderGraphNodeCompute(Handle<SHRenderGraphStorage> graphStorage, Handle<SHVkShaderModule> computeShaderModule, std::vector<Handle<SHRenderGraphResource>>&& subpassComputeResources, bool followingEndRP, float inNumWorkGroupScale = 1.0f) noexcept; SHRenderGraphNodeCompute(Handle<SHRenderGraphStorage> graphStorage, Handle<SHVkShaderModule> computeShaderModule, std::vector<Handle<SHRenderGraphResource>>&& subpassComputeResources, std::unordered_set<BindingAndSetHash>&& dynamicBufferBindings, bool followingEndRP, float inNumWorkGroupScale = 1.0f) noexcept;
void Execute (Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept; void Execute (Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept;
void HandleResize (void) noexcept; void HandleResize (void) noexcept;
void SetDynamicOffsets (std::span<uint32_t> perFrameSizes) noexcept;
void ModifyWriteDescBufferComputeResource (uint32_t set, uint32_t binding, std::span<Handle<SHVkBuffer>> const& buffers, uint32_t offset, uint32_t range) noexcept;
void ModifyWriteDescImageComputeResource(uint32_t set, uint32_t binding, std::span<SHVkDescriptorSetGroup::viewSamplerLayout> const& viewSamplerLayouts) noexcept;
friend class SHRenderGraph; friend class SHRenderGraph;
friend class SHRenderGraphNode; friend class SHRenderGraphNode;
}; };

View File

@ -142,6 +142,16 @@ namespace SHADE
case SpvOp::SpvOpTypeRuntimeArray: case SpvOp::SpvOpTypeRuntimeArray:
recurseForInfo(&member, interfaceHdl, member.offset, biggestAlignment, parentVarName + std::string(member.name) + "."); recurseForInfo(&member, interfaceHdl, member.offset, biggestAlignment, parentVarName + std::string(member.name) + ".");
break; break;
case SpvOp::SpvOpTypeArray:
interfaceHdl->AddVariable(parentVarName + std::string (member.name),
SHShaderBlockInterface::Variable
(
parentOffset + member.offset,
SHShaderBlockInterface::Variable::Type::OTHER
)
);
biggestAlignment = std::max(biggestAlignment, member.size);
break;
} }
} }
}; };

View File

@ -118,6 +118,17 @@ namespace SHADE
} }
{} {}
SHColour::SHColour(uint32_t rgba) noexcept
: XMFLOAT4 { 0.0f, 0.0f, 0.0f, 1.0f }
{
const SHColour32 TMP { ._32bitValue = rgba };
x = static_cast<float>(TMP._8bitValues[0]) / 255.0f;
y = static_cast<float>(TMP._8bitValues[1]) / 255.0f;
z = static_cast<float>(TMP._8bitValues[2]) / 255.0f;
w = static_cast<float>(TMP._8bitValues[3]) / 255.0f;
}
SHColour::SHColour(const SHVec3& rgb) noexcept SHColour::SHColour(const SHVec3& rgb) noexcept
: XMFLOAT4 { rgb.x, rgb.y, rgb.z, 1.0f } : XMFLOAT4 { rgb.x, rgb.y, rgb.z, 1.0f }
{} {}

View File

@ -34,6 +34,12 @@ namespace SHADE
float v = 0.0f; float v = 0.0f;
}; };
union SH_API SHColour32
{
uint32_t _32bitValue;
uint8_t _8bitValues[4];
};
class SH_API SHColour : public DirectX::XMFLOAT4 class SH_API SHColour : public DirectX::XMFLOAT4
{ {
public: public:
@ -46,6 +52,7 @@ namespace SHADE
SHColour (float r, float g, float b, float a) noexcept; SHColour (float r, float g, float b, float a) noexcept;
SHColour (uint8_t r, uint8_t g, uint8_t b) noexcept; SHColour (uint8_t r, uint8_t g, uint8_t b) noexcept;
SHColour (uint8_t r, uint8_t g, uint8_t b, uint8_t a) noexcept; SHColour (uint8_t r, uint8_t g, uint8_t b, uint8_t a) noexcept;
SHColour (uint32_t rgba) noexcept;
SHColour (const SHVec3& rgb) noexcept; SHColour (const SHVec3& rgb) noexcept;
SHColour (const SHVec4& rgba) noexcept; SHColour (const SHVec4& rgba) noexcept;

View File

@ -212,7 +212,7 @@ namespace SHADE
const SHVec3 TF_WORLD_SCALE = transformComponent->GetWorldScale(); const SHVec3 TF_WORLD_SCALE = transformComponent->GetWorldScale();
const float MAX_SCALE = SHMath::Max({ TF_WORLD_SCALE.x, TF_WORLD_SCALE.y, TF_WORLD_SCALE.z }); const float MAX_SCALE = SHMath::Max({ TF_WORLD_SCALE.x, TF_WORLD_SCALE.y, TF_WORLD_SCALE.z });
worldRadius *= MAX_SCALE; worldRadius *= MAX_SCALE * 0.5f;
} }
if (type == Type::SPHERE) if (type == Type::SPHERE)

View File

@ -17,10 +17,12 @@
#include "ECS_Base/Managers/SHComponentManager.h" #include "ECS_Base/Managers/SHComponentManager.h"
#include "ECS_Base/Managers/SHEntityManager.h" #include "ECS_Base/Managers/SHEntityManager.h"
#include "ECS_Base/Managers/SHSystemManager.h" #include "ECS_Base/Managers/SHSystemManager.h"
#include "Graphics/MiddleEnd/Interface/SHDebugDrawSystem.h"
#include "Math/SHMathHelpers.h" #include "Math/SHMathHelpers.h"
#include "Math/Transform/SHTransformComponent.h" #include "Math/Transform/SHTransformComponent.h"
#include "Scene/SHSceneManager.h" #include "Scene/SHSceneManager.h"
#include "Scripting/SHScriptEngine.h" #include "Scripting/SHScriptEngine.h"
#include "Tools/SHUtilities.h"
namespace SHADE namespace SHADE
{ {
@ -30,6 +32,7 @@ namespace SHADE
SHPhysicsSystem::SHPhysicsSystem() SHPhysicsSystem::SHPhysicsSystem()
: worldUpdated { false } : worldUpdated { false }
, debugDrawFlags { 0 }
, interpolationFactor { 0.0 } , interpolationFactor { 0.0 }
, fixedDT { 60.0 } , fixedDT { 60.0 }
, world { nullptr } , world { nullptr }
@ -47,6 +50,11 @@ namespace SHADE
: SHSystemRoutine { "Physics PostUpdate", false } : SHSystemRoutine { "Physics PostUpdate", false }
{} {}
SHPhysicsSystem::PhysicsDebugDraw::PhysicsDebugDraw()
: SHSystemRoutine { "Physics DebugDraw", true }
{}
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Getter Function Definitions */ /* Getter Function Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
@ -99,6 +107,31 @@ namespace SHADE
return 0; return 0;
} }
bool SHPhysicsSystem::GetDrawColliders() const noexcept
{
return debugDrawFlags & SHUtilities::ConvertEnum(DebugDrawFlags::COLLIDER);
}
bool SHPhysicsSystem::GetDrawColliderAABBs() const noexcept
{
return debugDrawFlags & SHUtilities::ConvertEnum(DebugDrawFlags::COLLIDER_AABB);
}
bool SHPhysicsSystem::GetDrawBroadPhase() const noexcept
{
return debugDrawFlags & SHUtilities::ConvertEnum(DebugDrawFlags::BROAD_PHASE_AABB);
}
bool SHPhysicsSystem::GetDrawContactPoints() const noexcept
{
return debugDrawFlags & SHUtilities::ConvertEnum(DebugDrawFlags::CONTACT_POINTS);
}
bool SHPhysicsSystem::GetDrawContactNormals() const noexcept
{
return debugDrawFlags & SHUtilities::ConvertEnum(DebugDrawFlags::CONTACT_NORMALS);
}
const SHPhysicsSystem::CollisionEvents& SHPhysicsSystem::GetCollisionInfo() const noexcept const SHPhysicsSystem::CollisionEvents& SHPhysicsSystem::GetCollisionInfo() const noexcept
{ {
return collisionInfo; return collisionInfo;
@ -181,6 +214,96 @@ namespace SHADE
} }
} }
void SHPhysicsSystem::SetDrawColliders(bool shouldDraw) noexcept
{
static constexpr auto FLAG_VALUE = SHUtilities::ConvertEnum(DebugDrawFlags::COLLIDER);
shouldDraw ? debugDrawFlags |= FLAG_VALUE : debugDrawFlags &= ~(FLAG_VALUE);
if (world == nullptr)
{
SHLOGV_WARNING("No physics world has been initialised!")
return;
}
world->getDebugRenderer().setIsDebugItemDisplayed
(
rp3d::DebugRenderer::DebugItem::COLLISION_SHAPE,
shouldDraw
);
}
void SHPhysicsSystem::SetDrawColliderAABBs(bool shouldDraw) noexcept
{
static constexpr auto FLAG_VALUE = SHUtilities::ConvertEnum(DebugDrawFlags::COLLIDER_AABB);
shouldDraw ? debugDrawFlags |= FLAG_VALUE : debugDrawFlags &= ~(FLAG_VALUE);
if (world == nullptr)
{
SHLOGV_WARNING("No physics world has been initialised!")
return;
}
world->getDebugRenderer().setIsDebugItemDisplayed
(
rp3d::DebugRenderer::DebugItem::COLLIDER_AABB,
shouldDraw
);
}
void SHPhysicsSystem::SetDrawBroadPhase(bool shouldDraw) noexcept
{
static constexpr auto FLAG_VALUE = SHUtilities::ConvertEnum(DebugDrawFlags::BROAD_PHASE_AABB);
shouldDraw ? debugDrawFlags |= FLAG_VALUE : debugDrawFlags &= ~(FLAG_VALUE);
if (world == nullptr)
{
SHLOGV_WARNING("No physics world has been initialised!")
return;
}
world->getDebugRenderer().setIsDebugItemDisplayed
(
rp3d::DebugRenderer::DebugItem::COLLIDER_BROADPHASE_AABB,
shouldDraw
);
}
void SHPhysicsSystem::SetDrawContactPoints(bool shouldDraw) noexcept
{
static constexpr auto FLAG_VALUE = SHUtilities::ConvertEnum(DebugDrawFlags::CONTACT_POINTS);
shouldDraw ? debugDrawFlags |= FLAG_VALUE : debugDrawFlags &= ~(FLAG_VALUE);
if (world == nullptr)
{
SHLOGV_WARNING("No physics world has been initialised!")
return;
}
world->getDebugRenderer().setIsDebugItemDisplayed
(
rp3d::DebugRenderer::DebugItem::CONTACT_POINT,
shouldDraw
);
}
void SHPhysicsSystem::SetDrawContactNormals(bool shouldDraw) noexcept
{
static constexpr auto FLAG_VALUE = SHUtilities::ConvertEnum(DebugDrawFlags::CONTACT_NORMALS);
shouldDraw ? debugDrawFlags |= FLAG_VALUE : debugDrawFlags &= ~(FLAG_VALUE);
if (world == nullptr)
{
SHLOGV_WARNING("No physics world has been initialised!")
return;
}
world->getDebugRenderer().setIsDebugItemDisplayed
(
rp3d::DebugRenderer::DebugItem::CONTACT_NORMAL,
shouldDraw
);
}
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Public Function Member Definitions */ /* Public Function Member Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
@ -198,6 +321,7 @@ namespace SHADE
world = factory.createPhysicsWorld(settings); world = factory.createPhysicsWorld(settings);
world->setEventListener(this); world->setEventListener(this);
world->setIsDebugRenderingEnabled(true);
// Set up solvers // Set up solvers
world->setContactsPositionCorrectionTechnique(rp3d::ContactsPositionCorrectionTechnique::SPLIT_IMPULSES); world->setContactsPositionCorrectionTechnique(rp3d::ContactsPositionCorrectionTechnique::SPLIT_IMPULSES);
@ -323,7 +447,7 @@ namespace SHADE
auto* scriptingSystem = SHSystemManager::GetSystem<SHScriptEngine>(); auto* scriptingSystem = SHSystemManager::GetSystem<SHScriptEngine>();
if (scriptingSystem == nullptr) if (scriptingSystem == nullptr)
{ {
SHLOGV_WARNING("Unable to invoke FixedUpdate() on scripts due to missing SHScriptEngine!"); SHLOGV_ERROR("Unable to invoke FixedUpdate() on scripts due to missing SHScriptEngine!");
} }
fixedTimeStep = 1.0 / physicsSystem->fixedDT; fixedTimeStep = 1.0 / physicsSystem->fixedDT;
@ -353,7 +477,7 @@ namespace SHADE
auto* scriptingSystem = SHSystemManager::GetSystem<SHScriptEngine>(); auto* scriptingSystem = SHSystemManager::GetSystem<SHScriptEngine>();
if (scriptingSystem == nullptr) if (scriptingSystem == nullptr)
{ {
SHLOGV_WARNING("Unable to invoke collision and trigger script events due to missing SHScriptEngine!"); SHLOGV_ERROR("Unable to invoke collision and trigger script events due to missing SHScriptEngine!");
} }
// Interpolate transforms for rendering // Interpolate transforms for rendering
@ -369,6 +493,40 @@ namespace SHADE
} }
} }
void SHPhysicsSystem::PhysicsDebugDraw::Execute(double) noexcept
{
const auto* PHYSICS_SYSTEM = reinterpret_cast<SHPhysicsSystem*>(GetSystem());
if (PHYSICS_SYSTEM->debugDrawFlags == 0)
return;
auto* debugDrawSystem = SHSystemManager::GetSystem<SHDebugDrawSystem>();
if (debugDrawSystem == nullptr)
{
SHLOGV_ERROR("Unable to debug draw physics objects due to missing SHDebugDrawSystem!");
return;
}
const auto& RP3D_DEBUG_RENDERER = PHYSICS_SYSTEM->world->getDebugRenderer();
const auto& LINES = RP3D_DEBUG_RENDERER.getLines();
const auto& TRIANGLES = RP3D_DEBUG_RENDERER.getTriangles();
// Draw all lines
for (uint32_t i = 0; i < RP3D_DEBUG_RENDERER.getNbLines(); ++i)
{
const auto& LINE = LINES[i];
debugDrawSystem->DrawLine(SHColour{ LINE.color1 }, LINE.point1, LINE.point2);
}
for (uint32_t i = 0; i < RP3D_DEBUG_RENDERER.getNbTriangles(); ++i)
{
const auto& TRIANGLE = TRIANGLES[i];
SHColour triColour{ TRIANGLE.color1 };
triColour.a() = 1.0f;
debugDrawSystem->DrawTri(triColour, TRIANGLE.point1, TRIANGLE.point2, TRIANGLE.point3);
}
}
void SHPhysicsSystem::onContact(const CallbackData& callbackData) void SHPhysicsSystem::onContact(const CallbackData& callbackData)
{ {
for (uint32_t i = 0; i < callbackData.getNbContactPairs(); ++i) for (uint32_t i = 0; i < callbackData.getNbContactPairs(); ++i)

View File

@ -51,6 +51,15 @@ namespace SHADE
using CollisionEvents = std::vector<SHCollisionEvent>; using CollisionEvents = std::vector<SHCollisionEvent>;
enum class DebugDrawFlags : uint8_t
{
COLLIDER = 1
, COLLIDER_AABB = 2
, BROAD_PHASE_AABB = 4
, CONTACT_POINTS = 8
, CONTACT_NORMALS = 16
};
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Constructors & Destructor */ /* Constructors & Destructor */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
@ -69,6 +78,12 @@ namespace SHADE
[[nodiscard]] uint16_t GetNumberVelocityIterations () const noexcept; [[nodiscard]] uint16_t GetNumberVelocityIterations () const noexcept;
[[nodiscard]] uint16_t GetNumberPositionIterations () const noexcept; [[nodiscard]] uint16_t GetNumberPositionIterations () const noexcept;
[[nodiscard]] bool GetDrawColliders () const noexcept;
[[nodiscard]] bool GetDrawColliderAABBs () const noexcept;
[[nodiscard]] bool GetDrawBroadPhase () const noexcept;
[[nodiscard]] bool GetDrawContactPoints () const noexcept;
[[nodiscard]] bool GetDrawContactNormals () const noexcept;
[[nodiscard]] const CollisionEvents& GetCollisionInfo () const noexcept; [[nodiscard]] const CollisionEvents& GetCollisionInfo () const noexcept;
[[nodiscard]] const CollisionEvents& GetTriggerInfo () const noexcept; [[nodiscard]] const CollisionEvents& GetTriggerInfo () const noexcept;
@ -85,6 +100,13 @@ namespace SHADE
void SetWorldSettings (const WorldSettings& settings) const noexcept; void SetWorldSettings (const WorldSettings& settings) const noexcept;
// TODO(Diren): Can the debug draw flags be done through an enum?
void SetDrawColliders (bool shouldDraw) noexcept;
void SetDrawColliderAABBs (bool shouldDraw) noexcept;
void SetDrawBroadPhase (bool shouldDraw) noexcept;
void SetDrawContactPoints (bool shouldDraw) noexcept;
void SetDrawContactNormals (bool shouldDraw) noexcept;
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Function Members */ /* Function Members */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
@ -105,48 +127,31 @@ namespace SHADE
class SH_API PhysicsPreUpdate final : public SHSystemRoutine class SH_API PhysicsPreUpdate final : public SHSystemRoutine
{ {
public: public:
/*-------------------------------------------------------------------------------*/
/* Constructors & Destructor */
/*-------------------------------------------------------------------------------*/
PhysicsPreUpdate(); PhysicsPreUpdate();
/*-------------------------------------------------------------------------------*/
/* Function Members */
/*-------------------------------------------------------------------------------*/
void Execute(double dt) noexcept override; void Execute(double dt) noexcept override;
}; };
class SH_API PhysicsFixedUpdate final : public SHFixedSystemRoutine class SH_API PhysicsFixedUpdate final : public SHFixedSystemRoutine
{ {
public: public:
/*-------------------------------------------------------------------------------*/
/* Constructors & Destructor */
/*-------------------------------------------------------------------------------*/
PhysicsFixedUpdate(); PhysicsFixedUpdate();
/*-------------------------------------------------------------------------------*/
/* Function Members */
/*-------------------------------------------------------------------------------*/
void Execute (double dt) noexcept override; void Execute (double dt) noexcept override;
}; };
class SH_API PhysicsPostUpdate final : public SHSystemRoutine class SH_API PhysicsPostUpdate final : public SHSystemRoutine
{ {
public: public:
/*-------------------------------------------------------------------------------*/
/* Constructors & Destructor */
/*-------------------------------------------------------------------------------*/
PhysicsPostUpdate(); PhysicsPostUpdate();
void Execute(double dt) noexcept override;
};
/*-------------------------------------------------------------------------------*/ class SH_API PhysicsDebugDraw final : public SHSystemRoutine
/* Function Members */ {
/*-------------------------------------------------------------------------------*/ public:
PhysicsDebugDraw();
void Execute(double dt) noexcept override; void Execute(double dt) noexcept override;
}; };
@ -162,6 +167,7 @@ namespace SHADE
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
bool worldUpdated; bool worldUpdated;
uint8_t debugDrawFlags;
double interpolationFactor; double interpolationFactor;
double fixedDT; double fixedDT;

View File

@ -70,4 +70,40 @@ namespace SHADE
{ {
dbgDrawSys->DrawSphere(color, pos, radius); dbgDrawSys->DrawSphere(color, pos, radius);
} }
void SHDebugDraw::PersistentLine(const SHVec4& color, const SHVec3& startPt, const SHVec3& endPt)
{
dbgDrawSys->DrawPersistentLine(color, startPt, endPt);
}
void SHDebugDraw::PersistentTri(const SHVec4& color, const SHVec3& pt1, const SHVec3& pt2, const SHVec3& pt3)
{
dbgDrawSys->DrawPersistentTri(color, pt1, pt2, pt3);
}
void SHDebugDraw::PersistentQuad(const SHVec4& color, const SHVec3& pt1, const SHVec3& pt2, const SHVec3& pt3, const SHVec3& pt4)
{
dbgDrawSys->DrawPersistentQuad(color, pt1, pt2, pt3, pt4);
}
void SHDebugDraw::PersistentPoly(const SHVec4& color, std::initializer_list<SHVec3> pointList)
{
dbgDrawSys->DrawPersistentPoly(color, pointList);
}
void SHDebugDraw::PersistentCube(const SHVec4& color, const SHVec3& pos, const SHVec3& size)
{
dbgDrawSys->DrawPersistentCube(color, pos, size);
}
void SHDebugDraw::PersistentSphere(const SHVec4& color, const SHVec3& pos, double radius)
{
dbgDrawSys->DrawPersistentSphere(color, pos, radius);
}
void SHDebugDraw::ClearPersistentDraws()
{
dbgDrawSys->ClearPersistentDraws();
}
} }

View File

@ -92,6 +92,64 @@ namespace SHADE
/// <param name="size">Size of the rendered sphere.</param> /// <param name="size">Size of the rendered sphere.</param>
static void Sphere(const SHVec4& color, const SHVec3& pos, double radius); static void Sphere(const SHVec4& color, const SHVec3& pos, double radius);
/*---------------------------------------------------------------------------------*/
/* Persistent Draw Functions */
/*---------------------------------------------------------------------------------*/
/// <summary>
/// Renders a line between two points in world space that will persist until
/// ClearPersistentDraws() is called.
/// </summary>
/// <param name="color">Colour of the line.</param>
/// <param name="startPt">First point of the line.</param>
/// <param name="endPt">Second point of the line.</param>
static void PersistentLine(const SHVec4& color, const SHVec3& startPt, const SHVec3& endPt);
/// <summary>
/// Renders a triangle indicated by three points in world space that will persist
/// until ClearPersistentDraws() is called.
/// </summary>
/// <param name="color">Colour of the triangle.</param>
/// <param name="pt1">First point of the triangle.</param>
/// <param name="pt2">Second point of the triangle.</param>
/// <param name="pt3">Third point of the triangle.</param>
static void PersistentTri(const SHVec4& color, const SHVec3& pt1, const SHVec3& pt2, const SHVec3& pt3);
/// <summary>
/// Renders a quadrilateral indicated by four points in world space that will persist
/// until ClearPersistentDraws() is called.
/// </summary>
/// <param name="color">Colour of the quadrilateral.</param>
/// <param name="pt1">First point of the triangle.</param>
/// <param name="pt2">Second point of the quadrilateral.</param>
/// <param name="pt3">Third point of the quadrilateral.</param>
/// <param name="pt4">Third point of the quadrilateral.</param>
static void PersistentQuad(const SHVec4& color, const SHVec3& pt1, const SHVec3& pt2, const SHVec3& pt3, const SHVec3& pt4);
/// <summary>
/// Renders a polygon indicated by the specified set of points in world space that
/// will persist until ClearPersistentDraws() is called.
/// </summary>
/// <param name="color">Colour of the polygon.</param>
/// <param name="pointList">List of points for the polygon.</param>
static void PersistentPoly(const SHVec4& color, std::initializer_list<SHVec3> pointList);
/// <summary>
/// Renders a wireframe cube centered around the position specified in world space
/// that will persist until ClearPersistentDraws() is called.
/// </summary>
/// <param name="color">Colour of the cube.</param>
/// <param name="pos">Position where the cube wil be centered at.</param>
/// <param name="size">Size of the rendered cube.</param>
static void PersistentCube(const SHVec4& color, const SHVec3& pos, const SHVec3& size);
/// <summary>
/// Renders a wireframe sphere centered around the position specified in world space
/// that will persist until ClearPersistentDraws() is called.
/// </summary>
/// <param name="color">Colour of the sphere.</param>
/// <param name="pos">Position where the sphere wil be centered at.</param>
/// <param name="size">Size of the rendered sphere.</param>
static void PersistentSphere(const SHVec4& color, const SHVec3& pos, double radius);
/// <summary>
/// Clears any persistent drawn debug primitives.
/// </summary>
static void ClearPersistentDraws();
private: private:
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Static Data Members */ /* Static Data Members */

View File

@ -39,7 +39,7 @@ namespace SHADE
* @param[in] enumClassMember A member of the specified enum class. * @param[in] enumClassMember A member of the specified enum class.
* @returns The value of the enum class member in the output type. * @returns The value of the enum class member in the output type.
*/ */
template <IsEnum InputType, IsIntegral OutputType = int> template <IsEnum InputType, IsIntegral OutputType = std::underlying_type_t<InputType>>
static constexpr OutputType ConvertEnum(InputType enumClassMember) noexcept; static constexpr OutputType ConvertEnum(InputType enumClassMember) noexcept;
/** /**

View File

@ -148,6 +148,14 @@ namespace SHADE
{ {
return Convert::ToCLI(GetNativeComponent()->GetTorque()); return Convert::ToCLI(GetNativeComponent()->GetTorque());
} }
bool RigidBody::Interpolating::get()
{
return GetNativeComponent()->IsInterpolating();
}
void RigidBody::Interpolating::set(bool value)
{
GetNativeComponent()->SetInterpolate(value);
}
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Force Functions */ /* Force Functions */

View File

@ -129,6 +129,11 @@ namespace SHADE
{ {
Vector3 get(); Vector3 get();
} }
property bool Interpolating
{
bool get();
void set(bool value);
}
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* Force Functions */ /* Force Functions */