Merge branch 'main' into SP3-141-Camera-System
This commit is contained in:
commit
d8086edbe2
|
@ -0,0 +1,5 @@
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*.{c,cpp,h,hpp}]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
|
@ -1,3 +1,3 @@
|
||||||
Name: Cube.003
|
Name: Cube.003
|
||||||
ID: 110152941
|
ID: 110152941
|
||||||
Type:
|
Type: 6
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
Name: Cube.012
|
Name: Cube.012
|
||||||
ID: 107348815
|
ID: 107348815
|
||||||
Type:
|
Type: 6
|
||||||
|
|
|
@ -4,13 +4,13 @@ Size=1920,20
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
|
|
||||||
[Window][SHEditorMenuBar]
|
[Window][SHEditorMenuBar]
|
||||||
Pos=0,24
|
Pos=0,48
|
||||||
Size=1920,1036
|
Size=1920,1012
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
|
|
||||||
[Window][Hierarchy Panel]
|
[Window][Hierarchy Panel]
|
||||||
Pos=0,120
|
Pos=0,197
|
||||||
Size=225,940
|
Size=308,863
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000004,0
|
DockId=0x00000004,0
|
||||||
|
|
||||||
|
@ -20,29 +20,96 @@ Size=400,400
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
|
|
||||||
[Window][Inspector]
|
[Window][Inspector]
|
||||||
Pos=1686,24
|
Pos=1528,48
|
||||||
Size=234,1036
|
Size=392,1012
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000006,0
|
DockId=0x00000006,0
|
||||||
|
|
||||||
[Window][Profiler]
|
[Window][Profiler]
|
||||||
Pos=0,24
|
Pos=0,48
|
||||||
Size=225,94
|
Size=308,147
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000003,0
|
DockId=0x00000003,0
|
||||||
|
|
||||||
[Window][Viewport]
|
[Window][Viewport]
|
||||||
Pos=227,24
|
Pos=227,48
|
||||||
Size=1457,1036
|
Size=1457,1012
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000002,0
|
DockId=0x0000000B,0
|
||||||
|
|
||||||
|
[Window][ÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌð‡Žoû]
|
||||||
|
Pos=60,60
|
||||||
|
Size=32,64
|
||||||
|
Collapsed=0
|
||||||
|
|
||||||
|
[Window][ÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌ]
|
||||||
|
Pos=60,60
|
||||||
|
Size=999,581
|
||||||
|
Collapsed=0
|
||||||
|
|
||||||
|
[Window][ð‡–oû]
|
||||||
|
Pos=60,60
|
||||||
|
Size=32,64
|
||||||
|
Collapsed=0
|
||||||
|
|
||||||
|
[Window][ÌÌÌÌ]
|
||||||
|
Pos=60,60
|
||||||
|
Size=553,422
|
||||||
|
Collapsed=0
|
||||||
|
|
||||||
|
[Window][]
|
||||||
|
Pos=60,60
|
||||||
|
Size=770,394
|
||||||
|
Collapsed=0
|
||||||
|
|
||||||
|
[Window][ Viewport]
|
||||||
|
Pos=227,48
|
||||||
|
Size=1457,1012
|
||||||
|
Collapsed=0
|
||||||
|
DockId=0x0000000B,0
|
||||||
|
|
||||||
|
[Window][ Viewport]
|
||||||
|
Pos=227,48
|
||||||
|
Size=1457,1012
|
||||||
|
Collapsed=0
|
||||||
|
DockId=0x0000000B,0
|
||||||
|
|
||||||
|
[Window][î<>‹ Viewport]
|
||||||
|
Pos=310,48
|
||||||
|
Size=1216,715
|
||||||
|
Collapsed=0
|
||||||
|
DockId=0x0000000B,0
|
||||||
|
|
||||||
|
[Window][V]
|
||||||
|
Pos=310,722
|
||||||
|
Size=1501,338
|
||||||
|
Collapsed=0
|
||||||
|
DockId=0x00000008,0
|
||||||
|
|
||||||
|
[Window][p›£€Ê]
|
||||||
|
Pos=310,750
|
||||||
|
Size=1501,310
|
||||||
|
Collapsed=0
|
||||||
|
DockId=0x0000000A,0
|
||||||
|
|
||||||
|
[Window][ Asset Browser]
|
||||||
|
Pos=310,765
|
||||||
|
Size=1216,295
|
||||||
|
Collapsed=0
|
||||||
|
DockId=0x0000000C,0
|
||||||
|
|
||||||
[Docking][Data]
|
[Docking][Data]
|
||||||
DockSpace ID=0xC5C9B8AB Window=0xBE4044E9 Pos=8,55 Size=1920,1036 Split=X
|
DockSpace ID=0xC5C9B8AB Window=0xBE4044E9 Pos=8,79 Size=1920,1012 Split=X
|
||||||
DockNode ID=0x00000005 Parent=0xC5C9B8AB SizeRef=1684,1036 Split=X
|
DockNode ID=0x00000005 Parent=0xC5C9B8AB SizeRef=1526,1036 Split=X
|
||||||
DockNode ID=0x00000001 Parent=0x00000005 SizeRef=225,1036 Split=Y Selected=0x1E6EB881
|
DockNode ID=0x00000001 Parent=0x00000005 SizeRef=308,1036 Split=Y Selected=0x1E6EB881
|
||||||
DockNode ID=0x00000003 Parent=0x00000001 SizeRef=225,94 Selected=0x1E6EB881
|
DockNode ID=0x00000003 Parent=0x00000001 SizeRef=225,147 Selected=0x1E6EB881
|
||||||
DockNode ID=0x00000004 Parent=0x00000001 SizeRef=225,940 Selected=0xE096E5AE
|
DockNode ID=0x00000004 Parent=0x00000001 SizeRef=225,863 Selected=0xE096E5AE
|
||||||
DockNode ID=0x00000002 Parent=0x00000005 SizeRef=1293,1036 CentralNode=1 Selected=0x13926F0B
|
DockNode ID=0x00000002 Parent=0x00000005 SizeRef=1216,1036 Split=Y Selected=0xB41284E7
|
||||||
DockNode ID=0x00000006 Parent=0xC5C9B8AB SizeRef=234,1036 Selected=0xE7039252
|
DockNode ID=0x00000007 Parent=0x00000002 SizeRef=1501,672 Split=Y Selected=0xB41284E7
|
||||||
|
DockNode ID=0x00000009 Parent=0x00000007 SizeRef=1501,700 Split=Y Selected=0xB41284E7
|
||||||
|
DockNode ID=0x0000000B Parent=0x00000009 SizeRef=1501,715 CentralNode=1 Selected=0xB41284E7
|
||||||
|
DockNode ID=0x0000000C Parent=0x00000009 SizeRef=1501,295 Selected=0xB128252A
|
||||||
|
DockNode ID=0x0000000A Parent=0x00000007 SizeRef=1501,310 Selected=0xD446F7B6
|
||||||
|
DockNode ID=0x00000008 Parent=0x00000002 SizeRef=1501,338 Selected=0xD9F31532
|
||||||
|
DockNode ID=0x00000006 Parent=0xC5C9B8AB SizeRef=392,1036 Selected=0xE7039252
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
Name: RaccoonPreTexturedVer1_Base9
|
Name: RaccoonPreTexturedVer1_Base9
|
||||||
ID: 91918845
|
ID: 91918845
|
||||||
Type:
|
Type: 4
|
||||||
|
|
|
@ -56,8 +56,8 @@ namespace Sandbox
|
||||||
_In_ INT nCmdShow
|
_In_ INT nCmdShow
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
// Set working directory
|
// Set working directory
|
||||||
SHFileUtilities::SetWorkDirToExecDir();
|
SHFileUtilities::SetWorkDirToExecDir();
|
||||||
|
|
||||||
window.Create(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
|
window.Create(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
|
||||||
|
|
||||||
|
@ -83,16 +83,19 @@ namespace Sandbox
|
||||||
SHSystemManager::RegisterRoutine<SHScriptEngine, SHScriptEngine::LateUpdateRoutine>();
|
SHSystemManager::RegisterRoutine<SHScriptEngine, SHScriptEngine::LateUpdateRoutine>();
|
||||||
SHSystemManager::RegisterRoutine<SHScriptEngine, SHScriptEngine::FrameCleanUpRoutine>();
|
SHSystemManager::RegisterRoutine<SHScriptEngine, SHScriptEngine::FrameCleanUpRoutine>();
|
||||||
|
|
||||||
|
SHSystemManager::RegisterRoutine<SHTransformSystem, SHTransformSystem::TransformPostLogicUpdate>();
|
||||||
|
|
||||||
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<SHTransformSystem, SHTransformSystem::TransformUpdateRoutine>();
|
SHSystemManager::RegisterRoutine<SHTransformSystem, SHTransformSystem::TransformPostPhysicsUpdate>();
|
||||||
|
|
||||||
SHSystemManager::RegisterRoutine<SHGraphicsSystem, SHGraphicsSystem::BatcherDispatcherRoutine>();
|
SHSystemManager::RegisterRoutine<SHGraphicsSystem, SHGraphicsSystem::BatcherDispatcherRoutine>();
|
||||||
SHSystemManager::RegisterRoutine<SHGraphicsSystem, SHGraphicsSystem::BeginRoutine>();
|
SHSystemManager::RegisterRoutine<SHGraphicsSystem, SHGraphicsSystem::BeginRoutine>();
|
||||||
|
|
||||||
SHSystemManager::RegisterRoutine<SHCameraSystem, SHCameraSystem::EditorCameraUpdate>();
|
SHSystemManager::RegisterRoutine<SHCameraSystem, SHCameraSystem::EditorCameraUpdate>();
|
||||||
|
SHSystemManager::RegisterRoutine<SHCameraSystem, SHCameraSystem::CameraSystemUpdate>();
|
||||||
|
|
||||||
#ifdef SHEDITOR
|
#ifdef SHEDITOR
|
||||||
SHSystemManager::RegisterRoutine<SHEditor, SHEditor::EditorRoutine>();
|
SHSystemManager::RegisterRoutine<SHEditor, SHEditor::EditorRoutine>();
|
||||||
|
@ -149,16 +152,16 @@ namespace Sandbox
|
||||||
SHSceneManager::SceneUpdate(0.016f);
|
SHSceneManager::SceneUpdate(0.016f);
|
||||||
#endif
|
#endif
|
||||||
SHSystemManager::RunRoutines(editor->editorState != SHEditor::State::PLAY, 0.016f);
|
SHSystemManager::RunRoutines(editor->editorState != SHEditor::State::PLAY, 0.016f);
|
||||||
//editor->PollPicking();
|
editor->PollPicking();
|
||||||
}
|
}
|
||||||
// Finish all graphics jobs first
|
// Finish all graphics jobs first
|
||||||
graphicsSystem->AwaitGraphicsExecution();
|
graphicsSystem->AwaitGraphicsExecution();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void SBApplication::Exit(void)
|
void SBApplication::Exit(void)
|
||||||
{
|
{
|
||||||
#ifdef SHEDITOR
|
#ifdef SHEDITOR
|
||||||
SDL_DestroyWindow(sdlWindow);
|
SDL_DestroyWindow(sdlWindow);
|
||||||
SDL_Quit();
|
SDL_Quit();
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -12,8 +12,10 @@
|
||||||
#include "Graphics/MiddleEnd/Interface/SHMaterialInstance.h"
|
#include "Graphics/MiddleEnd/Interface/SHMaterialInstance.h"
|
||||||
#include "Physics/Components/SHRigidBodyComponent.h"
|
#include "Physics/Components/SHRigidBodyComponent.h"
|
||||||
#include "Physics/Components/SHColliderComponent.h"
|
#include "Physics/Components/SHColliderComponent.h"
|
||||||
|
#include "Graphics/MiddleEnd/Lights/SHLightComponent.h"
|
||||||
|
|
||||||
#include "Assets/SHAssetManager.h"
|
#include "Assets/SHAssetManager.h"
|
||||||
|
#include "Camera/SHCameraComponent.h"
|
||||||
#include "Resource/SHResourceManager.h"
|
#include "Resource/SHResourceManager.h"
|
||||||
|
|
||||||
using namespace SHADE;
|
using namespace SHADE;
|
||||||
|
@ -51,7 +53,7 @@ namespace Sandbox
|
||||||
if (asset.name == "Cube.012")
|
if (asset.name == "Cube.012")
|
||||||
handles.emplace_back(SHResourceManager::LoadOrGet<SHMesh>(asset.id));
|
handles.emplace_back(SHResourceManager::LoadOrGet<SHMesh>(asset.id));
|
||||||
break;
|
break;
|
||||||
case AssetType::TEXTURE:
|
case AssetType::IMAGE:
|
||||||
texHandles.emplace_back(SHResourceManager::LoadOrGet<SHTexture>(asset.id));
|
texHandles.emplace_back(SHResourceManager::LoadOrGet<SHTexture>(asset.id));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -66,9 +68,9 @@ namespace Sandbox
|
||||||
customMat->SetProperty("data.alpha", 0.1f);
|
customMat->SetProperty("data.alpha", 0.1f);
|
||||||
|
|
||||||
// Create Stress Test Objects
|
// Create Stress Test Objects
|
||||||
static const SHVec3 TEST_OBJ_SCALE = SHVec3::One * 0.5f;
|
static const SHVec3 TEST_OBJ_SCALE = SHVec3::One;
|
||||||
constexpr int NUM_ROWS = 0;
|
constexpr int NUM_ROWS = 3;
|
||||||
constexpr int NUM_COLS = 0;
|
constexpr int NUM_COLS = 1;
|
||||||
static const SHVec3 TEST_OBJ_SPACING = { 0.1f, 0.1f, 0.1f };
|
static const SHVec3 TEST_OBJ_SPACING = { 0.1f, 0.1f, 0.1f };
|
||||||
static const SHVec3 TEST_OBJ_START_POS = { -(NUM_COLS / 2 * TEST_OBJ_SPACING.x) + 1.0f, -2.0f, -1.0f };
|
static const SHVec3 TEST_OBJ_START_POS = { -(NUM_COLS / 2 * TEST_OBJ_SPACING.x) + 1.0f, -2.0f, -1.0f };
|
||||||
|
|
||||||
|
@ -90,13 +92,13 @@ namespace Sandbox
|
||||||
//Set initial positions
|
//Set initial positions
|
||||||
transform.SetWorldPosition(TEST_OBJ_START_POS + SHVec3{ x * TEST_OBJ_SPACING.x, y * TEST_OBJ_SPACING.y, SHMath::GenerateRandomNumber(-3.5f, -5.0f) });
|
transform.SetWorldPosition(TEST_OBJ_START_POS + SHVec3{ x * TEST_OBJ_SPACING.x, y * TEST_OBJ_SPACING.y, SHMath::GenerateRandomNumber(-3.5f, -5.0f) });
|
||||||
//transform.SetWorldPosition({-1.0f, -1.0f, -1.0f});
|
//transform.SetWorldPosition({-1.0f, -1.0f, -1.0f});
|
||||||
transform.SetWorldRotation(SHMath::GenerateRandomNumber(), SHMath::GenerateRandomNumber(), SHMath::GenerateRandomNumber());
|
transform.SetWorldRotation(SHMath::GenerateRandomNumber(0.0f, 360.0f), SHMath::GenerateRandomNumber(0.0f, 360.0f), SHMath::GenerateRandomNumber(0.0f, 360.0f));
|
||||||
transform.SetWorldScale(TEST_OBJ_SCALE);
|
transform.SetWorldScale(TEST_OBJ_SCALE);
|
||||||
|
|
||||||
if (const bool IS_EVEN = (y * NUM_ROWS + x) % 2; IS_EVEN)
|
//if (const bool IS_EVEN = (y * NUM_ROWS + x) % 2; IS_EVEN)
|
||||||
collider.AddBoundingBox(SHVec3::One * 0.5f, SHVec3::Zero);
|
collider.AddBoundingBox(SHVec3::One * 0.5f, SHVec3::Zero);
|
||||||
else
|
//else
|
||||||
collider.AddBoundingSphere(0.5f, SHVec3::Zero);
|
// collider.AddBoundingSphere(0.5f, SHVec3::Zero);
|
||||||
|
|
||||||
stressTestObjects.emplace_back(entity);
|
stressTestObjects.emplace_back(entity);
|
||||||
}
|
}
|
||||||
|
@ -155,6 +157,11 @@ namespace Sandbox
|
||||||
transformShowcase.SetWorldPosition({ 3.0f, -1.0f, -1.0f });
|
transformShowcase.SetWorldPosition({ 3.0f, -1.0f, -1.0f });
|
||||||
transformShowcase.SetLocalScale({ 5.0f, 5.0f, 5.0f });
|
transformShowcase.SetLocalScale({ 5.0f, 5.0f, 5.0f });
|
||||||
scriptEngine->AddScript(raccoonShowcase, "RaccoonShowcase");
|
scriptEngine->AddScript(raccoonShowcase, "RaccoonShowcase");
|
||||||
|
|
||||||
|
SHComponentManager::AddComponent<SHCameraComponent>(0);
|
||||||
|
SHComponentManager::AddComponent<SHLightComponent>(0);
|
||||||
|
SHComponentManager::RemoveComponent <SHRigidBodyComponent>(0);
|
||||||
|
SHComponentManager::RemoveComponent <SHColliderComponent>(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SBTestScene::Update(float dt)
|
void SBTestScene::Update(float dt)
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
/*************************************************************************//**
|
||||||
|
* \file SHAnimationAsset.h
|
||||||
|
* \author Loh Xiao Qi
|
||||||
|
* \date October 2022
|
||||||
|
* \brief
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||||
|
* disclosure of this file or its contents without the prior written consent
|
||||||
|
* of DigiPen Institute of Technology is prohibited.
|
||||||
|
*****************************************************************************/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <assimp/anim.h>
|
||||||
|
#include "SH_API.power h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
struct SH_API SHAnimationAsset
|
||||||
|
{
|
||||||
|
std::string name;
|
||||||
|
|
||||||
|
std::vector<aiNodeAnim*> nodeChannels;
|
||||||
|
std::vector<aiMeshAnim*> meshChannels;
|
||||||
|
std::vector<aiMeshMorphAnim*> morphMeshChannels;
|
||||||
|
|
||||||
|
double duration;
|
||||||
|
double ticksPerSecond;
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
/*************************************************************************//**
|
||||||
|
* \file SHAnimationAsset.h
|
||||||
|
* \author Loh Xiao Qi
|
||||||
|
* \date October 2022
|
||||||
|
* \brief
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||||
|
* disclosure of this file or its contents without the prior written consent
|
||||||
|
* of DigiPen Institute of Technology is prohibited.
|
||||||
|
*****************************************************************************/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <assimp/anim.h>
|
||||||
|
#include "SHAssetData.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
struct SH_API SHAnimationAsset : SHAssetData
|
||||||
|
{
|
||||||
|
std::string name;
|
||||||
|
|
||||||
|
std::vector<aiNodeAnim*> nodeChannels;
|
||||||
|
std::vector<aiMeshAnim*> meshChannels;
|
||||||
|
std::vector<aiMeshMorphAnim*> morphMeshChannels;
|
||||||
|
|
||||||
|
double duration;
|
||||||
|
double ticksPerSecond;
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
/*************************************************************************//**
|
||||||
|
* \file SHAssetDataBase.h
|
||||||
|
* \author Loh Xiao Qi
|
||||||
|
* \date October 2022
|
||||||
|
* \brief
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||||
|
* disclosure of this file or its contents without the prior written consent
|
||||||
|
* of DigiPen Institute of Technology is prohibited.
|
||||||
|
*****************************************************************************/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
struct SHAssetData
|
||||||
|
{
|
||||||
|
virtual ~SHAssetData(){}
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "SHMeshAsset.h"
|
||||||
|
#include "SHTextureAsset.h"
|
|
@ -0,0 +1,21 @@
|
||||||
|
/*************************************************************************//**
|
||||||
|
* \file SHInternalAsset.h
|
||||||
|
* \author Loh Xiao Qi
|
||||||
|
* \date October 2022
|
||||||
|
* \brief
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||||
|
* disclosure of this file or its contents without the prior written consent
|
||||||
|
* of DigiPen Institute of Technology is prohibited.
|
||||||
|
*****************************************************************************/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "SHAsset.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
struct SHInternalAsset : SHAsset
|
||||||
|
{
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
|
@ -14,7 +14,7 @@
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "Math/SHMath.h"
|
#include "Math/SHMath.h"
|
||||||
#include "SH_API.h"
|
#include "SHAssetData.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
@ -22,10 +22,10 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
uint32_t vertexCount;
|
uint32_t vertexCount;
|
||||||
uint32_t indexCount;
|
uint32_t indexCount;
|
||||||
std::string meshName;
|
std::string name;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SH_API SHMeshAsset
|
struct SH_API SHMeshAsset : SHAssetData
|
||||||
{
|
{
|
||||||
bool compiled;
|
bool compiled;
|
||||||
bool changed;
|
bool changed;
|
||||||
|
|
|
@ -2,10 +2,11 @@
|
||||||
|
|
||||||
#include "tinyddsloader.h"
|
#include "tinyddsloader.h"
|
||||||
#include "Graphics/MiddleEnd/Textures/SHTextureLibrary.h"
|
#include "Graphics/MiddleEnd/Textures/SHTextureLibrary.h"
|
||||||
|
#include "SHAssetData.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
struct SHTextureAsset
|
struct SHTextureAsset : SHAssetData
|
||||||
{
|
{
|
||||||
bool compiled;
|
bool compiled;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
/*************************************************************************//**
|
||||||
|
* \file SHAssetLoader.h
|
||||||
|
* \author Loh Xiao Qi
|
||||||
|
* \date October 2022
|
||||||
|
* \brief
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||||
|
* disclosure of this file or its contents without the prior written consent
|
||||||
|
* of DigiPen Institute of Technology is prohibited.
|
||||||
|
*****************************************************************************/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Assets/Asset Types/SHAssetData.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
struct SHAssetLoader
|
||||||
|
{
|
||||||
|
virtual SHAssetData* Load(AssetPath path) = 0;
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,141 @@
|
||||||
|
/*************************************************************************//**
|
||||||
|
* \file SHAssimpLibrary.cpp
|
||||||
|
* \author Loh Xiao Qi
|
||||||
|
* \date October 2022
|
||||||
|
* \brief
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||||
|
* disclosure of this file or its contents without the prior written consent
|
||||||
|
* of DigiPen Institute of Technology is prohibited.
|
||||||
|
*****************************************************************************/
|
||||||
|
#include "SHpch.h"
|
||||||
|
#include "SHAssimpLibrary.h"
|
||||||
|
#include <assimp/postprocess.h>
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
Assimp::Importer SHAssimpLibrary::aiImporter;
|
||||||
|
|
||||||
|
void SHAssimpLibrary::ProcessNode(aiNode const& node, aiScene const& scene, MeshVectorRef meshes) noexcept
|
||||||
|
{
|
||||||
|
for (size_t i {0}; i < node.mNumMeshes; ++i)
|
||||||
|
{
|
||||||
|
aiMesh* mesh = scene.mMeshes[node.mMeshes[i]];
|
||||||
|
meshes.push_back(ProcessMesh(*mesh));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i{ 0 }; i < node.mNumChildren; ++i)
|
||||||
|
{
|
||||||
|
ProcessNode(*node.mChildren[i], scene, meshes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHAssimpLibrary::ExtractAnimations(aiScene const& scene, AnimVectorRef anims) noexcept
|
||||||
|
{
|
||||||
|
if (scene.HasAnimations())
|
||||||
|
{
|
||||||
|
std::vector<SHAnimationAsset> anims(scene.mNumAnimations);
|
||||||
|
for (auto i{0}; i < scene.mNumAnimations; ++i)
|
||||||
|
{
|
||||||
|
auto const& anim {*scene.mAnimations[i]};
|
||||||
|
|
||||||
|
anims[i].name = anim.mName.C_Str();
|
||||||
|
|
||||||
|
anims[i].duration = anim.mDuration;
|
||||||
|
anims[i].ticksPerSecond = anim.mTicksPerSecond;
|
||||||
|
|
||||||
|
std::copy_n(anim.mChannels, anim.mNumChannels, anims[i].nodeChannels.data());
|
||||||
|
std::copy_n(anim.mMeshChannels, anim.mNumMeshChannels, anims[i].meshChannels.data());
|
||||||
|
std::copy_n(anim.mMorphMeshChannels, anim.mNumMorphMeshChannels, anims[i].morphMeshChannels.data());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SHMeshAsset* SHAssimpLibrary::ProcessMesh(aiMesh const& mesh) noexcept
|
||||||
|
{
|
||||||
|
SHMeshAsset* result = new SHMeshAsset();
|
||||||
|
result->compiled = false;
|
||||||
|
result->changed = false;
|
||||||
|
|
||||||
|
for (size_t i{0}; i < mesh.mNumVertices; ++i)
|
||||||
|
{
|
||||||
|
// Vertex position
|
||||||
|
SHVec3 vertex;
|
||||||
|
vertex.x = mesh.mVertices[i].x;
|
||||||
|
vertex.y = mesh.mVertices[i].y;
|
||||||
|
vertex.z = mesh.mVertices[i].z;
|
||||||
|
result->vertexPosition.push_back(vertex);
|
||||||
|
|
||||||
|
// Tex coords
|
||||||
|
SHVec2 texCoord{0.f, 0.f};
|
||||||
|
if (mesh.mTextureCoords[0])
|
||||||
|
{
|
||||||
|
texCoord.x = mesh.mTextureCoords[0][i].x;
|
||||||
|
texCoord.y = mesh.mTextureCoords[0][i].y;
|
||||||
|
}
|
||||||
|
result->texCoords.push_back(texCoord);
|
||||||
|
|
||||||
|
// Normals
|
||||||
|
SHVec3 normal{0.f, 0.f, 0.f};
|
||||||
|
if (mesh.mNormals)
|
||||||
|
{
|
||||||
|
normal.x = mesh.mNormals[i].x;
|
||||||
|
normal.y = mesh.mNormals[i].y;
|
||||||
|
normal.z = mesh.mNormals[i].z;
|
||||||
|
}
|
||||||
|
result->vertexNormal.push_back(normal);
|
||||||
|
|
||||||
|
// Tangent
|
||||||
|
SHVec3 tangent{0.f, 0.f, 0.f};
|
||||||
|
if (mesh.mTangents)
|
||||||
|
{
|
||||||
|
tangent.x = mesh.mTangents[i].x;
|
||||||
|
tangent.y = mesh.mTangents[i].y;
|
||||||
|
tangent.z = mesh.mTangents[i].z;
|
||||||
|
}
|
||||||
|
result->vertexTangent.push_back(tangent);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i {0}; i < mesh.mNumFaces; ++i)
|
||||||
|
{
|
||||||
|
aiFace face = mesh.mFaces[i];
|
||||||
|
for (size_t j{0}; j < face.mNumIndices; ++j)
|
||||||
|
{
|
||||||
|
result->indices.push_back(face.mIndices[j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result->header.vertexCount = static_cast<uint32_t>(result->vertexPosition.size());
|
||||||
|
result->header.indexCount = static_cast<uint32_t>(result->indices.size());
|
||||||
|
result->header.name = mesh.mName.C_Str();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHAssimpLibrary::LoadFromFile(AssetPath path, MeshVectorRef meshes, AnimVectorRef anims) noexcept
|
||||||
|
{
|
||||||
|
const aiScene* scene = aiImporter.ReadFile(path.string().c_str(),
|
||||||
|
aiProcess_Triangulate // Make sure we get triangles rather than nvert polygons
|
||||||
|
| aiProcess_GenUVCoords // Convert any type of mapping to uv mapping
|
||||||
|
| aiProcess_TransformUVCoords // preprocess UV transformations (scaling, translation ...)
|
||||||
|
| aiProcess_FindInstances // search for instanced meshes and remove them by references to one master
|
||||||
|
| aiProcess_CalcTangentSpace // calculate tangents and bitangents if possible
|
||||||
|
| aiProcess_JoinIdenticalVertices // join identical vertices/ optimize indexing
|
||||||
|
| aiProcess_RemoveRedundantMaterials // remove redundant materials
|
||||||
|
| aiProcess_FindInvalidData // detect invalid model data, such as invalid normal vectors
|
||||||
|
| aiProcess_FlipUVs // flip the V to match the Vulkans way of doing UVs
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!scene || !scene->HasMeshes())
|
||||||
|
{
|
||||||
|
SHLOG_ERROR("ERROR in GLTF::ASSIMP: {}\nFile: {}", aiImporter.GetErrorString(), path.string());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ExtractAnimations(*scene, anims);
|
||||||
|
|
||||||
|
ProcessNode(*scene->mRootNode, *scene, meshes);
|
||||||
|
|
||||||
|
aiImporter.FreeScene();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
/*************************************************************************//**
|
||||||
|
* \file SHAssimpLibrary.h
|
||||||
|
* \author Loh Xiao Qi
|
||||||
|
* \date October 2022
|
||||||
|
* \brief
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||||
|
* disclosure of this file or its contents without the prior written consent
|
||||||
|
* of DigiPen Institute of Technology is prohibited.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <assimp/Importer.hpp>
|
||||||
|
#include <assimp/scene.h>
|
||||||
|
#include <vector>
|
||||||
|
#include "../SHAssetMacros.h"
|
||||||
|
#include "../Asset Types/SHMeshAsset.h"
|
||||||
|
#include "../Asset Types/SHAnimationAsset.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
class SHAssimpLibrary
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
using MeshVectorRef = std::vector<SHMeshAsset*>&;
|
||||||
|
using AnimVectorRef = std::vector<SHAnimationAsset*>&;
|
||||||
|
|
||||||
|
static Assimp::Importer aiImporter;
|
||||||
|
static void ProcessNode(aiNode const& node, aiScene const& scene,MeshVectorRef meshes) noexcept;
|
||||||
|
static void ExtractAnimations(aiScene const& scene, AnimVectorRef anims) noexcept;
|
||||||
|
static SHMeshAsset* ProcessMesh(aiMesh const& mesh) noexcept;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static void LoadFromFile(AssetPath path, MeshVectorRef meshes, AnimVectorRef anims) noexcept;
|
||||||
|
};
|
||||||
|
}
|
|
@ -20,7 +20,7 @@ std::string SHADE::SHMeshCompiler::CompileMeshBinary(SHMeshAsset const& asset, A
|
||||||
{
|
{
|
||||||
std::string newPath{ path.string() };
|
std::string newPath{ path.string() };
|
||||||
newPath = newPath.substr(0, newPath.find_last_of('/') + 1);
|
newPath = newPath.substr(0, newPath.find_last_of('/') + 1);
|
||||||
newPath += asset.header.meshName + MESH_EXTENSION;
|
newPath += asset.header.name + MESH_EXTENSION.data();
|
||||||
|
|
||||||
std::ofstream file{ newPath, std::ios::out | std::ios::binary | std::ios::trunc };
|
std::ofstream file{ newPath, std::ios::out | std::ios::binary | std::ios::trunc };
|
||||||
if (!file.is_open())
|
if (!file.is_open())
|
||||||
|
|
|
@ -12,129 +12,11 @@
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
#include "SHpch.h"
|
#include "SHpch.h"
|
||||||
#include "SHMeshLoader.h"
|
#include "SHMeshLoader.h"
|
||||||
#include <assimp/postprocess.h>
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
Assimp::Importer SHMeshLoader::aiImporter;
|
void SHMeshLoader::LoadSHMesh(AssetPath path, SHMeshAsset& mesh) noexcept
|
||||||
|
|
||||||
void SHMeshLoader::ProcessNode(aiNode const& node, aiScene const& scene, std::vector<SHMeshAsset>& meshes) noexcept
|
|
||||||
{
|
|
||||||
for (size_t i {0}; i < node.mNumMeshes; ++i)
|
|
||||||
{
|
|
||||||
aiMesh* mesh = scene.mMeshes[node.mMeshes[i]];
|
|
||||||
meshes.push_back(ProcessMesh(*mesh, scene));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i{ 0 }; i < node.mNumChildren; ++i)
|
|
||||||
{
|
|
||||||
ProcessNode(*node.mChildren[i], scene, meshes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SHMeshAsset SHMeshLoader::ProcessMesh(aiMesh const& mesh, aiScene const& scene) noexcept
|
|
||||||
{
|
|
||||||
(void)scene;
|
|
||||||
|
|
||||||
SHMeshAsset result
|
|
||||||
{
|
|
||||||
.compiled { false},
|
|
||||||
.changed { false }
|
|
||||||
};
|
|
||||||
|
|
||||||
for (size_t i{0}; i < mesh.mNumVertices; ++i)
|
|
||||||
{
|
|
||||||
// Vertex position
|
|
||||||
SHVec3 vertex;
|
|
||||||
vertex.x = mesh.mVertices[i].x;
|
|
||||||
vertex.y = mesh.mVertices[i].y;
|
|
||||||
vertex.z = mesh.mVertices[i].z;
|
|
||||||
result.vertexPosition.push_back(vertex);
|
|
||||||
|
|
||||||
// Tex coords
|
|
||||||
SHVec2 texCoord{0.f, 0.f};
|
|
||||||
if (mesh.mTextureCoords[0])
|
|
||||||
{
|
|
||||||
texCoord.x = mesh.mTextureCoords[0][i].x;
|
|
||||||
texCoord.y = mesh.mTextureCoords[0][i].y;
|
|
||||||
}
|
|
||||||
result.texCoords.push_back(texCoord);
|
|
||||||
|
|
||||||
// Normals
|
|
||||||
SHVec3 normal{0.f, 0.f, 0.f};
|
|
||||||
if (mesh.mNormals)
|
|
||||||
{
|
|
||||||
normal.x = mesh.mNormals[i].x;
|
|
||||||
normal.y = mesh.mNormals[i].y;
|
|
||||||
normal.z = mesh.mNormals[i].z;
|
|
||||||
}
|
|
||||||
result.vertexNormal.push_back(normal);
|
|
||||||
|
|
||||||
// Tangent
|
|
||||||
SHVec3 tangent{0.f, 0.f, 0.f};
|
|
||||||
if (mesh.mTangents)
|
|
||||||
{
|
|
||||||
tangent.x = mesh.mTangents[i].x;
|
|
||||||
tangent.y = mesh.mTangents[i].y;
|
|
||||||
tangent.z = mesh.mTangents[i].z;
|
|
||||||
}
|
|
||||||
result.vertexTangent.push_back(tangent);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i {0}; i < mesh.mNumFaces; ++i)
|
|
||||||
{
|
|
||||||
aiFace face = mesh.mFaces[i];
|
|
||||||
for (size_t j{0}; j < face.mNumIndices; ++j)
|
|
||||||
{
|
|
||||||
result.indices.push_back(face.mIndices[j]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
result.header.vertexCount = static_cast<uint32_t>(result.vertexPosition.size());
|
|
||||||
result.header.indexCount = static_cast<uint32_t>(result.indices.size());
|
|
||||||
result.header.meshName = mesh.mName.C_Str();
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHMeshLoader::LoadExternal(std::vector<SHMeshAsset>& meshes, AssetPath path) noexcept
|
|
||||||
{
|
|
||||||
const aiScene* scene = aiImporter.ReadFile(path.string().c_str(),
|
|
||||||
aiProcess_Triangulate // Make sure we get triangles rather than nvert polygons
|
|
||||||
| aiProcess_GenUVCoords // Convert any type of mapping to uv mapping
|
|
||||||
| aiProcess_TransformUVCoords // preprocess UV transformations (scaling, translation ...)
|
|
||||||
| aiProcess_FindInstances // search for instanced meshes and remove them by references to one master
|
|
||||||
| aiProcess_CalcTangentSpace // calculate tangents and bitangents if possible
|
|
||||||
| aiProcess_JoinIdenticalVertices // join identical vertices/ optimize indexing
|
|
||||||
| aiProcess_RemoveRedundantMaterials // remove redundant materials
|
|
||||||
| aiProcess_FindInvalidData // detect invalid model data, such as invalid normal vectors
|
|
||||||
| aiProcess_FlipUVs // flip the V to match the Vulkans way of doing UVs
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!scene || !scene->HasMeshes())
|
|
||||||
{
|
|
||||||
SHLOG_ERROR("ERROR in GLTF::ASSIMP: {}\nFile: {}", aiImporter.GetErrorString(), path.string());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//TODO MATERIALS FROM MESHES
|
|
||||||
//if (scene->HasMaterials())
|
|
||||||
//{
|
|
||||||
// for (int i{0}; i < scene->mNumMaterials; ++i)
|
|
||||||
// {
|
|
||||||
// if (scene->mMaterials[i]->mNumProperties > 0)
|
|
||||||
// {
|
|
||||||
// for (int j{0}; j < scene->mMaterials[i]->mProperties[j].)
|
|
||||||
// }
|
|
||||||
//std::cout << scene->mMaterials[i]->;
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
ProcessNode(*scene->mRootNode, *scene, meshes);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHMeshLoader::LoadSHMesh(SHMeshAsset& mesh, AssetPath path) noexcept
|
|
||||||
{
|
{
|
||||||
std::ifstream file{ path.string(), std::ios::in | std::ios::binary };
|
std::ifstream file{ path.string(), std::ios::in | std::ios::binary };
|
||||||
if (!file.is_open())
|
if (!file.is_open())
|
||||||
|
@ -168,45 +50,13 @@ namespace SHADE
|
||||||
file.read(reinterpret_cast<char *>(vertNorm.data()), vertexVec3Byte);
|
file.read(reinterpret_cast<char *>(vertNorm.data()), vertexVec3Byte);
|
||||||
file.read(reinterpret_cast<char *>(texCoord.data()), vertexVec2Byte);
|
file.read(reinterpret_cast<char *>(texCoord.data()), vertexVec2Byte);
|
||||||
file.read(reinterpret_cast<char *>(indices.data()), sizeof(uint32_t) * indexCount);
|
file.read(reinterpret_cast<char *>(indices.data()), sizeof(uint32_t) * indexCount);
|
||||||
|
|
||||||
//for (auto i{ 0 }; i < vertCount; ++i)
|
|
||||||
//{
|
|
||||||
// file >> vertPos[i].x;
|
|
||||||
// file >> vertPos[i].y;
|
|
||||||
// file >> vertPos[i].z;
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
//for (auto i{ 0 }; i < vertCount; ++i)
|
|
||||||
//{
|
|
||||||
// file >> vertTan[i].x;
|
|
||||||
// file >> vertTan[i].y;
|
|
||||||
// file >> vertTan[i].z;
|
|
||||||
//}
|
|
||||||
|
|
||||||
//for (auto i{ 0 }; i < vertCount; ++i)
|
|
||||||
//{
|
|
||||||
// file >> vertNorm[i].x;
|
|
||||||
// file >> vertNorm[i].y;
|
|
||||||
// file >> vertNorm[i].z;
|
|
||||||
//}
|
|
||||||
|
|
||||||
//for (auto i{ 0 }; i < vertCount; ++i)
|
|
||||||
//{
|
|
||||||
// file >> texCoord[i].x;
|
|
||||||
// file >> texCoord[i].y;
|
|
||||||
//}
|
|
||||||
|
|
||||||
//for (auto i{ 0 }; i < indexCount; ++i)
|
|
||||||
//{
|
|
||||||
// file >> indices[i];
|
|
||||||
//}
|
|
||||||
|
|
||||||
mesh.compiled = true;
|
mesh.compiled = true;
|
||||||
mesh.changed = false;
|
mesh.changed = false;
|
||||||
|
|
||||||
mesh.header.indexCount = indexCount;
|
mesh.header.indexCount = indexCount;
|
||||||
mesh.header.vertexCount = vertCount;
|
mesh.header.vertexCount = vertCount;
|
||||||
mesh.header.meshName = name;
|
mesh.header.name = name;
|
||||||
|
|
||||||
mesh.vertexPosition = std::move(vertPos);
|
mesh.vertexPosition = std::move(vertPos);
|
||||||
mesh.vertexTangent = std::move(vertTan);
|
mesh.vertexTangent = std::move(vertTan);
|
||||||
|
@ -217,15 +67,12 @@ namespace SHADE
|
||||||
file.close();
|
file.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHMeshLoader::LoadMesh(std::vector<SHMeshAsset>& meshes, AssetPath path) noexcept
|
SHAssetData* SHMeshLoader::Load(AssetPath path)
|
||||||
{
|
{
|
||||||
if (path.extension().string() == GLTF_EXTENSION)
|
auto result = new SHMeshAsset();
|
||||||
{
|
|
||||||
LoadExternal(meshes, path);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
meshes.emplace_back();
|
LoadSHMesh(path, *result);
|
||||||
LoadSHMesh(meshes.back(), path);
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,27 +10,15 @@
|
||||||
* of DigiPen Institute of Technology is prohibited.
|
* of DigiPen Institute of Technology is prohibited.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <assimp/Importer.hpp>
|
|
||||||
#include <assimp/scene.h>
|
|
||||||
#include "../SHAssetMacros.h"
|
#include "../SHAssetMacros.h"
|
||||||
#include "../Asset Types/SHMeshAsset.h"
|
#include "../Asset Types/SHMeshAsset.h"
|
||||||
#include <vector>
|
#include "SHAssetLoader.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
class SHMeshLoader
|
struct SHMeshLoader : public SHAssetLoader
|
||||||
{
|
{
|
||||||
private:
|
void LoadSHMesh(AssetPath path, SHMeshAsset& meshes) noexcept;
|
||||||
static Assimp::Importer aiImporter;
|
SHAssetData* Load(AssetPath path) override;
|
||||||
|
|
||||||
static void ProcessNode(aiNode const& node, aiScene const& scene, std::vector<SHMeshAsset>& meshes) noexcept;
|
|
||||||
|
|
||||||
static SHMeshAsset ProcessMesh(aiMesh const& mesh, aiScene const& scene) noexcept;
|
|
||||||
|
|
||||||
static void LoadExternal(std::vector<SHMeshAsset>& meshes, AssetPath path) noexcept;
|
|
||||||
|
|
||||||
public:
|
|
||||||
static void LoadMesh(std::vector<SHMeshAsset>& meshes, AssetPath path) noexcept;
|
|
||||||
static void LoadSHMesh(SHMeshAsset& meshes, AssetPath path) noexcept;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
|
@ -133,6 +133,15 @@ namespace SHADE
|
||||||
file.close();
|
file.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SHAssetData* SHTextureLoader::Load(AssetPath path)
|
||||||
|
{
|
||||||
|
auto result = new SHTextureAsset();
|
||||||
|
|
||||||
|
LoadImageAsset(path, *result);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
void SHTextureLoader::LoadImageAsset(AssetPath path, SHTextureAsset& asset)
|
void SHTextureLoader::LoadImageAsset(AssetPath path, SHTextureAsset& asset)
|
||||||
{
|
{
|
||||||
if (path.extension().string() == DDS_EXTENSION)
|
if (path.extension().string() == DDS_EXTENSION)
|
||||||
|
|
|
@ -15,19 +15,20 @@
|
||||||
#include "../SHAssetMacros.h"
|
#include "../SHAssetMacros.h"
|
||||||
#include "../Asset Types/SHTextureAsset.h"
|
#include "../Asset Types/SHTextureAsset.h"
|
||||||
#include "tinyddsloader.h"
|
#include "tinyddsloader.h"
|
||||||
|
#include "SHAssetLoader.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
class SHTextureLoader
|
class SHTextureLoader : public SHAssetLoader
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
static std::string TinyDDSResultToString(tinyddsloader::Result value);
|
std::string TinyDDSResultToString(tinyddsloader::Result value);
|
||||||
static vk::Format ddsLoaderToVkFormat(tinyddsloader::DDSFile::DXGIFormat format, bool isLinear);
|
vk::Format ddsLoaderToVkFormat(tinyddsloader::DDSFile::DXGIFormat format, bool isLinear);
|
||||||
|
|
||||||
|
void LoadTinyDDS(AssetPath path, SHTextureAsset& asset) noexcept;
|
||||||
static void LoadTinyDDS(AssetPath path, SHTextureAsset& asset) noexcept;
|
|
||||||
public:
|
public:
|
||||||
static void LoadImageAsset(AssetPath paths, SHTextureAsset& image);
|
void LoadImageAsset(AssetPath paths, SHTextureAsset& image);
|
||||||
static void LoadSHTexture(AssetPath path, SHTextureAsset& asset) noexcept;
|
void LoadSHTexture(AssetPath path, SHTextureAsset& asset) noexcept;
|
||||||
|
SHAssetData* Load(AssetPath path) override;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,11 +12,12 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Filesystem/SHFileSystem.h"
|
#include "Filesystem/SHFileSystem.h"
|
||||||
#include "SHAssetMacros.h"
|
#include "Assets/SHAssetMacros.h"
|
||||||
|
#include "SH_API.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
struct SHAsset
|
struct SH_API SHAsset
|
||||||
{
|
{
|
||||||
AssetName name;
|
AssetName name;
|
||||||
AssetID id;
|
AssetID id;
|
||||||
|
|
|
@ -32,12 +32,12 @@ typedef std::filesystem::path AssetPath;
|
||||||
typedef unsigned char* AssetData;
|
typedef unsigned char* AssetData;
|
||||||
typedef std::string AssetMetaVersion;
|
typedef std::string AssetMetaVersion;
|
||||||
typedef std::string AssetExtension;
|
typedef std::string AssetExtension;
|
||||||
typedef unsigned char AssetTypeMeta;
|
typedef size_t AssetTypeMeta;
|
||||||
|
|
||||||
typedef FMOD::Sound* SHSound;
|
typedef FMOD::Sound* SHSound;
|
||||||
|
|
||||||
// Asset Meta Version
|
// Asset Meta Version
|
||||||
#define ASSET_META_VER "1.0"
|
constexpr std::string_view ASSET_META_VER { "1.0" };
|
||||||
|
|
||||||
// Asset type enum
|
// Asset type enum
|
||||||
enum class AssetType : AssetTypeMeta
|
enum class AssetType : AssetTypeMeta
|
||||||
|
@ -53,34 +53,35 @@ enum class AssetType : AssetTypeMeta
|
||||||
SCENE,
|
SCENE,
|
||||||
PREFAB,
|
PREFAB,
|
||||||
AUDIO_WAV,
|
AUDIO_WAV,
|
||||||
DDS
|
DDS,
|
||||||
|
MAX_COUNT
|
||||||
};
|
};
|
||||||
|
|
||||||
//Directory
|
//Directory
|
||||||
#ifdef _PUBLISH
|
#ifdef _PUBLISH
|
||||||
#define ASSET_ROOT "Assets"
|
constexpr std::string_view ASSET_ROOT {"Assets"};
|
||||||
#else
|
#else
|
||||||
#define ASSET_ROOT "../../Assets"
|
constexpr std::string_view ASSET_ROOT {"../../Assets"};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
// ASSET EXTENSIONS
|
// ASSET EXTENSIONS
|
||||||
#define META_EXTENSION ".shmeta"
|
constexpr std::string_view META_EXTENSION {".shmeta"};
|
||||||
#define IMAGE_EXTENSION ".png"
|
constexpr std::string_view IMAGE_EXTENSION {".png"};
|
||||||
#define AUDIO_EXTENSION ".ogg"
|
constexpr std::string_view AUDIO_EXTENSION {".ogg"};
|
||||||
#define AUDIO_WAV_EXTENSION ".wav"
|
constexpr std::string_view AUDIO_WAV_EXTENSION {".wav"};
|
||||||
#define SHADER_EXTENSION ".glsl"
|
constexpr std::string_view SHADER_EXTENSION {".glsl"};
|
||||||
#define SCRIPT_EXTENSION ".cs"
|
constexpr std::string_view SCRIPT_EXTENSION {".cs"};
|
||||||
#define SCENE_EXTENSION ".SHADE"
|
constexpr std::string_view SCENE_EXTENSION {".SHADE"};
|
||||||
#define PREFAB_EXTENSION ".SHPrefab"
|
constexpr std::string_view PREFAB_EXTENSION {".SHPrefab"};
|
||||||
#define MATERIAL_EXTENSION ".SHMat"
|
constexpr std::string_view MATERIAL_EXTENSION {".SHMat"};
|
||||||
#define TEXTURE_EXTENSION ".shtex"
|
constexpr std::string_view TEXTURE_EXTENSION {".shtex"};
|
||||||
#define DDS_EXTENSION ".dds"
|
constexpr std::string_view DDS_EXTENSION {".dds"};
|
||||||
#define FBX_EXTENSION ".fbx"
|
constexpr std::string_view FBX_EXTENSION {".fbx"};
|
||||||
#define GLTF_EXTENSION ".gltf"
|
constexpr std::string_view GLTF_EXTENSION {".gltf"};
|
||||||
#define MESH_EXTENSION ".shmesh"
|
constexpr std::string_view MESH_EXTENSION {".shmesh"};
|
||||||
|
|
||||||
std::string const EXTENSIONS[] = {
|
constexpr std::string_view EXTENSIONS[] = {
|
||||||
AUDIO_EXTENSION,
|
AUDIO_EXTENSION,
|
||||||
SHADER_EXTENSION,
|
SHADER_EXTENSION,
|
||||||
MATERIAL_EXTENSION,
|
MATERIAL_EXTENSION,
|
||||||
|
@ -96,10 +97,12 @@ std::string const EXTENSIONS[] = {
|
||||||
GLTF_EXTENSION
|
GLTF_EXTENSION
|
||||||
};
|
};
|
||||||
|
|
||||||
|
constexpr size_t TYPE_COUNT {static_cast<size_t>(AssetType::MAX_COUNT) };
|
||||||
|
|
||||||
// Error flags
|
// Error flags
|
||||||
#define FILE_NOT_FOUND_ERR "FILE NOT FOUND"
|
constexpr std::string_view FILE_NOT_FOUND_ERR {"FILE NOT FOUND"};
|
||||||
#define META_NOT_FOUND_ERR "META NOT FOUND"
|
constexpr std::string_view META_NOT_FOUND_ERR {"META NOT FOUND"};
|
||||||
#define ASSET_NOT_FOUND_ERR "ASSET NOT FOUND"
|
constexpr std::string_view ASSET_NOT_FOUND_ERR {"ASSET NOT FOUND"};
|
||||||
#define EXT_DOES_NOT_EXIST "TYPE DOES NOT HAVE EXTENSION DEFINED"
|
constexpr std::string_view EXT_DOES_NOT_EXIST {"TYPE DOES NOT HAVE EXTENSION DEFINED"};
|
||||||
|
|
||||||
#endif // !SH_ASSET_MACROS_H
|
#endif // !SH_ASSET_MACROS_H
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include "SHAssetMetaHandler.h"
|
#include "SHAssetMetaHandler.h"
|
||||||
#include "Filesystem/SHFileSystem.h"
|
#include "Filesystem/SHFileSystem.h"
|
||||||
|
|
||||||
|
#include "Libraries/SHAssimpLibrary.h"
|
||||||
#include "Libraries/SHMeshLoader.h"
|
#include "Libraries/SHMeshLoader.h"
|
||||||
#include "Libraries/SHTextureLoader.h"
|
#include "Libraries/SHTextureLoader.h"
|
||||||
|
|
||||||
|
@ -25,11 +26,10 @@ namespace SHADE
|
||||||
FMOD::System* SHAssetManager::audioSystem;
|
FMOD::System* SHAssetManager::audioSystem;
|
||||||
std::unordered_map<AssetID, SHSound >* SHAssetManager::audioSoundList;
|
std::unordered_map<AssetID, SHSound >* SHAssetManager::audioSoundList;
|
||||||
|
|
||||||
std::vector<SHAsset> SHAssetManager::assetCollection;
|
std::vector<SHAssetLoader*> SHAssetManager::loaders(TYPE_COUNT);
|
||||||
std::unordered_map<AssetID, SHAsset> SHAssetManager::assetRegistry;
|
|
||||||
|
|
||||||
std::unordered_map<AssetID, SHMeshAsset> SHAssetManager::meshCollection;
|
std::vector<SHAsset> SHAssetManager::assetCollection;
|
||||||
std::unordered_map<AssetID, SHTextureAsset> SHAssetManager::textureCollection;
|
std::unordered_map<AssetID, SHAssetData * const> SHAssetManager::assetData;
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* \brief Static function to generate asset ID.
|
* \brief Static function to generate asset ID.
|
||||||
|
@ -56,18 +56,15 @@ namespace SHADE
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
void SHAssetManager::Unload() noexcept
|
void SHAssetManager::Unload() noexcept
|
||||||
{
|
{
|
||||||
for (auto const& asset : assetCollection)
|
|
||||||
{
|
|
||||||
SHAssetMetaHandler::WriteMetaData(asset);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHAssetManager::Unload(AssetID assetId) noexcept
|
void SHAssetManager::Unload(AssetID assetId) noexcept
|
||||||
{
|
{
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
AssetPath SHAssetManager::GenerateLocalPath(AssetPath path) noexcept
|
AssetPath SHAssetManager::GenerateLocalPath(AssetPath path) noexcept
|
||||||
{
|
{
|
||||||
if (!IsRecognised(path.extension().string().c_str()))
|
if (!IsRecognised(path.extension().string().c_str()))
|
||||||
{
|
{
|
||||||
|
@ -85,7 +82,37 @@ namespace SHADE
|
||||||
// return std::filesystem::path();
|
// return std::filesystem::path();
|
||||||
//}
|
//}
|
||||||
|
|
||||||
return std::filesystem::path(ASSET_ROOT + folder + path.filename().string());
|
return std::filesystem::path(std::string(ASSET_ROOT) + folder + path.filename().string());
|
||||||
|
}
|
||||||
|
|
||||||
|
AssetPath SHAssetManager::GenerateNewPath(AssetName name, AssetType type)
|
||||||
|
{
|
||||||
|
std::string folder;
|
||||||
|
|
||||||
|
switch(type)
|
||||||
|
{
|
||||||
|
case AssetType::SCENE:
|
||||||
|
folder = "scenes/";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AssetType::PREFAB:
|
||||||
|
folder = "prefabs/";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AssetType::MATERIAL:
|
||||||
|
folder = "materials/";
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
folder = "/";
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::filesystem::path{
|
||||||
|
std::string(ASSET_ROOT) +
|
||||||
|
folder +
|
||||||
|
name +
|
||||||
|
std::string(EXTENSIONS[static_cast<size_t>(type)])
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
@ -121,7 +148,7 @@ namespace SHADE
|
||||||
// folder = "";
|
// folder = "";
|
||||||
// break;
|
// break;
|
||||||
//}
|
//}
|
||||||
AssetPath path{ ASSET_ROOT + folder + name + SHAssetMetaHandler::GetExtensionFromType(type) };
|
AssetPath path{ std::string{ASSET_ROOT} + folder + name + SHAssetMetaHandler::GetExtensionFromType(type) };
|
||||||
|
|
||||||
SHAssetMetaHandler::WriteMetaData(meta);
|
SHAssetMetaHandler::WriteMetaData(meta);
|
||||||
|
|
||||||
|
@ -130,6 +157,19 @@ namespace SHADE
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AssetID SHAssetManager::CreateAsset(AssetName name, AssetType type) noexcept
|
||||||
|
{
|
||||||
|
AssetID id = GenerateAssetID(type);
|
||||||
|
|
||||||
|
assetCollection.emplace_back(
|
||||||
|
name,
|
||||||
|
id,
|
||||||
|
type,
|
||||||
|
GenerateNewPath(name, type),
|
||||||
|
0
|
||||||
|
);
|
||||||
|
return id;
|
||||||
|
}
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* \brief Import new asset from outside editor window.
|
* \brief Import new asset from outside editor window.
|
||||||
*
|
*
|
||||||
|
@ -138,7 +178,10 @@ namespace SHADE
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
AssetID SHAssetManager::ImportNewAsset(char const* p) noexcept
|
AssetID SHAssetManager::ImportNewAsset(char const* p) noexcept
|
||||||
{
|
{
|
||||||
std::filesystem::path const path{ p };
|
std::filesystem::path const path{ p };
|
||||||
|
|
||||||
|
auto const type = SHAssetMetaHandler::GetTypeFromExtension(path.extension().string());
|
||||||
|
auto const id = GenerateAssetID(type);
|
||||||
|
|
||||||
std::filesystem::path const newPath{ GenerateLocalPath(path) };
|
std::filesystem::path const newPath{ GenerateLocalPath(path) };
|
||||||
if (newPath.empty())
|
if (newPath.empty())
|
||||||
|
@ -149,11 +192,7 @@ namespace SHADE
|
||||||
|
|
||||||
std::filesystem::copy(path, newPath);
|
std::filesystem::copy(path, newPath);
|
||||||
|
|
||||||
AssetID id{ RetrieveAsset(newPath.string().c_str()) };
|
assetCollection.push_back(CreateAssetFromPath(newPath));
|
||||||
if (id != 0)
|
|
||||||
{
|
|
||||||
LoadData(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
@ -164,158 +203,14 @@ namespace SHADE
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
void SHAssetManager::RefreshAllAssets() noexcept
|
void SHAssetManager::RefreshAllAssets() noexcept
|
||||||
{
|
{
|
||||||
std::vector<AssetPath> metaFiles;
|
|
||||||
std::vector<AssetPath> AssetFiles;
|
|
||||||
|
|
||||||
//SHFileSystem::LoadAllFiles(metaFiles, AssetFiles);
|
|
||||||
//std::vector<AssetPath> AssetFilesVerified;
|
|
||||||
std::vector<AssetPath> AssetFilesNew;
|
|
||||||
|
|
||||||
for (auto const& asset : AssetFiles)
|
|
||||||
{
|
|
||||||
bool found = false;
|
|
||||||
for (auto it {metaFiles.begin()}; it != metaFiles.end(); ++it)
|
|
||||||
{
|
|
||||||
std::string fileExtCheck{ asset.filename().string() };
|
|
||||||
fileExtCheck += META_EXTENSION;
|
|
||||||
if (it->filename().string() == fileExtCheck)
|
|
||||||
{
|
|
||||||
metaFiles.erase(it);
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!found && IsRecognised(asset.extension().string().c_str()))
|
|
||||||
{
|
|
||||||
AssetFilesNew.push_back(asset);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<SHAsset> newLoad;
|
|
||||||
newLoad.reserve(AssetFilesNew.size());
|
|
||||||
|
|
||||||
//TODO: Handle if meta does not match all assets (if meta exist and asset doesnt, vice versa)
|
|
||||||
for (auto const& file : AssetFilesNew)
|
|
||||||
{
|
|
||||||
newLoad.push_back(RegisterAssetNew(file));
|
|
||||||
}
|
|
||||||
|
|
||||||
//UpdateAllSpriteSets();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHAssetManager::LoadDataTemp(std::string p) noexcept
|
|
||||||
{
|
|
||||||
AssetPath path{ p };
|
|
||||||
|
|
||||||
if (path.extension().string() == FBX_EXTENSION
|
|
||||||
|| path.extension().string() == GLTF_EXTENSION
|
|
||||||
|| path.extension().string() == MESH_EXTENSION)
|
|
||||||
{
|
|
||||||
LoadGLTF(
|
|
||||||
{
|
|
||||||
.name {path.filename().string()},
|
|
||||||
.id {0},
|
|
||||||
.type {AssetType::MESH},
|
|
||||||
.path {path},
|
|
||||||
.location {0}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else if (path.extension().string() == DDS_EXTENSION
|
|
||||||
|| path.extension().string() == TEXTURE_EXTENSION)
|
|
||||||
{
|
|
||||||
LoadDDS(
|
|
||||||
{
|
|
||||||
.name {path.filename().string()},
|
|
||||||
.id {0},
|
|
||||||
.type {AssetType::DDS},
|
|
||||||
.path {path},
|
|
||||||
.location {0}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<SHMeshAsset> SHAssetManager::GetAllMeshes() noexcept
|
|
||||||
{
|
|
||||||
std::vector<SHMeshAsset> result;
|
|
||||||
for (auto const& mesh : meshCollection)
|
|
||||||
{
|
|
||||||
result.push_back(mesh.second);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<SHTextureAsset> SHAssetManager::GetAllTextures() noexcept
|
|
||||||
{
|
|
||||||
std::vector<SHTextureAsset> result;
|
|
||||||
for (auto const& dds : textureCollection)
|
|
||||||
{
|
|
||||||
result.push_back(dds.second);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
SHMeshAsset const* SHAssetManager::GetMesh(AssetID id) noexcept
|
|
||||||
{
|
|
||||||
if (meshCollection.find(id) == meshCollection.end())
|
|
||||||
{
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return &meshCollection[id];
|
|
||||||
}
|
|
||||||
|
|
||||||
SHTextureAsset const* SHAssetManager::GetTexture(AssetID id) noexcept
|
|
||||||
{
|
|
||||||
if (textureCollection.find(id) == textureCollection.end())
|
|
||||||
{
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return &textureCollection[id];
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* \param Path for meta data file
|
|
||||||
* \param Path for asset file
|
|
||||||
|
|
||||||
* \brief Links meta data to asset in registries. Meta data should
|
|
||||||
* already exist
|
|
||||||
****************************************************************************/
|
|
||||||
void SHAssetManager::RegisterAsset(AssetPath const& metaPath, AssetPath const& path) noexcept
|
|
||||||
{
|
|
||||||
SHAsset const meta = SHAssetMetaHandler::RetrieveMetaData(metaPath);
|
|
||||||
|
|
||||||
assetCollection.push_back(meta);
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* \param Path for asset file
|
|
||||||
|
|
||||||
* \brief Creates new meta data for new asset.
|
|
||||||
****************************************************************************/
|
|
||||||
SHAsset SHAssetManager::RegisterAssetNew(AssetPath const& asset) noexcept
|
|
||||||
{
|
|
||||||
SHAsset meta;
|
|
||||||
meta.type = SHAssetMetaHandler::GetTypeFromExtension(asset.extension().string());
|
|
||||||
meta.id = GenerateAssetID(meta.type);
|
|
||||||
|
|
||||||
assetCollection.push_back(meta);
|
|
||||||
|
|
||||||
SHAssetMetaHandler::WriteMetaData(meta);
|
|
||||||
return assetCollection.back();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SHAssetManager::IsRecognised(char const* ext) noexcept
|
bool SHAssetManager::IsRecognised(char const* ext) noexcept
|
||||||
{
|
{
|
||||||
for (auto const& e : EXTENSIONS)
|
for (auto const& e : EXTENSIONS)
|
||||||
{
|
{
|
||||||
if (strcmp(ext, e.c_str()) == 0)
|
if (strcmp(ext, e.data()) == 0)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -324,54 +219,31 @@ namespace SHADE
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHAssetManager::LoadGLTF(SHAsset asset) noexcept
|
SHAsset SHAssetManager::CreateAssetFromPath(AssetPath path) noexcept
|
||||||
{
|
{
|
||||||
std::vector<SHMeshAsset> meshes;
|
SHAsset result;
|
||||||
|
|
||||||
SHMeshLoader::LoadMesh(meshes, asset.path);
|
result.name = path.stem().string();
|
||||||
|
result.type = SHAssetMetaHandler::GetTypeFromExtension(path.extension().string());
|
||||||
|
result.id = GenerateAssetID(result.type);
|
||||||
|
result.path = path;
|
||||||
|
|
||||||
for (auto const& mesh : meshes)
|
return result;
|
||||||
{
|
|
||||||
auto id{ GenerateAssetID(AssetType::MESH) };
|
|
||||||
meshCollection.emplace(id, mesh);
|
|
||||||
|
|
||||||
AssetPath path;
|
|
||||||
if (!mesh.compiled)
|
|
||||||
{
|
|
||||||
path = SHMeshCompiler::CompileMeshBinary(mesh, asset.path);
|
|
||||||
}
|
|
||||||
|
|
||||||
assetCollection.emplace_back(
|
|
||||||
mesh.header.meshName,
|
|
||||||
id,
|
|
||||||
AssetType::MESH,
|
|
||||||
path,
|
|
||||||
0
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHAssetManager::LoadDDS(SHAsset asset) noexcept
|
void SHAssetManager::InitLoaders() noexcept
|
||||||
{
|
{
|
||||||
SHTextureAsset image;
|
loaders[static_cast<size_t>(AssetType::AUDIO)] = nullptr;
|
||||||
|
loaders[static_cast<size_t>(AssetType::SHADER)] = nullptr;
|
||||||
SHTextureLoader::LoadImageAsset(asset.path, image);
|
loaders[static_cast<size_t>(AssetType::MATERIAL)] = nullptr;
|
||||||
|
loaders[static_cast<size_t>(AssetType::IMAGE)] = dynamic_cast<SHAssetLoader*>(new SHTextureLoader());
|
||||||
if (!image.compiled)
|
loaders[static_cast<size_t>(AssetType::TEXTURE)] = nullptr;
|
||||||
{
|
loaders[static_cast<size_t>(AssetType::MESH)] = dynamic_cast<SHAssetLoader*>(new SHMeshLoader());
|
||||||
auto id{ GenerateAssetID(AssetType::TEXTURE) };
|
loaders[static_cast<size_t>(AssetType::SCRIPT)] = nullptr;
|
||||||
textureCollection.emplace(id, image);
|
loaders[static_cast<size_t>(AssetType::SCENE)] = nullptr;
|
||||||
|
loaders[static_cast<size_t>(AssetType::PREFAB)] = nullptr;
|
||||||
auto path{ SHTextureCompiler::CompileTextureBinary(image, asset.path) };
|
loaders[static_cast<size_t>(AssetType::AUDIO_WAV)] = nullptr;
|
||||||
|
loaders[static_cast<size_t>(AssetType::DDS)] = nullptr;
|
||||||
assetCollection.emplace_back(
|
|
||||||
image.name,
|
|
||||||
id,
|
|
||||||
AssetType::TEXTURE,
|
|
||||||
path,
|
|
||||||
0
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
@ -379,8 +251,9 @@ namespace SHADE
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
void SHAssetManager::Load() noexcept
|
void SHAssetManager::Load() noexcept
|
||||||
{
|
{
|
||||||
RetrieveAssets();
|
InitLoaders();
|
||||||
LoadAllData();
|
BuildAssetCollection();
|
||||||
|
//LoadAllData();
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
@ -388,143 +261,40 @@ namespace SHADE
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
void SHAssetManager::LoadAllData() noexcept
|
void SHAssetManager::LoadAllData() noexcept
|
||||||
{
|
{
|
||||||
//TODO Remove when on demand loading is done
|
|
||||||
for (auto const& asset : assetCollection)
|
for (auto const& asset : assetCollection)
|
||||||
{
|
{
|
||||||
switch (asset.type)
|
SHAssetData* data = loaders[static_cast<size_t>(asset.type)]->Load(asset.path);
|
||||||
{
|
assetData.emplace(asset.id, data);
|
||||||
case AssetType::MESH:
|
|
||||||
meshCollection.emplace(asset.id, SHMeshAsset());
|
|
||||||
SHMeshLoader::LoadSHMesh(meshCollection[asset.id], asset.path);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case AssetType::TEXTURE:
|
|
||||||
textureCollection.emplace(asset.id, SHTextureAsset());
|
|
||||||
SHTextureLoader::LoadSHTexture(asset.path, textureCollection[asset.id]);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
void;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHAssetManager::LoadData(AssetID id) noexcept
|
SHAssetData* SHAssetManager::LoadData(SHAsset const& asset) noexcept
|
||||||
{
|
{
|
||||||
(void)id;
|
SHAssetData* data = loaders[static_cast<size_t>(asset.type)]->Load(asset.path);
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************************
|
if (data == nullptr)
|
||||||
* \brief Retrieve all asset files and meta files from filesystem
|
|
||||||
****************************************************************************/
|
|
||||||
void SHAssetManager::RetrieveAssets() noexcept
|
|
||||||
{
|
|
||||||
std::vector<AssetPath> metaFiles;
|
|
||||||
std::vector<AssetPath> AssetFiles;
|
|
||||||
|
|
||||||
for (auto const dir : std::filesystem::recursive_directory_iterator(ASSET_ROOT))
|
|
||||||
{
|
{
|
||||||
if (dir.path().extension().string() == META_EXTENSION)
|
SHLOG_ERROR("Unable to load asset into memory: {}\n", asset.path.string());
|
||||||
{
|
|
||||||
auto meta{ SHAssetMetaHandler::RetrieveMetaData(dir.path()) };
|
|
||||||
|
|
||||||
assetCollection.push_back(meta);
|
|
||||||
assetRegistry.emplace(meta.id, meta);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//TODO: Write new function for file manager to loop through all files
|
|
||||||
//SHFileSystem::StartupFillDirectories(ASSET_ROOT);
|
|
||||||
//FolderPointer rootFolder = SHFileSystem::GetRoot();
|
|
||||||
|
|
||||||
//for (auto const& meta : metaFiles)
|
|
||||||
//{
|
|
||||||
// for (std::vector<AssetPath>::const_iterator it{ AssetFiles.cbegin() };
|
|
||||||
// it != AssetFiles.cend();
|
|
||||||
// ++it)
|
|
||||||
// {
|
|
||||||
// // Asset exists for meta file
|
|
||||||
// std::string fileExtCheck{ it->filename().string() };
|
|
||||||
// fileExtCheck += META_EXTENSION;
|
|
||||||
// if (meta.filename().string() == fileExtCheck)
|
|
||||||
// {
|
|
||||||
// RegisterAsset(meta, *it);
|
|
||||||
// AssetFiles.erase(it);
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
//TODO: Handle if meta does not match all assets (if meta exist and asset doesnt, vice versa)
|
|
||||||
//for (auto const& file : AssetFiles)
|
|
||||||
//{
|
|
||||||
// if (IsRecognised(file.extension().string().c_str()))
|
|
||||||
// {
|
|
||||||
// SHAssetMetaHandler::WriteMetaData(RegisterAssetNew(file));
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
// {
|
|
||||||
// std::cout << "Unsupported File Format: " << file.filename() << "\n";
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
}
|
|
||||||
|
|
||||||
AssetID SHAssetManager::RetrieveAsset(char const* path) noexcept
|
|
||||||
{
|
|
||||||
std::filesystem::path p{ path };
|
|
||||||
if (IsRecognised(p.extension().string().c_str()))
|
|
||||||
{
|
|
||||||
SHAsset const& meta{ RegisterAssetNew(p) };
|
|
||||||
SHAssetMetaHandler::WriteMetaData(meta);
|
|
||||||
return meta.id;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::cout << "Unsupported File Format: " << p.filename() << "\n";
|
assetData.emplace(asset.id, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Assert that file imported is not recognised
|
return data;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
void SHAssetManager::BuildAssetCollection() noexcept
|
||||||
* \param Full path of file
|
|
||||||
|
|
||||||
* \brief Extracts file name from path. Formats file name into readable
|
|
||||||
* with spaces and capitalises first letter of every word
|
|
||||||
****************************************************************************/
|
|
||||||
AssetName SHAssetManager::GetNameFromPath(AssetPath filepath) noexcept
|
|
||||||
{
|
{
|
||||||
std::string name{ filepath.filename().string() };
|
for (auto const& dir : std::filesystem::recursive_directory_iterator{ASSET_ROOT})
|
||||||
name = name.substr(0, name.find_last_of('.'));
|
{
|
||||||
|
if (dir.is_regular_file())
|
||||||
//if (name[0] <= 122 && name[0] >= 97)
|
{
|
||||||
//{
|
if (dir.path().extension().string() == META_EXTENSION.data())
|
||||||
// name[0] -= 32;
|
{
|
||||||
//}
|
assetCollection.push_back(SHAssetMetaHandler::RetrieveMetaData(dir.path()));
|
||||||
|
}
|
||||||
//for (size_t i{ 1 }; i < name.length(); ++i)
|
}
|
||||||
//{
|
}
|
||||||
// // Replace all underscores with spaces
|
|
||||||
// if (name[i] == '_')
|
|
||||||
// {
|
|
||||||
// name[i] = ' ';
|
|
||||||
// continue;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (name[i + 1] <= 'Z' && name[i + 1] >= 'A'
|
|
||||||
// && name[i] <= 'z' && name[i] >= 'a')
|
|
||||||
// {
|
|
||||||
// name.insert(i + 1, 1, ' ');
|
|
||||||
// continue;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (name[i - 1] == ' ' && name[i] <= 'z' && name[i] >= 'a')
|
|
||||||
// {
|
|
||||||
// name[i] -= 32;
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
return name;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,9 +11,10 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "tinyddsloader.h"
|
#include "tinyddsloader.h"
|
||||||
#include "SHAsset.h"
|
#include "SHAsset.h"
|
||||||
|
#include "Asset Types/SHAssetData.h"
|
||||||
|
#include "Libraries/SHAssetLoader.h"
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
#include "Asset Types/SHMeshAsset.h"
|
|
||||||
#include "Asset Types/SHTextureAsset.h"
|
|
||||||
#include "SH_API.h"
|
#include "SH_API.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
|
@ -28,6 +29,8 @@ namespace SHADE
|
||||||
|
|
||||||
static AssetPath GenerateLocalPath(AssetPath path) noexcept;
|
static AssetPath GenerateLocalPath(AssetPath path) noexcept;
|
||||||
|
|
||||||
|
static AssetPath GenerateNewPath(AssetName name, AssetType type);
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* \brief Deallocate all memory used by resource data
|
* \brief Deallocate all memory used by resource data
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
@ -55,6 +58,7 @@ namespace SHADE
|
||||||
* \return resource id generated for new asset
|
* \return resource id generated for new asset
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
static AssetID CreateNewAsset(AssetType, AssetName) noexcept;
|
static AssetID CreateNewAsset(AssetType, AssetName) noexcept;
|
||||||
|
static AssetID CreateAsset(AssetName name, AssetType type) noexcept;
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* \brief Import new resource from outside editor window.
|
* \brief Import new resource from outside editor window.
|
||||||
|
@ -71,66 +75,33 @@ namespace SHADE
|
||||||
static void RefreshAllAssets() noexcept;
|
static void RefreshAllAssets() noexcept;
|
||||||
// -------------------------------------------------------------------------/
|
// -------------------------------------------------------------------------/
|
||||||
|
|
||||||
//TODO: TEMPORARY FOR TESTING GLTF & DDS
|
template<typename T>
|
||||||
static void LoadDataTemp(std::string path) noexcept;
|
static std::enable_if_t<std::is_base_of_v<SHAssetData, T>, T const* const> GetData(AssetID id) noexcept;
|
||||||
static std::vector<SHMeshAsset> GetAllMeshes() noexcept;
|
|
||||||
static std::vector<SHTextureAsset> GetAllTextures() noexcept;
|
|
||||||
|
|
||||||
static SHMeshAsset const* GetMesh(AssetID id) noexcept;
|
|
||||||
static SHTextureAsset const* GetTexture(AssetID id) noexcept;
|
|
||||||
private:
|
private:
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* \brief Load resource data into memory
|
* \brief Load resource data into memory
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
static void LoadAllData() noexcept;
|
static void LoadAllData() noexcept;
|
||||||
|
|
||||||
static void LoadData(AssetID id) noexcept;
|
static SHAssetData* LoadData(SHAsset const& asset) noexcept;
|
||||||
|
|
||||||
/****************************************************************************
|
inline static void BuildAssetCollection() noexcept;
|
||||||
* \brief Retrieve all resource files and meta files from filesystem
|
|
||||||
****************************************************************************/
|
|
||||||
static void RetrieveAssets() noexcept;
|
|
||||||
|
|
||||||
static AssetID RetrieveAsset(char const* path) noexcept;
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* \param Full path of file
|
|
||||||
|
|
||||||
* \brief Extracts file name from path. Formats file name into readable
|
|
||||||
* with spaces and capitalises first letter of every word
|
|
||||||
****************************************************************************/
|
|
||||||
static AssetName GetNameFromPath(AssetPath) noexcept;
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* \param Path for meta data file
|
|
||||||
* \param Path for resource file
|
|
||||||
|
|
||||||
* \brief Links meta data to resource in registries. Meta data should
|
|
||||||
* already exist
|
|
||||||
****************************************************************************/
|
|
||||||
static void RegisterAsset(AssetPath const&, AssetPath const&) noexcept;
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* \param Path for resource file
|
|
||||||
|
|
||||||
* \brief Creates new meta data for new resource.
|
|
||||||
****************************************************************************/
|
|
||||||
static SHAsset RegisterAssetNew(AssetPath const&) noexcept;
|
|
||||||
|
|
||||||
static bool IsRecognised(char const*) noexcept;
|
static bool IsRecognised(char const*) noexcept;
|
||||||
|
|
||||||
|
static SHAsset CreateAssetFromPath(AssetPath path) noexcept;
|
||||||
|
|
||||||
// Specialised load calls
|
static void InitLoaders() noexcept;
|
||||||
static void LoadGLTF(SHAsset asset) noexcept;
|
|
||||||
static void LoadDDS(SHAsset asset) noexcept;
|
|
||||||
|
|
||||||
static FMOD::System* audioSystem;
|
static FMOD::System* audioSystem;
|
||||||
static std::unordered_map<AssetID,SHSound>* audioSoundList;
|
static std::unordered_map<AssetID,SHSound>* audioSoundList;
|
||||||
|
|
||||||
|
static std::vector<SHAssetLoader*> loaders;
|
||||||
|
|
||||||
// For all resources
|
// For all resources
|
||||||
static std::vector<SHAsset> assetCollection;
|
static std::vector<SHAsset> assetCollection;
|
||||||
static std::unordered_map<AssetID, SHAsset> assetRegistry;
|
static std::unordered_map<AssetID, SHAssetData * const> assetData;
|
||||||
|
|
||||||
static std::unordered_map<AssetID, SHMeshAsset> meshCollection;
|
|
||||||
static std::unordered_map<AssetID, SHTextureAsset> textureCollection;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include "SHAssetManager.hpp"
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
|
||||||
|
#include "SHAssetManager.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
template<typename T>
|
||||||
|
std::enable_if_t<std::is_base_of_v<SHAssetData, T>, T const* const> SHAssetManager::GetData(AssetID id) noexcept
|
||||||
|
{
|
||||||
|
if (!assetData.contains(id))
|
||||||
|
{
|
||||||
|
for (auto const& asset : assetCollection)
|
||||||
|
{
|
||||||
|
if (asset.id == id)
|
||||||
|
{
|
||||||
|
assetData.emplace(id, LoadData(asset));
|
||||||
|
return dynamic_cast<T const* const>(assetData[id]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SHLOG_ERROR("Asset ID provided does not exist: {}", id);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return dynamic_cast<T const* const>(assetData[id]);
|
||||||
|
}
|
||||||
|
}
|
|
@ -37,7 +37,7 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
for (int i{0}; i < EXTENSIONS->size(); ++i)
|
for (int i{0}; i < EXTENSIONS->size(); ++i)
|
||||||
{
|
{
|
||||||
if (ext == EXTENSIONS[i])
|
if (strcmp(ext.c_str(), EXTENSIONS[i].data()) == 0)
|
||||||
{
|
{
|
||||||
return static_cast<AssetType>(i);
|
return static_cast<AssetType>(i);
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,7 @@ namespace SHADE
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
AssetExtension SHAssetMetaHandler::GetExtensionFromType(AssetType type) noexcept
|
AssetExtension SHAssetMetaHandler::GetExtensionFromType(AssetType type) noexcept
|
||||||
{
|
{
|
||||||
return EXTENSIONS[static_cast<size_t>(type)];
|
return AssetExtension(EXTENSIONS[static_cast<size_t>(type)]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
@ -124,16 +124,6 @@ namespace SHADE
|
||||||
metaFile << "ID: " << meta.id << "\n";
|
metaFile << "ID: " << meta.id << "\n";
|
||||||
metaFile << "Type: " << static_cast<AssetTypeMeta>(meta.type) << std::endl;
|
metaFile << "Type: " << static_cast<AssetTypeMeta>(meta.type) << std::endl;
|
||||||
|
|
||||||
////TODO Add in information that is specific to types like mesh
|
|
||||||
//switch(meta.type)
|
|
||||||
//{
|
|
||||||
//case AssetType::MESH:
|
|
||||||
// break;
|
|
||||||
|
|
||||||
//default:
|
|
||||||
// break;
|
|
||||||
//}
|
|
||||||
|
|
||||||
metaFile.close();
|
metaFile.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -140,10 +140,11 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
auto transform = SHComponentManager::GetComponent<SHTransformComponent>(camera.GetEID());
|
auto transform = SHComponentManager::GetComponent<SHTransformComponent>(camera.GetEID());
|
||||||
SHVec3 rotation = transform->GetWorldRotation();
|
SHVec3 rotation = transform->GetWorldRotation();
|
||||||
camera.pitch = rotation.x;
|
camera.pitch = SHMath::RadiansToDegrees(rotation.x);
|
||||||
camera.yaw = rotation.y;
|
camera.yaw = SHMath::RadiansToDegrees(rotation.y);
|
||||||
camera.roll = rotation.z;
|
camera.roll = SHMath::RadiansToDegrees(rotation.z);
|
||||||
camera.position = transform->GetWorldPosition();
|
camera.position = transform->GetWorldPosition();
|
||||||
|
camera.dirtyView = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,84 @@
|
||||||
|
#include "SHpch.h"
|
||||||
|
#include "SHAssetBrowser.h"
|
||||||
|
|
||||||
|
#include "Editor/IconsMaterialDesign.h"
|
||||||
|
#include "Editor/SHImGuiHelpers.hpp"
|
||||||
|
#include <imgui.h>
|
||||||
|
|
||||||
|
#include "Assets/SHAssetManager.h"
|
||||||
|
#include "Editor/DragDrop/SHDragDrop.hpp"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
SHAssetBrowser::SHAssetBrowser()
|
||||||
|
:SHEditorWindow("\xee\x8b\x87 Asset Browser", ImGuiWindowFlags_MenuBar)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHAssetBrowser::Init()
|
||||||
|
{
|
||||||
|
SHEditorWindow::Init();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHAssetBrowser::Update()
|
||||||
|
{
|
||||||
|
SHEditorWindow::Update();
|
||||||
|
if(Begin())
|
||||||
|
{
|
||||||
|
DrawMenuBar();
|
||||||
|
auto const& assets = SHAssetManager::GetAllAssets();
|
||||||
|
if(ImGui::BeginTable("AssetBrowserTable", 3))
|
||||||
|
{
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::TableHeader("Asset ID");
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::TableHeader("Name");
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::TableHeader("Type");
|
||||||
|
for(SHAsset const& asset : assets)
|
||||||
|
{
|
||||||
|
DrawAsset(asset);
|
||||||
|
}
|
||||||
|
ImGui::EndTable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::End();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHAssetBrowser::DrawMenuBar()
|
||||||
|
{
|
||||||
|
if(ImGui::BeginMenuBar())
|
||||||
|
{
|
||||||
|
|
||||||
|
ImGui::EndMenuBar();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHAssetBrowser::DrawAsset(SHAsset const& asset)
|
||||||
|
{
|
||||||
|
ImGui::PushID(asset.id);
|
||||||
|
ImGui::BeginGroup();
|
||||||
|
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::Selectable(std::format("{}", asset.id).data(), false, ImGuiSelectableFlags_SpanAllColumns);
|
||||||
|
if(SHDragDrop::BeginSource())
|
||||||
|
{
|
||||||
|
auto id = asset.id;
|
||||||
|
ImGui::Text("Moving Asset: %zu", id);
|
||||||
|
SHDragDrop::SetPayload<AssetID>(DRAG_RESOURCE, &id);
|
||||||
|
SHDragDrop::EndSource();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::Text("%s", asset.name.c_str());
|
||||||
|
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::Text("%s", "Type");
|
||||||
|
|
||||||
|
ImGui::EndGroup();
|
||||||
|
ImGui::PopID();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Assets/SHAsset.h"
|
||||||
|
#include "Editor/EditorWindow/SHEditorWindow.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
class SHAssetBrowser final : public SHEditorWindow
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SHAssetBrowser();
|
||||||
|
|
||||||
|
void Init();
|
||||||
|
void Update();
|
||||||
|
|
||||||
|
void Refresh();
|
||||||
|
private:
|
||||||
|
void DrawMenuBar();
|
||||||
|
void DrawAsset(SHAsset const& asset);
|
||||||
|
|
||||||
|
float idColumnWidth, nameColumnWidth, typeColumnWidth;
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
|
@ -93,8 +93,7 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
if (ImGui::BeginMenuBar())
|
if (ImGui::BeginMenuBar())
|
||||||
{
|
{
|
||||||
|
ImGui::SetCursorPosX(ImGui::GetContentRegionAvail().x * 0.75f);
|
||||||
ImGui::SetCursorPosX(ImGui::GetContentRegionAvail().x - 35.0f);
|
|
||||||
if(ImGui::SmallButton(ICON_MD_DESELECT))
|
if(ImGui::SmallButton(ICON_MD_DESELECT))
|
||||||
{
|
{
|
||||||
auto editor = SHSystemManager::GetSystem<SHEditor>();
|
auto editor = SHSystemManager::GetSystem<SHEditor>();
|
||||||
|
|
|
@ -39,6 +39,10 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
SHComponentManager::RemoveComponent<T>(component->GetEID());
|
SHComponentManager::RemoveComponent<T>(component->GetEID());
|
||||||
}
|
}
|
||||||
|
if (ImGui::Selectable(std::format("{} Reset {}", ICON_MD_RESTART_ALT, componentName.data()).data()))
|
||||||
|
{
|
||||||
|
*component = T();
|
||||||
|
}
|
||||||
ImGui::EndPopup();
|
ImGui::EndPopup();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -48,7 +52,7 @@ namespace SHADE
|
||||||
if (!component)
|
if (!component)
|
||||||
return;
|
return;
|
||||||
const auto componentType = rttr::type::get(*component);
|
const auto componentType = rttr::type::get(*component);
|
||||||
SHEditorWidgets::CheckBox("##IsActive", [component]() {return component->isActive; }, [component](bool const& active) {component->isActive = active; });
|
SHEditorWidgets::CheckBox("##IsActive", [component]() {return component->isActive; }, [component](bool const& active) {component->isActive = active; }, "Is Component Active");
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
if (ImGui::CollapsingHeader(componentType.get_name().data()))
|
if (ImGui::CollapsingHeader(componentType.get_name().data()))
|
||||||
{
|
{
|
||||||
|
@ -89,7 +93,7 @@ namespace SHADE
|
||||||
auto metaMax = property.get_metadata(META::max);
|
auto metaMax = property.get_metadata(META::max);
|
||||||
if (metaMin && metaMax)
|
if (metaMin && metaMax)
|
||||||
{
|
{
|
||||||
SHEditorWidgets::SliderInt(property.get_name().data(), metaMin.template get_value<int>(), metaMin.template get_value<int>(), [component, property] {return property.get_value(component).to_int(); }, [component, property](int const& result) {property.set_value(component, result); });
|
SHEditorWidgets::SliderInt(property.get_name().data(), metaMin.template get_value<int>(), metaMax.template get_value<int>(), [component, property] {return property.get_value(component).to_int(); }, [component, property](int const& result) {property.set_value(component, result); });
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -115,7 +119,7 @@ namespace SHADE
|
||||||
auto metaMax = property.get_metadata(META::max);
|
auto metaMax = property.get_metadata(META::max);
|
||||||
if (metaMin.is_valid() && metaMax.is_valid())
|
if (metaMin.is_valid() && metaMax.is_valid())
|
||||||
{
|
{
|
||||||
SHEditorWidgets::SliderScalar<uint16_t>(property.get_name().data(), ImGuiDataType_U16, metaMin.template get_value<uint16_t>(), metaMin.template get_value<uint16_t>(), [component, property] {return property.get_value(component).to_uint16(); }, [component, property](uint16_t const& result) {property.set_value(component, result); }, "%zu");
|
SHEditorWidgets::SliderScalar<uint16_t>(property.get_name().data(), ImGuiDataType_U16, metaMin.template get_value<uint16_t>(), metaMax.template get_value<uint16_t>(), [component, property] {return property.get_value(component).to_uint16(); }, [component, property](uint16_t const& result) {property.set_value(component, result); }, "%zu");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -128,7 +132,7 @@ namespace SHADE
|
||||||
auto metaMax = property.get_metadata(META::max);
|
auto metaMax = property.get_metadata(META::max);
|
||||||
if (metaMin.is_valid() && metaMax.is_valid())
|
if (metaMin.is_valid() && metaMax.is_valid())
|
||||||
{
|
{
|
||||||
SHEditorWidgets::SliderScalar<uint32_t>(property.get_name().data(), ImGuiDataType_U32, metaMin.template get_value<uint32_t>(), metaMin.template get_value<uint32_t>(), [component, property] { return property.get_value(component).to_uint32(); }, [component, property](uint32_t const& result) {property.set_value(component, result); }, "%zu");
|
SHEditorWidgets::SliderScalar<uint32_t>(property.get_name().data(), ImGuiDataType_U32, metaMin.template get_value<uint32_t>(), metaMax.template get_value<uint32_t>(), [component, property] { return property.get_value(component).to_uint32(); }, [component, property](uint32_t const& result) {property.set_value(component, result); }, "%zu");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -141,7 +145,7 @@ namespace SHADE
|
||||||
auto metaMax = property.get_metadata(META::max);
|
auto metaMax = property.get_metadata(META::max);
|
||||||
if (metaMin.is_valid() && metaMax.is_valid())
|
if (metaMin.is_valid() && metaMax.is_valid())
|
||||||
{
|
{
|
||||||
SHEditorWidgets::SliderScalar<uint64_t>(property.get_name().data(), ImGuiDataType_U64, metaMin.template get_value<uint64_t>(), metaMin.template get_value<uint64_t>(), [component, property] {return property.get_value(component).to_uint64(); }, [component, property](uint64_t const& result) {property.set_value(component, result); }, "%zu");
|
SHEditorWidgets::SliderScalar<uint64_t>(property.get_name().data(), ImGuiDataType_U64, metaMin.template get_value<uint64_t>(), metaMax.template get_value<uint64_t>(), [component, property] {return property.get_value(component).to_uint64(); }, [component, property](uint64_t const& result) {property.set_value(component, result); }, "%zu");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -152,13 +156,18 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
auto metaMin = property.get_metadata(META::min);
|
auto metaMin = property.get_metadata(META::min);
|
||||||
auto metaMax = property.get_metadata(META::max);
|
auto metaMax = property.get_metadata(META::max);
|
||||||
|
float min{}, max{};
|
||||||
|
if(metaMin.is_valid())
|
||||||
|
min = std::max(metaMin.template get_value<float>(), -FLT_MAX * 0.5f);
|
||||||
|
if(metaMax.is_valid())
|
||||||
|
max = std::min(metaMax.template get_value<float>(), FLT_MAX * 0.5f);
|
||||||
if (metaMin.is_valid() && metaMax.is_valid())
|
if (metaMin.is_valid() && metaMax.is_valid())
|
||||||
{
|
{
|
||||||
SHEditorWidgets::SliderFloat(property.get_name().data(), metaMin.template get_value<float>(), metaMin.template get_value<float>(), [component, property] {return property.get_value(component).to_float(); }, [component, property](float const& result) {property.set_value(component, result); });
|
SHEditorWidgets::SliderFloat(property.get_name().data(), min, max, [component, property] {return property.get_value(component).to_float(); }, [component, property](float const& result) {property.set_value(component, result); });
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SHEditorWidgets::DragFloat(property.get_name().data(), [component, property] {return property.get_value(component).to_float(); }, [component, property](float const& result) {property.set_value(component, result); });
|
SHEditorWidgets::DragFloat(property.get_name().data(), [component, property] {return property.get_value(component).to_float(); }, [component, property](float const& result) {property.set_value(component, result); }, "Test");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (type == rttr::type::get<double>())
|
else if (type == rttr::type::get<double>())
|
||||||
|
@ -167,7 +176,7 @@ namespace SHADE
|
||||||
auto metaMax = property.get_metadata(META::max);
|
auto metaMax = property.get_metadata(META::max);
|
||||||
if (metaMin.is_valid() && metaMax.is_valid())
|
if (metaMin.is_valid() && metaMax.is_valid())
|
||||||
{
|
{
|
||||||
SHEditorWidgets::SliderScalar<double>(property.get_name().data(), ImGuiDataType_Double, metaMin.template get_value<double>(), metaMin.template get_value<double>(), [component, property] {return property.get_value(component).to_double(); }, [component, property](double const& result) {property.set_value(component, result); });
|
SHEditorWidgets::SliderScalar<double>(property.get_name().data(), ImGuiDataType_Double, metaMin.template get_value<double>(), metaMax.template get_value<double>(), [component, property] {return property.get_value(component).to_double(); }, [component, property](double const& result) {property.set_value(component, result); });
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -35,6 +35,23 @@ namespace SHADE
|
||||||
return selected;
|
return selected;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename ComponentType, typename EnforcedComponent, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true, std::enable_if_t<std::is_base_of_v<SHComponent, EnforcedComponent>, bool> = true>
|
||||||
|
bool DrawAddComponentWithEnforcedComponentButton(EntityID const& eid)
|
||||||
|
{
|
||||||
|
bool selected = false;
|
||||||
|
if (!SHComponentManager::HasComponent<ComponentType>(eid))
|
||||||
|
{
|
||||||
|
if(selected = ImGui::Selectable(std::format("Add {}", rttr::type::get<ComponentType>().get_name().data()).data()); selected)
|
||||||
|
{
|
||||||
|
if(SHComponentManager::GetComponent_s<EnforcedComponent>(eid) == nullptr)
|
||||||
|
SHComponentManager::AddComponent<EnforcedComponent>(eid);
|
||||||
|
|
||||||
|
SHComponentManager::AddComponent<ComponentType>(eid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return selected;
|
||||||
|
}
|
||||||
|
|
||||||
SHEditorInspector::SHEditorInspector()
|
SHEditorInspector::SHEditorInspector()
|
||||||
:SHEditorWindow("Inspector", ImGuiWindowFlags_MenuBar)
|
:SHEditorWindow("Inspector", ImGuiWindowFlags_MenuBar)
|
||||||
{
|
{
|
||||||
|
@ -84,21 +101,19 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
// Render Scripts
|
// Render Scripts
|
||||||
SHScriptEngine* scriptEngine = static_cast<SHScriptEngine*>(SHSystemManager::GetSystem<SHScriptEngine>());
|
SHScriptEngine* scriptEngine = static_cast<SHScriptEngine*>(SHSystemManager::GetSystem<SHScriptEngine>());
|
||||||
scriptEngine->RenderScriptsInInspector(eid);
|
scriptEngine->RenderScriptsInInspector(eid);
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
if(ImGui::BeginMenu(std::format("{} Add Component", ICON_MD_LIBRARY_ADD).data()))
|
if(ImGui::BeginMenu(std::format("{} Add Component", ICON_MD_LIBRARY_ADD).data()))
|
||||||
{
|
{
|
||||||
DrawAddComponentButton<SHTransformComponent>(eid);
|
DrawAddComponentButton<SHTransformComponent>(eid);
|
||||||
DrawAddComponentButton<SHRenderable>(eid);
|
|
||||||
DrawAddComponentButton<SHColliderComponent>(eid);
|
// Components that require Transforms
|
||||||
if(DrawAddComponentButton<SHRigidBodyComponent>(eid))
|
|
||||||
{
|
DrawAddComponentWithEnforcedComponentButton<SHRenderable, SHTransformComponent>(eid);
|
||||||
if(SHComponentManager::GetComponent_s<SHTransformComponent>(eid) == nullptr)
|
DrawAddComponentWithEnforcedComponentButton<SHRigidBodyComponent, SHTransformComponent>(eid);
|
||||||
{
|
DrawAddComponentWithEnforcedComponentButton<SHColliderComponent, SHTransformComponent>(eid);
|
||||||
SHComponentManager::AddComponent<SHTransformComponent>(eid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ImGui::EndMenu();
|
ImGui::EndMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,4 +3,5 @@
|
||||||
#include "HierarchyPanel/SHHierarchyPanel.h" //Hierarchy Panel
|
#include "HierarchyPanel/SHHierarchyPanel.h" //Hierarchy Panel
|
||||||
#include "Inspector/SHEditorInspector.h" //Inspector
|
#include "Inspector/SHEditorInspector.h" //Inspector
|
||||||
#include "Profiling/SHEditorProfiler.h" //Profiler
|
#include "Profiling/SHEditorProfiler.h" //Profiler
|
||||||
#include "ViewportWindow/SHEditorViewport.h" //Editor Viewport
|
#include "ViewportWindow/SHEditorViewport.h" //Editor Viewport
|
||||||
|
#include "AssetBrowser/SHAssetBrowser.h" //Asset Browser
|
|
@ -24,12 +24,13 @@ namespace SHADE
|
||||||
void SHEditorViewport::Init()
|
void SHEditorViewport::Init()
|
||||||
{
|
{
|
||||||
SHEditorWindow::Init();
|
SHEditorWindow::Init();
|
||||||
|
transformGizmo.Init();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHEditorViewport::Update()
|
void SHEditorViewport::Update()
|
||||||
{
|
{
|
||||||
SHEditorWindow::Update();
|
SHEditorWindow::Update();
|
||||||
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f,0.0f));
|
||||||
if(Begin())
|
if(Begin())
|
||||||
{
|
{
|
||||||
ImGuizmo::SetDrawlist();
|
ImGuizmo::SetDrawlist();
|
||||||
|
@ -55,7 +56,7 @@ namespace SHADE
|
||||||
ImGuizmo::SetRect(beginCursorPos.x , beginCursorPos.y, beginContentRegionAvailable.x, beginContentRegionAvailable.y);
|
ImGuizmo::SetRect(beginCursorPos.x , beginCursorPos.y, beginContentRegionAvailable.x, beginContentRegionAvailable.y);
|
||||||
transformGizmo.Draw();
|
transformGizmo.Draw();
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
|
ImGui::PopStyleVar();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHEditorViewport::Exit()
|
void SHEditorViewport::Exit()
|
||||||
|
|
|
@ -13,6 +13,12 @@
|
||||||
#include "Editor/EditorWindow/ViewportWindow/SHEditorViewport.h"
|
#include "Editor/EditorWindow/ViewportWindow/SHEditorViewport.h"
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
void SHTransformGizmo::Init()
|
||||||
|
{
|
||||||
|
auto& style = ImGuizmo::GetStyle();
|
||||||
|
style.RotationLineThickness = 2.5f;
|
||||||
|
}
|
||||||
|
|
||||||
void SHTransformGizmo::Draw()
|
void SHTransformGizmo::Draw()
|
||||||
{
|
{
|
||||||
bool justChangedTfm = false;
|
bool justChangedTfm = false;
|
||||||
|
@ -26,9 +32,12 @@ namespace SHADE
|
||||||
|
|
||||||
SHMatrix view = SHMatrix::Transpose(editorCamera->GetViewMatrix());
|
SHMatrix view = SHMatrix::Transpose(editorCamera->GetViewMatrix());
|
||||||
SHMatrix proj = SHMatrix::Transpose(editorCamera->GetProjMatrix());
|
SHMatrix proj = SHMatrix::Transpose(editorCamera->GetProjMatrix());
|
||||||
|
|
||||||
|
//Invert projection y-axis
|
||||||
proj(1, 1) *= -1;
|
proj(1, 1) *= -1;
|
||||||
|
|
||||||
static SHMatrix gridMat = SHMatrix::Translate(0, -0.5f, 0.f) * SHMatrix::Identity;
|
static SHMatrix gridMat = SHMatrix::Translate(0, -0.5f, 0.f) * SHMatrix::Identity;
|
||||||
//ImGuizmo::DrawGrid(&view._11, &proj._11, &gridMat._11, 100.f);
|
|
||||||
if (selectedEntityTransformComponent == nullptr)
|
if (selectedEntityTransformComponent == nullptr)
|
||||||
{
|
{
|
||||||
SHEditor* editor = SHSystemManager::GetSystem<SHEditor>();
|
SHEditor* editor = SHSystemManager::GetSystem<SHEditor>();
|
||||||
|
@ -55,31 +64,37 @@ namespace SHADE
|
||||||
return;
|
return;
|
||||||
|
|
||||||
SHMatrix mat = selectedEntityTransformComponent->GetTRS();
|
SHMatrix mat = selectedEntityTransformComponent->GetTRS();
|
||||||
isManipulating = ImGuizmo::Manipulate(&view._11, &proj._11, static_cast<ImGuizmo::OPERATION>(operation), ImGuizmo::MODE::WORLD, &mat._11);
|
useSnap = ImGui::IsKeyDown(ImGuiKey_LeftCtrl);
|
||||||
if (!justChangedTfm)
|
if(useSnap)
|
||||||
{
|
{
|
||||||
if (ImGui::IsItemClicked())
|
switch (operation)
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHMatrix>>(selectedEntityTransformComponent->GetTRS(), mat, [tfm = std::move(selectedEntityTransformComponent)](SHMatrix const& mtx)
|
{
|
||||||
{
|
case Operation::TRANSLATE: snap = &translationSnap.x; break;
|
||||||
if (!tfm)
|
case Operation::ROTATE: snap = &rotationSnap; break;
|
||||||
return;
|
case Operation::SCALE: snap = &scaleSnap; break;
|
||||||
SHVec3 translate{}, rotate{}, scale{};
|
default: snap = &translationSnap.x;
|
||||||
mtx.Decompose(translate, rotate, scale);
|
}
|
||||||
tfm->SetWorldPosition(translate);
|
|
||||||
tfm->SetWorldRotation(rotate);
|
|
||||||
tfm->SetWorldScale(scale);
|
|
||||||
})));
|
|
||||||
else if (ImGui::IsItemHovered(ImGuiMouseButton_Left) && ImGui::IsMouseDown(ImGuiMouseButton_Left) && isManipulating)
|
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHMatrix>>(selectedEntityTransformComponent->GetTRS(), mat, [tfm = std::move(selectedEntityTransformComponent)](SHMatrix const& mtx)
|
|
||||||
{
|
|
||||||
if (!tfm)
|
|
||||||
return;
|
|
||||||
SHVec3 translate{}, rotate{}, scale{};
|
|
||||||
mtx.Decompose(translate, rotate, scale);
|
|
||||||
tfm->SetWorldPosition(translate);
|
|
||||||
tfm->SetWorldRotation(rotate);
|
|
||||||
tfm->SetWorldScale(scale);
|
|
||||||
})), true);
|
|
||||||
}
|
}
|
||||||
|
ImGuizmo::Manipulate(&view._11, &proj._11, static_cast<ImGuizmo::OPERATION>(operation), ImGuizmo::MODE::WORLD, &mat._11, nullptr, useSnap ? snap : nullptr);
|
||||||
|
static bool startRecording = false;
|
||||||
|
if (!justChangedTfm && ImGuizmo::IsUsing())
|
||||||
|
{
|
||||||
|
|
||||||
|
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHMatrix>>(selectedEntityTransformComponent->GetTRS(), mat, [tfm = (selectedEntityTransformComponent)](SHMatrix const& mtx)
|
||||||
|
{
|
||||||
|
if (!tfm)
|
||||||
|
return;
|
||||||
|
SHVec3 translate{}, rotate{}, scale{};
|
||||||
|
mtx.Decompose(translate, rotate, scale);
|
||||||
|
tfm->SetWorldPosition(translate);
|
||||||
|
tfm->SetWorldRotation(rotate);
|
||||||
|
tfm->SetWorldScale(scale);
|
||||||
|
})), startRecording);
|
||||||
|
if(!startRecording)
|
||||||
|
startRecording = true;
|
||||||
|
}
|
||||||
|
isManipulating = ImGuizmo::IsUsing() || startRecording;
|
||||||
|
if(startRecording && ImGui::IsMouseReleased(ImGuiMouseButton_Left))
|
||||||
|
startRecording = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,11 +37,17 @@ namespace SHADE
|
||||||
UNIVERSAL = TRANSLATE | ROTATE | SCALEU
|
UNIVERSAL = TRANSLATE | ROTATE | SCALEU
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void Init();
|
||||||
void Draw();
|
void Draw();
|
||||||
bool isManipulating = false;
|
bool isManipulating = false;
|
||||||
|
bool useSnap = false;
|
||||||
Mode mode = Mode::WORLD;
|
Mode mode = Mode::WORLD;
|
||||||
Operation operation = Operation::TRANSLATE;
|
Operation operation = Operation::TRANSLATE;
|
||||||
private:
|
private:
|
||||||
|
float scaleSnap = 0.25f;
|
||||||
|
float rotationSnap = 1.0f;
|
||||||
|
SHVec3 translationSnap = SHVec3(0.25f, 0.25f, 0.25f);
|
||||||
|
float* snap = nullptr;
|
||||||
SHTransformComponent* selectedEntityTransformComponent{nullptr};
|
SHTransformComponent* selectedEntityTransformComponent{nullptr};
|
||||||
SHCameraComponent* editorCamera{nullptr};
|
SHCameraComponent* editorCamera{nullptr};
|
||||||
};
|
};
|
||||||
|
|
|
@ -92,6 +92,7 @@ namespace SHADE
|
||||||
SHEditorWindowManager::CreateEditorWindow<SHHierarchyPanel>();
|
SHEditorWindowManager::CreateEditorWindow<SHHierarchyPanel>();
|
||||||
SHEditorWindowManager::CreateEditorWindow<SHEditorInspector>();
|
SHEditorWindowManager::CreateEditorWindow<SHEditorInspector>();
|
||||||
SHEditorWindowManager::CreateEditorWindow<SHEditorProfiler>();
|
SHEditorWindowManager::CreateEditorWindow<SHEditorProfiler>();
|
||||||
|
SHEditorWindowManager::CreateEditorWindow<SHAssetBrowser>();
|
||||||
SHEditorWindowManager::CreateEditorWindow<SHEditorViewport>();
|
SHEditorWindowManager::CreateEditorWindow<SHEditorViewport>();
|
||||||
|
|
||||||
io = &ImGui::GetIO();
|
io = &ImGui::GetIO();
|
||||||
|
@ -134,7 +135,7 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PollPicking();
|
//PollPicking();
|
||||||
|
|
||||||
if(ImGui::IsKeyDown(ImGuiKey_LeftShift) && ImGui::IsKeyDown(ImGuiKey_LeftCtrl) && ImGui::IsKeyReleased(ImGuiKey_Z))
|
if(ImGui::IsKeyDown(ImGuiKey_LeftShift) && ImGui::IsKeyDown(ImGuiKey_LeftCtrl) && ImGui::IsKeyReleased(ImGuiKey_Z))
|
||||||
{
|
{
|
||||||
|
|
|
@ -40,7 +40,6 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
ImGui::BeginGroup();
|
ImGui::BeginGroup();
|
||||||
|
|
||||||
auto cursorPos = ImGui::GetCursorScreenPos();
|
|
||||||
auto itemSpacing = ImGui::GetStyle().ItemSpacing;
|
auto itemSpacing = ImGui::GetStyle().ItemSpacing;
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0.0f, 0.0f));
|
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0.0f, 0.0f));
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0f, 0.0f));
|
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0f, 0.0f));
|
||||||
|
@ -158,7 +157,7 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, std::size_t N>
|
template <typename T, std::size_t N>
|
||||||
static bool DragN(const std::string& fieldLabel, std::vector<std::string>const& componentLabels,
|
static bool DragN(const std::string& label, std::vector<std::string>const& componentLabels,
|
||||||
std::vector<T*> values, float speed = 0.1f, const char* displayFormat = "", T valueMin = T(), T valueMax = T(),
|
std::vector<T*> values, float speed = 0.1f, const char* displayFormat = "", T valueMin = T(), T valueMax = T(),
|
||||||
ImGuiSliderFlags flags = 0, bool* isHovered = nullptr)
|
ImGuiSliderFlags flags = 0, bool* isHovered = nullptr)
|
||||||
{
|
{
|
||||||
|
@ -169,13 +168,13 @@ namespace SHADE
|
||||||
const ImGuiContext& g = *GImGui;
|
const ImGuiContext& g = *GImGui;
|
||||||
bool valueChanged = false;
|
bool valueChanged = false;
|
||||||
ImGui::BeginGroup();
|
ImGui::BeginGroup();
|
||||||
ImGui::PushID(fieldLabel.c_str());
|
ImGui::PushID(label.c_str());
|
||||||
PushMultiItemsWidthsAndLabels(componentLabels, 0.0f);
|
PushMultiItemsWidthsAndLabels(componentLabels, 0.0f);
|
||||||
ImGui::BeginColumns("DragVecCol", 2, ImGuiOldColumnFlags_NoBorder | ImGuiOldColumnFlags_NoResize);
|
ImGui::BeginColumns("DragVecCol", 2, ImGuiOldColumnFlags_NoBorder | ImGuiOldColumnFlags_NoResize);
|
||||||
ImGui::SetColumnWidth(-1, 80.0f);
|
ImGui::SetColumnWidth(-1, 80.0f);
|
||||||
ImGui::Text(fieldLabel.c_str());
|
ImGui::Text(label.c_str());
|
||||||
if (isHovered)
|
if (isHovered)
|
||||||
*isHovered = ImGui::IsItemHovered();
|
*isHovered = ImGui::IsItemHovered();
|
||||||
ImGui::NextColumn();
|
ImGui::NextColumn();
|
||||||
for (std::size_t i = 0; i < N; ++i)
|
for (std::size_t i = 0; i < N; ++i)
|
||||||
{
|
{
|
||||||
|
@ -203,75 +202,91 @@ namespace SHADE
|
||||||
return valueChanged;
|
return valueChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool DragVec2(const std::string& fieldLabel, std::vector<std::string>const& componentLabels, std::function<SHVec2(void)> get,
|
static bool DragVec2(const std::string& label, std::vector<std::string>const& componentLabels, std::function<SHVec2(void)> get,
|
||||||
std::function<void(SHVec2)> set, float speed = 0.1f, const char* displayFormat = "%.3f", float valueMin = 0.0f, float valueMax = 0.0f,
|
std::function<void(SHVec2)> set, float speed = 0.1f, const char* displayFormat = "%.3f", std::string_view const& tooltip = {}, float valueMin = 0.0f, float valueMax = 0.0f,
|
||||||
ImGuiSliderFlags flags = 0)
|
ImGuiSliderFlags flags = 0)
|
||||||
{
|
{
|
||||||
SHVec2 values = get();
|
SHVec2 values = get();
|
||||||
bool changed = false;
|
bool const changed = DragN<float, 2>(label, componentLabels, { &values.x, &values.y }, speed, displayFormat, valueMin, valueMax, flags);
|
||||||
if (DragN<float, 2>(fieldLabel, componentLabels, { &values.x, &values.y }, speed, displayFormat, valueMin, valueMax, flags))
|
static bool startRecording = false;
|
||||||
{
|
|
||||||
changed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (changed)
|
if (changed)
|
||||||
{
|
{
|
||||||
if (ImGui::IsMouseClicked(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left))
|
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec2>>(get(), values, set)), startRecording);
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec2>>(get(), values, set)), false);
|
if (!startRecording)
|
||||||
else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left))
|
startRecording = true;
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec2>>(get(), values, set)), true);
|
}
|
||||||
else if (ImGui::IsItemDeactivatedAfterEdit())
|
if (startRecording && ImGui::IsMouseReleased(ImGuiMouseButton_Left))
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec2>>(get(), values, set)), false);
|
startRecording = false;
|
||||||
|
if(!tooltip.empty())
|
||||||
|
{
|
||||||
|
if(ImGui::IsItemHovered())
|
||||||
|
{
|
||||||
|
ImGui::BeginTooltip();
|
||||||
|
ImGui::Text(tooltip.data());
|
||||||
|
ImGui::EndTooltip();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool DragVec3(const std::string& fieldLabel, std::vector<std::string>const& componentLabels, std::function<SHVec3(void)> get,
|
static bool DragVec3(const std::string& label, std::vector<std::string>const& componentLabels, std::function<SHVec3(void)> get,
|
||||||
std::function<void(SHVec3)> set, float speed = 0.1f, const char* displayFormat = "%.3f", float valueMin = 0.0f, float valueMax = 0.0f,
|
std::function<void(SHVec3)> set, float speed = 0.1f, const char* displayFormat = "%.3f", std::string_view const& tooltip = {}, float valueMin = 0.0f, float valueMax = 0.0f,
|
||||||
ImGuiSliderFlags flags = 0)
|
ImGuiSliderFlags flags = 0)
|
||||||
{
|
{
|
||||||
SHVec3 values = get();
|
SHVec3 values = get();
|
||||||
bool changed = false;
|
bool const changed = DragN<float, 3>(label, componentLabels, { &values.x, &values.y, &values.z }, speed, displayFormat, valueMin, valueMax, flags);
|
||||||
if (DragN<float, 3>(fieldLabel, componentLabels, { &values.x, &values.y, &values.z }, speed, displayFormat, valueMin, valueMax, flags))
|
|
||||||
{
|
|
||||||
changed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
static bool startRecording = false;
|
||||||
if (changed)
|
if (changed)
|
||||||
{
|
{
|
||||||
if (ImGui::IsMouseDown(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left, -0.2f))
|
SHVec3 old = get();
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec3>>(get(), values, set)), false);
|
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec3>>(old, values, set)), startRecording);
|
||||||
else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left))
|
if (!startRecording)
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec3>>(get(), values, set)), true);
|
startRecording = true;
|
||||||
else if (ImGui::IsItemDeactivatedAfterEdit())
|
}
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec3>>(get(), values, set)), false);
|
if (startRecording && ImGui::IsMouseReleased(ImGuiMouseButton_Left))
|
||||||
|
{
|
||||||
|
startRecording = false;
|
||||||
|
}
|
||||||
|
if(!tooltip.empty())
|
||||||
|
{
|
||||||
|
if(ImGui::IsItemHovered())
|
||||||
|
{
|
||||||
|
ImGui::BeginTooltip();
|
||||||
|
ImGui::Text(tooltip.data());
|
||||||
|
ImGui::EndTooltip();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool DragVec4(const std::string& fieldLabel, std::vector<std::string>const& componentLabels, std::function<SHVec4(void)> get,
|
static bool DragVec4(const std::string& label, std::vector<std::string>const& componentLabels, std::function<SHVec4(void)> get,
|
||||||
std::function<void(SHVec4)> set, float speed = 0.1f, const char* displayFormat = "%.3f", float valueMin = 0.0f, float valueMax = 0.0f,
|
std::function<void(SHVec4)> set, float speed = 0.1f, const char* displayFormat = "%.3f", std::string_view const& tooltip = {}, float valueMin = 0.0f, float valueMax = 0.0f,
|
||||||
ImGuiSliderFlags flags = 0)
|
ImGuiSliderFlags flags = 0)
|
||||||
{
|
{
|
||||||
SHVec4 values = get();
|
SHVec4 values = get();
|
||||||
bool changed = false;
|
bool const changed = DragN<float, 4>(label, componentLabels, { &values.x, &values.y, &values.z, &values.w }, speed, displayFormat, valueMin, valueMax, flags);
|
||||||
if (DragN<float, 4>(fieldLabel, componentLabels, { &values.x, &values.y, &values.z, &values.w }, speed, displayFormat, valueMin, valueMax, flags))
|
static bool startRecording = false;
|
||||||
{
|
|
||||||
changed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (changed)
|
if (changed)
|
||||||
{
|
{
|
||||||
if (ImGui::IsMouseDown(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left, -0.2f))
|
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec4>>(get(), values, set)), startRecording);
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec4>>(get(), values, set)), false);
|
if (!startRecording)
|
||||||
else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left))
|
startRecording = true;
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec4>>(get(), values, set)), true);
|
}
|
||||||
else if (ImGui::IsItemDeactivatedAfterEdit())
|
if (startRecording && ImGui::IsMouseReleased(ImGuiMouseButton_Left))
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec4>>(get(), values, set)), false);
|
{
|
||||||
|
startRecording = false;
|
||||||
|
}
|
||||||
|
if(!tooltip.empty())
|
||||||
|
{
|
||||||
|
if(ImGui::IsItemHovered())
|
||||||
|
{
|
||||||
|
ImGui::BeginTooltip();
|
||||||
|
ImGui::Text(tooltip.data());
|
||||||
|
ImGui::EndTooltip();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -279,173 +294,325 @@ namespace SHADE
|
||||||
//|| Widget Extensions ||
|
//|| Widget Extensions ||
|
||||||
//#==============================================================#
|
//#==============================================================#
|
||||||
|
|
||||||
static bool CheckBox(std::string const& label, std::function<bool(void)> get, std::function<void(bool const&)> set)
|
static void TextLabel(std::string_view const& text, bool sameLine = true)
|
||||||
|
{
|
||||||
|
const ImVec2 textSize = ImGui::CalcTextSize(text.data(), NULL, true);
|
||||||
|
if(textSize.x > 0.0f)
|
||||||
|
{
|
||||||
|
ImGui::Text(text.data());
|
||||||
|
ImGui::SameLine();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool CheckBox(std::string_view const& label, std::function<bool(void)> get, std::function<void(bool const&)> set, std::string_view const& tooltip = {})
|
||||||
{
|
{
|
||||||
bool value = get();
|
bool value = get();
|
||||||
if (ImGui::Checkbox(label.c_str(), &value))
|
ImGui::BeginGroup();
|
||||||
|
ImGui::PushID(label.data());
|
||||||
|
TextLabel(label);
|
||||||
|
if (ImGui::Checkbox("##", &value))
|
||||||
{
|
{
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<bool>>(get(), value, set)), false);
|
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<bool>>(get(), value, set)), false);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
ImGui::PopID();
|
||||||
|
ImGui::EndGroup();
|
||||||
|
if(!tooltip.empty())
|
||||||
|
{
|
||||||
|
if(ImGui::IsItemHovered())
|
||||||
|
{
|
||||||
|
ImGui::BeginTooltip();
|
||||||
|
ImGui::Text(tooltip.data());
|
||||||
|
ImGui::EndTooltip();
|
||||||
|
}
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static bool RadioButton(std::vector<std::string> const& listLabels, std::vector<T> const& listTypes, std::function<T(void)> get, std::function<void(T const&)> set)
|
static bool RadioButton(std::vector<std::string> const& label, std::vector<T> const& listTypes, std::function<T(void)> get, std::function<void(T const&)> set ,std::string_view const& tooltip = {})
|
||||||
{
|
{
|
||||||
T type = get();
|
T type = get();
|
||||||
|
ImGui::BeginGroup();
|
||||||
|
ImGui::PushID(label.data());
|
||||||
|
TextLabel(label);
|
||||||
for (size_t i = 0; i < listTypes.size(); i++)
|
for (size_t i = 0; i < listTypes.size(); i++)
|
||||||
{
|
{
|
||||||
if (ImGui::RadioButton(listLabels[i].c_str(), type == listTypes[i]))
|
if (ImGui::RadioButton(label[i].c_str(), type == listTypes[i]))
|
||||||
{
|
{
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<T>>(get(), listTypes[i], set)), false);
|
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<T>>(get(), listTypes[i], set)), false);
|
||||||
}
|
}
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
}
|
}
|
||||||
|
ImGui::PopID();
|
||||||
|
ImGui::EndGroup();
|
||||||
|
if (!tooltip.empty())
|
||||||
|
{
|
||||||
|
if (ImGui::IsItemHovered())
|
||||||
|
{
|
||||||
|
ImGui::BeginTooltip();
|
||||||
|
ImGui::Text(tooltip.data());
|
||||||
|
ImGui::EndTooltip();
|
||||||
|
}
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool InputText(const std::string& label, const std::function<std::string(void)> get,
|
static bool InputText(const std::string& label, const std::function<std::string(void)> get,
|
||||||
const std::function<void(std::string)> set, ImGuiInputTextFlags flag = 0,
|
const std::function<void(std::string)> set, std::string_view const& tooltip = {},
|
||||||
ImGuiInputTextCallback callback = (ImGuiInputTextCallback)0, void* userData = (void*)0)
|
ImGuiInputTextFlags flag = 0, ImGuiInputTextCallback callback = (ImGuiInputTextCallback)0, void* userData = (void*)0)
|
||||||
{
|
{
|
||||||
std::string text = get();
|
std::string text = get();
|
||||||
if (ImGui::InputText(label.c_str(), &text, flag, callback, userData))
|
ImGui::BeginGroup();
|
||||||
|
ImGui::PushID(label.data());
|
||||||
|
TextLabel(label);
|
||||||
|
if (ImGui::InputText("##", &text, flag, callback, userData))
|
||||||
{
|
{
|
||||||
if (ImGui::IsItemDeactivatedAfterEdit())
|
if (ImGui::IsItemDeactivatedAfterEdit())
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<std::string>>(get(), text, set)), false);
|
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<std::string>>(get(), text, set)), false);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
ImGui::PopID();
|
||||||
}
|
ImGui::EndGroup();
|
||||||
|
if (!tooltip.empty())
|
||||||
template <typename T>
|
|
||||||
static bool DragScalar(const std::string& fieldLabel, ImGuiDataType data_type, std::function<T(void)> get, std::function<void(T const&)> set,
|
|
||||||
float speed = 1.0f, T p_min = T(), T p_max = T(), const char* displayFormat = "%.3f", ImGuiSliderFlags flags = 0)
|
|
||||||
{
|
|
||||||
T value = get();
|
|
||||||
std::cout << value << " \n";
|
|
||||||
//bool hasChange = ImGui::DragScalar(fieldLabel.c_str(), data_type, &value, speed, &p_min, &p_max, displayFormat, flags);
|
|
||||||
|
|
||||||
if (ImGui::DragScalar(fieldLabel.c_str(), data_type, &value, speed, &p_min, &p_max, displayFormat, flags))
|
|
||||||
{
|
{
|
||||||
if (ImGui::IsMouseDown(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left))
|
if (ImGui::IsItemHovered())
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<T>>(get(), value, set)), false);
|
{
|
||||||
else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left))
|
ImGui::BeginTooltip();
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<T>>(get(), value, set)), true);
|
ImGui::Text(tooltip.data());
|
||||||
else if (ImGui::IsItemDeactivatedAfterEdit())
|
ImGui::EndTooltip();
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<T>>(get(), value, set)), false);
|
}
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool DragFloat(const std::string& fieldLabel, std::function<float(void)> get, std::function<void(float const&)> set,
|
template <typename T>
|
||||||
|
static bool DragScalar(const std::string& label, ImGuiDataType data_type, std::function<T(void)> get, std::function<void(T const&)> set,
|
||||||
|
float speed = 1.0f, T p_min = T(), T p_max = T(), const char* displayFormat = "%.3f", std::string_view const& tooltip = {}, ImGuiSliderFlags flags = 0)
|
||||||
|
{
|
||||||
|
T value = get();
|
||||||
|
ImGui::BeginGroup();
|
||||||
|
ImGui::PushID(label.data());
|
||||||
|
TextLabel(label);
|
||||||
|
const bool hasChange = ImGui::DragScalar("##", data_type, &value, speed, &p_min, &p_max, displayFormat, flags);
|
||||||
|
static bool startRecording = false;
|
||||||
|
if (hasChange)
|
||||||
|
{
|
||||||
|
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<T>>(get(), value, set)), startRecording);
|
||||||
|
if (!startRecording)
|
||||||
|
startRecording = true;
|
||||||
|
}
|
||||||
|
if (startRecording && ImGui::IsMouseReleased(ImGuiMouseButton_Left))
|
||||||
|
{
|
||||||
|
startRecording = false;
|
||||||
|
}
|
||||||
|
ImGui::PopID();
|
||||||
|
ImGui::EndGroup();
|
||||||
|
if (!tooltip.empty())
|
||||||
|
{
|
||||||
|
if (ImGui::IsItemHovered())
|
||||||
|
{
|
||||||
|
ImGui::BeginTooltip();
|
||||||
|
ImGui::Text(tooltip.data());
|
||||||
|
ImGui::EndTooltip();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hasChange;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool DragFloat(const std::string_view& label, std::function<float(void)> get, std::function<void(float const&)> set, std::string_view const& tooltip = {},
|
||||||
float speed = 0.1f, float p_min = float(), float p_max = float(), const char* displayFormat = "%.3f", ImGuiSliderFlags flags = 0)
|
float speed = 0.1f, float p_min = float(), float p_max = float(), const char* displayFormat = "%.3f", ImGuiSliderFlags flags = 0)
|
||||||
{
|
{
|
||||||
float value = get();
|
float value = get();
|
||||||
//bool hasChange = ImGui::DragFloat(fieldLabel.c_str(), &value, speed, p_min, p_max, displayFormat, flags);
|
ImGui::BeginGroup();
|
||||||
if (ImGui::DragFloat(fieldLabel.c_str(), &value, speed, p_min, p_max, displayFormat, flags))
|
ImGui::PushID(label.data());
|
||||||
|
TextLabel(label);
|
||||||
|
const bool hasChange = ImGui::DragFloat("##", &value, speed, p_min, p_max, displayFormat, flags);
|
||||||
|
static bool startRecording = false;
|
||||||
|
if (hasChange)
|
||||||
{
|
{
|
||||||
if (ImGui::IsMouseDown(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left))
|
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<float>>(get(), value, set)), startRecording);
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<float>>(get(), value, set)), false);
|
if (!startRecording)
|
||||||
else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left))
|
startRecording = true;
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<float>>(get(), value, set)), true);
|
|
||||||
else if (ImGui::IsItemDeactivatedAfterEdit())
|
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<float>>(get(), value, set)), false);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
if (startRecording && ImGui::IsMouseReleased(ImGuiMouseButton_Left))
|
||||||
return false;
|
{
|
||||||
|
startRecording = false;
|
||||||
|
}
|
||||||
|
ImGui::PopID();
|
||||||
|
ImGui::EndGroup();
|
||||||
|
if(!tooltip.empty())
|
||||||
|
{
|
||||||
|
if(ImGui::IsItemHovered())
|
||||||
|
{
|
||||||
|
ImGui::BeginTooltip();
|
||||||
|
ImGui::Text(tooltip.data());
|
||||||
|
ImGui::EndTooltip();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hasChange;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool DragInt(const std::string& fieldLabel, std::function<int(void)> get, std::function<void(int const&)> set,
|
static bool DragInt(const std::string& label, std::function<int(void)> get, std::function<void(int const&)> set, std::string_view const& tooltip = {},
|
||||||
float speed = 1.0f, int p_min = int(), int p_max = int(), const char* displayFormat = "%d", ImGuiSliderFlags flags = 0)
|
float speed = 1.0f, int p_min = int(), int p_max = int(), const char* displayFormat = "%d", ImGuiSliderFlags flags = 0)
|
||||||
{
|
{
|
||||||
int value = get();
|
int value = get();
|
||||||
//bool hasChange = ImGui::DragFloat(fieldLabel.c_str(), &value, speed, p_min, p_max, displayFormat, flags);
|
ImGui::BeginGroup();
|
||||||
if (ImGui::DragInt(fieldLabel.c_str(), &value, speed, p_min, p_max, displayFormat, flags))
|
ImGui::PushID(label.data());
|
||||||
|
TextLabel(label);
|
||||||
|
const bool hasChange = ImGui::DragInt("##", &value, speed, p_min, p_max, displayFormat, flags);
|
||||||
|
static bool startRecording = false;
|
||||||
|
if (hasChange)
|
||||||
{
|
{
|
||||||
if (ImGui::IsMouseDown(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left))
|
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<int>>(get(), value, set)), startRecording);
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<int>>(get(), value, set)), false);
|
if (!startRecording)
|
||||||
else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left))
|
startRecording = true;
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<int>>(get(), value, set)), true);
|
|
||||||
else if (ImGui::IsItemDeactivatedAfterEdit())
|
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<int>>(get(), value, set)), false);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
if (startRecording && ImGui::IsMouseReleased(ImGuiMouseButton_Left))
|
||||||
return false;
|
{
|
||||||
|
startRecording = false;
|
||||||
|
}
|
||||||
|
ImGui::PopID();
|
||||||
|
ImGui::EndGroup();
|
||||||
|
if (!tooltip.empty())
|
||||||
|
{
|
||||||
|
if (ImGui::IsItemHovered())
|
||||||
|
{
|
||||||
|
ImGui::BeginTooltip();
|
||||||
|
ImGui::Text(tooltip.data());
|
||||||
|
ImGui::EndTooltip();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hasChange;
|
||||||
}
|
}
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static bool SliderScalar(const std::string& fieldLabel, ImGuiDataType data_type, T min, T max, std::function<T(void)> get, std::function<void(T const&)> set,
|
static bool SliderScalar(const std::string& label, ImGuiDataType data_type, T min, T max, std::function<T(void)> get, std::function<void(T const&)> set, std::string_view const& tooltip = {},
|
||||||
const char* displayFormat = "%.3f", ImGuiSliderFlags flags = 0)
|
const char* displayFormat = "%.3f", ImGuiSliderFlags flags = 0)
|
||||||
{
|
{
|
||||||
T value = get();
|
T value = get();
|
||||||
if (ImGui::SliderScalar(fieldLabel.c_str(), data_type, &value, &min, &max, displayFormat, flags))
|
ImGui::BeginGroup();
|
||||||
|
ImGui::PushID(label.data());
|
||||||
|
TextLabel(label);
|
||||||
|
bool const hasChange = ImGui::SliderScalar("##", data_type, &value, &min, &max, displayFormat, flags);
|
||||||
|
static bool startRecording = false;
|
||||||
|
if (hasChange)
|
||||||
{
|
{
|
||||||
if (ImGui::IsMouseClicked(ImGuiMouseButton_Left, false) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left, -0.2f))
|
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<T>>(get(), value, set)), startRecording);
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<T>>(get(), value, set)), false);
|
if (!startRecording)
|
||||||
else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left))
|
startRecording = true;
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<T>>(get(), value, set)), true);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
if (startRecording && ImGui::IsMouseReleased(ImGuiMouseButton_Left))
|
||||||
return false;
|
{
|
||||||
|
startRecording = false;
|
||||||
|
}
|
||||||
|
ImGui::PopID();
|
||||||
|
ImGui::EndGroup();
|
||||||
|
if (!tooltip.empty())
|
||||||
|
{
|
||||||
|
if (ImGui::IsItemHovered())
|
||||||
|
{
|
||||||
|
ImGui::BeginTooltip();
|
||||||
|
ImGui::Text(tooltip.data());
|
||||||
|
ImGui::EndTooltip();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hasChange;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool SliderFloat(const std::string& fieldLabel, float min, float max, std::function<float(void)> get, std::function<void(float const&)> set,
|
static bool SliderFloat(const std::string& label, float const& min, float const& max, std::function<float(void)> get, std::function<void(float const&)> set, std::string_view const& tooltip = {},
|
||||||
const char* displayFormat = "%.3f", ImGuiSliderFlags flags = 0)
|
const char* displayFormat = "%.3f", ImGuiSliderFlags flags = 0)
|
||||||
{
|
{
|
||||||
float value = get();
|
float value = get();
|
||||||
if (ImGui::SliderFloat(fieldLabel.c_str(), &value, min, max, displayFormat, flags))
|
ImGui::BeginGroup();
|
||||||
|
ImGui::PushID(label.data());
|
||||||
|
TextLabel(label);
|
||||||
|
bool const hasChange = ImGui::SliderFloat("##", &value, min, max, displayFormat, flags);
|
||||||
|
static bool startRecording = false;
|
||||||
|
if (hasChange)
|
||||||
{
|
{
|
||||||
if (ImGui::IsMouseClicked(ImGuiMouseButton_Left, false) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left, -0.2f))
|
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<float>>(get(), value, set)), startRecording);
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<float>>(get(), value, set)), false);
|
if (!startRecording)
|
||||||
else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left))
|
startRecording = true;
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<float>>(get(), value, set)), true);
|
|
||||||
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
if (startRecording && ImGui::IsMouseReleased(ImGuiMouseButton_Left))
|
||||||
return false;
|
{
|
||||||
|
startRecording = false;
|
||||||
|
}
|
||||||
|
ImGui::PopID();
|
||||||
|
ImGui::EndGroup();
|
||||||
|
if (!tooltip.empty())
|
||||||
|
{
|
||||||
|
if (ImGui::IsItemHovered())
|
||||||
|
{
|
||||||
|
ImGui::BeginTooltip();
|
||||||
|
ImGui::Text(tooltip.data());
|
||||||
|
ImGui::EndTooltip();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hasChange;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool SliderInt(const std::string& fieldLabel, int min, int max, std::function<int(void)> get, std::function<void(int const&)> set,
|
static bool SliderInt(const std::string& label, int min, int max, std::function<int(void)> get, std::function<void(int const&)> set, std::string_view const& tooltip = {},
|
||||||
const char* displayFormat = "%d", ImGuiSliderFlags flags = 0)
|
const char* displayFormat = "%d", ImGuiSliderFlags flags = 0)
|
||||||
{
|
{
|
||||||
int value = get();
|
int value = get();
|
||||||
if (ImGui::SliderInt(fieldLabel.c_str(), &value, min, max, displayFormat, flags))
|
ImGui::BeginGroup();
|
||||||
|
ImGui::PushID(label.data());
|
||||||
|
TextLabel(label);
|
||||||
|
bool const hasChange = ImGui::SliderInt("##", &value, min, max, displayFormat, flags);
|
||||||
|
static bool startRecording = false;
|
||||||
|
if (hasChange)
|
||||||
{
|
{
|
||||||
if (ImGui::IsMouseClicked(ImGuiMouseButton_Left, false) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left, -0.2f))
|
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<int>>(get(), value, set)), false);
|
|
||||||
else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left))
|
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<int>>(get(), value, set)), true);
|
|
||||||
|
|
||||||
return true;
|
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<int>>(get(), value, set)), startRecording);
|
||||||
|
if (!startRecording)
|
||||||
|
startRecording = true;
|
||||||
}
|
}
|
||||||
|
if (startRecording && ImGui::IsMouseReleased(ImGuiMouseButton_Left))
|
||||||
return false;
|
{
|
||||||
|
startRecording = false;
|
||||||
|
}
|
||||||
|
ImGui::PopID();
|
||||||
|
ImGui::EndGroup();
|
||||||
|
if (!tooltip.empty())
|
||||||
|
{
|
||||||
|
if (ImGui::IsItemHovered())
|
||||||
|
{
|
||||||
|
ImGui::BeginTooltip();
|
||||||
|
ImGui::Text(tooltip.data());
|
||||||
|
ImGui::EndTooltip();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hasChange;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ComboBox(const std::string& fieldLabel, std::vector<const char*> list, std::function<int(void)> get, std::function<void(int const&)> set)
|
static bool ComboBox(const std::string& label, std::vector<const char*> list, std::function<int(void)> get, std::function<void(int const&)> set, std::string_view const& tooltip = {})
|
||||||
{
|
{
|
||||||
bool edited = false;
|
bool edited = false;
|
||||||
int selected = get();
|
int selected = get();
|
||||||
ImGui::PushID(fieldLabel.c_str());
|
ImGui::BeginGroup();
|
||||||
ImGui::Text(fieldLabel.c_str()); ImGui::SameLine();
|
ImGui::PushID(label.c_str());
|
||||||
|
TextLabel(label);
|
||||||
|
ImGui::SameLine();
|
||||||
|
|
||||||
if (edited = ImGui::Combo("##Combo", &selected, list.data(), static_cast<int>(list.size())))
|
if (edited = ImGui::Combo("##Combo", &selected, list.data(), static_cast<int>(list.size())))
|
||||||
{
|
{
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<int>>(get(), selected, set)), false);
|
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<int>>(get(), selected, set)), false);
|
||||||
}
|
}
|
||||||
ImGui::PopID();
|
ImGui::PopID();
|
||||||
|
ImGui::EndGroup();
|
||||||
|
if (!tooltip.empty())
|
||||||
|
{
|
||||||
|
if (ImGui::IsItemHovered())
|
||||||
|
{
|
||||||
|
ImGui::BeginTooltip();
|
||||||
|
ImGui::Text(tooltip.data());
|
||||||
|
ImGui::EndTooltip();
|
||||||
|
}
|
||||||
|
}
|
||||||
return edited;
|
return edited;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -5,8 +5,12 @@ typedef uint32_t SHEventIdentifier;
|
||||||
typedef uint32_t SHEventHandle;
|
typedef uint32_t SHEventHandle;
|
||||||
|
|
||||||
//Add your event identifiers here:
|
//Add your event identifiers here:
|
||||||
constexpr SHEventIdentifier SH_EXAMPLE_EVENT{0};
|
constexpr SHEventIdentifier SH_EXAMPLE_EVENT { 0 };
|
||||||
constexpr SHEventIdentifier SH_ENTITY_DESTROYED_EVENT{ 1 };
|
constexpr SHEventIdentifier SH_ENTITY_DESTROYED_EVENT { 1 };
|
||||||
constexpr SHEventIdentifier SH_ENTITY_CREATION_EVENT{ 2 };
|
constexpr SHEventIdentifier SH_ENTITY_CREATION_EVENT { 2 };
|
||||||
constexpr SHEventIdentifier SH_COMPONENT_ADDED_EVENT{ 3 };
|
constexpr SHEventIdentifier SH_COMPONENT_ADDED_EVENT { 3 };
|
||||||
constexpr SHEventIdentifier SH_COMPONENT_REMOVED_EVENT{ 4 };
|
constexpr SHEventIdentifier SH_COMPONENT_REMOVED_EVENT { 4 };
|
||||||
|
constexpr SHEventIdentifier SH_SCENEGRAPH_CHANGE_PARENT_EVENT { 5 };
|
||||||
|
constexpr SHEventIdentifier SH_PHYSICS_COLLIDER_ADDED_EVENT { 6 };
|
||||||
|
constexpr SHEventIdentifier SH_PHYSICS_COLLIDER_REMOVED_EVENT { 7 };
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include "SHpch.h"
|
#include "SHpch.h"
|
||||||
#include "SHEvent.h"
|
#include "SHEvent.h"
|
||||||
#include "SHEventReceiver.h"
|
#include "SHEventReceiver.h"
|
||||||
|
#include "SH_API.h"
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
INSTRUCTIONS FOR USE:
|
INSTRUCTIONS FOR USE:
|
||||||
|
@ -67,7 +68,7 @@ namespace SHADE
|
||||||
using EventManagerListener = std::function<void(SHEvent)>;
|
using EventManagerListener = std::function<void(SHEvent)>;
|
||||||
|
|
||||||
|
|
||||||
class SHEventManager
|
class SH_API SHEventManager
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include "Graphics/Buffers/SHVkBuffer.h"
|
#include "Graphics/Buffers/SHVkBuffer.h"
|
||||||
#include "Graphics/Images/SHVkImage.h"
|
#include "Graphics/Images/SHVkImage.h"
|
||||||
#include "Graphics/Descriptors/SHVkDescriptorSetGroup.h"
|
#include "Graphics/Descriptors/SHVkDescriptorSetGroup.h"
|
||||||
|
#include "Graphics/SHVkUtil.h"
|
||||||
|
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
|
@ -299,7 +300,7 @@ namespace SHADE
|
||||||
SHLOG_ERROR("Command buffer must have started recording before a pipeline can be bound. ");
|
SHLOG_ERROR("Command buffer must have started recording before a pipeline can be bound. ");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
boundPipelineLayoutHdl = pipelineHdl->GetPipelineLayout();
|
bindPointData[static_cast<uint32_t>(pipelineHdl->GetPipelineType())].boundPipelineLayoutHdl = pipelineHdl->GetPipelineLayout();
|
||||||
vkCommandBuffer.bindPipeline(pipelineHdl->GetPipelineBindPoint(), pipelineHdl->GetVkPipeline());
|
vkCommandBuffer.bindPipeline(pipelineHdl->GetPipelineBindPoint(), pipelineHdl->GetVkPipeline());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -358,9 +359,10 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHVkCommandBuffer::BindDescriptorSet(Handle<SHVkDescriptorSetGroup> descSetGroup, vk::PipelineBindPoint bindPoint, uint32_t firstSet, std::span<uint32_t> dynamicOffsets)
|
void SHVkCommandBuffer::BindDescriptorSet(Handle<SHVkDescriptorSetGroup> descSetGroup, SH_PIPELINE_TYPE bindPoint, uint32_t firstSet, std::span<uint32_t> dynamicOffsets)
|
||||||
{
|
{
|
||||||
vkCommandBuffer.bindDescriptorSets(bindPoint, boundPipelineLayoutHdl->GetVkPipelineLayout(), firstSet, descSetGroup->GetVkHandle(), dynamicOffsets);
|
uint32_t bindPointIndex = static_cast<uint32_t>(bindPoint);
|
||||||
|
vkCommandBuffer.bindDescriptorSets(SHVkUtil::GetPipelineBindPointFromType(bindPoint), bindPointData[bindPointIndex].boundPipelineLayoutHdl->GetVkPipelineLayout(), firstSet, descSetGroup->GetVkHandle(), dynamicOffsets);
|
||||||
}
|
}
|
||||||
|
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
|
@ -452,6 +454,11 @@ namespace SHADE
|
||||||
vkCommandBuffer.drawIndexedIndirect(indirectDrawData->GetVkBuffer(), 0, drawCount, sizeof(vk::DrawIndexedIndirectCommand));
|
vkCommandBuffer.drawIndexedIndirect(indirectDrawData->GetVkBuffer(), 0, drawCount, sizeof(vk::DrawIndexedIndirectCommand));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SHVkCommandBuffer::ComputeDispatch(uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ) noexcept
|
||||||
|
{
|
||||||
|
vkCommandBuffer.dispatch (groupCountX, groupCountY, groupCountZ);
|
||||||
|
}
|
||||||
|
|
||||||
void SHVkCommandBuffer::CopyBufferToImage(const vk::Buffer& src, const vk::Image& dst, const std::vector<vk::BufferImageCopy>& copyInfo)
|
void SHVkCommandBuffer::CopyBufferToImage(const vk::Buffer& src, const vk::Image& dst, const std::vector<vk::BufferImageCopy>& copyInfo)
|
||||||
{
|
{
|
||||||
vkCommandBuffer.copyBufferToImage
|
vkCommandBuffer.copyBufferToImage
|
||||||
|
@ -500,9 +507,9 @@ namespace SHADE
|
||||||
// //vkCommandBuffer.pipelineBarrier()
|
// //vkCommandBuffer.pipelineBarrier()
|
||||||
//}
|
//}
|
||||||
|
|
||||||
void SHVkCommandBuffer::ForceSetPipelineLayout(Handle<SHVkPipelineLayout> pipelineLayout) noexcept
|
void SHVkCommandBuffer::ForceSetPipelineLayout(Handle<SHVkPipelineLayout> pipelineLayout, SH_PIPELINE_TYPE pipelineType) noexcept
|
||||||
{
|
{
|
||||||
boundPipelineLayoutHdl = pipelineLayout;
|
bindPointData[static_cast<uint32_t>(pipelineType)].boundPipelineLayoutHdl = pipelineLayout;
|
||||||
}
|
}
|
||||||
|
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
|
@ -513,12 +520,13 @@ namespace SHADE
|
||||||
|
|
||||||
*/
|
*/
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
void SHVkCommandBuffer::SubmitPushConstants(void) const noexcept
|
void SHVkCommandBuffer::SubmitPushConstants(SH_PIPELINE_TYPE bindPoint) const noexcept
|
||||||
{
|
{
|
||||||
vkCommandBuffer.pushConstants(boundPipelineLayoutHdl->GetVkPipelineLayout(),
|
auto layoutHdl = bindPointData[static_cast<uint32_t>(bindPoint)].boundPipelineLayoutHdl;
|
||||||
boundPipelineLayoutHdl->GetPushConstantInterface().GetShaderStageFlags(),
|
vkCommandBuffer.pushConstants(layoutHdl->GetVkPipelineLayout(),
|
||||||
|
layoutHdl->GetPushConstantInterface().GetShaderStageFlags(),
|
||||||
0,
|
0,
|
||||||
boundPipelineLayoutHdl->GetPushConstantInterface().GetSize(), pushConstantData);
|
layoutHdl->GetPushConstantInterface().GetSize(), pushConstantData);
|
||||||
}
|
}
|
||||||
|
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
|
@ -695,7 +703,7 @@ namespace SHADE
|
||||||
, usageFlags{ rhs.usageFlags }
|
, usageFlags{ rhs.usageFlags }
|
||||||
, commandBufferCount{ rhs.commandBufferCount }
|
, commandBufferCount{ rhs.commandBufferCount }
|
||||||
, parentPool{ rhs.parentPool }
|
, parentPool{ rhs.parentPool }
|
||||||
, boundPipelineLayoutHdl{ rhs.boundPipelineLayoutHdl }
|
, bindPointData{ std::move (rhs.bindPointData)}
|
||||||
{
|
{
|
||||||
memcpy(pushConstantData, rhs.pushConstantData, PUSH_CONSTANT_SIZE);
|
memcpy(pushConstantData, rhs.pushConstantData, PUSH_CONSTANT_SIZE);
|
||||||
|
|
||||||
|
@ -728,7 +736,7 @@ namespace SHADE
|
||||||
usageFlags = rhs.usageFlags;
|
usageFlags = rhs.usageFlags;
|
||||||
commandBufferCount = rhs.commandBufferCount;
|
commandBufferCount = rhs.commandBufferCount;
|
||||||
parentPool = rhs.parentPool;
|
parentPool = rhs.parentPool;
|
||||||
boundPipelineLayoutHdl = rhs.boundPipelineLayoutHdl;
|
bindPointData = std::move(rhs.bindPointData);
|
||||||
memcpy(pushConstantData, rhs.pushConstantData, PUSH_CONSTANT_SIZE);
|
memcpy(pushConstantData, rhs.pushConstantData, PUSH_CONSTANT_SIZE);
|
||||||
|
|
||||||
rhs.vkCommandBuffer = VK_NULL_HANDLE;
|
rhs.vkCommandBuffer = VK_NULL_HANDLE;
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include "SHCommandPoolResetMode.h"
|
#include "SHCommandPoolResetMode.h"
|
||||||
#include "Resource/SHResourceLibrary.h"
|
#include "Resource/SHResourceLibrary.h"
|
||||||
#include "Graphics/Pipeline/SHVkPipelineLayout.h"
|
#include "Graphics/Pipeline/SHVkPipelineLayout.h"
|
||||||
|
#include "Graphics/Pipeline/SHPipelineType.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
@ -39,7 +40,14 @@ namespace SHADE
|
||||||
friend class SHResourceLibrary<SHVkCommandBuffer>;
|
friend class SHResourceLibrary<SHVkCommandBuffer>;
|
||||||
|
|
||||||
static constexpr uint16_t PUSH_CONSTANT_SIZE = 512;
|
static constexpr uint16_t PUSH_CONSTANT_SIZE = 512;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
struct PipelineBindPointData
|
||||||
|
{
|
||||||
|
//! The currently bound pipeline
|
||||||
|
Handle<SHVkPipelineLayout> boundPipelineLayoutHdl;
|
||||||
|
};
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
/* PRIVATE MEMBER VARIABLES */
|
/* PRIVATE MEMBER VARIABLES */
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
|
@ -66,8 +74,8 @@ namespace SHADE
|
||||||
//! The command pool that this command buffer belongs to
|
//! The command pool that this command buffer belongs to
|
||||||
Handle<SHVkCommandPool> parentPool;
|
Handle<SHVkCommandPool> parentPool;
|
||||||
|
|
||||||
//! The currently bound pipeline
|
//! Every command buffer will have a set of pipeline bind point specific data
|
||||||
Handle<SHVkPipelineLayout> boundPipelineLayoutHdl;
|
std::array<PipelineBindPointData, static_cast<uint32_t>(SH_PIPELINE_TYPE::NUM_TYPES)> bindPointData;
|
||||||
|
|
||||||
//! The push constant data for the command buffer
|
//! The push constant data for the command buffer
|
||||||
uint8_t pushConstantData[PUSH_CONSTANT_SIZE];
|
uint8_t pushConstantData[PUSH_CONSTANT_SIZE];
|
||||||
|
@ -112,13 +120,16 @@ namespace SHADE
|
||||||
void BindPipeline (Handle<SHVkPipeline> const& pipelineHdl) noexcept;
|
void BindPipeline (Handle<SHVkPipeline> const& pipelineHdl) noexcept;
|
||||||
void BindVertexBuffer (uint32_t bindingPoint, Handle<SHVkBuffer> const& buffer, vk::DeviceSize offset) noexcept;
|
void BindVertexBuffer (uint32_t bindingPoint, Handle<SHVkBuffer> const& buffer, vk::DeviceSize offset) noexcept;
|
||||||
void BindIndexBuffer (Handle<SHVkBuffer> const& buffer, uint32_t startingIndex) const noexcept;
|
void BindIndexBuffer (Handle<SHVkBuffer> const& buffer, uint32_t startingIndex) const noexcept;
|
||||||
void BindDescriptorSet (Handle<SHVkDescriptorSetGroup> descSetGroup, vk::PipelineBindPoint bindPoint, uint32_t firstSet, std::span<uint32_t> dynamicOffsets);
|
void BindDescriptorSet (Handle<SHVkDescriptorSetGroup> descSetGroup, SH_PIPELINE_TYPE bindPoint, uint32_t firstSet, std::span<uint32_t> dynamicOffsets);
|
||||||
|
|
||||||
// Draw Commands
|
// Draw Commands
|
||||||
void DrawArrays (uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance) const noexcept;
|
void DrawArrays (uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance) const noexcept;
|
||||||
void DrawIndexed (uint32_t indexCount, uint32_t firstIndex, uint32_t vertexOffset) const noexcept;
|
void DrawIndexed (uint32_t indexCount, uint32_t firstIndex, uint32_t vertexOffset) const noexcept;
|
||||||
void DrawMultiIndirect (Handle<SHVkBuffer> indirectDrawData, uint32_t drawCount);
|
void DrawMultiIndirect (Handle<SHVkBuffer> indirectDrawData, uint32_t drawCount);
|
||||||
|
|
||||||
|
// Compute Commands
|
||||||
|
void ComputeDispatch (uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ) noexcept;
|
||||||
|
|
||||||
// Buffer Copy
|
// Buffer Copy
|
||||||
void CopyBufferToImage (const vk::Buffer& src, const vk::Image& dst, const std::vector<vk::BufferImageCopy>& copyInfo);
|
void CopyBufferToImage (const vk::Buffer& src, const vk::Image& dst, const std::vector<vk::BufferImageCopy>& copyInfo);
|
||||||
void CopyImageToBuffer (const vk::Image& src, const vk::Buffer& dst, const std::vector<vk::BufferImageCopy>& copyInfo);
|
void CopyImageToBuffer (const vk::Image& src, const vk::Buffer& dst, const std::vector<vk::BufferImageCopy>& copyInfo);
|
||||||
|
@ -138,13 +149,13 @@ namespace SHADE
|
||||||
|
|
||||||
// Push Constant variable setting
|
// Push Constant variable setting
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void SetPushConstantVariable(std::string variableName, T const& data) noexcept
|
void SetPushConstantVariable(std::string variableName, T const& data, SH_PIPELINE_TYPE bindPoint) noexcept
|
||||||
{
|
{
|
||||||
memcpy (static_cast<uint8_t*>(pushConstantData) + boundPipelineLayoutHdl->GetPushConstantInterface().GetOffset(variableName), &data, sizeof (T));
|
memcpy (static_cast<uint8_t*>(pushConstantData) + bindPointData[static_cast<uint32_t>(bindPoint)].boundPipelineLayoutHdl->GetPushConstantInterface().GetOffset(variableName), &data, sizeof (T));
|
||||||
};
|
};
|
||||||
void ForceSetPipelineLayout (Handle<SHVkPipelineLayout> pipelineLayout) noexcept;
|
void ForceSetPipelineLayout (Handle<SHVkPipelineLayout> pipelineLayout, SH_PIPELINE_TYPE pipelineType) noexcept;
|
||||||
|
|
||||||
void SubmitPushConstants (void) const noexcept;
|
void SubmitPushConstants (SH_PIPELINE_TYPE bindPoint) const noexcept;
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
/* GETTERS AND SETTERS */
|
/* GETTERS AND SETTERS */
|
||||||
|
|
|
@ -25,7 +25,8 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
|
|
||||||
SHVkDescriptorPool::SHVkDescriptorPool(SHVkDescriptorPool&& rhs) noexcept
|
SHVkDescriptorPool::SHVkDescriptorPool(SHVkDescriptorPool&& rhs) noexcept
|
||||||
: device{ rhs.device }
|
: ISelfHandle (rhs)
|
||||||
|
, device{ rhs.device }
|
||||||
, pool{ rhs.pool }
|
, pool{ rhs.pool }
|
||||||
{
|
{
|
||||||
rhs.pool = VK_NULL_HANDLE;
|
rhs.pool = VK_NULL_HANDLE;
|
||||||
|
|
|
@ -91,7 +91,7 @@ namespace SHADE
|
||||||
|
|
||||||
// new write for the binding
|
// new write for the binding
|
||||||
updater.writeInfos.emplace_back();
|
updater.writeInfos.emplace_back();
|
||||||
updater.writeHashMap.try_emplace(writeHash, updater.writeInfos.size() - 1);
|
updater.writeHashMap.try_emplace(writeHash, static_cast<uint32_t>(updater.writeInfos.size()) - 1u);
|
||||||
auto& writeInfo = updater.writeInfos.back();
|
auto& writeInfo = updater.writeInfos.back();
|
||||||
|
|
||||||
// Descriptor count for the write descriptor set. Usually this is set to 1, but if binding is variable sized, set to info passed in
|
// Descriptor count for the write descriptor set. Usually this is set to 1, but if binding is variable sized, set to info passed in
|
||||||
|
@ -102,10 +102,10 @@ namespace SHADE
|
||||||
//case vk::DescriptorType::eSampler:
|
//case vk::DescriptorType::eSampler:
|
||||||
//case vk::DescriptorType::eSampledImage:
|
//case vk::DescriptorType::eSampledImage:
|
||||||
case vk::DescriptorType::eCombinedImageSampler:
|
case vk::DescriptorType::eCombinedImageSampler:
|
||||||
|
case vk::DescriptorType::eStorageImage:
|
||||||
|
case vk::DescriptorType::eInputAttachment:
|
||||||
writeInfo.descImageInfos.resize(descriptorCount);
|
writeInfo.descImageInfos.resize(descriptorCount);
|
||||||
break;
|
break;
|
||||||
//case vk::DescriptorType::eStorageImage:
|
|
||||||
// break;
|
|
||||||
case vk::DescriptorType::eUniformTexelBuffer:
|
case vk::DescriptorType::eUniformTexelBuffer:
|
||||||
case vk::DescriptorType::eStorageTexelBuffer:
|
case vk::DescriptorType::eStorageTexelBuffer:
|
||||||
case vk::DescriptorType::eUniformBuffer:
|
case vk::DescriptorType::eUniformBuffer:
|
||||||
|
@ -165,6 +165,7 @@ namespace SHADE
|
||||||
if (imageViewsAndSamplers.size() > writeInfo.descImageInfos.size())
|
if (imageViewsAndSamplers.size() > writeInfo.descImageInfos.size())
|
||||||
{
|
{
|
||||||
SHLOG_ERROR("Attempting write too many descriptors into descriptor set. Failed to write to vk::WriteDescriptorSet. ");
|
SHLOG_ERROR("Attempting write too many descriptors into descriptor set. Failed to write to vk::WriteDescriptorSet. ");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint32_t i = 0; i < imageViewsAndSamplers.size(); ++i)
|
for (uint32_t i = 0; i < imageViewsAndSamplers.size(); ++i)
|
||||||
|
|
|
@ -31,6 +31,8 @@ namespace SHADE
|
||||||
class SHVkDescriptorSetGroup
|
class SHVkDescriptorSetGroup
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
using viewSamplerLayout = std::tuple<Handle<SHVkImageView>, Handle<SHVkSampler>, vk::ImageLayout>;
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------*/
|
||||||
/* Constructor/Destructors */
|
/* Constructor/Destructors */
|
||||||
/*-----------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
|
|
@ -233,6 +233,8 @@ namespace SHADE
|
||||||
, vmaAllocator{rhs.vmaAllocator}
|
, vmaAllocator{rhs.vmaAllocator}
|
||||||
, nonDedicatedBestIndex {0}
|
, nonDedicatedBestIndex {0}
|
||||||
, parentPhysicalDeviceHdl {rhs.parentPhysicalDeviceHdl}
|
, parentPhysicalDeviceHdl {rhs.parentPhysicalDeviceHdl}
|
||||||
|
, uboBufferMemoryAlignment{ 0 }
|
||||||
|
, ssboBufferMemoryAlignment{ 0 }
|
||||||
{
|
{
|
||||||
rhs.vkLogicalDevice = VK_NULL_HANDLE;
|
rhs.vkLogicalDevice = VK_NULL_HANDLE;
|
||||||
}
|
}
|
||||||
|
@ -261,6 +263,8 @@ namespace SHADE
|
||||||
vmaAllocator = rhs.vmaAllocator;
|
vmaAllocator = rhs.vmaAllocator;
|
||||||
nonDedicatedBestIndex = 0;
|
nonDedicatedBestIndex = 0;
|
||||||
parentPhysicalDeviceHdl = rhs.parentPhysicalDeviceHdl;
|
parentPhysicalDeviceHdl = rhs.parentPhysicalDeviceHdl;
|
||||||
|
uboBufferMemoryAlignment = rhs.uboBufferMemoryAlignment;
|
||||||
|
ssboBufferMemoryAlignment = rhs.ssboBufferMemoryAlignment;
|
||||||
|
|
||||||
rhs.vkLogicalDevice = VK_NULL_HANDLE;
|
rhs.vkLogicalDevice = VK_NULL_HANDLE;
|
||||||
|
|
||||||
|
@ -529,6 +533,11 @@ namespace SHADE
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Handle<SHVkPipeline> SHVkLogicalDevice::CreateComputePipeline(Handle<SHVkPipelineLayout> const& pipelineLayoutHdl) noexcept
|
||||||
|
{
|
||||||
|
return SHVkInstance::GetResourceManager().Create <SHVkPipeline>(GetHandle(), pipelineLayoutHdl);
|
||||||
|
}
|
||||||
|
|
||||||
Handle<SHVkSampler> SHVkLogicalDevice::CreateSampler(const SHVkSamplerParams& params) noexcept
|
Handle<SHVkSampler> SHVkLogicalDevice::CreateSampler(const SHVkSamplerParams& params) noexcept
|
||||||
{
|
{
|
||||||
return SHVkInstance::GetResourceManager().Create <SHVkSampler>(GetHandle(), params);
|
return SHVkInstance::GetResourceManager().Create <SHVkSampler>(GetHandle(), params);
|
||||||
|
|
|
@ -175,12 +175,17 @@ namespace SHADE
|
||||||
std::string const& shaderName
|
std::string const& shaderName
|
||||||
) noexcept;
|
) noexcept;
|
||||||
|
|
||||||
Handle<SHVkPipeline> CreateGraphicsPipeline (
|
Handle<SHVkPipeline> CreateGraphicsPipeline (
|
||||||
Handle<SHVkPipelineLayout> const& pipelineLayoutHdl,
|
Handle<SHVkPipelineLayout> const& pipelineLayoutHdl,
|
||||||
SHVkPipelineState const* const state,
|
SHVkPipelineState const* const state,
|
||||||
Handle<SHVkRenderpass> const& renderpassHdl,
|
Handle<SHVkRenderpass> const& renderpassHdl,
|
||||||
Handle<SHSubpass> subpass
|
Handle<SHSubpass> subpass
|
||||||
) noexcept;
|
) noexcept;
|
||||||
|
|
||||||
|
Handle<SHVkPipeline> CreateComputePipeline (
|
||||||
|
Handle<SHVkPipelineLayout> const& pipelineLayoutHdl
|
||||||
|
) noexcept;
|
||||||
|
|
||||||
Handle<SHVkSampler> CreateSampler (const SHVkSamplerParams& params) noexcept;
|
Handle<SHVkSampler> CreateSampler (const SHVkSamplerParams& params) noexcept;
|
||||||
|
|
||||||
Handle<SHVkRenderpass> CreateRenderpass (std::span<vk::AttachmentDescription> const vkDescriptions, std::vector<SHVkSubpassParams> const& subpasses) noexcept;
|
Handle<SHVkRenderpass> CreateRenderpass (std::span<vk::AttachmentDescription> const vkDescriptions, std::vector<SHVkSubpassParams> const& subpasses) noexcept;
|
||||||
|
|
|
@ -49,7 +49,7 @@ namespace SHADE
|
||||||
SHVkSampler::~SHVkSampler() noexcept
|
SHVkSampler::~SHVkSampler() noexcept
|
||||||
{
|
{
|
||||||
if (vkSampler)
|
if (vkSampler)
|
||||||
device->GetVkLogicalDevice().destroySampler();
|
device->GetVkLogicalDevice().destroySampler(vkSampler);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -30,185 +30,200 @@ of DigiPen Institute of Technology is prohibited.
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/* SHBatch - Usage Functions */
|
/* SHBatch - Usage Functions */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
SHBatch::SHBatch(Handle<SHVkPipeline> pipeline)
|
SHBatch::SHBatch(Handle<SHVkPipeline> pipeline)
|
||||||
: pipeline{ pipeline }
|
: pipeline{ pipeline }
|
||||||
{
|
{
|
||||||
if (!pipeline)
|
if (!pipeline)
|
||||||
throw std::invalid_argument("Attempted to create a SHBatch with an invalid SHPipeline!");
|
throw std::invalid_argument("Attempted to create a SHBatch with an invalid SHPipeline!");
|
||||||
|
|
||||||
// Mark all as dirty
|
// Mark all as dirty
|
||||||
setAllDirtyFlags();
|
setAllDirtyFlags();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHBatch::Add(const SHRenderable* renderable)
|
||||||
|
{
|
||||||
|
// Check if we have a SubBatch with the same mesh yet
|
||||||
|
auto subBatch = std::find_if(subBatches.begin(), subBatches.end(), [&](const SHSubBatch& batch)
|
||||||
|
{
|
||||||
|
return batch.Mesh == renderable->Mesh;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Create one if not found
|
||||||
|
if (subBatch == subBatches.end())
|
||||||
|
{
|
||||||
|
subBatches.emplace_back(renderable->Mesh);
|
||||||
|
subBatch = subBatches.end() - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHBatch::Add(const SHRenderable* renderable)
|
// Add renderable in
|
||||||
{
|
subBatch->Renderables.insert(renderable->GetEID());
|
||||||
// Check if we have a SubBatch with the same mesh yet
|
|
||||||
auto subBatch = std::find_if(subBatches.begin(), subBatches.end(), [&](const SHSubBatch& batch)
|
|
||||||
{
|
|
||||||
return batch.Mesh == renderable->Mesh;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Create one if not found
|
// Also add material instance in
|
||||||
if (subBatch == subBatches.end())
|
referencedMatInstances.insert(renderable->GetMaterial());
|
||||||
|
|
||||||
|
// Mark all as dirty
|
||||||
|
setAllDirtyFlags();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHBatch::Remove(const SHRenderable* renderable)
|
||||||
|
{
|
||||||
|
// Check if we have a SubBatch with the same mesh yet
|
||||||
|
auto subBatch = std::find_if(subBatches.begin(), subBatches.end(), [&](const SHSubBatch& batch)
|
||||||
|
{
|
||||||
|
return batch.Mesh == renderable->Mesh;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Attempt to remove if it exists
|
||||||
|
if (subBatch == subBatches.end())
|
||||||
|
return;
|
||||||
|
|
||||||
|
subBatch->Renderables.erase(renderable->GetEID());
|
||||||
|
|
||||||
|
// Check if other renderables in subBatches contain the same material instance
|
||||||
|
bool matUnused = true;
|
||||||
|
for (const auto& sb : subBatches)
|
||||||
|
for (const auto& rendId : sb.Renderables)
|
||||||
|
{
|
||||||
|
auto rend = SHComponentManager::GetComponent<SHRenderable>(rendId);
|
||||||
|
if (rend)
|
||||||
{
|
{
|
||||||
subBatches.emplace_back(renderable->Mesh);
|
if (rend->GetMaterial() == renderable->GetMaterial())
|
||||||
subBatch = subBatches.end() - 1;
|
{
|
||||||
|
matUnused = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SHLOG_WARNING("[SHBatch] Entity with a missing SHRenderable found!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Add renderable in
|
// Material is no longer in this library, so we remove it
|
||||||
subBatch->Renderables.insert(renderable);
|
if (matUnused)
|
||||||
|
referencedMatInstances.erase(renderable->WasMaterialChanged() ? renderable->GetPrevMaterial() : renderable->GetMaterial());
|
||||||
|
|
||||||
// Also add material instance in
|
// Mark all as dirty
|
||||||
referencedMatInstances.insert(renderable->GetMaterial());
|
setAllDirtyFlags();
|
||||||
|
}
|
||||||
|
|
||||||
// Mark all as dirty
|
void SHBatch::Clear()
|
||||||
setAllDirtyFlags();
|
{
|
||||||
|
subBatches.clear();
|
||||||
|
|
||||||
|
// Clear CPU buffers
|
||||||
|
drawData.clear();
|
||||||
|
transformData.clear();
|
||||||
|
instancedIntegerData.clear();
|
||||||
|
matPropsData.reset();
|
||||||
|
matPropsDataSize = 0;
|
||||||
|
|
||||||
|
|
||||||
|
// Clear GPU buffers
|
||||||
|
for (int i = 0; i < SHGraphicsConstants::NUM_FRAME_BUFFERS; ++i)
|
||||||
|
{
|
||||||
|
drawDataBuffer[i].Free();
|
||||||
|
transformDataBuffer[i].Free();
|
||||||
|
instancedIntegerBuffer[i].Free();
|
||||||
|
matPropsBuffer[i].Free();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHBatch::UpdateMaterialBuffer(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool)
|
||||||
|
{
|
||||||
|
if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS)
|
||||||
|
{
|
||||||
|
SHLOG_WARNING("[SHBatch] Attempted to update transform buffers with an invalid frame index.");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHBatch::Remove(const SHRenderable* renderable)
|
// Check if there are even material properties to update
|
||||||
|
if (!matPropsData)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Check if any materials have changed
|
||||||
|
bool hasChanged = false;
|
||||||
|
for (const auto& material : referencedMatInstances)
|
||||||
{
|
{
|
||||||
// Check if we have a SubBatch with the same mesh yet
|
if (material->HasChanged())
|
||||||
auto subBatch = std::find_if(subBatches.begin(), subBatches.end(), [&](const SHSubBatch& batch)
|
{
|
||||||
{
|
hasChanged = true;
|
||||||
return batch.Mesh == renderable->Mesh;
|
break;
|
||||||
});
|
}
|
||||||
|
|
||||||
// Attempt to remove if it exists
|
|
||||||
if (subBatch == subBatches.end())
|
|
||||||
return;
|
|
||||||
|
|
||||||
subBatch->Renderables.erase(renderable);
|
|
||||||
|
|
||||||
// Check if other renderables in subBatches contain the same material instance
|
|
||||||
bool matUnused = true;
|
|
||||||
for (const auto& sb : subBatches)
|
|
||||||
for (const auto& rend : sb.Renderables)
|
|
||||||
{
|
|
||||||
if (rend->GetMaterial() == renderable->GetMaterial())
|
|
||||||
{
|
|
||||||
matUnused = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Material is no longer in this library, so we remove it
|
|
||||||
if (matUnused)
|
|
||||||
referencedMatInstances.erase(renderable->GetMaterial());
|
|
||||||
|
|
||||||
// Mark all as dirty
|
|
||||||
for (bool& dirt : isDirty)
|
|
||||||
dirt = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHBatch::Clear()
|
// We need to update all the material buffers if the materials have changed
|
||||||
|
if (hasChanged)
|
||||||
{
|
{
|
||||||
subBatches.clear();
|
for (auto& dirt : matBufferDirty)
|
||||||
|
dirt = true;
|
||||||
// Clear CPU buffers
|
|
||||||
drawData.clear();
|
|
||||||
transformData.clear();
|
|
||||||
eidData.clear();
|
|
||||||
matPropsData.reset();
|
|
||||||
matPropsDataSize = 0;
|
|
||||||
|
|
||||||
|
|
||||||
// Clear GPU buffers
|
|
||||||
for (int i = 0; i < SHGraphicsConstants::NUM_FRAME_BUFFERS; ++i)
|
|
||||||
{
|
|
||||||
drawDataBuffer[i].Free();
|
|
||||||
transformDataBuffer[i].Free();
|
|
||||||
eidBuffer[i].Free();
|
|
||||||
matPropsBuffer[i].Free();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHBatch::UpdateMaterialBuffer(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool)
|
// Check if this frame's buffer is dirty
|
||||||
{
|
if (!matBufferDirty[frameIndex])
|
||||||
if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS)
|
return;
|
||||||
{
|
|
||||||
SHLOG_WARNING("[SHBatch] Attempted to update transform buffers with an invalid frame index.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if there are even material properties to update
|
// Build CPU Buffer
|
||||||
if (!matPropsData)
|
char* propsCurrPtr = matPropsData.get();
|
||||||
return;
|
for (auto& subBatch : subBatches)
|
||||||
|
for (auto rendId : subBatch.Renderables)
|
||||||
// Check if any materials have changed
|
{
|
||||||
bool hasChanged = false;
|
const SHRenderable* renderable = SHComponentManager::GetComponent<SHRenderable>(rendId);
|
||||||
for (const auto& material : referencedMatInstances)
|
if (renderable)
|
||||||
{
|
{
|
||||||
if (material->HasChanged())
|
renderable->GetMaterial()->ExportProperties(propsCurrPtr);
|
||||||
{
|
|
||||||
hasChanged = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
// We need to update all the material buffers if the materials have changed
|
|
||||||
if (hasChanged)
|
|
||||||
{
|
{
|
||||||
for (auto& dirt : matBufferDirty)
|
SHLOG_WARNING("[SHBatch] Entity with a missing SHRenderable found!");
|
||||||
dirt = true;
|
|
||||||
}
|
}
|
||||||
|
propsCurrPtr += singleMatPropAlignedSize;
|
||||||
|
}
|
||||||
|
|
||||||
// Check if this frame's buffer is dirty
|
// Transfer to GPU
|
||||||
if (!matBufferDirty[frameIndex])
|
rebuildMaterialBuffers(frameIndex, descPool);
|
||||||
return;
|
|
||||||
|
|
||||||
// Build CPU Buffer
|
// This frame is updated
|
||||||
char* propsCurrPtr = matPropsData.get();
|
matBufferDirty[frameIndex] = false;
|
||||||
for (auto& subBatch : subBatches)
|
}
|
||||||
for (const SHRenderable* renderable : subBatch.Renderables)
|
|
||||||
{
|
|
||||||
renderable->GetMaterial()->ExportProperties(propsCurrPtr);
|
|
||||||
propsCurrPtr += singleMatPropAlignedSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Transfer to GPU
|
|
||||||
rebuildMaterialBuffers(frameIndex, descPool);
|
|
||||||
|
|
||||||
// This frame is updated
|
void SHBatch::UpdateTransformBuffer(uint32_t frameIndex)
|
||||||
matBufferDirty[frameIndex] = false;
|
{
|
||||||
}
|
if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS)
|
||||||
|
|
||||||
void SHBatch::UpdateTransformBuffer(uint32_t frameIndex)
|
|
||||||
{
|
{
|
||||||
if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS)
|
SHLOG_WARNING("[SHBatch] Attempted to update transform buffers with an invalid frame index.");
|
||||||
{
|
return;
|
||||||
SHLOG_WARNING("[SHBatch] Attempted to update transform buffers with an invalid frame index.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reset Transform Data
|
|
||||||
transformData.clear();
|
|
||||||
|
|
||||||
// Populate on the CPU
|
|
||||||
for (auto& subBatch : subBatches)
|
|
||||||
for (const SHRenderable* renderable : subBatch.Renderables)
|
|
||||||
{
|
|
||||||
// Transform
|
|
||||||
auto transform = SHComponentManager::GetComponent<SHTransformComponent>(renderable->GetEID());
|
|
||||||
if (!transform)
|
|
||||||
{
|
|
||||||
SHLOG_WARNING("[SHBatch] Entity contianing a SHRenderable with no SHTransformComponent found!");
|
|
||||||
transformData.emplace_back();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
transformData.emplace_back(transform->GetTRS());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Transfer to GPU
|
|
||||||
if (transformDataBuffer[frameIndex])
|
|
||||||
transformDataBuffer[frameIndex]->WriteToMemory(transformData.data(), static_cast<uint32_t>(transformData.size() * sizeof(SHMatrix)), 0, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHBatch::UpdateEIDBuffer(uint32_t frameIndex)
|
// Reset Transform Data
|
||||||
|
transformData.clear();
|
||||||
|
|
||||||
|
// Populate on the CPU
|
||||||
|
for (auto& subBatch : subBatches)
|
||||||
|
for (auto rendId : subBatch.Renderables)
|
||||||
|
{
|
||||||
|
// Transform
|
||||||
|
auto transform = SHComponentManager::GetComponent<SHTransformComponent>(rendId);
|
||||||
|
if (transform)
|
||||||
|
{
|
||||||
|
transformData.emplace_back(transform->GetTRS());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SHLOG_WARNING("[SHBatch] Entity contianing a SHRenderable with no SHTransformComponent found!");
|
||||||
|
transformData.emplace_back();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Transfer to GPU
|
||||||
|
if (transformDataBuffer[frameIndex])
|
||||||
|
transformDataBuffer[frameIndex]->WriteToMemory(transformData.data(), static_cast<uint32_t>(transformData.size() * sizeof(SHMatrix)), 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHBatch::UpdateInstancedIntegerBuffer(uint32_t frameIndex)
|
||||||
{
|
{
|
||||||
if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS)
|
if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS)
|
||||||
{
|
{
|
||||||
|
@ -217,224 +232,244 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset Transform Data
|
// Reset Transform Data
|
||||||
eidData.clear();
|
instancedIntegerData.clear();
|
||||||
|
|
||||||
// Populate on the CPU
|
// Populate on the CPU
|
||||||
for (auto& subBatch : subBatches)
|
for (auto& subBatch : subBatches)
|
||||||
for (const SHRenderable* renderable : subBatch.Renderables)
|
for (auto rendId : subBatch.Renderables)
|
||||||
{
|
{
|
||||||
eidData.emplace_back(renderable->GetEID());
|
auto* renderable = SHComponentManager::GetComponent<SHRenderable>(rendId);
|
||||||
|
instancedIntegerData.emplace_back(SHInstancedIntegerData
|
||||||
|
{
|
||||||
|
rendId,
|
||||||
|
renderable->GetLightLayer()
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Transfer to GPU
|
// Transfer to GPU
|
||||||
if (eidBuffer[frameIndex])
|
if (instancedIntegerBuffer[frameIndex])
|
||||||
eidBuffer[frameIndex]->WriteToMemory(eidData.data(), static_cast<EntityID>(eidData.size() * sizeof(EntityID)), 0, 0);
|
instancedIntegerBuffer[frameIndex]->WriteToMemory(instancedIntegerData.data(), static_cast<uint32_t>(instancedIntegerData.size() * sizeof(SHInstancedIntegerData)), 0, 0);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHBatch::Build(Handle<SHVkLogicalDevice> _device, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex)
|
void SHBatch::Build(Handle<SHVkLogicalDevice> _device, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex)
|
||||||
|
{
|
||||||
|
if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS)
|
||||||
{
|
{
|
||||||
if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS)
|
SHLOG_WARNING("[SHBatch] Attempted to update build batch buffers with an invalid frame index.");
|
||||||
{
|
return;
|
||||||
SHLOG_WARNING("[SHBatch] Attempted to update build batch buffers with an invalid frame index.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Save logical device
|
|
||||||
device = _device;
|
|
||||||
|
|
||||||
// No need to build as there are no changes
|
|
||||||
if (!isDirty[frameIndex])
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Count number of elements
|
|
||||||
size_t numTotalElements = 0;
|
|
||||||
for (const auto& subBatch : subBatches)
|
|
||||||
{
|
|
||||||
numTotalElements += subBatch.Renderables.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate CPU buffers if there are changes
|
|
||||||
if (isCPUBuffersDirty)
|
|
||||||
{
|
|
||||||
// - Draw data
|
|
||||||
drawData.reserve(subBatches.size());
|
|
||||||
drawData.clear();
|
|
||||||
// - Transform data
|
|
||||||
transformData.reserve(numTotalElements);
|
|
||||||
transformData.clear();
|
|
||||||
// - EID data
|
|
||||||
eidData.reserve(numTotalElements);
|
|
||||||
eidData.clear();
|
|
||||||
|
|
||||||
|
|
||||||
// - Material Properties Data
|
|
||||||
const Handle<SHShaderBlockInterface> SHADER_INFO = pipeline->GetPipelineLayout()->GetShaderBlockInterface
|
|
||||||
(
|
|
||||||
SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE,
|
|
||||||
SHGraphicsConstants::DescriptorSetBindings::BATCHED_PER_INST_DATA,
|
|
||||||
vk::ShaderStageFlagBits::eFragment
|
|
||||||
);
|
|
||||||
const bool EMPTY_MAT_PROPS = !SHADER_INFO;
|
|
||||||
Byte matPropTotalBytes = 0;
|
|
||||||
if (!EMPTY_MAT_PROPS)
|
|
||||||
{
|
|
||||||
singleMatPropSize = SHADER_INFO->GetBytesRequired();
|
|
||||||
singleMatPropAlignedSize = device->PadSSBOSize(static_cast<uint32_t>(singleMatPropSize));
|
|
||||||
matPropTotalBytes = numTotalElements * singleMatPropAlignedSize;
|
|
||||||
if (matPropsDataSize < matPropTotalBytes)
|
|
||||||
{
|
|
||||||
matPropsData.reset(new char[matPropTotalBytes]);
|
|
||||||
matPropsDataSize = matPropTotalBytes;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Build Sub Batches
|
|
||||||
uint32_t nextInstanceIndex = 0;
|
|
||||||
char* propsCurrPtr = matPropsData.get();
|
|
||||||
for (auto& subBatch : subBatches)
|
|
||||||
{
|
|
||||||
// Create command
|
|
||||||
drawData.emplace_back(vk::DrawIndexedIndirectCommand
|
|
||||||
{
|
|
||||||
.indexCount = subBatch.Mesh->IndexCount,
|
|
||||||
.instanceCount = static_cast<uint32_t>(subBatch.Renderables.size()),
|
|
||||||
.firstIndex = subBatch.Mesh->FirstIndex,
|
|
||||||
.vertexOffset = subBatch.Mesh->FirstVertex,
|
|
||||||
.firstInstance = nextInstanceIndex++
|
|
||||||
});
|
|
||||||
|
|
||||||
// Fill in buffers (CPU)
|
|
||||||
for (const SHRenderable* renderable : subBatch.Renderables)
|
|
||||||
{
|
|
||||||
// Transform
|
|
||||||
EntityID eid = renderable->GetEID();
|
|
||||||
auto transform = SHComponentManager::GetComponent_s<SHTransformComponent>(eid);
|
|
||||||
if (!transform)
|
|
||||||
{
|
|
||||||
SHLOG_WARNING("[SHBatch] Entity contianing a SHRenderable with no SHTransformComponent found!");
|
|
||||||
transformData.emplace_back();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
transformData.emplace_back(transform->GetTRS());
|
|
||||||
}
|
|
||||||
|
|
||||||
eidData.emplace_back(eid);
|
|
||||||
|
|
||||||
// Material Properties
|
|
||||||
if (!EMPTY_MAT_PROPS)
|
|
||||||
{
|
|
||||||
renderable->GetMaterial()->ExportProperties(propsCurrPtr);
|
|
||||||
propsCurrPtr += singleMatPropAlignedSize;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Successfully update CPU buffers
|
|
||||||
isCPUBuffersDirty = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send all buffered data to the GPU buffers
|
|
||||||
using BuffUsage = vk::BufferUsageFlagBits;
|
|
||||||
// - Draw Data
|
|
||||||
const uint32_t DRAW_DATA_BYTES = static_cast<uint32_t>(drawData.size() * sizeof(vk::DrawIndexedIndirectCommand));
|
|
||||||
SHVkUtil::EnsureBufferAndCopyHostVisibleData
|
|
||||||
(
|
|
||||||
device, drawDataBuffer[frameIndex], drawData.data(), DRAW_DATA_BYTES,
|
|
||||||
BuffUsage::eIndirectBuffer
|
|
||||||
);
|
|
||||||
// - Transform Buffer
|
|
||||||
const uint32_t TF_DATA_BYTES = static_cast<uint32_t>(transformData.size() * sizeof(SHMatrix));
|
|
||||||
SHVkUtil::EnsureBufferAndCopyHostVisibleData
|
|
||||||
(
|
|
||||||
device, transformDataBuffer[frameIndex], transformData.data(), TF_DATA_BYTES,
|
|
||||||
BuffUsage::eVertexBuffer
|
|
||||||
);
|
|
||||||
const uint32_t EID_DATA_BYTES = static_cast<uint32_t>(eidData.size() * sizeof(EntityID));
|
|
||||||
SHVkUtil::EnsureBufferAndCopyHostVisibleData
|
|
||||||
(
|
|
||||||
device, eidBuffer[frameIndex], eidData.data(), EID_DATA_BYTES,
|
|
||||||
BuffUsage::eVertexBuffer
|
|
||||||
);
|
|
||||||
// - Material Properties Buffer
|
|
||||||
rebuildMaterialBuffers(frameIndex, descPool);
|
|
||||||
|
|
||||||
// Mark this frame as no longer dirty
|
|
||||||
isDirty[frameIndex] = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
// Save logical device
|
||||||
/* SHBatch - Usage Functions */
|
device = _device;
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
void SHBatch::Draw(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex)
|
|
||||||
{
|
|
||||||
if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS)
|
|
||||||
{
|
|
||||||
SHLOG_WARNING("[SHBatch] Attempted to draw a batch with an invalid frame index.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bind all required objects before drawing
|
// No need to build as there are no changes
|
||||||
static std::array<uint32_t, 1> dynamicOffset { 0 };
|
if (!isDirty[frameIndex])
|
||||||
cmdBuffer->BindPipeline(pipeline);
|
return;
|
||||||
cmdBuffer->BindVertexBuffer(SHGraphicsConstants::VertexBufferBindings::TRANSFORM, transformDataBuffer[frameIndex], 0);
|
|
||||||
cmdBuffer->BindVertexBuffer(SHGraphicsConstants::VertexBufferBindings::EID, eidBuffer[frameIndex], 0);
|
// Count number of elements
|
||||||
if (matPropsDescSet[frameIndex])
|
size_t numTotalElements = 0;
|
||||||
|
for (const auto& subBatch : subBatches)
|
||||||
|
{
|
||||||
|
numTotalElements += subBatch.Renderables.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate CPU buffers if there are changes
|
||||||
|
if (isCPUBuffersDirty)
|
||||||
|
{
|
||||||
|
// - Draw data
|
||||||
|
drawData.reserve(subBatches.size());
|
||||||
|
drawData.clear();
|
||||||
|
// - Transform data
|
||||||
|
transformData.reserve(numTotalElements);
|
||||||
|
transformData.clear();
|
||||||
|
// - EID data
|
||||||
|
instancedIntegerData.reserve(numTotalElements);
|
||||||
|
instancedIntegerData.clear();
|
||||||
|
|
||||||
|
|
||||||
|
// - Material Properties Data
|
||||||
|
const Handle<SHShaderBlockInterface> SHADER_INFO = pipeline->GetPipelineLayout()->GetShaderBlockInterface
|
||||||
|
(
|
||||||
|
SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE,
|
||||||
|
SHGraphicsConstants::DescriptorSetBindings::BATCHED_PER_INST_DATA,
|
||||||
|
vk::ShaderStageFlagBits::eFragment
|
||||||
|
);
|
||||||
|
const bool EMPTY_MAT_PROPS = !SHADER_INFO;
|
||||||
|
Byte matPropTotalBytes = 0;
|
||||||
|
if (!EMPTY_MAT_PROPS)
|
||||||
|
{
|
||||||
|
singleMatPropSize = SHADER_INFO->GetBytesRequired();
|
||||||
|
singleMatPropAlignedSize = device->PadSSBOSize(static_cast<uint32_t>(singleMatPropSize));
|
||||||
|
matPropTotalBytes = numTotalElements * singleMatPropAlignedSize;
|
||||||
|
if (matPropsDataSize < matPropTotalBytes)
|
||||||
{
|
{
|
||||||
cmdBuffer->BindDescriptorSet
|
matPropsData.reset(new char[matPropTotalBytes]);
|
||||||
(
|
matPropsDataSize = matPropTotalBytes;
|
||||||
matPropsDescSet[frameIndex],
|
}
|
||||||
vk::PipelineBindPoint::eGraphics,
|
}
|
||||||
SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE,
|
|
||||||
dynamicOffset
|
// Build Sub Batches
|
||||||
|
uint32_t nextInstanceIndex = 0;
|
||||||
|
char* propsCurrPtr = matPropsData.get();
|
||||||
|
for (auto& subBatch : subBatches)
|
||||||
|
{
|
||||||
|
// Create command
|
||||||
|
const uint32_t CURR_INSTANCES = static_cast<uint32_t>(subBatch.Renderables.size());
|
||||||
|
drawData.emplace_back(vk::DrawIndexedIndirectCommand
|
||||||
|
{
|
||||||
|
.indexCount = subBatch.Mesh->IndexCount,
|
||||||
|
.instanceCount = CURR_INSTANCES,
|
||||||
|
.firstIndex = subBatch.Mesh->FirstIndex,
|
||||||
|
.vertexOffset = subBatch.Mesh->FirstVertex,
|
||||||
|
.firstInstance = nextInstanceIndex
|
||||||
|
});
|
||||||
|
nextInstanceIndex += CURR_INSTANCES;
|
||||||
|
|
||||||
|
// Fill in buffers (CPU)
|
||||||
|
for (auto rendId : subBatch.Renderables)
|
||||||
|
{
|
||||||
|
// Transform
|
||||||
|
auto transform = SHComponentManager::GetComponent_s<SHTransformComponent>(rendId);
|
||||||
|
if (!transform)
|
||||||
|
{
|
||||||
|
SHLOG_WARNING("[SHBatch] Entity contianing a SHRenderable with no SHTransformComponent found!");
|
||||||
|
transformData.emplace_back();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
transformData.emplace_back(transform->GetTRS());
|
||||||
|
}
|
||||||
|
|
||||||
|
const SHRenderable* renderable = SHComponentManager::GetComponent<SHRenderable>(rendId);
|
||||||
|
instancedIntegerData.emplace_back(SHInstancedIntegerData
|
||||||
|
{
|
||||||
|
rendId,
|
||||||
|
renderable->GetLightLayer()
|
||||||
|
}
|
||||||
);
|
);
|
||||||
}
|
|
||||||
cmdBuffer->DrawMultiIndirect(drawDataBuffer[frameIndex], static_cast<uint32_t>(drawData.size()));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
// Material Properties
|
||||||
/* SHBatch - Helper Functions */
|
if (!EMPTY_MAT_PROPS)
|
||||||
/*---------------------------------------------------------------------------------*/
|
{
|
||||||
void SHBatch::setAllDirtyFlags()
|
if (renderable)
|
||||||
{
|
|
||||||
for (bool& dirt : isDirty)
|
|
||||||
dirt = true;
|
|
||||||
isCPUBuffersDirty = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHBatch::rebuildMaterialBuffers(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool)
|
|
||||||
{
|
|
||||||
if (matPropsData)
|
|
||||||
{
|
|
||||||
SHVkUtil::EnsureBufferAndCopyHostVisibleData
|
|
||||||
(
|
|
||||||
device, matPropsBuffer[frameIndex], matPropsData.get(), static_cast<uint32_t>(matPropsDataSize),
|
|
||||||
vk::BufferUsageFlagBits::eStorageBuffer
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!matPropsDescSet[frameIndex])
|
|
||||||
{
|
{
|
||||||
matPropsDescSet[frameIndex] = descPool->Allocate
|
renderable->GetMaterial()->ExportProperties(propsCurrPtr);
|
||||||
(
|
|
||||||
{ SHGraphicsGlobalData::GetDescSetLayouts()[SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE] },
|
|
||||||
{ 0 }
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
std::array<Handle<SHVkBuffer>, 1> bufferList = { matPropsBuffer[frameIndex] };
|
else
|
||||||
matPropsDescSet[frameIndex]->ModifyWriteDescBuffer
|
{
|
||||||
(
|
SHLOG_WARNING("[SHBatch] Entity with a missing SHRenderable found!");
|
||||||
SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE,
|
}
|
||||||
SHGraphicsConstants::DescriptorSetBindings::BATCHED_PER_INST_DATA,
|
propsCurrPtr += singleMatPropAlignedSize;
|
||||||
bufferList,
|
}
|
||||||
0, static_cast<uint32_t>(matPropsDataSize)
|
|
||||||
);
|
|
||||||
matPropsDescSet[frameIndex]->UpdateDescriptorSetBuffer
|
|
||||||
(
|
|
||||||
SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE,
|
|
||||||
SHGraphicsConstants::DescriptorSetBindings::BATCHED_PER_INST_DATA
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Successfully update CPU buffers
|
||||||
|
isCPUBuffersDirty = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Send all buffered data to the GPU buffers
|
||||||
|
using BuffUsage = vk::BufferUsageFlagBits;
|
||||||
|
// - Draw Data
|
||||||
|
const uint32_t DRAW_DATA_BYTES = static_cast<uint32_t>(drawData.size() * sizeof(vk::DrawIndexedIndirectCommand));
|
||||||
|
SHVkUtil::EnsureBufferAndCopyHostVisibleData
|
||||||
|
(
|
||||||
|
device, drawDataBuffer[frameIndex], drawData.data(), DRAW_DATA_BYTES,
|
||||||
|
BuffUsage::eIndirectBuffer
|
||||||
|
);
|
||||||
|
// - Transform Buffer
|
||||||
|
const uint32_t TF_DATA_BYTES = static_cast<uint32_t>(transformData.size() * sizeof(SHMatrix));
|
||||||
|
SHVkUtil::EnsureBufferAndCopyHostVisibleData
|
||||||
|
(
|
||||||
|
device, transformDataBuffer[frameIndex], transformData.data(), TF_DATA_BYTES,
|
||||||
|
BuffUsage::eVertexBuffer
|
||||||
|
);
|
||||||
|
const uint32_t EID_DATA_BYTES = static_cast<uint32_t>(instancedIntegerData.size() * sizeof(SHInstancedIntegerData));
|
||||||
|
SHVkUtil::EnsureBufferAndCopyHostVisibleData
|
||||||
|
(
|
||||||
|
device, instancedIntegerBuffer[frameIndex], instancedIntegerData.data(), EID_DATA_BYTES,
|
||||||
|
BuffUsage::eVertexBuffer
|
||||||
|
);
|
||||||
|
// - Material Properties Buffer
|
||||||
|
rebuildMaterialBuffers(frameIndex, descPool);
|
||||||
|
|
||||||
|
// Mark this frame as no longer dirty
|
||||||
|
isDirty[frameIndex] = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* SHBatch - Usage Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
void SHBatch::Draw(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex)
|
||||||
|
{
|
||||||
|
if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS)
|
||||||
|
{
|
||||||
|
SHLOG_WARNING("[SHBatch] Attempted to draw a batch with an invalid frame index.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bind all required objects before drawing
|
||||||
|
static std::array<uint32_t, 1> dynamicOffset{ 0 };
|
||||||
|
cmdBuffer->BindPipeline(pipeline);
|
||||||
|
cmdBuffer->BindVertexBuffer(SHGraphicsConstants::VertexBufferBindings::TRANSFORM, transformDataBuffer[frameIndex], 0);
|
||||||
|
cmdBuffer->BindVertexBuffer(SHGraphicsConstants::VertexBufferBindings::INTEGER_DATA, instancedIntegerBuffer[frameIndex], 0);
|
||||||
|
if (matPropsDescSet[frameIndex])
|
||||||
|
{
|
||||||
|
cmdBuffer->BindDescriptorSet
|
||||||
|
(
|
||||||
|
matPropsDescSet[frameIndex],
|
||||||
|
SH_PIPELINE_TYPE::GRAPHICS,
|
||||||
|
SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE,
|
||||||
|
dynamicOffset
|
||||||
|
);
|
||||||
|
}
|
||||||
|
cmdBuffer->DrawMultiIndirect(drawDataBuffer[frameIndex], static_cast<uint32_t>(drawData.size()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* SHBatch - Helper Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
void SHBatch::setAllDirtyFlags()
|
||||||
|
{
|
||||||
|
for (bool& dirt : isDirty)
|
||||||
|
dirt = true;
|
||||||
|
isCPUBuffersDirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHBatch::rebuildMaterialBuffers(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool)
|
||||||
|
{
|
||||||
|
if (matPropsData)
|
||||||
|
{
|
||||||
|
SHVkUtil::EnsureBufferAndCopyHostVisibleData
|
||||||
|
(
|
||||||
|
device, matPropsBuffer[frameIndex], matPropsData.get(), static_cast<uint32_t>(matPropsDataSize),
|
||||||
|
vk::BufferUsageFlagBits::eStorageBuffer
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!matPropsDescSet[frameIndex])
|
||||||
|
{
|
||||||
|
matPropsDescSet[frameIndex] = descPool->Allocate
|
||||||
|
(
|
||||||
|
{ SHGraphicsGlobalData::GetDescSetLayouts()[SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE] },
|
||||||
|
{ 0 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
std::array<Handle<SHVkBuffer>, 1> bufferList = { matPropsBuffer[frameIndex] };
|
||||||
|
matPropsDescSet[frameIndex]->ModifyWriteDescBuffer
|
||||||
|
(
|
||||||
|
SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE,
|
||||||
|
SHGraphicsConstants::DescriptorSetBindings::BATCHED_PER_INST_DATA,
|
||||||
|
bufferList,
|
||||||
|
0, static_cast<uint32_t>(matPropsDataSize)
|
||||||
|
);
|
||||||
|
matPropsDescSet[frameIndex]->UpdateDescriptorSetBuffer
|
||||||
|
(
|
||||||
|
SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE,
|
||||||
|
SHGraphicsConstants::DescriptorSetBindings::BATCHED_PER_INST_DATA
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ of DigiPen Institute of Technology is prohibited.
|
||||||
#include "Math/SHMatrix.h"
|
#include "Math/SHMatrix.h"
|
||||||
#include "Graphics/MiddleEnd/Interface/SHGraphicsConstants.h"
|
#include "Graphics/MiddleEnd/Interface/SHGraphicsConstants.h"
|
||||||
#include "ECS_Base/SHECSMacros.h"
|
#include "ECS_Base/SHECSMacros.h"
|
||||||
|
#include "Graphics/MiddleEnd/Interface/SHInstancedIntegerData.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
@ -55,7 +56,7 @@ namespace SHADE
|
||||||
/* Data Members */
|
/* Data Members */
|
||||||
/*-----------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------*/
|
||||||
Handle<SHMesh> Mesh;
|
Handle<SHMesh> Mesh;
|
||||||
std::unordered_set<const SHRenderable*> Renderables;
|
std::unordered_set<EntityID> Renderables;
|
||||||
};
|
};
|
||||||
/***********************************************************************************/
|
/***********************************************************************************/
|
||||||
/*!
|
/*!
|
||||||
|
@ -79,7 +80,7 @@ namespace SHADE
|
||||||
void Clear();
|
void Clear();
|
||||||
void UpdateMaterialBuffer(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool);
|
void UpdateMaterialBuffer(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool);
|
||||||
void UpdateTransformBuffer(uint32_t frameIndex);
|
void UpdateTransformBuffer(uint32_t frameIndex);
|
||||||
void UpdateEIDBuffer(uint32_t frameIndex);
|
void UpdateInstancedIntegerBuffer(uint32_t frameIndex);
|
||||||
void Build(Handle<SHVkLogicalDevice> device, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) ;
|
void Build(Handle<SHVkLogicalDevice> device, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) ;
|
||||||
void Draw(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex);
|
void Draw(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex);
|
||||||
|
|
||||||
|
@ -111,7 +112,7 @@ namespace SHADE
|
||||||
// CPU Buffers
|
// CPU Buffers
|
||||||
std::vector<vk::DrawIndexedIndirectCommand> drawData;
|
std::vector<vk::DrawIndexedIndirectCommand> drawData;
|
||||||
std::vector<SHMatrix> transformData;
|
std::vector<SHMatrix> transformData;
|
||||||
std::vector<EntityID> eidData;
|
std::vector<SHInstancedIntegerData> instancedIntegerData;
|
||||||
std::unique_ptr<char> matPropsData;
|
std::unique_ptr<char> matPropsData;
|
||||||
Byte matPropsDataSize = 0;
|
Byte matPropsDataSize = 0;
|
||||||
Byte singleMatPropAlignedSize = 0;
|
Byte singleMatPropAlignedSize = 0;
|
||||||
|
@ -120,7 +121,7 @@ namespace SHADE
|
||||||
// GPU Buffers
|
// GPU Buffers
|
||||||
TripleBuffer drawDataBuffer;
|
TripleBuffer drawDataBuffer;
|
||||||
TripleBuffer transformDataBuffer;
|
TripleBuffer transformDataBuffer;
|
||||||
TripleBuffer eidBuffer;
|
TripleBuffer instancedIntegerBuffer;
|
||||||
TripleBuffer matPropsBuffer;
|
TripleBuffer matPropsBuffer;
|
||||||
TripleDescSet matPropsDescSet;
|
TripleDescSet matPropsDescSet;
|
||||||
|
|
||||||
|
|
|
@ -20,91 +20,91 @@ of DigiPen Institute of Technology is prohibited.
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/* Constructor/Destructors */
|
/* Constructor/Destructors */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
SHSuperBatch::SHSuperBatch(Handle<SHSubpass> sp)
|
SHSuperBatch::SHSuperBatch(Handle<SHSubpass> sp)
|
||||||
: subpass { sp }
|
: subpass{ sp }
|
||||||
{}
|
{}
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/* Usage Functions */
|
/* Usage Functions */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
void SHSuperBatch::Add(const SHRenderable* renderable) noexcept
|
void SHSuperBatch::Add(const SHRenderable* renderable) noexcept
|
||||||
|
{
|
||||||
|
const Handle<SHVkPipeline> PIPELINE = renderable->GetMaterial()->GetBaseMaterial()->GetPipeline();
|
||||||
|
|
||||||
|
// Check if we have a batch with the same pipeline first
|
||||||
|
auto batch = std::find_if(batches.begin(), batches.end(), [&](const SHBatch& batch)
|
||||||
|
{
|
||||||
|
return batch.GetPipeline() == PIPELINE;
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// Create one if not found
|
||||||
|
if (batch == batches.end())
|
||||||
{
|
{
|
||||||
const Handle<SHVkPipeline> PIPELINE = renderable->GetMaterial()->GetBaseMaterial()->GetPipeline();
|
batches.emplace_back(PIPELINE);
|
||||||
|
batch = batches.end() - 1;
|
||||||
// Check if we have a batch with the same pipeline first
|
|
||||||
auto batch = std::find_if(batches.begin(), batches.end(), [&](const SHBatch& batch)
|
|
||||||
{
|
|
||||||
return batch.GetPipeline() == PIPELINE;
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
// Create one if not found
|
|
||||||
if (batch == batches.end())
|
|
||||||
{
|
|
||||||
batches.emplace_back(PIPELINE);
|
|
||||||
batch = batches.end() - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add renderable in
|
|
||||||
batch->Add(renderable);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHSuperBatch::Remove(const SHRenderable* renderable) noexcept
|
// Add renderable in
|
||||||
|
batch->Add(renderable);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHSuperBatch::Remove(const SHRenderable* renderable) noexcept
|
||||||
|
{
|
||||||
|
const Handle<SHVkPipeline> PIPELINE = renderable->GetMaterial()->GetBaseMaterial()->GetPipeline();
|
||||||
|
|
||||||
|
// Check if we have a Batch with the same pipeline yet
|
||||||
|
auto batch = std::find_if(batches.begin(), batches.end(), [&](const SHBatch& batch)
|
||||||
|
{
|
||||||
|
return batch.GetPipeline() == PIPELINE;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Attempt to remove if it exists
|
||||||
|
if (batch == batches.end())
|
||||||
|
return;
|
||||||
|
|
||||||
|
batch->Remove(renderable);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHSuperBatch::Clear() noexcept
|
||||||
|
{
|
||||||
|
for (auto& batch : batches)
|
||||||
{
|
{
|
||||||
const Handle<SHVkPipeline> PIPELINE = renderable->GetMaterial()->GetBaseMaterial()->GetPipeline();
|
batch.Clear();
|
||||||
|
|
||||||
// Check if we have a Batch with the same pipeline yet
|
|
||||||
auto batch = std::find_if(batches.begin(), batches.end(), [&](const SHBatch& batch)
|
|
||||||
{
|
|
||||||
return batch.GetPipeline() == PIPELINE;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Attempt to remove if it exists
|
|
||||||
if (batch == batches.end())
|
|
||||||
return;
|
|
||||||
|
|
||||||
batch->Remove(renderable);
|
|
||||||
}
|
}
|
||||||
|
batches.clear();
|
||||||
|
}
|
||||||
|
|
||||||
void SHSuperBatch::Clear() noexcept
|
void SHSuperBatch::UpdateBuffers(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool)
|
||||||
|
{
|
||||||
|
for (auto& batch : batches)
|
||||||
{
|
{
|
||||||
for (auto& batch : batches)
|
batch.UpdateMaterialBuffer(frameIndex, descPool);
|
||||||
{
|
batch.UpdateTransformBuffer(frameIndex);
|
||||||
batch.Clear();
|
batch.UpdateInstancedIntegerBuffer(frameIndex);
|
||||||
}
|
|
||||||
batches.clear();
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void SHSuperBatch::UpdateBuffers(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool)
|
void SHSuperBatch::Build(Handle<SHVkLogicalDevice> device, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) noexcept
|
||||||
|
{
|
||||||
|
// Build all batches
|
||||||
|
for (auto& batch : batches)
|
||||||
{
|
{
|
||||||
for (auto& batch : batches)
|
batch.Build(device, descPool, frameIndex);
|
||||||
{
|
|
||||||
batch.UpdateMaterialBuffer(frameIndex, descPool);
|
|
||||||
batch.UpdateTransformBuffer(frameIndex);
|
|
||||||
batch.UpdateEIDBuffer(frameIndex);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void SHSuperBatch::Build(Handle<SHVkLogicalDevice> device, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) noexcept
|
void SHSuperBatch::Draw(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept
|
||||||
|
{
|
||||||
|
// Build all batches
|
||||||
|
for (auto& batch : batches)
|
||||||
{
|
{
|
||||||
// Build all batches
|
batch.Draw(cmdBuffer, frameIndex);
|
||||||
for (auto& batch : batches)
|
|
||||||
{
|
|
||||||
batch.Build(device, descPool, frameIndex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHSuperBatch::Draw(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept
|
|
||||||
{
|
|
||||||
// Build all batches
|
|
||||||
for (auto& batch : batches)
|
|
||||||
{
|
|
||||||
batch.Draw(cmdBuffer, frameIndex);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
#include "Graphics/Pipeline/SHPipelineState.h"
|
#include "Graphics/Pipeline/SHPipelineState.h"
|
||||||
#include "Graphics/Pipeline/SHVkPipelineLayout.h"
|
#include "Graphics/Pipeline/SHVkPipelineLayout.h"
|
||||||
#include "Graphics/Descriptors/SHVkDescriptorSetLayout.h"
|
#include "Graphics/Descriptors/SHVkDescriptorSetLayout.h"
|
||||||
|
#include "Graphics/MiddleEnd/Lights/SHLightData.h"
|
||||||
|
#include "Tools/SHUtilities.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
@ -45,16 +47,35 @@ namespace SHADE
|
||||||
// For global data (generic data and textures)
|
// For global data (generic data and textures)
|
||||||
Handle<SHVkDescriptorSetLayout> staticGlobalLayout = logicalDevice->CreateDescriptorSetLayout(SHGraphicsConstants::DescriptorSetIndex::STATIC_GLOBALS,{ genericDataBinding, texturesBinding });
|
Handle<SHVkDescriptorSetLayout> staticGlobalLayout = logicalDevice->CreateDescriptorSetLayout(SHGraphicsConstants::DescriptorSetIndex::STATIC_GLOBALS,{ genericDataBinding, texturesBinding });
|
||||||
|
|
||||||
SHVkDescriptorSetLayout::Binding lightBinding
|
std::vector<SHVkDescriptorSetLayout::Binding> lightBindings{};
|
||||||
|
for (uint32_t i = 0; i < SHUtilities::ToUnderlying(SH_LIGHT_TYPE::NUM_TYPES); ++i)
|
||||||
{
|
{
|
||||||
.Type = vk::DescriptorType::eStorageBufferDynamic,
|
lightBindings.push_back (SHVkDescriptorSetLayout::Binding
|
||||||
.Stage = vk::ShaderStageFlagBits::eFragment,
|
{
|
||||||
.BindPoint = SHGraphicsConstants::DescriptorSetBindings::LIGHTS_DATA,
|
.Type = vk::DescriptorType::eStorageBufferDynamic,
|
||||||
.DescriptorCount = 1,
|
.Stage = vk::ShaderStageFlagBits::eFragment,
|
||||||
};
|
.BindPoint = i,
|
||||||
|
.DescriptorCount = 1,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
//SHVkDescriptorSetLayout::Binding pointLightBinding
|
||||||
|
//{
|
||||||
|
// .Type = vk::DescriptorType::eStorageBufferDynamic,
|
||||||
|
// .Stage = vk::ShaderStageFlagBits::eFragment,
|
||||||
|
// .BindPoint = SHGraphicsConstants::DescriptorSetBindings::POINT_LIGHT_DATA,
|
||||||
|
// .DescriptorCount = 1,
|
||||||
|
//};
|
||||||
|
|
||||||
|
//SHVkDescriptorSetLayout::Binding spotLightBinding
|
||||||
|
//{
|
||||||
|
// .Type = vk::DescriptorType::eStorageBufferDynamic,
|
||||||
|
// .Stage = vk::ShaderStageFlagBits::eFragment,
|
||||||
|
// .BindPoint = SHGraphicsConstants::DescriptorSetBindings::SPOT_LIGHT_DATA,
|
||||||
|
// .DescriptorCount = 1,
|
||||||
|
//};
|
||||||
|
|
||||||
// For Dynamic global data (lights)
|
// For Dynamic global data (lights)
|
||||||
Handle<SHVkDescriptorSetLayout> dynamicGlobalLayout = logicalDevice->CreateDescriptorSetLayout(SHGraphicsConstants::DescriptorSetIndex::DYNAMIC_GLOBALS, { lightBinding });
|
Handle<SHVkDescriptorSetLayout> dynamicGlobalLayout = logicalDevice->CreateDescriptorSetLayout(SHGraphicsConstants::DescriptorSetIndex::DYNAMIC_GLOBALS, lightBindings);
|
||||||
|
|
||||||
SHVkDescriptorSetLayout::Binding cameraDataBinding
|
SHVkDescriptorSetLayout::Binding cameraDataBinding
|
||||||
{
|
{
|
||||||
|
@ -94,7 +115,7 @@ namespace SHADE
|
||||||
defaultVertexInputState.AddBinding(false, false, { SHVertexAttribute(SHAttribFormat::FLOAT_3D) }); // Normals at binding 2
|
defaultVertexInputState.AddBinding(false, false, { SHVertexAttribute(SHAttribFormat::FLOAT_3D) }); // Normals at binding 2
|
||||||
defaultVertexInputState.AddBinding(false, false, { SHVertexAttribute(SHAttribFormat::FLOAT_3D) }); // Tangents at binding 3
|
defaultVertexInputState.AddBinding(false, false, { SHVertexAttribute(SHAttribFormat::FLOAT_3D) }); // Tangents at binding 3
|
||||||
defaultVertexInputState.AddBinding(true, true, { SHVertexAttribute(SHAttribFormat::MAT_4D) }); // Transform at binding 4 - 7 (4 slots)
|
defaultVertexInputState.AddBinding(true, true, { SHVertexAttribute(SHAttribFormat::MAT_4D) }); // Transform at binding 4 - 7 (4 slots)
|
||||||
defaultVertexInputState.AddBinding(true, true, { SHVertexAttribute(SHAttribFormat::UINT32_1D) }); // EID at binding 8
|
defaultVertexInputState.AddBinding(true, true, { SHVertexAttribute(SHAttribFormat::UINT32_2D) }); // Instanced integer data at index 8
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHGraphicsGlobalData::Init(Handle<SHVkLogicalDevice> logicalDevice) noexcept
|
void SHGraphicsGlobalData::Init(Handle<SHVkLogicalDevice> logicalDevice) noexcept
|
||||||
|
|
|
@ -63,6 +63,14 @@ namespace SHADE
|
||||||
*/
|
*/
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
static constexpr uint32_t PER_INSTANCE = 3;
|
static constexpr uint32_t PER_INSTANCE = 3;
|
||||||
|
/***************************************************************************/
|
||||||
|
/*!
|
||||||
|
\brief
|
||||||
|
DescriptorSet Index for render graph resources.
|
||||||
|
*/
|
||||||
|
/***************************************************************************/
|
||||||
|
static constexpr uint32_t RENDERGRAPH_RESOURCE = 4;
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -86,14 +94,32 @@ namespace SHADE
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
static constexpr uint32_t IMAGE_AND_SAMPLERS_DATA = 1;
|
static constexpr uint32_t IMAGE_AND_SAMPLERS_DATA = 1;
|
||||||
|
|
||||||
/***************************************************************************/
|
///***************************************************************************/
|
||||||
/*!
|
///*!
|
||||||
\brief
|
// \brief
|
||||||
DescriptorSet binding for lights.
|
// DescriptorSet binding for directional lights.
|
||||||
|
|
||||||
*/
|
//*/
|
||||||
/***************************************************************************/
|
///***************************************************************************/
|
||||||
static constexpr uint32_t LIGHTS_DATA = 0;
|
//static constexpr uint32_t DIRECTIONAL_LIGHT_DATA = 0;
|
||||||
|
|
||||||
|
///***************************************************************************/
|
||||||
|
///*!
|
||||||
|
// \brief
|
||||||
|
// DescriptorSet binding for directional lights.
|
||||||
|
|
||||||
|
//*/
|
||||||
|
///***************************************************************************/
|
||||||
|
//static constexpr uint32_t POINT_LIGHT_DATA = 1;
|
||||||
|
|
||||||
|
///***************************************************************************/
|
||||||
|
///*!
|
||||||
|
// \brief
|
||||||
|
// DescriptorSet binding for directional lights.
|
||||||
|
|
||||||
|
//*/
|
||||||
|
///***************************************************************************/
|
||||||
|
//static constexpr uint32_t SPOT_LIGHT_DATA = 2;
|
||||||
|
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
/*!
|
/*!
|
||||||
|
@ -156,7 +182,7 @@ namespace SHADE
|
||||||
Vertex buffer bindings for the eid buffer.
|
Vertex buffer bindings for the eid buffer.
|
||||||
*/
|
*/
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
static constexpr uint32_t EID = 5;
|
static constexpr uint32_t INTEGER_DATA = 5;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,7 @@ of DigiPen Institute of Technology is prohibited.
|
||||||
#include "Graphics/Images/SHVkSampler.h"
|
#include "Graphics/Images/SHVkSampler.h"
|
||||||
#include "Assets/Asset Types/SHTextureAsset.h"
|
#include "Assets/Asset Types/SHTextureAsset.h"
|
||||||
#include "Graphics/MiddleEnd/Interface/SHMousePickSystem.h"
|
#include "Graphics/MiddleEnd/Interface/SHMousePickSystem.h"
|
||||||
|
#include "Graphics/MiddleEnd/Lights/SHLightingSubSystem.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
@ -115,6 +116,26 @@ namespace SHADE
|
||||||
graphicsCmdPool = device->CreateCommandPool(SH_QUEUE_FAMILY_ARRAY_INDEX::GRAPHICS, SH_CMD_POOL_RESET::POOL_BASED, true);
|
graphicsCmdPool = device->CreateCommandPool(SH_QUEUE_FAMILY_ARRAY_INDEX::GRAPHICS, SH_CMD_POOL_RESET::POOL_BASED, true);
|
||||||
transferCmdBuffer = graphicsCmdPool->RequestCommandBuffer(SH_CMD_BUFFER_TYPE::PRIMARY);
|
transferCmdBuffer = graphicsCmdPool->RequestCommandBuffer(SH_CMD_BUFFER_TYPE::PRIMARY);
|
||||||
graphicsTexCmdBuffer = graphicsCmdPool->RequestCommandBuffer(SH_CMD_BUFFER_TYPE::PRIMARY);
|
graphicsTexCmdBuffer = graphicsCmdPool->RequestCommandBuffer(SH_CMD_BUFFER_TYPE::PRIMARY);
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: This is VERY temporarily here until a more solid resource management system is implemented
|
||||||
|
shaderSourceLibrary.Init("../../TempShaderFolder/");
|
||||||
|
|
||||||
|
shaderSourceLibrary.LoadShader(0, "TestCubeVs.glsl", SH_SHADER_TYPE::VERTEX, true);
|
||||||
|
shaderSourceLibrary.LoadShader(1, "TestCubeFs.glsl", SH_SHADER_TYPE::FRAGMENT, true);
|
||||||
|
|
||||||
|
shaderSourceLibrary.LoadShader(2, "KirschCs.glsl", SH_SHADER_TYPE::COMPUTE, true);
|
||||||
|
shaderSourceLibrary.LoadShader(3, "PureCopyCs.glsl", SH_SHADER_TYPE::COMPUTE, true);
|
||||||
|
|
||||||
|
shaderModuleLibrary.ImportFromSourceLibrary(device, shaderSourceLibrary);
|
||||||
|
auto cubeVS = shaderModuleLibrary.GetShaderModule("TestCubeVs.glsl");
|
||||||
|
auto cubeFS = shaderModuleLibrary.GetShaderModule("TestCubeFs.glsl");
|
||||||
|
auto greyscale = shaderModuleLibrary.GetShaderModule("KirschCs.glsl");
|
||||||
|
auto pureCopy = shaderModuleLibrary.GetShaderModule("PureCopyCs.glsl");
|
||||||
|
cubeVS->Reflect();
|
||||||
|
cubeFS->Reflect();
|
||||||
|
greyscale->Reflect();
|
||||||
|
pureCopy->Reflect();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHGraphicsSystem::InitSceneRenderGraph(void) noexcept
|
void SHGraphicsSystem::InitSceneRenderGraph(void) noexcept
|
||||||
|
@ -130,6 +151,7 @@ namespace SHADE
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
auto windowDims = window->GetWindowSize();
|
auto windowDims = window->GetWindowSize();
|
||||||
|
|
||||||
|
auto cameraSystem = SHSystemManager::GetSystem<SHCameraSystem>();
|
||||||
|
|
||||||
// Set Up Cameras
|
// Set Up Cameras
|
||||||
screenCamera = resourceManager.Create<SHCamera>();
|
screenCamera = resourceManager.Create<SHCamera>();
|
||||||
|
@ -154,21 +176,32 @@ namespace SHADE
|
||||||
|
|
||||||
// Initialize world render graph
|
// Initialize world render graph
|
||||||
worldRenderGraph->Init(device, swapchain);
|
worldRenderGraph->Init(device, swapchain);
|
||||||
worldRenderGraph->AddResource("Scene", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT }, windowDims.first, windowDims.second);
|
worldRenderGraph->AddResource("Scene Pre-Process", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second);
|
||||||
worldRenderGraph->AddResource("Depth Buffer", { SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL }, windowDims.first, windowDims.second, vk::Format::eD32SfloatS8Uint);
|
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("Entity ID", { SH_ATT_DESC_TYPE_FLAGS::COLOR }, windowDims.first, windowDims.second, vk::Format::eR32Uint, 1, vk::ImageUsageFlagBits::eTransferSrc);
|
worldRenderGraph->AddResource("Depth Buffer", { SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL }, windowDims.first, windowDims.second, vk::Format::eD32SfloatS8Uint);
|
||||||
|
worldRenderGraph->AddResource("Entity ID", { SH_ATT_DESC_TYPE_FLAGS::COLOR }, windowDims.first, windowDims.second, vk::Format::eR32Uint, 1, vk::ImageUsageFlagBits::eTransferSrc);
|
||||||
|
worldRenderGraph->AddResource("Light Layer Indices", { SH_ATT_DESC_TYPE_FLAGS::COLOR }, windowDims.first, windowDims.second, vk::Format::eR32Uint, 1, vk::ImageUsageFlagBits::eTransferSrc);
|
||||||
|
|
||||||
auto node = worldRenderGraph->AddNode("G-Buffer", { "Entity ID", "Depth Buffer", "Scene"}, {}); // no predecessors
|
auto gBufferNode = worldRenderGraph->AddNode("G-Buffer", { "Light Layer Indices", "Entity ID", "Depth Buffer", "Scene", "Scene Pre-Process"}, {}); // no predecessors
|
||||||
|
auto gBufferSubpass = gBufferNode->AddSubpass("G-Buffer Write");
|
||||||
|
gBufferSubpass->AddColorOutput("Scene Pre-Process");
|
||||||
|
gBufferSubpass->AddColorOutput("Entity ID");
|
||||||
|
gBufferSubpass->AddColorOutput("Light Layer Indices");
|
||||||
|
gBufferSubpass->AddDepthOutput("Depth Buffer", SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL);
|
||||||
|
|
||||||
//First subpass to write to G-Buffer
|
//// kirsch
|
||||||
auto gBufferWriteSubpass = node->AddSubpass("G-Buffer Write");
|
//auto kirschShader = shaderModuleLibrary.GetShaderModule("KirschCs.glsl");
|
||||||
gBufferWriteSubpass->AddColorOutput("Scene");
|
//gBufferNode->AddNodeCompute(kirschShader, { "Scene Pre-Process", "Scene" });
|
||||||
gBufferWriteSubpass->AddColorOutput("Entity ID");
|
|
||||||
gBufferWriteSubpass->AddDepthOutput("Depth Buffer", SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL);
|
// copy
|
||||||
|
auto pureCopyShader = shaderModuleLibrary.GetShaderModule("PureCopyCs.glsl");
|
||||||
|
gBufferNode->AddNodeCompute(pureCopyShader, { "Scene Pre-Process", "Scene" });
|
||||||
|
|
||||||
|
|
||||||
|
auto dummyNode = worldRenderGraph->AddNode("Dummy Pass", { "Scene" }, {"G-Buffer"}); // no predecessors
|
||||||
|
auto dummySubpass = dummyNode->AddSubpass("Dummy Subpass");
|
||||||
|
dummySubpass->AddInput("Scene");
|
||||||
|
|
||||||
// We do this to just transition our scene layout to shader read
|
|
||||||
auto sceneLayoutTransitionSubpass = node->AddSubpass("Scene Layout Transition");
|
|
||||||
sceneLayoutTransitionSubpass->AddInput("Scene");
|
|
||||||
|
|
||||||
// Generate world render graph
|
// Generate world render graph
|
||||||
worldRenderGraph->Generate();
|
worldRenderGraph->Generate();
|
||||||
|
@ -177,20 +210,13 @@ namespace SHADE
|
||||||
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);
|
||||||
|
|
||||||
|
worldRenderer->SetCameraDirector(cameraSystem->CreateDirector());
|
||||||
|
|
||||||
// TODO: This is VERY temporarily here until a more solid resource management system is implemented
|
|
||||||
shaderSourceLibrary.Init("../../TempShaderFolder/");
|
|
||||||
|
|
||||||
shaderSourceLibrary.LoadShader(0, "TestCubeVs.glsl", SH_SHADER_TYPE::VERTEX, true);
|
|
||||||
shaderSourceLibrary.LoadShader(1, "TestCubeFs.glsl", SH_SHADER_TYPE::FRAGMENT, true);
|
|
||||||
|
|
||||||
shaderModuleLibrary.ImportFromSourceLibrary(device, shaderSourceLibrary);
|
|
||||||
auto cubeVS = shaderModuleLibrary.GetShaderModule("TestCubeVs.glsl");
|
auto cubeVS = shaderModuleLibrary.GetShaderModule("TestCubeVs.glsl");
|
||||||
auto cubeFS = shaderModuleLibrary.GetShaderModule("TestCubeFs.glsl");
|
auto cubeFS = shaderModuleLibrary.GetShaderModule("TestCubeFs.glsl");
|
||||||
cubeVS->Reflect();
|
|
||||||
cubeFS->Reflect();
|
|
||||||
|
|
||||||
defaultMaterial = AddMaterial(cubeVS, cubeFS, gBufferWriteSubpass);
|
defaultMaterial = AddMaterial(cubeVS, cubeFS, gBufferSubpass);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHGraphicsSystem::InitMiddleEnd(void) noexcept
|
void SHGraphicsSystem::InitMiddleEnd(void) noexcept
|
||||||
|
@ -220,11 +246,15 @@ namespace SHADE
|
||||||
for (uint32_t i = 0; i < swapchain->GetNumImages(); ++i)
|
for (uint32_t i = 0; i < swapchain->GetNumImages(); ++i)
|
||||||
cmdPools.push_back(renderContext.GetFrameData(i).cmdPoolHdls[0]);
|
cmdPools.push_back(renderContext.GetFrameData(i).cmdPoolHdls[0]);
|
||||||
|
|
||||||
|
// Mouse picking system for the editor (Will still run with editor disabled)
|
||||||
mousePickSystem->Init(device, cmdPools, worldRenderGraph->GetRenderGraphResource("Entity ID"));
|
mousePickSystem->Init(device, cmdPools, worldRenderGraph->GetRenderGraphResource("Entity ID"));
|
||||||
|
|
||||||
// Register the post offscreen render to the system
|
// Register the post offscreen render to the system
|
||||||
postOffscreenRender = resourceManager.Create<SHPostOffscreenRenderSystem>();
|
postOffscreenRender = resourceManager.Create<SHPostOffscreenRenderSystem>();
|
||||||
postOffscreenRender->Init(device, worldRenderGraph->GetRenderGraphResource("Scene"), descPool);
|
postOffscreenRender->Init(device, worldRenderGraph->GetRenderGraphResource("Scene"), descPool);
|
||||||
|
|
||||||
|
lightingSubSystem = resourceManager.Create<SHLightingSubSystem>();
|
||||||
|
lightingSubSystem->Init(device, descPool);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SHEDITOR
|
#ifdef SHEDITOR
|
||||||
|
@ -323,21 +353,7 @@ 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)
|
|
||||||
{
|
|
||||||
worldRenderer->SetViewProjectionMatrix(SHMatrix::Transpose(cameraSystem->GetEditorCamera()->GetProjMatrix() * cameraSystem->GetEditorCamera()->GetViewMatrix()));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// main camera
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
// main camera
|
|
||||||
#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)
|
||||||
|
@ -356,11 +372,13 @@ namespace SHADE
|
||||||
// Begin recording the command buffer
|
// Begin recording the command buffer
|
||||||
currentCmdBuffer->BeginRecording();
|
currentCmdBuffer->BeginRecording();
|
||||||
|
|
||||||
|
// set viewport and scissor
|
||||||
uint32_t w = static_cast<uint32_t>(viewports[vpIndex]->GetWidth());
|
uint32_t w = static_cast<uint32_t>(viewports[vpIndex]->GetWidth());
|
||||||
uint32_t h = static_cast<uint32_t>(viewports[vpIndex]->GetHeight());
|
uint32_t h = static_cast<uint32_t>(viewports[vpIndex]->GetHeight());
|
||||||
currentCmdBuffer->SetViewportScissor (static_cast<float>(w), static_cast<float>(h), w, h);
|
currentCmdBuffer->SetViewportScissor (static_cast<float>(w), static_cast<float>(h), w, h);
|
||||||
|
|
||||||
currentCmdBuffer->ForceSetPipelineLayout(SHGraphicsGlobalData::GetDummyPipelineLayout());
|
// Force set the pipeline layout
|
||||||
|
currentCmdBuffer->ForceSetPipelineLayout(SHGraphicsGlobalData::GetDummyPipelineLayout(), SH_PIPELINE_TYPE::GRAPHICS);
|
||||||
|
|
||||||
// Bind all the buffers required for meshes
|
// Bind all the buffers required for meshes
|
||||||
for (auto& [buffer, bindingPoint] : MESH_DATA)
|
for (auto& [buffer, bindingPoint] : MESH_DATA)
|
||||||
|
@ -371,6 +389,8 @@ namespace SHADE
|
||||||
currentCmdBuffer->BindIndexBuffer(buffer, 0);
|
currentCmdBuffer->BindIndexBuffer(buffer, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Bind the descriptor set for lights
|
||||||
|
lightingSubSystem->Run(currentCmdBuffer, frameIndex);
|
||||||
|
|
||||||
// Bind textures
|
// Bind textures
|
||||||
auto textureDescSet = texLibrary.GetTextureDescriptorSetGroup();
|
auto textureDescSet = texLibrary.GetTextureDescriptorSetGroup();
|
||||||
|
@ -380,16 +400,31 @@ namespace SHADE
|
||||||
currentCmdBuffer->BindDescriptorSet
|
currentCmdBuffer->BindDescriptorSet
|
||||||
(
|
(
|
||||||
textureDescSet,
|
textureDescSet,
|
||||||
vk::PipelineBindPoint::eGraphics,
|
SH_PIPELINE_TYPE::GRAPHICS,
|
||||||
0,
|
0,
|
||||||
texDynamicOffset
|
texDynamicOffset
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// bind camera data
|
// bind camera data
|
||||||
renderers[renIndex]->UpdateDataAndBind(currentCmdBuffer, frameIndex);
|
//renderers[renIndex]->UpdateDataAndBind(currentCmdBuffer, frameIndex);
|
||||||
|
|
||||||
// Draw first
|
#ifdef SHEDITOR
|
||||||
|
if (renderers[renIndex] == worldRenderer)
|
||||||
|
{
|
||||||
|
auto editorSystem = SHSystemManager::GetSystem<SHEditor>();
|
||||||
|
if (editorSystem->editorState != SHEditor::State::PLAY)
|
||||||
|
worldRenderer->UpdateDataAndBind(currentCmdBuffer, frameIndex, SHMatrix::Transpose(cameraSystem->GetEditorCamera()->GetProjMatrix() * cameraSystem->GetEditorCamera()->GetViewMatrix()));
|
||||||
|
else
|
||||||
|
renderers[renIndex]->UpdateDataAndBind(currentCmdBuffer, frameIndex);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
renderers[renIndex]->UpdateDataAndBind(currentCmdBuffer, frameIndex);
|
||||||
|
#else
|
||||||
|
renderers[renIndex]->UpdateDataAndBind(currentCmdBuffer, frameIndex);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Draw the scene
|
||||||
renderers[renIndex]->Draw(frameIndex, descPool);
|
renderers[renIndex]->Draw(frameIndex, descPool);
|
||||||
|
|
||||||
// End the command buffer recording
|
// End the command buffer recording
|
||||||
|
@ -665,10 +700,10 @@ namespace SHADE
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Remove from old material's SuperBatch
|
// Remove from old material's SuperBatch
|
||||||
Handle<SHMaterial> prevMaterial = renderable.GetPrevMaterial();
|
Handle<SHMaterialInstance> prevMaterial = renderable.GetPrevMaterial();
|
||||||
if (prevMaterial)
|
if (prevMaterial)
|
||||||
{
|
{
|
||||||
Handle<SHSuperBatch> oldSuperBatch = prevMaterial->GetPipeline()->GetPipelineState().GetSubpass()->GetSuperBatch();
|
Handle<SHSuperBatch> oldSuperBatch = prevMaterial->GetBaseMaterial()->GetPipeline()->GetPipelineState().GetSubpass()->GetSuperBatch();
|
||||||
oldSuperBatch->Remove(&renderable);
|
oldSuperBatch->Remove(&renderable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -726,8 +761,8 @@ namespace SHADE
|
||||||
|
|
||||||
auto cameraSystem = SHSystemManager::GetSystem<SHCameraSystem>();
|
auto cameraSystem = SHSystemManager::GetSystem<SHCameraSystem>();
|
||||||
#ifdef SHEDITOR
|
#ifdef SHEDITOR
|
||||||
cameraSystem->GetEditorCamera()->SetWidth(resizeWidth);
|
cameraSystem->GetEditorCamera()->SetWidth(static_cast<float>(resizeWidth));
|
||||||
cameraSystem->GetEditorCamera()->SetHeight(resizeHeight);
|
cameraSystem->GetEditorCamera()->SetHeight(static_cast<float>(resizeHeight));
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -32,6 +32,7 @@ of DigiPen Institute of Technology is prohibited.
|
||||||
#include "../Textures/SHTextureLibrary.h"
|
#include "../Textures/SHTextureLibrary.h"
|
||||||
#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"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
@ -351,6 +352,7 @@ namespace SHADE
|
||||||
// Sub systems
|
// Sub systems
|
||||||
Handle<SHMousePickSystem> mousePickSystem;
|
Handle<SHMousePickSystem> mousePickSystem;
|
||||||
Handle<SHPostOffscreenRenderSystem> postOffscreenRender;
|
Handle<SHPostOffscreenRenderSystem> postOffscreenRender;
|
||||||
|
Handle<SHLightingSubSystem> lightingSubSystem;
|
||||||
|
|
||||||
uint32_t resizeWidth;
|
uint32_t resizeWidth;
|
||||||
uint32_t resizeHeight;
|
uint32_t resizeHeight;
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "ECS_Base/SHECSMacros.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
struct SHInstancedIntegerData
|
||||||
|
{
|
||||||
|
EntityID eid;
|
||||||
|
uint32_t lightLayer;
|
||||||
|
};
|
||||||
|
}
|
|
@ -7,6 +7,7 @@
|
||||||
#include "Graphics/Buffers/SHVkBuffer.h"
|
#include "Graphics/Buffers/SHVkBuffer.h"
|
||||||
#include "Graphics/SHVkUtil.h"
|
#include "Graphics/SHVkUtil.h"
|
||||||
#include "Graphics/MiddleEnd/Interface/SHViewport.h"
|
#include "Graphics/MiddleEnd/Interface/SHViewport.h"
|
||||||
|
//#include "Graphics/MiddleEnd/Interface/SHInstancedIntegerData.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
@ -53,7 +54,7 @@ namespace SHADE
|
||||||
// wait for the copy to be done
|
// wait for the copy to be done
|
||||||
afterCopyFence->Wait(true, std::numeric_limits<uint64_t>::max());
|
afterCopyFence->Wait(true, std::numeric_limits<uint64_t>::max());
|
||||||
|
|
||||||
pickedEID = imageDataDstBuffer->GetDataFromMappedPointer<uint32_t>(static_cast<uint32_t>(viewportMousePos.y) * entityIDAttachment->GetWidth() + static_cast<uint32_t>(viewportMousePos.x));
|
pickedEID = imageDataDstBuffer->GetDataFromMappedPointer<EntityID>(static_cast<uint32_t>(viewportMousePos.y) * entityIDAttachment->GetWidth() + static_cast<uint32_t>(viewportMousePos.x));
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,19 +27,22 @@ namespace SHADE
|
||||||
sharedMaterial = {};
|
sharedMaterial = {};
|
||||||
material = {};
|
material = {};
|
||||||
oldMaterial = {};
|
oldMaterial = {};
|
||||||
|
|
||||||
|
lightLayer = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHRenderable::OnDestroy()
|
void SHRenderable::OnDestroy()
|
||||||
{
|
{
|
||||||
|
// Remove from SuperBatch
|
||||||
|
Handle<SHSuperBatch> superBatch = sharedMaterial->GetBaseMaterial()->GetPipeline()->GetPipelineState().GetSubpass()->GetSuperBatch();
|
||||||
|
superBatch->Remove(this);
|
||||||
|
|
||||||
|
// Free resources
|
||||||
if (material)
|
if (material)
|
||||||
{
|
{
|
||||||
material.Free();
|
material.Free();
|
||||||
material = {};
|
material = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove from SuperBatch
|
|
||||||
Handle<SHSuperBatch> superBatch = sharedMaterial->GetBaseMaterial()->GetPipeline()->GetPipelineState().GetSubpass()->GetSuperBatch();
|
|
||||||
superBatch->Remove(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
@ -51,20 +54,23 @@ namespace SHADE
|
||||||
if (!material && sharedMaterial == materialInstance)
|
if (!material && sharedMaterial == materialInstance)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// Flag that material was changed
|
||||||
|
materialChanged = true;
|
||||||
|
|
||||||
// Free copies of materials if any
|
// Free copies of materials if any
|
||||||
if (material)
|
if (material)
|
||||||
{
|
{
|
||||||
|
oldMaterial = material;
|
||||||
material.Free();
|
material.Free();
|
||||||
material = {};
|
material = {};
|
||||||
}
|
}
|
||||||
|
else if (sharedMaterial)
|
||||||
// Flag that material was changed
|
{
|
||||||
materialChanged = true;
|
oldMaterial = sharedMaterial;
|
||||||
if (sharedMaterial)
|
}
|
||||||
oldMaterial = sharedMaterial->GetBaseMaterial();
|
|
||||||
|
|
||||||
// Update the material
|
// Update the material
|
||||||
sharedMaterial = materialInstance;
|
sharedMaterial = materialInstance;
|
||||||
}
|
}
|
||||||
|
|
||||||
Handle<SHMaterialInstance> SHRenderable::GetMaterial() const
|
Handle<SHMaterialInstance> SHRenderable::GetMaterial() const
|
||||||
|
@ -87,6 +93,11 @@ namespace SHADE
|
||||||
return material;
|
return material;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t SHRenderable::GetLightLayer(void) const noexcept
|
||||||
|
{
|
||||||
|
return lightLayer;
|
||||||
|
}
|
||||||
|
|
||||||
void SHRenderable::ResetChangedFlag()
|
void SHRenderable::ResetChangedFlag()
|
||||||
{
|
{
|
||||||
materialChanged = false;
|
materialChanged = false;
|
||||||
|
|
|
@ -55,7 +55,8 @@ namespace SHADE
|
||||||
/* Getter Functions */
|
/* Getter Functions */
|
||||||
/*-------------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------------*/
|
||||||
bool WasMaterialChanged() const noexcept { return materialChanged; }
|
bool WasMaterialChanged() const noexcept { return materialChanged; }
|
||||||
Handle<SHMaterial> GetPrevMaterial() const noexcept { return oldMaterial; }
|
Handle<SHMaterialInstance> GetPrevMaterial() const noexcept { return oldMaterial; }
|
||||||
|
uint8_t GetLightLayer (void) const noexcept;
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------------*/
|
||||||
/* Batcher Dispatcher Functions */
|
/* Batcher Dispatcher Functions */
|
||||||
|
@ -74,7 +75,8 @@ namespace SHADE
|
||||||
Handle<SHMaterialInstance> sharedMaterial;
|
Handle<SHMaterialInstance> sharedMaterial;
|
||||||
Handle<SHMaterialInstance> material;
|
Handle<SHMaterialInstance> material;
|
||||||
bool materialChanged = true;
|
bool materialChanged = true;
|
||||||
Handle<SHMaterial> oldMaterial;
|
Handle<SHMaterialInstance> oldMaterial;
|
||||||
|
uint8_t lightLayer;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ of DigiPen Institute of Technology is prohibited.
|
||||||
#include "Graphics/MiddleEnd/Interface/SHGraphicsConstants.h"
|
#include "Graphics/MiddleEnd/Interface/SHGraphicsConstants.h"
|
||||||
#include "Graphics/Descriptors/SHVkDescriptorSetGroup.h"
|
#include "Graphics/Descriptors/SHVkDescriptorSetGroup.h"
|
||||||
#include "Graphics/Buffers/SHVkBuffer.h"
|
#include "Graphics/Buffers/SHVkBuffer.h"
|
||||||
|
#include "Camera/SHCameraDirector.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
@ -65,6 +66,11 @@ namespace SHADE
|
||||||
camera = _camera;
|
camera = _camera;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SHRenderer::SetCameraDirector(Handle<SHCameraDirector> director) noexcept
|
||||||
|
{
|
||||||
|
cameraDirector = director;
|
||||||
|
}
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
/* Drawing Functions */
|
/* Drawing Functions */
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
@ -75,17 +81,24 @@ namespace SHADE
|
||||||
|
|
||||||
void SHRenderer::UpdateDataAndBind(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept
|
void SHRenderer::UpdateDataAndBind(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept
|
||||||
{
|
{
|
||||||
if (camera)
|
if (camera && cameraDirector)
|
||||||
{
|
{
|
||||||
//cpuCameraData.viewProjectionMatrix = camera->GetViewProjectionMatrix();
|
UpdateDataAndBind(cmdBuffer, frameIndex, SHMatrix::Transpose(cameraDirector->GetVPMatrix()));
|
||||||
cameraBuffer->WriteToMemory(&cpuCameraData, sizeof(SHShaderCameraData), 0, cameraDataAlignedSize * frameIndex);
|
|
||||||
|
|
||||||
std::array<uint32_t, 1> dynamicOffsets{ frameIndex * cameraDataAlignedSize };
|
|
||||||
|
|
||||||
cmdBuffer->BindDescriptorSet(cameraDescriptorSet, vk::PipelineBindPoint::eGraphics, SHGraphicsConstants::DescriptorSetIndex::HIGH_FREQUENCY_GLOBALS, std::span{ dynamicOffsets.data(), 1 });
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SHRenderer::UpdateDataAndBind(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex, SHMatrix exteriorMatrix) noexcept
|
||||||
|
{
|
||||||
|
SetViewProjectionMatrix(exteriorMatrix);
|
||||||
|
|
||||||
|
//cpuCameraData.viewProjectionMatrix = camera->GetViewProjectionMatrix();
|
||||||
|
cameraBuffer->WriteToMemory(&cpuCameraData, sizeof(SHShaderCameraData), 0, cameraDataAlignedSize * frameIndex);
|
||||||
|
|
||||||
|
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 });
|
||||||
|
}
|
||||||
|
|
||||||
void SHRenderer::UpdateCameraDataToBuffer(void) noexcept
|
void SHRenderer::UpdateCameraDataToBuffer(void) noexcept
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,6 +40,7 @@ namespace SHADE
|
||||||
class SHGraphicsGlobalData;
|
class SHGraphicsGlobalData;
|
||||||
class SHVkDescriptorPool;
|
class SHVkDescriptorPool;
|
||||||
class SHVkBuffer;
|
class SHVkBuffer;
|
||||||
|
class SHCameraDirector;
|
||||||
|
|
||||||
struct SHShaderCameraData
|
struct SHShaderCameraData
|
||||||
{
|
{
|
||||||
|
@ -71,12 +72,14 @@ namespace SHADE
|
||||||
/* Camera Registration */
|
/* Camera Registration */
|
||||||
/*-----------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------*/
|
||||||
void SetCamera(Handle<SHCamera> _camera);
|
void SetCamera(Handle<SHCamera> _camera);
|
||||||
|
void SetCameraDirector (Handle<SHCameraDirector> director) noexcept;
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------*/
|
||||||
/* Drawing Functions */
|
/* Drawing Functions */
|
||||||
/*-----------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------*/
|
||||||
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 UpdateCameraDataToBuffer (void) noexcept;
|
void UpdateCameraDataToBuffer (void) noexcept;
|
||||||
void SetViewProjectionMatrix (SHMatrix const& vpMatrix) noexcept;
|
void SetViewProjectionMatrix (SHMatrix const& vpMatrix) noexcept;
|
||||||
|
|
||||||
|
@ -99,6 +102,8 @@ namespace SHADE
|
||||||
Handle<SHVkDescriptorSetGroup> cameraDescriptorSet;
|
Handle<SHVkDescriptorSetGroup> cameraDescriptorSet;
|
||||||
Handle<SHVkBuffer> cameraBuffer;
|
Handle<SHVkBuffer> cameraBuffer;
|
||||||
|
|
||||||
|
Handle<SHCameraDirector> cameraDirector;
|
||||||
|
|
||||||
// we really only need 1 copy even though we need %swapchainImages copies for
|
// we really only need 1 copy even though we need %swapchainImages copies for
|
||||||
// GPU.
|
// GPU.
|
||||||
SHShaderCameraData cpuCameraData;
|
SHShaderCameraData cpuCameraData;
|
||||||
|
|
|
@ -0,0 +1,123 @@
|
||||||
|
#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();
|
||||||
|
active = true;
|
||||||
|
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(uint32_t inIndexInBuffer) noexcept
|
||||||
|
{
|
||||||
|
bound = true;
|
||||||
|
indexInBuffer = inIndexInBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHLightComponent::SetActive(bool flag) noexcept
|
||||||
|
{
|
||||||
|
MakeDirty();
|
||||||
|
active = flag;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t SHLightComponent::GetIndexInBuffer(void) const noexcept
|
||||||
|
{
|
||||||
|
return indexInBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
#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;
|
||||||
|
|
||||||
|
//! If the light is active, this is true.
|
||||||
|
bool active;
|
||||||
|
|
||||||
|
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 (uint32_t inIndexInBuffer) noexcept;
|
||||||
|
void SetActive (bool flag) noexcept;
|
||||||
|
|
||||||
|
|
||||||
|
SHLightData const& GetLightData (void) const noexcept;
|
||||||
|
bool IsDirty (void) const noexcept;
|
||||||
|
bool GetBound (void) const noexcept;
|
||||||
|
uint32_t GetIndexInBuffer (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,431 @@
|
||||||
|
#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"
|
||||||
|
#include "SHLightComponent.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
/***************************************************************************/
|
||||||
|
/*!
|
||||||
|
|
||||||
|
\brief
|
||||||
|
This function takes an address in the CPU container and writes light
|
||||||
|
component data to it. What gets written depends on the light type.
|
||||||
|
|
||||||
|
\param address
|
||||||
|
The address to write to.
|
||||||
|
|
||||||
|
\param lightComp
|
||||||
|
The light component with the data to write from.
|
||||||
|
|
||||||
|
\param lightType
|
||||||
|
The type of the light
|
||||||
|
|
||||||
|
\return
|
||||||
|
|
||||||
|
*/
|
||||||
|
/***************************************************************************/
|
||||||
|
void SHLightingSubSystem::PerTypeData::WriteLightToAddress(void* address, SHLightComponent* lightComp) noexcept
|
||||||
|
{
|
||||||
|
auto const& lightData = lightComp->GetLightData();
|
||||||
|
switch (lightData.type)
|
||||||
|
{
|
||||||
|
case SH_LIGHT_TYPE::DIRECTIONAL:
|
||||||
|
{
|
||||||
|
SHDirectionalLightData* lightPtr = reinterpret_cast<SHDirectionalLightData*>(address);
|
||||||
|
|
||||||
|
lightPtr->cullingMask = lightData.cullingMask;
|
||||||
|
lightPtr->direction = lightData.direction;
|
||||||
|
lightPtr->diffuseColor = lightData.diffuseColor;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SH_LIGHT_TYPE::POINT:
|
||||||
|
break;
|
||||||
|
case SH_LIGHT_TYPE::SPOT:
|
||||||
|
break;
|
||||||
|
case SH_LIGHT_TYPE::NUM_TYPES:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************************************/
|
||||||
|
/*!
|
||||||
|
|
||||||
|
\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;
|
||||||
|
|
||||||
|
// boilerplate
|
||||||
|
intermediateData = nullptr;
|
||||||
|
|
||||||
|
// 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 the capacity.
|
||||||
|
|
||||||
|
*/
|
||||||
|
/***************************************************************************/
|
||||||
|
void SHLightingSubSystem::PerTypeData::Expand(Handle<SHVkLogicalDevice> logicalDevice) noexcept
|
||||||
|
{
|
||||||
|
if (lightDataAlignmentSize == 0)
|
||||||
|
{
|
||||||
|
SHLOG_ERROR ("One of the types of lights have not been accounted for. Make sure lightDataAlignmentSize is not nullptr.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// we want to wait for the command buffers to finish using the buffers first
|
||||||
|
logicalDevice->WaitIdle();
|
||||||
|
|
||||||
|
// First time we are initializing lights
|
||||||
|
if (intermediateData == nullptr)
|
||||||
|
{
|
||||||
|
// max lights should start of at STARTING_NUM_LIGHTS lights
|
||||||
|
maxLights = STARTING_NUM_LIGHTS;
|
||||||
|
numLights = 0;
|
||||||
|
|
||||||
|
// Initialize the data for lights
|
||||||
|
intermediateData = std::make_unique<uint8_t[]>(lightDataAlignmentSize * maxLights);
|
||||||
|
|
||||||
|
// We want to initialize 3 times the amount of data required.
|
||||||
|
dataBuffer = logicalDevice->CreateBuffer(maxLights * lightDataAlignmentSize * SHGraphicsConstants::NUM_FRAME_BUFFERS, nullptr, maxLights * lightDataAlignmentSize * SHGraphicsConstants::NUM_FRAME_BUFFERS, vk::BufferUsageFlagBits::eStorageBuffer, VMA_MEMORY_USAGE_AUTO, VMA_ALLOCATION_CREATE_MAPPED_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// save old number of lights
|
||||||
|
uint32_t const OLD_MAX_LIGHTS = maxLights;
|
||||||
|
|
||||||
|
// 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_MAX_LIGHTS);
|
||||||
|
|
||||||
|
// copy data over.
|
||||||
|
std::memcpy (oldData.get(), intermediateData.get(), lightDataAlignmentSize * OLD_MAX_LIGHTS);
|
||||||
|
|
||||||
|
// now we start to expand....
|
||||||
|
|
||||||
|
// double space for lights
|
||||||
|
maxLights *= 2;
|
||||||
|
|
||||||
|
// destroy old data and initialize container for double the amount of data.
|
||||||
|
intermediateData = std::make_unique<uint8_t[]>(lightDataAlignmentSize * maxLights);
|
||||||
|
|
||||||
|
// copy old data to new container
|
||||||
|
std::memcpy(intermediateData.get(), oldData.get(), lightDataAlignmentSize * OLD_MAX_LIGHTS);
|
||||||
|
|
||||||
|
// Resize the GPU buffer. TODO: Replace with Resize no copy here
|
||||||
|
dataBuffer->ResizeReplace(maxLights * lightDataAlignmentSize * SHGraphicsConstants::NUM_FRAME_BUFFERS, oldData.get(), lightDataAlignmentSize * OLD_MAX_LIGHTS);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************************************/
|
||||||
|
/*!
|
||||||
|
|
||||||
|
\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 sizeof(SHDirectionalLightData);
|
||||||
|
case SH_LIGHT_TYPE::POINT:
|
||||||
|
return 4;
|
||||||
|
case SH_LIGHT_TYPE::SPOT:
|
||||||
|
// TOOD: Change after creating spot light struct
|
||||||
|
return 4;
|
||||||
|
case SH_LIGHT_TYPE::NUM_TYPES:
|
||||||
|
default:
|
||||||
|
return 4;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Handle<SHVkBuffer> SHLightingSubSystem::PerTypeData::GetDataBuffer(void) const noexcept
|
||||||
|
{
|
||||||
|
return dataBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t SHLightingSubSystem::PerTypeData::GetAlignmentSize(void) const noexcept
|
||||||
|
{
|
||||||
|
return lightDataAlignmentSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t SHLightingSubSystem::PerTypeData::GetNumLights(void) const noexcept
|
||||||
|
{
|
||||||
|
return numLights;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t SHLightingSubSystem::PerTypeData::GetMaxLights(void) const noexcept
|
||||||
|
{
|
||||||
|
return maxLights;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************************************************/
|
||||||
|
/*!
|
||||||
|
|
||||||
|
\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 to hold the new light. If the buffer is too small, expand
|
||||||
|
it.
|
||||||
|
|
||||||
|
\param lightComp
|
||||||
|
The light component to add.
|
||||||
|
|
||||||
|
*/
|
||||||
|
/***************************************************************************/
|
||||||
|
void SHLightingSubSystem::PerTypeData::AddLight(Handle<SHVkLogicalDevice> logicalDevice, SHLightComponent* unboundLight, bool expanded) noexcept
|
||||||
|
{
|
||||||
|
if (unboundLight)
|
||||||
|
{
|
||||||
|
// capacity is full
|
||||||
|
if (numLights == maxLights)
|
||||||
|
{
|
||||||
|
// expand first
|
||||||
|
Expand(logicalDevice);
|
||||||
|
|
||||||
|
expanded = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now that the container is big enough, bind the new light
|
||||||
|
|
||||||
|
// Get address of write location
|
||||||
|
void* writeLocation = reinterpret_cast<uint8_t*>(intermediateData.get()) + (lightDataAlignmentSize * numLights);
|
||||||
|
|
||||||
|
// Write the light data to address
|
||||||
|
WriteLightToAddress(writeLocation, unboundLight);
|
||||||
|
|
||||||
|
// Set the light component to be bound to that location
|
||||||
|
unboundLight->SetBound(numLights);
|
||||||
|
|
||||||
|
// Increase light count
|
||||||
|
++numLights;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************************************/
|
||||||
|
/*!
|
||||||
|
|
||||||
|
\brief
|
||||||
|
Modify the data at a specific light address.
|
||||||
|
|
||||||
|
\param lightComp
|
||||||
|
The light component to write.
|
||||||
|
|
||||||
|
*/
|
||||||
|
/***************************************************************************/
|
||||||
|
void SHLightingSubSystem::PerTypeData::ModifyLight(SHLightComponent* lightComp) noexcept
|
||||||
|
{
|
||||||
|
void* writeLocation = reinterpret_cast<uint8_t*>(intermediateData.get()) + (lightDataAlignmentSize * lightComp->GetIndexInBuffer());
|
||||||
|
WriteLightToAddress(writeLocation, lightComp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHLightingSubSystem::PerTypeData::WriteToGPU(uint32_t frameIndex) noexcept
|
||||||
|
{
|
||||||
|
if (intermediateData)
|
||||||
|
{
|
||||||
|
// we want to write to the offset of the current frame
|
||||||
|
dataBuffer->WriteToMemory(intermediateData.get(), lightDataAlignmentSize * numLights, 0, lightDataAlignmentSize * maxLights * frameIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************************************/
|
||||||
|
/*!
|
||||||
|
|
||||||
|
\brief
|
||||||
|
Update descriptor sets. We want to call this every time we expand buffers.
|
||||||
|
|
||||||
|
\param binding
|
||||||
|
The binding in the set we want to update.
|
||||||
|
|
||||||
|
*/
|
||||||
|
/***************************************************************************/
|
||||||
|
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() * perTypeData[binding].GetMaxLights());
|
||||||
|
|
||||||
|
lightingDataDescSet->UpdateDescriptorSetBuffer(SHGraphicsConstants::DescriptorSetIndex::DYNAMIC_GLOBALS, binding);
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************************************/
|
||||||
|
/*!
|
||||||
|
|
||||||
|
\brief
|
||||||
|
Computes dynamic offsets.
|
||||||
|
|
||||||
|
*/
|
||||||
|
/***************************************************************************/
|
||||||
|
void SHLightingSubSystem::ComputeDynamicOffsets(void) noexcept
|
||||||
|
{
|
||||||
|
for (uint32_t i = 0; i < SHGraphicsConstants::NUM_FRAME_BUFFERS; ++i)
|
||||||
|
{
|
||||||
|
for (uint32_t j = 0; j < dynamicOffsets.size(); ++j)
|
||||||
|
{
|
||||||
|
auto const& typeData = perTypeData[j];
|
||||||
|
{
|
||||||
|
dynamicOffsets[i][j] = j * typeData.GetAlignmentSize() * typeData.GetMaxLights();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************************************/
|
||||||
|
/*!
|
||||||
|
|
||||||
|
\brief
|
||||||
|
Initializes per light type data. This includes buffers and descriptor
|
||||||
|
sets.
|
||||||
|
|
||||||
|
|
||||||
|
*/
|
||||||
|
/***************************************************************************/
|
||||||
|
void SHLightingSubSystem::Init(Handle<SHVkLogicalDevice> device, Handle<SHVkDescriptorPool> descPool) noexcept
|
||||||
|
{
|
||||||
|
SHComponentManager::CreateComponentSparseSet<SHLightComponent>();
|
||||||
|
|
||||||
|
logicalDevice = device;
|
||||||
|
uint32_t constexpr NUM_LIGHT_TYPES = SHUtilities::ToUnderlying(SH_LIGHT_TYPE::NUM_TYPES);
|
||||||
|
|
||||||
|
std::vector<uint32_t> variableSizes{ NUM_LIGHT_TYPES };
|
||||||
|
std::fill (variableSizes.begin(), variableSizes.end(), 1);
|
||||||
|
|
||||||
|
// Create the descriptor set
|
||||||
|
lightingDataDescSet = descPool->Allocate({SHGraphicsGlobalData::GetDescSetLayouts()[SHGraphicsConstants::DescriptorSetIndex::DYNAMIC_GLOBALS]}, variableSizes);
|
||||||
|
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < NUM_LIGHT_TYPES; ++i)
|
||||||
|
{
|
||||||
|
// initialize all the data first. We add more lights here as we add more types.
|
||||||
|
perTypeData[i].InitializeData(logicalDevice, static_cast<SH_LIGHT_TYPE>(i));
|
||||||
|
UpdateDescSet(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < SHGraphicsConstants::NUM_FRAME_BUFFERS; ++i)
|
||||||
|
{
|
||||||
|
dynamicOffsets[i].resize(NUM_LIGHT_TYPES);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************************************/
|
||||||
|
/*!
|
||||||
|
|
||||||
|
\brief
|
||||||
|
Loops through every single light component and checks for dirty light
|
||||||
|
data. If light data is dirty, rewrite to the CPU container. We also want
|
||||||
|
to bind the descriptor set for the light data.
|
||||||
|
|
||||||
|
*/
|
||||||
|
/***************************************************************************/
|
||||||
|
void SHLightingSubSystem::Run(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept
|
||||||
|
{
|
||||||
|
auto& lightComps = SHComponentManager::GetDense<SHLightComponent>();
|
||||||
|
bool expanded = false;
|
||||||
|
for (auto& light : lightComps)
|
||||||
|
{
|
||||||
|
auto enumValue = SHUtilities::ToUnderlying(light.GetLightData().type);
|
||||||
|
|
||||||
|
// First we want to make sure the light is already bound to the system. if it
|
||||||
|
// isn't, we write it to the correct buffer.
|
||||||
|
if (!light.GetBound())
|
||||||
|
{
|
||||||
|
perTypeData[enumValue].AddLight(logicalDevice, &light, expanded);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if there was modification to the light data
|
||||||
|
if (light.IsDirty())
|
||||||
|
{
|
||||||
|
// Write the data to the CPU
|
||||||
|
perTypeData[enumValue].ModifyLight(&light);
|
||||||
|
|
||||||
|
// Light is now updated in the container
|
||||||
|
light.ClearDirtyFlag();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write data to GPU
|
||||||
|
for (auto& data : perTypeData)
|
||||||
|
{
|
||||||
|
data.WriteToGPU(frameIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If any of the buffers got expanded, the descriptor set is invalid because the expanded buffer
|
||||||
|
// is a new buffer. If some expansion was detected, update descriptor sets.
|
||||||
|
if (expanded)
|
||||||
|
{
|
||||||
|
uint32_t constexpr NUM_LIGHT_TYPES = SHUtilities::ToUnderlying(SH_LIGHT_TYPE::NUM_TYPES);
|
||||||
|
for (uint32_t i = 0; i < NUM_LIGHT_TYPES; ++i)
|
||||||
|
{
|
||||||
|
UpdateDescSet(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// compute dynamic offsets. We don't actually have to compute every frame but its pretty lightweight,
|
||||||
|
// so we do it anyway. #NoteToSelf: if at any point it affects performance, do a check before computing.
|
||||||
|
ComputeDynamicOffsets();
|
||||||
|
|
||||||
|
// Bind descriptor set (We bind at an offset because the buffer holds NUM_FRAME_BUFFERS sets of data).
|
||||||
|
cmdBuffer->BindDescriptorSet(lightingDataDescSet, SH_PIPELINE_TYPE::GRAPHICS, SHGraphicsConstants::DescriptorSetIndex::DYNAMIC_GLOBALS, {dynamicOffsets[frameIndex]});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************************************/
|
||||||
|
/*!
|
||||||
|
|
||||||
|
\brief
|
||||||
|
Does nothing for now.
|
||||||
|
|
||||||
|
*/
|
||||||
|
/***************************************************************************/
|
||||||
|
void SHLightingSubSystem::Exit(void) noexcept
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,124 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Resource/SHHandle.h"
|
||||||
|
#include "Math/Vector/SHVec3.h"
|
||||||
|
#include "Math/Vector/SHVec4.h"
|
||||||
|
#include "SHLightData.h"
|
||||||
|
#include "Graphics/MiddleEnd/Interface/SHGraphicsConstants.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
class SHVkLogicalDevice;
|
||||||
|
class SHVkDescriptorPool;
|
||||||
|
class SHVkDescriptorSetGroup;
|
||||||
|
class SHVkDescriptorSetLayout;
|
||||||
|
class SHVkBuffer;
|
||||||
|
class SHLightComponent;
|
||||||
|
class SHVkCommandBuffer;
|
||||||
|
|
||||||
|
// Represents how the data will be interpreted in GPU. we want to copy to a container of these before passing to GPU.
|
||||||
|
struct SHDirectionalLightData
|
||||||
|
{
|
||||||
|
//! Direction of the light
|
||||||
|
SHVec3 direction;
|
||||||
|
|
||||||
|
//! Represents if the light is active or not
|
||||||
|
uint32_t active;
|
||||||
|
|
||||||
|
//! Each bit in this 32 bit field will represent a layer. If the bit is set,
|
||||||
|
//! when a fragment is being evaluated, the shader will use the fragment's
|
||||||
|
//! layer value to AND with the light's. If result is 1, do lighting calculations.
|
||||||
|
uint32_t cullingMask;
|
||||||
|
|
||||||
|
//! Diffuse color emitted by the light
|
||||||
|
SHVec4 diffuseColor;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class SH_API SHLightingSubSystem
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
class PerTypeData
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
/* STATIC MEMBER VARIABLES */
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
static constexpr uint32_t STARTING_NUM_LIGHTS = 20;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
/* PRIVATE MEMBER VARIABLES */
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
//! Capacity of the container.
|
||||||
|
uint32_t maxLights;
|
||||||
|
|
||||||
|
//! 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;
|
||||||
|
|
||||||
|
//! 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. Note this will store only 1 copy of all the lights, compared
|
||||||
|
//! to the GPU that stores NUM_FRAME_BUFFERS copies.
|
||||||
|
std::unique_ptr<uint8_t[]> intermediateData;
|
||||||
|
|
||||||
|
void WriteLightToAddress (void* address, SHLightComponent* lightComp) noexcept;
|
||||||
|
public:
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
/* PUBLIC MEMBER FUNCTIONS */
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
void InitializeData (Handle<SHVkLogicalDevice> logicalDevice, SH_LIGHT_TYPE type) noexcept;
|
||||||
|
void Expand (Handle<SHVkLogicalDevice> logicalDevice) noexcept;
|
||||||
|
void AddLight (Handle<SHVkLogicalDevice> logicalDevice, SHLightComponent* unboundLight, bool expanded) noexcept;
|
||||||
|
void ModifyLight (SHLightComponent* lightComp) noexcept;
|
||||||
|
void WriteToGPU (uint32_t frameIndex) noexcept;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
/* GETTERS */
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
static uint32_t GetLightTypeSize (SH_LIGHT_TYPE type) noexcept;
|
||||||
|
Handle<SHVkBuffer> GetDataBuffer (void) const noexcept;
|
||||||
|
uint32_t GetAlignmentSize (void) const noexcept;
|
||||||
|
uint32_t GetNumLights (void) const noexcept;
|
||||||
|
uint32_t GetMaxLights (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;
|
||||||
|
|
||||||
|
//! Container to store dynamic offsets for binding descriptor sets
|
||||||
|
std::array<std::vector<uint32_t>, static_cast<uint32_t>(SHGraphicsConstants::NUM_FRAME_BUFFERS)> dynamicOffsets;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
/* PRIVATE MEMBER FUNCTIONS */
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
void UpdateDescSet (uint32_t binding) noexcept;
|
||||||
|
void ComputeDynamicOffsets (void) noexcept;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
/* PUBLIC MEMBER FUNCTIONS */
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
void Init (Handle<SHVkLogicalDevice> device, Handle<SHVkDescriptorPool> descPool) noexcept;
|
||||||
|
void Run (Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept;
|
||||||
|
void Exit (void) noexcept;
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
|
@ -8,7 +8,7 @@
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
|
||||||
Handle<SHVkPipeline> SHPipelineLibrary::CreateDrawPipeline(std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair, Handle<SHVkRenderpass> renderpass, Handle<SHSubpass> subpass) noexcept
|
Handle<SHVkPipeline> SHPipelineLibrary::CreateGraphicsPipelines(std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair, Handle<SHVkRenderpass> renderpass, Handle<SHSubpass> subpass) noexcept
|
||||||
{
|
{
|
||||||
SHPipelineLayoutParams params
|
SHPipelineLayoutParams params
|
||||||
{
|
{
|
||||||
|
@ -52,7 +52,7 @@ namespace SHADE
|
||||||
newPipeline->ConstructPipeline();
|
newPipeline->ConstructPipeline();
|
||||||
|
|
||||||
// Emplace the new pipeline
|
// Emplace the new pipeline
|
||||||
pipelines.emplace (vsFsPair, newPipeline);
|
graphicsPipelines.emplace (vsFsPair, newPipeline);
|
||||||
|
|
||||||
return newPipeline;
|
return newPipeline;
|
||||||
}
|
}
|
||||||
|
@ -62,19 +62,19 @@ namespace SHADE
|
||||||
logicalDevice = device;
|
logicalDevice = device;
|
||||||
}
|
}
|
||||||
|
|
||||||
Handle<SHVkPipeline> SHPipelineLibrary::GetDrawPipline(std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair) noexcept
|
Handle<SHVkPipeline> SHPipelineLibrary::GetGraphicsPipeline(std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair) noexcept
|
||||||
{
|
{
|
||||||
// return the pipeline requested for
|
// return the pipeline requested for
|
||||||
if (pipelines.contains(vsFsPair))
|
if (graphicsPipelines.contains(vsFsPair))
|
||||||
return pipelines.at(vsFsPair);
|
return graphicsPipelines.at(vsFsPair);
|
||||||
else
|
else
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SHPipelineLibrary::CheckDrawPipelineExistence(std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair) noexcept
|
bool SHPipelineLibrary::CheckGraphicsPipelineExistence(std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair) noexcept
|
||||||
{
|
{
|
||||||
// Returns if a pipeline exists or not
|
// Returns if a pipeline exists or not
|
||||||
return pipelines.contains(vsFsPair);
|
return graphicsPipelines.contains(vsFsPair);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -23,19 +23,19 @@ namespace SHADE
|
||||||
Handle<SHVkLogicalDevice> logicalDevice;
|
Handle<SHVkLogicalDevice> logicalDevice;
|
||||||
|
|
||||||
//! a map of pipelines that are hashed using a pair of shader module handles
|
//! a map of pipelines that are hashed using a pair of shader module handles
|
||||||
std::unordered_map<std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>>, Handle<SHVkPipeline>> pipelines;
|
std::unordered_map<std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>>, Handle<SHVkPipeline>> graphicsPipelines;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void Init (Handle<SHVkLogicalDevice> device) noexcept;
|
void Init (Handle<SHVkLogicalDevice> device) noexcept;
|
||||||
|
|
||||||
// Draw pipeline functions. used only when creating pipelines for drawing using a vertex and fragment shader
|
// Draw pipeline functions. used only when creating pipelines for drawing using a vertex and fragment shader
|
||||||
Handle<SHVkPipeline> CreateDrawPipeline (
|
Handle<SHVkPipeline> CreateGraphicsPipelines (
|
||||||
std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair,
|
std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair,
|
||||||
Handle<SHVkRenderpass> renderpass,
|
Handle<SHVkRenderpass> renderpass,
|
||||||
Handle<SHSubpass> subpass
|
Handle<SHSubpass> subpass
|
||||||
) noexcept;
|
) noexcept;
|
||||||
Handle<SHVkPipeline> GetDrawPipline (std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair) noexcept;
|
Handle<SHVkPipeline> GetGraphicsPipeline (std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair) noexcept;
|
||||||
bool CheckDrawPipelineExistence (std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair) noexcept;
|
bool CheckGraphicsPipelineExistence (std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair) noexcept;
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -142,6 +142,12 @@ namespace SHADE
|
||||||
|
|
||||||
case SHAttribFormat::UINT32_1D:
|
case SHAttribFormat::UINT32_1D:
|
||||||
return std::make_tuple(1, 4, vk::Format::eR32Uint);
|
return std::make_tuple(1, 4, vk::Format::eR32Uint);
|
||||||
|
case SHAttribFormat::UINT32_2D:
|
||||||
|
return std::make_tuple(1, 8, vk::Format::eR32G32Uint);
|
||||||
|
case SHAttribFormat::UINT32_3D:
|
||||||
|
return std::make_tuple(1, 12, vk::Format::eR32G32B32Uint);
|
||||||
|
case SHAttribFormat::UINT32_4D:
|
||||||
|
return std::make_tuple(1, 16, vk::Format::eR32G32B32A32Uint);
|
||||||
}
|
}
|
||||||
return std::make_tuple(0, 0, vk::Format::eR32Sfloat);
|
return std::make_tuple(0, 0, vk::Format::eR32Sfloat);
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,9 +5,13 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
enum class SH_PIPELINE_TYPE
|
enum class SH_PIPELINE_TYPE
|
||||||
{
|
{
|
||||||
GRAPHICS,
|
GRAPHICS = 0,
|
||||||
COMPUTE,
|
COMPUTE,
|
||||||
|
RAY_TRACING,
|
||||||
|
NUM_TYPES,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
|
@ -4,6 +4,7 @@
|
||||||
#include "Graphics/Shaders/SHVkShaderModule.h"
|
#include "Graphics/Shaders/SHVkShaderModule.h"
|
||||||
#include "Graphics/Debugging/SHVulkanDebugUtil.h"
|
#include "Graphics/Debugging/SHVulkanDebugUtil.h"
|
||||||
#include "Graphics/RenderGraph/SHRenderGraph.h"
|
#include "Graphics/RenderGraph/SHRenderGraph.h"
|
||||||
|
#include "Graphics/SHVkUtil.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
@ -171,6 +172,29 @@ namespace SHADE
|
||||||
|
|
||||||
void SHVkPipeline::CreateComputePipeline(void) noexcept
|
void SHVkPipeline::CreateComputePipeline(void) noexcept
|
||||||
{
|
{
|
||||||
|
auto shaderModule = pipelineLayout->GetShaderModules()[0];
|
||||||
|
|
||||||
|
vk::PipelineShaderStageCreateInfo shaderStageCreateInfo
|
||||||
|
{
|
||||||
|
.stage = vk::ShaderStageFlagBits::eCompute,
|
||||||
|
.module = shaderModule->GetVkShaderModule(),
|
||||||
|
.pName = shaderModule->GetEntryPoint().c_str(),
|
||||||
|
};
|
||||||
|
|
||||||
|
vk::ComputePipelineCreateInfo cpCreateInfo
|
||||||
|
{
|
||||||
|
.flags = {},
|
||||||
|
.stage = shaderStageCreateInfo,
|
||||||
|
.layout = pipelineLayout->GetVkPipelineLayout(),
|
||||||
|
};
|
||||||
|
|
||||||
|
if (auto result = logicalDeviceHdl->GetVkLogicalDevice().createComputePipelines({}, 1, &cpCreateInfo, nullptr, &vkPipeline); result != vk::Result::eSuccess)
|
||||||
|
SHVulkanDebugUtil::ReportVkError(result, "Failed to create Compute Pipeline. ");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SHVulkanDebugUtil::ReportVkSuccess("Successfully created a Compute Pipeline. ");
|
||||||
|
created = true;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -245,7 +269,7 @@ namespace SHADE
|
||||||
, logicalDeviceHdl{ rhs.logicalDeviceHdl }
|
, logicalDeviceHdl{ rhs.logicalDeviceHdl }
|
||||||
, pipelineLayout { rhs.pipelineLayout }
|
, pipelineLayout { rhs.pipelineLayout }
|
||||||
{
|
{
|
||||||
vkPipeline = VK_NULL_HANDLE;
|
rhs.vkPipeline = VK_NULL_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
|
@ -285,7 +309,8 @@ namespace SHADE
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
SHVkPipeline::~SHVkPipeline(void) noexcept
|
SHVkPipeline::~SHVkPipeline(void) noexcept
|
||||||
{
|
{
|
||||||
logicalDeviceHdl->GetVkLogicalDevice().destroyPipeline(vkPipeline, nullptr);
|
if (vkPipeline)
|
||||||
|
logicalDeviceHdl->GetVkLogicalDevice().destroyPipeline(vkPipeline, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
|
@ -313,7 +338,7 @@ namespace SHADE
|
||||||
created = rhs.created;
|
created = rhs.created;
|
||||||
logicalDeviceHdl = rhs.logicalDeviceHdl;
|
logicalDeviceHdl = rhs.logicalDeviceHdl;
|
||||||
|
|
||||||
vkPipeline = VK_NULL_HANDLE;
|
rhs.vkPipeline = VK_NULL_HANDLE;
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
@ -399,18 +424,7 @@ namespace SHADE
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
vk::PipelineBindPoint SHVkPipeline::GetPipelineBindPoint(void) const noexcept
|
vk::PipelineBindPoint SHVkPipeline::GetPipelineBindPoint(void) const noexcept
|
||||||
{
|
{
|
||||||
switch (pipelineType)
|
return SHVkUtil::GetPipelineBindPointFromType(pipelineType);
|
||||||
{
|
|
||||||
case SH_PIPELINE_TYPE::GRAPHICS:
|
|
||||||
return vk::PipelineBindPoint::eGraphics;
|
|
||||||
case SH_PIPELINE_TYPE::COMPUTE:
|
|
||||||
return vk::PipelineBindPoint::eCompute;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return vk::PipelineBindPoint::eGraphics;
|
|
||||||
break;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
|
@ -450,4 +464,9 @@ namespace SHADE
|
||||||
return pipelineLayout;
|
return pipelineLayout;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SH_PIPELINE_TYPE SHVkPipeline::GetPipelineType(void) const noexcept
|
||||||
|
{
|
||||||
|
return pipelineType;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -77,6 +77,7 @@ namespace SHADE
|
||||||
vk::Pipeline GetVkPipeline (void) const noexcept;
|
vk::Pipeline GetVkPipeline (void) const noexcept;
|
||||||
bool GetIsCreated (void) const noexcept;
|
bool GetIsCreated (void) const noexcept;
|
||||||
Handle<SHVkPipelineLayout> GetPipelineLayout (void) const noexcept;
|
Handle<SHVkPipelineLayout> GetPipelineLayout (void) const noexcept;
|
||||||
|
SH_PIPELINE_TYPE GetPipelineType (void) const noexcept;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -216,9 +216,18 @@ namespace SHADE
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
void SHVkPipelineLayout::PrepareVkDescriptorSetLayouts(void) noexcept
|
void SHVkPipelineLayout::PrepareVkDescriptorSetLayouts(void) noexcept
|
||||||
{
|
{
|
||||||
|
// pipeline layouts contain global layouts first, then layouts for allocation
|
||||||
descriptorSetLayoutsPipeline.reserve(descriptorSetLayoutsAllocate.size() + descriptorSetLayoutsGlobal.size());
|
descriptorSetLayoutsPipeline.reserve(descriptorSetLayoutsAllocate.size() + descriptorSetLayoutsGlobal.size());
|
||||||
|
vkDescriptorSetLayoutsPipeline.reserve(descriptorSetLayoutsAllocate.size() + descriptorSetLayoutsGlobal.size());
|
||||||
|
|
||||||
// Settle allocate layouts first
|
// First we insert the global layouts
|
||||||
|
for (auto const& layout : descriptorSetLayoutsGlobal)
|
||||||
|
{
|
||||||
|
descriptorSetLayoutsPipeline.emplace_back(layout);
|
||||||
|
//vkDescriptorSetLayoutsPipeline.emplace_back(layout->GetVkHandle());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Then the allocate layouts
|
||||||
vkDescriptorSetLayoutsAllocate.reserve(descriptorSetLayoutsAllocate.size());
|
vkDescriptorSetLayoutsAllocate.reserve(descriptorSetLayoutsAllocate.size());
|
||||||
for (auto const& layout : descriptorSetLayoutsAllocate)
|
for (auto const& layout : descriptorSetLayoutsAllocate)
|
||||||
{
|
{
|
||||||
|
@ -226,18 +235,13 @@ namespace SHADE
|
||||||
vkDescriptorSetLayoutsAllocate.emplace_back(layout->GetVkHandle());
|
vkDescriptorSetLayoutsAllocate.emplace_back(layout->GetVkHandle());
|
||||||
}
|
}
|
||||||
|
|
||||||
// pipeline layouts contain global layouts first, then layouts for allocation
|
for (auto const& layout : descriptorSetLayoutsPipeline)
|
||||||
vkDescriptorSetLayoutsPipeline.reserve(descriptorSetLayoutsAllocate.size() + descriptorSetLayoutsGlobal.size());
|
|
||||||
|
|
||||||
// First we insert the global layouts
|
|
||||||
for (auto const& layout : descriptorSetLayoutsGlobal)
|
|
||||||
{
|
{
|
||||||
descriptorSetLayoutsPipeline.emplace_back(layout);
|
|
||||||
vkDescriptorSetLayoutsPipeline.emplace_back(layout->GetVkHandle());
|
vkDescriptorSetLayoutsPipeline.emplace_back(layout->GetVkHandle());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Then we append layouts for allocation at the back of the vector
|
// Then we append layouts for allocation at the back of the vector
|
||||||
std::copy(vkDescriptorSetLayoutsAllocate.begin(), vkDescriptorSetLayoutsAllocate.end(), std::back_inserter(vkDescriptorSetLayoutsPipeline));
|
//std::copy(vkDescriptorSetLayoutsAllocate.begin(), vkDescriptorSetLayoutsAllocate.end(), std::back_inserter(vkDescriptorSetLayoutsPipeline));
|
||||||
}
|
}
|
||||||
|
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
|
@ -294,6 +298,7 @@ namespace SHADE
|
||||||
, descriptorSetLayoutsGlobal{pipelineLayoutParams.globalDescSetLayouts } // do a copy, some other pipeline layout might need this
|
, descriptorSetLayoutsGlobal{pipelineLayoutParams.globalDescSetLayouts } // do a copy, some other pipeline layout might need this
|
||||||
, descriptorSetLayoutsAllocate{}
|
, descriptorSetLayoutsAllocate{}
|
||||||
, vkDescriptorSetLayoutsAllocate{}
|
, vkDescriptorSetLayoutsAllocate{}
|
||||||
|
, descriptorSetLayoutsPipeline{}
|
||||||
, vkDescriptorSetLayoutsPipeline{}
|
, vkDescriptorSetLayoutsPipeline{}
|
||||||
{
|
{
|
||||||
for (auto& mod : shaderModules)
|
for (auto& mod : shaderModules)
|
||||||
|
@ -318,6 +323,7 @@ namespace SHADE
|
||||||
, descriptorSetLayoutsGlobal{}
|
, descriptorSetLayoutsGlobal{}
|
||||||
, descriptorSetLayoutsAllocate{}
|
, descriptorSetLayoutsAllocate{}
|
||||||
, vkDescriptorSetLayoutsAllocate{}
|
, vkDescriptorSetLayoutsAllocate{}
|
||||||
|
, descriptorSetLayoutsPipeline{}
|
||||||
, vkDescriptorSetLayoutsPipeline{}
|
, vkDescriptorSetLayoutsPipeline{}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -368,7 +374,8 @@ namespace SHADE
|
||||||
, descriptorSetLayoutsGlobal {std::move (rhs.descriptorSetLayoutsGlobal)}
|
, descriptorSetLayoutsGlobal {std::move (rhs.descriptorSetLayoutsGlobal)}
|
||||||
, descriptorSetLayoutsAllocate {std::move (rhs.descriptorSetLayoutsAllocate)}
|
, descriptorSetLayoutsAllocate {std::move (rhs.descriptorSetLayoutsAllocate)}
|
||||||
, vkDescriptorSetLayoutsAllocate{std::move (rhs.vkDescriptorSetLayoutsAllocate)}
|
, vkDescriptorSetLayoutsAllocate{std::move (rhs.vkDescriptorSetLayoutsAllocate)}
|
||||||
, vkDescriptorSetLayoutsPipeline{std::move (rhs.vkDescriptorSetLayoutsAllocate)}
|
, descriptorSetLayoutsPipeline { std::move(rhs.descriptorSetLayoutsPipeline) }
|
||||||
|
, vkDescriptorSetLayoutsPipeline{ std::move(rhs.vkDescriptorSetLayoutsPipeline) }
|
||||||
{
|
{
|
||||||
rhs.vkPipelineLayout = VK_NULL_HANDLE;
|
rhs.vkPipelineLayout = VK_NULL_HANDLE;
|
||||||
}
|
}
|
||||||
|
@ -441,12 +448,12 @@ namespace SHADE
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Handle<SHVkDescriptorSetLayout>> SHVkPipelineLayout::GetDescriptorSetLayoutsPipeline(void) const noexcept
|
std::vector<Handle<SHVkDescriptorSetLayout>> const& SHVkPipelineLayout::GetDescriptorSetLayoutsPipeline(void) const noexcept
|
||||||
{
|
{
|
||||||
return descriptorSetLayoutsPipeline;
|
return descriptorSetLayoutsPipeline;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Handle<SHVkDescriptorSetLayout>> SHVkPipelineLayout::GetDescriptorSetLayoutsAllocate(void) const noexcept
|
std::vector<Handle<SHVkDescriptorSetLayout>> const& SHVkPipelineLayout::GetDescriptorSetLayoutsAllocate(void) const noexcept
|
||||||
{
|
{
|
||||||
return descriptorSetLayoutsAllocate;
|
return descriptorSetLayoutsAllocate;
|
||||||
}
|
}
|
||||||
|
@ -464,7 +471,8 @@ namespace SHADE
|
||||||
descriptorSetLayoutsGlobal = std::move(rhs.descriptorSetLayoutsGlobal);
|
descriptorSetLayoutsGlobal = std::move(rhs.descriptorSetLayoutsGlobal);
|
||||||
descriptorSetLayoutsAllocate = std::move(rhs.descriptorSetLayoutsAllocate);
|
descriptorSetLayoutsAllocate = std::move(rhs.descriptorSetLayoutsAllocate);
|
||||||
vkDescriptorSetLayoutsAllocate = std::move(rhs.vkDescriptorSetLayoutsAllocate);
|
vkDescriptorSetLayoutsAllocate = std::move(rhs.vkDescriptorSetLayoutsAllocate);
|
||||||
vkDescriptorSetLayoutsPipeline = std::move(rhs.vkDescriptorSetLayoutsAllocate);
|
descriptorSetLayoutsPipeline = std::move(rhs.descriptorSetLayoutsPipeline);
|
||||||
|
vkDescriptorSetLayoutsPipeline = std::move(rhs.vkDescriptorSetLayoutsPipeline);
|
||||||
|
|
||||||
rhs.vkPipelineLayout = VK_NULL_HANDLE;
|
rhs.vkPipelineLayout = VK_NULL_HANDLE;
|
||||||
|
|
||||||
|
|
|
@ -74,12 +74,12 @@ namespace SHADE
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
/* SETTERS AND GETTERS */
|
/* SETTERS AND GETTERS */
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
std::vector<Handle<SHVkShaderModule>> const& GetShaderModules (void) const noexcept;
|
std::vector<Handle<SHVkShaderModule>> const& GetShaderModules (void) const noexcept;
|
||||||
vk::PipelineLayout GetVkPipelineLayout (void) const noexcept;
|
vk::PipelineLayout GetVkPipelineLayout (void) const noexcept;
|
||||||
SHPushConstantInterface const& GetPushConstantInterface (void) const noexcept;
|
SHPushConstantInterface const& GetPushConstantInterface (void) const noexcept;
|
||||||
Handle<SHShaderBlockInterface> GetShaderBlockInterface (uint32_t set, uint32_t binding, vk::ShaderStageFlagBits shaderStage) const noexcept;
|
Handle<SHShaderBlockInterface> GetShaderBlockInterface (uint32_t set, uint32_t binding, vk::ShaderStageFlagBits shaderStage) const noexcept;
|
||||||
std::vector<Handle<SHVkDescriptorSetLayout>> GetDescriptorSetLayoutsPipeline(void) const noexcept;
|
std::vector<Handle<SHVkDescriptorSetLayout>> const& GetDescriptorSetLayoutsPipeline(void) const noexcept;
|
||||||
std::vector<Handle<SHVkDescriptorSetLayout>> GetDescriptorSetLayoutsAllocate(void) const noexcept;
|
std::vector<Handle<SHVkDescriptorSetLayout>> const& GetDescriptorSetLayoutsAllocate(void) const noexcept;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,8 @@ namespace SHADE
|
||||||
DEPTH = 0x04,
|
DEPTH = 0x04,
|
||||||
STENCIL = 0x08,
|
STENCIL = 0x08,
|
||||||
DEPTH_STENCIL = 0x10,
|
DEPTH_STENCIL = 0x10,
|
||||||
INPUT = 0x20
|
INPUT = 0x20,
|
||||||
|
STORAGE = 0x40
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,8 @@
|
||||||
#include "Graphics/Buffers/SHVkBuffer.h"
|
#include "Graphics/Buffers/SHVkBuffer.h"
|
||||||
#include "Tools/SHLogger.h"
|
#include "Tools/SHLogger.h"
|
||||||
#include "SHAttachmentDescInitParams.h"
|
#include "SHAttachmentDescInitParams.h"
|
||||||
|
#include "SHRenderGraphStorage.h"
|
||||||
|
#include "Graphics/RenderGraph/SHRenderGraphNodeCompute.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
@ -52,12 +54,12 @@ namespace SHADE
|
||||||
// If we set to
|
// If we set to
|
||||||
if (w == static_cast<uint32_t>(-1) && h == static_cast<uint32_t>(-1))
|
if (w == static_cast<uint32_t>(-1) && h == static_cast<uint32_t>(-1))
|
||||||
{
|
{
|
||||||
w = swapchainHdl->GetSwapchainImage(0)->GetWidth();
|
w = renderGraphStorage->swapchain->GetSwapchainImage(0)->GetWidth();
|
||||||
h = swapchainHdl->GetSwapchainImage(0)->GetHeight();
|
h = renderGraphStorage->swapchain->GetSwapchainImage(0)->GetHeight();
|
||||||
format = swapchainHdl->GetSurfaceFormatKHR().format;
|
format = renderGraphStorage->swapchain->GetSurfaceFormatKHR().format;
|
||||||
}
|
}
|
||||||
|
|
||||||
graphResources.try_emplace(resourceName, resourceManager->Create<SHRenderGraphResource>(logicalDeviceHdl, swapchainHdl, resourceName, typeFlags, format, w, h, levels, usageFlags, createFlags));
|
renderGraphStorage->graphResources->try_emplace(resourceName, resourceManager->Create<SHRenderGraphResource>(renderGraphStorage, resourceName, typeFlags, format, w, h, levels, usageFlags, createFlags));
|
||||||
}
|
}
|
||||||
|
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
|
@ -77,36 +79,38 @@ namespace SHADE
|
||||||
|
|
||||||
for (uint32_t i = 0; auto& node : nodes)
|
for (uint32_t i = 0; auto& node : nodes)
|
||||||
{
|
{
|
||||||
// key is handle ID, value is pair (first is initial layout, second is final layout).
|
// key is handle ID, value is final layout.
|
||||||
std::unordered_map<uint32_t, vk::ImageLayout> resourceAttLayouts;
|
std::unordered_map<uint32_t, vk::ImageLayout> resourceAttFinalLayouts;
|
||||||
if (node->subpasses.empty())
|
if (node->subpasses.empty())
|
||||||
{
|
{
|
||||||
SHLOG_ERROR("Node does not contain a subpass. Cannot configure attachment descriptions as a result. ");
|
SHLOG_ERROR("Node does not contain a subpass. Cannot configure attachment descriptions as a result. ");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// attempt to get all final layouts for all resources
|
||||||
for (auto& subpass : node->subpasses)
|
for (auto& subpass : node->subpasses)
|
||||||
{
|
{
|
||||||
for (auto& color : subpass->colorReferences)
|
for (auto& color : subpass->colorReferences)
|
||||||
{
|
{
|
||||||
|
// If final renderpass and attachment is a COLOR_PRESENT resource, make resource transition to present after last subpass
|
||||||
if (i == nodes.size() - 1 && (node->attResources[color.attachment]->resourceTypeFlags & static_cast<uint32_t>(SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT)))
|
if (i == nodes.size() - 1 && (node->attResources[color.attachment]->resourceTypeFlags & static_cast<uint32_t>(SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT)))
|
||||||
resourceAttLayouts[color.attachment] = vk::ImageLayout::ePresentSrcKHR;
|
resourceAttFinalLayouts[color.attachment] = vk::ImageLayout::ePresentSrcKHR;
|
||||||
else
|
else
|
||||||
resourceAttLayouts[color.attachment] = color.layout;
|
resourceAttFinalLayouts[color.attachment] = color.layout;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& depth : subpass->depthReferences)
|
for (auto& depth : subpass->depthReferences)
|
||||||
resourceAttLayouts[depth.attachment] = depth.layout;
|
resourceAttFinalLayouts[depth.attachment] = depth.layout;
|
||||||
|
|
||||||
for (auto& input : subpass->inputReferences)
|
for (auto& input : subpass->inputReferences)
|
||||||
resourceAttLayouts[input.attachment] = input.layout;
|
resourceAttFinalLayouts[input.attachment] = input.layout;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint32_t j = 0; j < node->attachmentDescriptions.size(); ++j)
|
for (uint32_t j = 0; j < node->attachmentDescriptions.size(); ++j)
|
||||||
{
|
{
|
||||||
auto& att = node->attachmentDescriptions[j];
|
auto& att = node->attachmentDescriptions[j];
|
||||||
att.initialLayout = vk::ImageLayout::eUndefined;
|
att.initialLayout = vk::ImageLayout::eUndefined;
|
||||||
att.finalLayout = resourceAttLayouts[j];
|
att.finalLayout = resourceAttFinalLayouts[j];
|
||||||
}
|
}
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
|
@ -138,6 +142,9 @@ namespace SHADE
|
||||||
attDesc.loadOp = vk::AttachmentLoadOp::eLoad;
|
attDesc.loadOp = vk::AttachmentLoadOp::eLoad;
|
||||||
predAttDesc.storeOp = vk::AttachmentStoreOp::eStore;
|
predAttDesc.storeOp = vk::AttachmentStoreOp::eStore;
|
||||||
|
|
||||||
|
attDesc.stencilLoadOp = vk::AttachmentLoadOp::eLoad;
|
||||||
|
attDesc.stencilStoreOp = vk::AttachmentStoreOp::eStore;
|
||||||
|
|
||||||
// TODO: Stencil load and store
|
// TODO: Stencil load and store
|
||||||
|
|
||||||
// When an image is done being used in a renderpass, the image layout will end up being the finalLayout
|
// When an image is done being used in a renderpass, the image layout will end up being the finalLayout
|
||||||
|
@ -292,6 +299,9 @@ namespace SHADE
|
||||||
dep.dstAccessMask = dstAccess;
|
dep.dstAccessMask = dstAccess;
|
||||||
|
|
||||||
dep.srcStageMask = srcStage;
|
dep.srcStageMask = srcStage;
|
||||||
|
|
||||||
|
// initialize input descriptors
|
||||||
|
node->subpasses[i]->CreateInputDescriptors();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -343,10 +353,18 @@ namespace SHADE
|
||||||
|
|
||||||
*/
|
*/
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
void SHRenderGraph::Init(Handle<SHVkLogicalDevice> const& logicalDevice, Handle<SHVkSwapchain> const& swapchain) noexcept
|
void SHRenderGraph::Init(Handle<SHVkLogicalDevice> logicalDevice, Handle<SHVkSwapchain> swapchain) noexcept
|
||||||
{
|
{
|
||||||
logicalDeviceHdl = logicalDevice;
|
resourceManager = std::make_shared<SHResourceHub>();
|
||||||
swapchainHdl = swapchain;
|
|
||||||
|
renderGraphStorage = resourceManager->Create<SHRenderGraphStorage>();
|
||||||
|
renderGraphStorage->graphResources = resourceManager->Create<std::unordered_map<std::string, Handle<SHRenderGraphResource>>>();
|
||||||
|
|
||||||
|
renderGraphStorage->logicalDevice = logicalDevice;
|
||||||
|
renderGraphStorage->swapchain = swapchain;
|
||||||
|
|
||||||
|
renderGraphStorage->resourceManager = resourceManager;
|
||||||
|
renderGraphStorage->descriptorPool = logicalDevice->CreateDescriptorPools();
|
||||||
}
|
}
|
||||||
|
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
|
@ -361,24 +379,19 @@ namespace SHADE
|
||||||
*/
|
*/
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
SHRenderGraph::SHRenderGraph(void) noexcept
|
SHRenderGraph::SHRenderGraph(void) noexcept
|
||||||
: logicalDeviceHdl{ }
|
: renderGraphStorage{}
|
||||||
, swapchainHdl{ }
|
|
||||||
, nodes{}
|
, nodes{}
|
||||||
, graphResources{}
|
|
||||||
, resourceManager{nullptr}
|
, resourceManager{nullptr}
|
||||||
{
|
{
|
||||||
resourceManager = std::make_shared<SHResourceHub>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SHRenderGraph::SHRenderGraph(SHRenderGraph&& rhs) noexcept
|
SHRenderGraph::SHRenderGraph(SHRenderGraph&& rhs) noexcept
|
||||||
: logicalDeviceHdl{ rhs.logicalDeviceHdl }
|
: renderGraphStorage{ rhs.renderGraphStorage }
|
||||||
, swapchainHdl{ rhs.swapchainHdl }
|
|
||||||
, nodeIndexing{ std::move(rhs.nodeIndexing) }
|
, nodeIndexing{ std::move(rhs.nodeIndexing) }
|
||||||
, nodes{ std::move(rhs.nodes) }
|
, nodes{ std::move(rhs.nodes) }
|
||||||
, graphResources{ std::move(rhs.graphResources) }
|
|
||||||
, resourceManager{ std::move(rhs.resourceManager) }
|
, resourceManager{ std::move(rhs.resourceManager) }
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SHRenderGraph& SHRenderGraph::operator=(SHRenderGraph&& rhs) noexcept
|
SHRenderGraph& SHRenderGraph::operator=(SHRenderGraph&& rhs) noexcept
|
||||||
|
@ -386,11 +399,9 @@ namespace SHADE
|
||||||
if (&rhs == this)
|
if (&rhs == this)
|
||||||
return *this;
|
return *this;
|
||||||
|
|
||||||
logicalDeviceHdl = rhs.logicalDeviceHdl;
|
renderGraphStorage = rhs.renderGraphStorage;
|
||||||
swapchainHdl = rhs.swapchainHdl;
|
|
||||||
nodeIndexing = std::move(rhs.nodeIndexing);
|
nodeIndexing = std::move(rhs.nodeIndexing);
|
||||||
nodes = std::move(rhs.nodes);
|
nodes = std::move(rhs.nodes);
|
||||||
graphResources = std::move(rhs.graphResources);
|
|
||||||
resourceManager = std::move(rhs.resourceManager);
|
resourceManager = std::move(rhs.resourceManager);
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
|
@ -426,12 +437,12 @@ namespace SHADE
|
||||||
for (auto const& instruction : resourceInstruction)
|
for (auto const& instruction : resourceInstruction)
|
||||||
{
|
{
|
||||||
// If the resource that the new node is requesting for exists, allow the graph to reference it
|
// If the resource that the new node is requesting for exists, allow the graph to reference it
|
||||||
if (graphResources.contains(instruction.resourceName))
|
if (renderGraphStorage->graphResources->contains(instruction.resourceName))
|
||||||
{
|
{
|
||||||
descInitParams.push_back(
|
descInitParams.push_back(
|
||||||
{
|
{
|
||||||
.resourceHdl = graphResources.at(instruction.resourceName),
|
.resourceHdl = renderGraphStorage->graphResources->at(instruction.resourceName),
|
||||||
.dontClearOnLoad = false,
|
.dontClearOnLoad = instruction.dontClearOnLoad,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -456,7 +467,7 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nodes.emplace_back(resourceManager->Create<SHRenderGraphNode>(resourceManager, logicalDeviceHdl, swapchainHdl, std::move(descInitParams), std::move(predecessors), &graphResources));
|
nodes.emplace_back(resourceManager->Create<SHRenderGraphNode>(renderGraphStorage, std::move(descInitParams), std::move(predecessors)));
|
||||||
nodeIndexing.emplace(nodeName, static_cast<uint32_t>(nodes.size()) - 1u);
|
nodeIndexing.emplace(nodeName, static_cast<uint32_t>(nodes.size()) - 1u);
|
||||||
return nodes.at(nodeIndexing[nodeName]);
|
return nodes.at(nodeIndexing[nodeName]);
|
||||||
}
|
}
|
||||||
|
@ -476,12 +487,31 @@ namespace SHADE
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
void SHRenderGraph::Generate(void) noexcept
|
void SHRenderGraph::Generate(void) noexcept
|
||||||
{
|
{
|
||||||
|
CheckForNodeComputes();
|
||||||
ConfigureAttachmentDescriptions();
|
ConfigureAttachmentDescriptions();
|
||||||
ConfigureSubpasses();
|
ConfigureSubpasses();
|
||||||
ConfigureRenderpasses();
|
ConfigureRenderpasses();
|
||||||
ConfigureFramebuffers();
|
ConfigureFramebuffers();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/***************************************************************************/
|
||||||
|
/*!
|
||||||
|
|
||||||
|
\brief
|
||||||
|
This function goes through all renderpasses and checks for existence of
|
||||||
|
node computes. If they exist, adds dummy subpasses to transition resources
|
||||||
|
into general.
|
||||||
|
|
||||||
|
*/
|
||||||
|
/***************************************************************************/
|
||||||
|
void SHRenderGraph::CheckForNodeComputes(void) noexcept
|
||||||
|
{
|
||||||
|
for (auto& node : nodes)
|
||||||
|
{
|
||||||
|
node->AddDummySubpassIfNeeded();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: The graph scope buffers were meant to bind vertex buffers and index buffers for meshes. Find a
|
// TODO: The graph scope buffers were meant to bind vertex buffers and index buffers for meshes. Find a
|
||||||
// better way to manage these
|
// better way to manage these
|
||||||
void SHRenderGraph::Execute(uint32_t frameIndex, Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHVkDescriptorPool> descPool) noexcept
|
void SHRenderGraph::Execute(uint32_t frameIndex, Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHVkDescriptorPool> descPool) noexcept
|
||||||
|
@ -501,7 +531,7 @@ namespace SHADE
|
||||||
void SHRenderGraph::HandleResize(uint32_t newWidth, uint32_t newHeight) noexcept
|
void SHRenderGraph::HandleResize(uint32_t newWidth, uint32_t newHeight) noexcept
|
||||||
{
|
{
|
||||||
// resize resources
|
// resize resources
|
||||||
for (auto& [name, resource]: graphResources)
|
for (auto& [name, resource] : *renderGraphStorage->graphResources)
|
||||||
resource->HandleResize(newWidth, newHeight);
|
resource->HandleResize(newWidth, newHeight);
|
||||||
|
|
||||||
for (auto& node : nodes)
|
for (auto& node : nodes)
|
||||||
|
@ -521,9 +551,9 @@ namespace SHADE
|
||||||
|
|
||||||
Handle<SHRenderGraphResource> SHRenderGraph::GetRenderGraphResource(std::string const& resourceName) const noexcept
|
Handle<SHRenderGraphResource> SHRenderGraph::GetRenderGraphResource(std::string const& resourceName) const noexcept
|
||||||
{
|
{
|
||||||
if (graphResources.contains(resourceName))
|
if (renderGraphStorage->graphResources->contains(resourceName))
|
||||||
{
|
{
|
||||||
return graphResources.at(resourceName);
|
return renderGraphStorage->graphResources->at(resourceName);
|
||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,8 @@ namespace SHADE
|
||||||
class SHVkCommandBuffer;
|
class SHVkCommandBuffer;
|
||||||
class SHRenderGraphNode;
|
class SHRenderGraphNode;
|
||||||
class SHGraphicsGlobalData;
|
class SHGraphicsGlobalData;
|
||||||
|
class SHVkDescriptorPool;
|
||||||
|
class SHRenderGraphStorage;
|
||||||
|
|
||||||
class SH_API SHRenderGraph
|
class SH_API SHRenderGraph
|
||||||
{
|
{
|
||||||
|
@ -56,10 +57,8 @@ namespace SHADE
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
/* PRIVATE MEMBER VARIABLES */
|
/* PRIVATE MEMBER VARIABLES */
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
Handle<SHVkLogicalDevice> logicalDeviceHdl;
|
|
||||||
|
|
||||||
//! swapchain used for querying image count
|
Handle<SHRenderGraphStorage> renderGraphStorage;
|
||||||
Handle<SHVkSwapchain> swapchainHdl;
|
|
||||||
|
|
||||||
//! For indexing render graph node container
|
//! For indexing render graph node container
|
||||||
std::map<std::string, uint32_t> nodeIndexing;
|
std::map<std::string, uint32_t> nodeIndexing;
|
||||||
|
@ -67,9 +66,6 @@ namespace SHADE
|
||||||
//! Render graph nodes
|
//! Render graph nodes
|
||||||
std::vector<Handle<SHRenderGraphNode>> nodes;
|
std::vector<Handle<SHRenderGraphNode>> nodes;
|
||||||
|
|
||||||
//! Resources that exist for the entire render graph
|
|
||||||
std::unordered_map<std::string, Handle<SHRenderGraphResource>> graphResources;
|
|
||||||
|
|
||||||
//! Resource library for graph handles
|
//! Resource library for graph handles
|
||||||
std::shared_ptr<SHResourceHub> resourceManager;
|
std::shared_ptr<SHResourceHub> resourceManager;
|
||||||
|
|
||||||
|
@ -85,14 +81,15 @@ namespace SHADE
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
/* PUBLIC MEMBER FUNCTIONS */
|
/* PUBLIC MEMBER FUNCTIONS */
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
void Init (Handle<SHVkLogicalDevice> const& logicalDevice, Handle<SHVkSwapchain> const& swapchain) noexcept;
|
void Init (Handle<SHVkLogicalDevice> logicalDevice, Handle<SHVkSwapchain> swapchain) noexcept;
|
||||||
void AddResource(std::string resourceName, std::initializer_list<SH_ATT_DESC_TYPE_FLAGS> typeFlags, uint32_t w = static_cast<uint32_t>(-1), uint32_t h = static_cast<uint32_t>(-1), vk::Format format = vk::Format::eB8G8R8A8Unorm, uint8_t levels = 1, vk::ImageUsageFlagBits usageFlags = {}, vk::ImageCreateFlagBits createFlags = {});
|
void AddResource(std::string resourceName, std::initializer_list<SH_ATT_DESC_TYPE_FLAGS> typeFlags, uint32_t w = static_cast<uint32_t>(-1), uint32_t h = static_cast<uint32_t>(-1), vk::Format format = vk::Format::eB8G8R8A8Unorm, uint8_t levels = 1, vk::ImageUsageFlagBits usageFlags = {}, vk::ImageCreateFlagBits createFlags = {});
|
||||||
Handle<SHRenderGraphNode> AddNode (std::string nodeName, std::initializer_list<ResourceInstruction> resourceInstruction, std::initializer_list<std::string> predecessorNodes) noexcept;
|
Handle<SHRenderGraphNode> AddNode (std::string nodeName, std::initializer_list<ResourceInstruction> resourceInstruction, std::initializer_list<std::string> predecessorNodes) noexcept;
|
||||||
|
|
||||||
void Generate (void) noexcept;
|
void Generate (void) noexcept;
|
||||||
void Execute (uint32_t frameIndex, Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHVkDescriptorPool> descPool) noexcept;
|
void CheckForNodeComputes (void) noexcept;
|
||||||
void FinaliseBatch(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool);
|
void Execute (uint32_t frameIndex, Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHVkDescriptorPool> descPool) noexcept;
|
||||||
void HandleResize (uint32_t newWidth, uint32_t newHeight) noexcept;
|
void FinaliseBatch (uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool);
|
||||||
|
void HandleResize (uint32_t newWidth, uint32_t newHeight) noexcept;
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
/* SETTERS AND GETTERS */
|
/* SETTERS AND GETTERS */
|
||||||
|
|
|
@ -6,6 +6,9 @@
|
||||||
#include "Graphics/Framebuffer/SHVkFramebuffer.h"
|
#include "Graphics/Framebuffer/SHVkFramebuffer.h"
|
||||||
#include "SHRenderGraphResource.h"
|
#include "SHRenderGraphResource.h"
|
||||||
#include "SHSubpass.h"
|
#include "SHSubpass.h"
|
||||||
|
#include "SHRenderGraphStorage.h"
|
||||||
|
#include "Graphics/RenderGraph/SHRenderGraphNodeCompute.h"
|
||||||
|
#include "Graphics/SHVkUtil.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
@ -21,7 +24,7 @@ namespace SHADE
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
void SHRenderGraphNode::CreateRenderpass(void) noexcept
|
void SHRenderGraphNode::CreateRenderpass(void) noexcept
|
||||||
{
|
{
|
||||||
renderpass = logicalDeviceHdl->CreateRenderpass(attachmentDescriptions, spDescs, spDeps);
|
renderpass = graphStorage->logicalDevice->CreateRenderpass(attachmentDescriptions, spDescs, spDeps);
|
||||||
}
|
}
|
||||||
|
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
|
@ -53,7 +56,7 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
framebuffers[i] = logicalDeviceHdl->CreateFramebuffer(renderpass, imageViews, fbWidth, fbHeight);
|
framebuffers[i] = graphStorage->logicalDevice->CreateFramebuffer(renderpass, imageViews, fbWidth, fbHeight);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,9 +82,18 @@ namespace SHADE
|
||||||
fbHeight = attResources[j]->height;
|
fbHeight = attResources[j]->height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
framebuffers[i]->HandleResize(renderpass, imageViews, fbWidth, fbHeight);
|
framebuffers[i]->HandleResize(renderpass, imageViews, fbWidth, fbHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (auto& subpass : subpasses)
|
||||||
|
{
|
||||||
|
subpass->HandleResize();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& nodeCompute : nodeComputes)
|
||||||
|
{
|
||||||
|
nodeCompute->HandleResize();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
|
@ -104,8 +116,8 @@ namespace SHADE
|
||||||
|
|
||||||
*/
|
*/
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
SHRenderGraphNode::SHRenderGraphNode(std::shared_ptr<SHResourceHub> rm, Handle<SHVkLogicalDevice> const& logicalDevice, Handle<SHVkSwapchain> const& swapchain, std::vector<SHAttachmentDescInitParams> attDescInitParams, std::vector<Handle<SHRenderGraphNode>> predecessors, std::unordered_map<std::string, Handle<SHRenderGraphResource>> const* resources) noexcept
|
SHRenderGraphNode::SHRenderGraphNode(Handle<SHRenderGraphStorage> renderGraphStorage, std::vector<SHAttachmentDescInitParams> attDescInitParams, std::vector<Handle<SHRenderGraphNode>> predecessors) noexcept
|
||||||
: logicalDeviceHdl{ logicalDevice }
|
: graphStorage{ renderGraphStorage}
|
||||||
, renderpass{}
|
, renderpass{}
|
||||||
, framebuffers{}
|
, framebuffers{}
|
||||||
, prereqNodes{ std::move(predecessors) }
|
, prereqNodes{ std::move(predecessors) }
|
||||||
|
@ -115,11 +127,10 @@ namespace SHADE
|
||||||
, subpasses{}
|
, subpasses{}
|
||||||
, executed{ false }
|
, executed{ false }
|
||||||
, configured{ false }
|
, configured{ false }
|
||||||
, resourceManager{ rm }
|
, nodeComputes{}
|
||||||
, ptrToResources{ resources }
|
|
||||||
{
|
{
|
||||||
// pipeline library initialization
|
// pipeline library initialization
|
||||||
pipelineLibrary.Init(logicalDeviceHdl);
|
pipelineLibrary.Init(graphStorage->logicalDevice);
|
||||||
|
|
||||||
// Store all the handles to resources
|
// Store all the handles to resources
|
||||||
attResources.reserve (attDescInitParams.size());
|
attResources.reserve (attDescInitParams.size());
|
||||||
|
@ -155,15 +166,14 @@ namespace SHADE
|
||||||
if (!containsSwapchainImage)
|
if (!containsSwapchainImage)
|
||||||
framebuffers.resize(1);
|
framebuffers.resize(1);
|
||||||
else
|
else
|
||||||
framebuffers.resize(swapchain->GetNumImages());
|
framebuffers.resize(graphStorage->swapchain->GetNumImages());
|
||||||
|
|
||||||
// At this point, we could configure framebuffers if we had the renderpass object but we don't so their creation has to be
|
// At this point, we could configure framebuffers if we had the renderpass object but we don't so their creation has to be
|
||||||
// deferred to when renderpasses are also created.
|
// deferred to when renderpasses are also created.
|
||||||
}
|
}
|
||||||
|
|
||||||
SHRenderGraphNode::SHRenderGraphNode(SHRenderGraphNode&& rhs) noexcept
|
SHRenderGraphNode::SHRenderGraphNode(SHRenderGraphNode&& rhs) noexcept
|
||||||
: resourceManager{ std::move (rhs.resourceManager) }
|
: graphStorage{ rhs.graphStorage}
|
||||||
, logicalDeviceHdl{ rhs.logicalDeviceHdl }
|
|
||||||
, renderpass{ rhs.renderpass }
|
, renderpass{ rhs.renderpass }
|
||||||
, framebuffers{ std::move(rhs.framebuffers) }
|
, framebuffers{ std::move(rhs.framebuffers) }
|
||||||
, prereqNodes{ std::move(rhs.prereqNodes) }
|
, prereqNodes{ std::move(rhs.prereqNodes) }
|
||||||
|
@ -174,11 +184,11 @@ namespace SHADE
|
||||||
, subpassIndexing{ std::move(rhs.subpassIndexing) }
|
, subpassIndexing{ std::move(rhs.subpassIndexing) }
|
||||||
, configured{ rhs.configured }
|
, configured{ rhs.configured }
|
||||||
, executed{ rhs.executed }
|
, executed{ rhs.executed }
|
||||||
, ptrToResources{ rhs.ptrToResources }
|
|
||||||
, pipelineLibrary{ std::move(rhs.pipelineLibrary) }
|
, pipelineLibrary{ std::move(rhs.pipelineLibrary) }
|
||||||
, batcher{ std::move(rhs.batcher) }
|
, batcher{ std::move(rhs.batcher) }
|
||||||
, spDescs{ std::move(rhs.spDescs) }
|
, spDescs{ std::move(rhs.spDescs) }
|
||||||
, spDeps{ std::move(rhs.spDeps) }
|
, spDeps{ std::move(rhs.spDeps) }
|
||||||
|
, nodeComputes{ std::move(rhs.nodeComputes) }
|
||||||
|
|
||||||
{
|
{
|
||||||
rhs.renderpass = {};
|
rhs.renderpass = {};
|
||||||
|
@ -189,8 +199,7 @@ namespace SHADE
|
||||||
if (&rhs == this)
|
if (&rhs == this)
|
||||||
return *this;
|
return *this;
|
||||||
|
|
||||||
resourceManager = std::move(rhs.resourceManager);
|
graphStorage = rhs.graphStorage;
|
||||||
logicalDeviceHdl = rhs.logicalDeviceHdl;
|
|
||||||
renderpass = rhs.renderpass;
|
renderpass = rhs.renderpass;
|
||||||
framebuffers = std::move(rhs.framebuffers);
|
framebuffers = std::move(rhs.framebuffers);
|
||||||
prereqNodes = std::move(rhs.prereqNodes);
|
prereqNodes = std::move(rhs.prereqNodes);
|
||||||
|
@ -199,11 +208,11 @@ namespace SHADE
|
||||||
subpasses = std::move(rhs.subpasses);
|
subpasses = std::move(rhs.subpasses);
|
||||||
resourceAttachmentMapping = std::move(rhs.resourceAttachmentMapping);
|
resourceAttachmentMapping = std::move(rhs.resourceAttachmentMapping);
|
||||||
subpassIndexing = std::move(rhs.subpassIndexing);
|
subpassIndexing = std::move(rhs.subpassIndexing);
|
||||||
ptrToResources = std::move(rhs.ptrToResources);
|
|
||||||
pipelineLibrary = std::move(rhs.pipelineLibrary);
|
pipelineLibrary = std::move(rhs.pipelineLibrary);
|
||||||
batcher = std::move(rhs.batcher);
|
batcher = std::move(rhs.batcher);
|
||||||
spDescs = std::move(rhs.spDescs);
|
spDescs = std::move(rhs.spDescs);
|
||||||
spDeps = std::move(rhs.spDeps);
|
spDeps = std::move(rhs.spDeps);
|
||||||
|
nodeComputes = std::move(rhs.nodeComputes);
|
||||||
|
|
||||||
|
|
||||||
rhs.renderpass = {};
|
rhs.renderpass = {};
|
||||||
|
@ -235,10 +244,10 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add subpass to container and create mapping for it
|
// Add subpass to container and create mapping for it
|
||||||
subpasses.emplace_back(resourceManager->Create<SHSubpass>(GetHandle(), subpasses.size(), &resourceAttachmentMapping, ptrToResources));
|
subpasses.emplace_back(graphStorage->resourceManager->Create<SHSubpass>(graphStorage, GetHandle(), static_cast<uint32_t>(subpasses.size()), &resourceAttachmentMapping));
|
||||||
subpassIndexing.try_emplace(subpassName, static_cast<uint32_t>(subpasses.size()) - 1u);
|
subpassIndexing.try_emplace(subpassName, static_cast<uint32_t>(subpasses.size()) - 1u);
|
||||||
Handle<SHSubpass> subpass = subpasses.back();
|
Handle<SHSubpass> subpass = subpasses.back();
|
||||||
subpass->Init(*resourceManager);
|
subpass->Init(*graphStorage->resourceManager);
|
||||||
|
|
||||||
// Register the SuperBatch
|
// Register the SuperBatch
|
||||||
batcher.RegisterSuperBatch(subpass->GetSuperBatch());
|
batcher.RegisterSuperBatch(subpass->GetSuperBatch());
|
||||||
|
@ -246,21 +255,84 @@ namespace SHADE
|
||||||
return subpass;
|
return subpass;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Handle<SHRenderGraphNodeCompute> SHRenderGraphNode::AddNodeCompute(Handle<SHVkShaderModule> computeShaderModule, std::initializer_list<std::string> resources, float numWorkGroupScale/* = 1.0f*/) noexcept
|
||||||
|
{
|
||||||
|
// Look for the required resources in the graph
|
||||||
|
std::vector<Handle<SHRenderGraphResource>> nodeComputeResources{};
|
||||||
|
nodeComputeResources.reserve(resources.size());
|
||||||
|
|
||||||
|
for (auto& resourceName : resources)
|
||||||
|
{
|
||||||
|
auto resource = graphStorage->graphResources->at(resourceName);
|
||||||
|
nodeComputeResources.push_back(resource);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the subpass compute with the resources
|
||||||
|
auto nodeCompute = graphStorage->resourceManager->Create<SHRenderGraphNodeCompute>(graphStorage, computeShaderModule, std::move(nodeComputeResources));
|
||||||
|
nodeComputes.push_back(nodeCompute);
|
||||||
|
|
||||||
|
return nodeCompute;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************************************/
|
||||||
|
/*!
|
||||||
|
|
||||||
|
\brief
|
||||||
|
This function checks all node computes and adds a subpass to transition
|
||||||
|
all needed resources to general.
|
||||||
|
|
||||||
|
*/
|
||||||
|
/***************************************************************************/
|
||||||
|
void SHRenderGraphNode::AddDummySubpassIfNeeded(void) noexcept
|
||||||
|
{
|
||||||
|
if (!nodeComputes.empty())
|
||||||
|
{
|
||||||
|
// we save the resource names involved
|
||||||
|
std::unordered_set<std::string> resourcesInvolved;
|
||||||
|
for (auto& compute : nodeComputes)
|
||||||
|
{
|
||||||
|
for (auto& resource : compute->resources)
|
||||||
|
{
|
||||||
|
resourcesInvolved.emplace(resource->GetName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// insert them all for a subpass to transition them. This subpass is the last subpass
|
||||||
|
auto dummySubpass = AddSubpass("dummy");
|
||||||
|
for (auto& resource : resourcesInvolved)
|
||||||
|
{
|
||||||
|
dummySubpass->AddGeneralInput(resource);
|
||||||
|
|
||||||
|
if (SHVkUtil::IsDepthStencilAttachment(graphStorage->graphResources->at(resource)->GetResourceFormat()))
|
||||||
|
dummySubpass->AddGeneralDepthOutput(resource);
|
||||||
|
else
|
||||||
|
dummySubpass->AddGeneralColorOutput(resource);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void SHRenderGraphNode::Execute(Handle<SHVkCommandBuffer>& commandBuffer, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) noexcept
|
void SHRenderGraphNode::Execute(Handle<SHVkCommandBuffer>& commandBuffer, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) noexcept
|
||||||
{
|
{
|
||||||
frameIndex = (framebuffers.size() > 1) ? frameIndex : 0;
|
uint32_t framebufferIndex = (framebuffers.size() > 1) ? frameIndex : 0;
|
||||||
commandBuffer->BeginRenderpass(renderpass, framebuffers[frameIndex]);
|
commandBuffer->BeginRenderpass(renderpass, framebuffers[framebufferIndex]);
|
||||||
|
|
||||||
for (uint32_t i = 0; i < subpasses.size(); ++i)
|
for (uint32_t i = 0; i < subpasses.size(); ++i)
|
||||||
{
|
{
|
||||||
subpasses[i]->Execute(commandBuffer, descPool, frameIndex);
|
subpasses[i]->Execute(commandBuffer, descPool, frameIndex);
|
||||||
|
|
||||||
// Go to next subpass if not last subpass
|
// Go to next subpass if not last subpass
|
||||||
if (i != subpasses.size() - 1)
|
if (i != static_cast<uint32_t>(subpasses.size()) - 1u)
|
||||||
commandBuffer->NextSubpass();
|
commandBuffer->NextSubpass();
|
||||||
}
|
}
|
||||||
|
|
||||||
commandBuffer->EndRenderpass();
|
commandBuffer->EndRenderpass();
|
||||||
|
|
||||||
|
|
||||||
|
// Execute all subpass computes
|
||||||
|
for (auto& sbCompute : nodeComputes)
|
||||||
|
{
|
||||||
|
sbCompute->Execute(commandBuffer, frameIndex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Handle<SHVkPipeline> SHRenderGraphNode::GetOrCreatePipeline(std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair, Handle<SHSubpass> subpass) noexcept
|
Handle<SHVkPipeline> SHRenderGraphNode::GetOrCreatePipeline(std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair, Handle<SHSubpass> subpass) noexcept
|
||||||
|
@ -273,10 +345,10 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Handle<SHVkPipeline> pipeline = pipelineLibrary.GetDrawPipline(vsFsPair);
|
Handle<SHVkPipeline> pipeline = pipelineLibrary.GetGraphicsPipeline(vsFsPair);
|
||||||
if (!pipeline)
|
if (!pipeline)
|
||||||
{
|
{
|
||||||
pipeline = pipelineLibrary.CreateDrawPipeline
|
pipeline = pipelineLibrary.CreateGraphicsPipelines
|
||||||
(
|
(
|
||||||
vsFsPair,
|
vsFsPair,
|
||||||
renderpass,
|
renderpass,
|
||||||
|
@ -289,7 +361,7 @@ namespace SHADE
|
||||||
|
|
||||||
void SHRenderGraphNode::FinaliseBatch(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool)
|
void SHRenderGraphNode::FinaliseBatch(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool)
|
||||||
{
|
{
|
||||||
batcher.FinaliseBatches(logicalDeviceHdl, descPool, frameIndex);
|
batcher.FinaliseBatches(graphStorage->logicalDevice, descPool, frameIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
|
|
|
@ -19,6 +19,9 @@ namespace SHADE
|
||||||
class SHVkLogicalDevice;
|
class SHVkLogicalDevice;
|
||||||
class SHVkRenderpass;
|
class SHVkRenderpass;
|
||||||
class SHVkDescriptorPool;
|
class SHVkDescriptorPool;
|
||||||
|
class SHGraphicsGlobalData;
|
||||||
|
class SHRenderGraphStorage;
|
||||||
|
class SHRenderGraphNodeCompute;
|
||||||
|
|
||||||
class SH_API SHRenderGraphNode : public ISelfHandle<SHRenderGraphNode>
|
class SH_API SHRenderGraphNode : public ISelfHandle<SHRenderGraphNode>
|
||||||
{
|
{
|
||||||
|
@ -26,10 +29,9 @@ namespace SHADE
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
/* PRIVATE MEMBER VARIABLES */
|
/* PRIVATE MEMBER VARIABLES */
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
std::shared_ptr<SHResourceHub> resourceManager;
|
|
||||||
|
|
||||||
//! For Vulkan object creation
|
//! For Vulkan object creation
|
||||||
Handle<SHVkLogicalDevice> logicalDeviceHdl;
|
//Handle<SHVkLogicalDevice> logicalDeviceHdl;
|
||||||
|
Handle<SHRenderGraphStorage> graphStorage;
|
||||||
|
|
||||||
//! Each node will have a renderpass and each renderpass will have its own subpasses.
|
//! Each node will have a renderpass and each renderpass will have its own subpasses.
|
||||||
//! These subpasses will execute sequentially.
|
//! These subpasses will execute sequentially.
|
||||||
|
@ -63,12 +65,13 @@ namespace SHADE
|
||||||
//! For indexing subpasses
|
//! For indexing subpasses
|
||||||
std::map<std::string, uint32_t> subpassIndexing;
|
std::map<std::string, uint32_t> subpassIndexing;
|
||||||
|
|
||||||
//! Pointer to resources in the render graph (for getting handle IDs)
|
|
||||||
std::unordered_map<std::string, Handle<SHRenderGraphResource>> const* ptrToResources;
|
|
||||||
|
|
||||||
//! Every renderpass will require a pipeline library that will contain pipelines compatible with this renderpass
|
//! Every renderpass will require a pipeline library that will contain pipelines compatible with this renderpass
|
||||||
SHPipelineLibrary pipelineLibrary;
|
SHPipelineLibrary pipelineLibrary;
|
||||||
|
|
||||||
|
//! Sometimes we want the subpass to do something to the images instead
|
||||||
|
//! of drawing objects on the image (i.e. compute).
|
||||||
|
std::vector<Handle<SHRenderGraphNodeCompute>> nodeComputes;
|
||||||
|
|
||||||
//! Whether or not the node has finished execution
|
//! Whether or not the node has finished execution
|
||||||
bool executed;
|
bool executed;
|
||||||
|
|
||||||
|
@ -77,6 +80,7 @@ namespace SHADE
|
||||||
|
|
||||||
SHBatcher batcher;
|
SHBatcher batcher;
|
||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
/* PRIVATE MEMBER FUNCTIONS */
|
/* PRIVATE MEMBER FUNCTIONS */
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
|
@ -88,7 +92,7 @@ namespace SHADE
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
/* CTORS AND DTORS */
|
/* CTORS AND DTORS */
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
SHRenderGraphNode(std::shared_ptr<SHResourceHub> rm, Handle<SHVkLogicalDevice> const& logicalDevice, Handle<SHVkSwapchain> const& swapchain, std::vector<SHAttachmentDescInitParams> attDescInitParams, std::vector<Handle<SHRenderGraphNode>> predecessors, std::unordered_map<std::string, Handle<SHRenderGraphResource>> const* resources) noexcept;
|
SHRenderGraphNode(Handle<SHRenderGraphStorage> renderGraphStorage, std::vector<SHAttachmentDescInitParams> attDescInitParams, std::vector<Handle<SHRenderGraphNode>> predecessors) noexcept;
|
||||||
SHRenderGraphNode(SHRenderGraphNode&& rhs) noexcept;
|
SHRenderGraphNode(SHRenderGraphNode&& rhs) noexcept;
|
||||||
SHRenderGraphNode& operator= (SHRenderGraphNode&& rhs) noexcept;
|
SHRenderGraphNode& operator= (SHRenderGraphNode&& rhs) noexcept;
|
||||||
|
|
||||||
|
@ -96,6 +100,9 @@ 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;
|
||||||
|
void AddDummySubpassIfNeeded (void) noexcept;
|
||||||
|
|
||||||
// TODO: RemoveSubpass()
|
// TODO: RemoveSubpass()
|
||||||
void Execute(Handle<SHVkCommandBuffer>& commandBuffer, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) noexcept;
|
void Execute(Handle<SHVkCommandBuffer>& commandBuffer, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) noexcept;
|
||||||
Handle<SHVkPipeline> GetOrCreatePipeline(std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair, Handle<SHSubpass> subpass) noexcept;
|
Handle<SHVkPipeline> GetOrCreatePipeline(std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair, Handle<SHSubpass> subpass) noexcept;
|
||||||
|
|
|
@ -0,0 +1,109 @@
|
||||||
|
#include "SHpch.h"
|
||||||
|
#include "SHRenderGraphNodeCompute.h"
|
||||||
|
#include "Graphics/Pipeline/SHVkPipeline.h"
|
||||||
|
#include "Graphics/Descriptors/SHVkDescriptorSetGroup.h"
|
||||||
|
#include "Graphics/Descriptors/SHVkDescriptorPool.h"
|
||||||
|
#include "Graphics/Descriptors/SHVkDescriptorSetLayout.h"
|
||||||
|
#include "Graphics/Devices/SHVkLogicalDevice.h"
|
||||||
|
#include "Graphics/Pipeline/SHVkPipelineLayout.h"
|
||||||
|
#include "Graphics/MiddleEnd/GlobalData/SHGraphicsGlobalData.h"
|
||||||
|
#include "SHRenderGraphStorage.h"
|
||||||
|
#include "SHRenderGraphResource.h"
|
||||||
|
#include "Graphics/Commands/SHVkCommandBuffer.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
SHRenderGraphNodeCompute::SHRenderGraphNodeCompute(Handle<SHRenderGraphStorage> graphStorage, Handle<SHVkShaderModule> computeShaderModule, std::vector<Handle<SHRenderGraphResource>>&& subpassComputeResources, float inNumWorkGroupScale/* = 1.0f*/) noexcept
|
||||||
|
: computePipeline{}
|
||||||
|
, pipelineLayout{}
|
||||||
|
, resources{}
|
||||||
|
, groupSizeX{0}
|
||||||
|
, groupSizeY{0}
|
||||||
|
, numWorkGroupScale {std::clamp(inNumWorkGroupScale, 0.0f, 1.0f)}
|
||||||
|
{
|
||||||
|
SHPipelineLayoutParams pipelineLayoutParams
|
||||||
|
{
|
||||||
|
.shaderModules = {computeShaderModule},
|
||||||
|
.globalDescSetLayouts = SHGraphicsGlobalData::GetDescSetLayouts()
|
||||||
|
};
|
||||||
|
|
||||||
|
// Create pipeline layout from parameters
|
||||||
|
pipelineLayout = graphStorage->logicalDevice->CreatePipelineLayout (pipelineLayoutParams);
|
||||||
|
|
||||||
|
// Create the compute pipeline
|
||||||
|
computePipeline = graphStorage->logicalDevice->CreateComputePipeline(pipelineLayout);
|
||||||
|
|
||||||
|
// and construct it
|
||||||
|
computePipeline->ConstructPipeline();
|
||||||
|
|
||||||
|
// save the resources
|
||||||
|
resources = std::move (subpassComputeResources);
|
||||||
|
|
||||||
|
//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.
|
||||||
|
auto const& layouts = computePipeline->GetPipelineLayout()->GetDescriptorSetLayoutsAllocate();
|
||||||
|
|
||||||
|
//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)
|
||||||
|
for (uint32_t i = 0; i < SHGraphicsConstants::NUM_FRAME_BUFFERS; ++i)
|
||||||
|
{
|
||||||
|
descSetGroups[i] = graphStorage->descriptorPool->Allocate(layouts, variableCounts);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
HandleResize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHRenderGraphNodeCompute::Execute(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept
|
||||||
|
{
|
||||||
|
// bind the compute pipeline
|
||||||
|
cmdBuffer->BindPipeline(computePipeline);
|
||||||
|
|
||||||
|
// bind descriptor sets
|
||||||
|
cmdBuffer->BindDescriptorSet(descSetGroups[frameIndex], SH_PIPELINE_TYPE::COMPUTE, SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_RESOURCE, {});
|
||||||
|
|
||||||
|
// dispatch compute
|
||||||
|
cmdBuffer->ComputeDispatch(groupSizeX, groupSizeY, 1);
|
||||||
|
|
||||||
|
// TODO: barrier
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHRenderGraphNodeCompute::HandleResize(void) noexcept
|
||||||
|
{
|
||||||
|
// Get the layout for the render graph resource. We can index it this way because the container returned is a container of layouts that includes the global ones
|
||||||
|
auto pipelineDescSetLayouts = computePipeline->GetPipelineLayout()->GetDescriptorSetLayoutsPipeline()[SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_RESOURCE];
|
||||||
|
|
||||||
|
// everything below here needs resizing
|
||||||
|
for (uint32_t frameIndex = 0; frameIndex < SHGraphicsConstants::NUM_FRAME_BUFFERS; ++frameIndex)
|
||||||
|
{
|
||||||
|
uint32_t i = 0;
|
||||||
|
|
||||||
|
// loop through bindings and write descriptor sets
|
||||||
|
for (auto& binding : pipelineDescSetLayouts->GetBindings())
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
descSetGroups[frameIndex]->ModifyWriteDescImage(SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_RESOURCE, binding.BindPoint, { &vsl, 1 });
|
||||||
|
descSetGroups[frameIndex]->UpdateDescriptorSetImages(SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_RESOURCE, binding.BindPoint);
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the group size from the max width and height
|
||||||
|
uint32_t maxWidth = 0, maxHeight = 0;
|
||||||
|
for (auto& resource : resources)
|
||||||
|
{
|
||||||
|
maxWidth = std::max(resource->GetWidth(), maxWidth);
|
||||||
|
maxHeight = std::max(resource->GetHeight(), maxHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
groupSizeX = maxWidth / workGroupSizeX;
|
||||||
|
groupSizeY = maxHeight / workGroupSizeY;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Resource/SHHandle.h"
|
||||||
|
#include "Graphics/MiddleEnd/Interface/SHGraphicsConstants.h"
|
||||||
|
#include <initializer_list>
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
class SHVkPipeline;
|
||||||
|
class SHVkDescriptorSetGroup;
|
||||||
|
class SHVkDescriptorPool;
|
||||||
|
class SHVkLogicalDevice;
|
||||||
|
class SHVkPipelineLayout;
|
||||||
|
class SHRenderGraphStorage;
|
||||||
|
class SHRenderGraphResource;
|
||||||
|
class SHVkShaderModule;
|
||||||
|
class SHVkCommandBuffer;
|
||||||
|
|
||||||
|
class SHRenderGraphNodeCompute
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
static constexpr uint32_t workGroupSizeX = 16;
|
||||||
|
static constexpr uint32_t workGroupSizeY = 16;
|
||||||
|
|
||||||
|
//! To run the dispatch command
|
||||||
|
Handle<SHVkPipeline> computePipeline;
|
||||||
|
|
||||||
|
//! Pipeline layout for the pipeline creation
|
||||||
|
Handle<SHVkPipelineLayout> pipelineLayout;
|
||||||
|
|
||||||
|
//! Descriptor set group to hold the images for reading (STORAGE_IMAGE)
|
||||||
|
std::array<Handle<SHVkDescriptorSetGroup>, SHGraphicsConstants::NUM_FRAME_BUFFERS> descSetGroups;
|
||||||
|
|
||||||
|
//! vector of resources needed by the subpass compute
|
||||||
|
std::vector<Handle<SHRenderGraphResource>> resources;
|
||||||
|
|
||||||
|
//! X dimension work group size. Should scale with resource size.
|
||||||
|
uint32_t groupSizeX;
|
||||||
|
|
||||||
|
//! Y dimension work group size
|
||||||
|
uint32_t groupSizeY;
|
||||||
|
|
||||||
|
float numWorkGroupScale;
|
||||||
|
|
||||||
|
public:
|
||||||
|
SHRenderGraphNodeCompute(Handle<SHRenderGraphStorage> graphStorage, Handle<SHVkShaderModule> computeShaderModule, std::vector<Handle<SHRenderGraphResource>>&& subpassComputeResources, float inNumWorkGroupScale = 1.0f) noexcept;
|
||||||
|
|
||||||
|
void Execute (Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept;
|
||||||
|
void HandleResize (void) noexcept;
|
||||||
|
|
||||||
|
friend class SHRenderGraph;
|
||||||
|
friend class SHRenderGraphNode;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include "Graphics/Images/SHVkImageView.h"
|
#include "Graphics/Images/SHVkImageView.h"
|
||||||
#include "Graphics/Buffers/SHVkBuffer.h"
|
#include "Graphics/Buffers/SHVkBuffer.h"
|
||||||
#include "Graphics/SHVkUtil.h"
|
#include "Graphics/SHVkUtil.h"
|
||||||
|
#include "SHRenderGraphStorage.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
@ -45,9 +46,8 @@ namespace SHADE
|
||||||
|
|
||||||
*/
|
*/
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
SHRenderGraphResource::SHRenderGraphResource(Handle<SHVkLogicalDevice> const& logicalDevice, Handle<SHVkSwapchain> const& swapchain, std::string const& name, std::initializer_list<SH_ATT_DESC_TYPE_FLAGS> typeFlags, vk::Format format, uint32_t w, uint32_t h, uint8_t levels, vk::ImageUsageFlagBits usageFlags, vk::ImageCreateFlagBits createFlags) noexcept
|
SHRenderGraphResource::SHRenderGraphResource(Handle<SHRenderGraphStorage> renderGraphStorage, std::string const& name, std::initializer_list<SH_ATT_DESC_TYPE_FLAGS> typeFlags, vk::Format format, uint32_t w, uint32_t h, uint8_t levels, vk::ImageUsageFlagBits usageFlags, vk::ImageCreateFlagBits createFlags) noexcept
|
||||||
: logicalDevice {logicalDevice}
|
: graphStorage{renderGraphStorage}
|
||||||
, swapchain{ swapchain }
|
|
||||||
, resourceTypeFlags{ }
|
, resourceTypeFlags{ }
|
||||||
, resourceFormat{ format }
|
, resourceFormat{ format }
|
||||||
, images{}
|
, images{}
|
||||||
|
@ -66,7 +66,7 @@ namespace SHADE
|
||||||
SHImageViewDetails viewDetails
|
SHImageViewDetails viewDetails
|
||||||
{
|
{
|
||||||
.viewType = vk::ImageViewType::e2D,
|
.viewType = vk::ImageViewType::e2D,
|
||||||
.format = swapchain->GetSurfaceFormatKHR().format,
|
.format = graphStorage->swapchain->GetSurfaceFormatKHR().format,
|
||||||
.imageAspectFlags = vk::ImageAspectFlagBits::eColor,
|
.imageAspectFlags = vk::ImageAspectFlagBits::eColor,
|
||||||
.baseMipLevel = 0,
|
.baseMipLevel = 0,
|
||||||
.mipLevelCount = 1,
|
.mipLevelCount = 1,
|
||||||
|
@ -75,13 +75,13 @@ namespace SHADE
|
||||||
};
|
};
|
||||||
|
|
||||||
// We want an image handle for every swapchain image
|
// We want an image handle for every swapchain image
|
||||||
images.resize(swapchain->GetNumImages());
|
images.resize(graphStorage->swapchain->GetNumImages());
|
||||||
imageViews.resize(swapchain->GetNumImages());
|
imageViews.resize(graphStorage->swapchain->GetNumImages());
|
||||||
|
|
||||||
for (uint32_t i = 0; i < swapchain->GetNumImages(); ++i)
|
for (uint32_t i = 0; i < graphStorage->swapchain->GetNumImages(); ++i)
|
||||||
{
|
{
|
||||||
images[i] = swapchain->GetSwapchainImage(i);
|
images[i] = graphStorage->swapchain->GetSwapchainImage(i);
|
||||||
imageViews[i] = images[i]->CreateImageView(logicalDevice, images[i], viewDetails);
|
imageViews[i] = images[i]->CreateImageView(graphStorage->logicalDevice, images[i], viewDetails);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else // if swapchain image resource
|
else // if swapchain image resource
|
||||||
|
@ -117,6 +117,9 @@ namespace SHADE
|
||||||
usage |= vk::ImageUsageFlagBits::eInputAttachment;
|
usage |= vk::ImageUsageFlagBits::eInputAttachment;
|
||||||
usage |= vk::ImageUsageFlagBits::eSampled;
|
usage |= vk::ImageUsageFlagBits::eSampled;
|
||||||
break;
|
break;
|
||||||
|
case SH_ATT_DESC_TYPE_FLAGS::STORAGE:
|
||||||
|
usage |= vk::ImageUsageFlagBits::eStorage;
|
||||||
|
break;
|
||||||
case SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT:
|
case SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT:
|
||||||
{
|
{
|
||||||
SHLOG_ERROR ("COLOR_PRESENT cannot be with other resource type flags. ");
|
SHLOG_ERROR ("COLOR_PRESENT cannot be with other resource type flags. ");
|
||||||
|
@ -126,7 +129,7 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
|
|
||||||
// The resource is not a swapchain image, just use the first slot of the vector
|
// The resource is not a swapchain image, just use the first slot of the vector
|
||||||
images.push_back(logicalDevice->CreateImage(width, height, mipLevels, resourceFormat, usage, createFlags));
|
images.push_back(graphStorage->logicalDevice->CreateImage(width, height, mipLevels, resourceFormat, usage, createFlags));
|
||||||
|
|
||||||
// prepare image view details
|
// prepare image view details
|
||||||
SHImageViewDetails viewDetails
|
SHImageViewDetails viewDetails
|
||||||
|
@ -141,7 +144,7 @@ namespace SHADE
|
||||||
};
|
};
|
||||||
|
|
||||||
// just 1 image view created
|
// just 1 image view created
|
||||||
imageViews.push_back(images[0]->CreateImageView(logicalDevice, images[0], viewDetails));
|
imageViews.push_back(images[0]->CreateImageView(graphStorage->logicalDevice, images[0], viewDetails));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -166,7 +169,7 @@ namespace SHADE
|
||||||
, height{ rhs.height }
|
, height{ rhs.height }
|
||||||
, mipLevels{ rhs.mipLevels }
|
, mipLevels{ rhs.mipLevels }
|
||||||
, imageAspectFlags{ rhs.imageAspectFlags }
|
, imageAspectFlags{ rhs.imageAspectFlags }
|
||||||
, swapchain {rhs.swapchain}
|
, graphStorage{rhs.graphStorage}
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -198,7 +201,7 @@ namespace SHADE
|
||||||
height = rhs.height;
|
height = rhs.height;
|
||||||
mipLevels = rhs.mipLevels;
|
mipLevels = rhs.mipLevels;
|
||||||
imageAspectFlags = rhs.imageAspectFlags;
|
imageAspectFlags = rhs.imageAspectFlags;
|
||||||
swapchain = rhs.swapchain;
|
graphStorage = rhs.graphStorage;
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
@ -247,7 +250,7 @@ namespace SHADE
|
||||||
SHImageViewDetails viewDetails
|
SHImageViewDetails viewDetails
|
||||||
{
|
{
|
||||||
.viewType = vk::ImageViewType::e2D,
|
.viewType = vk::ImageViewType::e2D,
|
||||||
.format = swapchain->GetSurfaceFormatKHR().format,
|
.format = graphStorage->swapchain->GetSurfaceFormatKHR().format,
|
||||||
.imageAspectFlags = vk::ImageAspectFlagBits::eColor,
|
.imageAspectFlags = vk::ImageAspectFlagBits::eColor,
|
||||||
.baseMipLevel = 0,
|
.baseMipLevel = 0,
|
||||||
.mipLevelCount = 1,
|
.mipLevelCount = 1,
|
||||||
|
@ -255,9 +258,9 @@ namespace SHADE
|
||||||
.layerCount = 1,
|
.layerCount = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
for (uint32_t i = 0; i < swapchain->GetNumImages(); ++i)
|
for (uint32_t i = 0; i < graphStorage->swapchain->GetNumImages(); ++i)
|
||||||
{
|
{
|
||||||
images[i] = swapchain->GetSwapchainImage(i);
|
images[i] = graphStorage->swapchain->GetSwapchainImage(i);
|
||||||
imageViews[i]->ViewNewImage(images[i], viewDetails);
|
imageViews[i]->ViewNewImage(images[i], viewDetails);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -308,6 +311,7 @@ namespace SHADE
|
||||||
return resourceFormat;
|
return resourceFormat;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint32_t SHRenderGraphResource::GetWidth(void) const noexcept
|
uint32_t SHRenderGraphResource::GetWidth(void) const noexcept
|
||||||
{
|
{
|
||||||
return width;
|
return width;
|
||||||
|
@ -323,4 +327,19 @@ namespace SHADE
|
||||||
return imageViews [index];
|
return imageViews [index];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Handle<SHVkImage> SHRenderGraphResource::GetImage(uint32_t index /*= NON_SWAPCHAIN_RESOURCE_INDEX*/) const noexcept
|
||||||
|
{
|
||||||
|
return images[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t SHRenderGraphResource::GetMipLevels(void) const noexcept
|
||||||
|
{
|
||||||
|
return mipLevels;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string SHRenderGraphResource::GetName(void) const noexcept
|
||||||
|
{
|
||||||
|
return resourceName;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -15,6 +15,7 @@ namespace SHADE
|
||||||
class SHVkSwapchain;
|
class SHVkSwapchain;
|
||||||
class SHVkCommandBuffer;
|
class SHVkCommandBuffer;
|
||||||
class SHVkBuffer;
|
class SHVkBuffer;
|
||||||
|
class SHRenderGraphStorage;
|
||||||
|
|
||||||
static constexpr uint32_t NON_SWAPCHAIN_RESOURCE_INDEX = 0;
|
static constexpr uint32_t NON_SWAPCHAIN_RESOURCE_INDEX = 0;
|
||||||
|
|
||||||
|
@ -24,11 +25,8 @@ namespace SHADE
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
/* PRIVATE MEMBER VARIABLES */
|
/* PRIVATE MEMBER VARIABLES */
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
// for creation/recreation
|
//! Storage from the render graph
|
||||||
Handle<SHVkLogicalDevice> logicalDevice;
|
Handle<SHRenderGraphStorage> graphStorage;
|
||||||
|
|
||||||
// for creation/recreation
|
|
||||||
Handle<SHVkSwapchain> swapchain;
|
|
||||||
|
|
||||||
//! Name of the resource
|
//! Name of the resource
|
||||||
std::string resourceName;
|
std::string resourceName;
|
||||||
|
@ -69,7 +67,7 @@ namespace SHADE
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
/* CTORS AND DTORS */
|
/* CTORS AND DTORS */
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
SHRenderGraphResource(Handle<SHVkLogicalDevice> const& logicalDevice, Handle<SHVkSwapchain> const& swapchain, std::string const& name, std::initializer_list<SH_ATT_DESC_TYPE_FLAGS> typeFlags, vk::Format format, uint32_t w, uint32_t h, uint8_t levels, vk::ImageUsageFlagBits usageFlags, vk::ImageCreateFlagBits createFlags) noexcept;
|
SHRenderGraphResource(Handle<SHRenderGraphStorage> renderGraphStorage, std::string const& name, std::initializer_list<SH_ATT_DESC_TYPE_FLAGS> typeFlags, vk::Format format, uint32_t w, uint32_t h, uint8_t levels, vk::ImageUsageFlagBits usageFlags, vk::ImageCreateFlagBits createFlags) noexcept;
|
||||||
SHRenderGraphResource(SHRenderGraphResource&& rhs) noexcept;
|
SHRenderGraphResource(SHRenderGraphResource&& rhs) noexcept;
|
||||||
SHRenderGraphResource& operator=(SHRenderGraphResource&& rhs) noexcept;
|
SHRenderGraphResource& operator=(SHRenderGraphResource&& rhs) noexcept;
|
||||||
~SHRenderGraphResource(void) noexcept;
|
~SHRenderGraphResource(void) noexcept;
|
||||||
|
@ -84,12 +82,17 @@ namespace SHADE
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
/* SETTERS AND GETTERS */
|
/* SETTERS AND GETTERS */
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
vk::Format GetResourceFormat (void) const noexcept;
|
vk::Format GetResourceFormat (void) const noexcept;
|
||||||
uint32_t GetWidth (void) const noexcept;
|
uint32_t GetWidth (void) const noexcept;
|
||||||
uint32_t GetHeight (void) const noexcept;
|
uint32_t GetHeight (void) const noexcept;
|
||||||
Handle<SHVkImageView> GetImageView (uint32_t index = NON_SWAPCHAIN_RESOURCE_INDEX) const noexcept;
|
Handle<SHVkImageView> GetImageView (uint32_t index = NON_SWAPCHAIN_RESOURCE_INDEX) const noexcept;
|
||||||
|
Handle<SHVkImage> GetImage (uint32_t index = NON_SWAPCHAIN_RESOURCE_INDEX) const noexcept;
|
||||||
|
uint8_t GetMipLevels (void) const noexcept;
|
||||||
|
std::string GetName (void) const noexcept;
|
||||||
|
|
||||||
friend class SHRenderGraphNode;
|
friend class SHRenderGraphNode;
|
||||||
friend class SHRenderGraph;
|
friend class SHRenderGraph;
|
||||||
|
friend class SHSubpass;
|
||||||
|
friend class SHRenderGraphNodeCompute;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Resource/SHHandle.h"
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
class SHVkLogicalDevice;
|
||||||
|
class SHVkSwapchain;
|
||||||
|
class SHGraphicsGlobalData;
|
||||||
|
class SHVkDescriptorPool;
|
||||||
|
class SHRenderGraphResource;
|
||||||
|
|
||||||
|
class SHRenderGraphStorage
|
||||||
|
{
|
||||||
|
//! Logical device for creation of vulkan objects
|
||||||
|
Handle<SHVkLogicalDevice> logicalDevice;
|
||||||
|
|
||||||
|
//! swapchain handle
|
||||||
|
Handle<SHVkSwapchain> swapchain;
|
||||||
|
|
||||||
|
//! Resource manager for creation of objects
|
||||||
|
std::shared_ptr<SHResourceHub> resourceManager;
|
||||||
|
|
||||||
|
//! Descriptor pool for the descriptor sets to be created in the subpasses
|
||||||
|
Handle<SHVkDescriptorPool> descriptorPool;
|
||||||
|
|
||||||
|
//! For accessing resources anywhere in the graph
|
||||||
|
Handle<std::unordered_map<std::string, Handle<SHRenderGraphResource>>> graphResources;
|
||||||
|
|
||||||
|
//SHRenderGraphStorage(void) noexcept;
|
||||||
|
//SHRenderGraphStorage(SHRenderGraphStorage&& rhs) noexcept;
|
||||||
|
//SHRenderGraphStorage& operator=(SHRenderGraphStorage&& rhs) noexcept;
|
||||||
|
|
||||||
|
friend class SHRenderGraph;
|
||||||
|
friend class SHRenderGraphNode;
|
||||||
|
friend class SHSubpass;
|
||||||
|
friend class SHRenderGraphResource;
|
||||||
|
friend class SHRenderGraphNodeCompute;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -4,6 +4,13 @@
|
||||||
#include "Graphics/Devices/SHVkLogicalDevice.h"
|
#include "Graphics/Devices/SHVkLogicalDevice.h"
|
||||||
#include "SHRenderGraphNode.h"
|
#include "SHRenderGraphNode.h"
|
||||||
#include "SHRenderGraphResource.h"
|
#include "SHRenderGraphResource.h"
|
||||||
|
#include "Graphics/Shaders/SHVkShaderModule.h"
|
||||||
|
#include "SHRenderGraphNode.h"
|
||||||
|
#include "SHRenderGraphStorage.h"
|
||||||
|
#include "Graphics/Descriptors/SHVkDescriptorSetGroup.h"
|
||||||
|
#include "Graphics/Swapchain/SHVkSwapchain.h"
|
||||||
|
#include "Graphics/Images/SHVkSampler.h"
|
||||||
|
#include "SHRenderGraphResource.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
@ -23,15 +30,16 @@ namespace SHADE
|
||||||
|
|
||||||
*/
|
*/
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
SHSubpass::SHSubpass(Handle<SHRenderGraphNode> const& parent, uint32_t index, std::unordered_map<uint64_t, uint32_t> const* mapping, std::unordered_map<std::string, Handle<SHRenderGraphResource>> const* resources) noexcept
|
SHSubpass::SHSubpass(Handle<SHRenderGraphStorage> renderGraphStorage, Handle<SHRenderGraphNode> const& parent, uint32_t index, std::unordered_map<uint64_t, uint32_t> const* mapping) noexcept
|
||||||
: resourceAttachmentMapping{ mapping }
|
: resourceAttachmentMapping{ mapping }
|
||||||
, ptrToResources{ resources }
|
|
||||||
, parentNode{ parent }
|
, parentNode{ parent }
|
||||||
, subpassIndex{ index }
|
, subpassIndex{ index }
|
||||||
, superBatch{}
|
, superBatch{}
|
||||||
, colorReferences{}
|
, colorReferences{}
|
||||||
, depthReferences{}
|
, depthReferences{}
|
||||||
, inputReferences{}
|
, inputReferences{}
|
||||||
|
, graphStorage{ renderGraphStorage }
|
||||||
|
, inputImageDescriptors {SHGraphicsConstants::NUM_FRAME_BUFFERS}
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,9 +62,14 @@ namespace SHADE
|
||||||
, depthReferences{ std::move(rhs.depthReferences) }
|
, depthReferences{ std::move(rhs.depthReferences) }
|
||||||
, inputReferences{ std::move(rhs.inputReferences) }
|
, inputReferences{ std::move(rhs.inputReferences) }
|
||||||
, resourceAttachmentMapping{ rhs.resourceAttachmentMapping }
|
, resourceAttachmentMapping{ rhs.resourceAttachmentMapping }
|
||||||
, ptrToResources{ rhs.ptrToResources }
|
|
||||||
, descriptorSetLayout{ rhs.descriptorSetLayout }
|
, descriptorSetLayout{ rhs.descriptorSetLayout }
|
||||||
, exteriorDrawCalls{ std::move (rhs.exteriorDrawCalls) }
|
, exteriorDrawCalls{ std::move(rhs.exteriorDrawCalls) }
|
||||||
|
, graphStorage{ rhs.graphStorage }
|
||||||
|
, inputNames{ std::move(rhs.inputNames) }
|
||||||
|
, inputImageDescriptors{ std::move(rhs.inputImageDescriptors) }
|
||||||
|
, inputDescriptorLayout{ rhs.inputDescriptorLayout }
|
||||||
|
, inputSamplers{ rhs.inputSamplers }
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -84,9 +97,13 @@ namespace SHADE
|
||||||
depthReferences = std::move(rhs.depthReferences);
|
depthReferences = std::move(rhs.depthReferences);
|
||||||
inputReferences = std::move(rhs.inputReferences);
|
inputReferences = std::move(rhs.inputReferences);
|
||||||
resourceAttachmentMapping = rhs.resourceAttachmentMapping;
|
resourceAttachmentMapping = rhs.resourceAttachmentMapping;
|
||||||
ptrToResources = rhs.ptrToResources;
|
|
||||||
descriptorSetLayout = rhs.descriptorSetLayout;
|
descriptorSetLayout = rhs.descriptorSetLayout;
|
||||||
exteriorDrawCalls = std::move(rhs.exteriorDrawCalls);
|
exteriorDrawCalls = std::move(rhs.exteriorDrawCalls);
|
||||||
|
graphStorage = rhs.graphStorage;
|
||||||
|
inputNames = std::move(rhs.inputNames);
|
||||||
|
inputImageDescriptors = std::move(rhs.inputImageDescriptors);
|
||||||
|
inputDescriptorLayout = rhs.inputDescriptorLayout;
|
||||||
|
inputSamplers = rhs.inputSamplers;
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
@ -105,7 +122,12 @@ namespace SHADE
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
void SHSubpass::AddColorOutput(std::string resourceToReference) noexcept
|
void SHSubpass::AddColorOutput(std::string resourceToReference) noexcept
|
||||||
{
|
{
|
||||||
colorReferences.push_back({ resourceAttachmentMapping->at(ptrToResources->at(resourceToReference).GetId().Raw), vk::ImageLayout::eColorAttachmentOptimal });
|
colorReferences.push_back({ resourceAttachmentMapping->at(graphStorage->graphResources->at(resourceToReference).GetId().Raw), vk::ImageLayout::eColorAttachmentOptimal });
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHSubpass::AddGeneralColorOutput(std::string resourceToReference) noexcept
|
||||||
|
{
|
||||||
|
colorReferences.push_back({ resourceAttachmentMapping->at(graphStorage->graphResources->at(resourceToReference).GetId().Raw), vk::ImageLayout::eGeneral });
|
||||||
}
|
}
|
||||||
|
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
|
@ -142,7 +164,13 @@ namespace SHADE
|
||||||
//Invalid
|
//Invalid
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
depthReferences.push_back({ resourceAttachmentMapping->at(ptrToResources->at(resourceToReference).GetId().Raw), imageLayout });
|
depthReferences.push_back({ resourceAttachmentMapping->at(graphStorage->graphResources->at(resourceToReference).GetId().Raw), imageLayout });
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHSubpass::AddGeneralDepthOutput(std::string resourceToReference) noexcept
|
||||||
|
{
|
||||||
|
depthReferences.push_back({ resourceAttachmentMapping->at(graphStorage->graphResources->at(resourceToReference).GetId().Raw), vk::ImageLayout::eGeneral });
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
|
@ -159,7 +187,14 @@ namespace SHADE
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
void SHSubpass::AddInput(std::string resourceToReference) noexcept
|
void SHSubpass::AddInput(std::string resourceToReference) noexcept
|
||||||
{
|
{
|
||||||
inputReferences.push_back({ resourceAttachmentMapping->at(ptrToResources->at(resourceToReference).GetId().Raw), vk::ImageLayout::eShaderReadOnlyOptimal });
|
inputReferences.push_back({ resourceAttachmentMapping->at(graphStorage->graphResources->at(resourceToReference).GetId().Raw), vk::ImageLayout::eShaderReadOnlyOptimal });
|
||||||
|
|
||||||
|
inputNames.push_back(resourceToReference);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHSubpass::AddGeneralInput(std::string resourceToReference) noexcept
|
||||||
|
{
|
||||||
|
inputReferences.push_back({ resourceAttachmentMapping->at(graphStorage->graphResources->at(resourceToReference).GetId().Raw), vk::ImageLayout::eGeneral });
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHSubpass::Execute(Handle<SHVkCommandBuffer>& commandBuffer, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) noexcept
|
void SHSubpass::Execute(Handle<SHVkCommandBuffer>& commandBuffer, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) noexcept
|
||||||
|
@ -175,6 +210,12 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
drawCall(commandBuffer);
|
drawCall(commandBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHSubpass::HandleResize(void) noexcept
|
||||||
|
{
|
||||||
|
UpdateWriteDescriptors();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHSubpass::AddExteriorDrawCalls(std::function<void(Handle<SHVkCommandBuffer>&)> const& newDrawCall) noexcept
|
void SHSubpass::AddExteriorDrawCalls(std::function<void(Handle<SHVkCommandBuffer>&)> const& newDrawCall) noexcept
|
||||||
|
@ -188,6 +229,152 @@ namespace SHADE
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SHSubpass::CreateInputDescriptors(void) noexcept
|
||||||
|
{
|
||||||
|
if (inputNames.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
std::vector<SHVkDescriptorSetLayout::Binding> bindings{};
|
||||||
|
|
||||||
|
for (auto& input : inputReferences)
|
||||||
|
{
|
||||||
|
SHVkDescriptorSetLayout::Binding newBinding
|
||||||
|
{
|
||||||
|
.Type = (input.layout == vk::ImageLayout::eShaderReadOnlyOptimal) ? vk::DescriptorType::eInputAttachment : vk::DescriptorType::eStorageImage,
|
||||||
|
.Stage = vk::ShaderStageFlagBits::eFragment,
|
||||||
|
.BindPoint = static_cast<uint32_t>(bindings.size()),
|
||||||
|
.DescriptorCount = 1,
|
||||||
|
.flags = {},
|
||||||
|
};
|
||||||
|
|
||||||
|
bindings.push_back(newBinding);
|
||||||
|
}
|
||||||
|
|
||||||
|
// We build a new descriptor set layout to store our images
|
||||||
|
inputDescriptorLayout = graphStorage->logicalDevice->CreateDescriptorSetLayout(SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_RESOURCE, bindings);
|
||||||
|
|
||||||
|
// we store a sampler if its an input attachment. if it is storage image, no need sampler, store an empty handle.
|
||||||
|
for (uint32_t i = 0; i < bindings.size(); ++i)
|
||||||
|
{
|
||||||
|
if (bindings[i].Type == vk::DescriptorType::eInputAttachment)
|
||||||
|
{
|
||||||
|
auto newSampler = graphStorage->logicalDevice->CreateSampler(SHVkSamplerParams
|
||||||
|
{
|
||||||
|
.minFilter = vk::Filter::eLinear,
|
||||||
|
.magFilter = vk::Filter::eLinear,
|
||||||
|
.addressMode = vk::SamplerAddressMode::eRepeat,
|
||||||
|
.mipmapMode = vk::SamplerMipmapMode::eLinear,
|
||||||
|
.minLod = -1000,
|
||||||
|
.maxLod = 1000
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
inputSamplers.push_back(newSampler);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
inputSamplers.push_back({});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//// maybe do this in handle resize?
|
||||||
|
//UpdateWriteDescriptors();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHSubpass::UpdateWriteDescriptors(void) noexcept
|
||||||
|
{
|
||||||
|
if (inputNames.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto const& bindings = inputDescriptorLayout->GetBindings();
|
||||||
|
|
||||||
|
std::vector<uint32_t> variableCounts{ static_cast<uint32_t>(bindings.size()) };
|
||||||
|
std::fill (variableCounts.begin(), variableCounts.end(), 0u);
|
||||||
|
|
||||||
|
|
||||||
|
// For every frame's descriptor set
|
||||||
|
for (auto& group : inputImageDescriptors)
|
||||||
|
{
|
||||||
|
if (group)
|
||||||
|
group.Free();
|
||||||
|
|
||||||
|
group = graphStorage->descriptorPool->Allocate({ inputDescriptorLayout }, variableCounts);
|
||||||
|
|
||||||
|
uint32_t i = 0;
|
||||||
|
for (auto& binding : bindings)
|
||||||
|
{
|
||||||
|
// get the resource
|
||||||
|
auto resource = graphStorage->graphResources->at(inputNames[binding.BindPoint]);
|
||||||
|
|
||||||
|
// If resource is swapchain image, get the correct image, if not just get 0.
|
||||||
|
uint32_t viewIndex = (resource->resourceTypeFlags & static_cast<uint32_t>(SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT)) ? i : 0;
|
||||||
|
|
||||||
|
// layout is GENERAL if image is meant to be used as storage image, if not use SHADER_READ_ONLY_OPTINAL
|
||||||
|
vk::ImageLayout descriptorLayout = (binding.Type == vk::DescriptorType::eStorageImage) ? vk::ImageLayout::eGeneral : vk::ImageLayout::eShaderReadOnlyOptimal;
|
||||||
|
|
||||||
|
// Update descriptor sets
|
||||||
|
auto args = std::make_tuple(resource->GetImageView(viewIndex), inputSamplers[i], descriptorLayout);
|
||||||
|
group->ModifyWriteDescImage(SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_RESOURCE, binding.BindPoint, std::span{&args, 1});
|
||||||
|
group->UpdateDescriptorSetImages(SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_RESOURCE, binding.BindPoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//void SHSubpass::InitComputeBarriers(void) noexcept
|
||||||
|
//{
|
||||||
|
// std::unordered_set <uint64_t> handleBarriers{};
|
||||||
|
|
||||||
|
// // we will have swapchainNumImages vectors of vector of barriers
|
||||||
|
// subpassComputeBarriers.resize(graphStorage->swapchain->GetNumImages());
|
||||||
|
|
||||||
|
// for (auto sbCompute : subpassComputes)
|
||||||
|
// {
|
||||||
|
// // for every resource the subpass compute is using
|
||||||
|
// for (auto resource : sbCompute->resources)
|
||||||
|
// {
|
||||||
|
// // Get the resource handle
|
||||||
|
// uint64_t resourceRaw = resource.GetId().Raw;
|
||||||
|
|
||||||
|
// // if the barrier is not registered
|
||||||
|
// if (!handleBarriers.contains(resourceRaw))
|
||||||
|
// {
|
||||||
|
// // If the resource is a swapchain image
|
||||||
|
// bool isSwapchainImage = (resource->resourceTypeFlags & static_cast<uint32_t>(SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT));
|
||||||
|
// for (uint32_t i = 0; i < graphStorage->swapchain->GetNumImages(); ++i)
|
||||||
|
// {
|
||||||
|
// // if swapchain image, we want the index of the swapchain image, if not take base image
|
||||||
|
// uint32_t imageIndex = isSwapchainImage ? i : 0;
|
||||||
|
|
||||||
|
// // Prepare image barrier
|
||||||
|
// vk::ImageMemoryBarrier imageBarrier
|
||||||
|
// {
|
||||||
|
// .oldLayout = colorReferences[resourceAttachmentMapping->at(resource.GetId().Raw)].layout,
|
||||||
|
// .newLayout = vk::ImageLayout::eGeneral,
|
||||||
|
// .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||||
|
// .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||||
|
// .image = resource->GetImage(imageIndex)->GetVkImage(),
|
||||||
|
// .subresourceRange =
|
||||||
|
// {
|
||||||
|
// .aspectMask = resource->imageAspectFlags,
|
||||||
|
// .levelCount = resource->GetMipLevels(),
|
||||||
|
// .baseArrayLayer = 0,
|
||||||
|
// .layerCount = 1
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
|
||||||
|
// // push the barrier
|
||||||
|
// subpassComputeBarriers[i].push_back(imageBarrier);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // Image transition registered
|
||||||
|
// handleBarriers.emplace(resourceRaw);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
/*!
|
/*!
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,11 @@ namespace SHADE
|
||||||
class SHRenderGraphResource;
|
class SHRenderGraphResource;
|
||||||
class SHVkCommandBuffer;
|
class SHVkCommandBuffer;
|
||||||
class SHVkDescriptorSetLayout;
|
class SHVkDescriptorSetLayout;
|
||||||
|
class SHVkDescriptorSetGroup;
|
||||||
class SHVkDescriptorPool;
|
class SHVkDescriptorPool;
|
||||||
|
class SHRenderGraphStorage;
|
||||||
|
class SHVkShaderModule;
|
||||||
|
class SHVkSampler;
|
||||||
|
|
||||||
class SH_API SHSubpass : public ISelfHandle<SHSubpass>
|
class SH_API SHSubpass : public ISelfHandle<SHSubpass>
|
||||||
{
|
{
|
||||||
|
@ -22,32 +26,49 @@ namespace SHADE
|
||||||
/*---------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------*/
|
||||||
/* PRIVATE MEMBER VARIABLES */
|
/* PRIVATE MEMBER VARIABLES */
|
||||||
/*---------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------*/
|
||||||
|
Handle<SHRenderGraphStorage> graphStorage;
|
||||||
|
|
||||||
//! The index of the subpass in the render graph
|
//! The index of the subpass in the render graph
|
||||||
uint32_t subpassIndex;
|
uint32_t subpassIndex;
|
||||||
|
|
||||||
//! The parent renderpass that this subpass belongs to
|
//! The parent renderpass that this subpass belongs to
|
||||||
Handle<SHRenderGraphNode> parentNode;
|
Handle<SHRenderGraphNode> parentNode;
|
||||||
|
|
||||||
//!
|
//!
|
||||||
Handle<SHSuperBatch> superBatch;
|
Handle<SHSuperBatch> superBatch;
|
||||||
|
|
||||||
//! Descriptor set layout to hold attachments
|
//! Descriptor set layout to hold attachments
|
||||||
Handle<SHVkDescriptorSetLayout> descriptorSetLayout;
|
Handle<SHVkDescriptorSetLayout> descriptorSetLayout;
|
||||||
|
|
||||||
//! Color attachments
|
//! Color attachments
|
||||||
std::vector<vk::AttachmentReference> colorReferences;
|
std::vector<vk::AttachmentReference> colorReferences;
|
||||||
|
|
||||||
//! Depth attachments
|
//! Depth attachments
|
||||||
std::vector<vk::AttachmentReference> depthReferences;
|
std::vector<vk::AttachmentReference> depthReferences;
|
||||||
|
|
||||||
//! Input attachments
|
//! Input attachments
|
||||||
std::vector<vk::AttachmentReference> inputReferences;
|
std::vector<vk::AttachmentReference> inputReferences;
|
||||||
|
|
||||||
|
//! This is mainly for when we want to retrieve resources using names.
|
||||||
|
std::vector<std::string> inputNames;
|
||||||
|
|
||||||
//! For getting attachment reference indices using handles
|
//! For getting attachment reference indices using handles
|
||||||
std::unordered_map<uint64_t, uint32_t> const* resourceAttachmentMapping;
|
std::unordered_map<uint64_t, uint32_t> const* resourceAttachmentMapping;
|
||||||
|
|
||||||
//! Pointer to resources in the render graph (for getting handle IDs)
|
//! Descriptor set group to hold the images for input
|
||||||
std::unordered_map<std::string, Handle<SHRenderGraphResource>> const* ptrToResources;
|
std::vector<Handle<SHVkDescriptorSetGroup>> inputImageDescriptors;
|
||||||
|
|
||||||
|
//! Descriptor set layout for allocating descriptor set for inputs
|
||||||
|
Handle<SHVkDescriptorSetLayout> inputDescriptorLayout;
|
||||||
|
|
||||||
|
std::vector<Handle<SHVkSampler>> inputSamplers;
|
||||||
|
|
||||||
|
|
||||||
|
////! subpass compute image barriers. We do this because every frame has a different
|
||||||
|
////! swapchain image. If the resource we want to transition is not a swapchain image,
|
||||||
|
////! we duplicate the barrier anyway, not much memory wasted. ;)
|
||||||
|
//std::vector<std::vector<vk::ImageMemoryBarrier>> subpassComputeBarriers{};
|
||||||
|
|
||||||
|
|
||||||
//! Sometimes there exists entities that we want to render onto a render target
|
//! Sometimes there exists entities that we want to render onto a render target
|
||||||
//! but don't want it to come from the batching system. An example would be ImGUI.
|
//! but don't want it to come from the batching system. An example would be ImGUI.
|
||||||
|
@ -62,7 +83,7 @@ namespace SHADE
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
/* CTORS AND DTORS */
|
/* CTORS AND DTORS */
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
SHSubpass(Handle<SHRenderGraphNode> const& parent, uint32_t index, std::unordered_map<uint64_t, uint32_t> const* mapping, std::unordered_map<std::string, Handle<SHRenderGraphResource>> const* ptrToResources) noexcept;
|
SHSubpass(Handle<SHRenderGraphStorage> renderGraphStorage, Handle<SHRenderGraphNode> const& parent, uint32_t index, std::unordered_map<uint64_t, uint32_t> const* mapping) noexcept;
|
||||||
SHSubpass(SHSubpass&& rhs) noexcept;
|
SHSubpass(SHSubpass&& rhs) noexcept;
|
||||||
SHSubpass& operator=(SHSubpass&& rhs) noexcept;
|
SHSubpass& operator=(SHSubpass&& rhs) noexcept;
|
||||||
|
|
||||||
|
@ -71,14 +92,22 @@ namespace SHADE
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
// Preparation functions
|
// Preparation functions
|
||||||
void AddColorOutput(std::string resourceToReference) noexcept;
|
void AddColorOutput(std::string resourceToReference) noexcept;
|
||||||
|
void AddGeneralColorOutput(std::string resourceToReference) noexcept;
|
||||||
void AddDepthOutput(std::string resourceToReference, SH_ATT_DESC_TYPE_FLAGS attachmentDescriptionType = SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL) noexcept;
|
void AddDepthOutput(std::string resourceToReference, SH_ATT_DESC_TYPE_FLAGS attachmentDescriptionType = SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL) noexcept;
|
||||||
|
void AddGeneralDepthOutput(std::string resourceToReference) noexcept;
|
||||||
void AddInput(std::string resourceToReference) noexcept;
|
void AddInput(std::string resourceToReference) noexcept;
|
||||||
|
void AddGeneralInput (std::string resourceToReference) noexcept;
|
||||||
|
void AddExteriorDrawCalls(std::function<void(Handle<SHVkCommandBuffer>&)> const& newDrawCall) noexcept;
|
||||||
|
|
||||||
// Runtime functions
|
// Runtime functions
|
||||||
void Execute(Handle<SHVkCommandBuffer>& commandBuffer, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) noexcept;
|
void Execute(Handle<SHVkCommandBuffer>& commandBuffer, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) noexcept;
|
||||||
void AddExteriorDrawCalls(std::function<void(Handle<SHVkCommandBuffer>&)> const& newDrawCall) noexcept;
|
void HandleResize (void) noexcept;
|
||||||
|
|
||||||
void Init(SHResourceHub& resourceManager) noexcept;
|
void Init(SHResourceHub& resourceManager) noexcept;
|
||||||
|
|
||||||
|
//void InitComputeBarriers (void) noexcept;
|
||||||
|
void CreateInputDescriptors (void) noexcept;
|
||||||
|
void UpdateWriteDescriptors (void) noexcept;
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
/* GETTERS AND SETTERS */
|
/* GETTERS AND SETTERS */
|
||||||
|
@ -91,5 +120,6 @@ namespace SHADE
|
||||||
|
|
||||||
friend class SHRenderGraphNode;
|
friend class SHRenderGraphNode;
|
||||||
friend class SHRenderGraph;
|
friend class SHRenderGraph;
|
||||||
|
friend class SHSubpass;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,23 +0,0 @@
|
||||||
#include "SHpch.h"
|
|
||||||
#include "SHSubpassCompute.h"
|
|
||||||
#include "Graphics/Pipeline/SHVkPipeline.h"
|
|
||||||
#include "Graphics/Descriptors/SHVkDescriptorSetGroup.h"
|
|
||||||
#include "Graphics/Descriptors/SHVkDescriptorPool.h"
|
|
||||||
|
|
||||||
namespace SHADE
|
|
||||||
{
|
|
||||||
SHSubpassCompute::SHSubpassCompute(Handle<SHVkPipeline> inPipeline, Handle<SHVkDescriptorPool> descPool) noexcept
|
|
||||||
: pipeline {inPipeline}
|
|
||||||
{
|
|
||||||
// Get the descriptor set layouts required to allocate. we will bind a different pipeline layout, one that includes the layout for global.
|
|
||||||
auto const& layouts = pipeline->GetPipelineLayout()->GetDescriptorSetLayoutsAllocate();
|
|
||||||
|
|
||||||
// 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)
|
|
||||||
descPool->Allocate(layouts, variableCounts);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,25 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <Resource/SHHandle.h>
|
|
||||||
|
|
||||||
namespace SHADE
|
|
||||||
{
|
|
||||||
class SHVkPipeline;
|
|
||||||
class SHVkDescriptorSetGroup;
|
|
||||||
class SHVkDescriptorPool;
|
|
||||||
|
|
||||||
class SHSubpassCompute
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
//! To run the dispatch command
|
|
||||||
Handle<SHVkPipeline> pipeline;
|
|
||||||
|
|
||||||
//! Descriptor set group
|
|
||||||
Handle<SHVkDescriptorSetGroup> descSetGroup;
|
|
||||||
|
|
||||||
public:
|
|
||||||
SHSubpassCompute (Handle<SHVkPipeline> inPipeline, Handle<SHVkDescriptorPool> descPool) noexcept;
|
|
||||||
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
|
@ -51,10 +51,37 @@ namespace SHADE
|
||||||
case vk::Format::eR32Uint:
|
case vk::Format::eR32Uint:
|
||||||
case vk::Format::eR32Sfloat:
|
case vk::Format::eR32Sfloat:
|
||||||
return 4;
|
return 4;
|
||||||
|
case vk::Format::eR32G32Sint:
|
||||||
|
case vk::Format::eR32G32Uint:
|
||||||
|
case vk::Format::eR32G32Sfloat:
|
||||||
|
return 8;
|
||||||
|
case vk::Format::eR32G32B32Sint:
|
||||||
|
case vk::Format::eR32G32B32Uint:
|
||||||
|
case vk::Format::eR32G32B32Sfloat:
|
||||||
|
return 12;
|
||||||
|
case vk::Format::eR32G32B32A32Sint:
|
||||||
|
case vk::Format::eR32G32B32A32Uint:
|
||||||
|
case vk::Format::eR32G32B32A32Sfloat:
|
||||||
|
return 16;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vk::PipelineBindPoint SHVkUtil::GetPipelineBindPointFromType(SH_PIPELINE_TYPE pipelineType) noexcept
|
||||||
|
{
|
||||||
|
switch (pipelineType)
|
||||||
|
{
|
||||||
|
case SH_PIPELINE_TYPE::GRAPHICS:
|
||||||
|
return vk::PipelineBindPoint::eGraphics;
|
||||||
|
case SH_PIPELINE_TYPE::COMPUTE:
|
||||||
|
return vk::PipelineBindPoint::eCompute;
|
||||||
|
case SH_PIPELINE_TYPE::RAY_TRACING:
|
||||||
|
return vk::PipelineBindPoint::eRayTracingKHR;
|
||||||
|
default:
|
||||||
|
return vk::PipelineBindPoint::eGraphics;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void SHVkUtil::EnsureBufferAndCopyData(Handle<SHVkLogicalDevice> device, Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHVkBuffer>& bufferHandle, void* src, uint32_t size, vk::BufferUsageFlagBits usage)
|
void SHVkUtil::EnsureBufferAndCopyData(Handle<SHVkLogicalDevice> device, Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHVkBuffer>& bufferHandle, void* src, uint32_t size, vk::BufferUsageFlagBits usage)
|
||||||
{
|
{
|
||||||
if (bufferHandle)
|
if (bufferHandle)
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include "SHVulkanIncludes.h"
|
#include "SHVulkanIncludes.h"
|
||||||
|
|
||||||
#include "Resource/SHHandle.h"
|
#include "Resource/SHHandle.h"
|
||||||
|
#include "Graphics/Pipeline/SHPipelineType.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
@ -20,11 +21,12 @@ namespace SHADE
|
||||||
class SHVkUtil
|
class SHVkUtil
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static bool IsDepthOnlyFormat (vk::Format format) noexcept;
|
static bool IsDepthOnlyFormat (vk::Format format) noexcept;
|
||||||
static bool IsDepthStencilAttachment (vk::Format format) noexcept;
|
static bool IsDepthStencilAttachment (vk::Format format) noexcept;
|
||||||
static bool IsBlendCompatible (vk::Format format) noexcept;
|
static bool IsBlendCompatible (vk::Format format) noexcept;
|
||||||
static uint32_t GetBytesPerPixelFromFormat (vk::Format format) noexcept;
|
static uint32_t GetBytesPerPixelFromFormat (vk::Format format) noexcept;
|
||||||
|
static vk::PipelineBindPoint GetPipelineBindPointFromType (SH_PIPELINE_TYPE pipelineType) noexcept;
|
||||||
|
|
||||||
/***********************************************************************************/
|
/***********************************************************************************/
|
||||||
/*!
|
/*!
|
||||||
|
|
||||||
|
|
|
@ -177,6 +177,9 @@ namespace SHADE
|
||||||
return vk::DescriptorType::eStorageBufferDynamic;
|
return vk::DescriptorType::eStorageBufferDynamic;
|
||||||
case SpvReflectDescriptorType::SPV_REFLECT_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
|
case SpvReflectDescriptorType::SPV_REFLECT_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
|
||||||
return vk::DescriptorType::eInputAttachment;
|
return vk::DescriptorType::eInputAttachment;
|
||||||
|
case SpvReflectDescriptorType::SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_IMAGE:
|
||||||
|
return vk::DescriptorType::eStorageImage;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return vk::DescriptorType::eCombinedImageSampler;
|
return vk::DescriptorType::eCombinedImageSampler;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -22,6 +22,9 @@ namespace SHADE
|
||||||
|
|
||||||
// integer formats
|
// integer formats
|
||||||
UINT32_1D,
|
UINT32_1D,
|
||||||
|
UINT32_2D,
|
||||||
|
UINT32_3D,
|
||||||
|
UINT32_4D,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SHVertexAttribute
|
struct SHVertexAttribute
|
||||||
|
|
|
@ -295,32 +295,33 @@ namespace SHADE
|
||||||
) != 0;
|
) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SHMatrix::operator XMMATRIX() const noexcept
|
||||||
|
{
|
||||||
|
return XMLoadFloat4x4(this);
|
||||||
|
}
|
||||||
|
|
||||||
SHMatrix operator*(float lhs, const SHMatrix& rhs) noexcept
|
SHMatrix operator*(float lhs, const SHMatrix& rhs) noexcept
|
||||||
{
|
{
|
||||||
return rhs * lhs;
|
return rhs * lhs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
/* Function Member Definitions */
|
/* Function Member Definitions */
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
void SHMatrix::Transpose() noexcept
|
void SHMatrix::Transpose() noexcept
|
||||||
{
|
{
|
||||||
const XMMATRIX M = XMLoadFloat4x4(this);
|
XMStoreFloat4x4(this, XMMatrixTranspose(*this));
|
||||||
XMStoreFloat4x4(this, XMMatrixTranspose(M));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHMatrix::Invert() noexcept
|
void SHMatrix::Invert() noexcept
|
||||||
{
|
{
|
||||||
const XMMATRIX M = XMLoadFloat4x4(this);
|
XMStoreFloat4x4(this, XMMatrixInverse(nullptr, *this));
|
||||||
XMStoreFloat4x4(this, XMMatrixInverse(nullptr, M));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float SHMatrix::Determinant() const noexcept
|
float SHMatrix::Determinant() const noexcept
|
||||||
{
|
{
|
||||||
const XMMATRIX M = XMLoadFloat4x4(this);
|
return XMVectorGetX(XMMatrixDeterminant(*this));
|
||||||
return XMVectorGetX(XMMatrixDeterminant(M));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string SHMatrix::ToString() const noexcept
|
std::string SHMatrix::ToString() const noexcept
|
||||||
|
@ -337,9 +338,8 @@ namespace SHADE
|
||||||
bool SHMatrix::Decompose(SHVec3& translation, SHVec3& rotation, SHVec3& scale) const noexcept
|
bool SHMatrix::Decompose(SHVec3& translation, SHVec3& rotation, SHVec3& scale) const noexcept
|
||||||
{
|
{
|
||||||
XMVECTOR s, r, t;
|
XMVECTOR s, r, t;
|
||||||
const XMMATRIX M = XMLoadFloat4x4(this);
|
|
||||||
|
|
||||||
if (!XMMatrixDecompose(&s, &r, &t, M))
|
if (!XMMatrixDecompose(&s, &r, &t, *this))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
SHQuaternion orientation;
|
SHQuaternion orientation;
|
||||||
|
@ -356,9 +356,8 @@ namespace SHADE
|
||||||
bool SHMatrix::Decompose(SHVec3& translation, SHQuaternion& orientation, SHVec3& scale) const noexcept
|
bool SHMatrix::Decompose(SHVec3& translation, SHQuaternion& orientation, SHVec3& scale) const noexcept
|
||||||
{
|
{
|
||||||
XMVECTOR s, r, t;
|
XMVECTOR s, r, t;
|
||||||
const XMMATRIX M = XMLoadFloat4x4(this);
|
|
||||||
|
|
||||||
if (!XMMatrixDecompose(&s, &r, &t, M))
|
if (!XMMatrixDecompose(&s, &r, &t, *this))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
XMStoreFloat3(&scale, s);
|
XMStoreFloat3(&scale, s);
|
||||||
|
@ -376,8 +375,7 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
SHMatrix result;
|
SHMatrix result;
|
||||||
|
|
||||||
const XMMATRIX M = XMLoadFloat4x4(&matrix);
|
XMStoreFloat4x4(&result, XMMatrixTranspose(matrix));
|
||||||
XMStoreFloat4x4(&result, XMMatrixTranspose(M));
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -385,8 +383,7 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
SHMatrix result;
|
SHMatrix result;
|
||||||
|
|
||||||
const XMMATRIX M = XMLoadFloat4x4(&matrix);
|
XMStoreFloat4x4(&result, XMMatrixInverse(nullptr, matrix));
|
||||||
XMStoreFloat4x4(&result, XMMatrixInverse(nullptr, M));
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -401,8 +398,8 @@ namespace SHADE
|
||||||
SHMatrix SHMatrix::Translate(const SHVec3& pos) noexcept
|
SHMatrix SHMatrix::Translate(const SHVec3& pos) noexcept
|
||||||
{
|
{
|
||||||
SHMatrix result;
|
SHMatrix result;
|
||||||
XMStoreFloat4x4(&result, XMMatrixTranslation(pos.x, pos.y, pos.z));
|
|
||||||
|
|
||||||
|
XMStoreFloat4x4(&result, XMMatrixTranslation(pos.x, pos.y, pos.z));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -410,25 +407,23 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
SHMatrix result;
|
SHMatrix result;
|
||||||
|
|
||||||
const XMVECTOR A = XMLoadFloat3(&axis);
|
XMStoreFloat4x4(&result, XMMatrixRotationAxis(axis, angleInRad));
|
||||||
XMStoreFloat4x4(&result, XMMatrixRotationAxis(A, angleInRad));
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
SHMatrix SHMatrix::Rotate(float yaw, float pitch, float roll) noexcept
|
SHMatrix SHMatrix::Rotate(float yaw, float pitch, float roll) noexcept
|
||||||
{
|
{
|
||||||
SHMatrix result;
|
SHMatrix result;
|
||||||
XMStoreFloat4x4(&result, XMMatrixRotationRollPitchYaw(pitch, yaw, roll));
|
|
||||||
|
|
||||||
|
XMStoreFloat4x4(&result, XMMatrixRotationRollPitchYaw(pitch, yaw, roll));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
SHMatrix SHMatrix::Rotate(const SHVec3& eulerAngles) noexcept
|
SHMatrix SHMatrix::Rotate(const SHVec3& eulerAngles) noexcept
|
||||||
{
|
{
|
||||||
SHMatrix result;
|
SHMatrix result;
|
||||||
XMStoreFloat4x4(&result, XMMatrixRotationRollPitchYaw(eulerAngles.x, eulerAngles.y, eulerAngles.z));
|
|
||||||
|
|
||||||
|
XMStoreFloat4x4(&result, XMMatrixRotationRollPitchYawFromVector(eulerAngles));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -436,57 +431,55 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
SHMatrix result;
|
SHMatrix result;
|
||||||
|
|
||||||
const XMVECTOR Q = XMLoadFloat4(&q);
|
XMStoreFloat4x4(&result, XMMatrixRotationQuaternion(q));
|
||||||
XMStoreFloat4x4(&result, XMMatrixRotationQuaternion(Q));
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
SHMatrix SHMatrix::RotateX(float angleInRad) noexcept
|
SHMatrix SHMatrix::RotateX(float angleInRad) noexcept
|
||||||
{
|
{
|
||||||
SHMatrix result;
|
SHMatrix result;
|
||||||
XMStoreFloat4x4(&result, XMMatrixRotationX(angleInRad));
|
|
||||||
|
|
||||||
|
XMStoreFloat4x4(&result, XMMatrixRotationX(angleInRad));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
SHMatrix SHMatrix::RotateY(float angleInRad) noexcept
|
SHMatrix SHMatrix::RotateY(float angleInRad) noexcept
|
||||||
{
|
{
|
||||||
SHMatrix result;
|
SHMatrix result;
|
||||||
XMStoreFloat4x4(&result, XMMatrixRotationY(angleInRad));
|
|
||||||
|
|
||||||
|
XMStoreFloat4x4(&result, XMMatrixRotationY(angleInRad));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
SHMatrix SHMatrix::RotateZ(float angleInRad) noexcept
|
SHMatrix SHMatrix::RotateZ(float angleInRad) noexcept
|
||||||
{
|
{
|
||||||
SHMatrix result;
|
SHMatrix result;
|
||||||
XMStoreFloat4x4(&result, XMMatrixRotationZ(angleInRad));
|
|
||||||
|
|
||||||
|
XMStoreFloat4x4(&result, XMMatrixRotationZ(angleInRad));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
SHMatrix SHMatrix::Scale(float uniformScaleFactor) noexcept
|
SHMatrix SHMatrix::Scale(float uniformScaleFactor) noexcept
|
||||||
{
|
{
|
||||||
SHMatrix result;
|
SHMatrix result;
|
||||||
XMStoreFloat4x4(&result, XMMatrixScaling(uniformScaleFactor, uniformScaleFactor, uniformScaleFactor));
|
|
||||||
|
|
||||||
|
XMStoreFloat4x4(&result, XMMatrixScaling(uniformScaleFactor, uniformScaleFactor, uniformScaleFactor));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
SHMatrix SHMatrix::Scale(float x, float y, float z) noexcept
|
SHMatrix SHMatrix::Scale(float x, float y, float z) noexcept
|
||||||
{
|
{
|
||||||
SHMatrix result;
|
SHMatrix result;
|
||||||
XMStoreFloat4x4(&result, XMMatrixScaling(x, y, z));
|
|
||||||
|
|
||||||
|
XMStoreFloat4x4(&result, XMMatrixScaling(x, y, z));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
SHMatrix SHMatrix::Scale(const SHVec3& scale) noexcept
|
SHMatrix SHMatrix::Scale(const SHVec3& scale) noexcept
|
||||||
{
|
{
|
||||||
SHMatrix result;
|
SHMatrix result;
|
||||||
XMStoreFloat4x4(&result, XMMatrixScaling(scale.x, scale.y, scale.z));
|
|
||||||
|
|
||||||
|
XMStoreFloat4x4(&result, XMMatrixScalingFromVector(scale));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -494,12 +487,7 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
SHMatrix result;
|
SHMatrix result;
|
||||||
|
|
||||||
const XMVECTOR EYE = XMLoadFloat3(&eye);
|
XMStoreFloat4x4(&result, XMMatrixLookAtRH(eye, target, up));
|
||||||
const XMVECTOR TGT = XMLoadFloat3(&target);
|
|
||||||
const XMVECTOR UP = XMLoadFloat3(&up);
|
|
||||||
|
|
||||||
XMStoreFloat4x4(&result, XMMatrixLookAtRH(EYE, TGT, UP));
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -507,12 +495,7 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
SHMatrix result;
|
SHMatrix result;
|
||||||
|
|
||||||
const XMVECTOR EYE = XMLoadFloat3(&eye);
|
XMStoreFloat4x4(&result, XMMatrixLookAtLH(eye, target, up));
|
||||||
const XMVECTOR TGT = XMLoadFloat3(&target);
|
|
||||||
const XMVECTOR UP = XMLoadFloat3(&up);
|
|
||||||
|
|
||||||
XMStoreFloat4x4(&result, XMMatrixLookAtLH(EYE, TGT, UP));
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -522,8 +505,8 @@ namespace SHADE
|
||||||
|
|
||||||
const SHVec3 FWD_HAT = SHVec3::Normalise(-forward);
|
const SHVec3 FWD_HAT = SHVec3::Normalise(-forward);
|
||||||
|
|
||||||
const XMVECTOR Z_HAT = XMVector3Normalize(XMLoadFloat3(&FWD_HAT));
|
const XMVECTOR Z_HAT = XMVector3Normalize(FWD_HAT);
|
||||||
const XMVECTOR X_HAT = XMVector3Normalize(XMVector3Cross(XMLoadFloat3(&up), Z_HAT));
|
const XMVECTOR X_HAT = XMVector3Normalize(XMVector3Cross(up, Z_HAT));
|
||||||
const XMVECTOR Y_HAT = XMVector3Cross(Z_HAT, X_HAT);
|
const XMVECTOR Y_HAT = XMVector3Cross(Z_HAT, X_HAT);
|
||||||
|
|
||||||
XMStoreFloat3(reinterpret_cast<XMFLOAT3*>(&result._11), X_HAT);
|
XMStoreFloat3(reinterpret_cast<XMFLOAT3*>(&result._11), X_HAT);
|
||||||
|
@ -543,8 +526,8 @@ namespace SHADE
|
||||||
|
|
||||||
const SHVec3 FWD_HAT = SHVec3::Normalise(forward);
|
const SHVec3 FWD_HAT = SHVec3::Normalise(forward);
|
||||||
|
|
||||||
const XMVECTOR Z_HAT = XMVector3Normalize(XMLoadFloat3(&FWD_HAT));
|
const XMVECTOR Z_HAT = XMVector3Normalize(FWD_HAT);
|
||||||
const XMVECTOR X_HAT = XMVector3Normalize(XMVector3Cross(XMLoadFloat3(&up), Z_HAT));
|
const XMVECTOR X_HAT = XMVector3Normalize(XMVector3Cross(up, Z_HAT));
|
||||||
const XMVECTOR Y_HAT = XMVector3Cross(Z_HAT, X_HAT);
|
const XMVECTOR Y_HAT = XMVector3Cross(Z_HAT, X_HAT);
|
||||||
|
|
||||||
XMStoreFloat3(reinterpret_cast<XMFLOAT3*>(&result._11), X_HAT);
|
XMStoreFloat3(reinterpret_cast<XMFLOAT3*>(&result._11), X_HAT);
|
||||||
|
@ -563,7 +546,6 @@ namespace SHADE
|
||||||
SHMatrix result;
|
SHMatrix result;
|
||||||
|
|
||||||
XMStoreFloat4x4(&result, XMMatrixPerspectiveFovRH(fov, aspectRatio, nearPlane, farPlane));
|
XMStoreFloat4x4(&result, XMMatrixPerspectiveFovRH(fov, aspectRatio, nearPlane, farPlane));
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -572,7 +554,6 @@ namespace SHADE
|
||||||
SHMatrix result;
|
SHMatrix result;
|
||||||
|
|
||||||
XMStoreFloat4x4(&result, XMMatrixPerspectiveFovLH(fov, aspectRatio, nearPlane, farPlane));
|
XMStoreFloat4x4(&result, XMMatrixPerspectiveFovLH(fov, aspectRatio, nearPlane, farPlane));
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -581,7 +562,6 @@ namespace SHADE
|
||||||
SHMatrix result;
|
SHMatrix result;
|
||||||
|
|
||||||
XMStoreFloat4x4(&result, XMMatrixPerspectiveRH(width, height, nearPlane, farPlane));
|
XMStoreFloat4x4(&result, XMMatrixPerspectiveRH(width, height, nearPlane, farPlane));
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -590,7 +570,6 @@ namespace SHADE
|
||||||
SHMatrix result;
|
SHMatrix result;
|
||||||
|
|
||||||
XMStoreFloat4x4(&result, XMMatrixPerspectiveLH(width, height, nearPlane, farPlane));
|
XMStoreFloat4x4(&result, XMMatrixPerspectiveLH(width, height, nearPlane, farPlane));
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -599,7 +578,6 @@ namespace SHADE
|
||||||
SHMatrix result;
|
SHMatrix result;
|
||||||
|
|
||||||
XMStoreFloat4x4(&result, XMMatrixOrthographicRH(width, height, nearPlane, farPlane));
|
XMStoreFloat4x4(&result, XMMatrixOrthographicRH(width, height, nearPlane, farPlane));
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -608,7 +586,6 @@ namespace SHADE
|
||||||
SHMatrix result;
|
SHMatrix result;
|
||||||
|
|
||||||
XMStoreFloat4x4(&result, XMMatrixOrthographicLH(width, height, nearPlane, farPlane));
|
XMStoreFloat4x4(&result, XMMatrixOrthographicLH(width, height, nearPlane, farPlane));
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -77,6 +77,8 @@ namespace SHADE
|
||||||
SHMatrix& operator= (const SHMatrix& rhs) = default;
|
SHMatrix& operator= (const SHMatrix& rhs) = default;
|
||||||
SHMatrix& operator= (SHMatrix&& rhs) = default;
|
SHMatrix& operator= (SHMatrix&& rhs) = default;
|
||||||
|
|
||||||
|
operator DirectX::XMMATRIX () const noexcept;
|
||||||
|
|
||||||
SHMatrix& operator+= (const SHMatrix& rhs) noexcept;
|
SHMatrix& operator+= (const SHMatrix& rhs) noexcept;
|
||||||
SHMatrix& operator-= (const SHMatrix& rhs) noexcept;
|
SHMatrix& operator-= (const SHMatrix& rhs) noexcept;
|
||||||
SHMatrix& operator*= (const SHMatrix& rhs) noexcept;
|
SHMatrix& operator*= (const SHMatrix& rhs) noexcept;
|
||||||
|
|
|
@ -36,44 +36,18 @@ namespace SHADE
|
||||||
: XMFLOAT4( 0.0f, 0.0f, 0.0f, 1.0f )
|
: XMFLOAT4( 0.0f, 0.0f, 0.0f, 1.0f )
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
SHQuaternion::SHQuaternion(const SHVec4& vec4) noexcept
|
||||||
|
: XMFLOAT4( vec4.x, vec4.y, vec4.z, vec4.w )
|
||||||
|
{}
|
||||||
|
|
||||||
SHQuaternion::SHQuaternion(float _x, float _y, float _z, float _w) noexcept
|
SHQuaternion::SHQuaternion(float _x, float _y, float _z, float _w) noexcept
|
||||||
: XMFLOAT4( _x, _y, _z, _w )
|
: XMFLOAT4( _x, _y, _z, _w )
|
||||||
{}
|
{}
|
||||||
|
|
||||||
SHQuaternion::SHQuaternion(float yaw, float pitch, float roll) noexcept
|
|
||||||
: XMFLOAT4( 0.0f, 0.0f, 0.0f, 1.0f )
|
|
||||||
{
|
|
||||||
XMStoreFloat4(this, XMQuaternionRotationRollPitchYaw(pitch, yaw, roll));
|
|
||||||
}
|
|
||||||
|
|
||||||
SHQuaternion::SHQuaternion(const SHVec3& eulerAngles) noexcept
|
|
||||||
: XMFLOAT4( 0.0f, 0.0f, 0.0f, 1.0f )
|
|
||||||
{
|
|
||||||
const XMVECTOR V = XMLoadFloat3(&eulerAngles);
|
|
||||||
XMStoreFloat4(this, XMQuaternionRotationRollPitchYawFromVector(V));
|
|
||||||
}
|
|
||||||
|
|
||||||
SHQuaternion::SHQuaternion(const SHVec3& axis, float angleInRad) noexcept
|
|
||||||
: XMFLOAT4( 0.0f, 0.0f, 0.0f, 1.0f )
|
|
||||||
{
|
|
||||||
const XMVECTOR AXIS = XMLoadFloat3(&axis);
|
|
||||||
XMStoreFloat4(this, XMQuaternionRotationAxis(AXIS, angleInRad));
|
|
||||||
}
|
|
||||||
|
|
||||||
SHQuaternion::SHQuaternion(const SHMatrix& rotationMatrix) noexcept
|
|
||||||
: XMFLOAT4( 0.0f, 0.0f, 0.0f, 1.0f )
|
|
||||||
{
|
|
||||||
const XMMATRIX M = XMLoadFloat4x4(&rotationMatrix);
|
|
||||||
XMStoreFloat4(this, XMQuaternionRotationMatrix(M));
|
|
||||||
}
|
|
||||||
|
|
||||||
SHQuaternion::SHQuaternion(const reactphysics3d::Vector3& rp3dEuler) noexcept
|
SHQuaternion::SHQuaternion(const reactphysics3d::Vector3& rp3dEuler) noexcept
|
||||||
: XMFLOAT4( 0.0f, 0.0f, 0.0f, 1.0f )
|
: XMFLOAT4( 0.0f, 0.0f, 0.0f, 1.0f )
|
||||||
{
|
{
|
||||||
const SHVec3& SHADE_VEC{ rp3dEuler };
|
XMStoreFloat4(this, XMQuaternionRotationRollPitchYawFromVector(SHVec3 { rp3dEuler }));
|
||||||
|
|
||||||
const XMVECTOR V = XMLoadFloat3(&SHADE_VEC);
|
|
||||||
XMStoreFloat4(this, XMQuaternionRotationRollPitchYawFromVector(V));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SHQuaternion::SHQuaternion(const reactphysics3d::Quaternion& rp3dQuat) noexcept
|
SHQuaternion::SHQuaternion(const reactphysics3d::Quaternion& rp3dQuat) noexcept
|
||||||
|
@ -113,10 +87,7 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
SHQuaternion result;
|
SHQuaternion result;
|
||||||
|
|
||||||
const XMVECTOR Q1 = XMLoadFloat4(this);
|
XMStoreFloat4(&result, XMVectorAdd(*this, rhs));
|
||||||
const XMVECTOR Q2 = XMLoadFloat4(&rhs);
|
|
||||||
|
|
||||||
XMStoreFloat4(&result, XMVectorAdd(Q1, Q2));
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,10 +95,7 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
SHQuaternion result;
|
SHQuaternion result;
|
||||||
|
|
||||||
const XMVECTOR Q1 = XMLoadFloat4(this);
|
XMStoreFloat4(&result, XMVectorSubtract(*this, rhs));
|
||||||
const XMVECTOR Q2 = XMLoadFloat4(&rhs);
|
|
||||||
|
|
||||||
XMStoreFloat4(&result, XMVectorSubtract(Q1, Q2));
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,9 +103,7 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
SHQuaternion result;
|
SHQuaternion result;
|
||||||
|
|
||||||
const XMVECTOR Q = XMLoadFloat4(this);
|
XMStoreFloat4(&result, XMVectorNegate(*this));
|
||||||
|
|
||||||
XMStoreFloat4(&result, XMVectorNegate(Q));
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,10 +111,7 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
SHQuaternion result;
|
SHQuaternion result;
|
||||||
|
|
||||||
const XMVECTOR Q1 = XMLoadFloat4(this);
|
XMStoreFloat4(&result, XMQuaternionMultiply(*this, rhs));
|
||||||
const XMVECTOR Q2 = XMLoadFloat4(&rhs);
|
|
||||||
|
|
||||||
XMStoreFloat4(&result, XMQuaternionMultiply(Q1, Q2));
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,9 +119,7 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
SHQuaternion result;
|
SHQuaternion result;
|
||||||
|
|
||||||
const XMVECTOR Q = XMLoadFloat4(this);
|
XMStoreFloat4(&result, XMVectorScale(*this, rhs));
|
||||||
|
|
||||||
XMStoreFloat4(&result, XMVectorScale(Q, rhs));
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -166,27 +127,18 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
SHQuaternion result;
|
SHQuaternion result;
|
||||||
|
|
||||||
const XMVECTOR Q1 = XMLoadFloat4(this);
|
XMStoreFloat4(&result, XMQuaternionMultiply(*this, XMQuaternionInverse(rhs)));
|
||||||
const XMVECTOR Q2 = XMQuaternionInverse(XMLoadFloat4(&rhs));
|
|
||||||
|
|
||||||
XMStoreFloat4(&result, XMQuaternionMultiply(Q1, Q2));
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SHQuaternion::operator==(const SHQuaternion& rhs) const noexcept
|
bool SHQuaternion::operator==(const SHQuaternion& rhs) const noexcept
|
||||||
{
|
{
|
||||||
const XMVECTOR Q1 = XMLoadFloat4(this);
|
return XMQuaternionEqual(*this, rhs);
|
||||||
const XMVECTOR Q2 = XMLoadFloat4(&rhs);
|
|
||||||
|
|
||||||
return XMQuaternionEqual(Q1, Q2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SHQuaternion::operator!=(const SHQuaternion& rhs) const noexcept
|
bool SHQuaternion::operator!=(const SHQuaternion& rhs) const noexcept
|
||||||
{
|
{
|
||||||
const XMVECTOR Q1 = XMLoadFloat4(this);
|
return XMQuaternionNotEqual(*this, rhs);
|
||||||
const XMVECTOR Q2 = XMLoadFloat4(&rhs);
|
|
||||||
|
|
||||||
return XMQuaternionNotEqual(Q1, Q2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SHQuaternion::operator reactphysics3d::Quaternion() const noexcept
|
SHQuaternion::operator reactphysics3d::Quaternion() const noexcept
|
||||||
|
@ -199,6 +151,11 @@ namespace SHADE
|
||||||
return reactphysics3d::Vector3{ ToEuler() };
|
return reactphysics3d::Vector3{ ToEuler() };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SHQuaternion::operator XMVECTOR() const noexcept
|
||||||
|
{
|
||||||
|
return XMLoadFloat4(this);
|
||||||
|
}
|
||||||
|
|
||||||
SHQuaternion operator*(float lhs, const SHQuaternion& rhs) noexcept
|
SHQuaternion operator*(float lhs, const SHQuaternion& rhs) noexcept
|
||||||
{
|
{
|
||||||
return rhs * lhs;
|
return rhs * lhs;
|
||||||
|
@ -213,8 +170,7 @@ namespace SHADE
|
||||||
XMVECTOR axis;
|
XMVECTOR axis;
|
||||||
float angle;
|
float angle;
|
||||||
|
|
||||||
const XMVECTOR Q = XMLoadFloat4(this);
|
XMQuaternionToAxisAngle(&axis, &angle, *this);
|
||||||
XMQuaternionToAxisAngle(&axis, &angle, Q);
|
|
||||||
return angle;
|
return angle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -223,8 +179,7 @@ namespace SHADE
|
||||||
XMVECTOR axis;
|
XMVECTOR axis;
|
||||||
float angle;
|
float angle;
|
||||||
|
|
||||||
const XMVECTOR Q = XMLoadFloat4(this);
|
XMQuaternionToAxisAngle(&axis, &angle, *this);
|
||||||
XMQuaternionToAxisAngle(&axis, &angle, Q);
|
|
||||||
|
|
||||||
|
|
||||||
return SHVec4{XMVectorGetX(axis), XMVectorGetY(axis), XMVectorGetZ(axis), angle};
|
return SHVec4{XMVectorGetX(axis), XMVectorGetY(axis), XMVectorGetZ(axis), angle};
|
||||||
|
@ -238,64 +193,49 @@ namespace SHADE
|
||||||
|
|
||||||
void SHQuaternion::Invert() noexcept
|
void SHQuaternion::Invert() noexcept
|
||||||
{
|
{
|
||||||
const XMVECTOR Q = XMLoadFloat4(this);
|
XMStoreFloat4(this, XMQuaternionInverse(*this));
|
||||||
XMStoreFloat4(this, XMQuaternionInverse(Q));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float SHQuaternion::Length() const noexcept
|
float SHQuaternion::Length() const noexcept
|
||||||
{
|
{
|
||||||
const XMVECTOR Q = XMLoadFloat4(this);
|
return XMVectorGetX(XMQuaternionLength(*this));
|
||||||
return XMVectorGetX(XMQuaternionLength(Q));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float SHQuaternion::LengthSquared() const noexcept
|
float SHQuaternion::LengthSquared() const noexcept
|
||||||
{
|
{
|
||||||
const XMVECTOR Q = XMLoadFloat4(this);
|
return XMVectorGetX(XMQuaternionLengthSq(*this));
|
||||||
return XMVectorGetX(XMQuaternionLengthSq(Q));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float SHQuaternion::Dot(const SHQuaternion& rhs) const noexcept
|
float SHQuaternion::Dot(const SHQuaternion& rhs) const noexcept
|
||||||
{
|
{
|
||||||
const XMVECTOR Q1 = XMLoadFloat4(this);
|
return XMVectorGetX(XMQuaternionDot(*this, rhs));
|
||||||
const XMVECTOR Q2 = XMLoadFloat4(&rhs);
|
|
||||||
|
|
||||||
return XMVectorGetX(XMQuaternionDot(Q1, Q2));
|
|
||||||
}
|
|
||||||
|
|
||||||
SHQuaternion SHQuaternion::RotateTowards(const SHQuaternion&, float) const noexcept
|
|
||||||
{
|
|
||||||
SHQuaternion result;
|
|
||||||
|
|
||||||
// TODO (Diren)
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SHVec3 SHQuaternion::ToEuler() const noexcept
|
SHVec3 SHQuaternion::ToEuler() const noexcept
|
||||||
{
|
{
|
||||||
const float xx = x * x;
|
const float XX = x * x;
|
||||||
const float yy = y * y;
|
const float YY = y * y;
|
||||||
const float zz = z * z;
|
const float ZZ = z * z;
|
||||||
|
|
||||||
const float m31 = 2.f * x * z + 2.f * y * w;
|
const float M_31 = 2.f * x * z + 2.f * y * w;
|
||||||
const float m32 = 2.f * y * z - 2.f * x * w;
|
const float M_32 = 2.f * y * z - 2.f * x * w;
|
||||||
const float m33 = 1.f - 2.f * xx - 2.f * yy;
|
const float M_33 = 1.f - 2.f * XX - 2.f * YY;
|
||||||
|
|
||||||
const float cy = sqrtf(m33 * m33 + m31 * m31);
|
const float CY = sqrtf(M_33 * M_33 + M_31 * M_31);
|
||||||
const float cx = atan2f(-m32, cy);
|
const float CX = atan2f(-M_32, CY);
|
||||||
if (cy > 16.0f * SHMath::EPSILON)
|
if (CY > 16.0f * SHMath::EPSILON)
|
||||||
{
|
{
|
||||||
const float m12 = 2.f * x * y + 2.f * z * w;
|
const float M_12 = 2.f * x * y + 2.f * z * w;
|
||||||
const float m22 = 1.f - 2.f * xx - 2.f * zz;
|
const float M_22 = 1.f - 2.f * XX - 2.f * ZZ;
|
||||||
|
|
||||||
return SHVec3(cx, atan2f(m31, m33), atan2f(m12, m22));
|
return SHVec3(CX, atan2f(M_31, M_33), atan2f(M_12, M_22));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const float m11 = 1.f - 2.f * yy - 2.f * zz;
|
const float m11 = 1.f - 2.f * YY - 2.f * ZZ;
|
||||||
const float m21 = 2.f * x * y - 2.f * z * w;
|
const float m21 = 2.f * x * y - 2.f * z * w;
|
||||||
|
|
||||||
return SHVec3(cx, 0.f, atan2f(-m21, m11));
|
return SHVec3(CX, 0.f, atan2f(-m21, m11));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -311,13 +251,43 @@ namespace SHADE
|
||||||
/* Static Function Member Definitions */
|
/* Static Function Member Definitions */
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
SHQuaternion SHQuaternion::FromEuler(const SHVec3& eulerAngles) noexcept
|
||||||
|
{
|
||||||
|
SHQuaternion result;
|
||||||
|
|
||||||
|
XMStoreFloat4(&result, XMQuaternionRotationRollPitchYawFromVector(eulerAngles));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
SHQuaternion SHQuaternion::FromPitchYawRoll(float pitch, float yaw, float roll) noexcept
|
||||||
|
{
|
||||||
|
SHQuaternion result;
|
||||||
|
|
||||||
|
XMStoreFloat4(&result, XMQuaternionRotationRollPitchYaw(pitch, yaw, roll));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
SHQuaternion SHQuaternion::FromAxisAngle(const SHVec3& axis, float angle) noexcept
|
||||||
|
{
|
||||||
|
SHQuaternion result;
|
||||||
|
|
||||||
|
XMStoreFloat4(&result, XMQuaternionRotationAxis(axis, angle));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
SHQuaternion SHQuaternion::FromRotationMatrix(const SHMatrix& rotationMatrix) noexcept
|
||||||
|
{
|
||||||
|
SHQuaternion result;
|
||||||
|
|
||||||
|
XMStoreFloat4(&result, XMQuaternionRotationMatrix(rotationMatrix));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
SHQuaternion SHQuaternion::Normalise(const SHQuaternion& q) noexcept
|
SHQuaternion SHQuaternion::Normalise(const SHQuaternion& q) noexcept
|
||||||
{
|
{
|
||||||
SHQuaternion result;
|
SHQuaternion result;
|
||||||
|
|
||||||
const XMVECTOR Q = XMLoadFloat4(&q);
|
XMStoreFloat4(&result, XMQuaternionNormalize(q));
|
||||||
|
|
||||||
XMStoreFloat4(&result, XMQuaternionNormalize(Q));
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -325,9 +295,7 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
SHQuaternion result;
|
SHQuaternion result;
|
||||||
|
|
||||||
const XMVECTOR Q = XMLoadFloat4(&q);
|
XMStoreFloat4(&result, XMQuaternionConjugate(q));
|
||||||
|
|
||||||
XMStoreFloat4(&result, XMQuaternionConjugate(Q));
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -335,26 +303,37 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
SHQuaternion result;
|
SHQuaternion result;
|
||||||
|
|
||||||
const XMVECTOR Q = XMLoadFloat4(&q);
|
XMStoreFloat4(&result, XMQuaternionInverse(q));
|
||||||
XMStoreFloat4(&result, XMQuaternionInverse(Q));
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
float SHQuaternion::Angle(const SHQuaternion&, const SHQuaternion&) noexcept
|
float SHQuaternion::Angle(const SHQuaternion& q1, const SHQuaternion& q2) noexcept
|
||||||
{
|
{
|
||||||
// TODO (Diren)
|
XMVECTOR R = XMQuaternionMultiply(XMQuaternionConjugate(q1), q2);
|
||||||
|
|
||||||
return 0.0f;
|
const float RS = XMVectorGetW(R);
|
||||||
|
R = XMVector3Length(R);
|
||||||
|
return 2.0f * atan2f(XMVectorGetX(R), RS);
|
||||||
}
|
}
|
||||||
|
|
||||||
SHQuaternion SHQuaternion::Lerp(const SHQuaternion&, const SHQuaternion&, float) noexcept
|
SHQuaternion SHQuaternion::Lerp(const SHQuaternion& q1, const SHQuaternion& q2, float t) noexcept
|
||||||
{
|
{
|
||||||
SHQuaternion result;
|
SHQuaternion result;
|
||||||
|
|
||||||
// TODO (Diren)
|
XMVECTOR R = XMVectorZero();
|
||||||
|
if (XMVector4GreaterOrEqual(XMVector4Dot(q1, q2), R))
|
||||||
|
{
|
||||||
|
R = XMVectorLerp(q1, q2, t);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const XMVECTOR X0 = XMVectorMultiply(q1, XMVectorReplicate(1.f - t));
|
||||||
|
const XMVECTOR X1 = XMVectorMultiply(q2, XMVectorReplicate(t));
|
||||||
|
R = XMVectorSubtract(X0, X1);
|
||||||
|
}
|
||||||
|
|
||||||
|
XMStoreFloat4(&result, XMQuaternionNormalize(R));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -362,19 +341,105 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
SHQuaternion result;
|
SHQuaternion result;
|
||||||
|
|
||||||
const XMVECTOR Q1 = XMLoadFloat4(&q1);
|
XMStoreFloat4(&result, XMQuaternionSlerp(q1, q2, t));
|
||||||
const XMVECTOR Q2 = XMLoadFloat4(&q2);
|
|
||||||
|
|
||||||
XMStoreFloat4(&result, XMQuaternionSlerp(Q1, Q2, t));
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
SHQuaternion SHQuaternion::Rotate(const SHVec3& , const SHVec3&) noexcept
|
SHQuaternion SHQuaternion::ClampedLerp(const SHQuaternion& q1, const SHQuaternion& q2, float t, float tMin, float tMax) noexcept
|
||||||
|
{
|
||||||
|
return Lerp(q1, q2, std::clamp(t, tMin, tMax));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SHQuaternion SHQuaternion::ClampedSlerp(const SHQuaternion& q1, const SHQuaternion& q2, float t, float tMin, float tMax) noexcept
|
||||||
|
{
|
||||||
|
return Slerp(q1, q2, std::clamp(t, tMin, tMax));
|
||||||
|
}
|
||||||
|
|
||||||
|
SHQuaternion SHQuaternion::FromToRotation(const SHVec3& from, const SHVec3& to) noexcept
|
||||||
|
{
|
||||||
|
// Melax, "The Shortest Arc Quaternion", Game Programming Gems
|
||||||
|
|
||||||
|
SHQuaternion result;
|
||||||
|
|
||||||
|
const XMVECTOR F = XMVector3Normalize(from);
|
||||||
|
const XMVECTOR T = XMVector3Normalize(to);
|
||||||
|
|
||||||
|
const float dot = XMVectorGetX(XMVector3Dot(F, T));
|
||||||
|
if (dot >= 1.f)
|
||||||
|
{
|
||||||
|
result = Identity;
|
||||||
|
}
|
||||||
|
else if (dot <= -1.f)
|
||||||
|
{
|
||||||
|
XMVECTOR axis = XMVector3Cross(F, SHVec3::Right);
|
||||||
|
if (XMVector3NearEqual(XMVector3LengthSq(axis), g_XMZero, g_XMEpsilon))
|
||||||
|
{
|
||||||
|
axis = XMVector3Cross(F, SHVec3::Up);
|
||||||
|
}
|
||||||
|
|
||||||
|
const XMVECTOR Q = XMQuaternionRotationAxis(axis, XM_PI);
|
||||||
|
XMStoreFloat4(&result, Q);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const XMVECTOR C = XMVector3Cross(F, T);
|
||||||
|
XMStoreFloat4(&result, C);
|
||||||
|
|
||||||
|
const float s = sqrtf((1.f + dot) * 2.f);
|
||||||
|
result.x /= s;
|
||||||
|
result.y /= s;
|
||||||
|
result.z /= s;
|
||||||
|
result.w = s * 0.5f;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
SHQuaternion SHQuaternion::LookRotation(const SHVec3& forward, const SHVec3& up) noexcept
|
||||||
{
|
{
|
||||||
SHQuaternion result;
|
SHQuaternion result;
|
||||||
|
|
||||||
// TODO (Diren)
|
const SHQuaternion Q1 = FromToRotation(SHVec3::Forward, forward);
|
||||||
|
|
||||||
|
const XMVECTOR C = XMVector3Cross(forward, up);
|
||||||
|
if (XMVector3NearEqual(XMVector3LengthSq(C), g_XMZero, g_XMEpsilon))
|
||||||
|
{
|
||||||
|
// forward and up are co-linear
|
||||||
|
return Q1;
|
||||||
|
}
|
||||||
|
|
||||||
|
SHVec3 qU;
|
||||||
|
XMStoreFloat3(&qU, XMQuaternionMultiply(Q1, SHVec3::Up));
|
||||||
|
|
||||||
|
const SHQuaternion Q2 = FromToRotation(qU, up);
|
||||||
|
|
||||||
|
XMStoreFloat4(&result, XMQuaternionMultiply(Q2, Q1));
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
SHQuaternion SHQuaternion::RotateTowards(const SHQuaternion& from, const SHQuaternion& to, float maxAngleInRad) noexcept
|
||||||
|
{
|
||||||
|
SHQuaternion result;
|
||||||
|
|
||||||
|
// We can use the conjugate here instead of inverse assuming q1 & q2 are normalized.
|
||||||
|
const XMVECTOR R = XMQuaternionMultiply(XMQuaternionConjugate(from), to);
|
||||||
|
|
||||||
|
const float RS = XMVectorGetW(R);
|
||||||
|
const XMVECTOR L = XMVector3Length(R);
|
||||||
|
const float angle = 2.f * atan2f(XMVectorGetX(L), RS);
|
||||||
|
if (angle > maxAngleInRad)
|
||||||
|
{
|
||||||
|
const XMVECTOR delta = XMQuaternionRotationAxis(R, maxAngleInRad);
|
||||||
|
const XMVECTOR Q = XMQuaternionMultiply(delta, from);
|
||||||
|
XMStoreFloat4(&result, Q);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Don't overshoot.
|
||||||
|
result = to;
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -49,11 +49,8 @@ namespace SHADE
|
||||||
SHQuaternion (SHQuaternion&& rhs) = default;
|
SHQuaternion (SHQuaternion&& rhs) = default;
|
||||||
|
|
||||||
SHQuaternion () noexcept;
|
SHQuaternion () noexcept;
|
||||||
|
SHQuaternion (const SHVec4& vec4) noexcept;
|
||||||
SHQuaternion (float x, float y, float z, float w) noexcept;
|
SHQuaternion (float x, float y, float z, float w) noexcept;
|
||||||
SHQuaternion (float yaw, float pitch, float roll) noexcept;
|
|
||||||
SHQuaternion (const SHVec3& eulerAngles) noexcept;
|
|
||||||
SHQuaternion (const SHVec3& axis, float angleInRad) noexcept;
|
|
||||||
SHQuaternion (const SHMatrix& rotationMatrix) noexcept;
|
|
||||||
|
|
||||||
// Conversion from other math types
|
// Conversion from other math types
|
||||||
|
|
||||||
|
@ -87,6 +84,7 @@ namespace SHADE
|
||||||
|
|
||||||
operator reactphysics3d::Quaternion () const noexcept;
|
operator reactphysics3d::Quaternion () const noexcept;
|
||||||
operator reactphysics3d::Vector3 () const noexcept;
|
operator reactphysics3d::Vector3 () const noexcept;
|
||||||
|
operator DirectX::XMVECTOR () const noexcept;
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/* Getter Functions */
|
/* Getter Functions */
|
||||||
|
@ -99,29 +97,37 @@ namespace SHADE
|
||||||
/* Function Members */
|
/* Function Members */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
void Invert () noexcept;
|
void Invert () noexcept;
|
||||||
|
|
||||||
[[nodiscard]] float Length () const noexcept;
|
[[nodiscard]] float Length () const noexcept;
|
||||||
[[nodiscard]] float LengthSquared () const noexcept;
|
[[nodiscard]] float LengthSquared () const noexcept;
|
||||||
[[nodiscard]] float Dot (const SHQuaternion& rhs) const noexcept;
|
[[nodiscard]] float Dot (const SHQuaternion& rhs) const noexcept;
|
||||||
[[nodiscard]] SHQuaternion RotateTowards (const SHQuaternion& target, float maxAngleInRad) const noexcept;
|
|
||||||
|
|
||||||
[[nodiscard]] SHVec3 ToEuler () const noexcept;
|
[[nodiscard]] SHVec3 ToEuler () const noexcept;
|
||||||
[[nodiscard]] std::string ToString () const noexcept;
|
[[nodiscard]] std::string ToString () const noexcept;
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/* Static Function Members */
|
/* Static Function Members */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
[[nodiscard]] static SHQuaternion Normalise (const SHQuaternion& q) noexcept;
|
[[nodiscard]] static SHQuaternion FromEuler (const SHVec3& eulerAngles) noexcept;
|
||||||
[[nodiscard]] static SHQuaternion Conjugate (const SHQuaternion& q) noexcept;
|
[[nodiscard]] static SHQuaternion FromPitchYawRoll (float pitch, float yaw, float roll) noexcept;
|
||||||
[[nodiscard]] static SHQuaternion Inverse (const SHQuaternion& q) noexcept;
|
[[nodiscard]] static SHQuaternion FromAxisAngle (const SHVec3& axis, float angle) noexcept;
|
||||||
[[nodiscard]] static float Angle (const SHQuaternion& q1, const SHQuaternion& q2) noexcept;
|
[[nodiscard]] static SHQuaternion FromRotationMatrix(const SHMatrix& rotationMatrix) noexcept;
|
||||||
|
|
||||||
[[nodiscard]] static SHQuaternion Lerp (const SHQuaternion& q1, const SHQuaternion& q2, float t) noexcept;
|
[[nodiscard]] static SHQuaternion Normalise (const SHQuaternion& q) noexcept;
|
||||||
[[nodiscard]] static SHQuaternion Slerp (const SHQuaternion& q1, const SHQuaternion& q2, float t) noexcept;
|
[[nodiscard]] static SHQuaternion Conjugate (const SHQuaternion& q) noexcept;
|
||||||
|
[[nodiscard]] static SHQuaternion Inverse (const SHQuaternion& q) noexcept;
|
||||||
|
[[nodiscard]] static float Angle (const SHQuaternion& q1, const SHQuaternion& q2) noexcept;
|
||||||
|
|
||||||
[[nodiscard]] static SHQuaternion Rotate (const SHVec3& from, const SHVec3& to) noexcept;
|
[[nodiscard]] static SHQuaternion Lerp (const SHQuaternion& q1, const SHQuaternion& q2, float t) noexcept;
|
||||||
|
[[nodiscard]] static SHQuaternion Slerp (const SHQuaternion& q1, const SHQuaternion& q2, float t) noexcept;
|
||||||
|
[[nodiscard]] static SHQuaternion ClampedLerp (const SHQuaternion& q1, const SHQuaternion& q2, float t, float tMin = 0.0f, float tMax = 1.0f) noexcept;
|
||||||
|
[[nodiscard]] static SHQuaternion ClampedSlerp (const SHQuaternion& q1, const SHQuaternion& q2, float t, float tMin = 0.0f, float tMax = 1.0f) noexcept;
|
||||||
|
|
||||||
|
[[nodiscard]] static SHQuaternion FromToRotation (const SHVec3& from, const SHVec3& to) noexcept;
|
||||||
|
[[nodiscard]] static SHQuaternion LookRotation (const SHVec3& forward, const SHVec3& up) noexcept;
|
||||||
|
[[nodiscard]] static SHQuaternion RotateTowards (const SHQuaternion& from, const SHQuaternion& to, float maxAngleInRad) noexcept;
|
||||||
};
|
};
|
||||||
|
|
||||||
SHQuaternion operator*(float lhs, const SHQuaternion& rhs) noexcept;
|
SHQuaternion operator*(float lhs, const SHQuaternion& rhs) noexcept;
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue