Lights WIP
This commit is contained in:
parent
0788084bbd
commit
8fb0eddcc1
|
@ -10,7 +10,7 @@ Collapsed=0
|
||||||
|
|
||||||
[Window][Hierarchy Panel]
|
[Window][Hierarchy Panel]
|
||||||
Pos=0,142
|
Pos=0,142
|
||||||
Size=387,918
|
Size=768,918
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000004,0
|
DockId=0x00000004,0
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ DockId=0x00000006,0
|
||||||
|
|
||||||
[Window][Profiler]
|
[Window][Profiler]
|
||||||
Pos=0,48
|
Pos=0,48
|
||||||
Size=387,92
|
Size=768,92
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000003,0
|
DockId=0x00000003,0
|
||||||
|
|
||||||
|
@ -38,17 +38,17 @@ Collapsed=0
|
||||||
DockId=0x00000002,0
|
DockId=0x00000002,0
|
||||||
|
|
||||||
[Window][ Viewport]
|
[Window][ Viewport]
|
||||||
Pos=389,48
|
Pos=770,48
|
||||||
Size=1258,1012
|
Size=877,1012
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000002,0
|
DockId=0x00000002,0
|
||||||
|
|
||||||
[Docking][Data]
|
[Docking][Data]
|
||||||
DockSpace ID=0xC5C9B8AB Window=0xBE4044E9 Pos=8,79 Size=1920,1012 Split=X
|
DockSpace ID=0xC5C9B8AB Window=0xBE4044E9 Pos=8,79 Size=1920,1012 Split=X
|
||||||
DockNode ID=0x00000005 Parent=0xC5C9B8AB SizeRef=1992,1036 Split=X
|
DockNode ID=0x00000005 Parent=0xC5C9B8AB SizeRef=1992,1036 Split=X
|
||||||
DockNode ID=0x00000001 Parent=0x00000005 SizeRef=387,1036 Split=Y Selected=0x1E6EB881
|
DockNode ID=0x00000001 Parent=0x00000005 SizeRef=768,1036 Split=Y Selected=0x1E6EB881
|
||||||
DockNode ID=0x00000003 Parent=0x00000001 SizeRef=225,94 Selected=0x1E6EB881
|
DockNode ID=0x00000003 Parent=0x00000001 SizeRef=225,94 Selected=0x1E6EB881
|
||||||
DockNode ID=0x00000004 Parent=0x00000001 SizeRef=225,940 Selected=0xE096E5AE
|
DockNode ID=0x00000004 Parent=0x00000001 SizeRef=225,940 Selected=0xE096E5AE
|
||||||
DockNode ID=0x00000002 Parent=0x00000005 SizeRef=1258,1036 CentralNode=1 Selected=0xB41284E7
|
DockNode ID=0x00000002 Parent=0x00000005 SizeRef=877,1036 CentralNode=1 Selected=0xB41284E7
|
||||||
DockNode ID=0x00000006 Parent=0xC5C9B8AB SizeRef=271,1036 Selected=0xE7039252
|
DockNode ID=0x00000006 Parent=0xC5C9B8AB SizeRef=271,1036 Selected=0xE7039252
|
||||||
|
|
||||||
|
|
|
@ -155,7 +155,7 @@ namespace SHADE
|
||||||
SHVkDebugMessenger::GenMessengerType(SH_DEBUG_MSG_TYPE::T_GENERAL, SH_DEBUG_MSG_TYPE::T_VALIDATION, SH_DEBUG_MSG_TYPE::T_PERFORMANCE));
|
SHVkDebugMessenger::GenMessengerType(SH_DEBUG_MSG_TYPE::T_GENERAL, SH_DEBUG_MSG_TYPE::T_VALIDATION, SH_DEBUG_MSG_TYPE::T_PERFORMANCE));
|
||||||
|
|
||||||
instanceDbgInfo.pfnUserCallback = SHVulkanDebugUtil::GenericDebugCallback;
|
instanceDbgInfo.pfnUserCallback = SHVulkanDebugUtil::GenericDebugCallback;
|
||||||
instanceInfo.pNext = static_cast<vk::DebugUtilsMessengerCreateInfoEXT*>(&instanceDbgInfo);
|
//instanceInfo.pNext = static_cast<vk::DebugUtilsMessengerCreateInfoEXT*>(&instanceDbgInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finally create the instance
|
// Finally create the instance
|
||||||
|
|
|
@ -49,7 +49,7 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
.Type = vk::DescriptorType::eStorageBufferDynamic,
|
.Type = vk::DescriptorType::eStorageBufferDynamic,
|
||||||
.Stage = vk::ShaderStageFlagBits::eFragment,
|
.Stage = vk::ShaderStageFlagBits::eFragment,
|
||||||
.BindPoint = SHGraphicsConstants::DescriptorSetBindings::LIGHTS_DATA,
|
.BindPoint = SHGraphicsConstants::DescriptorSetBindings::DIRECTIONAL_LIGHT_DATA,
|
||||||
.DescriptorCount = 1,
|
.DescriptorCount = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -101,7 +101,7 @@ namespace SHADE
|
||||||
|
|
||||||
*/
|
*/
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
static constexpr uint32_t LIGHTS_DATA = 0;
|
static constexpr uint32_t DIRECTIONAL_LIGHT_DATA = 0;
|
||||||
|
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
/*!
|
/*!
|
||||||
|
|
|
@ -0,0 +1,109 @@
|
||||||
|
#include "SHpch.h"
|
||||||
|
#include "SHLightComponent.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
void SHLightComponent::OnCreate(void)
|
||||||
|
{
|
||||||
|
lightData.Reset();
|
||||||
|
SetType(SH_LIGHT_TYPE::DIRECTIONAL);
|
||||||
|
indexInBuffer = std::numeric_limits<uint32_t>::max();
|
||||||
|
Unbind();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SHLightComponent::OnDestroy(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHLightComponent::SetPosition(SHVec3 position) noexcept
|
||||||
|
{
|
||||||
|
lightData.position = position;
|
||||||
|
MakeDirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SHLightComponent::SetType(SH_LIGHT_TYPE type) noexcept
|
||||||
|
{
|
||||||
|
lightData.type = type;
|
||||||
|
MakeDirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SHLightComponent::SetDirection(SHVec3 direction) noexcept
|
||||||
|
{
|
||||||
|
lightData.direction = direction;
|
||||||
|
MakeDirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SHLightComponent::SetDiffuseColor(SHVec4 diffuseColor) noexcept
|
||||||
|
{
|
||||||
|
lightData.diffuseColor = diffuseColor;
|
||||||
|
MakeDirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHLightComponent::ModifyLayer(uint8_t layerIndex, bool value) noexcept
|
||||||
|
{
|
||||||
|
if (value)
|
||||||
|
lightData.cullingMask |= (1u << layerIndex);
|
||||||
|
else
|
||||||
|
lightData.cullingMask &= ~(1u << layerIndex);
|
||||||
|
|
||||||
|
MakeDirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SHLightComponent::SetAllLayers(void) noexcept
|
||||||
|
{
|
||||||
|
lightData.cullingMask = std::numeric_limits<uint32_t>::max();
|
||||||
|
MakeDirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SHLightComponent::ClearAllLayers(void) noexcept
|
||||||
|
{
|
||||||
|
lightData.cullingMask = 0;
|
||||||
|
MakeDirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHLightComponent::MakeDirty(void) noexcept
|
||||||
|
{
|
||||||
|
dirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHLightComponent::ClearDirtyFlag(void) noexcept
|
||||||
|
{
|
||||||
|
dirty = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHLightComponent::Unbind(void) noexcept
|
||||||
|
{
|
||||||
|
bound = false;
|
||||||
|
MakeDirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHLightComponent::SetBound(void) noexcept
|
||||||
|
{
|
||||||
|
bound = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
SHLightData const& SHLightComponent::GetLightData(void) const noexcept
|
||||||
|
{
|
||||||
|
return lightData;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SHLightComponent::IsDirty(void) const noexcept
|
||||||
|
{
|
||||||
|
return dirty;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SHLightComponent::GetBound(void) const noexcept
|
||||||
|
{
|
||||||
|
return bound;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "ECS_Base/Components/SHComponent.h"
|
||||||
|
#include "SHLightData.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
|
||||||
|
class SH_API SHLightComponent final : public SHComponent
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
//! General data for the light. This will purely be CPU bound. Whatever gets sent to the
|
||||||
|
//! GPU depends on the type of the light.
|
||||||
|
SHLightData lightData;
|
||||||
|
|
||||||
|
//! Since the lighting system is gonna be self contained and light weight, we store this
|
||||||
|
//! so that we only write this to the CPU buffer when this light component change, we don't
|
||||||
|
//! rewrite everything. However we still write to the GPU buffer when everything changes.
|
||||||
|
uint32_t indexInBuffer;
|
||||||
|
|
||||||
|
//! If the light component changed some value we mark this true.
|
||||||
|
bool dirty;
|
||||||
|
|
||||||
|
//! If the light's data is already in the buffers, this will be set to true.
|
||||||
|
bool bound;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
/* LIFECYCLE FUNCTIONS */
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
void OnCreate (void) override final;
|
||||||
|
void OnDestroy (void) override final;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
/* SETTERS AND GETTERS */
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
void SetPosition (SHVec3 position) noexcept;
|
||||||
|
void SetType (SH_LIGHT_TYPE type) noexcept;
|
||||||
|
void SetDirection (SHVec3 direction) noexcept;
|
||||||
|
void SetDiffuseColor (SHVec4 diffuseColor) noexcept;
|
||||||
|
void ModifyLayer (uint8_t layerIndex, bool value) noexcept;
|
||||||
|
void SetAllLayers (void) noexcept;
|
||||||
|
void ClearAllLayers (void) noexcept;
|
||||||
|
void MakeDirty (void) noexcept;
|
||||||
|
void ClearDirtyFlag (void) noexcept;
|
||||||
|
void Unbind (void) noexcept;
|
||||||
|
void SetBound (void) noexcept;
|
||||||
|
|
||||||
|
SHLightData const& GetLightData (void) const noexcept;
|
||||||
|
bool IsDirty (void) const noexcept;
|
||||||
|
bool GetBound (void) const noexcept;
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
#include "SHpch.h"
|
||||||
|
#include "SHLightData.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
void SHLightData::Reset(void) noexcept
|
||||||
|
{
|
||||||
|
// no culling is done.
|
||||||
|
cullingMask = std::numeric_limits<uint32_t>::max();
|
||||||
|
|
||||||
|
// reset position to 0
|
||||||
|
position = SHVec3::Zero;
|
||||||
|
|
||||||
|
// direction just point in positive z axis
|
||||||
|
direction = SHVec3::Forward;
|
||||||
|
|
||||||
|
// Diffuse color set to 1
|
||||||
|
diffuseColor = SHVec4::One;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Math/Vector/SHVec3.h"
|
||||||
|
#include "Math/Vector/SHVec4.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
enum class SH_LIGHT_TYPE : uint32_t
|
||||||
|
{
|
||||||
|
DIRECTIONAL = 0,
|
||||||
|
POINT,
|
||||||
|
SPOT,
|
||||||
|
NUM_TYPES
|
||||||
|
};
|
||||||
|
|
||||||
|
/***************************************************************************/
|
||||||
|
/*!
|
||||||
|
|
||||||
|
\class
|
||||||
|
Every light will essentially be using this struct. However, when passing
|
||||||
|
light data over to the GPU, the light data will be split according to
|
||||||
|
type for more optimal cache access.
|
||||||
|
|
||||||
|
*/
|
||||||
|
/***************************************************************************/
|
||||||
|
struct SHLightData
|
||||||
|
{
|
||||||
|
//! position of the light
|
||||||
|
SHVec3 position;
|
||||||
|
|
||||||
|
//! Type of the light
|
||||||
|
SH_LIGHT_TYPE type;
|
||||||
|
|
||||||
|
//! direction of the light
|
||||||
|
SHVec3 direction;
|
||||||
|
|
||||||
|
//! Each bit in this 32 bit field will represent a layer. If the bit is set,
|
||||||
|
//! when a fragment is being evaluated, the shader will use the fragment's
|
||||||
|
//! layer value to AND with the light's. If result is 1, do lighting calculations.
|
||||||
|
uint32_t cullingMask;
|
||||||
|
|
||||||
|
//! Diffuse color emitted by the light
|
||||||
|
SHVec4 diffuseColor;
|
||||||
|
|
||||||
|
void Reset (void) noexcept;
|
||||||
|
//! TODO:
|
||||||
|
//! - Add cut off. (inner and outer).
|
||||||
|
//! - Add constant, linear and quadratic for attenuation
|
||||||
|
//! - Specular color if needed. see below.
|
||||||
|
|
||||||
|
//! Specular color
|
||||||
|
//SHVec4 specularColor;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,250 @@
|
||||||
|
#include "SHpch.h"
|
||||||
|
#include "SHLightingSubSystem.h"
|
||||||
|
#include "Graphics/MiddleEnd/GlobalData/SHGraphicsGlobalData.h"
|
||||||
|
#include "Tools/SHUtilities.h"
|
||||||
|
#include "Graphics/Devices/SHVkLogicalDevice.h"
|
||||||
|
#include "Graphics/Buffers/SHVkBuffer.h"
|
||||||
|
#include "Graphics/Descriptors/SHVkDescriptorSetGroup.h"
|
||||||
|
#include "SHLightComponent.h"
|
||||||
|
#include "ECS_Base/Managers/SHComponentManager.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
|
||||||
|
/***************************************************************************/
|
||||||
|
/*!
|
||||||
|
|
||||||
|
\brief
|
||||||
|
Initializes type, intermediate data and buffer. dirty will be true.
|
||||||
|
|
||||||
|
\param lightType
|
||||||
|
type of the light.
|
||||||
|
|
||||||
|
*/
|
||||||
|
/***************************************************************************/
|
||||||
|
void SHLightingSubSystem::PerTypeData::InitializeData(Handle<SHVkLogicalDevice> logicalDevice, SH_LIGHT_TYPE type) noexcept
|
||||||
|
{
|
||||||
|
// initialize the type
|
||||||
|
lightType = type;
|
||||||
|
|
||||||
|
// we want to write to GPU when system runs
|
||||||
|
dirty = true;
|
||||||
|
|
||||||
|
// boilerplate
|
||||||
|
intermediateData = nullptr;
|
||||||
|
numLights = 0;
|
||||||
|
|
||||||
|
// initialize alignment
|
||||||
|
lightDataAlignmentSize = logicalDevice->PadSSBOSize(GetLightTypeSize(type));
|
||||||
|
|
||||||
|
// So create some data!
|
||||||
|
Expand(logicalDevice);
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************************************/
|
||||||
|
/*!
|
||||||
|
|
||||||
|
\brief
|
||||||
|
Expands both the CPU container and the GPU buffer when the number of
|
||||||
|
lights have exceeded
|
||||||
|
|
||||||
|
*/
|
||||||
|
/***************************************************************************/
|
||||||
|
void SHLightingSubSystem::PerTypeData::Expand(Handle<SHVkLogicalDevice> logicalDevice) noexcept
|
||||||
|
{
|
||||||
|
// we want to wait for the command buffers to finish using the buffers first
|
||||||
|
logicalDevice->WaitIdle();
|
||||||
|
|
||||||
|
// this is for CPU buffer.
|
||||||
|
uint32_t structSize = GetLightTypeSize(lightType);
|
||||||
|
|
||||||
|
// First time we are initializing lights
|
||||||
|
if (intermediateData == nullptr)
|
||||||
|
{
|
||||||
|
// num lights should start of at STARTING_NUM_LIGHTS lights
|
||||||
|
numLights = STARTING_NUM_LIGHTS;
|
||||||
|
|
||||||
|
// Initialize the data for lights
|
||||||
|
intermediateData = std::make_unique<uint8_t[]>(lightDataAlignmentSize * STARTING_NUM_LIGHTS);
|
||||||
|
|
||||||
|
dataBuffer = logicalDevice->CreateBuffer(numLights * lightDataAlignmentSize, nullptr, numLights * lightDataAlignmentSize, vk::BufferUsageFlagBits::eStorageBuffer, VMA_MEMORY_USAGE_AUTO, VMA_ALLOCATION_CREATE_MAPPED_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// save old number of lights
|
||||||
|
uint32_t const OLD_NUM_LIGHTS = numLights;
|
||||||
|
|
||||||
|
// before we increase the number of lights, create space to store old data.
|
||||||
|
std::unique_ptr<uint8_t[]> oldData = std::make_unique<uint8_t[]>(lightDataAlignmentSize * OLD_NUM_LIGHTS);
|
||||||
|
|
||||||
|
// copy data over.
|
||||||
|
std::memcpy (oldData.get(), intermediateData.get(), lightDataAlignmentSize * OLD_NUM_LIGHTS);
|
||||||
|
|
||||||
|
// now we start to expand....
|
||||||
|
|
||||||
|
// double space for lights
|
||||||
|
numLights *= 2;
|
||||||
|
|
||||||
|
// destroy old data and initialize container for double the amount of data.
|
||||||
|
intermediateData = std::make_unique<uint8_t[]>(lightDataAlignmentSize * numLights);
|
||||||
|
|
||||||
|
// copy old data to new container
|
||||||
|
std::memcpy(intermediateData.get(), oldData.get(), lightDataAlignmentSize * OLD_NUM_LIGHTS);
|
||||||
|
|
||||||
|
// Resize the GPU buffer
|
||||||
|
dataBuffer->ResizeReplace(lightDataAlignmentSize * numLights, oldData.get(), lightDataAlignmentSize * OLD_NUM_LIGHTS);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************************************/
|
||||||
|
/*!
|
||||||
|
|
||||||
|
\brief
|
||||||
|
This function takes in a light comp in the event that its data has not
|
||||||
|
been placed in the buffer yet. It also checks if the size of the buffer
|
||||||
|
is big enough
|
||||||
|
|
||||||
|
\param lightComp
|
||||||
|
|
||||||
|
\return
|
||||||
|
|
||||||
|
*/
|
||||||
|
/***************************************************************************/
|
||||||
|
void SHLightingSubSystem::PerTypeData::AddLight(SHLightComponent* lightComp) noexcept
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************************************/
|
||||||
|
/*!
|
||||||
|
|
||||||
|
\brief
|
||||||
|
Gets the size required to store data for a light type.
|
||||||
|
|
||||||
|
\param type
|
||||||
|
Type of a light.
|
||||||
|
|
||||||
|
\return
|
||||||
|
Size required to store a light based on type.
|
||||||
|
|
||||||
|
*/
|
||||||
|
/***************************************************************************/
|
||||||
|
uint32_t SHLightingSubSystem::PerTypeData::GetLightTypeSize(SH_LIGHT_TYPE type) noexcept
|
||||||
|
{
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case SH_LIGHT_TYPE::DIRECTIONAL:
|
||||||
|
// TOOD: Change after creating point light struct
|
||||||
|
return 0;
|
||||||
|
case SH_LIGHT_TYPE::POINT:
|
||||||
|
return sizeof (SHDirectionalLightData);
|
||||||
|
case SH_LIGHT_TYPE::SPOT:
|
||||||
|
// TOOD: Change after creating spot light struct
|
||||||
|
return 0;
|
||||||
|
case SH_LIGHT_TYPE::NUM_TYPES:
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Handle<SHVkBuffer> SHLightingSubSystem::PerTypeData::GetDataBuffer(void) const noexcept
|
||||||
|
{
|
||||||
|
return dataBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t SHLightingSubSystem::PerTypeData::GetAlignmentSize(void) const noexcept
|
||||||
|
{
|
||||||
|
return lightDataAlignmentSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHLightingSubSystem::UpdateDescSet(uint32_t binding) noexcept
|
||||||
|
{
|
||||||
|
auto buffer = perTypeData[binding].GetDataBuffer();
|
||||||
|
|
||||||
|
// We bind the buffer with the correct desc set binding
|
||||||
|
lightingDataDescSet->ModifyWriteDescBuffer(SHGraphicsConstants::DescriptorSetIndex::DYNAMIC_GLOBALS,
|
||||||
|
binding,
|
||||||
|
{ &buffer, 1 },
|
||||||
|
0,
|
||||||
|
perTypeData[binding].GetAlignmentSize());
|
||||||
|
|
||||||
|
lightingDataDescSet->UpdateDescriptorSetBuffer(SHGraphicsConstants::DescriptorSetIndex::DYNAMIC_GLOBALS, binding);
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************************************/
|
||||||
|
/*!
|
||||||
|
|
||||||
|
\brief
|
||||||
|
Initializes per light type data. This includes buffers and descriptor
|
||||||
|
sets.
|
||||||
|
|
||||||
|
|
||||||
|
*/
|
||||||
|
/***************************************************************************/
|
||||||
|
void SHLightingSubSystem::Init(Handle<SHVkLogicalDevice> logicalDevice, Handle<SHVkDescriptorPool> descPool) noexcept
|
||||||
|
{
|
||||||
|
std::vector<uint32_t> variableSizes{ SHUtilities::ToUnderlying(SH_LIGHT_TYPE::NUM_TYPES) };
|
||||||
|
std::fill (variableSizes.begin(), variableSizes.end(), 1);
|
||||||
|
|
||||||
|
// Create the descriptor set
|
||||||
|
lightingDataDescSet = descPool->Allocate({SHGraphicsGlobalData::GetDescSetLayouts()[SHGraphicsConstants::DescriptorSetIndex::DYNAMIC_GLOBALS]}, variableSizes);
|
||||||
|
|
||||||
|
// initialize all the data first. We add more lights here as we add more types.
|
||||||
|
perTypeData[SHUtilities::ToUnderlying(SH_LIGHT_TYPE::DIRECTIONAL)].InitializeData(logicalDevice, SH_LIGHT_TYPE::DIRECTIONAL);
|
||||||
|
UpdateDescSet(SHGraphicsConstants::DescriptorSetBindings::DIRECTIONAL_LIGHT_DATA);
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************************************/
|
||||||
|
/*!
|
||||||
|
|
||||||
|
\brief
|
||||||
|
Loops through every single light component and checks for dirty light
|
||||||
|
data. If light data is dirty, rewrite to the CPU container and do a
|
||||||
|
copy to the GPU data. We also check if the per light type data is too small
|
||||||
|
to handle more lights, if it is, expand buffer (both CPU and GPU).
|
||||||
|
|
||||||
|
*/
|
||||||
|
/***************************************************************************/
|
||||||
|
void SHLightingSubSystem::Run(void) noexcept
|
||||||
|
{
|
||||||
|
auto& lightComps = SHComponentManager::GetDense<SHLightComponent>();
|
||||||
|
for (auto& light : lightComps)
|
||||||
|
{
|
||||||
|
// First we want to make sure the light is already bound to the system. if it
|
||||||
|
// isn't, we write it to the correct buffer.
|
||||||
|
if (!light.GetBound())
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
light.SetBound();
|
||||||
|
}
|
||||||
|
|
||||||
|
// if there was modification to the light data
|
||||||
|
if (light.IsDirty())
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************************************/
|
||||||
|
/*!
|
||||||
|
|
||||||
|
\brief
|
||||||
|
Does nothing for now.
|
||||||
|
|
||||||
|
*/
|
||||||
|
/***************************************************************************/
|
||||||
|
void SHLightingSubSystem::Exit(void) noexcept
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,109 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Resource/SHHandle.h"
|
||||||
|
#include "Math/Vector/SHVec3.h"
|
||||||
|
#include "Math/Vector/SHVec4.h"
|
||||||
|
#include "SHLightData.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
class SHVkLogicalDevice;
|
||||||
|
class SHVkDescriptorPool;
|
||||||
|
class SHVkDescriptorSetGroup;
|
||||||
|
class SHVkDescriptorSetLayout;
|
||||||
|
class SHVkBuffer;
|
||||||
|
|
||||||
|
// Represents how the data will be interpreted in GPU. we want to copy to a container of these before passing to GPU.
|
||||||
|
struct SHDirectionalLightData
|
||||||
|
{
|
||||||
|
//! Direction of the light
|
||||||
|
SHVec3 direction;
|
||||||
|
|
||||||
|
//! Each bit in this 32 bit field will represent a layer. If the bit is set,
|
||||||
|
//! when a fragment is being evaluated, the shader will use the fragment's
|
||||||
|
//! layer value to AND with the light's. If result is 1, do lighting calculations.
|
||||||
|
uint32_t cullingMask;
|
||||||
|
|
||||||
|
//! Diffuse color emitted by the light
|
||||||
|
SHVec4 diffuseColor;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class SHLightingSubSystem
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
class PerTypeData
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
/* STATIC MEMBER VARIABLES */
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
static constexpr uint32_t STARTING_NUM_LIGHTS = 20;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
/* PRIVATE MEMBER VARIABLES */
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
//! SSBOs need to be aligned. This is to pad lighting structs
|
||||||
|
uint32_t lightDataAlignmentSize;
|
||||||
|
|
||||||
|
//! type of the light. Will be used later when we want to expand
|
||||||
|
SH_LIGHT_TYPE lightType;
|
||||||
|
|
||||||
|
//! number of lights currently alive.
|
||||||
|
uint32_t numLights;
|
||||||
|
|
||||||
|
//! if intermediateData has been modified(i.e. any 1 light's data is changed), set to true.
|
||||||
|
bool dirty;
|
||||||
|
|
||||||
|
//! GPU buffer required to store GPU data
|
||||||
|
Handle<SHVkBuffer> dataBuffer;
|
||||||
|
|
||||||
|
//! Before data gets copied to the GPU, it goes into here first. Data here is aligned to whatever struct is
|
||||||
|
//! used to represent data in this container.
|
||||||
|
std::unique_ptr<uint8_t[]> intermediateData;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
/* PUBLIC MEMBER FUNCTIONS */
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
void InitializeData (Handle<SHVkLogicalDevice> logicalDevice, SH_LIGHT_TYPE type) noexcept;
|
||||||
|
void Expand (Handle<SHVkLogicalDevice> logicalDevice) noexcept;
|
||||||
|
void AddLight (SHLightComponent* lightComp) noexcept;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
/* GETTERS */
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
static uint32_t GetLightTypeSize (SH_LIGHT_TYPE type) noexcept;
|
||||||
|
Handle<SHVkBuffer> GetDataBuffer (void) const noexcept;
|
||||||
|
uint32_t GetAlignmentSize (void) const noexcept;
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
//! logical device used for creation
|
||||||
|
Handle<SHVkLogicalDevice> logicalDevice;
|
||||||
|
|
||||||
|
//! The descriptor set that will hold the lighting data. Each binding will hold a buffer, NUM_FRAMES times the size required.
|
||||||
|
Handle<SHVkDescriptorSetGroup> lightingDataDescSet;
|
||||||
|
|
||||||
|
//! Each type will have some data associated with it for processing
|
||||||
|
std::array<PerTypeData, static_cast<uint32_t>(SH_LIGHT_TYPE::NUM_TYPES)> perTypeData;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
/* PRIVATE MEMBER FUNCTIONS */
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
void UpdateDescSet (uint32_t binding) noexcept;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
/* PUBLIC MEMBER FUNCTIONS */
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
void Init (Handle<SHVkLogicalDevice> logicalDevice, Handle<SHVkDescriptorPool> descPool) noexcept;
|
||||||
|
void Run (void) noexcept;
|
||||||
|
void Exit (void) noexcept;
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
|
@ -42,6 +42,15 @@ namespace SHADE
|
||||||
template <IsEnum InputType, IsIntegral OutputType = int>
|
template <IsEnum InputType, IsIntegral OutputType = int>
|
||||||
static constexpr OutputType ConvertEnum(InputType enumClassMember) noexcept;
|
static constexpr OutputType ConvertEnum(InputType enumClassMember) noexcept;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Converts an enum class member from it's type to the underlying type.
|
||||||
|
* @tparam Enum Restricted to an enum class
|
||||||
|
* @param[in] value A member of the specified enum class.
|
||||||
|
* @returns The value of the enum class member in the output type.
|
||||||
|
*/
|
||||||
|
template<typename Enum>
|
||||||
|
static constexpr typename std::underlying_type_t<Enum> ToUnderlying (Enum value) noexcept;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace SHADE
|
} // namespace SHADE
|
||||||
|
|
|
@ -25,4 +25,10 @@ namespace SHADE
|
||||||
return static_cast<OutputType>(enumClassMember);
|
return static_cast<OutputType>(enumClassMember);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename Enum>
|
||||||
|
constexpr typename std::underlying_type_t<Enum> SHUtilities::ToUnderlying(Enum value) noexcept
|
||||||
|
{
|
||||||
|
return static_cast<typename std::underlying_type_t<Enum>>(value);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace SHADE
|
} // namespace SHADE
|
Loading…
Reference in New Issue