Merge branch 'main' into SP3-8-serialization
This commit is contained in:
commit
6fd1cadf01
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
|
@ -19,10 +19,11 @@ echo "L - yamlcpp"
|
|||
echo "M - SDL"
|
||||
echo "N - dotnet"
|
||||
echo "O - tinyddsloader"
|
||||
echo "P - fmod"
|
||||
echo ---------------------------------------------------
|
||||
echo.
|
||||
|
||||
choice /C ABCDEFGHIJKLMNO /T 10 /D A
|
||||
choice /C ABCDEFGHIJKLMNOP /T 10 /D A
|
||||
set _e=%ERRORLEVEL%
|
||||
|
||||
if %_e%==1 goto VMA
|
||||
|
@ -40,6 +41,7 @@ if %_e%==12 goto yamlcpp
|
|||
if %_e%==13 goto SDL
|
||||
if %_e%==14 goto dotnet
|
||||
if %_e%==15 goto tinyddsloader
|
||||
if %_e%==16 goto fmod
|
||||
|
||||
:VMA
|
||||
echo -----------------------VMA----------------------------
|
||||
|
@ -144,7 +146,13 @@ if %_e%==14 (goto :done) else (goto :tinyddsloader)
|
|||
:tinyddsloader
|
||||
echo --------------------tinyddsloader-------------------------
|
||||
rmdir "Dependencies/tinyddsloader" /S /Q
|
||||
git clone https://github.com/benikabocha/tinyddsloader.git "Dependencies/tinyddsloader"
|
||||
git clone https://github.com/SHADE-DP/tinyddsloader.git "Dependencies/tinyddsloader"
|
||||
if %_e%==15 (goto :done) else (goto :fmod)
|
||||
|
||||
:fmod
|
||||
echo --------------------fmod-------------------------
|
||||
rmdir "Dependencies/fmod" /S /Q
|
||||
git clone https://github.com/SHADE-DP/FMOD.git "Dependencies/fmod"
|
||||
|
||||
:done
|
||||
echo DONE!
|
||||
|
|
|
@ -15,3 +15,4 @@ IncludeDir["SDL"] = "%{wks.location}\\Dependencies\\SDL"
|
|||
IncludeDir["VULKAN"] = "$(VULKAN_SDK)"
|
||||
IncludeDir["dotnet"] = "%{wks.location}\\Dependencies\\dotnet"
|
||||
IncludeDir["tinyddsloader"] = "%{wks.location}\\Dependencies\\tinyddsloader"
|
||||
IncludeDir["fmod"] = "%{wks.location}\\Dependencies\\fmod"
|
|
@ -30,12 +30,13 @@ project "SHADE_Application"
|
|||
|
||||
externalincludedirs
|
||||
{
|
||||
"%{IncludeDir.spdlog}/include",
|
||||
"%{IncludeDir.VULKAN}/include",
|
||||
"%{IncludeDir.VMA}/include",
|
||||
"%{IncludeDir.VULKAN}/Source/SPIRV-Reflect",
|
||||
"%{IncludeDir.RTTR}/include",
|
||||
"%{IncludeDir.tinyddsloader}"
|
||||
"%{IncludeDir.spdlog}/include",
|
||||
"%{IncludeDir.VULKAN}/include",
|
||||
"%{IncludeDir.VMA}/include",
|
||||
"%{IncludeDir.VULKAN}/Source/SPIRV-Reflect",
|
||||
"%{IncludeDir.tinyddsloader}",
|
||||
"%{IncludeDir.fmod}/include",
|
||||
"%{IncludeDir.RTTR}\\include"
|
||||
}
|
||||
|
||||
externalwarnings "Off"
|
||||
|
@ -66,9 +67,16 @@ project "SHADE_Application"
|
|||
|
||||
disablewarnings
|
||||
{
|
||||
"4251"
|
||||
"4251",
|
||||
"26812",
|
||||
"26439",
|
||||
"26451",
|
||||
"26437",
|
||||
"4275"
|
||||
}
|
||||
|
||||
linkoptions { "-IGNORE:4006" }
|
||||
|
||||
warnings 'Extra'
|
||||
|
||||
filter "configurations:Debug"
|
||||
|
@ -81,4 +89,4 @@ project "SHADE_Application"
|
|||
|
||||
filter "configurations:Publish"
|
||||
optimize "On"
|
||||
defines{"_RELEASE"}
|
||||
defines{"_RELEASE", "_PUBLISH"}
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
#include <chrono>
|
||||
#include <ratio>
|
||||
#include <ctime>
|
||||
#define SDL_HINT_VIDEO_FOREIGN_WINDOW_VULKAN 1
|
||||
#include <SDL.h>
|
||||
|
||||
#include "Scripting/SHScriptEngine.h"
|
||||
|
@ -23,13 +22,17 @@
|
|||
#include "Graphics/MiddleEnd/Interface/SHRenderable.h"
|
||||
#include "Scene/SHSceneManager.h"
|
||||
#include "Math/Transform/SHTransformSystem.h"
|
||||
#include "Input/SHInputManagerSystem.h"
|
||||
#include "Input/SHInputManager.h"
|
||||
#include "FRC/SHFramerateController.h"
|
||||
#include "AudioSystem/SHAudioSystem.h"
|
||||
|
||||
#include "Scenes/SBTestScene.h"
|
||||
#include "Math/Transform/SHTransformComponent.h"
|
||||
|
||||
#include "Assets/SHAssetManager.h"
|
||||
|
||||
#include "Tools/SHLogger.h"
|
||||
|
||||
using namespace SHADE;
|
||||
|
||||
namespace Sandbox
|
||||
|
@ -54,7 +57,7 @@ namespace Sandbox
|
|||
// TODO(Diren): Create Physics System here
|
||||
SHADE::SHSystemManager::CreateSystem<SHADE::SHTransformSystem>();
|
||||
SHADE::SHGraphicsSystem* graphicsSystem = static_cast<SHADE::SHGraphicsSystem*>(SHADE::SHSystemManager::GetSystem<SHADE::SHGraphicsSystem>());
|
||||
SHADE::SHSystemManager::CreateSystem<SHADE::SHInputManagerSystem>();
|
||||
SHADE::SHSystemManager::CreateSystem<SHADE::SHAudioSystem>();
|
||||
|
||||
// Create Routines
|
||||
SHADE::SHSystemManager::RegisterRoutine<SHADE::SHScriptEngine, SHADE::SHScriptEngine::FrameSetUpRoutine>();
|
||||
|
@ -75,13 +78,20 @@ namespace Sandbox
|
|||
SHADE::SHComponentManager::CreateComponentSparseSet<SHADE::SHRenderable>();
|
||||
SHADE::SHComponentManager::CreateComponentSparseSet<SHADE::SHTransformComponent>();
|
||||
|
||||
SHADE::SHSystemManager::RegisterRoutine<SHADE::SHInputManagerSystem, SHADE::SHInputManagerSystem::InputManagerRoutine>();
|
||||
//TODO: REMOVE AFTER PRESENTATION
|
||||
//SHADE::SHAssetManager::LoadDataTemp("../../Assets/racoon.gltf");
|
||||
SHADE::SHAssetManager::LoadDataTemp("../../Assets/Cube.012.shmesh");
|
||||
//SHADE::SHAssetManager::LoadDataTemp("../../Assets/RaccoonBag_Color_Ver4.dds");
|
||||
//SHADE::SHAssetManager::LoadDataTemp("../../Assets/RaccoonPreTexturedVer1_Base9.dds");
|
||||
SHADE::SHAssetManager::LoadDataTemp("../../Assets/RaccoonPreTexturedVer1_Base9.shtex");
|
||||
//TODO: REMOVE AFTER PRESENTATION
|
||||
|
||||
//TODO: REMOVE AFTER PRESENTATION
|
||||
SHADE::SHAssetManager::LoadDataTemp("../../Assets/racoon.fbx");
|
||||
SHADE::SHAssetManager::LoadDataTemp("../../Assets/RaccoonBag_Color_Ver4.dds");
|
||||
SHADE::SHAssetManager::LoadDataTemp("../../Assets/RaccoonPreTexturedVer1_Base9.dds");
|
||||
//TODO: REMOVE AFTER PRESENTATION
|
||||
|
||||
auto id = SHFamilyID<SHSystem>::GetID<SHGraphicsSystem>();
|
||||
auto id2 = SHFamilyID<SHSystem>::GetID<SHGraphicsSystem>();
|
||||
auto id3 = SHFamilyID<SHSystem>::GetID<SHGraphicsSystem>();
|
||||
|
||||
SHADE::SHSystemManager::RegisterRoutine<SHADE::SHAudioSystem, SHADE::SHAudioSystem::AudioRoutine>();
|
||||
|
||||
// Set up graphics system and windows
|
||||
graphicsSystem->SetWindow(&window);
|
||||
|
@ -94,7 +104,10 @@ namespace Sandbox
|
|||
#else
|
||||
#endif
|
||||
|
||||
|
||||
SHSceneManager::InitSceneManager<SBTestScene>("TestScene");
|
||||
|
||||
SHFrameRateController::UpdateFRC();
|
||||
}
|
||||
|
||||
void SBApplication::Update(void)
|
||||
|
@ -103,6 +116,8 @@ namespace Sandbox
|
|||
//TODO: Change true to window is open
|
||||
while (!window.WindowShouldClose())
|
||||
{
|
||||
SHFrameRateController::UpdateFRC();
|
||||
SHInputManager::UpdateInput(SHFrameRateController::GetRawDeltaTime());
|
||||
SHSceneManager::UpdateSceneManager();
|
||||
SHSceneManager::SceneUpdate(1/60.0f);
|
||||
//#ifdef SHEDITOR
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "Graphics/MiddleEnd/Interface/SHGraphicsSystem.h"
|
||||
#include "Scripting/SHScriptEngine.h"
|
||||
#include "Math/Transform/SHTransformComponent.h"
|
||||
#include "Graphics/MiddleEnd/Interface/SHMaterialInstance.h"
|
||||
|
||||
#include "Assets/SHAssetManager.h"
|
||||
|
||||
|
@ -35,86 +36,138 @@ namespace Sandbox
|
|||
SHADE::SHGraphicsSystem* graphicsSystem = static_cast<SHADE::SHGraphicsSystem*>(SHADE::SHSystemManager::GetSystem<SHADE::SHGraphicsSystem>());
|
||||
// Create temp meshes
|
||||
const auto CUBE_MESH = SHADE::SHPrimitiveGenerator::Cube(*graphicsSystem);
|
||||
//graphicsSystem->BuildMeshBuffers();
|
||||
|
||||
//Test Racoon mesh
|
||||
auto meshes = SHADE::SHAssetManager::GetAllMeshes();
|
||||
std::vector<Handle<SHMesh>> handles;
|
||||
for (auto const& mesh : meshes)
|
||||
{
|
||||
if (mesh.header.meshName == "Cube.012")
|
||||
{
|
||||
handles.push_back(graphicsSystem->AddMesh(
|
||||
mesh.header.vertexCount,
|
||||
mesh.vertexPosition.data(),
|
||||
mesh.texCoords.data(),
|
||||
mesh.vertexTangent.data(),
|
||||
mesh.vertexNormal.data(),
|
||||
mesh.header.indexCount,
|
||||
mesh.indices.data()
|
||||
));
|
||||
mesh.header.vertexCount,
|
||||
mesh.vertexPosition.data(),
|
||||
mesh.texCoords.data(),
|
||||
mesh.vertexTangent.data(),
|
||||
mesh.vertexNormal.data(),
|
||||
mesh.header.indexCount,
|
||||
mesh.indices.data()
|
||||
));
|
||||
}
|
||||
}
|
||||
graphicsSystem->BuildMeshBuffers();
|
||||
|
||||
// Load Textures
|
||||
auto textures = SHADE::SHAssetManager::GetAllTextures();
|
||||
std::vector<Handle<SHTexture>> texHandles;
|
||||
for (const auto& tex : textures)
|
||||
{
|
||||
auto texture = graphicsSystem->Add(tex);
|
||||
texHandles.push_back(texture);
|
||||
}
|
||||
graphicsSystem->BuildTextures();
|
||||
|
||||
// Create Materials
|
||||
auto matInst = graphicsSystem->AddOrGetBaseMaterialInstance();
|
||||
auto customMat = graphicsSystem->AddMaterialInstanceCopy(matInst);
|
||||
customMat->SetProperty("data.color", SHVec4(0.0f, 1.0f, 1.0f, 1.0f));
|
||||
customMat->SetProperty("data.textureIndex", 0);
|
||||
customMat->SetProperty("data.alpha", 0.1f);
|
||||
|
||||
// Create Stress Test Objects
|
||||
static const SHVec3 TEST_OBJ_SCALE = { 0.2f, 0.2f, 0.2f };
|
||||
constexpr int NUM_ROWS = 1;
|
||||
constexpr int NUM_COLS = 1;
|
||||
static const SHVec3 TEST_OBJ_SPACING = { 1.0f, 1.0f, 1.0f };
|
||||
static const SHVec3 TEST_OBJ_START_POS = { - (NUM_COLS / 2 * TEST_OBJ_SPACING.x ), 0.0f, 0.0f };
|
||||
//for (int z = 0; z < NUM_ROWS; ++z)
|
||||
//for (int x = 0; x < NUM_COLS; ++x)
|
||||
//{
|
||||
// auto entity = SHEntityManager::CreateEntity<SHRenderable, SHTransformComponent>();
|
||||
// auto& renderable = *SHComponentManager::GetComponent_s<SHRenderable>(entity);
|
||||
// auto& transform = *SHComponentManager::GetComponent_s<SHTransformComponent>(entity);
|
||||
|
||||
// renderable.Mesh = handles.front();
|
||||
// renderable.SetMaterial(matInst);
|
||||
|
||||
// // Set initial positions
|
||||
// transform.SetWorldPosition(TEST_OBJ_START_POS + SHVec3{ x * TEST_OBJ_SPACING.x, 0.0f, z * TEST_OBJ_SPACING.z });
|
||||
// //transform.SetLocalScale(TEST_OBJ_SCALE);
|
||||
|
||||
// stressTestObjects.emplace_back(entity);
|
||||
//}
|
||||
static const SHVec3 TEST_OBJ_SCALE = { 0.05f, 0.05f, 0.05f };
|
||||
constexpr int NUM_ROWS = 100;
|
||||
constexpr int NUM_COLS = 100;
|
||||
static const SHVec3 TEST_OBJ_SPACING = { 0.05f, 0.05f, 0.05f };
|
||||
static const SHVec3 TEST_OBJ_START_POS = { - (NUM_COLS / 2 * TEST_OBJ_SPACING.x ) + 1.0f, -2.0f, -1.0f };
|
||||
|
||||
for (int y = 0; y < NUM_ROWS; ++y)
|
||||
for (int x = 0; x < NUM_COLS; ++x)
|
||||
{
|
||||
auto entity = SHEntityManager::CreateEntity<SHRenderable, SHTransformComponent>();
|
||||
auto& renderable = *SHComponentManager::GetComponent_s<SHRenderable>(entity);
|
||||
auto& transform = *SHComponentManager::GetComponent_s<SHTransformComponent>(entity);
|
||||
|
||||
renderable.Mesh = handles.front();
|
||||
renderable.SetMaterial(matInst);
|
||||
renderable.SetMaterial(customMat);
|
||||
|
||||
//transform.SetLocalScale(TEST_OBJ_SCALE);
|
||||
if (y == 50)
|
||||
renderable.GetModifiableMaterial()->SetProperty("data.color", SHVec4(1.0f, 0.0f, 0.0f, 1.0f));
|
||||
|
||||
//Set initial positions
|
||||
transform.SetWorldPosition(TEST_OBJ_START_POS + SHVec3{
|
||||
x * TEST_OBJ_SPACING.x,
|
||||
y * TEST_OBJ_SPACING.y,
|
||||
0.0f
|
||||
});
|
||||
//transform.SetWorldPosition({-1.0f, -1.0f, -1.0f});
|
||||
//transform.SetWorldRotation(3.14159265f * 1.5f, -3.14159265f / 2.0f, 0.0f);
|
||||
transform.SetLocalScale(TEST_OBJ_SCALE);
|
||||
|
||||
stressTestObjects.emplace_back(entity);
|
||||
}
|
||||
|
||||
auto raccoonSpin = SHEntityManager::CreateEntity<SHRenderable, SHTransformComponent>();
|
||||
auto& renderable = *SHComponentManager::GetComponent_s<SHRenderable>(raccoonSpin);
|
||||
auto& transform = *SHComponentManager::GetComponent_s<SHTransformComponent>(raccoonSpin);
|
||||
|
||||
renderable.Mesh = handles.front();
|
||||
renderable.SetMaterial(customMat);
|
||||
renderable.GetModifiableMaterial()->SetProperty("data.color", SHVec4(0.0f, 0.0f, 0.0f, 0.0f));
|
||||
renderable.GetModifiableMaterial()->SetProperty("data.alpha", 1.0f);
|
||||
renderable.GetModifiableMaterial()->SetProperty("data.textureIndex", 0);
|
||||
|
||||
transform.SetWorldPosition ({-3.0f, -1.0f, -1.0f});
|
||||
transform.SetLocalScale({5.0f, 5.0f, 5.0f});
|
||||
|
||||
//auto entity = SHEntityManager::CreateEntity<SHRenderable, SHTransformComponent>();
|
||||
//auto& renderable = *SHComponentManager::GetComponent_s<SHRenderable>(entity);
|
||||
//auto& transform = *SHComponentManager::GetComponent_s<SHTransformComponent>(entity);
|
||||
|
||||
//renderable.Mesh = handles.back();
|
||||
//renderable.SetMaterial(customMat);
|
||||
|
||||
//transform.SetLocalScale(TEST_OBJ_SCALE);
|
||||
//transform.SetWorldPosition({-1.0f, -1.0f, -1.0f});
|
||||
|
||||
// Create blank entity with a script
|
||||
testObj = SHADE::SHEntityManager::CreateEntity();
|
||||
//testObj = SHADE::SHEntityManager::CreateEntity<SHRenderable, SHTransformComponent>();
|
||||
//auto& testObjRenderable = *SHComponentManager::GetComponent_s<SHRenderable>(testObj);
|
||||
//testObjRenderable.Mesh = CUBE_MESH;
|
||||
//testObjRenderable.SetMaterial(matInst);
|
||||
|
||||
SHADE::SHScriptEngine* scriptEngine = static_cast<SHADE::SHScriptEngine*>(SHADE::SHSystemManager::GetSystem<SHADE::SHScriptEngine>());
|
||||
scriptEngine->AddScript(testObj, "TestScript");
|
||||
scriptEngine->AddScript(raccoonSpin, "RaccoonSpin");
|
||||
|
||||
auto raccoonShowcase = SHEntityManager::CreateEntity<SHRenderable, SHTransformComponent>();
|
||||
auto& renderableShowcase = *SHComponentManager::GetComponent_s<SHRenderable>(raccoonShowcase);
|
||||
auto& transformShowcase = *SHComponentManager::GetComponent_s<SHTransformComponent>(raccoonShowcase);
|
||||
|
||||
renderableShowcase.Mesh = handles.front();
|
||||
renderableShowcase.SetMaterial(customMat);
|
||||
renderableShowcase.GetModifiableMaterial()->SetProperty("data.color", SHVec4(0.0f, 0.0f, 0.0f, 0.0f));
|
||||
renderableShowcase.GetModifiableMaterial()->SetProperty("data.alpha", 1.0f);
|
||||
renderableShowcase.GetModifiableMaterial()->SetProperty("data.textureIndex", 0);
|
||||
|
||||
transformShowcase.SetWorldPosition({ 3.0f, -1.0f, -1.0f });
|
||||
transformShowcase.SetLocalScale({ 5.0f, 5.0f, 5.0f });
|
||||
scriptEngine->AddScript(raccoonShowcase, "RaccoonShowcase");
|
||||
}
|
||||
|
||||
void SBTestScene::Update(float dt)
|
||||
{
|
||||
/*static float rotation = 0.0f;
|
||||
static float rotation = 0.0f;
|
||||
|
||||
auto& transform = *SHADE::SHComponentManager::GetComponent_s<SHADE::SHTransformComponent>(testObj);
|
||||
//auto& transform = *SHADE::SHComponentManager::GetComponent_s<SHADE::SHTransformComponent>(testObj);
|
||||
|
||||
transform.SetLocalRotation(rotation, 0.0f, 0.0f);
|
||||
rotation += dt * 10.0f;*/
|
||||
/*static float rotation = 0.0f;
|
||||
|
||||
auto& transform = *SHADE::SHComponentManager::GetComponent_s<SHADE::SHTransformComponent>(stressTestObjects[0]);
|
||||
|
||||
transform.SetWorldPosition({rotation, 0.0f, 0.0f});
|
||||
rotation += dt * 10.0f;*/
|
||||
//transform.SetWorldPosition({1.0f, 1.0f, -1.0f});
|
||||
//transform.SetWorldRotation(0.0f, 0.0f + rotation, 0.0f);
|
||||
//rotation += dt * 0.2f;
|
||||
|
||||
// Destroy entity if space is pressed
|
||||
if (GetKeyState(VK_SPACE) & 0x8000)
|
||||
{
|
||||
rotation = 0.0f;
|
||||
SHADE::SHScriptEngine* scriptEngine = static_cast<SHADE::SHScriptEngine*>(SHADE::SHSystemManager::GetSystem<SHADE::SHScriptEngine>());
|
||||
scriptEngine->RemoveAllScripts(testObj);
|
||||
}
|
||||
|
@ -122,6 +175,7 @@ namespace Sandbox
|
|||
|
||||
void SBTestScene::Render()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void SBTestScene::Unload()
|
||||
|
|
|
@ -42,7 +42,8 @@ project "SHADE_Engine"
|
|||
"%{IncludeDir.VULKAN}\\include",
|
||||
"%{IncludeDir.VULKAN}\\Source\\SPIRV-Reflect",
|
||||
"%{IncludeDir.dotnet}\\include",
|
||||
"%{IncludeDir.tinyddsloader}"
|
||||
"%{IncludeDir.tinyddsloader}",
|
||||
"%{IncludeDir.fmod}\\include"
|
||||
}
|
||||
|
||||
externalwarnings "Off"
|
||||
|
@ -55,7 +56,8 @@ project "SHADE_Engine"
|
|||
"%{IncludeDir.assimp}/lib/Release",
|
||||
"%{IncludeDir.RTTR}/lib",
|
||||
"%{IncludeDir.SDL}/lib",
|
||||
"%{IncludeDir.spdlog}/lib"
|
||||
"%{IncludeDir.spdlog}/lib",
|
||||
"%{IncludeDir.fmod}/lib",
|
||||
}
|
||||
|
||||
links
|
||||
|
@ -74,9 +76,16 @@ project "SHADE_Engine"
|
|||
|
||||
disablewarnings
|
||||
{
|
||||
"4251"
|
||||
"4251",
|
||||
"26812",
|
||||
"26439",
|
||||
"26451",
|
||||
"26437",
|
||||
"4275"
|
||||
}
|
||||
|
||||
linkoptions { "-IGNORE:4006" }
|
||||
|
||||
defines
|
||||
{
|
||||
"_LIB",
|
||||
|
@ -108,9 +117,30 @@ project "SHADE_Engine"
|
|||
}
|
||||
|
||||
filter "configurations:Debug"
|
||||
postbuildcommands {"xcopy /r /y /q \"%{IncludeDir.assimp}\\bin\\Debug\\assimp-vc142-mtd.dll\" \"$(OutDir)\""}
|
||||
postbuildcommands
|
||||
{
|
||||
"xcopy /r /y /q \"%{IncludeDir.assimp}\\bin\\Debug\\assimp-vc142-mtd.dll\" \"$(OutDir)\"",
|
||||
"xcopy /r /y /q \"%{IncludeDir.fmod}\\lib\\fmodL.dll\" \"$(OutDir)\"",
|
||||
"xcopy /r /y /q \"%{IncludeDir.fmod}\\lib\\fmodstudioL.dll\" \"$(OutDir)\""
|
||||
}
|
||||
|
||||
filter "configurations:Release"
|
||||
postbuildcommands
|
||||
{
|
||||
"xcopy /r /y /q \"%{IncludeDir.assimp}\\bin\\Release\\assimp-vc142-mt.dll\" \"$(OutDir)\"",
|
||||
"xcopy /r /y /q \"%{IncludeDir.fmod}\\lib\\fmod.dll\" \"$(OutDir)\"",
|
||||
"xcopy /r /y /q \"%{IncludeDir.fmod}\\lib\\fmodstudio.dll\" \"$(OutDir)\""
|
||||
}
|
||||
|
||||
filter "configurations:Publish"
|
||||
postbuildcommands
|
||||
{
|
||||
"xcopy /r /y /q \"%{IncludeDir.assimp}\\bin\\Release\\assimp-vc142-mt.dll\" \"$(OutDir)\"",
|
||||
"xcopy /r /y /q \"%{IncludeDir.fmod}\\lib\\fmod.dll\" \"$(OutDir)\"",
|
||||
"xcopy /r /y /q \"%{IncludeDir.fmod}\\lib\\fmodstudio.dll\" \"$(OutDir)\""
|
||||
}
|
||||
|
||||
filter "configurations:Publish"
|
||||
postbuildcommands {"xcopy /r /y /q \"%{IncludeDir.assimp}\\bin\\Release\\assimp-vc142-mt.dll\" \"$(OutDir)\""}
|
||||
|
||||
warnings 'Extra'
|
||||
|
@ -119,17 +149,17 @@ project "SHADE_Engine"
|
|||
symbols "On"
|
||||
defines {"_DEBUG", "SHEDITOR"}
|
||||
links{"assimp-vc142-mtd.lib", "librttr_core_d.lib", "spdlogd.lib"}
|
||||
--links{"fmodstudioL_vc.lib", "fmodL_vc.lib"}
|
||||
links{"fmodstudioL_vc.lib", "fmodL_vc.lib"}
|
||||
|
||||
filter "configurations:Release"
|
||||
optimize "On"
|
||||
defines{"_RELEASE", "SHEDITOR"}
|
||||
links{"assimp-vc142-mt.lib", "librttr_core.lib", "spdlog.lib"}
|
||||
--links{"fmodstudio_vc.lib", "fmod_vc.lib"}
|
||||
links{"fmodstudio_vc.lib", "fmod_vc.lib"}
|
||||
|
||||
filter "configurations:Publish"
|
||||
optimize "On"
|
||||
defines{"_RELEASE"}
|
||||
defines{"_RELEASE", "_PUBLISH"}
|
||||
links{"assimp-vc142-mt.lib", "librttr_core.lib", "spdlog.lib"}
|
||||
excludes
|
||||
{
|
||||
|
@ -137,4 +167,4 @@ project "SHADE_Engine"
|
|||
"%{prj.location}/src/Editor/**.h",
|
||||
"%{prj.location}/src/Editor/**.hpp",
|
||||
}
|
||||
--links{"fmodstudio_vc.lib", "fmod_vc.lib"}
|
||||
links{"fmodstudio_vc.lib", "fmod_vc.lib"}
|
|
@ -1,11 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "tinyddsloader.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
struct SHDDSAsset
|
||||
{
|
||||
tinyddsloader::DDSFile image;
|
||||
};
|
||||
}
|
|
@ -1,25 +1,37 @@
|
|||
/*************************************************************************//**
|
||||
* \file SHMeshAsset.h
|
||||
* \author Loh Xiao Qi
|
||||
* \date 30 September 2022
|
||||
* \brief Struct to contain ready data for loading into GPU. Also used for
|
||||
* compilation into binary files
|
||||
*
|
||||
*
|
||||
* 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 "Math/SHMath.h"
|
||||
#include "SH_API.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
struct SHMeshAssetHeader
|
||||
struct SH_API SHMeshAssetHeader
|
||||
{
|
||||
uint32_t vertexCount;
|
||||
uint32_t indexCount;
|
||||
std::string meshName;
|
||||
};
|
||||
|
||||
struct SHMeshAsset
|
||||
struct SH_API SHMeshAsset
|
||||
{
|
||||
bool compiled;
|
||||
bool changed;
|
||||
|
||||
SHMeshAssetHeader header;
|
||||
|
||||
std::string meshName;
|
||||
|
||||
std::vector<SHVec3> vertexPosition;
|
||||
std::vector<SHVec3> vertexTangent;
|
||||
std::vector<SHVec3> vertexNormal;
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
#pragma once
|
||||
|
||||
#include "tinyddsloader.h"
|
||||
#include "Graphics/MiddleEnd/Textures/SHTextureLibrary.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
struct SHTextureAsset
|
||||
{
|
||||
bool compiled;
|
||||
|
||||
uint32_t numBytes;
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
SHTexture::TextureFormat format;
|
||||
std::vector<uint32_t> mipOffsets;
|
||||
SHTexture::PixelChannel const * pixelData;
|
||||
|
||||
SHTextureAsset()
|
||||
: numBytes{ 0 },
|
||||
width{ 0 },
|
||||
height{ 0 },
|
||||
format{ SHTexture::TextureFormat::eUndefined },
|
||||
pixelData{ nullptr }
|
||||
{}
|
||||
|
||||
SHTextureAsset(SHTextureAsset const& rhs)
|
||||
: numBytes{ rhs.numBytes },
|
||||
width{ rhs.width },
|
||||
height{ rhs.height },
|
||||
format{ rhs.format },
|
||||
mipOffsets{ rhs.mipOffsets },
|
||||
pixelData(rhs.pixelData)
|
||||
{}
|
||||
|
||||
//SHTextureAsset(SHTextureAsset&& rhs)
|
||||
// : numBytes{ rhs.numBytes },
|
||||
// width{ rhs.width },
|
||||
// height{ rhs.height },
|
||||
// format{ rhs.format },
|
||||
// mipOffsets{ rhs.mipOffsets },
|
||||
// pixelData(std::move(rhs.pixelData))
|
||||
//{}
|
||||
};
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
#include "SHpch.h"
|
||||
#include "SHDDSLoader.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
std::string SHDDSLoader::TinyDDSResultToString(tinyddsloader::Result value)
|
||||
{
|
||||
switch (value)
|
||||
{
|
||||
case tinyddsloader::Result::ErrorFileOpen:
|
||||
return "File open err";
|
||||
case tinyddsloader::Result::ErrorRead:
|
||||
return "File read err";
|
||||
case tinyddsloader::Result::ErrorMagicWord:
|
||||
return "File header magicword err";
|
||||
case tinyddsloader::Result::ErrorSize:
|
||||
return "File size err";
|
||||
case tinyddsloader::Result::ErrorVerify:
|
||||
return "Pixel format err";
|
||||
case tinyddsloader::Result::ErrorNotSupported:
|
||||
return "Unsupported format";
|
||||
case tinyddsloader::Result::ErrorInvalidData:
|
||||
return "Invalid data";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
void SHDDSLoader::LoadImageAsset(AssetPath path, SHDDSAsset& asset)
|
||||
{
|
||||
tinyddsloader::Result loadResult = tinyddsloader::Result::Success;
|
||||
loadResult = asset.image.Load(path.string().c_str());
|
||||
if (loadResult != tinyddsloader::Result::Success)
|
||||
{
|
||||
SHLOG_ERROR("Unable to load DDS file: {} at {}", TinyDDSResultToString(loadResult), path.string());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
#pragma once
|
||||
#define TINYDDSLOADER_IMPLEMENTATION
|
||||
|
||||
#include "../SHAssetMacros.h"
|
||||
#include "../Asset Types/SHDDSAsset.h"
|
||||
#include "tinyddsloader.h"
|
||||
#include <vector>
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
class SHDDSLoader
|
||||
{
|
||||
private:
|
||||
static std::string TinyDDSResultToString(tinyddsloader::Result value);
|
||||
public:
|
||||
static void LoadImageAsset(AssetPath paths, SHDDSAsset& image);
|
||||
};
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
/*************************************************************************//**
|
||||
* \file SHMeshCompiler.cpp
|
||||
* \author Loh Xiao Qi
|
||||
* \date 30 September 2022
|
||||
* \brief Library to write data in SHMeshAsset into binary file for faster
|
||||
* loading in the future
|
||||
*
|
||||
*
|
||||
* 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 "SHMeshCompiler.h"
|
||||
#include "Graphics/MiddleEnd/Meshes/SHMeshData.h"
|
||||
|
||||
#include <fstream>
|
||||
|
||||
void SHADE::SHMeshCompiler::CompileMeshBinary(SHMeshAsset const& asset, AssetPath path) noexcept
|
||||
{
|
||||
std::string newPath{ path.string() };
|
||||
newPath = newPath.substr(0, newPath.find_last_of('/') + 1);
|
||||
newPath += asset.header.meshName + MESH_EXTENSION;
|
||||
|
||||
std::ofstream file{ newPath, std::ios::out | std::ios::binary | std::ios::trunc };
|
||||
if (!file.is_open())
|
||||
{
|
||||
SHLOG_ERROR("Unable to open file for writing mesh file: {}", path.string());
|
||||
}
|
||||
|
||||
file.write(
|
||||
reinterpret_cast<char const*>(&(asset.header.vertexCount)),
|
||||
sizeof(uint32_t)
|
||||
);
|
||||
|
||||
file.write(
|
||||
reinterpret_cast<const char*>(&(asset.header.indexCount)),
|
||||
sizeof(uint32_t)
|
||||
);
|
||||
|
||||
auto const vertexVec3Byte {sizeof(SHVec3) * asset.header.vertexCount};
|
||||
auto const vertexVec2Byte {sizeof(SHVec2) * asset.header.vertexCount};
|
||||
|
||||
file.write(
|
||||
reinterpret_cast<char const*>(asset.vertexPosition.data()),
|
||||
vertexVec3Byte
|
||||
);
|
||||
|
||||
file.write(
|
||||
reinterpret_cast<char const*>(asset.vertexTangent.data()),
|
||||
vertexVec3Byte
|
||||
);
|
||||
|
||||
file.write(
|
||||
reinterpret_cast<char const*>(asset.vertexNormal.data()),
|
||||
vertexVec3Byte
|
||||
);
|
||||
|
||||
file.write(
|
||||
reinterpret_cast<char const*>(asset.texCoords.data()),
|
||||
vertexVec2Byte
|
||||
);
|
||||
|
||||
file.write(
|
||||
reinterpret_cast<char const*>(asset.indices.data()),
|
||||
sizeof(uint32_t) * asset.header.indexCount
|
||||
);
|
||||
|
||||
file.close();
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
/*************************************************************************//**
|
||||
* \file SHMeshCompiler.h
|
||||
* \author Loh Xiao Qi
|
||||
* \date 30 September 2022
|
||||
* \brief Library to write data in SHMeshAsset into binary file for faster
|
||||
* loading in the future
|
||||
*
|
||||
*
|
||||
* 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 "../Asset Types/SHMeshAsset.h"
|
||||
#include "../SHAssetMacros.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
class SHMeshCompiler
|
||||
{
|
||||
private:
|
||||
public:
|
||||
static void CompileMeshBinary(SHMeshAsset const& asset, AssetPath path) noexcept;
|
||||
};
|
||||
}
|
|
@ -1,12 +1,25 @@
|
|||
/*************************************************************************//**
|
||||
* \file SHMeshLoader.cpp
|
||||
* \author Loh Xiao Qi
|
||||
* \date 30 September 2022
|
||||
* \brief Implementation for Mesh loader. Accounts for custom binary format
|
||||
* as well as GLTF file format.
|
||||
*
|
||||
*
|
||||
* 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 "SHMeshLoader.h"
|
||||
#include <assimp/postprocess.h>
|
||||
#include <fstream>
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
Assimp::Importer SHMeshLoader::aiImporter;
|
||||
|
||||
void SHMeshLoader::ProcessNode(aiNode const& node, aiScene const& scene, std::vector<SHMeshAsset>& meshes)
|
||||
void SHMeshLoader::ProcessNode(aiNode const& node, aiScene const& scene, std::vector<SHMeshAsset>& meshes) noexcept
|
||||
{
|
||||
for (size_t i {0}; i < node.mNumMeshes; ++i)
|
||||
{
|
||||
|
@ -20,15 +33,14 @@ namespace SHADE
|
|||
}
|
||||
}
|
||||
|
||||
SHMeshAsset SHMeshLoader::ProcessMesh(aiMesh const& mesh, aiScene const& scene)
|
||||
SHMeshAsset SHMeshLoader::ProcessMesh(aiMesh const& mesh, aiScene const& scene) noexcept
|
||||
{
|
||||
(void)scene;
|
||||
|
||||
SHMeshAsset result
|
||||
{
|
||||
.compiled { false},
|
||||
.changed { false },
|
||||
.meshName { mesh.mName.C_Str() }
|
||||
.changed { false }
|
||||
};
|
||||
|
||||
for (size_t i{0}; i < mesh.mNumVertices; ++i)
|
||||
|
@ -81,36 +93,31 @@ namespace SHADE
|
|||
|
||||
result.header.vertexCount = result.vertexPosition.size();
|
||||
result.header.indexCount = result.indices.size();
|
||||
result.header.meshName = mesh.mName.C_Str();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool SHMeshLoader::LoadMesh(std::vector<SHMeshAsset>& meshes, AssetPath path)
|
||||
{
|
||||
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_PreTransformVertices // pre-transform all vertices
|
||||
| aiProcess_FlipUVs // flip the V to match the Vulkans way of doing UVs
|
||||
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 false;
|
||||
return;
|
||||
}
|
||||
|
||||
//TODO MATERIALS FROM MESHES
|
||||
//if (scene->HasMaterials())
|
||||
//{
|
||||
|
@ -118,14 +125,108 @@ namespace SHADE
|
|||
// {
|
||||
// if (scene->mMaterials[i]->mNumProperties > 0)
|
||||
// {
|
||||
// for (int j{0}; j < scene->mMaterials[i]->mProperties[j].)
|
||||
// for (int j{0}; j < scene->mMaterials[i]->mProperties[j].)
|
||||
// }
|
||||
//std::cout << scene->mMaterials[i]->;
|
||||
//std::cout << scene->mMaterials[i]->;
|
||||
// }
|
||||
//}
|
||||
|
||||
ProcessNode(*scene->mRootNode, *scene, meshes);
|
||||
}
|
||||
|
||||
return true;
|
||||
void SHMeshLoader::LoadSHMesh(SHMeshAsset& mesh, AssetPath path) noexcept
|
||||
{
|
||||
std::ifstream file{ path.string(), std::ios::in | std::ios::binary };
|
||||
if (!file.is_open())
|
||||
{
|
||||
SHLOG_ERROR("Unable to open SHMesh File: {}", path.string());
|
||||
}
|
||||
|
||||
std::string name{ path.filename().string() };
|
||||
name = name.substr(0, name.find_last_of('.'));
|
||||
|
||||
file.seekg(0);
|
||||
|
||||
uint32_t vertCount, indexCount;
|
||||
std::vector<SHVec3> vertPos, vertTan, vertNorm;
|
||||
std::vector<SHVec2> texCoord;
|
||||
std::vector<uint32_t> indices;
|
||||
|
||||
file.read(reinterpret_cast<char*>(&vertCount), sizeof(uint32_t));
|
||||
file.read(reinterpret_cast<char*>(&indexCount), sizeof(uint32_t));
|
||||
|
||||
auto const vertexVec3Byte{ sizeof(SHVec3) * vertCount };
|
||||
auto const vertexVec2Byte{ sizeof(SHVec2) * vertCount };
|
||||
|
||||
vertPos.resize(vertCount);
|
||||
vertTan.resize(vertCount);
|
||||
vertNorm.resize(vertCount);
|
||||
texCoord.resize(vertCount);
|
||||
indices.resize(indexCount);
|
||||
|
||||
file.read(reinterpret_cast<char *>(vertPos.data()), vertexVec3Byte);
|
||||
file.read(reinterpret_cast<char *>(vertTan.data()), vertexVec3Byte);
|
||||
file.read(reinterpret_cast<char *>(vertNorm.data()), vertexVec3Byte);
|
||||
file.read(reinterpret_cast<char *>(texCoord.data()), vertexVec2Byte);
|
||||
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.changed = false;
|
||||
|
||||
mesh.header.indexCount = indexCount;
|
||||
mesh.header.vertexCount = vertCount;
|
||||
mesh.header.meshName = name;
|
||||
|
||||
mesh.vertexPosition = std::move(vertPos);
|
||||
mesh.vertexTangent = std::move(vertTan);
|
||||
mesh.vertexNormal = std::move(vertNorm);
|
||||
mesh.texCoords = std::move(texCoord);
|
||||
mesh.indices = std::move(indices);
|
||||
|
||||
file.close();
|
||||
}
|
||||
|
||||
void SHMeshLoader::LoadMesh(std::vector<SHMeshAsset>& meshes, AssetPath path) noexcept
|
||||
{
|
||||
if (path.extension().string() == GLTF_EXTENSION)
|
||||
{
|
||||
LoadExternal(meshes, path);
|
||||
return;
|
||||
}
|
||||
|
||||
meshes.emplace_back();
|
||||
LoadSHMesh(meshes.back(), path);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,14 @@
|
|||
/*************************************************************************//**
|
||||
* \file SHMeshLoader.h
|
||||
* \author Loh Xiao Qi
|
||||
* \date 30 September 2022
|
||||
* \brief Library to load gltf mesh files and custom binary format
|
||||
*
|
||||
*
|
||||
* 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>
|
||||
|
@ -12,10 +23,14 @@ namespace SHADE
|
|||
private:
|
||||
static Assimp::Importer aiImporter;
|
||||
|
||||
static void ProcessNode(aiNode const& node, aiScene const& scene, std::vector<SHMeshAsset>& meshes);
|
||||
static void ProcessNode(aiNode const& node, aiScene const& scene, std::vector<SHMeshAsset>& meshes) noexcept;
|
||||
|
||||
static SHMeshAsset ProcessMesh(aiMesh const& mesh, aiScene const& scene);
|
||||
static SHMeshAsset ProcessMesh(aiMesh const& mesh, aiScene const& scene) noexcept;
|
||||
|
||||
static void LoadExternal(std::vector<SHMeshAsset>& meshes, AssetPath path) noexcept;
|
||||
|
||||
static void LoadSHMesh(SHMeshAsset& meshes, AssetPath path) noexcept;
|
||||
public:
|
||||
static bool LoadMesh(std::vector<SHMeshAsset>& meshes, AssetPath path);
|
||||
static void LoadMesh(std::vector<SHMeshAsset>& meshes, AssetPath path) noexcept;
|
||||
};
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
/*************************************************************************//**
|
||||
* \file SHTextureCompiler.cpp
|
||||
* \author Loh Xiao Qi
|
||||
* \date 30 September 2022
|
||||
* \brief Library to write data in SHTextureAsset into binary file for
|
||||
* faster loading in the future
|
||||
*
|
||||
*
|
||||
* 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 "SHTextureCompiler.h"
|
||||
|
||||
#include <fstream>
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
void SHTextureCompiler::CompileTextureBinary(SHTextureAsset const& asset, AssetPath path)
|
||||
{
|
||||
std::string newPath{ path.string() };
|
||||
newPath = newPath.substr(0, newPath.find_last_of('.'));
|
||||
newPath += TEXTURE_EXTENSION;
|
||||
|
||||
std::ofstream file{ newPath, std::ios::out | std::ios::binary };
|
||||
if (!file.is_open())
|
||||
{
|
||||
SHLOG_ERROR("Unable to open file for writing texture file: {}", path.string());
|
||||
}
|
||||
|
||||
auto const intBytes{sizeof(uint32_t)};
|
||||
|
||||
uint32_t mipOffsetCount{ static_cast<uint32_t>(asset.mipOffsets.size()) };
|
||||
|
||||
file.write(
|
||||
reinterpret_cast<char const*>(&asset.numBytes),
|
||||
intBytes
|
||||
);
|
||||
|
||||
file.write(
|
||||
reinterpret_cast<char const*>(&asset.width),
|
||||
intBytes
|
||||
);
|
||||
|
||||
file.write(
|
||||
reinterpret_cast<char const*>(&asset.height),
|
||||
intBytes
|
||||
);
|
||||
|
||||
file.write(
|
||||
reinterpret_cast<char const*>(&asset.format),
|
||||
sizeof(SHTexture::TextureFormat)
|
||||
);
|
||||
|
||||
file.write(
|
||||
reinterpret_cast<char const*>(&mipOffsetCount),
|
||||
intBytes
|
||||
);
|
||||
|
||||
file.write(
|
||||
reinterpret_cast<char const*>(asset.mipOffsets.data()),
|
||||
intBytes * asset.mipOffsets.size()
|
||||
);
|
||||
|
||||
file.write(
|
||||
reinterpret_cast<char const*>(asset.pixelData),
|
||||
asset.numBytes
|
||||
);
|
||||
|
||||
file.close();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
/*************************************************************************//**
|
||||
* \file SHTextureCompiler.h
|
||||
* \author Loh Xiao Qi
|
||||
* \date 30 September 2022
|
||||
* \brief Library to write data in SHTextureAsset into binary file for
|
||||
* faster loading in the future
|
||||
*
|
||||
*
|
||||
* 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/SHTextureAsset.h"
|
||||
#include "Assets/SHAssetMacros.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
struct SHTextureCompiler
|
||||
{
|
||||
static void CompileTextureBinary(SHTextureAsset const& asset, AssetPath path);
|
||||
};
|
||||
}
|
|
@ -0,0 +1,146 @@
|
|||
/*************************************************************************//**
|
||||
* \file SHTextureLoader.cpp
|
||||
* \author Loh Xiao Qi
|
||||
* \date 30 September 2022
|
||||
* \brief Library to load dds textures and custom binary format
|
||||
*
|
||||
*
|
||||
* 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 "SHTextureLoader.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
std::string SHTextureLoader::TinyDDSResultToString(tinyddsloader::Result value)
|
||||
{
|
||||
switch (value)
|
||||
{
|
||||
case tinyddsloader::Result::ErrorFileOpen:
|
||||
return "File open err";
|
||||
case tinyddsloader::Result::ErrorRead:
|
||||
return "File read err";
|
||||
case tinyddsloader::Result::ErrorMagicWord:
|
||||
return "File header magic word err";
|
||||
case tinyddsloader::Result::ErrorSize:
|
||||
return "File size err";
|
||||
case tinyddsloader::Result::ErrorVerify:
|
||||
return "Pixel format err";
|
||||
case tinyddsloader::Result::ErrorNotSupported:
|
||||
return "Unsupported format";
|
||||
case tinyddsloader::Result::ErrorInvalidData:
|
||||
return "Invalid data";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
vk::Format SHTextureLoader::ddsLoaderToVkFormat(tinyddsloader::DDSFile::DXGIFormat format, bool isLinear)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case tinyddsloader::DDSFile::DXGIFormat::BC1_UNorm:
|
||||
case tinyddsloader::DDSFile::DXGIFormat::BC1_UNorm_SRGB:
|
||||
return isLinear ? vk::Format::eBc1RgbaUnormBlock : vk::Format::eBc1RgbaSrgbBlock;
|
||||
case tinyddsloader::DDSFile::DXGIFormat::BC2_UNorm:
|
||||
case tinyddsloader::DDSFile::DXGIFormat::BC2_UNorm_SRGB:
|
||||
return isLinear ? vk::Format::eBc2UnormBlock : vk::Format::eBc2SrgbBlock;
|
||||
case tinyddsloader::DDSFile::DXGIFormat::BC3_UNorm:
|
||||
case tinyddsloader::DDSFile::DXGIFormat::BC3_UNorm_SRGB:
|
||||
return isLinear ? vk::Format::eBc3UnormBlock : vk::Format::eBc3SrgbBlock;
|
||||
case tinyddsloader::DDSFile::DXGIFormat::BC5_UNorm:
|
||||
case tinyddsloader::DDSFile::DXGIFormat::BC5_SNorm:
|
||||
return isLinear ? vk::Format::eBc5UnormBlock : vk::Format::eBc5SnormBlock;
|
||||
case tinyddsloader::DDSFile::DXGIFormat::R8G8B8A8_UNorm:
|
||||
case tinyddsloader::DDSFile::DXGIFormat::R8G8B8A8_UNorm_SRGB:
|
||||
return isLinear ? vk::Format::eR8G8B8A8Unorm : vk::Format::eR8G8B8A8Srgb;
|
||||
case tinyddsloader::DDSFile::DXGIFormat::R8G8B8A8_SNorm:
|
||||
return vk::Format::eR8G8B8A8Snorm;
|
||||
case tinyddsloader::DDSFile::DXGIFormat::B8G8R8A8_UNorm:
|
||||
case tinyddsloader::DDSFile::DXGIFormat::B8G8R8A8_UNorm_SRGB:
|
||||
return isLinear ? vk::Format::eB8G8R8A8Unorm : vk::Format::eB8G8R8A8Srgb;
|
||||
case tinyddsloader::DDSFile::DXGIFormat::B8G8R8X8_UNorm:
|
||||
case tinyddsloader::DDSFile::DXGIFormat::B8G8R8X8_UNorm_SRGB:
|
||||
return isLinear ? vk::Format::eB8G8R8A8Unorm : vk::Format::eB8G8R8Srgb;
|
||||
default:
|
||||
throw std::runtime_error("Unsupported DDS format.");
|
||||
}
|
||||
}
|
||||
|
||||
void SHTextureLoader::LoadTinyDDS(AssetPath path, SHTextureAsset& asset) noexcept
|
||||
{
|
||||
tinyddsloader::Result loadResult = tinyddsloader::Result::Success;
|
||||
tinyddsloader::DDSFile file;
|
||||
loadResult = file.Load(path.string().c_str());
|
||||
if (loadResult != tinyddsloader::Result::Success)
|
||||
{
|
||||
SHLOG_ERROR("Unable to load Texture file: {} at {}", TinyDDSResultToString(loadResult), path.string());
|
||||
}
|
||||
|
||||
size_t totalBytes{ 0 };
|
||||
|
||||
std::vector<uint32_t> mipOff(file.GetMipCount());
|
||||
|
||||
for (auto i{0}; i < file.GetMipCount(); ++i)
|
||||
{
|
||||
mipOff[i] = totalBytes;
|
||||
totalBytes += file.GetImageData(i, 0)->m_memSlicePitch;
|
||||
}
|
||||
|
||||
SHTexture::PixelChannel* pixel = new SHTexture::PixelChannel[totalBytes];
|
||||
std::memcpy(pixel, file.GetImageData()->m_mem, totalBytes);
|
||||
//pixel = std::move(reinterpret_cast<SHTexture::PixelChannel const*>(file.GetDDSData()));
|
||||
|
||||
asset.compiled = false;
|
||||
asset.numBytes = totalBytes;
|
||||
asset.width = file.GetWidth();
|
||||
asset.height = file.GetHeight();
|
||||
asset.format = ddsLoaderToVkFormat(file.GetFormat(), true);
|
||||
asset.mipOffsets = std::move(mipOff);
|
||||
asset.pixelData = std::move(pixel);
|
||||
}
|
||||
|
||||
void SHTextureLoader::LoadSHTexture(AssetPath path, SHTextureAsset& asset) noexcept
|
||||
{
|
||||
std::ifstream file{path.string(), std::ios::in | std::ios::binary};
|
||||
if (!file.is_open())
|
||||
{
|
||||
SHLOG_ERROR("Error opening SHTexture file: {}", path.string());
|
||||
}
|
||||
|
||||
auto const intBytes{ sizeof(uint32_t) };
|
||||
uint32_t mipCount;
|
||||
|
||||
file.read(reinterpret_cast<char*>(&asset.numBytes), intBytes);
|
||||
file.read(reinterpret_cast<char*>(&asset.width), intBytes);
|
||||
file.read(reinterpret_cast<char*>(&asset.height), intBytes);
|
||||
file.read(reinterpret_cast<char*>(&asset.format), sizeof(SHTexture::TextureFormat));
|
||||
|
||||
file.read(reinterpret_cast<char*>(&mipCount), intBytes);
|
||||
std::vector<uint32_t> mips(mipCount);
|
||||
file.read(reinterpret_cast<char*>(mips.data()), intBytes * mipCount);
|
||||
|
||||
auto pixel = new SHTexture::PixelChannel[asset.numBytes];
|
||||
file.read(reinterpret_cast<char*>(pixel), asset.numBytes);
|
||||
|
||||
asset.mipOffsets = std::move(mips);
|
||||
asset.pixelData = std::move( pixel );
|
||||
|
||||
asset.compiled = true;
|
||||
file.close();
|
||||
}
|
||||
|
||||
void SHTextureLoader::LoadImageAsset(AssetPath path, SHTextureAsset& asset)
|
||||
{
|
||||
if (path.extension().string() == DDS_EXTENSION)
|
||||
{
|
||||
LoadTinyDDS(path, asset);
|
||||
}
|
||||
else if (path.extension().string() == TEXTURE_EXTENSION)
|
||||
{
|
||||
LoadSHTexture(path, asset);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
/*************************************************************************//**
|
||||
* \file SHTextureLoader.h
|
||||
* \author Loh Xiao Qi
|
||||
* \date 30 September 2022
|
||||
* \brief Library to load dds textures and custom binary format
|
||||
*
|
||||
*
|
||||
* 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
|
||||
#define TINYDDSLOADER_IMPLEMENTATION
|
||||
|
||||
#include "../SHAssetMacros.h"
|
||||
#include "../Asset Types/SHTextureAsset.h"
|
||||
#include "tinyddsloader.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
class SHTextureLoader
|
||||
{
|
||||
private:
|
||||
static std::string TinyDDSResultToString(tinyddsloader::Result value);
|
||||
static vk::Format ddsLoaderToVkFormat(tinyddsloader::DDSFile::DXGIFormat format, bool isLinear);
|
||||
|
||||
|
||||
static void LoadTinyDDS(AssetPath path, SHTextureAsset& asset) noexcept;
|
||||
static void LoadSHTexture(AssetPath path, SHTextureAsset& asset) noexcept;
|
||||
public:
|
||||
static void LoadImageAsset(AssetPath paths, SHTextureAsset& image);
|
||||
};
|
||||
}
|
|
@ -1,3 +1,14 @@
|
|||
/*************************************************************************//**
|
||||
* \file SHAsset.h
|
||||
* \author Loh Xiao Qi
|
||||
* \date 30 September 2022
|
||||
* \brief Struct for asset identification and meta file writing
|
||||
*
|
||||
*
|
||||
* 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 "Filesystem/SHFileSystem.h"
|
||||
|
|
|
@ -69,8 +69,10 @@ enum class AssetType : uint8_t
|
|||
#define SCENE_EXTENSION ".SHADE"
|
||||
#define PREFAB_EXTENSION ".SHPrefab"
|
||||
#define MATERIAL_EXTENSION ".SHMat"
|
||||
#define TEXTURE_EXTENSION ".dds"
|
||||
#define TEXTURE_EXTENSION ".shtex"
|
||||
#define DDS_EXTENSION ".dds"
|
||||
#define FBX_EXTENSION ".fbx"
|
||||
#define GLTF_EXTENSION ".gltf"
|
||||
#define MESH_EXTENSION ".shmesh"
|
||||
|
||||
std::string const EXTENSIONS[] = {
|
||||
|
@ -79,12 +81,14 @@ std::string const EXTENSIONS[] = {
|
|||
MATERIAL_EXTENSION,
|
||||
IMAGE_EXTENSION,
|
||||
TEXTURE_EXTENSION,
|
||||
DDS_EXTENSION,
|
||||
MESH_EXTENSION,
|
||||
SCRIPT_EXTENSION,
|
||||
SCENE_EXTENSION,
|
||||
PREFAB_EXTENSION,
|
||||
AUDIO_WAV_EXTENSION,
|
||||
FBX_EXTENSION
|
||||
FBX_EXTENSION,
|
||||
GLTF_EXTENSION
|
||||
};
|
||||
|
||||
// Error flags
|
||||
|
|
|
@ -15,7 +15,10 @@
|
|||
#include "Filesystem/SHFileSystem.h"
|
||||
|
||||
#include "Libraries/SHMeshLoader.h"
|
||||
#include "Libraries/SHDDSLoader.h"
|
||||
#include "Libraries/SHTextureLoader.h"
|
||||
|
||||
#include "Libraries/SHMeshCompiler.h"
|
||||
#include "Libraries/SHTextureCompiler.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
@ -26,7 +29,7 @@ namespace SHADE
|
|||
std::unordered_map<AssetID, SHAsset> SHAssetManager::assetRegistry;
|
||||
|
||||
std::unordered_map<AssetID, SHMeshAsset> SHAssetManager::meshCollection;
|
||||
std::unordered_map<AssetID, SHDDSAsset> SHAssetManager::ddsCollection;
|
||||
std::unordered_map<AssetID, SHTextureAsset> SHAssetManager::textureCollection;
|
||||
|
||||
/****************************************************************************
|
||||
* \brief Static function to generate asset ID.
|
||||
|
@ -199,7 +202,9 @@ namespace SHADE
|
|||
{
|
||||
AssetPath path{ p };
|
||||
|
||||
if (path.extension().string() == FBX_EXTENSION)
|
||||
if (path.extension().string() == FBX_EXTENSION
|
||||
|| path.extension().string() == GLTF_EXTENSION
|
||||
|| path.extension().string() == MESH_EXTENSION)
|
||||
{
|
||||
LoadGLTF(
|
||||
{
|
||||
|
@ -211,7 +216,8 @@ namespace SHADE
|
|||
}
|
||||
);
|
||||
}
|
||||
else if (path.extension().string() == TEXTURE_EXTENSION)
|
||||
else if (path.extension().string() == DDS_EXTENSION
|
||||
|| path.extension().string() == TEXTURE_EXTENSION)
|
||||
{
|
||||
LoadDDS(
|
||||
{
|
||||
|
@ -236,10 +242,10 @@ namespace SHADE
|
|||
return result;
|
||||
}
|
||||
|
||||
std::vector<SHDDSAsset> SHAssetManager::GetAllDDS() noexcept
|
||||
std::vector<SHTextureAsset> SHAssetManager::GetAllTextures() noexcept
|
||||
{
|
||||
std::vector<SHDDSAsset> result;
|
||||
for (auto const& dds : ddsCollection)
|
||||
std::vector<SHTextureAsset> result;
|
||||
for (auto const& dds : textureCollection)
|
||||
{
|
||||
result.push_back(dds.second);
|
||||
}
|
||||
|
@ -300,16 +306,26 @@ namespace SHADE
|
|||
for (auto const& mesh : meshes)
|
||||
{
|
||||
meshCollection.emplace(GenerateAssetID(AssetType::MESH), mesh);
|
||||
|
||||
if (!mesh.compiled)
|
||||
{
|
||||
SHMeshCompiler::CompileMeshBinary(mesh, asset.path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SHAssetManager::LoadDDS(SHAsset asset) noexcept
|
||||
{
|
||||
SHDDSAsset image;
|
||||
SHTextureAsset image;
|
||||
|
||||
SHDDSLoader::LoadImageAsset(asset.path, image);
|
||||
SHTextureLoader::LoadImageAsset(asset.path, image);
|
||||
|
||||
ddsCollection.emplace(GenerateAssetID(AssetType::DDS), image);
|
||||
textureCollection.emplace(GenerateAssetID(AssetType::DDS), image);
|
||||
|
||||
if (!image.compiled)
|
||||
{
|
||||
SHTextureCompiler::CompileTextureBinary(image, asset.path);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
#include "SHAsset.h"
|
||||
|
||||
#include "Asset Types/SHMeshAsset.h"
|
||||
#include "Asset Types/SHDDSAsset.h"
|
||||
#include "Asset Types/SHTextureAsset.h"
|
||||
#include "SH_API.h"
|
||||
|
||||
namespace SHADE
|
||||
|
@ -73,7 +73,7 @@ namespace SHADE
|
|||
//TODO: TEMPORARY FOR TESTING GLTF & DDS
|
||||
static void LoadDataTemp(std::string path) noexcept;
|
||||
static std::vector<SHMeshAsset> GetAllMeshes() noexcept;
|
||||
static std::vector<SHDDSAsset> GetAllDDS() noexcept;
|
||||
static std::vector<SHTextureAsset> GetAllTextures() noexcept;
|
||||
|
||||
private:
|
||||
/****************************************************************************
|
||||
|
@ -128,6 +128,6 @@ namespace SHADE
|
|||
static std::unordered_map<AssetID, SHAsset> assetRegistry;
|
||||
|
||||
static std::unordered_map<AssetID, SHMeshAsset> meshCollection;
|
||||
static std::unordered_map<AssetID, SHDDSAsset> ddsCollection;
|
||||
static std::unordered_map<AssetID, SHTextureAsset> textureCollection;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -99,6 +99,7 @@ namespace SHADE
|
|||
****************************************************************************/
|
||||
void SHAssetMetaHandler::WriteMetaData(SHAsset const& meta) noexcept
|
||||
{
|
||||
//TODO: Write into binary eventually
|
||||
std::string path{ meta.path.string() };
|
||||
path.append(META_EXTENSION);
|
||||
|
||||
|
@ -110,8 +111,20 @@ namespace SHADE
|
|||
return;
|
||||
}
|
||||
|
||||
metaFile << "Name: " << meta.name << "\n";
|
||||
metaFile << "ID: " << meta.id << "\n";
|
||||
metaFile << "Type: " << static_cast<int>(meta.type) << std::endl;
|
||||
|
||||
//TODO Add in information that is specific to types like mesh
|
||||
switch(meta.type)
|
||||
{
|
||||
case AssetType::MESH:
|
||||
break;
|
||||
|
||||
default:
|
||||
void;
|
||||
}
|
||||
|
||||
metaFile.close();
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
/*********************************************************************
|
||||
* \file SHAudioListenerComponent.cpp
|
||||
* \author Glence Low
|
||||
* \brief Definition of the SHAudioListenerComponent class.
|
||||
*
|
||||
* \copyright Copyright (c) 2021 DigiPen Institute of Technology. Reproduction
|
||||
or disclosure of this file or its contents without the prior written
|
||||
consent of DigiPen Institute of Technology is prohibited.
|
||||
*********************************************************************/
|
||||
|
||||
#include "SHpch.h"
|
||||
#include "SHAudioListenerComponent.h"
|
||||
#include "ECS_Base/Managers/SHSystemManager.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
const SHVec3 SHAudioListenerComponent::GetPos() const
|
||||
{
|
||||
return pos;
|
||||
}
|
||||
|
||||
const SHVec3 SHAudioListenerComponent::GetVel() const
|
||||
{
|
||||
return vel;
|
||||
}
|
||||
|
||||
const SHVec3 SHAudioListenerComponent::GetForward() const
|
||||
{
|
||||
return forward;
|
||||
}
|
||||
|
||||
const SHVec3 SHAudioListenerComponent::GetUp() const
|
||||
{
|
||||
return up;
|
||||
}
|
||||
|
||||
void SHAudioListenerComponent::SetPos(const SHVec3 p)
|
||||
{
|
||||
pos = p;
|
||||
}
|
||||
|
||||
void SHAudioListenerComponent::SetVel(const SHVec3 v)
|
||||
{
|
||||
vel = v;
|
||||
}
|
||||
|
||||
void SHAudioListenerComponent::SetForward(const SHVec3 f)
|
||||
{
|
||||
forward = f;
|
||||
}
|
||||
|
||||
void SHAudioListenerComponent::SetUp(const SHVec3 u)
|
||||
{
|
||||
up = u;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
#pragma once
|
||||
/*********************************************************************
|
||||
* \file SHAudioListenerComponent.h
|
||||
* \author Glence Low
|
||||
* \brief Declaration of the SHAudioListenerComponent class.
|
||||
*
|
||||
* \copyright Copyright (c) 2021 DigiPen Institute of Technology. Reproduction
|
||||
or disclosure of this file or its contents without the prior written
|
||||
consent of DigiPen Institute of Technology is prohibited.
|
||||
*********************************************************************/
|
||||
|
||||
#pragma once
|
||||
#include "ECS_Base/Components/SHComponent.h"
|
||||
#include "Math/SHMath.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
class SHAudioListenerComponent : public SHComponent
|
||||
{
|
||||
friend class SHAudioSystem;
|
||||
public:
|
||||
|
||||
SHAudioListenerComponent() = default;
|
||||
~SHAudioListenerComponent() = default;
|
||||
|
||||
const SHVec3 GetPos() const;
|
||||
void SetPos(const SHVec3 p);
|
||||
|
||||
const SHVec3 GetVel() const;
|
||||
const SHVec3 GetForward() const;
|
||||
const SHVec3 GetUp() const;
|
||||
|
||||
void SetVel(const SHVec3 v);
|
||||
void SetForward(const SHVec3 f);
|
||||
void SetUp(const SHVec3 u);
|
||||
|
||||
private:
|
||||
SHVec3 pos{}, vel{}, forward{}, up{ 0.f,1.f,0.f };
|
||||
};
|
||||
}//namespace SHADE
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
/*********************************************************************
|
||||
* \file SHAudioSourceComponet.cpp
|
||||
* \author Glence Low
|
||||
* \brief Definition of the SHAudioSourceComponet class.
|
||||
*
|
||||
* \copyright Copyright (c) 2021 DigiPen Institute of Technology. Reproduction
|
||||
or disclosure of this file or its contents without the prior written
|
||||
consent of DigiPen Institute of Technology is prohibited.
|
||||
*********************************************************************/
|
||||
|
||||
#include "SHpch.h"
|
||||
#include "ECS_Base/Managers/SHSystemManager.h"
|
||||
#include "AudioSystem/SHAudioSystem.h"
|
||||
#include "SHAudioSourceComponent.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/**
|
||||
* @brief play the sound
|
||||
*
|
||||
* @param index where the sound is in the index
|
||||
*/
|
||||
void SHAudioSourceComponent::PlaySoundSFX(EntityID id, bool loop, bool spatial, float min , float max )
|
||||
{
|
||||
SHSystemManager::GetSystem<SHAudioSystem>()->PlaySFX(id, GetEID(),loop,spatial, min, max);
|
||||
}
|
||||
|
||||
void SHAudioSourceComponent::PlaySoundBGM(EntityID id, bool loop, bool spatial, float min, float max)
|
||||
{
|
||||
SHSystemManager::GetSystem<SHAudioSystem>()->PlayBGM(id, GetEID(), loop, spatial, min, max);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stop the sound
|
||||
*
|
||||
* @param index where the sound is in the index
|
||||
*/
|
||||
void SHAudioSourceComponent::StopSound(EntityID id)
|
||||
{
|
||||
SHSystemManager::GetSystem<SHAudioSystem>()->StopSound(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Mute the sound
|
||||
*
|
||||
* @param index where the sound is in the index
|
||||
*/
|
||||
void SHAudioSourceComponent::SetMute(EntityID id, bool mute)
|
||||
{
|
||||
SHSystemManager::GetSystem<SHAudioSystem>()->SetMute(id, mute);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
/*********************************************************************
|
||||
* \file SHAudioSourceComponet.h
|
||||
* \author Glence Low
|
||||
* \brief Declaration of the SHAudioSourceComponet class.
|
||||
*
|
||||
* \copyright Copyright (c) 2021 DigiPen Institute of Technology. Reproduction
|
||||
or disclosure of this file or its contents without the prior written
|
||||
consent of DigiPen Institute of Technology is prohibited.
|
||||
*********************************************************************/
|
||||
|
||||
#pragma once
|
||||
#include "ECS_Base/Components/SHComponent.h"
|
||||
#include "ECS_Base/SHECSMacros.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
class SHAudioSourceComponent : public SHComponent
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief default constructor for the component
|
||||
*
|
||||
*/
|
||||
SHAudioSourceComponent() = default;
|
||||
|
||||
|
||||
/**
|
||||
* @brief default destructor for the component
|
||||
*
|
||||
*/
|
||||
~SHAudioSourceComponent() = default;
|
||||
|
||||
/**
|
||||
* @brief play the sound
|
||||
*
|
||||
* @param index where the sound is in the index
|
||||
*/
|
||||
void PlaySoundSFX(EntityID id, bool loop = false, bool spatial = false, float min = 5.0f, float max = 1000.f);
|
||||
|
||||
void PlaySoundBGM(EntityID id, bool loop = false, bool spatial = false, float min = 5.0f, float max = 1000.f);
|
||||
|
||||
/**
|
||||
* @brief Stop the sound
|
||||
*
|
||||
* @param index where the sound is in the index
|
||||
*/
|
||||
void StopSound(EntityID id);
|
||||
|
||||
/**
|
||||
* @brief Mute the sound
|
||||
*
|
||||
* @param index where the sound is in the index
|
||||
*/
|
||||
void SetMute(EntityID id, bool mute);
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
}//namespace SHADE
|
||||
|
|
@ -0,0 +1,557 @@
|
|||
#include "SHpch.h"
|
||||
#include "SHAudioSystem.h"
|
||||
#include "Scene/SHSceneManager.h"
|
||||
#include "ECS_Base/Managers/SHComponentManager.h"
|
||||
#include "ECS_Base/Managers/SHSystemManager.h"
|
||||
#include "ECS_Base/Managers/SHEntityManager.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "AudioSystem/SHAudioListenerComponent.h"
|
||||
#include "AudioSystem/SHAudioSourceComponent.h"
|
||||
#include "Math/Transform/SHTransformComponent.h"
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:26812) //disable warning about preference of enum class over enum as ImGuizmo uses enums
|
||||
#include <FMOD/fmod_errors.h>
|
||||
#include <FMOD/fmod.hpp>
|
||||
#include <FMOD/fmod_studio.hpp>
|
||||
#include <SDL_keyboard.h>
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
SHAudioSystem::SHAudioSystem()
|
||||
: fmodStudioSystem(nullptr)
|
||||
, extraDriverData(nullptr)
|
||||
, soundList()
|
||||
, bgmChannelGroup(nullptr)
|
||||
, sfxChannelGroup(nullptr)
|
||||
, masterGroup(nullptr)
|
||||
, audioChannels()
|
||||
, result(FMOD_RESULT_FORCEINT)
|
||||
, bgmVolume(1.F)
|
||||
, sfxVolume(1.F)
|
||||
, masterVolume(1.0F)
|
||||
, version(0)
|
||||
, speakerMode(FMOD_SPEAKERMODE_5POINT1)
|
||||
, paused(false)
|
||||
{
|
||||
result = FMOD::Studio::System::create(&fmodStudioSystem);
|
||||
ErrorCheck();
|
||||
}
|
||||
|
||||
SHAudioSystem::~SHAudioSystem()
|
||||
{
|
||||
}
|
||||
|
||||
void SHADE::SHAudioSystem::Init()
|
||||
{
|
||||
|
||||
SHADE::SHComponentManager::CreateComponentSparseSet<SHADE::SHAudioSourceComponent>();
|
||||
SHADE::SHComponentManager::CreateComponentSparseSet<SHADE::SHAudioListenerComponent>();
|
||||
|
||||
denseListener = &SHComponentManager::GetDense<SHAudioListenerComponent>();
|
||||
fmodStudioSystem->getCoreSystem(&fmodSystem);
|
||||
|
||||
result = fmodStudioSystem->initialize(AUDIO_SYS_MAX_CHANNELS, AUDIO_SYS_MAX_CHANNELS, FMOD_STUDIO_INIT_NORMAL, extraDriverData);
|
||||
ErrorCheck();
|
||||
|
||||
fmodSystem->setSoftwareFormat(0, speakerMode, 0);
|
||||
|
||||
result = fmodSystem->createChannelGroup("SFX", &sfxChannelGroup);
|
||||
ErrorCheck();
|
||||
|
||||
result = fmodSystem->createChannelGroup("BGM", &bgmChannelGroup);
|
||||
ErrorCheck();
|
||||
|
||||
result = fmodSystem->getMasterChannelGroup(&masterGroup);
|
||||
ErrorCheck();
|
||||
|
||||
result = masterGroup->addGroup(bgmChannelGroup);
|
||||
ErrorCheck();
|
||||
|
||||
result = masterGroup->addGroup(sfxChannelGroup);
|
||||
ErrorCheck();
|
||||
|
||||
bgmChannelGroup->setVolume(bgmVolume);
|
||||
sfxChannelGroup->setVolume(sfxVolume);
|
||||
masterGroup->setVolume(masterVolume);
|
||||
|
||||
//SHResourceManager::LoadAllAudio(system, soundList);
|
||||
|
||||
|
||||
LoadBank("../../Assets/Audio/Master.bank");
|
||||
LoadBank("../../Assets/Audio/Master.strings.bank");
|
||||
//LoadBank("../../Assets/Audio/Music.bank");
|
||||
LoadBank("../../Assets/Audio/footsteps.bank");
|
||||
|
||||
//auto clip = CreateAudioClip("event:/Characters/sfx_footsteps_human");
|
||||
//clip->Play();
|
||||
//PlayEventOnce("event:/Characters/sfx_footsteps_raccoon");
|
||||
//PlayEventOnce("event:/SFX/Dawn/Dawn_Attack");
|
||||
}
|
||||
|
||||
void SHADE::SHAudioSystem::Run(float dt)
|
||||
{
|
||||
static_cast<void>(dt);
|
||||
//if (GetKeyState(VK_SPACE) & 0x8000)
|
||||
// PlayEventOnce("event:/Characters/sfx_footsteps_raccoon");
|
||||
|
||||
fmodStudioSystem->update();
|
||||
if (!denseListener->empty())
|
||||
{
|
||||
SHAudioListenerComponent& listener = denseListener->at(0);
|
||||
SHTransformComponent* listenerTransform = SHComponentManager::GetComponent_s<SHTransformComponent>(listener.GetEID());
|
||||
if (listenerTransform)
|
||||
{
|
||||
listener.SetPos(listenerTransform->GetLocalPosition());
|
||||
listener.SetForward({ (listenerTransform->GetLocalScale()[0] > 0.f) ? 1.f : -1.f, 0.f, 0.f });
|
||||
FMOD_VECTOR pos = { listener.pos[0] ,listener.pos[1] ,0.f };
|
||||
FMOD_VECTOR forward = { listener.forward[0] ,listener.forward[1] ,listener.forward[2] };
|
||||
FMOD_VECTOR up = { listener.up[0] ,listener.up[1] ,listener.up[2] };
|
||||
fmodSystem->set3DListenerAttributes(0, &pos, nullptr, &forward, &up);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SHAudioSystem::AudioRoutine::AudioRoutine()
|
||||
: SHSystemRoutine("Audio Routine", false) {}
|
||||
|
||||
void SHAudioSystem::AudioRoutine::Execute(double dt) noexcept
|
||||
{
|
||||
reinterpret_cast<SHAudioSystem*>(system)->Run(dt);
|
||||
}
|
||||
|
||||
void SHADE::SHAudioSystem::Exit()
|
||||
{
|
||||
for (auto& event : eventMap)
|
||||
{
|
||||
result = event.second->releaseAllInstances();
|
||||
ErrorCheck();
|
||||
}
|
||||
|
||||
for (auto& bank : bankMap)
|
||||
{
|
||||
result = bank.second->unload();
|
||||
ErrorCheck();
|
||||
}
|
||||
|
||||
for (auto& sound : soundList)
|
||||
{
|
||||
result = sound.second->release();
|
||||
ErrorCheck();
|
||||
}
|
||||
|
||||
if (bgmChannelGroup)
|
||||
{
|
||||
result = bgmChannelGroup->release();
|
||||
ErrorCheck();
|
||||
}
|
||||
|
||||
if (sfxChannelGroup)
|
||||
{
|
||||
result = sfxChannelGroup->release();
|
||||
ErrorCheck();
|
||||
}
|
||||
|
||||
if (fmodStudioSystem)
|
||||
{
|
||||
result = fmodStudioSystem->release();
|
||||
ErrorCheck();
|
||||
}
|
||||
}
|
||||
|
||||
void SHAudioSystem::ErrorCheck() const
|
||||
{
|
||||
if (result != FMOD_OK)
|
||||
std::cerr << "Audio system error: " << FMOD_ErrorString(result) << std::endl;
|
||||
}
|
||||
|
||||
void SHAudioSystem::PlayEventOnce(const char* path, bool isSFX, EntityID eid, bool spatial)
|
||||
{
|
||||
if (paused)
|
||||
return;
|
||||
auto it = eventMap.find(path);
|
||||
if (it != eventMap.end())
|
||||
{
|
||||
FMOD::Studio::EventInstance* event = nullptr;
|
||||
it->second->createInstance(&event);
|
||||
if (event)
|
||||
{
|
||||
|
||||
event->setVolume(masterVolume * (isSFX ? sfxVolume : bgmVolume));
|
||||
if (spatial)
|
||||
{
|
||||
if (SHTransformComponent* audioTransform = SHComponentManager::GetComponent_s<SHTransformComponent>(eid))
|
||||
{
|
||||
FMOD_3D_ATTRIBUTES attributes{ {} };
|
||||
attributes.forward.z = 1.0f;
|
||||
attributes.up.y = 1.0f;
|
||||
SHAudioListenerComponent& listener = denseListener->at(0);
|
||||
SHTransformComponent* listenerTransform = SHComponentManager::GetComponent_s<SHTransformComponent>(listener.GetEID());
|
||||
if (listenerTransform)
|
||||
{
|
||||
attributes.position.z = listenerTransform->GetLocalPosition()[2];
|
||||
}
|
||||
attributes.position.x = audioTransform->GetLocalPosition()[0];
|
||||
attributes.position.y = audioTransform->GetLocalPosition()[1];
|
||||
event->set3DAttributes(&attributes);
|
||||
}
|
||||
}
|
||||
event->start();
|
||||
event->release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SHAudioSystem::PlaySFX(EntityID id, EntityID eid, const bool& loop, const bool& spatial, float min, float max)
|
||||
{
|
||||
SHSound sound = soundList[id];
|
||||
int index = GetAvailableChannelIndex();
|
||||
if (index >= 0)
|
||||
{
|
||||
unsigned int mode{};
|
||||
mode |= (loop ? FMOD_LOOP_NORMAL : FMOD_LOOP_OFF);
|
||||
mode |= (spatial ? FMOD_3D : FMOD_2D);
|
||||
sound->setMode(mode);
|
||||
result = fmodSystem->playSound(sound, sfxChannelGroup, false, &audioChannels[index]);
|
||||
if (spatial && SHComponentManager::HasComponent<SHTransformComponent>(eid))
|
||||
{
|
||||
SHTransformComponent* audioTransform = SHComponentManager::GetComponent_s<SHTransformComponent>(eid);
|
||||
FMOD_VECTOR fpos{ audioTransform->GetLocalPosition()[0],audioTransform->GetLocalPosition()[1] ,0.f};
|
||||
audioChannels[index]->set3DAttributes(&fpos, nullptr);
|
||||
audioChannels[index]->setMode(mode);
|
||||
audioChannels[index]->set3DMinMaxDistance(min, max);
|
||||
}
|
||||
ErrorCheck();
|
||||
}
|
||||
}
|
||||
|
||||
void SHAudioSystem::PlayBGM(EntityID id, EntityID eid, const bool& loop, const bool& spatial, float min, float max)
|
||||
{
|
||||
SHSound sound = soundList[id];
|
||||
int index = GetAvailableChannelIndex();
|
||||
if (index >= 0)
|
||||
{
|
||||
unsigned int mode{};
|
||||
mode |= (loop ? FMOD_LOOP_NORMAL : FMOD_LOOP_OFF);
|
||||
mode |= (spatial ? FMOD_3D : FMOD_2D);
|
||||
sound->setMode(mode);
|
||||
result = fmodSystem->playSound(sound, bgmChannelGroup, false, &audioChannels[index]);
|
||||
if (spatial && SHComponentManager::HasComponent<SHTransformComponent>(eid))
|
||||
{
|
||||
SHTransformComponent* audioTransform = SHComponentManager::GetComponent_s<SHTransformComponent>(eid);
|
||||
FMOD_VECTOR fpos{ audioTransform->GetLocalPosition()[0],audioTransform->GetLocalPosition()[1] ,0.f };
|
||||
audioChannels[index]->set3DAttributes(&fpos, nullptr);
|
||||
audioChannels[index]->setMode(mode);
|
||||
audioChannels[index]->set3DMinMaxDistance(min, max);
|
||||
}
|
||||
ErrorCheck();
|
||||
}
|
||||
}
|
||||
|
||||
void SHAudioSystem::SetMute(EntityID id, bool mute)
|
||||
{
|
||||
SHSound sound;
|
||||
for (auto& channel : audioChannels)
|
||||
{
|
||||
channel->getCurrentSound(&sound);
|
||||
if (soundList.find(id)->second == sound) // tbc
|
||||
{
|
||||
channel->setMute(mute);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SHAudioSystem::StopSound(EntityID id)
|
||||
{
|
||||
SHSound sound;
|
||||
for (auto& channel : audioChannels)
|
||||
{
|
||||
channel->getCurrentSound(&sound);
|
||||
if (soundList.find(id)->second == sound) // tbc
|
||||
{
|
||||
channel->stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SHAudioSystem::StopAllSounds()
|
||||
{
|
||||
for (auto& channel : audioChannels)
|
||||
{
|
||||
bool isPlaying{ false };
|
||||
if (channel->isPlaying(&isPlaying) == FMOD_OK && isPlaying)
|
||||
channel->stop();
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<FMOD_GUID> SHAudioSystem::GetEventGUID(const char* path)
|
||||
{
|
||||
FMOD_GUID guid;
|
||||
FMOD::Studio::EventDescription* event;
|
||||
result = fmodStudioSystem->getEvent(path, &event);
|
||||
ErrorCheck();
|
||||
if (result == FMOD_OK)
|
||||
{
|
||||
result = event->getID(&guid);
|
||||
ErrorCheck();
|
||||
if (result == FMOD_OK)
|
||||
{
|
||||
return guid;
|
||||
}
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
AudioClip* SHAudioSystem::CreateAudioClip(const char* path)
|
||||
{
|
||||
AudioClipID newID{};
|
||||
AudioClip* clip = nullptr;
|
||||
auto it = eventMap.find(path);
|
||||
if (it != eventMap.end())
|
||||
{
|
||||
FMOD::Studio::EventInstance* event = nullptr;
|
||||
it->second->createInstance(&event);
|
||||
if (event)
|
||||
{
|
||||
//event->start();
|
||||
newID = clipID;
|
||||
clipID++;
|
||||
eventInstances.emplace(newID, AudioClip(newID, event));
|
||||
clip = &eventInstances[newID];
|
||||
}
|
||||
}
|
||||
return clip;
|
||||
}
|
||||
|
||||
//std::vector<const char*> SHAudioSystem::GetAllEvents()
|
||||
//{
|
||||
// int count{};
|
||||
// stringsBank->getEventCount(&count);
|
||||
|
||||
// std::vector<FMOD::Studio::EventDescription*> events(count);
|
||||
// auto eventData = events.data();
|
||||
// int finalCount{};
|
||||
// stringsBank->getEventList(eventData, count, &finalCount);
|
||||
// std::vector<const char*> eventNames;
|
||||
// std::transform(events.begin(), events.end(), std::back_inserter(eventNames), [](FMOD::Studio::EventDescription* event)
|
||||
// {
|
||||
// char path[256];
|
||||
// event->getPath(path, 256, nullptr);
|
||||
// return path;
|
||||
// });
|
||||
// return eventNames;
|
||||
//}
|
||||
|
||||
//void SHAudioSystem::PlayEventInstance(FMOD::Studio::EventInstance* instance, bool isSFX, EntityID eid, bool spatial)
|
||||
//{
|
||||
// instance->setVolume(masterVolume * (isSFX ? sfxVolume : bgmVolume));
|
||||
// FMOD::ChannelGroup* channelGroup;
|
||||
// if (spatial)
|
||||
// {
|
||||
// if (SHTransformComponent* audioTransform = SHComponentManager::GetComponent_s<SHTransformComponent>(eid))
|
||||
// {
|
||||
// FMOD_3D_ATTRIBUTES attributes{ {} };
|
||||
// attributes.forward.z = 1.0f;
|
||||
// attributes.up.y = 1.0f;
|
||||
// SHAudioListenerComponent& listener = denseListener->at(0);
|
||||
// SHTransformComponent* listenerTransform = SHComponentManager::GetComponent_s<SHTransformComponent>(listener.GetEID());
|
||||
// if (listenerTransform)
|
||||
// {
|
||||
// attributes.position.z = listenerTransform->GetTranslation()[2];
|
||||
// }
|
||||
// attributes.position.x = audioTransform->GetTranslation()[0];
|
||||
// attributes.position.y = audioTransform->GetTranslation()[1];
|
||||
// instance->set3DAttributes(&attributes);
|
||||
// }
|
||||
// }
|
||||
// instance->start();
|
||||
//}
|
||||
|
||||
int SHAudioSystem::GetAvailableChannelIndex()
|
||||
{
|
||||
bool isPlaying = false;
|
||||
for (int i = 0; i < AUDIO_SYS_MAX_CHANNELS; ++i)
|
||||
{
|
||||
audioChannels[i]->isPlaying(&isPlaying);
|
||||
if (!isPlaying)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
float SHAudioSystem::GetBgmVolume()
|
||||
{
|
||||
return bgmVolume;
|
||||
}
|
||||
float SHAudioSystem::GetSfxVolume()
|
||||
{
|
||||
return sfxVolume;
|
||||
}
|
||||
float SHAudioSystem::GetMasterVolume()
|
||||
{
|
||||
return masterVolume;
|
||||
}
|
||||
void SHAudioSystem::SetBgmVolume(float const bgmvol)
|
||||
{
|
||||
bgmChannelGroup->setVolume(bgmvol);
|
||||
}
|
||||
void SHAudioSystem::SetSfxVolume(float const sfxvol)
|
||||
{
|
||||
sfxChannelGroup->setVolume(sfxvol);
|
||||
}
|
||||
void SHAudioSystem::SetMasterVolume(float const mastervol)
|
||||
{
|
||||
masterGroup->setVolume(mastervol);
|
||||
}
|
||||
|
||||
void SHAudioSystem::SetPaused(bool pause)
|
||||
{
|
||||
paused = pause;
|
||||
for (auto const& channel : audioChannels)
|
||||
{
|
||||
channel->setPaused(paused);
|
||||
}
|
||||
for (auto const& event : eventMap)
|
||||
{
|
||||
int instanceCount = 0;
|
||||
event.second->getInstanceCount(&instanceCount);
|
||||
std::vector<FMOD::Studio::EventInstance*> instances(instanceCount);
|
||||
event.second->getInstanceList(instances.data(), instances.size(), &instanceCount);
|
||||
for (auto const& instance : instances)
|
||||
{
|
||||
instance->setPaused(pause);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool SHAudioSystem::GetPaused() const
|
||||
{
|
||||
return paused;
|
||||
}
|
||||
|
||||
SHVec3 SHAudioSystem::GetListenerPosition()
|
||||
{
|
||||
auto &listener = denseListener->at(0);
|
||||
SHTransformComponent* listenerTransform = SHComponentManager::GetComponent_s<SHTransformComponent>(listener.GetEID());
|
||||
if (listenerTransform)
|
||||
{
|
||||
return listenerTransform->GetLocalPosition();
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
void SHAudioSystem::LoadBank(const char* path)
|
||||
{
|
||||
FMOD::Studio::Bank* bank = nullptr;
|
||||
result = fmodStudioSystem->loadBankFile(path, FMOD_STUDIO_LOAD_BANK_NORMAL, &bank);
|
||||
ErrorCheck();
|
||||
if (result != FMOD_OK)
|
||||
return;
|
||||
bankMap.emplace(path, bank);
|
||||
bank->loadSampleData();
|
||||
int numOfEvents;
|
||||
bank->getEventCount(&numOfEvents);
|
||||
if (numOfEvents > 0)
|
||||
{
|
||||
std::vector<FMOD::Studio::EventDescription*> events(numOfEvents);
|
||||
bank->getEventList(events.data(), numOfEvents, &numOfEvents);
|
||||
char eventName[512];
|
||||
for (int i{}; i < numOfEvents; ++i)
|
||||
{
|
||||
FMOD::Studio::EventDescription* event = events[i];
|
||||
event->getPath(eventName, 512, nullptr);
|
||||
eventMap.emplace(eventName, event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AudioClip::AudioClip(AudioClipID clipID, FMOD::Studio::EventInstance* inst)
|
||||
:instance(inst), id(clipID)
|
||||
{
|
||||
}
|
||||
|
||||
AudioClip::~AudioClip()
|
||||
{
|
||||
}
|
||||
|
||||
void AudioClip::Play(bool isSfx)
|
||||
{
|
||||
if (!instance)
|
||||
return;
|
||||
instance->start();
|
||||
auto audioSystem = SHSystemManager::GetSystem<SHADE::SHAudioSystem>();
|
||||
instance->setVolume(audioSystem->GetMasterVolume() * (isSfx ? audioSystem->GetSfxVolume() : audioSystem->GetBgmVolume()));
|
||||
}
|
||||
|
||||
void AudioClip::Play(SHVec3 position, bool isSfx)
|
||||
{
|
||||
if (!instance)
|
||||
return;
|
||||
instance->start();
|
||||
FMOD_3D_ATTRIBUTES attributes{ {} };
|
||||
attributes.forward.z = 1.0f;
|
||||
attributes.up.y = 1.0f;
|
||||
|
||||
auto audioSystem = SHSystemManager::GetSystem<SHADE::SHAudioSystem>();
|
||||
SHVec3 listenerPos = audioSystem->GetListenerPosition();
|
||||
attributes.position.x = position[0];
|
||||
attributes.position.y = position[1];
|
||||
attributes.position.z = listenerPos[2];
|
||||
instance->set3DAttributes(&attributes);
|
||||
instance->setVolume(audioSystem->GetMasterVolume() * (isSfx ? audioSystem->GetSfxVolume() : audioSystem->GetBgmVolume()));
|
||||
}
|
||||
|
||||
void AudioClip::Stop(bool fadeOut)
|
||||
{
|
||||
if (!instance)
|
||||
return;
|
||||
instance->stop(fadeOut ? FMOD_STUDIO_STOP_ALLOWFADEOUT : FMOD_STUDIO_STOP_IMMEDIATE);
|
||||
}
|
||||
|
||||
void AudioClip::SetPause(bool pause)
|
||||
{
|
||||
if (!instance)
|
||||
return;
|
||||
instance->setPaused(pause);
|
||||
}
|
||||
|
||||
bool AudioClip::IsPaused()
|
||||
{
|
||||
if (!instance)
|
||||
return true;
|
||||
|
||||
bool paused{};
|
||||
instance->getPaused(&paused);
|
||||
return paused;
|
||||
}
|
||||
|
||||
|
||||
void AudioClip::SetParameter(const char* paramName, float value)
|
||||
{
|
||||
if (!instance)
|
||||
return;
|
||||
instance->setParameterByName(paramName, value);
|
||||
}
|
||||
|
||||
void AudioClip::SetParameterLabel(const char* paramName, const char* label)
|
||||
{
|
||||
if (!instance)
|
||||
return;
|
||||
instance->setParameterByNameWithLabel(paramName, label);
|
||||
}
|
||||
|
||||
float AudioClip::GetParameterValue(const char* paramName)
|
||||
{
|
||||
if (!instance)
|
||||
return {};
|
||||
float value{};
|
||||
instance->getParameterByName(paramName, &value);
|
||||
return value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#pragma warning(pop)
|
||||
|
||||
|
|
@ -0,0 +1,110 @@
|
|||
#pragma once
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <unordered_map>
|
||||
#include "ECS_Base/System/SHSystem.h"
|
||||
#include "ECS_Base/System/SHSystemRoutine.h"
|
||||
#include "ECS_Base/SHECSMacros.h"
|
||||
#include "Math/SHMath.h"
|
||||
#include <optional>
|
||||
#include <FMOD/fmod_studio.hpp>
|
||||
#include "SH_API.h"
|
||||
#define AUDIO_SYS_MAX_CHANNELS 1024
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
typedef FMOD::Sound* SHSound;
|
||||
typedef FMOD::Studio::Bank* SHBank;
|
||||
|
||||
class SHAudioListenerComponent;
|
||||
|
||||
typedef uint64_t AudioClipID;
|
||||
|
||||
class AudioClip
|
||||
{
|
||||
public:
|
||||
AudioClip() = default;
|
||||
AudioClip(AudioClipID clipID, FMOD::Studio::EventInstance* inst);
|
||||
~AudioClip();
|
||||
void Play(bool isSfx = true);
|
||||
void Play(SHVec3 position, bool isSfx = true);
|
||||
void Stop(bool fadeOut = true);
|
||||
|
||||
void SetPause(bool pause);
|
||||
bool IsPaused();
|
||||
void SetParameter(const char* paramName, float value);
|
||||
void SetParameterLabel(const char* paramName, const char* label);
|
||||
float GetParameterValue(const char* paramName);
|
||||
friend class SHAudioSystem;
|
||||
private:
|
||||
FMOD::Studio::EventInstance* instance;
|
||||
AudioClipID id;
|
||||
};
|
||||
|
||||
class SH_API SHAudioSystem : public SHSystem
|
||||
{
|
||||
public:
|
||||
SHAudioSystem();
|
||||
~SHAudioSystem();
|
||||
|
||||
void Init();
|
||||
void Run(float dt);
|
||||
class SH_API AudioRoutine final : public SHSystemRoutine
|
||||
{
|
||||
public:
|
||||
AudioRoutine();
|
||||
void Execute(double dt) noexcept override final;
|
||||
};
|
||||
void Exit();
|
||||
|
||||
int GetAvailableChannelIndex();
|
||||
/*std::vector<SHSound>::size_type CreateSound(const char* filepath, bool loop = false);*/
|
||||
void PlaySFX(EntityID id, EntityID eid, const bool& loop, const bool& spatial, float min = 5.0f, float max = 1000.0f);
|
||||
void PlayBGM(EntityID id, EntityID eid, const bool& loop, const bool& spatial, float min = 5.0f, float max = 1000.0f);
|
||||
void PlayEventOnce(const char* path, bool isSFX = true, EntityID eid = MAX_EID, bool spatial = false);
|
||||
void SetMute(EntityID id, bool);
|
||||
void StopSound(EntityID id);
|
||||
void StopAllSounds();
|
||||
|
||||
std::optional<FMOD_GUID> GetEventGUID(const char* path);
|
||||
AudioClip* CreateAudioClip(const char* path);
|
||||
//std::vector<const char*> GetAllEvents();
|
||||
|
||||
float GetBgmVolume();
|
||||
float GetSfxVolume();
|
||||
float GetMasterVolume();
|
||||
void SetBgmVolume(float const bgmvol);
|
||||
void SetSfxVolume(float const sfxvol);
|
||||
void SetMasterVolume(float const mastervol);
|
||||
void SetPaused(bool pause);
|
||||
bool GetPaused() const;
|
||||
SHVec3 GetListenerPosition();
|
||||
void LoadBank(const char* path);
|
||||
private:
|
||||
FMOD::Studio::System* fmodStudioSystem;
|
||||
FMOD::System* fmodSystem;
|
||||
bool paused;
|
||||
void ErrorCheck() const;
|
||||
|
||||
void* extraDriverData;
|
||||
std::unordered_map<EntityID, SHSound> soundList;
|
||||
//std::unordered_map<ResourceID, SHBank> bankMap;
|
||||
std::unordered_map<std::string, SHBank> bankMap;
|
||||
std::unordered_map<std::string, FMOD::Studio::EventDescription*> eventMap;
|
||||
std::unordered_map<AudioClipID, AudioClip> eventInstances;
|
||||
FMOD::ChannelGroup* bgmChannelGroup, * sfxChannelGroup, * masterGroup;
|
||||
FMOD::Channel* audioChannels[AUDIO_SYS_MAX_CHANNELS];
|
||||
FMOD_RESULT result;
|
||||
float bgmVolume, sfxVolume, masterVolume;
|
||||
unsigned int version;
|
||||
FMOD_SPEAKERMODE speakerMode;
|
||||
SHBank masterBank, stringsBank, musicBank, sfxBank; //To do: change to map of banks loaded by resource manager
|
||||
|
||||
std::vector<SHAudioListenerComponent>* denseListener;
|
||||
AudioClipID clipID = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -14,6 +14,7 @@
|
|||
#include "SHpch.h"
|
||||
#include "../SHECSMacros.h"
|
||||
#include "SH_API.h"
|
||||
#include "ECS_Base/General/SHFamily.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
@ -117,4 +118,7 @@ namespace SHADE
|
|||
|
||||
|
||||
};
|
||||
|
||||
|
||||
template class SH_API SHFamilyID<SHComponent>;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
#pragma once
|
||||
|
||||
#include "ECS_Base/Components/SHComponent.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
struct SHComponentAddedEvent
|
||||
{
|
||||
EntityID eid;
|
||||
ComponentTypeID addedComponentType;
|
||||
};
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
#pragma once
|
||||
|
||||
#include "ECS_Base/Components/SHComponent.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
struct SHComponentRemovedEvent
|
||||
{
|
||||
EntityID eid;
|
||||
ComponentTypeID removedComponentType;
|
||||
};
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
#pragma once
|
||||
#include "SHFamily.h"
|
||||
#include "SHpch.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
//initialize currentID as 0
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -14,16 +14,17 @@
|
|||
#pragma once
|
||||
|
||||
#include "../SHECSMacros.h"
|
||||
#include "SH_API.h"
|
||||
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
||||
template<typename BaseClass>
|
||||
class SHFamilyID
|
||||
class SH_API SHFamilyID
|
||||
{
|
||||
private:
|
||||
//this is used to keep track of the new current ID to be assign to a new Derived class type.
|
||||
static ComponentTypeID currentID;
|
||||
|
||||
|
||||
/*!*************************************************************************
|
||||
* \brief Construct a new SHFamilyID object
|
||||
|
@ -46,6 +47,9 @@ namespace SHADE
|
|||
}
|
||||
public:
|
||||
|
||||
//this is used to keep track of the new current ID to be assign to a new Derived class type.
|
||||
static inline ComponentTypeID currentID = 0;
|
||||
|
||||
/*!*************************************************************************
|
||||
* \brief
|
||||
* Checks if this identifier is cuurrently in use / valid.
|
||||
|
@ -59,7 +63,6 @@ namespace SHADE
|
|||
{
|
||||
return(id < currentID);
|
||||
}
|
||||
|
||||
/*!*************************************************************************
|
||||
* \brief
|
||||
* Get the ID of a derived class type.
|
||||
|
@ -68,16 +71,27 @@ namespace SHADE
|
|||
* @tparam DerivedClass
|
||||
* The derived class type that we are trying to get the ID of.
|
||||
***************************************************************************/
|
||||
#ifdef SH_API_EXPORT
|
||||
template<typename DerivedClass>
|
||||
static ENABLE_IF_DERIVED(ComponentTypeID, BaseClass, DerivedClass) GetID() noexcept
|
||||
static SH_API ENABLE_IF_DERIVED(ComponentTypeID, BaseClass, DerivedClass) GetID() noexcept
|
||||
{
|
||||
//The first time a new derived class type call this get id, it will initialize id using the currentID from familyID class.
|
||||
static ComponentTypeID id = currentID++;
|
||||
static ComponentTypeID id = SHFamilyID<BaseClass>::currentID++;
|
||||
return id;
|
||||
//return 0;
|
||||
}
|
||||
#else
|
||||
template<typename DerivedClass>
|
||||
static SH_API ENABLE_IF_DERIVED(ComponentTypeID, BaseClass, DerivedClass) GetID() noexcept;
|
||||
#endif // SH_API_EXPORT
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
};
|
||||
//initialize currentID as 0
|
||||
template<typename BaseClass>
|
||||
ComponentTypeID SHFamilyID<BaseClass>::currentID = 0;
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -17,8 +17,11 @@
|
|||
#include "../General/SHSparseSetContainer.h"
|
||||
#include "../Components/SHComponent.h"
|
||||
#include "../Components/SHComponentGroup.h"
|
||||
#include "../Events/SHComponentAddedEvent.h"
|
||||
#include "../Events/SHComponentRemovedEvent.h"
|
||||
//#include "Scene/SHSceneNode.h"
|
||||
#include "SH_API.h"
|
||||
#include "Events/SHEventManager.hpp"
|
||||
|
||||
|
||||
#include <cassert>
|
||||
|
@ -216,6 +219,11 @@ namespace SHADE
|
|||
comp->OnCreate();
|
||||
}
|
||||
|
||||
SHComponentAddedEvent eventData;
|
||||
eventData.eid = entityID;
|
||||
eventData.addedComponentType = ComponentFamily::GetID<T>();
|
||||
|
||||
SHEventManager::BroadcastEvent<SHComponentAddedEvent>(eventData, SH_COMPONENT_ADDED_EVENT);
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
|
@ -247,6 +255,13 @@ namespace SHADE
|
|||
{
|
||||
comp->OnCreate();
|
||||
}
|
||||
|
||||
SHComponentAddedEvent eventData;
|
||||
eventData.eid = entityID;
|
||||
eventData.addedComponentType = componentTypeID;
|
||||
|
||||
SHEventManager::BroadcastEvent<SHComponentAddedEvent>(eventData, SH_COMPONENT_ADDED_EVENT);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -313,6 +328,12 @@ namespace SHADE
|
|||
|
||||
|
||||
componentSet.GetSparseSet<T>()->Remove(EntityHandleGenerator::GetIndex(entityID));
|
||||
|
||||
SHComponentRemovedEvent eventData;
|
||||
eventData.eid = entityID;
|
||||
eventData.removedComponentType = ComponentFamily::GetID<T>();
|
||||
|
||||
SHEventManager::BroadcastEvent<SHComponentRemovedEvent>(eventData, SH_COMPONENT_REMOVED_EVENT);
|
||||
}
|
||||
|
||||
/*!*************************************************************************
|
||||
|
@ -464,11 +485,6 @@ namespace SHADE
|
|||
return componentGroups[index];
|
||||
}
|
||||
|
||||
static void AddScriptComponent(EntityID eid, std::string const& scriptClassName) noexcept;
|
||||
|
||||
static void RemoveScriptComponent(EntityID eid, std::string const& scriptClassName) noexcept;
|
||||
|
||||
|
||||
};// end SHComponentManager
|
||||
|
||||
|
||||
|
|
|
@ -68,6 +68,9 @@ namespace SHADE
|
|||
id = ((SystemID)version << sizeof(SystemVersionID) * CHAR_BIT) + typeID;
|
||||
}
|
||||
systemContainer.emplace(id, std::make_unique<T>());
|
||||
|
||||
auto size = systemContainer.size();
|
||||
|
||||
systemContainer[id].get()->systemID = id;
|
||||
|
||||
return id;
|
||||
|
|
|
@ -26,4 +26,6 @@ const EntityIndex MAX_EID = 51000;
|
|||
#define ENABLE_IF_UINT(_TYPE, _RETURN)\
|
||||
typename std::enable_if<(std::is_integral<_TYPE>::value && !std::is_signed<_TYPE>::value),_RETURN>::type
|
||||
|
||||
|
||||
|
||||
#endif
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
#include "../SHECSMacros.h"
|
||||
#include "SH_API.h"
|
||||
#include "ECS_Base/General/SHFamily.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
@ -69,5 +70,9 @@ namespace SHADE
|
|||
};
|
||||
|
||||
|
||||
template class SH_API SHFamilyID<SHSystem>;
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "../Components/SHComponent.h"
|
||||
#include <rttr/registration>
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
@ -27,4 +28,50 @@ namespace SHADE
|
|||
std::string value{};
|
||||
};
|
||||
|
||||
class SHComponent_ENUM : public SHComponent
|
||||
{
|
||||
public:
|
||||
enum class Option
|
||||
{
|
||||
OPT_A,
|
||||
OPT_B,
|
||||
OPT_C
|
||||
};
|
||||
|
||||
bool boolTest{};
|
||||
int intTest{};
|
||||
float floatTest{};
|
||||
double doubleTest{};
|
||||
long longTest{};
|
||||
uint8_t uint8Test{};
|
||||
uint16_t uint16Test{};
|
||||
uint32_t uint32Test{};
|
||||
uint64_t uint64Test{};
|
||||
|
||||
|
||||
Option option;
|
||||
RTTR_ENABLE()
|
||||
};
|
||||
|
||||
RTTR_REGISTRATION
|
||||
{
|
||||
using namespace rttr;
|
||||
registration::enumeration<SHComponent_ENUM::Option>("Option")
|
||||
(
|
||||
value("Option A", SHComponent_ENUM::Option::OPT_A),
|
||||
value("Option B", SHComponent_ENUM::Option::OPT_B),
|
||||
value("Option C", SHComponent_ENUM::Option::OPT_C)
|
||||
);
|
||||
rttr::registration::class_<SHComponent_ENUM>("Enum Component")
|
||||
.property("Option", &SHComponent_ENUM::option)
|
||||
.property("boolTest", &SHComponent_ENUM::boolTest)
|
||||
.property("intTest", &SHComponent_ENUM::intTest)( metadata("MIN", 0.0f), metadata("MAX", 1.f))
|
||||
.property("floatTest", &SHComponent_ENUM::floatTest)(metadata("MIN", 0.0f), metadata("MAX", 1.f))
|
||||
.property("doubleTest", &SHComponent_ENUM::doubleTest)(metadata("MIN", 0.0f), metadata("MAX", 1.f))
|
||||
.property("uint8Test", &SHComponent_ENUM::uint8Test)(metadata("MIN", 0.0f), metadata("MAX", 1.f))
|
||||
.property("uint16Test", &SHComponent_ENUM::uint16Test)(metadata("MIN", 0.0f), metadata("MAX", 1.f))
|
||||
.property("uint32Test", &SHComponent_ENUM::uint32Test)(metadata("MIN", 0.0f), metadata("MAX", 1.f))
|
||||
.property("uint64Test", &SHComponent_ENUM::uint64Test)(metadata("MIN", 0.0f), metadata("MAX", 1.f));
|
||||
}
|
||||
|
||||
}
|
|
@ -12,6 +12,7 @@
|
|||
#include "Editor/IconsMaterialDesign.h"
|
||||
#include "ECS_Base/Components/SHComponent.h"
|
||||
#include "Editor/SHEditorWidgets.hpp"
|
||||
#include "Reflection/SHReflectionMetadata.h"
|
||||
namespace SHADE
|
||||
{
|
||||
template<typename T, std::enable_if_t<std::is_base_of<SHComponent, T>::value, bool> = true>
|
||||
|
@ -55,14 +56,136 @@ namespace SHADE
|
|||
{
|
||||
auto const& type = property.get_type();
|
||||
|
||||
if (type == rttr::type::get<SHVec4>())
|
||||
if(type.is_enumeration())
|
||||
{
|
||||
DragVec4(property.get_name().data(), { "X", "Y", "Z", "W" }, [component, property]() {return property.get_value(component).template convert<SHVec4>(); }, [component, property](SHVec4 vec) {return property.set_value(component, vec); });
|
||||
auto enumAlign = type.get_enumeration();
|
||||
auto names = enumAlign.get_names();
|
||||
std::vector<const char*> list;
|
||||
for(auto const& name : names)
|
||||
list.push_back(name.data());
|
||||
SHEditorWidgets::ComboBox(property.get_name().data(), list, [component, property]{return property.get_value(component).to_int();}, [component, property](int const& idx)
|
||||
{
|
||||
auto enumAlign = property.get_enumeration();
|
||||
auto values = enumAlign.get_values();
|
||||
auto it = std::next(values.begin(), idx);
|
||||
property.set_value(component, *it);
|
||||
});
|
||||
}
|
||||
else if(type.is_arithmetic())
|
||||
{
|
||||
if (type == rttr::type::get<bool>())
|
||||
{
|
||||
SHEditorWidgets::CheckBox(property.get_name().data(), [component, property]{return property.get_value(component).to_bool();}, [component, property](bool const& result){property.set_value(component, result);});
|
||||
}
|
||||
//else if (type == rttr::type::get<char>())
|
||||
//{
|
||||
//
|
||||
//}
|
||||
else if (type == rttr::type::get<int8_t>() || type == rttr::type::get<int16_t>() || type == rttr::type::get<int32_t>() || type == rttr::type::get<int64_t>())
|
||||
{
|
||||
auto metaMin = property.get_metadata(META::min);
|
||||
auto metaMax = property.get_metadata(META::max);
|
||||
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);});
|
||||
}
|
||||
else
|
||||
{
|
||||
SHEditorWidgets::DragInt(property.get_name().data(), [component, property]{return property.get_value(component).to_int();}, [component, property](int const& result){property.set_value(component, result);});
|
||||
}
|
||||
}
|
||||
else if (type == rttr::type::get<uint8_t>())
|
||||
{
|
||||
auto metaMin = property.get_metadata(META::min);
|
||||
auto metaMax = property.get_metadata(META::max);
|
||||
if(metaMin.is_valid() && metaMax.is_valid())
|
||||
{
|
||||
SHEditorWidgets::SliderScalar<uint8_t>(property.get_name().data(), ImGuiDataType_U8, metaMin.template get_value<uint8_t>(), metaMax.template get_value<uint8_t>(), [component, property]{return property.get_value(component).to_uint8();}, [component, property](uint8_t const& result){property.set_value(component, result);},"%zu");
|
||||
}
|
||||
else
|
||||
{
|
||||
SHEditorWidgets::DragScalar<uint8_t>(property.get_name().data(), ImGuiDataType_U8, [component, property]{return property.get_value(component).to_uint8();}, [component, property](uint8_t const& result){property.set_value(component, result);},0.1f,0,0,"%zu");
|
||||
}
|
||||
}
|
||||
else if (type == rttr::type::get<uint16_t>())
|
||||
{
|
||||
auto metaMin = property.get_metadata(META::min);
|
||||
auto metaMax = property.get_metadata(META::max);
|
||||
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");
|
||||
}
|
||||
else
|
||||
{
|
||||
SHEditorWidgets::DragScalar<uint16_t>(property.get_name().data(), ImGuiDataType_U16, [component, property]{return property.get_value(component).to_uint16();}, [component, property](uint16_t const& result){property.set_value(component, result);},0.1f,0,0,"%zu");
|
||||
}
|
||||
}
|
||||
else if (type == rttr::type::get<uint32_t>())
|
||||
{
|
||||
auto metaMin = property.get_metadata(META::min);
|
||||
auto metaMax = property.get_metadata(META::max);
|
||||
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");
|
||||
}
|
||||
else
|
||||
{
|
||||
SHEditorWidgets::DragScalar<uint32_t>(property.get_name().data(), ImGuiDataType_U32, [component, property]{ return property.get_value(component).to_uint32(); }, [component, property](uint32_t const& result){property.set_value(component, result); },0.1f,0,0,"%zu");
|
||||
}
|
||||
}
|
||||
else if (type == rttr::type::get<uint64_t>())
|
||||
{
|
||||
auto metaMin = property.get_metadata(META::min);
|
||||
auto metaMax = property.get_metadata(META::max);
|
||||
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");
|
||||
}
|
||||
else
|
||||
{
|
||||
SHEditorWidgets::DragScalar<uint64_t>(property.get_name().data(), ImGuiDataType_U64, [component, property]{return property.get_value(component).to_uint64();}, [component, property](uint64_t const& result){property.set_value(component, result);},0.1f,0,0,"%zu");
|
||||
}
|
||||
}
|
||||
else if (type == rttr::type::get<float>())
|
||||
{
|
||||
auto metaMin = property.get_metadata(META::min);
|
||||
auto metaMax = property.get_metadata(META::max);
|
||||
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);});
|
||||
}
|
||||
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);});
|
||||
}
|
||||
}
|
||||
else if (type == rttr::type::get<double>())
|
||||
{
|
||||
auto metaMin = property.get_metadata(META::min);
|
||||
auto metaMax = property.get_metadata(META::max);
|
||||
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);});
|
||||
}
|
||||
else
|
||||
{
|
||||
SHEditorWidgets::DragScalar<double>(property.get_name().data(), ImGuiDataType_Double, [component, property]{return property.get_value(component).to_double();}, [component, property](double const& result){property.set_value(component, result);}, 0.1f);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (type == rttr::type::get<SHVec4>())
|
||||
{
|
||||
SHEditorWidgets::DragVec4(property.get_name().data(), { "X", "Y", "Z", "W" }, [component, property]() {return property.get_value(component).template convert<SHVec4>(); }, [component, property](SHVec4 vec) {return property.set_value(component, vec); });
|
||||
}
|
||||
else if (type == rttr::type::get<SHVec3>())
|
||||
{
|
||||
DragVec3(property.get_name().data(), { "X", "Y", "Z" }, [component, property]() {return property.get_value(component).template convert<SHVec3>(); }, [component, property](SHVec3 vec) {return property.set_value(component, vec); });
|
||||
SHEditorWidgets::DragVec3(property.get_name().data(), { "X", "Y", "Z" }, [component, property]() {return property.get_value(component).template convert<SHVec3>(); }, [component, property](SHVec3 vec) {return property.set_value(component, vec); });
|
||||
}
|
||||
else if (type == rttr::type::get<SHVec2>())
|
||||
{
|
||||
SHEditorWidgets::DragVec2(property.get_name().data(), { "X", "Y"}, [component, property]() {return property.get_value(component).template convert<SHVec2>(); }, [component, property](SHVec2 vec) {return property.set_value(component, vec); });
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
else DrawContextMenu(component);
|
||||
|
|
|
@ -11,7 +11,13 @@
|
|||
#include "Editor/SHImGuiHelpers.hpp"
|
||||
#include "Editor/SHEditorWidgets.hpp"
|
||||
#include "SHEditorComponentView.hpp"
|
||||
#include "ECS_Base/UnitTesting/SHTestComponents.h"
|
||||
#include "Graphics/MiddleEnd/Interface/SHRenderable.h"
|
||||
#include "Scripting/SHScriptEngine.h"
|
||||
#include "ECS_Base/Managers/SHSystemManager.h"
|
||||
|
||||
#include "ECS_Base/Managers/SHSystemManager.h"
|
||||
#include "AudioSystem/SHAudioSystem.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
@ -39,13 +45,19 @@ namespace SHADE
|
|||
SHEditorWindow::Update();
|
||||
if (Begin())
|
||||
{
|
||||
if (ImGui::Button("AUDIO"))
|
||||
{
|
||||
auto audioSystem = SHSystemManager::GetSystem<SHADE::SHAudioSystem>();
|
||||
audioSystem->PlayEventOnce("event:/Characters/sfx_footsteps_raccoon");
|
||||
}
|
||||
|
||||
if (!SHEditor::selectedEntities.empty())
|
||||
{
|
||||
EntityID const& eid = SHEditor::selectedEntities[0];
|
||||
SHEntity* entity = SHEntityManager::GetEntityByID(eid);
|
||||
|
||||
ImGui::TextColored(ImGuiColors::green, "EID: %zu", eid);
|
||||
CheckBox("##IsActive", [entity]()->bool {return entity->GetActive(); }, [entity](bool const& active) {entity->SetActive(active); });
|
||||
SHEditorWidgets::CheckBox("##IsActive", [entity]()->bool {return entity->GetActive(); }, [entity](bool const& active) {entity->SetActive(active); });
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGui::InputText("##EntityName", &entity->name);
|
||||
|
@ -54,13 +66,27 @@ namespace SHADE
|
|||
{
|
||||
DrawComponent(transformComponent);
|
||||
}
|
||||
if(auto renderableComponent = SHComponentManager::GetComponent_s<SHRenderable>(eid))
|
||||
{
|
||||
DrawComponent(renderableComponent);
|
||||
}
|
||||
if(auto testComponent = SHComponentManager::GetComponent_s<SHComponent_ENUM>(eid))
|
||||
{
|
||||
DrawComponent(testComponent);
|
||||
}
|
||||
ImGui::Separator();
|
||||
if(ImGui::BeginMenu(std::format("{} Add Component", ICON_MD_LIBRARY_ADD).data()))
|
||||
{
|
||||
DrawAddComponentButton<SHTransformComponent>(eid);
|
||||
DrawAddComponentButton<SHRenderable>(eid);
|
||||
DrawAddComponentButton<SHComponent_ENUM>(eid);
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
// Render Scripts
|
||||
SHScriptEngine* scriptEngine = static_cast<SHScriptEngine*>(SHSystemManager::GetSystem<SHScriptEngine>());
|
||||
scriptEngine->RenderScriptsInInspector(eid);
|
||||
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
|
|
|
@ -6,6 +6,9 @@
|
|||
#include "SHEditorMenuBar.h"
|
||||
#include "Editor/IconsMaterialDesign.h"
|
||||
#include "Editor/Command/SHCommandManager.h"
|
||||
#include "Scripting/SHScriptEngine.h"
|
||||
#include "Editor/SHEditor.hpp"
|
||||
#include "ECS_Base/Managers/SHSystemManager.h"
|
||||
|
||||
//#==============================================================#
|
||||
//|| Library Includes ||
|
||||
|
@ -14,9 +17,6 @@
|
|||
#include <imgui_internal.h>
|
||||
#include <rttr/type>
|
||||
|
||||
#include "Editor/SHEditor.hpp"
|
||||
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
constexpr ImGuiWindowFlags editorMenuBarFlags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse |
|
||||
|
@ -100,6 +100,25 @@ namespace SHADE
|
|||
}
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
if (ImGui::BeginMenu("Scripts"))
|
||||
{
|
||||
if (ImGui::Selectable("Generate Visual Studio Project"))
|
||||
{
|
||||
auto* scriptEngine = static_cast<SHScriptEngine*>(SHSystemManager::GetSystem<SHScriptEngine>());
|
||||
scriptEngine->GenerateScriptsCsProjFile();
|
||||
}
|
||||
if (ImGui::Selectable("Build Scripts - Debug"))
|
||||
{
|
||||
auto* scriptEngine = static_cast<SHScriptEngine*>(SHSystemManager::GetSystem<SHScriptEngine>());
|
||||
scriptEngine->BuildScriptAssembly(true, true);
|
||||
}
|
||||
if (ImGui::Selectable("Build Scripts - Release"))
|
||||
{
|
||||
auto* scriptEngine = static_cast<SHScriptEngine*>(SHSystemManager::GetSystem<SHScriptEngine>());
|
||||
scriptEngine->BuildScriptAssembly(false, true);
|
||||
}
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
ImGui::EndMainMenuBar();
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
#include "SHpch.h"
|
||||
#include "SHEditorProfiler.h"
|
||||
#include <imgui.h>
|
||||
|
||||
#include "ECS_Base/Managers/SHSystemManager.h"
|
||||
#include "FRC/SHFramerateController.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
SHEditorProfiler::SHEditorProfiler()
|
||||
:SHEditorWindow("Profiler", ImGuiWindowFlags_None)
|
||||
{
|
||||
}
|
||||
|
||||
void SHEditorProfiler::Init()
|
||||
{
|
||||
SHEditorWindow::Init();
|
||||
}
|
||||
|
||||
void SHEditorProfiler::Update()
|
||||
{
|
||||
SHEditorWindow::Update();
|
||||
|
||||
const float dt = static_cast<float>(SHFrameRateController::GetRawDeltaTime());
|
||||
if(frames.size() > MaxFramesDisplayed)
|
||||
{
|
||||
for (size_t i = 1; i < frames.size(); i++)
|
||||
{
|
||||
frames[i-1] = frames[i];
|
||||
}
|
||||
frames[frames.size() - 1] = dt;
|
||||
}
|
||||
else
|
||||
{
|
||||
frames.push_back(dt);
|
||||
}
|
||||
if(Begin())
|
||||
{
|
||||
ImGui::PlotLines("DT", frames.data(), static_cast<int>(frames.size()), 0, nullptr, 0.0f, 16.0f);
|
||||
ImGui::End();
|
||||
}
|
||||
}
|
||||
|
||||
void SHEditorProfiler::Exit()
|
||||
{
|
||||
SHEditorWindow::Exit();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
#pragma once
|
||||
|
||||
#include "Editor/EditorWindow/SHEditorWindow.h"
|
||||
#include <vector>
|
||||
constexpr uint32_t MaxFramesDisplayed = 100;
|
||||
namespace SHADE
|
||||
{
|
||||
class SHEditorProfiler final : public SHEditorWindow
|
||||
{
|
||||
public:
|
||||
SHEditorProfiler();
|
||||
void Init() override;
|
||||
void Update() override;
|
||||
void Exit() override;
|
||||
|
||||
private:
|
||||
std::vector<float> frames;
|
||||
};
|
||||
}
|
|
@ -2,3 +2,4 @@
|
|||
#include "MenuBar/SHEditorMenuBar.h" //Menu Bar
|
||||
#include "HierarchyPanel/SHHierarchyPanel.h" //Hierarchy Panel
|
||||
#include "Inspector/SHEditorInspector.h" //Inspector
|
||||
#include "Profiling/SHEditorProfiler.h" //Profiler
|
|
@ -23,6 +23,8 @@
|
|||
#include "SHEditor.hpp"
|
||||
#include "SHEditorWidgets.hpp"
|
||||
|
||||
#include "Math/Transform/SHTransformSystem.h"
|
||||
|
||||
//#==============================================================#
|
||||
//|| Editor Window Includes ||
|
||||
//#==============================================================#
|
||||
|
@ -87,6 +89,11 @@ namespace SHADE
|
|||
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; //Enable docking
|
||||
|
||||
InitFonts();
|
||||
|
||||
|
||||
auto id = SHFamilyID<SHSystem>::GetID<SHGraphicsSystem>();
|
||||
auto id2 = SHFamilyID<SHSystem>::GetID<SHTransformSystem>();
|
||||
auto id3 = SHFamilyID<SHSystem>::GetID<SHGraphicsSystem>();
|
||||
InitBackend(sdlWindow);
|
||||
|
||||
SetStyle(Style::SHADE);
|
||||
|
@ -95,6 +102,7 @@ namespace SHADE
|
|||
CreateEditorWindow<SHEditorMenuBar>();
|
||||
CreateEditorWindow<SHHierarchyPanel>();
|
||||
CreateEditorWindow<SHEditorInspector>();
|
||||
CreateEditorWindow<SHEditorProfiler>();
|
||||
|
||||
SHLOG_INFO("Successfully initialised SHADE Engine Editor")
|
||||
}
|
||||
|
@ -103,10 +111,10 @@ namespace SHADE
|
|||
{
|
||||
(void)dt;
|
||||
NewFrame();
|
||||
|
||||
for (const auto& window : editorWindows | std::views::values)
|
||||
{
|
||||
window->Update();
|
||||
if(window->isOpen)
|
||||
window->Update();
|
||||
}
|
||||
|
||||
if(ImGui::IsKeyDown(ImGuiKey_LeftShift) && ImGui::IsKeyDown(ImGuiKey_LeftCtrl) && ImGui::IsKeyReleased(ImGuiKey_Z))
|
||||
|
@ -292,6 +300,8 @@ namespace SHADE
|
|||
imguiCommandBuffer->EndRecording();
|
||||
gfxSystem->GetQueue()->SubmitCommandBuffer({ imguiCommandBuffer }, {}, {}, vk::PipelineStageFlagBits::eNone, {});
|
||||
|
||||
gfxSystem->GetDevice()->WaitIdle();
|
||||
|
||||
ImGui_ImplVulkan_DestroyFontUploadObjects();
|
||||
|
||||
renderGraph->GetNode("ImGui Node")->GetSubpass("ImGui Draw")->AddExteriorDrawCalls([](Handle<SHVkCommandBuffer>& cmd) {
|
||||
|
|
|
@ -0,0 +1,259 @@
|
|||
/************************************************************************************//*!
|
||||
\file EditorUI.cpp
|
||||
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||
\par email: kahwei.tng\@digipen.edu
|
||||
\date Nov 7, 2021
|
||||
\brief Contains the implementation of the EditorUI class.
|
||||
|
||||
Copyright (C) 2021 DigiPen Institute of Technology.
|
||||
Reproduction or disclosure of this file or its contents without the prior written consent
|
||||
of DigiPen Institute of Technology is prohibited.
|
||||
*//*************************************************************************************/
|
||||
// Precompiled Header
|
||||
#include "SHpch.h"
|
||||
// Primary Header
|
||||
#include "SHEditorUI.h"
|
||||
// External Dependencies
|
||||
#include <imgui.h>
|
||||
#include "SHEditorWidgets.hpp"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* ImGui Wrapper Functions - ID Stack */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
void SHEditorUI::PushID(const std::string& id)
|
||||
{
|
||||
ImGui::PushID(id.c_str());
|
||||
}
|
||||
|
||||
void SHEditorUI::PushID(int id)
|
||||
{
|
||||
ImGui::PushID(id);
|
||||
}
|
||||
|
||||
void SHEditorUI::PopID()
|
||||
{
|
||||
ImGui::PopID();
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* ImGui Wrapper Functions - Indent */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
void SHEditorUI::Indent()
|
||||
{
|
||||
ImGui::Indent();
|
||||
}
|
||||
void SHEditorUI::Unindent()
|
||||
{
|
||||
ImGui::Unindent();
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* ImGui Wrapper Functions - Organizers */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
bool SHEditorUI::CollapsingHeader(const std::string& title)
|
||||
{
|
||||
return ImGui::CollapsingHeader(title.c_str());
|
||||
}
|
||||
|
||||
void SHEditorUI::SameLine()
|
||||
{
|
||||
ImGui::SameLine();
|
||||
}
|
||||
|
||||
void SHEditorUI::Separator()
|
||||
{
|
||||
ImGui::Separator();
|
||||
}
|
||||
|
||||
bool SHEditorUI::BeginMenu(const std::string& label)
|
||||
{
|
||||
return ImGui::BeginMenu(label.data());
|
||||
}
|
||||
|
||||
bool SHEditorUI::BeginMenu(const std::string& label, const char* icon)
|
||||
{
|
||||
return ImGui::BeginMenu(std::format("{} {}", icon, label.data()).data());
|
||||
}
|
||||
|
||||
void SHEditorUI::EndMenu()
|
||||
{
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* ImGui Wrapper Functions - Pop Ups */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
bool SHEditorUI::BeginPopup(const std::string& label)
|
||||
{
|
||||
return ImGui::BeginPopup(label.c_str());
|
||||
}
|
||||
|
||||
bool SHEditorUI::BeginPopupContextItem(const std::string& label)
|
||||
{
|
||||
return ImGui::BeginPopupContextItem(label.data());
|
||||
}
|
||||
|
||||
void SHEditorUI::EndPopup()
|
||||
{
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
void SHEditorUI::OpenPopup(const std::string& label)
|
||||
{
|
||||
ImGui::OpenPopup(label.c_str());
|
||||
}
|
||||
|
||||
bool SHEditorUI::MenuItem(const std::string& label)
|
||||
{
|
||||
return ImGui::MenuItem(label.c_str());
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* ImGui Wrapper Functions - Widgets */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
void SHEditorUI::Text(const std::string& title)
|
||||
{
|
||||
ImGui::Text(title.c_str());
|
||||
}
|
||||
bool SHEditorUI::SmallButton(const std::string& title)
|
||||
{
|
||||
return ImGui::SmallButton(title.c_str());
|
||||
}
|
||||
bool SHEditorUI::Button(const std::string& title)
|
||||
{
|
||||
return ImGui::Button(title.c_str());
|
||||
}
|
||||
|
||||
bool SHEditorUI::Selectable(const std::string& label)
|
||||
{
|
||||
return ImGui::Selectable(label.data());
|
||||
}
|
||||
|
||||
bool SHEditorUI::Selectable(const std::string& label, const char* icon)
|
||||
{
|
||||
return ImGui::Selectable(std::format("{} {}", icon, label).data());
|
||||
}
|
||||
|
||||
bool SHEditorUI::InputCheckbox(const std::string& label, bool& value)
|
||||
{
|
||||
ImGui::Text(label.c_str());
|
||||
ImGui::SameLine();
|
||||
return ImGui::Checkbox("#", &value);
|
||||
}
|
||||
bool SHEditorUI::InputInt(const std::string& label, int& value)
|
||||
{
|
||||
ImGui::Text(label.c_str());
|
||||
ImGui::SameLine();
|
||||
return ImGui::InputInt("#", &value,
|
||||
1, 10,
|
||||
ImGuiInputTextFlags_EnterReturnsTrue);
|
||||
}
|
||||
bool SHEditorUI::InputUnsignedInt(const std::string& label, unsigned int& value)
|
||||
{
|
||||
int signedVal = static_cast<int>(value);
|
||||
ImGui::Text(label.c_str());
|
||||
ImGui::SameLine();
|
||||
const bool CHANGED = InputInt("#", signedVal);
|
||||
if (CHANGED)
|
||||
{
|
||||
signedVal = std::clamp(signedVal, 0, std::numeric_limits<int>::max());
|
||||
value = static_cast<unsigned int>(signedVal);
|
||||
}
|
||||
return CHANGED;
|
||||
}
|
||||
bool SHEditorUI::InputFloat(const std::string& label, float& value)
|
||||
{
|
||||
ImGui::Text(label.c_str());
|
||||
ImGui::SameLine();
|
||||
return ImGui::InputFloat("#", &value,
|
||||
0.1f, 1.0f, "%.3f",
|
||||
ImGuiInputTextFlags_EnterReturnsTrue);
|
||||
}
|
||||
bool SHEditorUI::InputDouble(const std::string& label, double& value)
|
||||
{
|
||||
ImGui::Text(label.c_str());
|
||||
ImGui::SameLine();
|
||||
return ImGui::InputDouble("#", &value,
|
||||
0.1, 1.0, "%.3f",
|
||||
ImGuiInputTextFlags_EnterReturnsTrue);
|
||||
}
|
||||
bool SHEditorUI::InputAngle(const std::string& label, double& value)
|
||||
{
|
||||
ImGui::Text(label.c_str());
|
||||
ImGui::SameLine();
|
||||
return ImGui::InputDouble("#", &value,
|
||||
1.0, 45.0, "%.3f",
|
||||
ImGuiInputTextFlags_EnterReturnsTrue);
|
||||
}
|
||||
|
||||
bool SHEditorUI::InputSlider(const std::string& label, double min, double max, double& value)
|
||||
{
|
||||
float val = static_cast<float>(value);
|
||||
ImGui::Text(label.c_str());
|
||||
ImGui::SameLine();
|
||||
const bool CHANGED = ImGui::SliderFloat("#", &val,
|
||||
static_cast<float>(min), static_cast<float>(max), "%.3f",
|
||||
ImGuiInputTextFlags_EnterReturnsTrue);
|
||||
|
||||
if (CHANGED)
|
||||
{
|
||||
value = val;
|
||||
}
|
||||
|
||||
return CHANGED;
|
||||
}
|
||||
|
||||
bool SHEditorUI::InputVec2(const std::string& label, SHVec2& value)
|
||||
{
|
||||
static const std::vector<std::string> COMPONENT_LABELS = { "X", "Y" };
|
||||
return SHEditorWidgets::DragN<float, 2>(label, COMPONENT_LABELS, { &value.x, &value.y });
|
||||
}
|
||||
bool SHEditorUI::InputVec3(const std::string& label, SHVec3& value, float speed)
|
||||
{
|
||||
static const std::vector<std::string> COMPONENT_LABELS = { "X", "Y", "Z"};
|
||||
return SHEditorWidgets::DragN<float, 3>(label, COMPONENT_LABELS, { &value.x, &value.y, &value.z }, speed, "%.3f");
|
||||
}
|
||||
|
||||
bool SHEditorUI::InputTextField(const std::string& label, std::string& value)
|
||||
{
|
||||
std::array<char, TEXT_FIELD_MAX_LENGTH> buffer = { '\0' };
|
||||
strcpy_s(buffer.data(), TEXT_FIELD_MAX_LENGTH, value.c_str());
|
||||
ImGui::Text(label.c_str());
|
||||
ImGui::SameLine();
|
||||
const bool CHANGED = ImGui::InputText("#", &buffer[0], TEXT_FIELD_MAX_LENGTH);
|
||||
if (CHANGED)
|
||||
{
|
||||
value = std::string(buffer.data(), buffer.data() + TEXT_FIELD_MAX_LENGTH);
|
||||
}
|
||||
return CHANGED;
|
||||
}
|
||||
|
||||
bool SHEditorUI::InputEnumCombo(const std::string& label, int& v, const std::vector<std::string>& enumNames)
|
||||
{
|
||||
// Clamp input value
|
||||
const std::string& INITIAL_NAME = v >= static_cast<int>(enumNames.size()) ? "Unknown" : enumNames[v];
|
||||
bool b = false;
|
||||
|
||||
ImGui::Text(label.c_str());
|
||||
ImGui::SameLine();
|
||||
if (ImGui::BeginCombo("#", INITIAL_NAME.c_str(), ImGuiComboFlags_None))
|
||||
{
|
||||
for (int i = 0; i < enumNames.size(); ++i)
|
||||
{
|
||||
const bool IS_SELECTED = v == i;
|
||||
if (ImGui::Selectable(enumNames[i].c_str(), IS_SELECTED))
|
||||
{
|
||||
v = i;
|
||||
b = true;
|
||||
}
|
||||
if (IS_SELECTED)
|
||||
{
|
||||
ImGui::SetItemDefaultFocus();
|
||||
}
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
return b;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,286 @@
|
|||
/************************************************************************************//*!
|
||||
\file SHEditorUI.h
|
||||
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||
\par email: kahwei.tng\@digipen.edu
|
||||
\par email: t.yanchongclarence\@digipen.edu
|
||||
\date Sep 27, 2022
|
||||
\brief Defines a class that contains wrapper functions for ImGui.
|
||||
|
||||
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
|
||||
// Standard Library
|
||||
#include <functional> // std::function
|
||||
#include <string> // std::string
|
||||
// Project Includes
|
||||
#include "Math/Vector/SHVec2.h"
|
||||
#include "Math/Vector/SHVec3.h"
|
||||
#include "Math/Vector/SHVec4.h"
|
||||
#include "Math/SHMatrix.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/// <summary>
|
||||
/// Static class that contains useful functions for Editor UI using ImGui.
|
||||
/// </summary>
|
||||
class SH_API SHEditorUI final
|
||||
{
|
||||
public:
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Constants */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Maximum length of a string supported by InputTextField()
|
||||
/// </summary>
|
||||
static constexpr size_t TEXT_FIELD_MAX_LENGTH = 256;
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* ImGui Wrapper Functions - ID Stack */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Marks the start of a stack of ImGui widgets with the specified id.
|
||||
/// <br/>
|
||||
/// Wraps up ImGui::PushID().
|
||||
/// </summary>
|
||||
/// <param name="id">String-based ID.</param>
|
||||
static void PushID(const std::string& id);
|
||||
/// <summary>
|
||||
/// Marks the start of a stack of ImGui widgets with the specified id.
|
||||
/// <br/>
|
||||
/// Wraps up ImGui::PushID().
|
||||
/// </summary>
|
||||
/// <param name="id">Integer-based ID.</param>
|
||||
static void PushID(int id);
|
||||
/// <summary>
|
||||
/// Marks the end of a stack of ImGui widgets from the last PushID() call.
|
||||
/// <br/>
|
||||
/// Wraps up ImGui::PopID().
|
||||
/// </summary>
|
||||
static void PopID();
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* ImGui Wrapper Functions - Indent */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Indents the widgets rendered after this call.
|
||||
/// <br/>
|
||||
/// Wraps up ImGui::Indent().
|
||||
/// </summary>
|
||||
static void Indent();
|
||||
/// <summary>
|
||||
/// Unindents the widgets rendered after this call.
|
||||
/// <br/>
|
||||
/// Wraps up ImGui::Unindent().
|
||||
/// </summary>
|
||||
static void Unindent();
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* ImGui Wrapper Functions - Organizers */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Creates a collapsing title header.
|
||||
/// <br/>
|
||||
/// Wraps up ImGui::CollapsingHeader().
|
||||
/// </summary>
|
||||
/// <param name="title">Label for the header.</param>
|
||||
/// <returns>True if the header is open, false otherwise.</returns>
|
||||
static bool CollapsingHeader(const std::string& title);
|
||||
static void SameLine();
|
||||
static void Separator();
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* ImGui Wrapper Functions - Menu */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
static bool BeginMenu(const std::string& label);
|
||||
static bool BeginMenu(const std::string& label, const char* icon);
|
||||
static void EndMenu();
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* ImGui Wrapper Functions - Pop Ups */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Marks the start of a definition of a mini pop up that can show options.
|
||||
/// <br/>
|
||||
/// Wraps up ImGui::BeginPopup().
|
||||
/// </summary>
|
||||
/// <param name="label">Label used to identify this widget.</param>
|
||||
/// <returns>Whether or not the pop up is open.</returns>
|
||||
static bool BeginPopup(const std::string& label);
|
||||
static bool BeginPopupContextItem(const std::string& label);
|
||||
/// <summary>
|
||||
/// Marks the end of a definition of a mini pop up that can show options.
|
||||
/// <br/>
|
||||
/// Wraps up ImGui::EndPopup().
|
||||
/// </summary>
|
||||
static void EndPopup();
|
||||
/// <summary>
|
||||
/// Opens the popup that was defined with the specified label.
|
||||
/// <br/>
|
||||
/// Wraps up ImGui::OpenPopup().
|
||||
/// </summary>
|
||||
static void OpenPopup(const std::string& label);
|
||||
/// <summary>
|
||||
/// Creates a menu item in the list of items for a mini popup.
|
||||
/// <br/>
|
||||
/// Wraps up ImGui::MenuItem().
|
||||
/// </summary>
|
||||
/// <param name="label">Label used to identify this widget.</param>
|
||||
/// <returns>Whether or not the menu item was selected.</returns>
|
||||
static bool MenuItem(const std::string& label);
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* ImGui Wrapper Functions - Widgets */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Creates a visual text widget.
|
||||
/// <br/>
|
||||
/// Wraps up ImGui::Text().
|
||||
/// </summary>
|
||||
/// <param name="title">Text to display.</param>
|
||||
static void Text(const std::string& title);
|
||||
/// <summary>
|
||||
/// Creates a small inline button widget.
|
||||
/// <br/>
|
||||
/// Wraps up ImGui::SmallButton().
|
||||
/// </summary>
|
||||
/// <param name="title">Text to display.</param>
|
||||
/// <returns>True if button was pressed.</returns>
|
||||
static bool SmallButton(const std::string& title);
|
||||
/// <summary>
|
||||
/// Creates a inline button widget.
|
||||
/// <br/>
|
||||
/// Wraps up ImGui::Button().
|
||||
/// </summary>
|
||||
/// <param name="title">Text to display.</param>
|
||||
/// <returns>True if button was pressed.</returns>
|
||||
static bool Button(const std::string& title);
|
||||
static bool Selectable(const std::string& label);
|
||||
static bool Selectable(const std::string& label, const char* icon);
|
||||
/// <summary>
|
||||
/// Creates a checkbox widget for boolean input.
|
||||
/// <br/>
|
||||
/// Wraps up ImGui::Checkbox().
|
||||
/// </summary>
|
||||
/// <param name="label">Label used to identify this widget.</param>
|
||||
/// <param name="value">Reference to the variable to store the result.</param>
|
||||
/// <returns>True if the value was changed.</returns>
|
||||
static bool InputCheckbox(const std::string& label, bool& value);
|
||||
/// <summary>
|
||||
/// Creates a integer field widget for integer input.
|
||||
/// <br/>
|
||||
/// Wraps up ImGui::InputInt().
|
||||
/// </summary>
|
||||
/// <param name="label">Label used to identify this widget.</param>
|
||||
/// <param name="value">Reference to the variable to store the result.</param>
|
||||
/// <returns>True if the value was changed.</returns>
|
||||
static bool InputInt(const std::string& label, int& value);
|
||||
/// <summary>
|
||||
/// Creates a integer field widget for unsigned integer input.
|
||||
/// <br/>
|
||||
/// Wraps up ImGui::InputInt() with an additional clamping of values.
|
||||
/// <br/>
|
||||
/// Note: As a result, the range of this function limits it to the maximum
|
||||
/// value of a 32-bit signed integer instead of a 32-bit unsigned integer.
|
||||
/// </summary>
|
||||
/// <param name="label">Label used to identify this widget.</param>
|
||||
/// <param name="value">Reference to the variable to store the result.</param>
|
||||
/// <returns>True if the value was changed.</returns>
|
||||
static bool InputUnsignedInt(const std::string& label, unsigned int& value);
|
||||
/// <summary>
|
||||
/// Creates a decimal field widget for single precision float input.
|
||||
/// <br/>
|
||||
/// Wraps up ImGui::InputFloat().
|
||||
/// </summary>
|
||||
/// <param name="label">Label used to identify this widget.</param>
|
||||
/// <param name="value">Reference to the variable to store the result.</param>
|
||||
/// <returns>True if the value was changed.</returns>
|
||||
static bool InputFloat(const std::string& label, float& value);
|
||||
/// <summary>
|
||||
/// Creates a decimal field widget for double precision float input.
|
||||
/// <br/>
|
||||
/// Wraps up ImGui::InputDouble().
|
||||
/// </summary>
|
||||
/// <param name="label">Label used to identify this widget.</param>
|
||||
/// <param name="value">Reference to the variable to store the result.</param>
|
||||
/// <returns>True if the value was changed.</returns>
|
||||
static bool InputDouble(const std::string& label, double& value);
|
||||
/// <summary>
|
||||
/// Creates a decimal field widget for double input with increments of higher
|
||||
/// steps meant for angle variables.
|
||||
/// <br/>
|
||||
/// Wraps up ImGui::InputDouble().
|
||||
/// </summary>
|
||||
/// <param name="label">Label used to identify this widget.</param>
|
||||
/// <param name="value">Reference to the variable to store the result.</param>
|
||||
/// <returns>True if the value was changed.</returns>
|
||||
static bool InputAngle(const std::string& label, double& value);
|
||||
/// <summary>
|
||||
/// Creates a double slider field widget for double input.
|
||||
/// <br/>
|
||||
/// Wraps up ImGui::InputSliderFloat().
|
||||
/// </summary>
|
||||
/// <param name="label">Label used to identify this widget.</param>
|
||||
/// <param name="min">Minimum value of the slider.</param>
|
||||
/// <param name="max">Maximum value of the slider.</param>
|
||||
/// <param name="value">Reference to the variable to store the result.</param>
|
||||
/// <returns>True if the value was changed.</returns>
|
||||
static bool InputSlider(const std::string& label, double min, double max, double& value);
|
||||
/// <summary>
|
||||
/// Creates a 2x double field widget for Vector2 input.
|
||||
/// <br/>
|
||||
/// Wraps up ImGui::InputFloat2().
|
||||
/// </summary>
|
||||
/// <param name="label">Label used to identify this widget.</param>
|
||||
/// <param name="value">Reference to the variable to store the result.</param>
|
||||
/// <returns>True if the value was changed.</returns>
|
||||
static bool InputVec2(const std::string& label, SHVec2& value);
|
||||
/// <summary>
|
||||
/// Creates a 3x double field widget for Vector3 input.
|
||||
/// <br/>
|
||||
/// Wraps up ImGui::InputFloat3().
|
||||
/// </summary>
|
||||
/// <param name="label">Label used to identify this widget.</param>
|
||||
/// <param name="value">Reference to the variable to store the result.</param>
|
||||
/// <returns>True if the value was changed.</returns>
|
||||
static bool InputVec3(const std::string& label, SHVec3& value, float speed = 0.1f);
|
||||
/// <summary>
|
||||
/// Creates a text field widget for string input.
|
||||
/// <br/>
|
||||
/// Wraps up ImGui::InputText().
|
||||
/// </summary>
|
||||
/// <param name="label">Label used to identify this widget.</param>
|
||||
/// <param name="value">Reference to the variable to store the result.</param>
|
||||
/// <returns>True if the value was changed.</returns>
|
||||
static bool InputTextField(const std::string& label, std::string& value);
|
||||
/// <summary>
|
||||
/// Creates a combo box for enumeration input.
|
||||
/// </summary>
|
||||
/// <typeparam name="Enum">The type of enum to input.</typeparam>
|
||||
/// <param name="label">The name of the input.</param>
|
||||
/// <param name="v">The reference to the value to modify.</param>
|
||||
/// <param name="maxVal">The maximum value of the enum.</param>
|
||||
/// <param name="toStrFn">
|
||||
/// Conversion function from the type of enum to C-style string.
|
||||
/// </param>
|
||||
/// <returns>Whether the value was modified.</returns>
|
||||
template<typename Enum>
|
||||
static bool InputEnumCombo(const std::string& label, Enum& v, int maxVal, std::function<const char*(Enum)> toStrFn);
|
||||
/// <summary>
|
||||
/// Creates a combo box for enumeration input using a specified list of names.
|
||||
/// </summary>
|
||||
/// <param name="label">The name of the input.</param>
|
||||
/// <param name="v">The reference to the value to modify.</param>
|
||||
/// <param name="enumNames">Vector of names for each enumeration value.</param>
|
||||
/// <returns>Whether the value was modified.</returns>
|
||||
static bool InputEnumCombo(const std::string& label, int& v, const std::vector<std::string>& enumNames);
|
||||
|
||||
|
||||
private:
|
||||
// Prevent instantiation of this static class
|
||||
SHEditorUI() = delete;
|
||||
};
|
||||
}
|
||||
|
||||
#include "SHEditorUI.hpp"
|
|
@ -0,0 +1,51 @@
|
|||
/************************************************************************************//*!
|
||||
\file SHEditorUI.hpp
|
||||
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||
\par email: kahwei.tng\@digipen.edu
|
||||
\date Sep 27, 2022
|
||||
\brief Contains the implementation of editor inspector template functions.
|
||||
|
||||
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.
|
||||
*//*************************************************************************************/
|
||||
// Primary Header
|
||||
#include "SHEditorUI.h"
|
||||
// External Dependencies
|
||||
#include <imgui.h>
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* ImGui Wrapper Functions - Widgets */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
template<typename Enum>
|
||||
inline bool SHEditorUI::InputEnumCombo(const std::string& label, Enum& v, int maxVal, std::function<const char* (Enum)> toStrFn)
|
||||
{
|
||||
std::vector<Enum> values;
|
||||
for (int i = 0; i <= maxVal; ++i)
|
||||
{
|
||||
values.emplace_back(static_cast<Enum>(i));
|
||||
}
|
||||
bool b = false;
|
||||
if (ImGui::BeginCombo(label.c_str(), toStrFn(v), ImGuiComboFlags_None))
|
||||
{
|
||||
for (int i = 0; i <= maxVal; ++i)
|
||||
{
|
||||
const auto VALUE = values[i];
|
||||
const bool IS_SELECTED = v == VALUE;
|
||||
if (ImGui::Selectable(toStrFn(VALUE), IS_SELECTED))
|
||||
{
|
||||
v = VALUE;
|
||||
b = true;
|
||||
}
|
||||
if (IS_SELECTED)
|
||||
{
|
||||
ImGui::SetItemDefaultFocus();
|
||||
}
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
return b;
|
||||
}
|
||||
}
|
|
@ -12,6 +12,7 @@
|
|||
#include "Math/SHMath.h"
|
||||
#include "Command/SHCommandManager.h"
|
||||
#include "SHImGuiHelpers.hpp"
|
||||
#include "SH_API.h"
|
||||
|
||||
//#==============================================================#
|
||||
//|| Library Includes ||
|
||||
|
@ -23,165 +24,315 @@
|
|||
|
||||
namespace SHADE
|
||||
{
|
||||
//#==============================================================#
|
||||
//|| Custom Widgets ||
|
||||
//#==============================================================#
|
||||
static bool Splitter(bool verticalSplit, float thickness, float* size1, float* size2, float minSize1, float minSize2, float splitterAxisSize = -1.0f)
|
||||
class SH_API SHEditorWidgets
|
||||
{
|
||||
ImGuiWindow* window = ImGui::GetCurrentWindow();
|
||||
const ImGuiID id = window->GetID("##Splitter");
|
||||
ImRect bb;
|
||||
bb.Min = window->DC.CursorPos + (verticalSplit ? ImVec2(*size1, 0.0f) : ImVec2(0.0f, *size1));
|
||||
bb.Max = bb.Min + (verticalSplit ? ImVec2(thickness, splitterAxisSize) : ImVec2(splitterAxisSize, thickness));
|
||||
return ImGui::SplitterBehavior(bb, id, verticalSplit ? ImGuiAxis_X : ImGuiAxis_Y, size1, size2, minSize1, minSize2, 0.0f);
|
||||
}
|
||||
public:
|
||||
//#==============================================================#
|
||||
//|| Constructor ||
|
||||
//#==============================================================#
|
||||
SHEditorWidgets() = delete;
|
||||
|
||||
template <typename T, std::size_t N>
|
||||
static bool DragN(const std::string& fieldLabel, std::vector<std::string>const& componentLabels,
|
||||
std::vector<T*> values, float speed = 0.1f, const char* displayFormat = "", T valueMin = T(), T valueMax = T(),
|
||||
ImGuiSliderFlags flags = 0)
|
||||
{
|
||||
const ImGuiWindow* const window = ImGui::GetCurrentWindow();
|
||||
if (window->SkipItems)
|
||||
return false;
|
||||
|
||||
const ImGuiContext& g = *GImGui;
|
||||
bool valueChanged = false;
|
||||
ImGui::BeginGroup();
|
||||
ImGui::PushID(fieldLabel.c_str());
|
||||
PushMultiItemsWidthsAndLabels(componentLabels, 0.0f);
|
||||
ImGui::BeginColumns("DragVecCol", 2, ImGuiOldColumnFlags_NoBorder | ImGuiOldColumnFlags_NoResize);
|
||||
ImGui::SetColumnWidth(-1, 80.0f);
|
||||
ImGui::Text(fieldLabel.c_str());
|
||||
ImGui::NextColumn();
|
||||
for (std::size_t i = 0; i < N; ++i)
|
||||
//#==============================================================#
|
||||
//|| Custom Widgets ||
|
||||
//#==============================================================#
|
||||
static bool Splitter(bool verticalSplit, float thickness, float* size1, float* size2, float minSize1, float minSize2, float splitterAxisSize = -1.0f)
|
||||
{
|
||||
ImGui::PushID(static_cast<int>(i));
|
||||
ImGui::TextUnformatted(componentLabels[i].c_str(), ImGui::FindRenderedTextEnd(componentLabels[i].c_str())); ImGui::SameLine();
|
||||
ImGui::SetNextItemWidth(80.0f);
|
||||
valueChanged |= ImGui::DragFloat("##v", values[i], speed, valueMin, valueMax, displayFormat, flags);
|
||||
|
||||
const ImVec2 min = ImGui::GetItemRectMin();
|
||||
const ImVec2 max = ImGui::GetItemRectMax();
|
||||
const float spacing = g.Style.FrameRounding;
|
||||
const float halfSpacing = spacing / 2;
|
||||
|
||||
window->DrawList->AddLine({ min.x + spacing, max.y - halfSpacing }, { max.x - spacing, max.y - halfSpacing },
|
||||
ImGuiColors::colors[i], 4);
|
||||
|
||||
ImGui::SameLine(0, g.Style.ItemInnerSpacing.x);
|
||||
ImGui::PopID();
|
||||
ImGui::PopItemWidth();
|
||||
ImGuiWindow* window = ImGui::GetCurrentWindow();
|
||||
const ImGuiID id = window->GetID("##Splitter");
|
||||
ImRect bb;
|
||||
bb.Min = window->DC.CursorPos + (verticalSplit ? ImVec2(*size1, 0.0f) : ImVec2(0.0f, *size1));
|
||||
bb.Max = bb.Min + (verticalSplit ? ImVec2(thickness, splitterAxisSize) : ImVec2(splitterAxisSize, thickness));
|
||||
return ImGui::SplitterBehavior(bb, id, verticalSplit ? ImGuiAxis_X : ImGuiAxis_Y, size1, size2, minSize1, minSize2, 0.0f);
|
||||
}
|
||||
ImGui::EndColumns();
|
||||
ImGui::PopID();
|
||||
ImGui::EndGroup();
|
||||
|
||||
return valueChanged;
|
||||
}
|
||||
template <typename T, std::size_t N>
|
||||
static bool DragN(const std::string& fieldLabel, std::vector<std::string>const& componentLabels,
|
||||
std::vector<T*> values, float speed = 0.1f, const char* displayFormat = "", T valueMin = T(), T valueMax = T(),
|
||||
ImGuiSliderFlags flags = 0)
|
||||
{
|
||||
const ImGuiWindow* const window = ImGui::GetCurrentWindow();
|
||||
if (window->SkipItems)
|
||||
return false;
|
||||
|
||||
const ImGuiContext& g = *GImGui;
|
||||
bool valueChanged = false;
|
||||
ImGui::BeginGroup();
|
||||
ImGui::PushID(fieldLabel.c_str());
|
||||
PushMultiItemsWidthsAndLabels(componentLabels, 0.0f);
|
||||
ImGui::BeginColumns("DragVecCol", 2, ImGuiOldColumnFlags_NoBorder | ImGuiOldColumnFlags_NoResize);
|
||||
ImGui::SetColumnWidth(-1, 80.0f);
|
||||
ImGui::Text(fieldLabel.c_str());
|
||||
ImGui::NextColumn();
|
||||
for (std::size_t i = 0; i < N; ++i)
|
||||
{
|
||||
ImGui::PushID(static_cast<int>(i));
|
||||
ImGui::TextUnformatted(componentLabels[i].c_str(), ImGui::FindRenderedTextEnd(componentLabels[i].c_str())); ImGui::SameLine();
|
||||
ImGui::SetNextItemWidth(80.0f);
|
||||
valueChanged |= ImGui::DragFloat("##v", values[i], speed, valueMin, valueMax, displayFormat, flags);
|
||||
|
||||
const ImVec2 min = ImGui::GetItemRectMin();
|
||||
const ImVec2 max = ImGui::GetItemRectMax();
|
||||
const float spacing = g.Style.FrameRounding;
|
||||
const float halfSpacing = spacing / 2;
|
||||
|
||||
window->DrawList->AddLine({ min.x + spacing, max.y - halfSpacing }, { max.x - spacing, max.y - halfSpacing },
|
||||
ImGuiColors::colors[i], 4);
|
||||
|
||||
ImGui::SameLine(0, g.Style.ItemInnerSpacing.x);
|
||||
ImGui::PopID();
|
||||
ImGui::PopItemWidth();
|
||||
}
|
||||
ImGui::EndColumns();
|
||||
ImGui::PopID();
|
||||
ImGui::EndGroup();
|
||||
|
||||
return valueChanged;
|
||||
}
|
||||
|
||||
static bool DragVec2(const std::string& fieldLabel, 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,
|
||||
ImGuiSliderFlags flags = 0)
|
||||
{
|
||||
SHVec2 values = get();
|
||||
bool changed = false;
|
||||
if (DragN<float, 2>(fieldLabel, componentLabels, {&values.x, &values.y}, speed, displayFormat, valueMin, valueMax, flags))
|
||||
std::function<void(SHVec2)> set, float speed = 0.1f, const char* displayFormat = "%.3f", float valueMin = 0.0f, float valueMax = 0.0f,
|
||||
ImGuiSliderFlags flags = 0)
|
||||
{
|
||||
changed = true;
|
||||
SHVec2 values = get();
|
||||
bool changed = false;
|
||||
if (DragN<float, 2>(fieldLabel, componentLabels, { &values.x, &values.y }, speed, displayFormat, valueMin, valueMax, flags))
|
||||
{
|
||||
changed = true;
|
||||
}
|
||||
|
||||
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)), false);
|
||||
else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left))
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec2>>(get(), values, set)), true);
|
||||
else if (ImGui::IsItemDeactivatedAfterEdit())
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec2>>(get(), values, set)), false);
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
if (changed)
|
||||
static bool DragVec3(const std::string& fieldLabel, 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,
|
||||
ImGuiSliderFlags flags = 0)
|
||||
{
|
||||
if (ImGui::IsMouseClicked(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left))
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec2>>(get(), values, set)), false);
|
||||
else if(ImGui::IsMouseDragging(ImGuiMouseButton_Left))
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec2>>(get(), values, set)), true);
|
||||
else if(ImGui::IsItemDeactivatedAfterEdit())
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec2>>(get(), values, set)), false);
|
||||
SHVec3 values = get();
|
||||
bool changed = false;
|
||||
if (DragN<float, 3>(fieldLabel, componentLabels, { &values.x, &values.y, &values.z }, speed, displayFormat, valueMin, valueMax, flags))
|
||||
{
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (changed)
|
||||
{
|
||||
if (ImGui::IsMouseDown(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left, -0.2f))
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec3>>(get(), values, set)), false);
|
||||
else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left))
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec3>>(get(), values, set)), true);
|
||||
else if (ImGui::IsItemDeactivatedAfterEdit())
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec3>>(get(), values, set)), false);
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
static bool DragVec3(const std::string& fieldLabel, 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,
|
||||
ImGuiSliderFlags flags = 0)
|
||||
{
|
||||
SHVec3 values = get();
|
||||
bool changed = false;
|
||||
if (DragN<float, 3>(fieldLabel, componentLabels, {&values.x, &values.y, &values.z}, speed, displayFormat, valueMin, valueMax, flags))
|
||||
static bool DragVec4(const std::string& fieldLabel, 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,
|
||||
ImGuiSliderFlags flags = 0)
|
||||
{
|
||||
changed = true;
|
||||
SHVec4 values = get();
|
||||
bool changed = false;
|
||||
if (DragN<float, 4>(fieldLabel, componentLabels, { &values.x, &values.y, &values.z, &values.w }, speed, displayFormat, valueMin, valueMax, flags))
|
||||
{
|
||||
changed = true;
|
||||
}
|
||||
|
||||
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)), false);
|
||||
else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left))
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec4>>(get(), values, set)), true);
|
||||
else if (ImGui::IsItemDeactivatedAfterEdit())
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec4>>(get(), values, set)), false);
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
if (changed)
|
||||
//#==============================================================#
|
||||
//|| Widget Extensions ||
|
||||
//#==============================================================#
|
||||
|
||||
static bool CheckBox(std::string const& label, std::function<bool(void)> get, std::function<void(bool const&)> set)
|
||||
{
|
||||
if (ImGui::IsMouseDown(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left, -0.2f))
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec3>>(get(), values, set)), false);
|
||||
else if(ImGui::IsMouseDragging(ImGuiMouseButton_Left))
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec3>>(get(), values, set)), true);
|
||||
else if(ImGui::IsItemDeactivatedAfterEdit())
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec3>>(get(), values, set)), false);
|
||||
bool value = get();
|
||||
if (ImGui::Checkbox(label.c_str(), &value))
|
||||
{
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<bool>>(get(), value, set)), false);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
static bool DragVec4(const std::string& fieldLabel, 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,
|
||||
ImGuiSliderFlags flags = 0)
|
||||
{
|
||||
SHVec4 values = get();
|
||||
bool changed = false;
|
||||
if (DragN<float, 4>(fieldLabel, componentLabels, {&values.x, &values.y, &values.z, &values.w}, speed, displayFormat, valueMin, valueMax, flags))
|
||||
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)
|
||||
{
|
||||
changed = true;
|
||||
}
|
||||
|
||||
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)), false);
|
||||
else if(ImGui::IsMouseDragging(ImGuiMouseButton_Left))
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec4>>(get(), values, set)), true);
|
||||
else if(ImGui::IsItemDeactivatedAfterEdit())
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec4>>(get(), values, set)), false);
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
//#==============================================================#
|
||||
//|| Widget Extensions ||
|
||||
//#==============================================================#
|
||||
|
||||
static bool CheckBox(std::string const& label, std::function<bool(void)> get, std::function<void(bool const&)> set)
|
||||
{
|
||||
bool value = get();
|
||||
if (ImGui::Checkbox(label.c_str(), &value))
|
||||
{
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<bool>>(get(), value, set)), false);
|
||||
T type = get();
|
||||
for (size_t i = 0; i < listTypes.size(); i++)
|
||||
{
|
||||
if (ImGui::RadioButton(listLabels[i].c_str(), type == listTypes[i]))
|
||||
{
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<T>>(get(), listTypes[i], set)), false);
|
||||
}
|
||||
ImGui::SameLine();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
T type = get();
|
||||
for (size_t i = 0; i < listTypes.size(); i++)
|
||||
static bool InputText(const std::string& label, const std::function<std::string(void)> get,
|
||||
const std::function<void(std::string)> set, ImGuiInputTextFlags flag = 0,
|
||||
ImGuiInputTextCallback callback = (ImGuiInputTextCallback)0, void* userData = (void*)0)
|
||||
{
|
||||
if (ImGui::RadioButton(listLabels[i].c_str(), type == listTypes[i]))
|
||||
std::string text = get();
|
||||
if (ImGui::InputText(label.c_str(), &text, flag, callback, userData))
|
||||
{
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<T>>(get(), listTypes[i], set)), false);
|
||||
if (ImGui::IsItemDeactivatedAfterEdit())
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<std::string>>(get(), text, set)), false);
|
||||
|
||||
return true;
|
||||
}
|
||||
ImGui::SameLine();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
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))
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<T>>(get(), value, set)), false);
|
||||
else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left))
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<T>>(get(), value, set)), true);
|
||||
else if (ImGui::IsItemDeactivatedAfterEdit())
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<T>>(get(), value, set)), false);
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool DragFloat(const std::string& fieldLabel, std::function<float(void)> get, std::function<void(float const&)> set,
|
||||
float speed = 0.1f, float p_min = float(), float p_max = float(), const char* displayFormat = "%.3f", ImGuiSliderFlags flags = 0)
|
||||
{
|
||||
float value = get();
|
||||
//bool hasChange = ImGui::DragFloat(fieldLabel.c_str(), &value, speed, p_min, p_max, displayFormat, flags);
|
||||
if (ImGui::DragFloat(fieldLabel.c_str(), &value, speed, p_min, p_max, displayFormat, flags))
|
||||
{
|
||||
if (ImGui::IsMouseDown(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left))
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<float>>(get(), value, set)), false);
|
||||
else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left))
|
||||
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;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool DragInt(const std::string& fieldLabel, std::function<int(void)> get, std::function<void(int const&)> set,
|
||||
float speed = 1.0f, int p_min = int(), int p_max = int(), const char* displayFormat = "%d", ImGuiSliderFlags flags = 0)
|
||||
{
|
||||
int value = get();
|
||||
//bool hasChange = ImGui::DragFloat(fieldLabel.c_str(), &value, speed, p_min, p_max, displayFormat, flags);
|
||||
if (ImGui::DragInt(fieldLabel.c_str(), &value, speed, p_min, p_max, displayFormat, flags))
|
||||
{
|
||||
if (ImGui::IsMouseDown(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left))
|
||||
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);
|
||||
else if (ImGui::IsItemDeactivatedAfterEdit())
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<int>>(get(), value, set)), false);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
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,
|
||||
const char* displayFormat = "%.3f", ImGuiSliderFlags flags = 0)
|
||||
{
|
||||
T value = get();
|
||||
if (ImGui::SliderScalar(fieldLabel.c_str(), data_type, &value, &min, &max, displayFormat, flags))
|
||||
{
|
||||
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)), false);
|
||||
else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left))
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<T>>(get(), value, set)), true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool SliderFloat(const std::string& fieldLabel, float min, float max, std::function<float(void)> get, std::function<void(float const&)> set,
|
||||
const char* displayFormat = "%.3f", ImGuiSliderFlags flags = 0)
|
||||
{
|
||||
float value = get();
|
||||
if (ImGui::SliderFloat(fieldLabel.c_str(), &value, min, max, displayFormat, flags))
|
||||
{
|
||||
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)), false);
|
||||
else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left))
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<float>>(get(), value, set)), true);
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool SliderInt(const std::string& fieldLabel, int min, int max, std::function<int(void)> get, std::function<void(int const&)> set,
|
||||
const char* displayFormat = "%d", ImGuiSliderFlags flags = 0)
|
||||
{
|
||||
int value = get();
|
||||
if (ImGui::SliderInt(fieldLabel.c_str(), &value, min, max, displayFormat, flags))
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool ComboBox(const std::string& fieldLabel, std::vector<const char*> list, std::function<int(void)> get, std::function<void(int const&)> set)
|
||||
{
|
||||
bool edited = false;
|
||||
int selected = get();
|
||||
ImGui::PushID(fieldLabel.c_str());
|
||||
ImGui::Text(fieldLabel.c_str()); ImGui::SameLine();
|
||||
|
||||
if (edited = ImGui::Combo("##Combo", &selected, list.data(), list.size()))
|
||||
{
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<int>>(get(), selected, set)), false);
|
||||
}
|
||||
ImGui::PopID();
|
||||
return edited;
|
||||
}
|
||||
};
|
||||
}//namespace SHADE
|
||||
|
|
|
@ -8,3 +8,5 @@ typedef uint32_t SHEventHandle;
|
|||
constexpr SHEventIdentifier SH_EXAMPLE_EVENT{0};
|
||||
constexpr SHEventIdentifier SH_ENTITY_DESTROYED_EVENT{ 1 };
|
||||
constexpr SHEventIdentifier SH_ENTITY_CREATION_EVENT{ 2 };
|
||||
constexpr SHEventIdentifier SH_COMPONENT_ADDED_EVENT{ 3 };
|
||||
constexpr SHEventIdentifier SH_COMPONENT_REMOVED_EVENT{ 4 };
|
||||
|
|
|
@ -9,12 +9,31 @@
|
|||
consent of DigiPen Institute of Technology is prohibited.
|
||||
*********************************************************************/
|
||||
|
||||
|
||||
//TODO Legacy code. Delete soon
|
||||
|
||||
#include <chrono>
|
||||
#include <cassert>
|
||||
#include <SHpch.h>
|
||||
#include "SHFramerateController.h"
|
||||
#include "../Tools/SHLogger.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
double SHFrameRateController::rawDeltaTime = 0.0;
|
||||
std::chrono::steady_clock::time_point SHFrameRateController::prevFrameTime = std::chrono::high_resolution_clock::now();
|
||||
|
||||
void SHFrameRateController::UpdateFRC() noexcept
|
||||
{
|
||||
std::chrono::duration<double> deltaTime;
|
||||
deltaTime = std::chrono::high_resolution_clock::now() - prevFrameTime;
|
||||
prevFrameTime = std::chrono::high_resolution_clock::now();
|
||||
rawDeltaTime = deltaTime.count();
|
||||
}
|
||||
}
|
||||
|
||||
//TODO Legacy code. Delete soon
|
||||
#if 0
|
||||
namespace SHADE
|
||||
{
|
||||
//Init statics
|
||||
|
@ -132,3 +151,4 @@ namespace SHADE
|
|||
}
|
||||
}
|
||||
}
|
||||
#endif
|
|
@ -13,6 +13,38 @@
|
|||
#define SH_FRAMERATECONTROLLER_H
|
||||
#pragma once
|
||||
|
||||
#include <chrono>
|
||||
#include "Tools/SHLogger.h"
|
||||
#include "SH_API.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
class SH_API SHFrameRateController
|
||||
{
|
||||
private:
|
||||
//Varying delta time. The actual time it took for every frame
|
||||
static double rawDeltaTime;
|
||||
static std::chrono::steady_clock::time_point prevFrameTime;
|
||||
|
||||
|
||||
public:
|
||||
//Gets the raw delta time
|
||||
static inline double GetRawDeltaTime() noexcept
|
||||
{
|
||||
return rawDeltaTime;
|
||||
}
|
||||
|
||||
//Updates the raw delta time accordingly
|
||||
static void UpdateFRC() noexcept;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
//TODO Legacy code. Delete soon
|
||||
#if 0
|
||||
#include "../Scene/SHScene.h"
|
||||
|
||||
namespace SHADE
|
||||
|
@ -56,7 +88,19 @@ namespace SHADE
|
|||
//halt execution of the current scene and prepare
|
||||
//execution of the next
|
||||
static inline void SetNextScene(SHScene* const next) { nextScene = next; }
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
|
@ -39,8 +39,10 @@ namespace SHADE
|
|||
std::vector<vk::DescriptorPoolSize> Limits =
|
||||
{
|
||||
{ vk::DescriptorType::eCombinedImageSampler, 100 },
|
||||
{ vk::DescriptorType::eUniformBuffer, 100 },
|
||||
{ vk::DescriptorType::eUniformBufferDynamic, 100 }
|
||||
{ vk::DescriptorType::eUniformBuffer, 100 },
|
||||
{ vk::DescriptorType::eUniformBufferDynamic, 100 },
|
||||
{ vk::DescriptorType::eStorageImage, 100},
|
||||
{ vk::DescriptorType::eStorageBufferDynamic, 100 }
|
||||
};
|
||||
/// <summary>
|
||||
/// Maximum number of descriptor sets allowed
|
||||
|
|
|
@ -155,7 +155,7 @@ namespace SHADE
|
|||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
void SHVkDescriptorSetGroup::ModifyWriteDescImage(uint32_t set, uint32_t binding, std::span<std::pair<Handle<SHVkImageView>, Handle<SHVkSampler>>> const& imageViewsAndSamplers) noexcept
|
||||
void SHVkDescriptorSetGroup::ModifyWriteDescImage(uint32_t set, uint32_t binding, std::span<std::tuple<Handle<SHVkImageView>, Handle<SHVkSampler>, vk::ImageLayout>> const& imageViewsAndSamplers) noexcept
|
||||
{
|
||||
// Find the target writeDescSet
|
||||
BindingAndSetHash writeHash = binding;
|
||||
|
@ -170,9 +170,10 @@ namespace SHADE
|
|||
for (uint32_t i = 0; i < imageViewsAndSamplers.size(); ++i)
|
||||
{
|
||||
// write sampler and image view
|
||||
auto& ivs = imageViewsAndSamplers[i];
|
||||
writeInfo.descImageInfos[i].imageView = ivs.first->GetImageView();
|
||||
writeInfo.descImageInfos[i].sampler = ivs.second->GetVkSampler();
|
||||
auto& [view, sampler, layout] = imageViewsAndSamplers[i];
|
||||
writeInfo.descImageInfos[i].imageView = view->GetImageView();
|
||||
writeInfo.descImageInfos[i].sampler = sampler->GetVkSampler();
|
||||
writeInfo.descImageInfos[i].imageLayout = layout;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <tuple>
|
||||
|
||||
// Project Includes
|
||||
#include "Graphics/SHVulkanIncludes.h"
|
||||
#include "Resource/Handle.h"
|
||||
|
@ -63,7 +65,7 @@ namespace SHADE
|
|||
void UpdateDescriptorSetImages(uint32_t set, uint32_t binding) noexcept;
|
||||
void UpdateDescriptorSetBuffer(uint32_t set, uint32_t binding) noexcept;
|
||||
|
||||
void ModifyWriteDescImage(uint32_t set, uint32_t binding, std::span<std::pair<Handle<SHVkImageView>, Handle<SHVkSampler>>> const& imageViewsAndSamplers) noexcept;
|
||||
void ModifyWriteDescImage(uint32_t set, uint32_t binding, std::span<std::tuple<Handle<SHVkImageView>, Handle<SHVkSampler>, vk::ImageLayout>> const& imageViewsAndSamplers) noexcept;
|
||||
void ModifyWriteDescBuffer (uint32_t set, uint32_t binding, std::span<Handle<SHVkBuffer>> const& buffers, uint32_t offset, uint32_t range) noexcept;
|
||||
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "Graphics/Framebuffer/SHVkFramebuffer.h"
|
||||
#include "Graphics/Images/SHVkImageView.h"
|
||||
#include "Graphics/Descriptors/SHVkDescriptorSetGroup.h"
|
||||
#include "Graphics/Images/SHVkSampler.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
@ -85,6 +86,17 @@ namespace SHADE
|
|||
|
||||
}
|
||||
|
||||
uint32_t SHVkLogicalDevice::ComputeAlignedBufferSize(uint32_t originalSize, size_t alignmentSize) const noexcept
|
||||
{
|
||||
uint32_t alignedSize = originalSize;
|
||||
//uint32_t minBuffer
|
||||
if (alignmentSize > 0)
|
||||
{
|
||||
alignedSize = (alignedSize + alignmentSize - 1) & ~(alignmentSize - 1);
|
||||
}
|
||||
return alignedSize;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
|
@ -176,6 +188,7 @@ namespace SHADE
|
|||
// point and lines fill mode
|
||||
features.fillModeNonSolid = true;
|
||||
features.samplerAnisotropy = VK_TRUE;
|
||||
features.multiDrawIndirect = true;
|
||||
|
||||
// for wide lines
|
||||
features.wideLines = true;
|
||||
|
@ -288,13 +301,12 @@ namespace SHADE
|
|||
|
||||
uint32_t SHVkLogicalDevice::PadUBOSize(uint32_t originalSize) const noexcept
|
||||
{
|
||||
uint32_t alignedSize = originalSize;
|
||||
//uint32_t minBuffer
|
||||
if (uboBufferMemoryAlignment > 0)
|
||||
{
|
||||
alignedSize = (alignedSize + uboBufferMemoryAlignment - 1) & ~(uboBufferMemoryAlignment - 1);
|
||||
}
|
||||
return alignedSize;
|
||||
return ComputeAlignedBufferSize(originalSize, uboBufferMemoryAlignment);
|
||||
}
|
||||
|
||||
uint32_t SHVkLogicalDevice::PadSSBOSize(uint32_t originalSize) const noexcept
|
||||
{
|
||||
return ComputeAlignedBufferSize(originalSize, ssboBufferMemoryAlignment);
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
@ -499,6 +511,11 @@ namespace SHADE
|
|||
|
||||
}
|
||||
|
||||
Handle<SHVkSampler> SHVkLogicalDevice::CreateSampler(const SHVkSamplerParams& params) noexcept
|
||||
{
|
||||
return SHVkInstance::GetResourceManager().Create <SHVkSampler>(GetHandle(), params);
|
||||
}
|
||||
|
||||
Handle<SHVkRenderpass> SHVkLogicalDevice::CreateRenderpass(std::span<vk::AttachmentDescription> const vkDescriptions, std::vector<SHVkSubpassParams> const& subpasses) noexcept
|
||||
{
|
||||
return SHVkInstance::GetResourceManager().Create <SHVkRenderpass>(GetHandle(), vkDescriptions, subpasses);
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
#include "Graphics/Descriptors/SHVkDescriptorSetLayout.h"
|
||||
#include "Graphics/Images/SHVkImage.h"
|
||||
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
@ -41,6 +40,8 @@ namespace SHADE
|
|||
class SHShaderBlockInterface;
|
||||
class SHVkDescriptorSetGroup;
|
||||
class SHSubpass;
|
||||
class SHVkSampler;
|
||||
struct SHVkSamplerParams;
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
@ -102,6 +103,7 @@ namespace SHADE
|
|||
/*-----------------------------------------------------------------------*/
|
||||
void InitializeVMA (void) noexcept;
|
||||
void InitializeQueues (std::initializer_list<SHQueueParams> queueCreateParams) noexcept;
|
||||
uint32_t ComputeAlignedBufferSize(uint32_t originalSize, size_t typeSize) const noexcept;
|
||||
|
||||
public:
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
@ -121,7 +123,8 @@ namespace SHADE
|
|||
// Miscellaneous functions
|
||||
void WaitIdle (void) noexcept;
|
||||
uint32_t FindMemoryType (uint32_t typeFilter, vk::MemoryPropertyFlags properties);
|
||||
uint32_t PadUBOSize (uint32_t originalSize) const noexcept;
|
||||
uint32_t PadUBOSize(uint32_t originalSize) const noexcept;
|
||||
uint32_t PadSSBOSize(uint32_t originalSize) const noexcept;
|
||||
|
||||
// creation functions
|
||||
Handle<SHVkSurface> CreateSurface (HWND const& windowHandle) const noexcept;
|
||||
|
@ -178,6 +181,7 @@ namespace SHADE
|
|||
Handle<SHVkRenderpass> const& renderpassHdl,
|
||||
Handle<SHSubpass> subpass
|
||||
) 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::span<vk::SubpassDescription> const spDescs, std::span<vk::SubpassDependency> const spDeps) noexcept;
|
||||
|
|
|
@ -26,7 +26,7 @@ namespace SHADE
|
|||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
void SHVkImage::PrepStagingBuffer(void* data, uint32_t srcSize) noexcept
|
||||
void SHVkImage::PrepStagingBuffer(const void* data, uint32_t srcSize) noexcept
|
||||
{
|
||||
// For creation of buffer
|
||||
vk::BufferCreateInfo bufferInfo{};
|
||||
|
@ -70,7 +70,7 @@ namespace SHADE
|
|||
vmaMapMemory(*vmaAllocator, stagingAlloc, &stagingBufferMappedPtr);
|
||||
|
||||
if (stagingBufferMappedPtr)
|
||||
std::memcpy(static_cast<uint8_t*>(stagingBufferMappedPtr), static_cast<uint8_t*>(data), srcSize);
|
||||
std::memcpy(static_cast<uint8_t*>(stagingBufferMappedPtr), static_cast<const uint8_t*>(data), srcSize);
|
||||
|
||||
const VkDeviceSize offsets = 0;
|
||||
const VkDeviceSize sizes = srcSize;
|
||||
|
@ -82,7 +82,7 @@ namespace SHADE
|
|||
SHVkImage::SHVkImage(
|
||||
VmaAllocator const* allocator,
|
||||
SHImageCreateParams const& imageDetails,
|
||||
unsigned char* data,
|
||||
const unsigned char* data,
|
||||
uint32_t dataSize,
|
||||
std::span<uint32_t> inMipOffsets,
|
||||
VmaMemoryUsage memUsage,
|
||||
|
|
|
@ -107,7 +107,7 @@ namespace SHADE
|
|||
/*-----------------------------------------------------------------------*/
|
||||
/* PRIVATE MEMBER FUNCTIONS */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
void PrepStagingBuffer(void* data, uint32_t srcSize) noexcept;
|
||||
void PrepStagingBuffer(const void* data, uint32_t srcSize) noexcept;
|
||||
|
||||
|
||||
public:
|
||||
|
@ -119,7 +119,7 @@ namespace SHADE
|
|||
SHVkImage(
|
||||
VmaAllocator const* allocator,
|
||||
SHImageCreateParams const& imageDetails,
|
||||
unsigned char* data,
|
||||
const unsigned char* data,
|
||||
uint32_t dataSize,
|
||||
std::span<uint32_t> inMipOffsets,
|
||||
VmaMemoryUsage memUsage,
|
||||
|
|
|
@ -1,12 +1,62 @@
|
|||
/************************************************************************************//*!
|
||||
\file SHVkSampler.cpp
|
||||
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||
\par email: kahwei.tng\@digipen.edu
|
||||
\date Sep 26, 2022
|
||||
\brief Contains definitions for all of the functions of the SHVkSampler class.
|
||||
|
||||
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 "SHVkSampler.h"
|
||||
|
||||
#include "Graphics/Devices/SHVkLogicalDevice.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
||||
vk::Sampler SHVkSampler::GetVkSampler(void) const noexcept
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Constructors */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
SHVkSampler::SHVkSampler(Handle<SHVkLogicalDevice> logicalDevice, const SHVkSamplerParams& params) noexcept
|
||||
: device { logicalDevice }
|
||||
{
|
||||
return vkSampler;
|
||||
const vk::SamplerCreateInfo SAMPLER_CREATE_INFO
|
||||
{
|
||||
.magFilter = params.magFilter,
|
||||
.minFilter = params.minFilter,
|
||||
.mipmapMode = params.mipmapMode,
|
||||
.addressModeU = params.addressMode,
|
||||
.addressModeV = params.addressMode,
|
||||
.addressModeW = params.addressMode,
|
||||
.minLod = params.minLod,
|
||||
.maxLod = params.maxLod
|
||||
};
|
||||
|
||||
// Create the sampler
|
||||
vkSampler = device->GetVkLogicalDevice().createSampler(SAMPLER_CREATE_INFO);
|
||||
}
|
||||
|
||||
SHVkSampler::SHVkSampler(SHVkSampler&& rhs) noexcept
|
||||
: vkSampler { rhs.vkSampler }
|
||||
{
|
||||
rhs.vkSampler = nullptr;
|
||||
}
|
||||
|
||||
SHVkSampler::~SHVkSampler() noexcept
|
||||
{
|
||||
if (vkSampler)
|
||||
device->GetVkLogicalDevice().destroySampler();
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Overloaded Operators */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
SHADE::SHVkSampler& SHVkSampler::operator=(SHVkSampler&& rhs) noexcept
|
||||
{
|
||||
vkSampler = rhs.vkSampler;
|
||||
rhs.vkSampler = nullptr;
|
||||
return *this;
|
||||
}
|
||||
}
|
|
@ -1,28 +1,80 @@
|
|||
/************************************************************************************//*!
|
||||
\file SHVkSampler.h
|
||||
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||
\par email: kahwei.tng\@digipen.edu
|
||||
\date Sep 26, 2022
|
||||
\brief Contains definitions of the SHVkSampler class.
|
||||
|
||||
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
|
||||
|
||||
// STL Includes
|
||||
#include <vector>
|
||||
// Project Includes
|
||||
#include "Graphics/SHVulkanIncludes.h"
|
||||
#include "Resource/Handle.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Forward Declarations */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
class SHVkLogicalDevice;
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Type Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/*************************************************************************************/
|
||||
/*!
|
||||
\brief
|
||||
Holds parameters for constructing the SHVkSampler.
|
||||
*/
|
||||
/*************************************************************************************/
|
||||
struct SHVkSamplerParams
|
||||
{
|
||||
vk::Filter minFilter;
|
||||
vk::Filter maxFilter;
|
||||
//vk::Filter maxFilter;
|
||||
vk::Filter minFilter = vk::Filter::eLinear;
|
||||
vk::Filter magFilter = vk::Filter::eLinear;
|
||||
vk::SamplerAddressMode addressMode = vk::SamplerAddressMode::eClampToEdge;
|
||||
vk::SamplerMipmapMode mipmapMode = vk::SamplerMipmapMode::eLinear;
|
||||
float minLod = 0;
|
||||
float maxLod = 0;
|
||||
};
|
||||
|
||||
/*************************************************************************************/
|
||||
/*!
|
||||
\brief
|
||||
Wrapper for a VkSampler.
|
||||
*/
|
||||
/*************************************************************************************/
|
||||
class SHVkSampler
|
||||
{
|
||||
private:
|
||||
//! The vulkan sampler handler
|
||||
vk::Sampler vkSampler;
|
||||
public:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Constructors */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
SHVkSampler(Handle<SHVkLogicalDevice> logicalDevice, const SHVkSamplerParams& params = {}) noexcept;
|
||||
SHVkSampler(SHVkSampler&& rhs) noexcept;
|
||||
~SHVkSampler() noexcept;
|
||||
|
||||
public:
|
||||
SHVkSampler () noexcept;
|
||||
SHVkSampler (SHVkSampler&& rhs) noexcept;
|
||||
SHVkSampler&& operator=(SHVkSampler&& rhs) noexcept;
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Overloaded Operators */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
SHVkSampler& operator=(SHVkSampler&& rhs) noexcept;
|
||||
|
||||
vk::Sampler GetVkSampler (void) const noexcept;
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Getter Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
vk::Sampler GetVkSampler(void) const noexcept { return vkSampler; }
|
||||
|
||||
private:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Data Members */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
vk::Sampler vkSampler; //! The Vulkan sampler handler
|
||||
Handle<SHVkLogicalDevice> device; //! Stored device for deallocating the object
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -22,8 +22,11 @@ of DigiPen Institute of Technology is prohibited.
|
|||
#include "Graphics/Pipeline/SHVkPipeline.h"
|
||||
#include "Graphics/MiddleEnd/Interface/SHGraphicsConstants.h"
|
||||
#include "Graphics/MiddleEnd/Interface/SHMaterialInstance.h"
|
||||
#include "Graphics/Descriptors/SHVkDescriptorSetGroup.h"
|
||||
#include "ECS_Base/Managers/SHComponentManager.h"
|
||||
#include "Math/Transform/SHTransformComponent.h"
|
||||
#include "Graphics/MiddleEnd/GlobalData/SHGraphicsGlobalData.h"
|
||||
#include "Graphics/Descriptors/SHVkDescriptorPool.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
@ -120,7 +123,7 @@ namespace SHADE
|
|||
}
|
||||
}
|
||||
|
||||
void SHBatch::UpdateMaterialBuffer(uint32_t frameIndex)
|
||||
void SHBatch::UpdateMaterialBuffer(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool)
|
||||
{
|
||||
if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS)
|
||||
{
|
||||
|
@ -154,21 +157,17 @@ namespace SHADE
|
|||
if (!matBufferDirty[frameIndex])
|
||||
return;
|
||||
|
||||
// Build CPI Buffer
|
||||
// Build CPU Buffer
|
||||
char* propsCurrPtr = matPropsData.get();
|
||||
for (auto& subBatch : subBatches)
|
||||
for (const SHRenderable* renderable : subBatch.Renderables)
|
||||
{
|
||||
renderable->GetMaterial()->ExportProperties(propsCurrPtr);
|
||||
propsCurrPtr += singleMatPropSize;
|
||||
propsCurrPtr += singleMatPropAlignedSize;
|
||||
}
|
||||
|
||||
// Transfer to GPU
|
||||
SHVkUtil::EnsureBufferAndCopyHostVisibleData
|
||||
(
|
||||
device, matPropsBuffer[frameIndex], matPropsData.get(), static_cast<uint32_t>(matPropsDataSize),
|
||||
vk::BufferUsageFlagBits::eStorageBuffer
|
||||
);
|
||||
rebuildMaterialBuffers(frameIndex, descPool);
|
||||
|
||||
// This frame is updated
|
||||
matBufferDirty[frameIndex] = false;
|
||||
|
@ -207,7 +206,7 @@ namespace SHADE
|
|||
transformDataBuffer[frameIndex]->WriteToMemory(transformData.data(), static_cast<uint32_t>(transformData.size() * sizeof(SHMatrix)), 0, 0);
|
||||
}
|
||||
|
||||
void SHBatch::Build(Handle<SHVkLogicalDevice> _device, uint32_t frameIndex)
|
||||
void SHBatch::Build(Handle<SHVkLogicalDevice> _device, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex)
|
||||
{
|
||||
if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS)
|
||||
{
|
||||
|
@ -215,6 +214,9 @@ namespace SHADE
|
|||
return;
|
||||
}
|
||||
|
||||
// Save logical device
|
||||
device = _device;
|
||||
|
||||
// No need to build as there are no changes
|
||||
if (!isDirty[frameIndex])
|
||||
return;
|
||||
|
@ -247,7 +249,8 @@ namespace SHADE
|
|||
if (!EMPTY_MAT_PROPS)
|
||||
{
|
||||
singleMatPropSize = SHADER_INFO->GetBytesRequired();
|
||||
matPropTotalBytes = drawData.size() * singleMatPropSize;
|
||||
singleMatPropAlignedSize = device->PadSSBOSize(singleMatPropSize);
|
||||
matPropTotalBytes = numTotalElements * singleMatPropAlignedSize;
|
||||
if (matPropsDataSize < matPropTotalBytes)
|
||||
{
|
||||
matPropsData.reset(new char[matPropTotalBytes]);
|
||||
|
@ -267,7 +270,7 @@ namespace SHADE
|
|||
.instanceCount = static_cast<uint32_t>(subBatch.Renderables.size()),
|
||||
.firstIndex = subBatch.Mesh->FirstIndex,
|
||||
.vertexOffset = subBatch.Mesh->FirstVertex,
|
||||
.firstInstance = nextInstanceIndex
|
||||
.firstInstance = nextInstanceIndex++
|
||||
});
|
||||
|
||||
// Fill in buffers (CPU)
|
||||
|
@ -289,7 +292,7 @@ namespace SHADE
|
|||
if (!EMPTY_MAT_PROPS)
|
||||
{
|
||||
renderable->GetMaterial()->ExportProperties(propsCurrPtr);
|
||||
propsCurrPtr += singleMatPropSize;
|
||||
propsCurrPtr += singleMatPropAlignedSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -304,30 +307,21 @@ namespace SHADE
|
|||
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,
|
||||
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,
|
||||
device, transformDataBuffer[frameIndex], transformData.data(), TF_DATA_BYTES,
|
||||
BuffUsage::eVertexBuffer
|
||||
);
|
||||
// - Material Properties Buffer
|
||||
if (matPropsData)
|
||||
{
|
||||
SHVkUtil::EnsureBufferAndCopyHostVisibleData
|
||||
(
|
||||
_device, matPropsBuffer[frameIndex], matPropsData.get(), static_cast<uint32_t>(matPropsDataSize),
|
||||
BuffUsage::eStorageBuffer
|
||||
);
|
||||
}
|
||||
rebuildMaterialBuffers(frameIndex, descPool);
|
||||
|
||||
// Mark this frame as no longer dirty
|
||||
isDirty[frameIndex] = false;
|
||||
|
||||
// Save logical device
|
||||
this->device = _device;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
@ -341,8 +335,20 @@ namespace SHADE
|
|||
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);
|
||||
if (matPropsDescSet[frameIndex])
|
||||
{
|
||||
cmdBuffer->BindDescriptorSet
|
||||
(
|
||||
matPropsDescSet[frameIndex],
|
||||
vk::PipelineBindPoint::eGraphics,
|
||||
SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE,
|
||||
dynamicOffset
|
||||
);
|
||||
}
|
||||
cmdBuffer->DrawMultiIndirect(drawDataBuffer[frameIndex], static_cast<uint32_t>(drawData.size()));
|
||||
}
|
||||
|
||||
|
@ -355,4 +361,39 @@ namespace SHADE
|
|||
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, matPropsDataSize
|
||||
);
|
||||
matPropsDescSet[frameIndex]->UpdateDescriptorSetBuffer
|
||||
(
|
||||
SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE,
|
||||
SHGraphicsConstants::DescriptorSetBindings::BATCHED_PER_INST_DATA
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -35,6 +35,8 @@ namespace SHADE
|
|||
class SHRenderable;
|
||||
class SHVkLogicalDevice;
|
||||
class SHMaterialInstance;
|
||||
class SHVkDescriptorSetGroup;
|
||||
class SHVkDescriptorPool;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Type Definitions */
|
||||
|
@ -74,9 +76,9 @@ namespace SHADE
|
|||
void Add(const SHRenderable* renderable);
|
||||
void Remove(const SHRenderable* renderable);
|
||||
void Clear();
|
||||
void UpdateMaterialBuffer(uint32_t frameIndex);
|
||||
void UpdateMaterialBuffer(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool);
|
||||
void UpdateTransformBuffer(uint32_t frameIndex);
|
||||
void Build(Handle<SHVkLogicalDevice> device, uint32_t frameIndex);
|
||||
void Build(Handle<SHVkLogicalDevice> device, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) ;
|
||||
void Draw(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex);
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
|
@ -84,34 +86,44 @@ namespace SHADE
|
|||
/*-----------------------------------------------------------------------------*/
|
||||
Handle<SHVkPipeline> GetPipeline() const noexcept { return pipeline; };
|
||||
|
||||
private:
|
||||
private:
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Type Definition */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
using TripleBool = std::array<bool, SHGraphicsConstants::NUM_FRAME_BUFFERS>;
|
||||
using TripleBuffer = std::array<Handle<SHVkBuffer>, SHGraphicsConstants::NUM_FRAME_BUFFERS>;
|
||||
using TripleDescSet = std::array<Handle<SHVkDescriptorSetGroup>, SHGraphicsConstants::NUM_FRAME_BUFFERS>;
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Data Members */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
// Resources
|
||||
Handle<SHVkLogicalDevice> device;
|
||||
Handle<SHVkLogicalDevice> device;
|
||||
// Batch Properties
|
||||
Handle<SHVkPipeline> pipeline;
|
||||
Handle<SHVkPipeline> pipeline;
|
||||
std::unordered_set<Handle<SHMaterialInstance>> referencedMatInstances;
|
||||
std::array<bool, SHGraphicsConstants::NUM_FRAME_BUFFERS> matBufferDirty;
|
||||
TripleBool matBufferDirty;
|
||||
// Batch Tree
|
||||
std::vector<SHSubBatch> subBatches;
|
||||
std::array<bool, SHGraphicsConstants::NUM_FRAME_BUFFERS> isDirty;
|
||||
std::vector<SHSubBatch> subBatches;
|
||||
TripleBool isDirty;
|
||||
// CPU Buffers
|
||||
std::vector<vk::DrawIndexedIndirectCommand> drawData;
|
||||
std::vector<SHMatrix> transformData;
|
||||
std::unique_ptr<char> matPropsData;
|
||||
Byte matPropsDataSize = 0;
|
||||
Byte singleMatPropSize = 0;
|
||||
bool isCPUBuffersDirty = true;
|
||||
std::vector<vk::DrawIndexedIndirectCommand> drawData;
|
||||
std::vector<SHMatrix> transformData;
|
||||
std::unique_ptr<char> matPropsData;
|
||||
Byte matPropsDataSize = 0;
|
||||
Byte singleMatPropAlignedSize = 0;
|
||||
Byte singleMatPropSize = 0;
|
||||
bool isCPUBuffersDirty = true;
|
||||
// GPU Buffers
|
||||
std::array<Handle<SHVkBuffer>, SHGraphicsConstants::NUM_FRAME_BUFFERS> drawDataBuffer;
|
||||
std::array<Handle<SHVkBuffer>, SHGraphicsConstants::NUM_FRAME_BUFFERS> transformDataBuffer;
|
||||
std::array<Handle<SHVkBuffer>, SHGraphicsConstants::NUM_FRAME_BUFFERS> matPropsBuffer;
|
||||
TripleBuffer drawDataBuffer;
|
||||
TripleBuffer transformDataBuffer;
|
||||
TripleBuffer matPropsBuffer;
|
||||
TripleDescSet matPropsDescSet;
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Helper Functions */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
void setAllDirtyFlags();
|
||||
void rebuildMaterialBuffers(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -91,12 +91,12 @@ namespace SHADE
|
|||
(*superBatch)->Remove(renderable);
|
||||
}
|
||||
|
||||
void SHBatcher::FinaliseBatches(Handle<SHVkLogicalDevice> device, uint32_t frameIndex)
|
||||
void SHBatcher::FinaliseBatches(Handle<SHVkLogicalDevice> device, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex)
|
||||
{
|
||||
// Build SuperBatches
|
||||
for (auto& batch : superBatches)
|
||||
{
|
||||
batch->Build(device, frameIndex);
|
||||
batch->Build(device, descPool, frameIndex);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -109,11 +109,11 @@ namespace SHADE
|
|||
superBatches.clear();
|
||||
}
|
||||
|
||||
void SHBatcher::UpdateBuffers(uint32_t frameIndex)
|
||||
void SHBatcher::UpdateBuffers(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool)
|
||||
{
|
||||
for (auto& batch : superBatches)
|
||||
{
|
||||
batch->UpdateBuffers(frameIndex);
|
||||
batch->UpdateBuffers(frameIndex, descPool);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@ namespace SHADE
|
|||
class SHSuperBatch;
|
||||
class SHVkLogicalDevice;
|
||||
class SHVkCommandBuffer;
|
||||
class SHVkDescriptorPool;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Type Definitions */
|
||||
|
@ -51,9 +52,9 @@ namespace SHADE
|
|||
void PrepareBatches();
|
||||
void AddToBatch(SHRenderable const* renderable);
|
||||
void RemoveFromBatch(SHRenderable const* renderable);
|
||||
void FinaliseBatches(Handle<SHVkLogicalDevice> device, uint32_t frameIndex);
|
||||
void FinaliseBatches(Handle<SHVkLogicalDevice> device, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex);
|
||||
void ClearBatches();
|
||||
void UpdateBuffers(uint32_t frameIndex);
|
||||
void UpdateBuffers(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool);
|
||||
void RegisterSuperBatch(Handle<SHSuperBatch> superBatch);
|
||||
void DeregisterSuperBatch(Handle<SHSuperBatch> superBatch);
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ of DigiPen Institute of Technology is prohibited.
|
|||
#include "SHBatch.h"
|
||||
#include "Graphics/MiddleEnd/Interface/SHMaterialInstance.h"
|
||||
#include "Graphics/MiddleEnd/Interface/SHRenderable.h"
|
||||
#include "Graphics/Descriptors/SHVkDescriptorPool.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
@ -78,21 +79,21 @@ namespace SHADE
|
|||
batches.clear();
|
||||
}
|
||||
|
||||
void SHSuperBatch::UpdateBuffers(uint32_t frameIndex)
|
||||
void SHSuperBatch::UpdateBuffers(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool)
|
||||
{
|
||||
for (auto& batch : batches)
|
||||
{
|
||||
batch.UpdateMaterialBuffer(frameIndex);
|
||||
batch.UpdateMaterialBuffer(frameIndex, descPool);
|
||||
batch.UpdateTransformBuffer(frameIndex);
|
||||
}
|
||||
}
|
||||
|
||||
void SHSuperBatch::Build(Handle<SHVkLogicalDevice> device, uint32_t frameIndex) noexcept
|
||||
void SHSuperBatch::Build(Handle<SHVkLogicalDevice> device, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) noexcept
|
||||
{
|
||||
// Build all batches
|
||||
for (auto& batch : batches)
|
||||
{
|
||||
batch.Build(device, frameIndex);
|
||||
batch.Build(device, descPool, frameIndex);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -55,8 +55,8 @@ namespace SHADE
|
|||
void Add(const SHRenderable* renderable) noexcept;
|
||||
void Remove(const SHRenderable* renderable) noexcept;
|
||||
void Clear() noexcept;
|
||||
void UpdateBuffers(uint32_t frameIndex);
|
||||
void Build(Handle<SHVkLogicalDevice> device, uint32_t frameIndex) noexcept;
|
||||
void UpdateBuffers(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool);
|
||||
void Build(Handle<SHVkLogicalDevice> device, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) noexcept;
|
||||
void Draw(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept;
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
|
|
|
@ -7,7 +7,22 @@
|
|||
|
||||
namespace SHADE
|
||||
{
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Static Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
std::vector<Handle<SHVkDescriptorSetLayout>> SHGraphicsGlobalData::globalDescSetLayouts;
|
||||
Handle<SHVkDescriptorSetGroup> SHGraphicsGlobalData::globalDescSets;
|
||||
SHVertexInputState SHGraphicsGlobalData::defaultVertexInputState;
|
||||
Handle<SHVkPipelineLayout> SHGraphicsGlobalData::dummyPipelineLayout;
|
||||
|
||||
void SHGraphicsGlobalData::InitHighFrequencyGlobalData(void) noexcept
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Function Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
void SHGraphicsGlobalData::InitDescSetLayouts(Handle<SHVkLogicalDevice> logicalDevice) noexcept
|
||||
{
|
||||
SHVkDescriptorSetLayout::Binding genericDataBinding
|
||||
|
@ -87,18 +102,18 @@ namespace SHADE
|
|||
InitDefaultVertexInputState();
|
||||
}
|
||||
|
||||
std::vector<Handle<SHVkDescriptorSetLayout>> const& SHGraphicsGlobalData::GetDescSetLayouts(void) const noexcept
|
||||
std::vector<Handle<SHVkDescriptorSetLayout>> const& SHGraphicsGlobalData::GetDescSetLayouts(void) noexcept
|
||||
{
|
||||
return globalDescSetLayouts;
|
||||
}
|
||||
|
||||
|
||||
SHVertexInputState const& SHGraphicsGlobalData::GetDefaultViState(void) const noexcept
|
||||
SHVertexInputState const& SHGraphicsGlobalData::GetDefaultViState(void) noexcept
|
||||
{
|
||||
return defaultVertexInputState;
|
||||
}
|
||||
|
||||
Handle<SHVkPipelineLayout> SHGraphicsGlobalData::GetDummyPipelineLayout(void) const noexcept
|
||||
Handle<SHVkPipelineLayout> SHGraphicsGlobalData::GetDummyPipelineLayout(void) noexcept
|
||||
{
|
||||
return dummyPipelineLayout;
|
||||
}
|
||||
|
|
|
@ -15,31 +15,38 @@ namespace SHADE
|
|||
{
|
||||
private:
|
||||
//! Global descriptor set layouts. Used to allocate descriptor sets
|
||||
std::vector<Handle<SHVkDescriptorSetLayout>> globalDescSetLayouts;
|
||||
static std::vector<Handle<SHVkDescriptorSetLayout>> globalDescSetLayouts;
|
||||
|
||||
//! Global Descriptor sets
|
||||
Handle<SHVkDescriptorSetGroup> globalDescSets;
|
||||
static Handle<SHVkDescriptorSetGroup> globalDescSets;
|
||||
|
||||
//! Default vertex input state (used by everything).
|
||||
SHVertexInputState defaultVertexInputState;
|
||||
static SHVertexInputState defaultVertexInputState;
|
||||
|
||||
//! Since we want to bind global data but can't do so without a pipeline layout,
|
||||
//! we create a dummy pipeline layout to use it for binding.
|
||||
Handle<SHVkPipelineLayout> dummyPipelineLayout;
|
||||
static Handle<SHVkPipelineLayout> dummyPipelineLayout;
|
||||
|
||||
static void InitHighFrequencyGlobalData (void) noexcept;
|
||||
static void InitDescSetLayouts (Handle<SHVkLogicalDevice> logicalDevice) noexcept;
|
||||
static void InitDefaultVertexInputState (void) noexcept;
|
||||
|
||||
void InitDescSetLayouts (Handle<SHVkLogicalDevice> logicalDevice) noexcept;
|
||||
void InitDefaultVertexInputState(void) noexcept;
|
||||
public:
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* Constructors */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
SHGraphicsGlobalData() = delete;
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* PUBLIC MEMBER FUNCTIONS */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
void Init (Handle<SHVkLogicalDevice> logicalDevice) noexcept;
|
||||
static void Init (Handle<SHVkLogicalDevice> logicalDevice) noexcept;
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* SETTERS AND GETTERS */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
std::vector<Handle<SHVkDescriptorSetLayout>> const& GetDescSetLayouts (void) const noexcept;
|
||||
SHVertexInputState const& GetDefaultViState (void) const noexcept;
|
||||
Handle<SHVkPipelineLayout> GetDummyPipelineLayout (void) const noexcept;
|
||||
static std::vector<Handle<SHVkDescriptorSetLayout>> const& GetDescSetLayouts (void) noexcept;
|
||||
static SHVertexInputState const& GetDefaultViState (void) noexcept;
|
||||
static Handle<SHVkPipelineLayout> GetDummyPipelineLayout (void) noexcept;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -23,21 +23,39 @@ namespace SHADE
|
|||
{
|
||||
SHVec3 view = target - pos; view = SHVec3::Normalise(view);
|
||||
SHVec3 right = SHVec3::Cross(view, up); right = SHVec3::Normalise(right);
|
||||
const SHVec3 UP = SHVec3::Cross(right, view);
|
||||
const SHVec3 UP = SHVec3::Cross(view, right);
|
||||
|
||||
//viewMatrix = SHMatrix::Identity;
|
||||
//viewMatrix(0, 0) = UP[0];
|
||||
//viewMatrix(1, 0) = UP[1];
|
||||
//viewMatrix(2, 0) = UP[2];
|
||||
//viewMatrix(0, 1) = right[0];
|
||||
//viewMatrix(1, 1) = right[1];
|
||||
//viewMatrix(2, 1) = right[2];
|
||||
//viewMatrix(0, 2) = view[0];
|
||||
//viewMatrix(1, 2) = view[1];
|
||||
//viewMatrix(2, 2) = view[2];
|
||||
//viewMatrix(3, 0) = -UP.Dot(pos);
|
||||
//viewMatrix(3, 1) = -right.Dot(pos);
|
||||
//viewMatrix(3, 2) = -view.Dot(pos);
|
||||
|
||||
viewMatrix = SHMatrix::Identity;
|
||||
viewMatrix(0, 0) = UP[0];
|
||||
viewMatrix(1, 0) = UP[1];
|
||||
viewMatrix(2, 0) = UP[2];
|
||||
viewMatrix(0, 1) = right[0];
|
||||
viewMatrix(1, 1) = right[1];
|
||||
viewMatrix(2, 1) = right[2];
|
||||
viewMatrix(0, 2) = view[0];
|
||||
viewMatrix(1, 2) = view[1];
|
||||
viewMatrix(2, 2) = view[2];
|
||||
viewMatrix(3, 0) = -UP.Dot(pos);
|
||||
viewMatrix(3, 1) = -right.Dot(pos);
|
||||
viewMatrix(3, 2) = -view.Dot(pos);
|
||||
viewMatrix(0, 0) = right[0];
|
||||
viewMatrix(0, 1) = right[1];
|
||||
viewMatrix(0, 2) = right[2];
|
||||
|
||||
viewMatrix(1, 0) = UP[0];
|
||||
viewMatrix(1, 1) = UP[1];
|
||||
viewMatrix(1, 2) = UP[2];
|
||||
|
||||
viewMatrix(2, 0) = view[0];
|
||||
viewMatrix(2, 1) = view[1];
|
||||
viewMatrix(2, 2) = view[2];
|
||||
|
||||
viewMatrix(0, 3) = -right.Dot(pos);
|
||||
viewMatrix(1, 3) = -UP.Dot(pos);
|
||||
viewMatrix(2, 3) = -view.Dot(pos);
|
||||
|
||||
|
||||
isDirty = true;
|
||||
}
|
||||
|
|
|
@ -30,6 +30,8 @@ of DigiPen Institute of Technology is prohibited.
|
|||
#include "SHGraphicsConstants.h"
|
||||
#include "Graphics/MiddleEnd/GlobalData/SHGraphicsGlobalData.h"
|
||||
#include "Graphics/Buffers/SHVkBuffer.h"
|
||||
#include "Graphics/Images/SHVkSampler.h"
|
||||
#include "Assets/Asset Types/SHTextureAsset.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
@ -91,8 +93,10 @@ namespace SHADE
|
|||
descPool = device->CreateDescriptorPools();
|
||||
|
||||
// Create generic command buffer
|
||||
transferCmdPool = device->CreateCommandPool(SH_QUEUE_FAMILY_ARRAY_INDEX::TRANSFER, SH_CMD_POOL_RESET::POOL_BASED, true);
|
||||
transferCmdBuffer = transferCmdPool->RequestCommandBuffer(SH_CMD_BUFFER_TYPE::PRIMARY);
|
||||
//transferCmdPool = 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);
|
||||
graphicsTexCmdBuffer = graphicsCmdPool->RequestCommandBuffer(SH_CMD_BUFFER_TYPE::PRIMARY);
|
||||
|
||||
|
||||
|
||||
|
@ -106,8 +110,7 @@ namespace SHADE
|
|||
- Global data
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
globalData = resourceManager.Create<SHGraphicsGlobalData>();
|
||||
globalData->Init(device);
|
||||
SHGraphicsGlobalData::Init(device);
|
||||
|
||||
// Set Up Cameras
|
||||
screenCamera = resourceManager.Create<SHCamera>();
|
||||
|
@ -115,7 +118,7 @@ namespace SHADE
|
|||
screenCamera->SetOrthographic(static_cast<float>(windowDims.first), static_cast<float>(windowDims.second), 0.01f, 100.0f);
|
||||
worldCamera = resourceManager.Create<SHCamera>();
|
||||
//worldCamera->SetLookAt(SHVec3(1.0f, 0.0f, -1.0f), SHVec3(0.0f, 0.0f, 2.0f), SHVec3(0.0f, 1.0f, 0.0f));
|
||||
worldCamera->SetLookAt(SHVec3(0.0f, 5.0f, -1.0f), SHVec3(0.0f, 0.0f, 2.0f), SHVec3(0.0f, 1.0f, 0.0f));
|
||||
worldCamera->SetLookAt(SHVec3(0.0f, 0.0f, 0.0f), SHVec3(0.0f, 0.0f, -2.0f), SHVec3(0.0f, 1.0f, 0.0f));
|
||||
worldCamera->SetPerspective(90.0f, static_cast<float>(windowDims.first), static_cast<float>(windowDims.second), 0.0f, 100.0f);
|
||||
|
||||
// Create Default Viewport
|
||||
|
@ -131,18 +134,20 @@ namespace SHADE
|
|||
}
|
||||
|
||||
// Initialize world render graph
|
||||
worldRenderGraph->Init(device, swapchain, globalData);
|
||||
worldRenderGraph->Init(device, swapchain);
|
||||
worldRenderGraph->AddResource("Depth Buffer", SH_ATT_DESC_TYPE::DEPTH_STENCIL, windowDims.first, windowDims.second, vk::Format::eD32SfloatS8Uint);
|
||||
//worldRenderGraph->AddResource("Position", SH_ATT_DESC_TYPE::COLOR, windowDims.first, windowDims.second, vk::Format::eR16G16B16A16Sfloat);
|
||||
//worldRenderGraph->AddResource("Normals", SH_ATT_DESC_TYPE::COLOR, windowDims.first, windowDims.second, vk::Format::eR16G16B16A16Sfloat);
|
||||
//worldRenderGraph->AddResource("Composite", SH_ATT_DESC_TYPE::COLOR, windowDims.first, windowDims.second, vk::Format::eR16G16B16A16Sfloat);
|
||||
worldRenderGraph->AddResource("Scene", SH_ATT_DESC_TYPE::COLOR, windowDims.first, windowDims.second, vk::Format::eB8G8R8A8Unorm);
|
||||
//worldRenderGraph->AddResource("Scene", SH_ATT_DESC_TYPE::COLOR, windowDims.first, windowDims.second, vk::Format::eB8G8R8A8Unorm);
|
||||
worldRenderGraph->AddResource("Present", SH_ATT_DESC_TYPE::COLOR_PRESENT, windowDims.first, windowDims.second);
|
||||
auto node = worldRenderGraph->AddNode("G-Buffer", { /*"Composite", "Position", */"Present" }, {}); // no predecessors
|
||||
auto node = worldRenderGraph->AddNode("G-Buffer", { /*"Composite", "Position", */"Depth Buffer", "Present" }, {}); // no predecessors
|
||||
|
||||
//First subpass to write to G-Buffer
|
||||
auto gBufferWriteSubpass = node->AddSubpass("G-Buffer Write");
|
||||
//gBufferWriteSubpass->AddColorOutput("Scene");
|
||||
gBufferWriteSubpass->AddColorOutput("Present");
|
||||
gBufferWriteSubpass->AddDepthOutput ("Depth Buffer", SH_ATT_DESC_TYPE::DEPTH_STENCIL);
|
||||
//writeSubpass->AddColorOutput("Normals");
|
||||
|
||||
// //Second subpass to read from G-Buffer
|
||||
|
@ -171,7 +176,7 @@ namespace SHADE
|
|||
debugWorldRenderer->SetCamera(worldCamera);*/
|
||||
|
||||
// Add world renderer to default viewport
|
||||
worldRenderer = defaultViewport->AddRenderer(resourceManager, swapchain->GetNumImages(), renderContextCmdPools, descPool, globalData->GetDescSetLayouts()[SHGraphicsConstants::DescriptorSetIndex::HIGH_FREQUENCY_GLOBALS], worldRenderGraph);
|
||||
worldRenderer = defaultViewport->AddRenderer(resourceManager, swapchain->GetNumImages(), renderContextCmdPools, descPool, SHGraphicsGlobalData::GetDescSetLayouts()[SHGraphicsConstants::DescriptorSetIndex::HIGH_FREQUENCY_GLOBALS], worldRenderGraph);
|
||||
worldRenderer->SetCamera(worldCamera);
|
||||
|
||||
|
||||
|
@ -184,8 +189,8 @@ namespace SHADE
|
|||
shaderModuleLibrary.ImportFromSourceLibrary(device, shaderSourceLibrary);
|
||||
auto cubeVS = shaderModuleLibrary.GetShaderModule("TestCubeVs.glsl");
|
||||
auto cubeFS = shaderModuleLibrary.GetShaderModule("TestCubeFs.glsl");
|
||||
//triVS->Reflect();
|
||||
//triFS->Reflect();
|
||||
cubeVS->Reflect();
|
||||
cubeFS->Reflect();
|
||||
|
||||
defaultMaterial = AddMaterial(cubeVS, cubeFS, gBufferWriteSubpass);
|
||||
}
|
||||
|
@ -224,6 +229,9 @@ namespace SHADE
|
|||
|
||||
renderContext.ResetFence();
|
||||
|
||||
// Bind textures
|
||||
|
||||
|
||||
// For every viewport
|
||||
for (int vpIndex = 0; vpIndex < static_cast<int>(viewports.size()); ++vpIndex)
|
||||
{
|
||||
|
@ -241,7 +249,7 @@ namespace SHADE
|
|||
// Begin recording the command buffer
|
||||
currentCmdBuffer->BeginRecording();
|
||||
|
||||
currentCmdBuffer->ForceSetPipelineLayout(globalData->GetDummyPipelineLayout());
|
||||
currentCmdBuffer->ForceSetPipelineLayout(SHGraphicsGlobalData::GetDummyPipelineLayout());
|
||||
|
||||
// Bind all the buffers required for meshes
|
||||
for (auto& [buffer, bindingPoint] : MESH_DATA)
|
||||
|
@ -252,11 +260,26 @@ namespace SHADE
|
|||
currentCmdBuffer->BindIndexBuffer(buffer, 0);
|
||||
}
|
||||
|
||||
|
||||
// Bind textures
|
||||
auto textureDescSet = texLibrary.GetTextureDescriptorSetGroup();
|
||||
if (textureDescSet)
|
||||
{
|
||||
std::array<uint32_t, 1> texDynamicOffset {0};
|
||||
currentCmdBuffer->BindDescriptorSet
|
||||
(
|
||||
textureDescSet,
|
||||
vk::PipelineBindPoint::eGraphics,
|
||||
0,
|
||||
texDynamicOffset
|
||||
);
|
||||
}
|
||||
|
||||
// bind camera data
|
||||
renderers[renIndex]->UpdateDataAndBind(currentCmdBuffer, frameIndex);
|
||||
|
||||
// Draw first
|
||||
renderers[renIndex]->Draw(frameIndex);
|
||||
renderers[renIndex]->Draw(frameIndex, descPool);
|
||||
|
||||
// End the command buffer recording
|
||||
currentCmdBuffer->EndRecording();
|
||||
|
@ -309,7 +332,7 @@ namespace SHADE
|
|||
for (auto vp : viewports)
|
||||
for (auto renderer : vp->GetRenderers())
|
||||
{
|
||||
renderer->GetRenderGraph()->FinaliseBatch(renderContext.GetCurrentFrame());
|
||||
renderer->GetRenderGraph()->FinaliseBatch(renderContext.GetCurrentFrame(), descPool);
|
||||
}
|
||||
|
||||
// Resize
|
||||
|
@ -455,7 +478,35 @@ namespace SHADE
|
|||
transferCmdBuffer->BeginRecording();
|
||||
meshLibrary.BuildBuffers(device, transferCmdBuffer);
|
||||
transferCmdBuffer->EndRecording();
|
||||
transferQueue->SubmitCommandBuffer({ transferCmdBuffer });
|
||||
graphicsQueue->SubmitCommandBuffer({ transferCmdBuffer });
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Texture Registration Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
Handle<SHTexture> SHGraphicsSystem::Add(const SHTextureAsset& texAsset)
|
||||
{
|
||||
auto sampler = samplerCache.GetSampler(device, SHVkSamplerParams { .maxLod = static_cast<float>(texAsset.mipOffsets.size()) });
|
||||
return texLibrary.Add(texAsset, sampler);
|
||||
}
|
||||
|
||||
SHADE::Handle<SHADE::SHTexture> SHGraphicsSystem::Add(uint32_t pixelCount, const SHTexture::PixelChannel* const pixelData, uint32_t width, uint32_t height, SHTexture::TextureFormat format, std::vector<uint32_t> mipOffsets)
|
||||
{
|
||||
auto sampler = samplerCache.GetSampler(device, SHVkSamplerParams{ .maxLod = static_cast<float>(mipOffsets.size()) });
|
||||
return texLibrary.Add(pixelCount, pixelData, width, height, format, mipOffsets, sampler);
|
||||
}
|
||||
|
||||
void SHGraphicsSystem::Remove(Handle<SHTexture> tex)
|
||||
{
|
||||
texLibrary.Remove(tex);
|
||||
}
|
||||
|
||||
void SHGraphicsSystem::BuildTextures()
|
||||
{
|
||||
texLibrary.BuildTextures
|
||||
(
|
||||
device, graphicsTexCmdBuffer, graphicsQueue, descPool
|
||||
);
|
||||
}
|
||||
|
||||
void SHGraphicsSystem::SetWindow(SHWindow* wind) noexcept
|
||||
|
@ -493,9 +544,13 @@ namespace SHADE
|
|||
oldSuperBatch->Remove(&renderable);
|
||||
}
|
||||
|
||||
// Add to new SuperBatch
|
||||
Handle<SHSuperBatch> newSuperBatch = renderable.GetMaterial()->GetBaseMaterial()->GetPipeline()->GetPipelineState().GetSubpass()->GetSuperBatch();
|
||||
newSuperBatch->Add(&renderable);
|
||||
// Add to new SuperBatch if there is a material
|
||||
Handle<SHMaterialInstance> newMatInstance = renderable.GetMaterial();
|
||||
if (newMatInstance)
|
||||
{
|
||||
Handle<SHSuperBatch> newSuperBatch = newMatInstance->GetBaseMaterial()->GetPipeline()->GetPipelineState().GetSubpass()->GetSuperBatch();
|
||||
newSuperBatch->Add(&renderable);
|
||||
}
|
||||
|
||||
// Unset change flag
|
||||
renderable.ResetChangedFlag();
|
||||
|
|
|
@ -29,6 +29,8 @@ of DigiPen Institute of Technology is prohibited.
|
|||
#include "Graphics/MiddleEnd/Shaders/SHShaderModuleLibrary.h"
|
||||
#include "SHMeshLibrary.h"
|
||||
#include "Graphics/MiddleEnd/Materials/SHMaterialInstanceCache.h"
|
||||
#include "../Textures/SHTextureLibrary.h"
|
||||
#include "../Textures/SHVkSamplerCache.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
@ -188,6 +190,62 @@ namespace SHADE
|
|||
/***************************************************************************/
|
||||
void BuildMeshBuffers();
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Texture Registration Functions */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/*******************************************************************************/
|
||||
/*!
|
||||
|
||||
\brief
|
||||
Adds a texture to the Texture Library. But this does not mean that the
|
||||
textures have been added yet. A call to "BuildTextures()" is required to
|
||||
transfer all textures into the GPU.
|
||||
|
||||
\param pixelCount
|
||||
Number of pixels in this Mesh.
|
||||
\param positions
|
||||
Pointer to the first in a contiguous array of SHMathVec3s that define vertex
|
||||
positions.
|
||||
\param format
|
||||
Format of the texture loaded in.
|
||||
|
||||
\return
|
||||
Handle to the created Texture. This is not valid to be used until a call to
|
||||
BuildImages().
|
||||
|
||||
*/
|
||||
/*******************************************************************************/
|
||||
Handle<SHTexture> Add(const SHTextureAsset& texAsset);
|
||||
Handle<SHTexture> Add(uint32_t pixelCount, const SHTexture::PixelChannel* const pixelData, uint32_t width, uint32_t height, SHTexture::TextureFormat format, std::vector<uint32_t> mipOffsets);
|
||||
/*******************************************************************************/
|
||||
/*!
|
||||
|
||||
\brief
|
||||
Removes a mesh from the Texture Library. But this does not mean that the
|
||||
textures have been removed yet. A call to "BuildTextures()" is required to
|
||||
finalise all changes.
|
||||
|
||||
\param mesh
|
||||
Handle to the Texture to remove.
|
||||
|
||||
*/
|
||||
/*******************************************************************************/
|
||||
void Remove(Handle<SHTexture> tex);
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
\brief
|
||||
Finalises all changes to the Texture Library into the GPU buffers.
|
||||
|
||||
\param cmdBuffer
|
||||
Command buffer used to set up transfers of data in the GPU memory. This
|
||||
call must be preceded by calls to cmdBuffer's BeginRecording() and ended
|
||||
with EndRecording(). Do recall to also submit the cmdBuffer to a transfer
|
||||
queue.
|
||||
*/
|
||||
/***************************************************************************/
|
||||
void BuildTextures();
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Setters */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
|
@ -220,19 +278,20 @@ namespace SHADE
|
|||
Handle<SHVkQueue> graphicsQueue;
|
||||
Handle<SHVkQueue> transferQueue;
|
||||
Handle<SHVkDescriptorPool> descPool;
|
||||
Handle<SHVkCommandPool> graphicsCmdPool;
|
||||
Handle<SHVkCommandPool> transferCmdPool;
|
||||
Handle<SHVkCommandBuffer> transferCmdBuffer;
|
||||
Handle<SHVkCommandBuffer> graphicsTexCmdBuffer;
|
||||
SHRenderContext renderContext;
|
||||
std::array<Handle<SHVkSemaphore>, 2> graphSemaphores;
|
||||
// Not Owned Resources
|
||||
SHWindow* window = nullptr;
|
||||
|
||||
// global data (descriptor sets as well)
|
||||
Handle<SHGraphicsGlobalData> globalData;
|
||||
|
||||
// Middle End Resources
|
||||
ResourceManager resourceManager;
|
||||
SHMeshLibrary meshLibrary;
|
||||
SHTextureLibrary texLibrary;
|
||||
SHSamplerCache samplerCache;
|
||||
SHMaterialInstanceCache materialInstanceCache;
|
||||
// Viewports
|
||||
Handle<SHViewport> defaultViewport; // Whole screen
|
||||
|
|
|
@ -40,8 +40,6 @@ namespace SHADE
|
|||
|
||||
void SHMaterialInstance::ExportProperties(void* dest)
|
||||
{
|
||||
assert(dataStore != nullptr);
|
||||
|
||||
if (!baseMaterial)
|
||||
throw std::runtime_error("[SHMaterialInstance] Attempted to set export a Material Instance with no base Material!");
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ of DigiPen Institute of Technology is prohibited.
|
|||
// Project Includes
|
||||
#include "Resource/Handle.h"
|
||||
#include "Graphics/Shaders/BlockInterface/SHShaderBlockInterface.h"
|
||||
#include "SH_API.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
@ -34,7 +35,7 @@ namespace SHADE
|
|||
a SHRenderable.
|
||||
*/
|
||||
/***********************************************************************************/
|
||||
class SHMaterialInstance
|
||||
class SH_API SHMaterialInstance
|
||||
{
|
||||
public:
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
|
|
|
@ -48,7 +48,7 @@ namespace SHADE
|
|||
}
|
||||
|
||||
// Get offset and modify the memory directly
|
||||
T* dataPtr = dataStore.get() + od.StoredDataOffset;
|
||||
T* dataPtr = reinterpret_cast<T*>(dataStore.get() + od.StoredDataOffset);
|
||||
*dataPtr = value;
|
||||
|
||||
// Save the override data information
|
||||
|
|
|
@ -81,7 +81,7 @@ namespace SHADE
|
|||
if (!material)
|
||||
{
|
||||
SHGraphicsSystem* gfxSystem = SHSystemManager::GetSystem<SHGraphicsSystem>();
|
||||
material = gfxSystem->AddOrGetBaseMaterialInstance(sharedMaterial->GetBaseMaterial());
|
||||
material = gfxSystem->AddMaterialInstanceCopy(sharedMaterial);
|
||||
}
|
||||
|
||||
return material;
|
||||
|
|
|
@ -60,9 +60,9 @@ namespace SHADE
|
|||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Drawing Functions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
void SHRenderer::Draw(uint32_t frameIndex) noexcept
|
||||
void SHRenderer::Draw(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool) noexcept
|
||||
{
|
||||
renderGraph->Execute(frameIndex, commandBuffers[frameIndex]);
|
||||
renderGraph->Execute(frameIndex, commandBuffers[frameIndex], descPool);
|
||||
}
|
||||
|
||||
void SHRenderer::UpdateDataAndBind(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept
|
||||
|
|
|
@ -74,7 +74,7 @@ namespace SHADE
|
|||
/*-----------------------------------------------------------------------------*/
|
||||
/* Drawing Functions */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
void Draw(uint32_t frameIndex) noexcept;
|
||||
void Draw(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool) noexcept;
|
||||
void UpdateDataAndBind (Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept;
|
||||
void UpdateCameraDataToBuffer (void) noexcept;
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ namespace SHADE
|
|||
SHPipelineLayoutParams params
|
||||
{
|
||||
.shaderModules = {vsFsPair.first, vsFsPair.second},
|
||||
.globalDescSetLayouts = globalData->GetDescSetLayouts()
|
||||
.globalDescSetLayouts = SHGraphicsGlobalData::GetDescSetLayouts()
|
||||
};
|
||||
|
||||
// Create the pipeline layout
|
||||
|
@ -19,7 +19,7 @@ namespace SHADE
|
|||
|
||||
// Create the pipeline and configure the default vertex input state
|
||||
auto newPipeline = logicalDevice->CreateGraphicsPipeline(pipelineLayout, nullptr, renderpass, subpass);
|
||||
newPipeline->GetPipelineState().SetVertexInputState(globalData->GetDefaultViState());
|
||||
newPipeline->GetPipelineState().SetVertexInputState(SHGraphicsGlobalData::GetDefaultViState());
|
||||
|
||||
// Actually construct the pipeline
|
||||
newPipeline->ConstructPipeline();
|
||||
|
@ -30,10 +30,9 @@ namespace SHADE
|
|||
return newPipeline;
|
||||
}
|
||||
|
||||
void SHPipelineLibrary::Init(Handle<SHVkLogicalDevice> device, Handle<SHGraphicsGlobalData> inGlobalData) noexcept
|
||||
void SHPipelineLibrary::Init(Handle<SHVkLogicalDevice> device) noexcept
|
||||
{
|
||||
logicalDevice = device;
|
||||
globalData = inGlobalData;
|
||||
}
|
||||
|
||||
Handle<SHVkPipeline> SHPipelineLibrary::GetDrawPipline(std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair) noexcept
|
||||
|
|
|
@ -25,13 +25,8 @@ namespace SHADE
|
|||
//! 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;
|
||||
|
||||
// Global data
|
||||
Handle<SHGraphicsGlobalData> globalData;
|
||||
|
||||
|
||||
|
||||
public:
|
||||
void Init (Handle<SHVkLogicalDevice> device, Handle<SHGraphicsGlobalData> inGlobalData) noexcept;
|
||||
void Init (Handle<SHVkLogicalDevice> device) noexcept;
|
||||
|
||||
// Draw pipeline functions. used only when creating pipelines for drawing using a vertex and fragment shader
|
||||
Handle<SHVkPipeline> CreateDrawPipeline (
|
||||
|
|
|
@ -20,18 +20,36 @@ of DigiPen Institute of Technology is prohibited.
|
|||
#include "Graphics/Commands/SHVkCommandBuffer.h"
|
||||
#include "Graphics/SHVkUtil.h"
|
||||
#include "Tools/SHLogger.h"
|
||||
#include "Graphics/MiddleEnd/Interface/SHGraphicsConstants.h"
|
||||
#include "Graphics/Descriptors/SHVkDescriptorSetGroup.h"
|
||||
#include "Graphics/Images/SHVkImage.h"
|
||||
#include "Graphics/MiddleEnd/GlobalData/SHGraphicsGlobalData.h"
|
||||
#include "Assets/Asset Types/SHTextureAsset.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Usage Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
Handle<SHTexture> SHTextureLibrary::Add(uint32_t pixelCount, const SHTexture::PixelChannel* const pixelData, SHTexture::TextureFormat format, uint32_t mipLevels)
|
||||
Handle<SHTexture> SHTextureLibrary::Add(const SHTextureAsset& texAsset, Handle<SHVkSampler> sampler)
|
||||
{
|
||||
return Add
|
||||
(
|
||||
texAsset.numBytes,
|
||||
texAsset.pixelData,
|
||||
texAsset.width, texAsset.height,
|
||||
texAsset.format,
|
||||
texAsset.mipOffsets,
|
||||
sampler
|
||||
);
|
||||
}
|
||||
|
||||
Handle<SHTexture> SHTextureLibrary::Add(uint32_t pixelCount, const SHTexture::PixelChannel* const pixelData, uint32_t width, uint32_t height, SHTexture::TextureFormat format, std::vector<uint32_t> mipOffsets, Handle<SHVkSampler> sampler)
|
||||
{
|
||||
isDirty = true;
|
||||
|
||||
auto handle = resourceManager.Create<SHTexture>();
|
||||
addJobs.emplace_back(AddJob { pixelCount, pixelData, format, mipLevels });
|
||||
addJobs.emplace_back(AddJob { pixelCount, pixelData, format, sampler, mipOffsets, width, height, handle });
|
||||
return handle;
|
||||
}
|
||||
|
||||
|
@ -44,22 +62,48 @@ namespace SHADE
|
|||
isDirty = true;
|
||||
}
|
||||
|
||||
void SHTextureLibrary::BuildImages(Handle<SHVkLogicalDevice> device, Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHVkQueue> graphicsQueue, Handle<SHVkDescriptorPool> descPool, Handle<SHVkDescriptorSetLayout> descLayout)
|
||||
void SHTextureLibrary::BuildTextures(Handle<SHVkLogicalDevice> device, Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHVkQueue> graphicsQueue, Handle<SHVkDescriptorPool> descPool)
|
||||
{
|
||||
// Don't do anything if there are no updates
|
||||
if (!isDirty)
|
||||
return;
|
||||
|
||||
/* Remove Textures */
|
||||
std::vector<vk::ImageMemoryBarrier> pipelineBarriers(addJobs.size());
|
||||
// TODO
|
||||
|
||||
/* Add Textures */
|
||||
// Transition
|
||||
// Load Textures - Transitions
|
||||
std::vector<vk::ImageMemoryBarrier> pipelineBarriers(addJobs.size());
|
||||
for (int i = 0; auto& job : addJobs)
|
||||
{
|
||||
job.Image = resourceManager.Create<SHVkImage>();
|
||||
job.Image = resourceManager.Create<SHVkImage>
|
||||
(
|
||||
&device->GetVMAAllocator(),
|
||||
SHImageCreateParams
|
||||
{
|
||||
.imageType = vk::ImageType::e2D,
|
||||
.width = job.Width,
|
||||
.height = job.Height,
|
||||
.depth = 1,
|
||||
.levels = static_cast<uint8_t>(job.MipOffsets.size()),
|
||||
.arrayLayers = 1,
|
||||
.imageFormat = job.TextureFormat,
|
||||
.usageFlags = vk::ImageUsageFlagBits::eSampled | vk::ImageUsageFlagBits::eTransferDst,
|
||||
.createFlags = {}
|
||||
},
|
||||
job.PixelData,
|
||||
job.PixelCount,
|
||||
job.MipOffsets,
|
||||
VmaMemoryUsage::VMA_MEMORY_USAGE_AUTO,
|
||||
VmaAllocationCreateFlagBits {}
|
||||
);
|
||||
job.Image->PrepareImageTransitionInfo(vk::ImageLayout::eUndefined, vk::ImageLayout::eTransferDstOptimal, pipelineBarriers[i]);
|
||||
++i;
|
||||
}
|
||||
vk::PipelineStageFlagBits srcStage = vk::PipelineStageFlagBits::eTopOfPipe;
|
||||
vk::PipelineStageFlagBits dstStage = vk::PipelineStageFlagBits::eTopOfPipe;
|
||||
preparePipelineBarriers(vk::ImageLayout::eUndefined, vk::ImageLayout::eTransferDstOptimal, srcStage, dstStage, pipelineBarriers);
|
||||
cmdBuffer->BeginRecording();
|
||||
cmdBuffer->PipelineBarrier(vk::PipelineStageFlagBits::eTopOfPipe, vk::PipelineStageFlagBits::eTransfer, {}, {}, {}, pipelineBarriers);
|
||||
|
||||
// Copy
|
||||
|
@ -73,13 +117,16 @@ namespace SHADE
|
|||
{
|
||||
// Transition
|
||||
job.Image->PrepareImageTransitionInfo(vk::ImageLayout::eTransferDstOptimal, vk::ImageLayout::eShaderReadOnlyOptimal, pipelineBarriers[i]);
|
||||
++i;
|
||||
}
|
||||
preparePipelineBarriers(vk::ImageLayout::eTransferDstOptimal, vk::ImageLayout::eShaderReadOnlyOptimal, srcStage, dstStage, pipelineBarriers);
|
||||
cmdBuffer->PipelineBarrier(vk::PipelineStageFlagBits::eTopOfPipe, vk::PipelineStageFlagBits::eTransfer, {}, {}, {}, pipelineBarriers);
|
||||
cmdBuffer->PipelineBarrier(vk::PipelineStageFlagBits::eTransfer, vk::PipelineStageFlagBits::eFragmentShader, {}, {}, {}, pipelineBarriers);
|
||||
|
||||
// Execute Commands
|
||||
cmdBuffer->EndRecording();
|
||||
graphicsQueue->SubmitCommandBuffer({ cmdBuffer });
|
||||
device->WaitIdle();
|
||||
graphicsQueue->GetVkQueue().waitIdle();
|
||||
|
||||
// Create Image View
|
||||
for (auto& job : addJobs)
|
||||
|
@ -90,16 +137,45 @@ namespace SHADE
|
|||
.format = job.TextureFormat,
|
||||
.imageAspectFlags = vk::ImageAspectFlagBits::eColor,
|
||||
.baseMipLevel = 0,
|
||||
.mipLevelCount = job.MipLevels,
|
||||
.mipLevelCount = static_cast<uint32_t>(job.MipOffsets.size()),
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = 0
|
||||
.layerCount = 1
|
||||
};
|
||||
job.Handle->ImageView = job.Image->CreateImageView(device, job.Image, DETAILS);
|
||||
job.TextureHandle->ImageView = job.Image->CreateImageView(device, job.Image, DETAILS);
|
||||
}
|
||||
|
||||
// Build Descriptor
|
||||
Handle<SHVkDescriptorSetGroup> descSetGroup = descPool->Allocate({ descLayout }, { 1 });
|
||||
// Add Textures
|
||||
for (auto& job : addJobs)
|
||||
{
|
||||
texOrder.emplace_back(job.TextureHandle);
|
||||
combinedImageSamplers.emplace_back(std::make_tuple(job.TextureHandle->ImageView, job.Sampler, vk::ImageLayout::eShaderReadOnlyOptimal));
|
||||
job.TextureHandle->TextureArrayIndex = texOrder.size() - 1;
|
||||
}
|
||||
addJobs.clear();
|
||||
|
||||
/* Build Descriptor Set with all the Textures only if there are textures */
|
||||
if (!texOrder.empty())
|
||||
{
|
||||
if (!texDescriptors)
|
||||
{
|
||||
texDescriptors = descPool->Allocate
|
||||
(
|
||||
{ SHGraphicsGlobalData::GetDescSetLayouts()[SHGraphicsConstants::DescriptorSetIndex::STATIC_GLOBALS] },
|
||||
{ static_cast<uint32_t>(texOrder.size()) }
|
||||
);
|
||||
}
|
||||
texDescriptors->ModifyWriteDescImage
|
||||
(
|
||||
SHGraphicsConstants::DescriptorSetIndex::STATIC_GLOBALS,
|
||||
SHGraphicsConstants::DescriptorSetBindings::IMAGE_AND_SAMPLERS_DATA,
|
||||
combinedImageSamplers
|
||||
);
|
||||
texDescriptors->UpdateDescriptorSetImages
|
||||
(
|
||||
SHGraphicsConstants::DescriptorSetIndex::STATIC_GLOBALS,
|
||||
SHGraphicsConstants::DescriptorSetBindings::IMAGE_AND_SAMPLERS_DATA
|
||||
);
|
||||
}
|
||||
|
||||
isDirty = false;
|
||||
}
|
||||
|
@ -139,4 +215,65 @@ namespace SHADE
|
|||
}
|
||||
}
|
||||
|
||||
vk::Format SHTextureLibrary::ddsLoaderToVkFormat(tinyddsloader::DDSFile::DXGIFormat format, bool isLinear)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case tinyddsloader::DDSFile::DXGIFormat::BC1_UNorm:
|
||||
return vk::Format::eBc1RgbaUnormBlock;
|
||||
case tinyddsloader::DDSFile::DXGIFormat::BC1_UNorm_SRGB:
|
||||
return vk::Format::eBc1RgbaSrgbBlock;
|
||||
case tinyddsloader::DDSFile::DXGIFormat::BC2_UNorm:
|
||||
case tinyddsloader::DDSFile::DXGIFormat::BC2_UNorm_SRGB:
|
||||
return isLinear ? vk::Format::eBc2UnormBlock : vk::Format::eBc2SrgbBlock;
|
||||
case tinyddsloader::DDSFile::DXGIFormat::BC3_UNorm:
|
||||
case tinyddsloader::DDSFile::DXGIFormat::BC3_UNorm_SRGB:
|
||||
return isLinear ? vk::Format::eBc3UnormBlock : vk::Format::eBc3SrgbBlock;
|
||||
case tinyddsloader::DDSFile::DXGIFormat::BC5_UNorm:
|
||||
case tinyddsloader::DDSFile::DXGIFormat::BC5_SNorm:
|
||||
return isLinear ? vk::Format::eBc5UnormBlock : vk::Format::eBc5SnormBlock;
|
||||
case tinyddsloader::DDSFile::DXGIFormat::R8G8B8A8_UNorm:
|
||||
case tinyddsloader::DDSFile::DXGIFormat::R8G8B8A8_UNorm_SRGB:
|
||||
return isLinear ? vk::Format::eR8G8B8A8Unorm : vk::Format::eR8G8B8A8Srgb;
|
||||
case tinyddsloader::DDSFile::DXGIFormat::R8G8B8A8_SNorm:
|
||||
return vk::Format::eR8G8B8A8Snorm;
|
||||
case tinyddsloader::DDSFile::DXGIFormat::B8G8R8A8_UNorm:
|
||||
case tinyddsloader::DDSFile::DXGIFormat::B8G8R8A8_UNorm_SRGB:
|
||||
return isLinear ? vk::Format::eB8G8R8A8Unorm : vk::Format::eB8G8R8A8Srgb;
|
||||
case tinyddsloader::DDSFile::DXGIFormat::B8G8R8X8_UNorm:
|
||||
case tinyddsloader::DDSFile::DXGIFormat::B8G8R8X8_UNorm_SRGB:
|
||||
return isLinear ? vk::Format::eB8G8R8A8Unorm : vk::Format::eB8G8R8Srgb;
|
||||
default:
|
||||
throw std::runtime_error("Unsupported DDS format.");
|
||||
}
|
||||
|
||||
//switch (format)
|
||||
//{
|
||||
//case tinyddsloader::DDSFile::DXGIFormat::R8G8B8A8_UNorm:
|
||||
//case tinyddsloader::DDSFile::DXGIFormat::R8G8B8A8_UNorm_SRGB:
|
||||
// return (isLinear) ? vk::Format::eR8G8B8A8Unorm : vk::Format::eR8G8B8A8Srgb;
|
||||
//
|
||||
|
||||
//case tinyddsloader::DDSFile::DXGIFormat::B8G8R8A8_UNorm:
|
||||
//case tinyddsloader::DDSFile::DXGIFormat::B8G8R8A8_UNorm_SRGB:
|
||||
// return (isLinear) ? vk::Format::eB8G8R8A8Unorm : vk::Format::eB8G8R8A8Srgb;
|
||||
//
|
||||
|
||||
//case tinyddsloader::DDSFile::DXGIFormat::BC1_UNorm:
|
||||
//case tinyddsloader::DDSFile::DXGIFormat::BC1_UNorm_SRGB:
|
||||
// return (isLinear) ? vk::Format::eBc1RgbaUnormBlock : vk::Format::eBc1RgbaSrgbBlock;
|
||||
|
||||
//case tinyddsloader::DDSFile::DXGIFormat::BC2_UNorm:
|
||||
//case tinyddsloader::DDSFile::DXGIFormat::BC2_UNorm_SRGB:
|
||||
// return (isLinear) ? vk::Format::eBc2UnormBlock : vk::Format::eBc2SrgbBlock;
|
||||
|
||||
//case tinyddsloader::DDSFile::DXGIFormat::BC3_UNorm:
|
||||
//case tinyddsloader::DDSFile::DXGIFormat::BC3_UNorm_SRGB:
|
||||
// return (isLinear) ? vk::Format::eBc3UnormBlock : vk::Format::eBc3SrgbBlock;
|
||||
|
||||
//case tinyddsloader::DDSFile::DXGIFormat::BC5_UNorm:
|
||||
// return (isLinear) ? vk::Format::eBc5UnormBlock : vk::Format::eBc5SnormBlock;
|
||||
//
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,6 +14,8 @@ of DigiPen Institute of Technology is prohibited.
|
|||
|
||||
// STL Includes
|
||||
#include <vector>
|
||||
// External Dependencies
|
||||
#include "tinyddsloader.h"
|
||||
// Project Includes
|
||||
#include "Resource/Handle.h"
|
||||
#include "Resource/ResourceLibrary.h"
|
||||
|
@ -33,6 +35,9 @@ namespace SHADE
|
|||
class SHVkQueue;
|
||||
class SHVkDescriptorPool;
|
||||
class SHVkDescriptorSetLayout;
|
||||
class SHVkDescriptorSetGroup;
|
||||
class SHVkSampler;
|
||||
class SHTextureAsset;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Type Definitions */
|
||||
|
@ -43,7 +48,7 @@ namespace SHADE
|
|||
/*-----------------------------------------------------------------------------*/
|
||||
/* Type Definitions */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
using PixelChannel = float;
|
||||
using PixelChannel = unsigned char;
|
||||
using TextureFormat = vk::Format; // TODO: Change
|
||||
using Index = uint32_t;
|
||||
|
||||
|
@ -71,7 +76,7 @@ namespace SHADE
|
|||
|
||||
\brief
|
||||
Adds a texture to the Texture Library. But this does not mean that the
|
||||
textures have been added yet. A call to "BuildImages()" is required to
|
||||
textures have been added yet. A call to "BuildTextures()" is required to
|
||||
transfer all textures into the GPU.
|
||||
|
||||
\param pixelCount
|
||||
|
@ -88,13 +93,15 @@ namespace SHADE
|
|||
|
||||
*/
|
||||
/*******************************************************************************/
|
||||
Handle<SHTexture> Add(uint32_t pixelCount, const SHTexture::PixelChannel* const pixelData, SHTexture::TextureFormat format, uint32_t mipLevels);
|
||||
|
||||
Handle<SHTexture> Add(const SHTextureAsset& texAsset, Handle<SHVkSampler> sampler);
|
||||
Handle<SHTexture> Add(uint32_t pixelCount, const SHTexture::PixelChannel* const pixelData, uint32_t width, uint32_t height, SHTexture::TextureFormat format, std::vector<uint32_t> mipOffsets, Handle<SHVkSampler> sampler);
|
||||
/*******************************************************************************/
|
||||
/*!
|
||||
|
||||
\brief
|
||||
Removes a mesh from the Texture Library. But this does not mean that the
|
||||
textures have been removed yet. A call to "BuildImages()" is required to
|
||||
textures have been removed yet. A call to "BuildTextures()" is required to
|
||||
finalise all changes.
|
||||
|
||||
\param mesh
|
||||
|
@ -118,12 +125,12 @@ namespace SHADE
|
|||
queue.
|
||||
*/
|
||||
/***************************************************************************/
|
||||
void BuildImages(Handle<SHVkLogicalDevice> device, Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHVkQueue> graphicsQueue, Handle<SHVkDescriptorPool> descPool, Handle<SHVkDescriptorSetLayout> descLayout);
|
||||
void BuildTextures(Handle<SHVkLogicalDevice> device, Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHVkQueue> graphicsQueue, Handle<SHVkDescriptorPool> descPool);
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Getter Functions */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
Handle<SHVkBuffer> GetTextureBuffer() const noexcept { return texStorageBuffer; }
|
||||
Handle<SHVkDescriptorSetGroup> GetTextureDescriptorSetGroup() const noexcept { return texDescriptors; }
|
||||
|
||||
private:
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
|
@ -134,9 +141,12 @@ namespace SHADE
|
|||
uint32_t PixelCount = 0;
|
||||
const SHTexture::PixelChannel* PixelData = nullptr;
|
||||
SHTexture::TextureFormat TextureFormat = {};
|
||||
uint32_t MipLevels = 0;
|
||||
Handle<SHVkSampler> Sampler;
|
||||
std::vector<uint32_t> MipOffsets;
|
||||
uint32_t Width;
|
||||
uint32_t Height;
|
||||
Handle<SHTexture> TextureHandle;
|
||||
Handle<SHVkImage> Image;
|
||||
Handle<SHTexture> Handle;
|
||||
};
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
|
@ -149,9 +159,9 @@ namespace SHADE
|
|||
ResourceManager resourceManager;
|
||||
std::vector<Handle<SHTexture>> texOrder;
|
||||
// CPU Storage
|
||||
std::vector<SHTexture::PixelChannel> texStorage;
|
||||
std::vector<std::tuple<Handle<SHVkImageView>, Handle<SHVkSampler>, vk::ImageLayout>> combinedImageSamplers;
|
||||
// GPU Storage
|
||||
Handle<SHVkBuffer> texStorageBuffer{};
|
||||
Handle<SHVkDescriptorSetGroup> texDescriptors;
|
||||
// Flags
|
||||
bool isDirty = true;
|
||||
|
||||
|
@ -159,5 +169,6 @@ namespace SHADE
|
|||
/* Helper Functions */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
void preparePipelineBarriers(vk::ImageLayout oldLayout, vk::ImageLayout newLayout, vk::PipelineStageFlagBits& srcStage, vk::PipelineStageFlagBits& dstStage, std::vector<vk::ImageMemoryBarrier>& barriers);
|
||||
vk::Format ddsLoaderToVkFormat(tinyddsloader::DDSFile::DXGIFormat format, bool isLinear);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
/************************************************************************************//*!
|
||||
\file SHVkSamplerCache.cpp
|
||||
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||
\par email: kahwei.tng\@digipen.edu
|
||||
\date Mar 16, 2022
|
||||
\brief Contains the implementation for the SHVkSamplerCache class.
|
||||
|
||||
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 "SHVkSamplerCache.h"
|
||||
|
||||
// Standard Library
|
||||
#include <functional>
|
||||
// Project Header
|
||||
#include "Graphics/Images/SHVkSampler.h"
|
||||
#include "Graphics/Devices/SHVkLogicalDevice.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Utility Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
void SHSamplerCache::Clear()
|
||||
{
|
||||
samplersMap.clear();
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Getter Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
Handle<SHVkSampler> SHSamplerCache::GetSampler(Handle<SHVkLogicalDevice> device, const SHVkSamplerParams& params)
|
||||
{
|
||||
// Get the hash to check if it was cached
|
||||
const RawSamplerHash HASH = calcHash
|
||||
(
|
||||
params.minFilter,
|
||||
params.magFilter,
|
||||
params.addressMode,
|
||||
params.mipmapMode,
|
||||
params.minLod,
|
||||
params.maxLod
|
||||
);
|
||||
|
||||
// Check if it was cached
|
||||
auto sampler = samplersMap.find(HASH);
|
||||
if (sampler == samplersMap.end())
|
||||
{
|
||||
const auto BUILD_RESULT = samplersMap.emplace(HASH, device->CreateSampler(params));
|
||||
sampler = BUILD_RESULT.first;
|
||||
}
|
||||
|
||||
return sampler->second;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Helper Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
SHSamplerCache::RawSamplerHash SHSamplerCache::calcHash(vk::Filter minFilter, vk::Filter magFilter, vk::SamplerAddressMode addressMode, vk::SamplerMipmapMode mipmapMode, float minLod, float maxLod)
|
||||
{
|
||||
static auto charHasher = std::hash<uint8_t>{};
|
||||
static auto floatHasher = std::hash<float>{};
|
||||
|
||||
const RawSamplerHash H1 = charHasher(static_cast<uint8_t>(minFilter));
|
||||
const RawSamplerHash H2 = charHasher(static_cast<uint8_t>(magFilter));
|
||||
const RawSamplerHash H3 = charHasher(static_cast<uint8_t>(addressMode));
|
||||
const RawSamplerHash H4 = charHasher(static_cast<uint8_t>(mipmapMode));
|
||||
const RawSamplerHash H5 = floatHasher(minLod);
|
||||
const RawSamplerHash H6 = floatHasher(maxLod);
|
||||
|
||||
return H1 ^ (H2 << 1) ^ (H3 << 2) ^ (H4 << 3) ^ (H5 << 4) ^ (H6 << 5);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
/************************************************************************************//*!
|
||||
\file SHSamplerCache.h
|
||||
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||
\par email: kahwei.tng\@digipen.edu
|
||||
\date Mar 16, 2022
|
||||
\brief Contains the interface for the SHSamplerCache class.
|
||||
|
||||
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
|
||||
|
||||
// Standard Libraries
|
||||
#include <unordered_map>
|
||||
// External Dependencies
|
||||
#include "Graphics/SHVulkanIncludes.h"
|
||||
// Project Includes
|
||||
#include "Resource/Handle.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Forward Declarations */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
class SHVkLogicalDevice;
|
||||
class SHVkSampler;
|
||||
struct SHVkSamplerParams;
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Type Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/*************************************************************************************/
|
||||
/*!
|
||||
\brief
|
||||
Class that is responsible for caching and providing Samplers to the user for
|
||||
sampling textures.
|
||||
*/
|
||||
/*************************************************************************************/
|
||||
class SHSamplerCache
|
||||
{
|
||||
public:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Utility Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Clears the cache, destroying all created samplers.
|
||||
/// </summary>
|
||||
void Clear();
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Getter Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Retrieves a Vulkan Sampler of the specified type. If this was retrieved
|
||||
/// before, a cached copy of the Vulkan Sampler will be provided.
|
||||
/// </summary>
|
||||
/// <param name="device">Logical device to create the sampler with if needed.</param>
|
||||
/// <param name="params">Describes the parameters for the sampler.</param>
|
||||
/// <returns>Handle to the SHVkSampler object specified.</returns>
|
||||
Handle<SHVkSampler> GetSampler(Handle<SHVkLogicalDevice> device, const SHVkSamplerParams& params);
|
||||
|
||||
private:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Type Definitions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
using RawSamplerHash = size_t;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Data Members */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
// Resources
|
||||
std::unordered_map<RawSamplerHash, Handle<SHVkSampler>> samplersMap;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Helper Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
static RawSamplerHash calcHash(vk::Filter minFilter, vk::Filter magFilter, vk::SamplerAddressMode addressMode, vk::SamplerMipmapMode mipmapMode, float minLod, float maxLod);
|
||||
};
|
||||
}
|
|
@ -216,10 +216,13 @@ namespace SHADE
|
|||
/***************************************************************************/
|
||||
void SHVkPipelineLayout::PrepareVkDescriptorSetLayouts(void) noexcept
|
||||
{
|
||||
descriptorSetLayoutsPipeline.reserve(descriptorSetLayoutsAllocate.size() + descriptorSetLayoutsGlobal.size());
|
||||
|
||||
// Settle allocate layouts first
|
||||
vkDescriptorSetLayoutsAllocate.reserve(descriptorSetLayoutsAllocate.size());
|
||||
for (auto const& layout : descriptorSetLayoutsAllocate)
|
||||
{
|
||||
descriptorSetLayoutsPipeline.emplace_back(layout);
|
||||
vkDescriptorSetLayoutsAllocate.emplace_back(layout->GetVkHandle());
|
||||
}
|
||||
|
||||
|
@ -228,7 +231,10 @@ namespace SHADE
|
|||
|
||||
// First we insert the global layouts
|
||||
for (auto const& layout : descriptorSetLayoutsGlobal)
|
||||
{
|
||||
descriptorSetLayoutsPipeline.emplace_back(layout);
|
||||
vkDescriptorSetLayoutsPipeline.emplace_back(layout->GetVkHandle());
|
||||
}
|
||||
|
||||
// Then we append layouts for allocation at the back of the vector
|
||||
std::copy(vkDescriptorSetLayoutsAllocate.begin(), vkDescriptorSetLayoutsAllocate.end(), std::back_inserter(vkDescriptorSetLayoutsPipeline));
|
||||
|
@ -435,6 +441,16 @@ namespace SHADE
|
|||
return {};
|
||||
}
|
||||
|
||||
std::vector<Handle<SHVkDescriptorSetLayout>> SHVkPipelineLayout::GetDescriptorSetLayoutsPipeline(void) const noexcept
|
||||
{
|
||||
return descriptorSetLayoutsPipeline;
|
||||
}
|
||||
|
||||
std::vector<Handle<SHVkDescriptorSetLayout>> SHVkPipelineLayout::GetDescriptorSetLayoutsAllocate(void) const noexcept
|
||||
{
|
||||
return descriptorSetLayoutsAllocate;
|
||||
}
|
||||
|
||||
SHVkPipelineLayout& SHVkPipelineLayout::operator=(SHVkPipelineLayout&& rhs) noexcept
|
||||
{
|
||||
if (&rhs == this)
|
||||
|
|
|
@ -42,6 +42,9 @@ namespace SHADE
|
|||
//! We want to store this also because we need to allocate later
|
||||
std::vector<vk::DescriptorSetLayout> vkDescriptorSetLayoutsAllocate;
|
||||
|
||||
//! Store for descriptor set group creation
|
||||
std::vector<Handle<SHVkDescriptorSetLayout>> descriptorSetLayoutsPipeline;
|
||||
|
||||
//! Store for pipeline layout recreation
|
||||
std::vector<vk::DescriptorSetLayout> vkDescriptorSetLayoutsPipeline;
|
||||
|
||||
|
@ -71,10 +74,12 @@ namespace SHADE
|
|||
/*-----------------------------------------------------------------------*/
|
||||
/* SETTERS AND GETTERS */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
std::vector<Handle<SHVkShaderModule>> const& GetShaderModules (void) const noexcept;
|
||||
vk::PipelineLayout GetVkPipelineLayout (void) const noexcept;
|
||||
SHPushConstantInterface const& GetPushConstantInterface (void) const noexcept;
|
||||
Handle<SHShaderBlockInterface> GetShaderBlockInterface (uint32_t set, uint32_t binding, vk::ShaderStageFlagBits shaderStage) const noexcept;
|
||||
std::vector<Handle<SHVkShaderModule>> const& GetShaderModules (void) const noexcept;
|
||||
vk::PipelineLayout GetVkPipelineLayout (void) const noexcept;
|
||||
SHPushConstantInterface const& GetPushConstantInterface (void) 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>> GetDescriptorSetLayoutsAllocate(void) const noexcept;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
#pragma once
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
// Used for attachment description creation for renderpass node
|
||||
enum class SH_ATT_DESC_TYPE
|
||||
{
|
||||
COLOR,
|
||||
COLOR_PRESENT,
|
||||
DEPTH,
|
||||
STENCIL,
|
||||
DEPTH_STENCIL,
|
||||
};
|
||||
}
|
|
@ -11,655 +11,7 @@
|
|||
|
||||
namespace SHADE
|
||||
{
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
\brief
|
||||
Non-default ctor for the resource. Using the type of the resource, we
|
||||
decide whether or not we create a resource or link with a swapchain
|
||||
resource (image).
|
||||
|
||||
\param logicalDevice
|
||||
Logical device required to create an image resource if the type is NOT
|
||||
SH_ATT_DESC_TYPE::COLOR_PRESENT.
|
||||
|
||||
\param swapchain
|
||||
Swapchain required to get swapchain image if the type IS
|
||||
SH_ATT_DESC_TYPE::COLOR_PRESENT.
|
||||
|
||||
\param type
|
||||
Type of the image resource.
|
||||
|
||||
\param format
|
||||
Format of the image resource.
|
||||
|
||||
\param w
|
||||
Width of the image resource.
|
||||
|
||||
\param h
|
||||
Height of the image resource.
|
||||
|
||||
\param levels
|
||||
Number of mipmap levels of the image resource.
|
||||
|
||||
\param createFlags
|
||||
Create flags used when an image resource needs to be created.
|
||||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
SHRenderGraphResource::SHRenderGraphResource(Handle<SHVkLogicalDevice> const& logicalDevice, Handle<SHVkSwapchain> const& swapchain, std::string const& name, SH_ATT_DESC_TYPE type, vk::Format format, uint32_t w, uint32_t h, uint8_t levels, vk::ImageCreateFlagBits createFlags) noexcept
|
||||
: resourceType{ type }
|
||||
, resourceFormat{ format }
|
||||
, images{}
|
||||
, imageViews{}
|
||||
, width{ w }
|
||||
, height{ h }
|
||||
, mipLevels{ levels }
|
||||
, resourceName{ name }
|
||||
{
|
||||
// If the resource type is an arbitrary image and not swapchain image
|
||||
if (type != SH_ATT_DESC_TYPE::COLOR_PRESENT)
|
||||
{
|
||||
vk::ImageAspectFlags imageAspectFlags;
|
||||
vk::ImageUsageFlags usage = {};
|
||||
|
||||
// Check the resource type and set image usage flags and image aspect flags accordingly
|
||||
switch (resourceType)
|
||||
{
|
||||
case SH_ATT_DESC_TYPE::COLOR:
|
||||
usage |= vk::ImageUsageFlagBits::eColorAttachment;
|
||||
imageAspectFlags |= vk::ImageAspectFlagBits::eColor;
|
||||
break;
|
||||
case SH_ATT_DESC_TYPE::DEPTH:
|
||||
usage |= vk::ImageUsageFlagBits::eDepthStencilAttachment;
|
||||
imageAspectFlags |= vk::ImageAspectFlagBits::eDepth;
|
||||
break;
|
||||
case SH_ATT_DESC_TYPE::STENCIL:
|
||||
usage |= vk::ImageUsageFlagBits::eDepthStencilAttachment;
|
||||
imageAspectFlags |= vk::ImageAspectFlagBits::eStencil;
|
||||
break;
|
||||
case SH_ATT_DESC_TYPE::DEPTH_STENCIL:
|
||||
usage |= vk::ImageUsageFlagBits::eDepthStencilAttachment;
|
||||
imageAspectFlags |= vk::ImageAspectFlagBits::eStencil | vk::ImageAspectFlagBits::eDepth;
|
||||
break;
|
||||
}
|
||||
|
||||
// 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));
|
||||
|
||||
// prepare image view details
|
||||
SHImageViewDetails viewDetails
|
||||
{
|
||||
.viewType = vk::ImageViewType::e2D,
|
||||
.format = images[0]->GetImageFormat(),
|
||||
.imageAspectFlags = imageAspectFlags,
|
||||
.baseMipLevel = 0,
|
||||
.mipLevelCount = mipLevels,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = 1,
|
||||
};
|
||||
|
||||
// just 1 image view created
|
||||
imageViews.push_back(images[0]->CreateImageView(logicalDevice, images[0], viewDetails));
|
||||
}
|
||||
else // if swapchain image resource
|
||||
{
|
||||
// Prepare image view details
|
||||
SHImageViewDetails viewDetails
|
||||
{
|
||||
.viewType = vk::ImageViewType::e2D,
|
||||
.format = swapchain->GetSurfaceFormatKHR().format,
|
||||
.imageAspectFlags = vk::ImageAspectFlagBits::eColor,
|
||||
.baseMipLevel = 0,
|
||||
.mipLevelCount = 1,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = 1,
|
||||
};
|
||||
|
||||
// We want an image handle for every swapchain image
|
||||
images.resize(swapchain->GetNumImages());
|
||||
imageViews.resize(swapchain->GetNumImages());
|
||||
|
||||
for (uint32_t i = 0; i < swapchain->GetNumImages(); ++i)
|
||||
{
|
||||
images[i] = swapchain->GetSwapchainImage(i);
|
||||
imageViews[i] = images[i]->CreateImageView(logicalDevice, images[i], viewDetails);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
\brief
|
||||
Move ctor for resource.
|
||||
|
||||
\param rhs
|
||||
The other resource.
|
||||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
SHRenderGraphResource::SHRenderGraphResource(SHRenderGraphResource&& rhs) noexcept
|
||||
: resourceName{ std::move(rhs.resourceName) }
|
||||
, resourceType{ std::move(rhs.resourceType) }
|
||||
, images{ std::move(rhs.images) }
|
||||
, imageViews{ std::move(rhs.imageViews) }
|
||||
, resourceFormat{ std::move(rhs.resourceFormat) }
|
||||
, width{ rhs.width }
|
||||
, height{ rhs.height }
|
||||
, mipLevels{ rhs.mipLevels }
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
\brief
|
||||
Move assignment operator.
|
||||
|
||||
\param rhs
|
||||
The other resource.
|
||||
|
||||
\return
|
||||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
SHRenderGraphResource& SHRenderGraphResource::operator=(SHRenderGraphResource&& rhs) noexcept
|
||||
{
|
||||
if (this == &rhs)
|
||||
return *this;
|
||||
|
||||
resourceName = std::move(rhs.resourceName);
|
||||
resourceType = std::move(rhs.resourceType);
|
||||
images = std::move(rhs.images);
|
||||
imageViews = std::move(rhs.imageViews);
|
||||
resourceFormat = std::move(rhs.resourceFormat);
|
||||
width = rhs.width;
|
||||
height = rhs.height;
|
||||
mipLevels = rhs.mipLevels;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
\brief
|
||||
Destructor for resource.
|
||||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
SHRenderGraphResource::~SHRenderGraphResource(void) noexcept
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
\brief
|
||||
Subpass non-default constructor. Simply initializes variables.
|
||||
|
||||
\param mapping
|
||||
Mapping from a resource handle to an attachment reference referencing
|
||||
the resource.
|
||||
|
||||
\param resources
|
||||
A mapping from string to render graph resource.
|
||||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
SHSubpass::SHSubpass(ResourceManager& rm, 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
|
||||
: resourceAttachmentMapping{ mapping }
|
||||
, ptrToResources{ resources }
|
||||
, parentNode{ parent }
|
||||
, subpassIndex{ index }
|
||||
, superBatch{}
|
||||
, colorReferences{}
|
||||
, depthReferences{}
|
||||
, inputReferences{}
|
||||
{
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
\brief
|
||||
Move constructor for subpass.
|
||||
|
||||
\param rhs
|
||||
The subpass the move from.
|
||||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
SHSubpass::SHSubpass(SHSubpass&& rhs) noexcept
|
||||
: subpassIndex{ std::move(rhs.subpassIndex) }
|
||||
, parentNode{ std::move(rhs.parentNode) }
|
||||
, superBatch{ std::move(rhs.superBatch) }
|
||||
, colorReferences{ std::move(rhs.colorReferences) }
|
||||
, depthReferences{ std::move(rhs.depthReferences) }
|
||||
, inputReferences{ std::move(rhs.inputReferences) }
|
||||
, resourceAttachmentMapping{ rhs.resourceAttachmentMapping }
|
||||
, ptrToResources{ rhs.ptrToResources }
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
\brief
|
||||
Move assignment operator for subpass.
|
||||
|
||||
\param rhs
|
||||
subpass to move from.
|
||||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
SHSubpass& SHSubpass::operator=(SHSubpass&& rhs) noexcept
|
||||
{
|
||||
if (this == &rhs)
|
||||
return *this;
|
||||
|
||||
subpassIndex = std::move(rhs.subpassIndex);
|
||||
parentNode = std::move(rhs.parentNode);
|
||||
superBatch = std::move(rhs.superBatch);
|
||||
colorReferences = std::move(rhs.colorReferences);
|
||||
depthReferences = std::move(rhs.depthReferences);
|
||||
inputReferences = std::move(rhs.inputReferences);
|
||||
resourceAttachmentMapping = rhs.resourceAttachmentMapping;
|
||||
ptrToResources = rhs.ptrToResources;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
\brief
|
||||
Adds a color output to a subpass. Takes in a string and finds the
|
||||
attachment index to create the vk::SubpassReference.
|
||||
|
||||
\param resourceToReference
|
||||
Resource name to find resource to attach.
|
||||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
void SHSubpass::AddColorOutput(std::string resourceToReference) noexcept
|
||||
{
|
||||
colorReferences.push_back({ resourceAttachmentMapping->at(ptrToResources->at(resourceToReference).GetId().Raw), vk::ImageLayout::eColorAttachmentOptimal });
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
\brief
|
||||
Adds a depth output to a subpass. Takes in a string and finds the
|
||||
attachment index to create the vk::SubpassReference.
|
||||
|
||||
\param resourceToReference
|
||||
Resource name to find resource to attach.
|
||||
|
||||
\param attachmentDescriptionType
|
||||
Depending on the type of the resource, initialize the image layout
|
||||
appropriately.
|
||||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
void SHSubpass::AddDepthOutput(std::string resourceToReference, SH_ATT_DESC_TYPE attachmentDescriptionType) noexcept
|
||||
{
|
||||
vk::ImageLayout imageLayout;
|
||||
switch (attachmentDescriptionType)
|
||||
{
|
||||
case SH_ATT_DESC_TYPE::DEPTH:
|
||||
imageLayout = vk::ImageLayout::eDepthAttachmentOptimal;
|
||||
break;
|
||||
case SH_ATT_DESC_TYPE::STENCIL:
|
||||
imageLayout = vk::ImageLayout::eStencilAttachmentOptimal;
|
||||
break;
|
||||
case SH_ATT_DESC_TYPE::DEPTH_STENCIL:
|
||||
imageLayout = vk::ImageLayout::eDepthStencilAttachmentOptimal;
|
||||
break;
|
||||
default:
|
||||
//Invalid
|
||||
return;
|
||||
}
|
||||
depthReferences.push_back({ resourceAttachmentMapping->at(ptrToResources->at(resourceToReference).GetId().Raw), imageLayout });
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
\brief
|
||||
Adds a input output to a subpass. Takes in a string and finds the
|
||||
attachment index to create the vk::SubpassReference.
|
||||
|
||||
\param resourceToReference
|
||||
Resource name to find resource to attach.
|
||||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
void SHSubpass::AddInput(std::string resourceToReference) noexcept
|
||||
{
|
||||
inputReferences.push_back({ resourceAttachmentMapping->at(ptrToResources->at(resourceToReference).GetId().Raw), vk::ImageLayout::eShaderReadOnlyOptimal });
|
||||
}
|
||||
|
||||
void SHSubpass::Execute(Handle<SHVkCommandBuffer>& commandBuffer, uint32_t frameIndex) noexcept
|
||||
{
|
||||
// Ensure correct transforms are provided
|
||||
superBatch->UpdateBuffers(frameIndex);
|
||||
|
||||
// Draw all the batches
|
||||
superBatch->Draw(commandBuffer, frameIndex);
|
||||
|
||||
// Draw all the exterior draw calls
|
||||
for (auto& drawCall : exteriorDrawCalls)
|
||||
{
|
||||
drawCall(commandBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
void SHSubpass::AddExteriorDrawCalls(std::function<void(Handle<SHVkCommandBuffer>&)> const& newDrawCall) noexcept
|
||||
{
|
||||
exteriorDrawCalls.push_back(newDrawCall);
|
||||
}
|
||||
|
||||
void SHSubpass::Init(ResourceManager& resourceManager) noexcept
|
||||
{
|
||||
superBatch = resourceManager.Create<SHSuperBatch>(GetHandle());
|
||||
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
\brief
|
||||
Getter for parent renderpass.
|
||||
|
||||
\return
|
||||
Returns the parent renderpass the subpass belongs to.
|
||||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
Handle<SHRenderGraphNode> const& SHSubpass::GetParentNode(void) const noexcept
|
||||
{
|
||||
return parentNode;
|
||||
}
|
||||
|
||||
SHADE::SHSubPassIndex SHSubpass::GetIndex() const noexcept
|
||||
{
|
||||
return subpassIndex;
|
||||
}
|
||||
|
||||
Handle<SHSuperBatch> SHSubpass::GetSuperBatch(void) const noexcept
|
||||
{
|
||||
return superBatch;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
\brief
|
||||
Creates a renderpass for the node. Uses subpass and attachment
|
||||
descriptions already configured beforehand in the render graph.
|
||||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
void SHRenderGraphNode::CreateRenderpass(void) noexcept
|
||||
{
|
||||
renderpass = logicalDeviceHdl->CreateRenderpass(attachmentDescriptions, spDescs, spDeps);
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
\brief
|
||||
Creates a framebuffer from the images used in the renderpass.
|
||||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
void SHRenderGraphNode::CreateFramebuffer(void) noexcept
|
||||
{
|
||||
for (uint32_t i = 0; i < framebuffers.size(); ++i)
|
||||
{
|
||||
std::vector<Handle<SHVkImageView>> imageViews(attResources.size());
|
||||
uint32_t fbWidth = std::numeric_limits<uint32_t>::max();
|
||||
uint32_t fbHeight = std::numeric_limits<uint32_t>::max();
|
||||
|
||||
for (uint32_t j = 0; j < attResources.size(); ++j)
|
||||
{
|
||||
uint32_t imageViewIndex = (attResources[j]->resourceType == SH_ATT_DESC_TYPE::COLOR_PRESENT) ? i : 0;
|
||||
imageViews[j] = attResources[j]->imageViews[imageViewIndex];
|
||||
|
||||
// We want the minimum dimensions for the framebuffer because the image attachments referenced cannot have dimensions smaller than the framebuffer's
|
||||
if (fbWidth > attResources[j]->width)
|
||||
fbWidth = attResources[j]->width;
|
||||
if (fbHeight > attResources[j]->height)
|
||||
fbHeight = attResources[j]->height;
|
||||
}
|
||||
|
||||
|
||||
framebuffers[i] = logicalDeviceHdl->CreateFramebuffer(renderpass, imageViews, fbWidth, fbHeight);
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
\brief
|
||||
Render Graph node constructor. Note that we do not create the renderpass
|
||||
yet. This is because layouts of attachment descriptions facilitate image
|
||||
transitions and we cannot know guarantee layouts until we've seen all
|
||||
renderpasses and their subpasses in the graph.
|
||||
|
||||
\param swapchain
|
||||
Swapchain required to query number of images as parameters for number
|
||||
of framebuffers to create.
|
||||
|
||||
\param attachmentDescriptionTypes
|
||||
|
||||
|
||||
\return
|
||||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
SHRenderGraphNode::SHRenderGraphNode(ResourceManager& rm, Handle<SHVkLogicalDevice> const& logicalDevice, Handle<SHVkSwapchain> const& swapchain, std::vector<Handle<SHRenderGraphResource>> attRes, std::vector<Handle<SHRenderGraphNode>> predecessors, std::unordered_map<std::string, Handle<SHRenderGraphResource>> const* resources, Handle<SHGraphicsGlobalData> globalData) noexcept
|
||||
: logicalDeviceHdl{ logicalDevice }
|
||||
, renderpass{}
|
||||
, framebuffers{}
|
||||
, prereqNodes{ std::move(predecessors) }
|
||||
, attachmentDescriptions{}
|
||||
, resourceAttachmentMapping{}
|
||||
, attResources{ std::move(attRes) }
|
||||
, subpasses{}
|
||||
, executed{ false }
|
||||
, configured{ false }
|
||||
, resourceManager{ rm }
|
||||
, ptrToResources{ resources }
|
||||
{
|
||||
// pipeline library initialization
|
||||
pipelineLibrary.Init(logicalDeviceHdl, globalData);
|
||||
|
||||
attachmentDescriptions.resize(attResources.size());
|
||||
|
||||
bool containsSwapchainImage = false;
|
||||
for (uint32_t i = 0; i < attResources.size(); ++i)
|
||||
{
|
||||
// As mentioned above we don't initialize much here because it's dependent on how other renderpasses are configured.
|
||||
vk::AttachmentDescription& newDesc = attachmentDescriptions[i];
|
||||
newDesc.samples = vk::SampleCountFlagBits::e1;
|
||||
|
||||
// We set this to clear first. If later we find out that some predecessor is writing to the same attachment,
|
||||
// we set the pred's storeOp to eStore and "this" loadOp to eLoad.
|
||||
newDesc.loadOp = vk::AttachmentLoadOp::eClear;
|
||||
newDesc.storeOp = vk::AttachmentStoreOp::eStore;
|
||||
|
||||
newDesc.stencilLoadOp = vk::AttachmentLoadOp::eClear;
|
||||
newDesc.stencilStoreOp = vk::AttachmentStoreOp::eStore;
|
||||
|
||||
newDesc.format = attResources[i]->resourceFormat;
|
||||
|
||||
if (attResources[i]->resourceType == SH_ATT_DESC_TYPE::COLOR_PRESENT)
|
||||
containsSwapchainImage = true;
|
||||
|
||||
resourceAttachmentMapping.try_emplace(attResources[i].GetId().Raw, i);
|
||||
}
|
||||
|
||||
if (!containsSwapchainImage)
|
||||
framebuffers.resize(1);
|
||||
else
|
||||
framebuffers.resize(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
|
||||
// deferred to when renderpasses are also created.
|
||||
}
|
||||
|
||||
SHRenderGraphNode::SHRenderGraphNode(SHRenderGraphNode&& rhs) noexcept
|
||||
: resourceManager{ rhs.resourceManager }
|
||||
, logicalDeviceHdl{ rhs.logicalDeviceHdl }
|
||||
, renderpass{ rhs.renderpass }
|
||||
, framebuffers{ std::move(rhs.framebuffers) }
|
||||
, prereqNodes{ std::move(rhs.prereqNodes) }
|
||||
, attachmentDescriptions{ std::move(rhs.attachmentDescriptions) }
|
||||
, attResources{ std::move(rhs.attResources) }
|
||||
, subpasses{ std::move(rhs.subpasses) }
|
||||
, resourceAttachmentMapping{ std::move(rhs.resourceAttachmentMapping) }
|
||||
, subpassIndexing{ std::move(rhs.subpassIndexing) }
|
||||
, configured{ rhs.configured }
|
||||
, executed{ rhs.executed }
|
||||
, ptrToResources{ rhs.ptrToResources }
|
||||
, pipelineLibrary{ std::move(rhs.pipelineLibrary) }
|
||||
, batcher { std::move(rhs.batcher) }
|
||||
|
||||
{
|
||||
rhs.renderpass = {};
|
||||
}
|
||||
|
||||
SHRenderGraphNode& SHRenderGraphNode::operator=(SHRenderGraphNode&& rhs) noexcept
|
||||
{
|
||||
if (&rhs == this)
|
||||
return *this;
|
||||
|
||||
resourceManager = rhs.resourceManager;
|
||||
logicalDeviceHdl = rhs.logicalDeviceHdl;
|
||||
renderpass = rhs.renderpass;
|
||||
framebuffers = std::move(rhs.framebuffers);
|
||||
prereqNodes = std::move(rhs.prereqNodes);
|
||||
attachmentDescriptions = std::move(rhs.attachmentDescriptions);
|
||||
attResources = std::move(rhs.attResources);
|
||||
subpasses = std::move(rhs.subpasses);
|
||||
resourceAttachmentMapping = std::move(rhs.resourceAttachmentMapping);
|
||||
subpassIndexing = std::move(rhs.subpassIndexing);
|
||||
ptrToResources = std::move(rhs.ptrToResources);
|
||||
pipelineLibrary = std::move(rhs.pipelineLibrary);
|
||||
batcher = std::move(rhs.batcher);
|
||||
|
||||
rhs.renderpass = {};
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
\brief
|
||||
Add subpasses to the renderpass and returns a reference to it.
|
||||
|
||||
\param subpassName
|
||||
Name of the subpass.
|
||||
|
||||
\return
|
||||
Handle to the new subpass.
|
||||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
Handle<SHSubpass> SHRenderGraphNode::AddSubpass(std::string subpassName) noexcept
|
||||
{
|
||||
// if subpass already exists, don't add.
|
||||
if (subpassIndexing.contains(subpassName))
|
||||
{
|
||||
SHLOG_ERROR("Subpass already exists.");
|
||||
return{};
|
||||
}
|
||||
|
||||
// Add subpass to container and create mapping for it
|
||||
subpasses.emplace_back(resourceManager.Create<SHSubpass>(resourceManager, GetHandle(), subpasses.size(), &resourceAttachmentMapping, ptrToResources));
|
||||
subpassIndexing.try_emplace(subpassName, static_cast<uint32_t>(subpasses.size()) - 1u);
|
||||
Handle<SHSubpass> subpass = subpasses.back();
|
||||
subpass->Init(resourceManager);
|
||||
|
||||
// Register the SuperBatch
|
||||
batcher.RegisterSuperBatch(subpass->GetSuperBatch());
|
||||
|
||||
return subpass;
|
||||
}
|
||||
|
||||
void SHRenderGraphNode::Execute(Handle<SHVkCommandBuffer>& commandBuffer, uint32_t frameIndex) noexcept
|
||||
{
|
||||
frameIndex = (framebuffers.size() > 1) ? frameIndex : 0;
|
||||
commandBuffer->BeginRenderpass(renderpass, framebuffers[frameIndex]);
|
||||
|
||||
for (uint32_t i = 0; i < subpasses.size(); ++i)
|
||||
{
|
||||
subpasses[i]->Execute(commandBuffer, frameIndex);
|
||||
|
||||
// Go to next subpass if not last subpass
|
||||
if (i != subpasses.size() - 1)
|
||||
commandBuffer->NextSubpass();
|
||||
}
|
||||
|
||||
commandBuffer->EndRenderpass();
|
||||
}
|
||||
|
||||
Handle<SHVkPipeline> SHRenderGraphNode::GetOrCreatePipeline(std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair, Handle<SHSubpass> subpass) noexcept
|
||||
{
|
||||
// verify subpass exists
|
||||
if (subpass->GetIndex() >= subpasses.size())
|
||||
{
|
||||
SHLOG_ERROR("Subpass index passed in is not valid. RenderGraphNode does not have that many passes. ");
|
||||
return {};
|
||||
}
|
||||
|
||||
Handle<SHVkPipeline> pipeline = pipelineLibrary.GetDrawPipline(vsFsPair);
|
||||
if (!pipeline)
|
||||
{
|
||||
pipeline = pipelineLibrary.CreateDrawPipeline
|
||||
(
|
||||
vsFsPair,
|
||||
renderpass,
|
||||
subpass
|
||||
);
|
||||
}
|
||||
|
||||
return pipeline;
|
||||
}
|
||||
|
||||
void SHRenderGraphNode::FinaliseBatch(uint32_t frameIndex)
|
||||
{
|
||||
batcher.FinaliseBatches(logicalDeviceHdl, frameIndex);
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
\brief
|
||||
Get the renderpass from the node.
|
||||
|
||||
\return
|
||||
Handle to the renderpass.
|
||||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
Handle<SHVkRenderpass> SHRenderGraphNode::GetRenderpass(void) const noexcept
|
||||
{
|
||||
return renderpass;
|
||||
}
|
||||
|
||||
Handle<SHSubpass> SHRenderGraphNode::GetSubpass(std::string_view subpassName) const noexcept
|
||||
{
|
||||
return subpasses[subpassIndexing.at(subpassName.data())];
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
@ -779,7 +131,7 @@ namespace SHADE
|
|||
attDesc.loadOp = vk::AttachmentLoadOp::eLoad;
|
||||
predAttDesc.storeOp = vk::AttachmentStoreOp::eStore;
|
||||
|
||||
// TODO: Stecil 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
|
||||
// value of the attachment description. We want this to carry over to the next renderpass; specifically
|
||||
|
@ -976,11 +328,10 @@ namespace SHADE
|
|||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
void SHRenderGraph::Init(Handle<SHVkLogicalDevice> const& logicalDevice, Handle<SHVkSwapchain> const& swapchain, Handle<SHGraphicsGlobalData> inGlobalData) noexcept
|
||||
void SHRenderGraph::Init(Handle<SHVkLogicalDevice> const& logicalDevice, Handle<SHVkSwapchain> const& swapchain) noexcept
|
||||
{
|
||||
logicalDeviceHdl = logicalDevice;
|
||||
swapchainHdl = swapchain;
|
||||
globalData = inGlobalData;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
@ -1012,7 +363,6 @@ namespace SHADE
|
|||
, nodes{ std::move(rhs.nodes) }
|
||||
, graphResources{ std::move(rhs.graphResources) }
|
||||
, resourceManager{ std::move(rhs.resourceManager) }
|
||||
, globalData{ rhs.globalData }
|
||||
{
|
||||
|
||||
}
|
||||
|
@ -1028,7 +378,6 @@ namespace SHADE
|
|||
nodes = std::move(rhs.nodes);
|
||||
graphResources = std::move(rhs.graphResources);
|
||||
resourceManager = std::move(rhs.resourceManager);
|
||||
globalData = rhs.globalData;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
@ -1086,7 +435,7 @@ namespace SHADE
|
|||
}
|
||||
}
|
||||
|
||||
nodes.emplace_back(resourceManager.Create<SHRenderGraphNode>(resourceManager, logicalDeviceHdl, swapchainHdl, std::move(resources), std::move(predecessors), &graphResources, globalData));
|
||||
nodes.emplace_back(resourceManager.Create<SHRenderGraphNode>(resourceManager, logicalDeviceHdl, swapchainHdl, std::move(resources), std::move(predecessors), &graphResources));
|
||||
nodeIndexing.emplace(nodeName, static_cast<uint32_t>(nodes.size()) - 1u);
|
||||
return nodes.at(nodeIndexing[nodeName]);
|
||||
}
|
||||
|
@ -1114,20 +463,20 @@ namespace SHADE
|
|||
|
||||
// TODO: The graph scope buffers were meant to bind vertex buffers and index buffers for meshes. Find a
|
||||
// better way to manage these
|
||||
void SHRenderGraph::Execute(uint32_t frameIndex, Handle<SHVkCommandBuffer> cmdBuffer) noexcept
|
||||
void SHRenderGraph::Execute(uint32_t frameIndex, Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHVkDescriptorPool> descPool) noexcept
|
||||
{
|
||||
// TODO: DON'T HARDCODE THIS
|
||||
cmdBuffer->SetViewportScissor(1920.0f, 1080.0f, 1920, 1080);
|
||||
|
||||
for (auto& node : nodes)
|
||||
node->Execute(cmdBuffer, frameIndex);
|
||||
node->Execute(cmdBuffer, descPool, frameIndex);
|
||||
}
|
||||
|
||||
void SHRenderGraph::FinaliseBatch(uint32_t frameIndex)
|
||||
void SHRenderGraph::FinaliseBatch(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool)
|
||||
{
|
||||
for (auto& node : nodes)
|
||||
{
|
||||
node->FinaliseBatch(frameIndex);
|
||||
node->FinaliseBatch(frameIndex, descPool);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,12 @@
|
|||
#include "Graphics/MiddleEnd/Pipeline/SHPipelineLibrary.h"
|
||||
#include "Graphics/MiddleEnd/Batching/SHSuperBatch.h"
|
||||
#include "../MiddleEnd/Batching/SHBatcher.h"
|
||||
#include "SHRenderGraphNode.h"
|
||||
#include "SHSubpass.h"
|
||||
#include "SHRenderGraphResource.h"
|
||||
#include "SHRenderGraphNode.h"
|
||||
#include "SHSubpass.h"
|
||||
#include "SHAttachmentDescriptionType.h"
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
@ -24,223 +30,6 @@ namespace SHADE
|
|||
class SHRenderGraphNode;
|
||||
class SHGraphicsGlobalData;
|
||||
|
||||
// Used for attachment description creation for renderpass node
|
||||
enum class SH_ATT_DESC_TYPE
|
||||
{
|
||||
COLOR,
|
||||
COLOR_PRESENT,
|
||||
DEPTH,
|
||||
STENCIL,
|
||||
DEPTH_STENCIL,
|
||||
};
|
||||
|
||||
|
||||
class SH_API SHRenderGraphResource
|
||||
{
|
||||
private:
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* PRIVATE MEMBER VARIABLES */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
//! Name of the resource
|
||||
std::string resourceName;
|
||||
|
||||
//! Used for initializing image layouts
|
||||
SH_ATT_DESC_TYPE resourceType;
|
||||
|
||||
//! The resource itself (this is a vector because if the resource happens
|
||||
//! to be a swapchain image, then we need however many frames in flight).
|
||||
//! However when it's not a swapchain image, we want this container to be size 1
|
||||
//! because writing to these images will not interfere with images in the previous
|
||||
//! frame, unlike the swapchain image.
|
||||
std::vector<Handle<SHVkImage>> images;
|
||||
|
||||
//! Views to resources (vector because same rationale as images. see above).
|
||||
std::vector<Handle<SHVkImageView>> imageViews;
|
||||
|
||||
//! Image format
|
||||
vk::Format resourceFormat;
|
||||
|
||||
//! width of the resource
|
||||
uint32_t width;
|
||||
|
||||
//! Height of the resource
|
||||
uint32_t height;
|
||||
|
||||
//! Number of mipmap levels
|
||||
uint8_t mipLevels;
|
||||
public:
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* CTORS AND DTORS */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
SHRenderGraphResource(Handle<SHVkLogicalDevice> const& logicalDevice, Handle<SHVkSwapchain> const& swapchain, std::string const& name, SH_ATT_DESC_TYPE type, vk::Format format, uint32_t w, uint32_t h, uint8_t levels, vk::ImageCreateFlagBits createFlags) noexcept;
|
||||
SHRenderGraphResource(SHRenderGraphResource&& rhs) noexcept;
|
||||
SHRenderGraphResource& operator=(SHRenderGraphResource&& rhs) noexcept;
|
||||
~SHRenderGraphResource(void) noexcept;
|
||||
|
||||
friend class SHRenderGraphNode;
|
||||
friend class SHRenderGraph;
|
||||
};
|
||||
|
||||
|
||||
class SH_API SHSubpass : public ISelfHandle<SHSubpass>
|
||||
{
|
||||
private:
|
||||
/*---------------------------------------------------------------------*/
|
||||
/* PRIVATE MEMBER VARIABLES */
|
||||
/*---------------------------------------------------------------------*/
|
||||
//! The index of the subpass in the render graph
|
||||
uint32_t subpassIndex;
|
||||
|
||||
//! The parent renderpass that this subpass belongs to
|
||||
Handle<SHRenderGraphNode> parentNode;
|
||||
|
||||
//!
|
||||
Handle<SHSuperBatch> superBatch;
|
||||
|
||||
//! Color attachments
|
||||
std::vector<vk::AttachmentReference> colorReferences;
|
||||
|
||||
//! Depth attachments
|
||||
std::vector<vk::AttachmentReference> depthReferences;
|
||||
|
||||
//! Input attachments
|
||||
std::vector<vk::AttachmentReference> inputReferences;
|
||||
|
||||
//! For getting attachment reference indices using handles
|
||||
std::unordered_map<uint64_t, uint32_t> const* resourceAttachmentMapping;
|
||||
|
||||
//! Pointer to resources in the render graph (for getting handle IDs)
|
||||
std::unordered_map<std::string, Handle<SHRenderGraphResource>> const* ptrToResources;
|
||||
|
||||
//! 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.
|
||||
//! For these entities we want to link a function from the outside and draw them
|
||||
//! after we draw everything from the batch. Because of this, these draw calls
|
||||
//! are always the last things drawn, so DO NOT USE THIS FUNCTIONALITY FOR ANYTHING
|
||||
//! COMPLEX.
|
||||
std::vector<std::function<void(Handle<SHVkCommandBuffer>&)>> exteriorDrawCalls;
|
||||
|
||||
public:
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* CTORS AND DTORS */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
SHSubpass(ResourceManager& rm, 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(SHSubpass&& rhs) noexcept;
|
||||
SHSubpass& operator=(SHSubpass&& rhs) noexcept;
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* PUBLIC MEMBER FUNCTIONS */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
// Preparation functions
|
||||
void AddColorOutput(std::string resourceToReference) noexcept;
|
||||
void AddDepthOutput(std::string resourceToReference, SH_ATT_DESC_TYPE attachmentDescriptionType = SH_ATT_DESC_TYPE::DEPTH_STENCIL) noexcept;
|
||||
void AddInput(std::string resourceToReference) noexcept;
|
||||
|
||||
// Runtime functions
|
||||
void Execute(Handle<SHVkCommandBuffer>& commandBuffer, uint32_t frameIndex) noexcept;
|
||||
void AddExteriorDrawCalls(std::function<void(Handle<SHVkCommandBuffer>&)> const& newDrawCall) noexcept;
|
||||
|
||||
void Init (ResourceManager& resourceManager) noexcept;
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* GETTERS AND SETTERS */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
Handle<SHRenderGraphNode> const& GetParentNode(void) const noexcept;
|
||||
SHSubPassIndex GetIndex() const noexcept;
|
||||
Handle<SHSuperBatch> GetSuperBatch (void) const noexcept;
|
||||
|
||||
|
||||
friend class SHRenderGraphNode;
|
||||
friend class SHRenderGraph;
|
||||
};
|
||||
|
||||
class SH_API SHRenderGraphNode : public ISelfHandle<SHRenderGraphNode>
|
||||
{
|
||||
private:
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* PRIVATE MEMBER VARIABLES */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
ResourceManager& resourceManager;
|
||||
|
||||
//! For Vulkan object creation
|
||||
Handle<SHVkLogicalDevice> logicalDeviceHdl;
|
||||
|
||||
//! Each node will have a renderpass and each renderpass will have its own subpasses.
|
||||
//! These subpasses will execute sequentially.
|
||||
Handle<SHVkRenderpass> renderpass;
|
||||
|
||||
//! Framebuffers used in this renderpass. If renderpass contains usage of a swapchain image
|
||||
//! used for presenting, then we cannot use just 1 framebuffer, we need to have 1 for however many frames in flight.
|
||||
std::vector<Handle<SHVkFramebuffer>> framebuffers;
|
||||
|
||||
//! Nodes that must finish execution before this node is executed will be in this container
|
||||
std::vector<Handle<SHRenderGraphNode>> prereqNodes;
|
||||
|
||||
//! Container of Attachment descriptions
|
||||
std::vector<vk::AttachmentDescription> attachmentDescriptions;
|
||||
|
||||
//! Resources used in this renderpass
|
||||
std::vector<Handle<SHRenderGraphResource>> attResources;
|
||||
|
||||
//! Vector of subpasses
|
||||
std::vector<Handle<SHSubpass>> subpasses;
|
||||
|
||||
//! Descriptions to pass to renderpass for renderpass creation. We want to keep this here because
|
||||
std::vector<vk::SubpassDescription> spDescs;
|
||||
|
||||
//! Subpass dependencies for renderpass creation
|
||||
std::vector<vk::SubpassDependency> spDeps;
|
||||
|
||||
//! For indexing resources fast
|
||||
std::unordered_map<uint64_t, uint32_t> resourceAttachmentMapping;
|
||||
|
||||
//! For indexing subpasses
|
||||
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
|
||||
SHPipelineLibrary pipelineLibrary;
|
||||
|
||||
//! Whether or not the node has finished execution
|
||||
bool executed;
|
||||
|
||||
//! Whether or not the node has been configured already or not
|
||||
bool configured;
|
||||
|
||||
SHBatcher batcher;
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* PRIVATE MEMBER FUNCTIONS */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
void CreateRenderpass (void) noexcept;
|
||||
void CreateFramebuffer(void) noexcept;
|
||||
|
||||
public:
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* CTORS AND DTORS */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
SHRenderGraphNode (ResourceManager& rm, Handle<SHVkLogicalDevice> const& logicalDevice, Handle<SHVkSwapchain> const& swapchain, std::vector<Handle<SHRenderGraphResource>> attRes, std::vector<Handle<SHRenderGraphNode>> predecessors, std::unordered_map<std::string, Handle<SHRenderGraphResource>> const* resources, Handle<SHGraphicsGlobalData> globalData) noexcept;
|
||||
SHRenderGraphNode(SHRenderGraphNode&& rhs) noexcept;
|
||||
SHRenderGraphNode& operator= (SHRenderGraphNode&& rhs) noexcept;
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* PUBLIC MEMBER FUNCTIONS */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
Handle<SHSubpass> AddSubpass (std::string subpassName) noexcept;
|
||||
// TODO: RemoveSubpass()
|
||||
void Execute (Handle<SHVkCommandBuffer>& commandBuffer, uint32_t frameIndex) noexcept;
|
||||
Handle<SHVkPipeline> GetOrCreatePipeline (std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair, Handle<SHSubpass> subpass) noexcept;
|
||||
void FinaliseBatch(uint32_t frameIndex);
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* SETTERS AND GETTERS */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
Handle<SHVkRenderpass> GetRenderpass (void) const noexcept;
|
||||
Handle<SHSubpass> GetSubpass(std::string_view subpassName) const noexcept;
|
||||
friend class SHRenderGraph;
|
||||
};
|
||||
|
||||
class SH_API SHRenderGraph
|
||||
{
|
||||
|
@ -273,9 +62,6 @@ namespace SHADE
|
|||
//! Resource library for graph handles
|
||||
ResourceManager resourceManager;
|
||||
|
||||
//! Handle to global data
|
||||
Handle<SHGraphicsGlobalData> globalData;
|
||||
|
||||
public:
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* CTORS AND DTORS */
|
||||
|
@ -288,12 +74,12 @@ namespace SHADE
|
|||
/*-----------------------------------------------------------------------*/
|
||||
/* PUBLIC MEMBER FUNCTIONS */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
void Init (Handle<SHVkLogicalDevice> const& logicalDevice, Handle<SHVkSwapchain> const& swapchain, Handle<SHGraphicsGlobalData> inGlobalData) noexcept;
|
||||
void Init (Handle<SHVkLogicalDevice> const& logicalDevice, Handle<SHVkSwapchain> const& swapchain) noexcept;
|
||||
void AddResource (std::string resourceName, SH_ATT_DESC_TYPE type, 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::ImageCreateFlagBits createFlags = {});
|
||||
Handle<SHRenderGraphNode> AddNode (std::string nodeName, std::initializer_list<std::string> resourceNames, std::initializer_list<std::string> predecessorNodes) noexcept;
|
||||
void Generate (void) noexcept;
|
||||
void Execute (uint32_t frameIndex, Handle<SHVkCommandBuffer> cmdBuffer) noexcept;
|
||||
void FinaliseBatch(uint32_t frameIndex);
|
||||
void Execute (uint32_t frameIndex, Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHVkDescriptorPool> descPool) noexcept;
|
||||
void FinaliseBatch(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool);
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* SETTERS AND GETTERS */
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue