SP3-2 Cleaned Up Physics System #85

Merged
direnbharwani merged 11 commits from SP3-2-Physics into main 2022-10-13 18:32:25 +08:00
185 changed files with 8960 additions and 1977 deletions
Showing only changes of commit 5b4838c5b9 - Show all commits

BIN
Assets/Audio/Master.bank Normal file

Binary file not shown.

Binary file not shown.

BIN
Assets/Audio/footsteps.bank Normal file

Binary file not shown.

BIN
Assets/Cube.003.shmesh Normal file

Binary file not shown.

BIN
Assets/Cube.012.shmesh Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -19,10 +19,11 @@ echo "L - yamlcpp"
echo "M - SDL" echo "M - SDL"
echo "N - dotnet" echo "N - dotnet"
echo "O - tinyddsloader" echo "O - tinyddsloader"
echo "P - fmod"
echo --------------------------------------------------- echo ---------------------------------------------------
echo. echo.
choice /C ABCDEFGHIJKLMNO /T 10 /D A choice /C ABCDEFGHIJKLMNOP /T 10 /D A
set _e=%ERRORLEVEL% set _e=%ERRORLEVEL%
if %_e%==1 goto VMA if %_e%==1 goto VMA
@ -40,6 +41,7 @@ if %_e%==12 goto yamlcpp
if %_e%==13 goto SDL if %_e%==13 goto SDL
if %_e%==14 goto dotnet if %_e%==14 goto dotnet
if %_e%==15 goto tinyddsloader if %_e%==15 goto tinyddsloader
if %_e%==16 goto fmod
:VMA :VMA
echo -----------------------VMA---------------------------- echo -----------------------VMA----------------------------
@ -145,6 +147,12 @@ if %_e%==14 (goto :done) else (goto :tinyddsloader)
echo --------------------tinyddsloader------------------------- echo --------------------tinyddsloader-------------------------
rmdir "Dependencies/tinyddsloader" /S /Q rmdir "Dependencies/tinyddsloader" /S /Q
git clone https://github.com/SHADE-DP/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 :done
echo DONE! echo DONE!

View File

@ -15,3 +15,4 @@ IncludeDir["SDL"] = "%{wks.location}\\Dependencies\\SDL"
IncludeDir["VULKAN"] = "$(VULKAN_SDK)" IncludeDir["VULKAN"] = "$(VULKAN_SDK)"
IncludeDir["dotnet"] = "%{wks.location}\\Dependencies\\dotnet" IncludeDir["dotnet"] = "%{wks.location}\\Dependencies\\dotnet"
IncludeDir["tinyddsloader"] = "%{wks.location}\\Dependencies\\tinyddsloader" IncludeDir["tinyddsloader"] = "%{wks.location}\\Dependencies\\tinyddsloader"
IncludeDir["fmod"] = "%{wks.location}\\Dependencies\\fmod"

View File

@ -30,12 +30,14 @@ project "SHADE_Application"
externalincludedirs externalincludedirs
{ {
"%{IncludeDir.spdlog}/include", "%{IncludeDir.RTTR}\\include",
"%{IncludeDir.VULKAN}/include", "%{IncludeDir.fmod}/include",
"%{IncludeDir.VMA}/include", "%{IncludeDir.VULKAN}/Source/SPIRV-Reflect",
"%{IncludeDir.VULKAN}/Source/SPIRV-Reflect", "%{IncludeDir.VMA}/include",
"%{IncludeDir.RTTR}/include", "%{IncludeDir.VULKAN}/include",
"%{IncludeDir.tinyddsloader}" "%{IncludeDir.spdlog}/include",
"%{IncludeDir.tinyddsloader}",
"%{IncludeDir.reactphysics3d}\\include"
} }
externalwarnings "Off" externalwarnings "Off"
@ -56,7 +58,7 @@ project "SHADE_Application"
libdirs libdirs
{ {
"%{IncludeDir.spdlog}/lib", "%{IncludeDir.spdlog}/lib",
"%{IncludeDir.SDL}/lib", "%{IncludeDir.SDL}/lib"
} }
defines defines
@ -66,9 +68,16 @@ project "SHADE_Application"
disablewarnings disablewarnings
{ {
"4251" "4251",
"26812",
"26439",
"26451",
"26437",
"4275"
} }
linkoptions { "-IGNORE:4006" }
warnings 'Extra' warnings 'Extra'
filter "configurations:Debug" filter "configurations:Debug"
@ -81,4 +90,4 @@ project "SHADE_Application"
filter "configurations:Publish" filter "configurations:Publish"
optimize "On" optimize "On"
defines{"_RELEASE"} defines{"_RELEASE", "_PUBLISH"}

View File

@ -14,22 +14,34 @@
#include <chrono> #include <chrono>
#include <ratio> #include <ratio>
#include <ctime> #include <ctime>
#define SDL_HINT_VIDEO_FOREIGN_WINDOW_VULKAN 1
#include <SDL.h> #include <SDL.h>
#include "Scripting/SHScriptEngine.h"
#include "Graphics/MiddleEnd/Meshes/SHPrimitiveGenerator.h"
#include "ECS_Base/Managers/SHEntityManager.h"
#include "Graphics/MiddleEnd/Interface/SHRenderable.h"
#include "Scene/SHSceneManager.h"
#include "Math/Transform/SHTransformSystem.h"
#include "Input/SHInputManagerSystem.h"
#include "Scenes/SBTestScene.h" #include "Graphics/MiddleEnd/Meshes/SHPrimitiveGenerator.h"
// Managers
#include "ECS_Base/Managers/SHEntityManager.h"
#include "Scene/SHSceneManager.h"
// Systems
#include "Scripting/SHScriptEngine.h"
#include "Physics/SHPhysicsSystem.h"
#include "Math/Transform/SHTransformSystem.h"
#include "Input/SHInputManager.h"
#include "FRC/SHFramerateController.h"
#include "AudioSystem/SHAudioSystem.h"
// Components
#include "Graphics/MiddleEnd/Interface/SHRenderable.h"
#include "Math/Transform/SHTransformComponent.h" #include "Math/Transform/SHTransformComponent.h"
#include "Scenes/SBTestScene.h"
#include "Assets/SHAssetManager.h" #include "Assets/SHAssetManager.h"
#include "Tools/SHLogger.h"
using namespace SHADE; using namespace SHADE;
namespace Sandbox namespace Sandbox
@ -51,10 +63,10 @@ namespace Sandbox
// Create Systems // Create Systems
SHADE::SHSystemManager::CreateSystem<SHADE::SHGraphicsSystem>(); SHADE::SHSystemManager::CreateSystem<SHADE::SHGraphicsSystem>();
SHADE::SHSystemManager::CreateSystem<SHADE::SHScriptEngine>(); SHADE::SHSystemManager::CreateSystem<SHADE::SHScriptEngine>();
// TODO(Diren): Create Physics System here SHADE::SHSystemManager::CreateSystem<SHADE::SHPhysicsSystem>();
SHADE::SHSystemManager::CreateSystem<SHADE::SHTransformSystem>(); SHADE::SHSystemManager::CreateSystem<SHADE::SHTransformSystem>();
SHADE::SHGraphicsSystem* graphicsSystem = static_cast<SHADE::SHGraphicsSystem*>(SHADE::SHSystemManager::GetSystem<SHADE::SHGraphicsSystem>()); SHADE::SHGraphicsSystem* graphicsSystem = static_cast<SHADE::SHGraphicsSystem*>(SHADE::SHSystemManager::GetSystem<SHADE::SHGraphicsSystem>());
SHADE::SHSystemManager::CreateSystem<SHADE::SHInputManagerSystem>(); SHADE::SHSystemManager::CreateSystem<SHADE::SHAudioSystem>();
// Create Routines // Create Routines
SHADE::SHSystemManager::RegisterRoutine<SHADE::SHScriptEngine, SHADE::SHScriptEngine::FrameSetUpRoutine>(); SHADE::SHSystemManager::RegisterRoutine<SHADE::SHScriptEngine, SHADE::SHScriptEngine::FrameSetUpRoutine>();
@ -62,27 +74,37 @@ namespace Sandbox
SHADE::SHSystemManager::RegisterRoutine<SHADE::SHScriptEngine, SHADE::SHScriptEngine::LateUpdateRoutine>(); SHADE::SHSystemManager::RegisterRoutine<SHADE::SHScriptEngine, SHADE::SHScriptEngine::LateUpdateRoutine>();
SHADE::SHSystemManager::RegisterRoutine<SHADE::SHScriptEngine, SHADE::SHScriptEngine::FrameCleanUpRoutine>(); SHADE::SHSystemManager::RegisterRoutine<SHADE::SHScriptEngine, SHADE::SHScriptEngine::FrameCleanUpRoutine>();
// TODO(Diren): Register Physics System & Routines here SHADE::SHSystemManager::RegisterRoutine<SHADE::SHPhysicsSystem, SHADE::SHPhysicsSystem::PhysicsPreUpdate>();
SHADE::SHSystemManager::RegisterRoutine<SHADE::SHPhysicsSystem, SHADE::SHPhysicsSystem::PhysicsFixedUpdate>();
SHADE::SHSystemManager::RegisterRoutine<SHADE::SHPhysicsSystem, SHADE::SHPhysicsSystem::PhysicsPostUpdate>();
SHADE::SHSystemManager::RegisterRoutine<SHADE::SHTransformSystem, SHADE::SHTransformSystem::TransformUpdateRoutine>(); SHADE::SHSystemManager::RegisterRoutine<SHADE::SHTransformSystem, SHADE::SHTransformSystem::TransformUpdateRoutine>();
SHADE::SHComponentManager::CreateComponentSparseSet<SHADE::SHTransformComponent>();
SHADE::SHSystemManager::RegisterRoutine<SHADE::SHGraphicsSystem, SHADE::SHGraphicsSystem::BatcherDispatcherRoutine>(); SHADE::SHSystemManager::RegisterRoutine<SHADE::SHGraphicsSystem, SHADE::SHGraphicsSystem::BatcherDispatcherRoutine>();
SHADE::SHSystemManager::RegisterRoutine<SHADE::SHGraphicsSystem, SHADE::SHGraphicsSystem::BeginRoutine>(); SHADE::SHSystemManager::RegisterRoutine<SHADE::SHGraphicsSystem, SHADE::SHGraphicsSystem::BeginRoutine>();
SHADE::SHSystemManager::RegisterRoutine<SHADE::SHGraphicsSystem, SHADE::SHGraphicsSystem::RenderRoutine>(); SHADE::SHSystemManager::RegisterRoutine<SHADE::SHGraphicsSystem, SHADE::SHGraphicsSystem::RenderRoutine>();
SHADE::SHSystemManager::RegisterRoutine<SHADE::SHGraphicsSystem, SHADE::SHGraphicsSystem::EndRoutine>(); SHADE::SHSystemManager::RegisterRoutine<SHADE::SHGraphicsSystem, SHADE::SHGraphicsSystem::EndRoutine>();
SHADE::SHComponentManager::CreateComponentSparseSet<SHADE::SHRenderable>(); SHADE::SHComponentManager::CreateComponentSparseSet<SHADE::SHRigidBodyComponent>();
SHADE::SHComponentManager::CreateComponentSparseSet<SHADE::SHColliderComponent>();
SHADE::SHComponentManager::CreateComponentSparseSet<SHADE::SHTransformComponent>(); SHADE::SHComponentManager::CreateComponentSparseSet<SHADE::SHTransformComponent>();
SHADE::SHComponentManager::CreateComponentSparseSet<SHADE::SHRenderable>();
SHADE::SHSystemManager::RegisterRoutine<SHADE::SHInputManagerSystem, SHADE::SHInputManagerSystem::InputManagerRoutine>();
//TODO: REMOVE AFTER PRESENTATION //TODO: REMOVE AFTER PRESENTATION
SHADE::SHAssetManager::LoadDataTemp("../../Assets/racoon.gltf"); //SHADE::SHAssetManager::LoadDataTemp("../../Assets/racoon.gltf");
SHADE::SHAssetManager::LoadDataTemp("../../Assets/RaccoonBag_Color_Ver4.dds"); SHADE::SHAssetManager::LoadDataTemp("../../Assets/Cube.012.shmesh");
SHADE::SHAssetManager::LoadDataTemp("../../Assets/RaccoonPreTexturedVer1_Base9.dds"); //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
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 // Set up graphics system and windows
graphicsSystem->SetWindow(&window); graphicsSystem->SetWindow(&window);
@ -94,7 +116,10 @@ namespace Sandbox
#else #else
#endif #endif
SHSceneManager::InitSceneManager<SBTestScene>("TestScene"); SHSceneManager::InitSceneManager<SBTestScene>("TestScene");
SHFrameRateController::UpdateFRC();
} }
void SBApplication::Update(void) void SBApplication::Update(void)
@ -103,6 +128,8 @@ namespace Sandbox
//TODO: Change true to window is open //TODO: Change true to window is open
while (!window.WindowShouldClose()) while (!window.WindowShouldClose())
{ {
SHFrameRateController::UpdateFRC();
SHInputManager::UpdateInput(SHFrameRateController::GetRawDeltaTime());
SHSceneManager::UpdateSceneManager(); SHSceneManager::UpdateSceneManager();
SHSceneManager::SceneUpdate(1/60.0f); SHSceneManager::SceneUpdate(1/60.0f);
//#ifdef SHEDITOR //#ifdef SHEDITOR
@ -118,6 +145,9 @@ namespace Sandbox
SHADE::SHSystemManager::RunRoutines(false, 0.016f); SHADE::SHSystemManager::RunRoutines(false, 0.016f);
} }
// Finish all graphics jobs first
graphicsSystem->AwaitGraphicsExecution();
} }

View File

@ -9,6 +9,9 @@
#include "Graphics/MiddleEnd/Interface/SHGraphicsSystem.h" #include "Graphics/MiddleEnd/Interface/SHGraphicsSystem.h"
#include "Scripting/SHScriptEngine.h" #include "Scripting/SHScriptEngine.h"
#include "Math/Transform/SHTransformComponent.h" #include "Math/Transform/SHTransformComponent.h"
#include "Graphics/MiddleEnd/Interface/SHMaterialInstance.h"
#include "Physics/Components/SHRigidBodyComponent.h"
#include "Physics/Components/SHColliderComponent.h"
#include "Assets/SHAssetManager.h" #include "Assets/SHAssetManager.h"
@ -17,9 +20,9 @@ using namespace SHADE;
namespace Sandbox namespace Sandbox
{ {
void SBTestScene::WindowFocusFunc([[maybe_unused]]void* window, int focused) void SBTestScene::WindowFocusFunc([[maybe_unused]] void* window, int focused)
{ {
if(focused) if (focused)
{ {
} }
else else
@ -35,99 +38,156 @@ namespace Sandbox
SHADE::SHGraphicsSystem* graphicsSystem = static_cast<SHADE::SHGraphicsSystem*>(SHADE::SHSystemManager::GetSystem<SHADE::SHGraphicsSystem>()); SHADE::SHGraphicsSystem* graphicsSystem = static_cast<SHADE::SHGraphicsSystem*>(SHADE::SHSystemManager::GetSystem<SHADE::SHGraphicsSystem>());
// Create temp meshes // Create temp meshes
const auto CUBE_MESH = SHADE::SHPrimitiveGenerator::Cube(*graphicsSystem); const auto CUBE_MESH = SHADE::SHPrimitiveGenerator::Cube(*graphicsSystem);
//graphicsSystem->BuildMeshBuffers();
//Test Racoon mesh //Test Racoon mesh
auto meshes = SHADE::SHAssetManager::GetAllMeshes(); auto meshes = SHADE::SHAssetManager::GetAllMeshes();
std::vector<Handle<SHMesh>> handles; std::vector<Handle<SHMesh>> handles;
for (auto const& mesh : meshes) for (auto const& mesh : meshes)
{ {
if (mesh.meshName == "Cube.012") if (mesh.header.meshName == "Cube.012")
{ {
handles.push_back(graphicsSystem->AddMesh( handles.push_back(graphicsSystem->AddMesh(
mesh.header.vertexCount, mesh.header.vertexCount,
mesh.vertexPosition.data(), mesh.vertexPosition.data(),
mesh.texCoords.data(), mesh.texCoords.data(),
mesh.vertexTangent.data(), mesh.vertexTangent.data(),
mesh.vertexNormal.data(), mesh.vertexNormal.data(),
mesh.header.indexCount, mesh.header.indexCount,
mesh.indices.data() mesh.indices.data()
)); ));
} }
} }
graphicsSystem->BuildMeshBuffers(); graphicsSystem->BuildMeshBuffers();
//Test Textures // Load Textures
auto textures{ SHADE::SHAssetManager::GetAllTextures() }; 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 // Create Materials
auto matInst = graphicsSystem->AddOrGetBaseMaterialInstance(); 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 // Create Stress Test Objects
static const SHVec3 TEST_OBJ_SCALE = { 0.2f, 0.2f, 0.2f }; static const SHVec3 TEST_OBJ_SCALE = SHVec3::One * 0.5f;
constexpr int NUM_ROWS = 1; constexpr int NUM_ROWS = 10;
constexpr int NUM_COLS = 1; constexpr int NUM_COLS = 10;
static const SHVec3 TEST_OBJ_SPACING = { 1.0f, 1.0f, 1.0f }; static const SHVec3 TEST_OBJ_SPACING = { 0.1f, 0.1f, 0.1f };
static const SHVec3 TEST_OBJ_START_POS = { - (NUM_COLS / 2 * TEST_OBJ_SPACING.x ), 0.0f, 0.0f }; static const SHVec3 TEST_OBJ_START_POS = { -(NUM_COLS / 2 * TEST_OBJ_SPACING.x) + 1.0f, -2.0f, -1.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(); for (int y = 0; y < NUM_ROWS; ++y)
// renderable.SetMaterial(matInst); for (int x = 0; x < NUM_COLS; ++x)
{
// // Set initial positions auto entity = SHEntityManager::CreateEntity<SHRenderable, SHTransformComponent, SHRigidBodyComponent, SHColliderComponent>();
// 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);
//}
auto entity = SHEntityManager::CreateEntity<SHRenderable, SHTransformComponent>();
auto& renderable = *SHComponentManager::GetComponent_s<SHRenderable>(entity); auto& renderable = *SHComponentManager::GetComponent_s<SHRenderable>(entity);
auto& transform = *SHComponentManager::GetComponent_s<SHTransformComponent>(entity); auto& transform = *SHComponentManager::GetComponent_s<SHTransformComponent>(entity);
auto& collider = *SHComponentManager::GetComponent_s<SHColliderComponent>(entity);
renderable.Mesh = handles.front(); //renderable.Mesh = handles.front();
renderable.SetMaterial(matInst); renderable.Mesh = CUBE_MESH;
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, SHMath::GenerateRandomNumber(-3.5f, -5.0f)});
//transform.SetWorldPosition({-1.0f, -1.0f, -1.0f});
transform.SetWorldRotation(SHMath::GenerateRandomNumber(), SHMath::GenerateRandomNumber(), SHMath::GenerateRandomNumber());
transform.SetWorldScale(TEST_OBJ_SCALE);
auto* box = collider.AddBoundingBox();
box->SetHalfExtents(transform.GetWorldScale() * 0.5f);
stressTestObjects.emplace_back(entity); 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 floor = SHEntityManager::CreateEntity<SHRenderable, SHTransformComponent, SHRigidBodyComponent, SHColliderComponent>();
auto& floorRenderable = *SHComponentManager::GetComponent_s<SHRenderable>(floor);
auto& floorTransform = *SHComponentManager::GetComponent_s<SHTransformComponent>(floor);
auto& floorRigidBody = *SHComponentManager::GetComponent_s<SHRigidBodyComponent>(floor);
auto& floorCollider = *SHComponentManager::GetComponent_s<SHColliderComponent>(floor);
floorRenderable.Mesh = CUBE_MESH;
floorRenderable.SetMaterial(customMat);
floorRenderable.GetModifiableMaterial()->SetProperty("data.color", SHVec4(1.0f, 1.0f, 1.0f, 1.0f));
floorTransform.SetWorldScale({7.5f, 0.5f, 7.5});
floorTransform.SetWorldPosition({0.0f, -3.0f, -5.0f});
floorRigidBody.SetType(SHRigidBodyComponent::Type::STATIC);
auto* floorBox = floorCollider.AddBoundingBox();
floorBox->SetHalfExtents(floorTransform.GetWorldScale() * 0.5f);
// Create blank entity with a script // Create blank entity with a script
testObj = SHADE::SHEntityManager::CreateEntity(); //testObj = SHADE::SHEntityManager::CreateEntity<SHRenderable, SHTransformComponent>();
//auto& testObjRenderable = *SHComponentManager::GetComponent<SHRenderable>(testObj);
//testObjRenderable.Mesh = CUBE_MESH;
//testObjRenderable.SetMaterial(matInst);
SHADE::SHScriptEngine* scriptEngine = static_cast<SHADE::SHScriptEngine*>(SHADE::SHSystemManager::GetSystem<SHADE::SHScriptEngine>()); 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) 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); //transform.SetWorldPosition({1.0f, 1.0f, -1.0f});
rotation += dt * 10.0f;*/ //transform.SetWorldRotation(0.0f, 0.0f + rotation, 0.0f);
/*static float rotation = 0.0f; //rotation += dt * 0.2f;
auto& transform = *SHADE::SHComponentManager::GetComponent_s<SHADE::SHTransformComponent>(stressTestObjects[0]);
transform.SetWorldPosition({rotation, 0.0f, 0.0f});
rotation += dt * 10.0f;*/
// Destroy entity if space is pressed // Destroy entity if space is pressed
if (GetKeyState(VK_SPACE) & 0x8000) if (GetKeyState(VK_SPACE) & 0x8000)
{ {
SHADE::SHScriptEngine* scriptEngine = static_cast<SHADE::SHScriptEngine*>(SHADE::SHSystemManager::GetSystem<SHADE::SHScriptEngine>()); rotation = 0.0f;
scriptEngine->RemoveAllScripts(testObj); SHADE::SHScriptEngine* scriptEngine = static_cast<SHADE::SHScriptEngine*>(SHADE::SHSystemManager::GetSystem<SHADE::SHScriptEngine>());
scriptEngine->RemoveAllScripts(testObj);
} }
} }
void SBTestScene::Render() void SBTestScene::Render()
{ {
} }
void SBTestScene::Unload() void SBTestScene::Unload()
@ -138,8 +198,4 @@ namespace Sandbox
{ {
//SHSerialization::SerializeScene("resources/scenes/Scene01.SHADE"); //SHSerialization::SerializeScene("resources/scenes/Scene01.SHADE");
} }
} }

View File

@ -42,7 +42,8 @@ project "SHADE_Engine"
"%{IncludeDir.VULKAN}\\include", "%{IncludeDir.VULKAN}\\include",
"%{IncludeDir.VULKAN}\\Source\\SPIRV-Reflect", "%{IncludeDir.VULKAN}\\Source\\SPIRV-Reflect",
"%{IncludeDir.dotnet}\\include", "%{IncludeDir.dotnet}\\include",
"%{IncludeDir.tinyddsloader}" "%{IncludeDir.tinyddsloader}",
"%{IncludeDir.fmod}\\include"
} }
externalwarnings "Off" externalwarnings "Off"
@ -55,7 +56,8 @@ project "SHADE_Engine"
"%{IncludeDir.assimp}/lib/Release", "%{IncludeDir.assimp}/lib/Release",
"%{IncludeDir.RTTR}/lib", "%{IncludeDir.RTTR}/lib",
"%{IncludeDir.SDL}/lib", "%{IncludeDir.SDL}/lib",
"%{IncludeDir.spdlog}/lib" "%{IncludeDir.spdlog}/lib",
"%{IncludeDir.fmod}/lib"
} }
links links
@ -74,9 +76,16 @@ project "SHADE_Engine"
disablewarnings disablewarnings
{ {
"4251" "4251",
"26812",
"26439",
"26451",
"26437",
"4275"
} }
linkoptions { "-IGNORE:4006" }
defines defines
{ {
"_LIB", "_LIB",
@ -108,9 +117,30 @@ project "SHADE_Engine"
} }
filter "configurations:Debug" 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" 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)\""} postbuildcommands {"xcopy /r /y /q \"%{IncludeDir.assimp}\\bin\\Release\\assimp-vc142-mt.dll\" \"$(OutDir)\""}
warnings 'Extra' warnings 'Extra'
@ -119,22 +149,22 @@ project "SHADE_Engine"
symbols "On" symbols "On"
defines {"_DEBUG", "SHEDITOR"} defines {"_DEBUG", "SHEDITOR"}
links{"assimp-vc142-mtd.lib", "librttr_core_d.lib", "spdlogd.lib"} 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" filter "configurations:Release"
optimize "On" optimize "On"
defines{"_RELEASE", "SHEDITOR"} defines{"_RELEASE", "SHEDITOR"}
links{"assimp-vc142-mt.lib", "librttr_core.lib", "spdlog.lib"} 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" filter "configurations:Publish"
optimize "On" optimize "On"
defines{"_RELEASE"} defines{"_RELEASE", "_PUBLISH"}
links{"assimp-vc142-mt.lib", "librttr_core.lib", "spdlog.lib"} links{"assimp-vc142-mt.lib", "librttr_core.lib", "spdlog.lib"}
excludes excludes
{ {
"%{prj.location}/src/Editor/**.cpp", -- "%{prj.location}/src/Editor/**.cpp",
"%{prj.location}/src/Editor/**.h", -- "%{prj.location}/src/Editor/**.h",
"%{prj.location}/src/Editor/**.hpp", -- "%{prj.location}/src/Editor/**.hpp",
} }
--links{"fmodstudio_vc.lib", "fmod_vc.lib"} links{"fmodstudio_vc.lib", "fmod_vc.lib"}

View File

@ -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 #pragma once
#include <vector> #include <vector>
#include "Math/SHMath.h" #include "Math/SHMath.h"
#include "SH_API.h"
namespace SHADE namespace SHADE
{ {
struct SHMeshAssetHeader struct SH_API SHMeshAssetHeader
{ {
uint32_t vertexCount; uint32_t vertexCount;
uint32_t indexCount; uint32_t indexCount;
std::string meshName;
}; };
struct SHMeshAsset struct SH_API SHMeshAsset
{ {
bool compiled; bool compiled;
bool changed; bool changed;
SHMeshAssetHeader header; SHMeshAssetHeader header;
std::string meshName;
std::vector<SHVec3> vertexPosition; std::vector<SHVec3> vertexPosition;
std::vector<SHVec3> vertexTangent; std::vector<SHVec3> vertexTangent;
std::vector<SHVec3> vertexNormal; std::vector<SHVec3> vertexNormal;

View File

@ -1,15 +1,14 @@
#pragma once #pragma once
#include "tinyddsloader.h" #include "tinyddsloader.h"
#include "Graphics/MiddleEnd/Textures/SHTextureLibrary.h" #include "Graphics/MiddleEnd/Textures/SHTextureLibrary.h"
#include <memory>
namespace SHADE namespace SHADE
{ {
struct SHTextureAsset struct SHTextureAsset
{ {
bool compiled;
uint32_t numBytes; uint32_t numBytes;
uint32_t width; uint32_t width;
uint32_t height; uint32_t height;
@ -18,7 +17,8 @@ namespace SHADE
SHTexture::PixelChannel const * pixelData; SHTexture::PixelChannel const * pixelData;
SHTextureAsset() SHTextureAsset()
: numBytes{ 0 }, : compiled{ false },
numBytes{ 0 },
width{ 0 }, width{ 0 },
height{ 0 }, height{ 0 },
format{ SHTexture::TextureFormat::eUndefined }, format{ SHTexture::TextureFormat::eUndefined },
@ -26,7 +26,8 @@ namespace SHADE
{} {}
SHTextureAsset(SHTextureAsset const& rhs) SHTextureAsset(SHTextureAsset const& rhs)
: numBytes{ rhs.numBytes }, : compiled{ false },
numBytes{ rhs.numBytes },
width{ rhs.width }, width{ rhs.width },
height{ rhs.height }, height{ rhs.height },
format{ rhs.format }, format{ rhs.format },

View File

@ -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();
}

View File

@ -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;
};
}

View File

@ -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 "SHpch.h"
#include "SHMeshLoader.h" #include "SHMeshLoader.h"
#include <assimp/postprocess.h> #include <assimp/postprocess.h>
#include <fstream>
namespace SHADE namespace SHADE
{ {
Assimp::Importer SHMeshLoader::aiImporter; 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) 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; (void)scene;
SHMeshAsset result SHMeshAsset result
{ {
.compiled { false}, .compiled { false},
.changed { false }, .changed { false }
.meshName { mesh.mName.C_Str() }
}; };
for (size_t i{0}; i < mesh.mNumVertices; ++i) for (size_t i{0}; i < mesh.mNumVertices; ++i)
@ -79,36 +91,33 @@ namespace SHADE
} }
} }
result.header.vertexCount = result.vertexPosition.size(); result.header.vertexCount = static_cast<uint32_t>(result.vertexPosition.size());
result.header.indexCount = result.indices.size(); result.header.indexCount = static_cast<uint32_t>(result.indices.size());
result.header.meshName = mesh.mName.C_Str();
return result; 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(), const aiScene* scene = aiImporter.ReadFile(path.string().c_str(),
aiProcess_Triangulate aiProcess_Triangulate // Make sure we get triangles rather than nvert polygons
// Make sure we get triangles rather than nvert polygons | aiProcess_GenUVCoords // Convert any type of mapping to uv mapping
| aiProcess_GenUVCoords // Convert any type of mapping to uv mapping | aiProcess_TransformUVCoords // preprocess UV transformations (scaling, translation ...)
| aiProcess_TransformUVCoords | aiProcess_FindInstances // search for instanced meshes and remove them by references to one master
// preprocess UV transformations (scaling, translation ...) | aiProcess_CalcTangentSpace // calculate tangents and bitangents if possible
| aiProcess_FindInstances | aiProcess_JoinIdenticalVertices // join identical vertices/ optimize indexing
// search for instanced meshes and remove them by references to one master | aiProcess_RemoveRedundantMaterials // remove redundant materials
| aiProcess_CalcTangentSpace | aiProcess_FindInvalidData // detect invalid model data, such as invalid normal vectors
// calculate tangents and bitangents if possible | aiProcess_FlipUVs // flip the V to match the Vulkans way of doing UVs
| 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()) if (!scene || !scene->HasMeshes())
{ {
SHLOG_ERROR("ERROR in GLTF::ASSIMP: {}\nFile: {}", aiImporter.GetErrorString(), path.string()); SHLOG_ERROR("ERROR in GLTF::ASSIMP: {}\nFile: {}", aiImporter.GetErrorString(), path.string());
return false; return;
} }
//TODO MATERIALS FROM MESHES //TODO MATERIALS FROM MESHES
//if (scene->HasMaterials()) //if (scene->HasMaterials())
//{ //{
@ -116,14 +125,108 @@ namespace SHADE
// { // {
// if (scene->mMaterials[i]->mNumProperties > 0) // 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); 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);
} }
} }

View File

@ -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 #pragma once
#include <assimp/Importer.hpp> #include <assimp/Importer.hpp>
#include <assimp/scene.h> #include <assimp/scene.h>
@ -12,10 +23,14 @@ namespace SHADE
private: private:
static Assimp::Importer aiImporter; 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: public:
static bool LoadMesh(std::vector<SHMeshAsset>& meshes, AssetPath path); static void LoadMesh(std::vector<SHMeshAsset>& meshes, AssetPath path) noexcept;
}; };
} }

View File

@ -1,48 +0,0 @@
#include "SHpch.h"
#include "SHMeshWriter.h"
#include <fstream>
void SHADE::SHMeshWriter::WriteMeshBinary(SHMeshAsset const& asset, AssetPath path) noexcept
{
std::ofstream file{path, std::ios::out | std::ios::binary};
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.close();
}

View File

@ -1,14 +0,0 @@
#pragma once
#include "../Asset Types/SHMeshAsset.h"
#include "../SHAssetMacros.h"
namespace SHADE
{
class SHMeshWriter
{
private:
public:
static void WriteMeshBinary(SHMeshAsset const& asset, AssetPath path) noexcept;
};
}

View File

@ -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();
}
}

View File

@ -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);
};
}

View File

@ -1,3 +1,14 @@
/*************************************************************************//**
* \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 "SHpch.h"
#include "SHTextureLoader.h" #include "SHTextureLoader.h"
@ -58,7 +69,7 @@ namespace SHADE
} }
} }
void SHTextureLoader::LoadImageAsset(AssetPath path, SHTextureAsset& asset) void SHTextureLoader::LoadTinyDDS(AssetPath path, SHTextureAsset& asset) noexcept
{ {
tinyddsloader::Result loadResult = tinyddsloader::Result::Success; tinyddsloader::Result loadResult = tinyddsloader::Result::Success;
tinyddsloader::DDSFile file; tinyddsloader::DDSFile file;
@ -72,21 +83,64 @@ namespace SHADE
std::vector<uint32_t> mipOff(file.GetMipCount()); std::vector<uint32_t> mipOff(file.GetMipCount());
for (auto i{0}; i < file.GetMipCount(); ++i) for (size_t i{0}; i < file.GetMipCount(); ++i)
{ {
mipOff.push_back(totalBytes); mipOff[i] = static_cast<uint32_t>(totalBytes);
totalBytes += file.GetImageData(i, 0)->m_memSlicePitch; totalBytes += file.GetImageData(static_cast<uint32_t>(i), 0)->m_memSlicePitch;
} }
SHTexture::PixelChannel* pixel = new SHTexture::PixelChannel[totalBytes]; SHTexture::PixelChannel* pixel = new SHTexture::PixelChannel[totalBytes];
std::memcpy(pixel, file.GetDDSData(), totalBytes); std::memcpy(pixel, file.GetImageData()->m_mem, totalBytes);
//pixel = std::move(reinterpret_cast<SHTexture::PixelChannel const*>(file.GetDDSData())); //pixel = std::move(reinterpret_cast<SHTexture::PixelChannel const*>(file.GetDDSData()));
asset.numBytes = totalBytes; asset.compiled = false;
asset.numBytes = static_cast<uint32_t>(totalBytes);
asset.width = file.GetWidth(); asset.width = file.GetWidth();
asset.height = file.GetHeight(); asset.height = file.GetHeight();
asset.format = ddsLoaderToVkFormat(file.GetFormat(), true); asset.format = ddsLoaderToVkFormat(file.GetFormat(), true);
asset.mipOffsets = std::move(mipOff); asset.mipOffsets = std::move(mipOff);
asset.pixelData = std::move(pixel); 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);
}
}
} }

View File

@ -1,3 +1,14 @@
/*************************************************************************//**
* \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 #pragma once
#define TINYDDSLOADER_IMPLEMENTATION #define TINYDDSLOADER_IMPLEMENTATION
@ -13,6 +24,9 @@ namespace SHADE
static std::string TinyDDSResultToString(tinyddsloader::Result value); static std::string TinyDDSResultToString(tinyddsloader::Result value);
static vk::Format ddsLoaderToVkFormat(tinyddsloader::DDSFile::DXGIFormat format, bool isLinear); 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: public:
static void LoadImageAsset(AssetPath paths, SHTextureAsset& image); static void LoadImageAsset(AssetPath paths, SHTextureAsset& image);
}; };

View File

@ -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 #pragma once
#include "Filesystem/SHFileSystem.h" #include "Filesystem/SHFileSystem.h"

View File

@ -17,6 +17,9 @@
#include "Libraries/SHMeshLoader.h" #include "Libraries/SHMeshLoader.h"
#include "Libraries/SHTextureLoader.h" #include "Libraries/SHTextureLoader.h"
#include "Libraries/SHMeshCompiler.h"
#include "Libraries/SHTextureCompiler.h"
namespace SHADE namespace SHADE
{ {
FMOD::System* SHAssetManager::audioSystem; FMOD::System* SHAssetManager::audioSystem;
@ -69,12 +72,13 @@ namespace SHADE
AssetType type = SHAssetMetaHandler::GetTypeFromExtension(path.extension().string().c_str()); AssetType type = SHAssetMetaHandler::GetTypeFromExtension(path.extension().string().c_str());
std::string folder; std::string folder;
switch (type) //TODO Implement asset type generation
{ //switch (type)
default: //{
//TODO:ASSERT UNSUPPORTED FILE TYPE //default:
return std::filesystem::path(); // //TODO:ASSERT UNSUPPORTED FILE TYPE
} // return std::filesystem::path();
//}
return std::filesystem::path(ASSET_ROOT + folder + path.filename().string()); return std::filesystem::path(ASSET_ROOT + folder + path.filename().string());
} }
@ -105,12 +109,13 @@ namespace SHADE
meta.type = type; meta.type = type;
std::string folder; std::string folder;
switch (type) //TODO implement folder choosing
{ //switch (type)
default: //{
folder = ""; //default:
break; // folder = "";
} // break;
//}
AssetPath path{ ASSET_ROOT + folder + name + SHAssetMetaHandler::GetExtensionFromType(type) }; AssetPath path{ ASSET_ROOT + folder + name + SHAssetMetaHandler::GetExtensionFromType(type) };
SHAssetMetaHandler::WriteMetaData(meta); SHAssetMetaHandler::WriteMetaData(meta);
@ -199,7 +204,9 @@ namespace SHADE
{ {
AssetPath path{ p }; AssetPath path{ p };
if (path.extension().string() == GLTF_EXTENSION) if (path.extension().string() == FBX_EXTENSION
|| path.extension().string() == GLTF_EXTENSION
|| path.extension().string() == MESH_EXTENSION)
{ {
LoadGLTF( LoadGLTF(
{ {
@ -211,7 +218,8 @@ namespace SHADE
} }
); );
} }
else if (path.extension().string() == DDS_EXTENSION) else if (path.extension().string() == DDS_EXTENSION
|| path.extension().string() == TEXTURE_EXTENSION)
{ {
LoadDDS( LoadDDS(
{ {
@ -300,6 +308,11 @@ namespace SHADE
for (auto const& mesh : meshes) for (auto const& mesh : meshes)
{ {
meshCollection.emplace(GenerateAssetID(AssetType::MESH), mesh); meshCollection.emplace(GenerateAssetID(AssetType::MESH), mesh);
if (!mesh.compiled)
{
SHMeshCompiler::CompileMeshBinary(mesh, asset.path);
}
} }
} }
@ -310,6 +323,11 @@ namespace SHADE
SHTextureLoader::LoadImageAsset(asset.path, image); SHTextureLoader::LoadImageAsset(asset.path, image);
textureCollection.emplace(GenerateAssetID(AssetType::DDS), image); textureCollection.emplace(GenerateAssetID(AssetType::DDS), image);
if (!image.compiled)
{
SHTextureCompiler::CompileTextureBinary(image, asset.path);
}
} }
/**************************************************************************** /****************************************************************************

View File

@ -99,6 +99,7 @@ namespace SHADE
****************************************************************************/ ****************************************************************************/
void SHAssetMetaHandler::WriteMetaData(SHAsset const& meta) noexcept void SHAssetMetaHandler::WriteMetaData(SHAsset const& meta) noexcept
{ {
//TODO: Write into binary eventually
std::string path{ meta.path.string() }; std::string path{ meta.path.string() };
path.append(META_EXTENSION); path.append(META_EXTENSION);
@ -110,8 +111,20 @@ namespace SHADE
return; return;
} }
metaFile << "Name: " << meta.name << "\n";
metaFile << "ID: " << meta.id << "\n"; metaFile << "ID: " << meta.id << "\n";
metaFile << "Type: " << static_cast<int>(meta.type) << std::endl; 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:
break;
}
metaFile.close(); metaFile.close();
} }

View File

@ -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;
}
}

View File

@ -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

View File

@ -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);
}
}

View File

@ -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

View File

@ -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(double 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(), static_cast<int>(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)

View File

@ -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(double 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;
};
}

View File

@ -14,6 +14,7 @@
#include "SHpch.h" #include "SHpch.h"
#include "../SHECSMacros.h" #include "../SHECSMacros.h"
#include "SH_API.h" #include "SH_API.h"
#include "ECS_Base/General/SHFamily.h"
namespace SHADE namespace SHADE
{ {
@ -117,4 +118,7 @@ namespace SHADE
}; };
template class SH_API SHFamilyID<SHComponent>;
} }

View File

@ -0,0 +1,12 @@
#pragma once
#include "ECS_Base/Components/SHComponent.h"
namespace SHADE
{
struct SHComponentAddedEvent
{
EntityID eid;
ComponentTypeID addedComponentType;
};
}

View File

@ -0,0 +1,12 @@
#pragma once
#include "ECS_Base/Components/SHComponent.h"
namespace SHADE
{
struct SHComponentRemovedEvent
{
EntityID eid;
ComponentTypeID removedComponentType;
};
}

View File

@ -0,0 +1,14 @@
#pragma once
#include "SHFamily.h"
#include "SHpch.h"
namespace SHADE
{
//initialize currentID as 0
}

View File

@ -14,16 +14,17 @@
#pragma once #pragma once
#include "../SHECSMacros.h" #include "../SHECSMacros.h"
#include "SH_API.h"
namespace SHADE namespace SHADE
{ {
template<typename BaseClass> template<typename BaseClass>
class SHFamilyID class SH_API SHFamilyID
{ {
private: 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 * \brief Construct a new SHFamilyID object
@ -46,6 +47,9 @@ namespace SHADE
} }
public: 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 * \brief
* Checks if this identifier is cuurrently in use / valid. * Checks if this identifier is cuurrently in use / valid.
@ -59,7 +63,6 @@ namespace SHADE
{ {
return(id < currentID); return(id < currentID);
} }
/*!************************************************************************* /*!*************************************************************************
* \brief * \brief
* Get the ID of a derived class type. * Get the ID of a derived class type.
@ -68,16 +71,27 @@ namespace SHADE
* @tparam DerivedClass * @tparam DerivedClass
* The derived class type that we are trying to get the ID of. * The derived class type that we are trying to get the ID of.
***************************************************************************/ ***************************************************************************/
#ifdef SH_API_EXPORT
template<typename DerivedClass> 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. //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 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;
} }

View File

@ -17,8 +17,11 @@
#include "../General/SHSparseSetContainer.h" #include "../General/SHSparseSetContainer.h"
#include "../Components/SHComponent.h" #include "../Components/SHComponent.h"
#include "../Components/SHComponentGroup.h" #include "../Components/SHComponentGroup.h"
#include "../Events/SHComponentAddedEvent.h"
#include "../Events/SHComponentRemovedEvent.h"
//#include "Scene/SHSceneNode.h" //#include "Scene/SHSceneNode.h"
#include "SH_API.h" #include "SH_API.h"
#include "Events/SHEventManager.hpp"
#include <cassert> #include <cassert>
@ -216,6 +219,11 @@ namespace SHADE
comp->OnCreate(); 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(); 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)); 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]; 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 };// end SHComponentManager

View File

@ -68,6 +68,9 @@ namespace SHADE
id = ((SystemID)version << sizeof(SystemVersionID) * CHAR_BIT) + typeID; id = ((SystemID)version << sizeof(SystemVersionID) * CHAR_BIT) + typeID;
} }
systemContainer.emplace(id, std::make_unique<T>()); systemContainer.emplace(id, std::make_unique<T>());
auto size = systemContainer.size();
systemContainer[id].get()->systemID = id; systemContainer[id].get()->systemID = id;
return id; return id;

View File

@ -26,4 +26,6 @@ const EntityIndex MAX_EID = 51000;
#define ENABLE_IF_UINT(_TYPE, _RETURN)\ #define ENABLE_IF_UINT(_TYPE, _RETURN)\
typename std::enable_if<(std::is_integral<_TYPE>::value && !std::is_signed<_TYPE>::value),_RETURN>::type typename std::enable_if<(std::is_integral<_TYPE>::value && !std::is_signed<_TYPE>::value),_RETURN>::type
#endif #endif

View File

@ -8,23 +8,19 @@ namespace SHADE
{ {
class SHFixedSystemRoutine: public SHSystemRoutine class SHFixedSystemRoutine: public SHSystemRoutine
{ {
private:
double accumulatedTime;
double fixedTimeStep;
protected: protected:
SHFixedSystemRoutine(double timeStep = DEFAULT_FIXED_STEP, std::string routineName = "Default Fixed Routine Name", bool editorPause = false) double accumulatedTime;
double fixedTimeStep;
SHFixedSystemRoutine(double timeStep = DEFAULT_FIXED_STEP, std::string routineName = "Default Fixed Routine Name", bool editorPause = false)
:SHSystemRoutine(routineName, editorPause), accumulatedTime(0.0), fixedTimeStep(timeStep){} :SHSystemRoutine(routineName, editorPause), accumulatedTime(0.0), fixedTimeStep(timeStep){}
public: public:
~SHFixedSystemRoutine() = default; ~SHFixedSystemRoutine() = default;
virtual void Execute(double dt) noexcept; virtual void Execute(double dt) noexcept override;
virtual void FixedExecute(double dt) noexcept {};
virtual void FixedExecute(double dt) noexcept {}
}; };

View File

@ -12,6 +12,7 @@
#include "../SHECSMacros.h" #include "../SHECSMacros.h"
#include "SH_API.h" #include "SH_API.h"
#include "ECS_Base/General/SHFamily.h"
namespace SHADE namespace SHADE
{ {
@ -69,5 +70,9 @@ namespace SHADE
}; };
template class SH_API SHFamilyID<SHSystem>;
} }

View File

@ -1,6 +1,7 @@
#pragma once #pragma once
#include "../Components/SHComponent.h" #include "../Components/SHComponent.h"
#include <rttr/registration>
namespace SHADE namespace SHADE
{ {
@ -27,4 +28,50 @@ namespace SHADE
std::string value{}; 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));
}
} }

View File

@ -5,9 +5,13 @@
//#==============================================================# //#==============================================================#
#include <functional> #include <functional>
#include "SH_API.h"
#include "Scripting/SHScriptEngine.h"
#include "ECS_Base/Managers/SHSystemManager.h"
namespace SHADE namespace SHADE
{ {
class SHBaseCommand class SH_API SHBaseCommand
{ {
public: public:
virtual ~SHBaseCommand() = default; virtual ~SHBaseCommand() = default;
@ -48,4 +52,20 @@ namespace SHADE
T newValue; T newValue;
SetterFunction set; SetterFunction set;
}; };
class SH_API SHCLICommand : SHBaseCommand
{
public:
SHCLICommand() = default;
void Execute() override
{
SHScriptEngine* scriptEngine = static_cast<SHScriptEngine*>(SHSystemManager::GetSystem<SHScriptEngine>());
scriptEngine->RedoScriptInspectorChanges();
}
void Undo() override
{
SHScriptEngine* scriptEngine = static_cast<SHScriptEngine*>(SHSystemManager::GetSystem<SHScriptEngine>());
scriptEngine->UndoScriptInspectorChanges();
}
};
}//namespace SHADE }//namespace SHADE

View File

@ -27,6 +27,11 @@ namespace SHADE
} }
} }
void SHCommandManager::RegisterCommand(CommandPtr commandPtr)
{
undoStack.push(commandPtr);
}
void SHCommandManager::UndoCommand() void SHCommandManager::UndoCommand()
{ {
if (undoStack.empty()) if (undoStack.empty())

View File

@ -9,10 +9,11 @@
//|| SHADE Includes || //|| SHADE Includes ||
//#==============================================================# //#==============================================================#
#include "SHCommand.hpp" #include "SHCommand.hpp"
#include "SH_API.h"
namespace SHADE namespace SHADE
{ {
class SHCommandManager class SH_API SHCommandManager
{ {
public: public:
//#==============================================================# //#==============================================================#
@ -22,6 +23,7 @@ namespace SHADE
using CommandStack = std::stack<CommandPtr>; using CommandStack = std::stack<CommandPtr>;
static void PerformCommand(CommandPtr commandPtr, bool const& overrideValue = false); static void PerformCommand(CommandPtr commandPtr, bool const& overrideValue = false);
static void RegisterCommand(CommandPtr commandPtr);
static void UndoCommand(); static void UndoCommand();
static void RedoCommand(); static void RedoCommand();
static std::size_t GetUndoStackSize(); static std::size_t GetUndoStackSize();

View File

@ -114,7 +114,7 @@ namespace SHADE
auto* entity = SHEntityManager::GetEntityByID(currentNode->GetEntityID()); auto* entity = SHEntityManager::GetEntityByID(currentNode->GetEntityID());
//Draw Node //Draw Node
bool isNodeOpen = ImGui::TreeNodeEx((void*)eid, nodeFlags, "%u: %s", EntityHandleGenerator::GetIndex(eid), entity->name.c_str()); bool isNodeOpen = ImGui::TreeNodeEx(reinterpret_cast<void*>(entity), nodeFlags, "%u: %s", EntityHandleGenerator::GetIndex(eid), entity->name.c_str());
const ImRect nodeRect = ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax()); const ImRect nodeRect = ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax());
//Check For Begin Drag //Check For Begin Drag

View File

@ -12,6 +12,7 @@
#include "Editor/IconsMaterialDesign.h" #include "Editor/IconsMaterialDesign.h"
#include "ECS_Base/Components/SHComponent.h" #include "ECS_Base/Components/SHComponent.h"
#include "Editor/SHEditorWidgets.hpp" #include "Editor/SHEditorWidgets.hpp"
#include "Reflection/SHReflectionMetadata.h"
namespace SHADE namespace SHADE
{ {
template<typename T, std::enable_if_t<std::is_base_of<SHComponent, T>::value, bool> = true> template<typename T, std::enable_if_t<std::is_base_of<SHComponent, T>::value, bool> = true>
@ -45,7 +46,7 @@ namespace SHADE
if (!component) if (!component)
return; return;
auto componentType = rttr::type::get(*component); auto componentType = rttr::type::get(*component);
CheckBox("##IsActive", [component]() {return component->isActive; }, [component](bool const& active) {component->isActive = active; }); SHEditorWidgets::CheckBox("##IsActive", [component]() {return component->isActive; }, [component](bool const& active) {component->isActive = active; });
ImGui::SameLine(); ImGui::SameLine();
if (ImGui::CollapsingHeader(componentType.get_name().data())) if (ImGui::CollapsingHeader(componentType.get_name().data()))
{ {
@ -55,14 +56,136 @@ namespace SHADE
{ {
auto const& type = property.get_type(); 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>()) 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); else DrawContextMenu(component);

View File

@ -11,7 +11,15 @@
#include "Editor/SHImGuiHelpers.hpp" #include "Editor/SHImGuiHelpers.hpp"
#include "Editor/SHEditorWidgets.hpp" #include "Editor/SHEditorWidgets.hpp"
#include "SHEditorComponentView.hpp" #include "SHEditorComponentView.hpp"
#include "ECS_Base/UnitTesting/SHTestComponents.h"
#include "Graphics/MiddleEnd/Interface/SHRenderable.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"
#include "Physics/Components/SHRigidBodyComponent.h"
#include "Physics/Components/SHColliderComponent.h"
namespace SHADE namespace SHADE
{ {
@ -39,13 +47,19 @@ namespace SHADE
SHEditorWindow::Update(); SHEditorWindow::Update();
if (Begin()) if (Begin())
{ {
if (ImGui::Button("AUDIO"))
{
auto audioSystem = SHSystemManager::GetSystem<SHADE::SHAudioSystem>();
audioSystem->PlayEventOnce("event:/Characters/sfx_footsteps_raccoon");
}
if (!SHEditor::selectedEntities.empty()) if (!SHEditor::selectedEntities.empty())
{ {
EntityID const& eid = SHEditor::selectedEntities[0]; EntityID const& eid = SHEditor::selectedEntities[0];
SHEntity* entity = SHEntityManager::GetEntityByID(eid); SHEntity* entity = SHEntityManager::GetEntityByID(eid);
ImGui::TextColored(ImGuiColors::green, "EID: %zu", 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::SameLine();
ImGui::InputText("##EntityName", &entity->name); ImGui::InputText("##EntityName", &entity->name);
@ -54,13 +68,32 @@ namespace SHADE
{ {
DrawComponent(transformComponent); DrawComponent(transformComponent);
} }
if(auto renderableComponent = SHComponentManager::GetComponent_s<SHRenderable>(eid))
{
DrawComponent(renderableComponent);
}
if(auto colliderComponent = SHComponentManager::GetComponent_s<SHColliderComponent>(eid))
{
DrawComponent(colliderComponent);
}
if(auto rigidbodyComponent = SHComponentManager::GetComponent_s<SHRigidBodyComponent>(eid))
{
DrawComponent(rigidbodyComponent);
}
ImGui::Separator();
// Render Scripts
SHScriptEngine* scriptEngine = static_cast<SHScriptEngine*>(SHSystemManager::GetSystem<SHScriptEngine>());
scriptEngine->RenderScriptsInInspector(eid);
ImGui::Separator(); ImGui::Separator();
if(ImGui::BeginMenu(std::format("{} Add Component", ICON_MD_LIBRARY_ADD).data())) if(ImGui::BeginMenu(std::format("{} Add Component", ICON_MD_LIBRARY_ADD).data()))
{ {
DrawAddComponentButton<SHTransformComponent>(eid); DrawAddComponentButton<SHTransformComponent>(eid);
DrawAddComponentButton<SHRenderable>(eid); DrawAddComponentButton<SHRenderable>(eid);
DrawAddComponentButton<SHColliderComponent>(eid);
DrawAddComponentButton<SHRigidBodyComponent>(eid);
ImGui::EndMenu(); ImGui::EndMenu();
} }
} }
ImGui::End(); ImGui::End();
} }

View File

@ -6,6 +6,9 @@
#include "SHEditorMenuBar.h" #include "SHEditorMenuBar.h"
#include "Editor/IconsMaterialDesign.h" #include "Editor/IconsMaterialDesign.h"
#include "Editor/Command/SHCommandManager.h" #include "Editor/Command/SHCommandManager.h"
#include "Scripting/SHScriptEngine.h"
#include "Editor/SHEditor.hpp"
#include "ECS_Base/Managers/SHSystemManager.h"
//#==============================================================# //#==============================================================#
//|| Library Includes || //|| Library Includes ||
@ -14,9 +17,6 @@
#include <imgui_internal.h> #include <imgui_internal.h>
#include <rttr/type> #include <rttr/type>
#include "Editor/SHEditor.hpp"
namespace SHADE namespace SHADE
{ {
constexpr ImGuiWindowFlags editorMenuBarFlags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | constexpr ImGuiWindowFlags editorMenuBarFlags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse |
@ -100,6 +100,25 @@ namespace SHADE
} }
ImGui::EndMenu(); 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(); ImGui::EndMainMenuBar();
} }

View File

@ -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();
}
}

View File

@ -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;
};
}

View File

@ -2,3 +2,4 @@
#include "MenuBar/SHEditorMenuBar.h" //Menu Bar #include "MenuBar/SHEditorMenuBar.h" //Menu Bar
#include "HierarchyPanel/SHHierarchyPanel.h" //Hierarchy Panel #include "HierarchyPanel/SHHierarchyPanel.h" //Hierarchy Panel
#include "Inspector/SHEditorInspector.h" //Inspector #include "Inspector/SHEditorInspector.h" //Inspector
#include "Profiling/SHEditorProfiler.h" //Profiler

View File

@ -843,7 +843,7 @@
#define ICON_MD_FLIP_TO_FRONT "\xee\xa2\x83" // U+e883 #define ICON_MD_FLIP_TO_FRONT "\xee\xa2\x83" // U+e883
#define ICON_MD_FLOOD "\xee\xaf\xa6" // U+ebe6 #define ICON_MD_FLOOD "\xee\xaf\xa6" // U+ebe6
#define ICON_MD_FLOURESCENT "\xee\xb0\xb1" // U+ec31 #define ICON_MD_FLOURESCENT "\xee\xb0\xb1" // U+ec31
#define ICON_MD_FLOURESCENT "\xef\x80\x8d" // U+f00d #define ICON_MD_FLOURESCENT2 "\xef\x80\x8d" // U+f00d
#define ICON_MD_FLUORESCENT "\xee\xb0\xb1" // U+ec31 #define ICON_MD_FLUORESCENT "\xee\xb0\xb1" // U+ec31
#define ICON_MD_FLUTTER_DASH "\xee\x80\x8b" // U+e00b #define ICON_MD_FLUTTER_DASH "\xee\x80\x8b" // U+e00b
#define ICON_MD_FMD_BAD "\xef\x80\x8e" // U+f00e #define ICON_MD_FMD_BAD "\xef\x80\x8e" // U+f00e

View File

@ -23,6 +23,8 @@
#include "SHEditor.hpp" #include "SHEditor.hpp"
#include "SHEditorWidgets.hpp" #include "SHEditorWidgets.hpp"
#include "Math/Transform/SHTransformSystem.h"
//#==============================================================# //#==============================================================#
//|| Editor Window Includes || //|| Editor Window Includes ||
//#==============================================================# //#==============================================================#
@ -87,6 +89,11 @@ namespace SHADE
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; //Enable docking io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; //Enable docking
InitFonts(); InitFonts();
auto id = SHFamilyID<SHSystem>::GetID<SHGraphicsSystem>();
auto id2 = SHFamilyID<SHSystem>::GetID<SHTransformSystem>();
auto id3 = SHFamilyID<SHSystem>::GetID<SHGraphicsSystem>();
InitBackend(sdlWindow); InitBackend(sdlWindow);
SetStyle(Style::SHADE); SetStyle(Style::SHADE);
@ -95,6 +102,7 @@ namespace SHADE
CreateEditorWindow<SHEditorMenuBar>(); CreateEditorWindow<SHEditorMenuBar>();
CreateEditorWindow<SHHierarchyPanel>(); CreateEditorWindow<SHHierarchyPanel>();
CreateEditorWindow<SHEditorInspector>(); CreateEditorWindow<SHEditorInspector>();
CreateEditorWindow<SHEditorProfiler>();
SHLOG_INFO("Successfully initialised SHADE Engine Editor") SHLOG_INFO("Successfully initialised SHADE Engine Editor")
} }
@ -103,10 +111,10 @@ namespace SHADE
{ {
(void)dt; (void)dt;
NewFrame(); NewFrame();
for (const auto& window : editorWindows | std::views::values) 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)) if(ImGui::IsKeyDown(ImGuiKey_LeftShift) && ImGui::IsKeyDown(ImGuiKey_LeftCtrl) && ImGui::IsKeyReleased(ImGuiKey_Z))
@ -292,6 +300,8 @@ namespace SHADE
imguiCommandBuffer->EndRecording(); imguiCommandBuffer->EndRecording();
gfxSystem->GetQueue()->SubmitCommandBuffer({ imguiCommandBuffer }, {}, {}, vk::PipelineStageFlagBits::eNone, {}); gfxSystem->GetQueue()->SubmitCommandBuffer({ imguiCommandBuffer }, {}, {}, vk::PipelineStageFlagBits::eNone, {});
gfxSystem->GetDevice()->WaitIdle();
ImGui_ImplVulkan_DestroyFontUploadObjects(); ImGui_ImplVulkan_DestroyFontUploadObjects();
renderGraph->GetNode("ImGui Node")->GetSubpass("ImGui Draw")->AddExteriorDrawCalls([](Handle<SHVkCommandBuffer>& cmd) { renderGraph->GetNode("ImGui Node")->GetSubpass("ImGui Draw")->AddExteriorDrawCalls([](Handle<SHVkCommandBuffer>& cmd) {

View File

@ -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;
}
}

View File

@ -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"

View File

@ -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;
}
}

View File

@ -12,6 +12,7 @@
#include "Math/SHMath.h" #include "Math/SHMath.h"
#include "Command/SHCommandManager.h" #include "Command/SHCommandManager.h"
#include "SHImGuiHelpers.hpp" #include "SHImGuiHelpers.hpp"
#include "SH_API.h"
//#==============================================================# //#==============================================================#
//|| Library Includes || //|| Library Includes ||
@ -23,165 +24,315 @@
namespace SHADE namespace SHADE
{ {
//#==============================================================# class SH_API SHEditorWidgets
//|| Custom Widgets ||
//#==============================================================#
static bool Splitter(bool verticalSplit, float thickness, float* size1, float* size2, float minSize1, float minSize2, float splitterAxisSize = -1.0f)
{ {
ImGuiWindow* window = ImGui::GetCurrentWindow(); public:
const ImGuiID id = window->GetID("##Splitter"); //#==============================================================#
ImRect bb; //|| Constructor ||
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)); SHEditorWidgets() = delete;
return ImGui::SplitterBehavior(bb, id, verticalSplit ? ImGuiAxis_X : ImGuiAxis_Y, size1, size2, minSize1, minSize2, 0.0f);
}
template <typename T, std::size_t N> //#==============================================================#
static bool DragN(const std::string& fieldLabel, std::vector<std::string>const& componentLabels, //|| Custom Widgets ||
std::vector<T*> values, float speed = 0.1f, const char* displayFormat = "", T valueMin = T(), T valueMax = T(), //#==============================================================#
ImGuiSliderFlags flags = 0) static bool Splitter(bool verticalSplit, float thickness, float* size1, float* size2, float minSize1, float minSize2, float splitterAxisSize = -1.0f)
{
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)); ImGuiWindow* window = ImGui::GetCurrentWindow();
ImGui::TextUnformatted(componentLabels[i].c_str(), ImGui::FindRenderedTextEnd(componentLabels[i].c_str())); ImGui::SameLine(); const ImGuiID id = window->GetID("##Splitter");
ImGui::SetNextItemWidth(80.0f); ImRect bb;
valueChanged |= ImGui::DragFloat("##v", values[i], speed, valueMin, valueMax, displayFormat, flags); 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));
const ImVec2 min = ImGui::GetItemRectMin(); return ImGui::SplitterBehavior(bb, id, verticalSplit ? ImGuiAxis_X : ImGuiAxis_Y, size1, size2, minSize1, minSize2, 0.0f);
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; 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, 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, std::function<void(SHVec2)> set, float speed = 0.1f, const char* displayFormat = "%.3f", float valueMin = 0.0f, float valueMax = 0.0f,
ImGuiSliderFlags flags = 0) ImGuiSliderFlags flags = 0)
{
SHVec2 values = get();
bool changed = false;
if (DragN<float, 2>(fieldLabel, componentLabels, {&values.x, &values.y}, speed, displayFormat, valueMin, valueMax, flags))
{ {
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)) SHVec3 values = get();
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec2>>(get(), values, set)), false); bool changed = false;
else if(ImGui::IsMouseDragging(ImGuiMouseButton_Left)) if (DragN<float, 3>(fieldLabel, componentLabels, { &values.x, &values.y, &values.z }, speed, displayFormat, valueMin, valueMax, flags))
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec2>>(get(), values, set)), true); {
else if(ImGui::IsItemDeactivatedAfterEdit()) changed = true;
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec2>>(get(), values, set)), false); }
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 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)
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))
{ {
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)) bool value = get();
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec3>>(get(), values, set)), false); if (ImGui::Checkbox(label.c_str(), &value))
else if(ImGui::IsMouseDragging(ImGuiMouseButton_Left)) {
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec3>>(get(), values, set)), true); SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<bool>>(get(), value, set)), false);
else if(ImGui::IsItemDeactivatedAfterEdit()) return true;
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec3>>(get(), values, set)), false); }
return false;
} }
return changed; template<typename T>
} static bool RadioButton(std::vector<std::string> const& listLabels, std::vector<T> const& listTypes, std::function<T(void)> get, std::function<void(T const&)> set)
static bool 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))
{ {
changed = true; T type = get();
} for (size_t i = 0; i < listTypes.size(); i++)
{
if (changed) if (ImGui::RadioButton(listLabels[i].c_str(), type == listTypes[i]))
{ {
if (ImGui::IsMouseDown(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left, -0.2f)) SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<T>>(get(), listTypes[i], set)), false);
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec4>>(get(), values, set)), false); }
else if(ImGui::IsMouseDragging(ImGuiMouseButton_Left)) ImGui::SameLine();
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);
return true; return true;
} }
return false;
}
template<typename T> static bool InputText(const std::string& label, const std::function<std::string(void)> get,
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) const std::function<void(std::string)> set, ImGuiInputTextFlags flag = 0,
{ ImGuiInputTextCallback callback = (ImGuiInputTextCallback)0, void* userData = (void*)0)
T type = get();
for (size_t i = 0; i < listTypes.size(); i++)
{ {
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(), static_cast<int>(list.size())))
{
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<int>>(get(), selected, set)), false);
}
ImGui::PopID();
return edited;
}
};
}//namespace SHADE }//namespace SHADE

View File

@ -8,3 +8,5 @@ typedef uint32_t SHEventHandle;
constexpr SHEventIdentifier SH_EXAMPLE_EVENT{0}; constexpr SHEventIdentifier SH_EXAMPLE_EVENT{0};
constexpr SHEventIdentifier SH_ENTITY_DESTROYED_EVENT{ 1 }; constexpr SHEventIdentifier SH_ENTITY_DESTROYED_EVENT{ 1 };
constexpr SHEventIdentifier SH_ENTITY_CREATION_EVENT{ 2 }; constexpr SHEventIdentifier SH_ENTITY_CREATION_EVENT{ 2 };
constexpr SHEventIdentifier SH_COMPONENT_ADDED_EVENT{ 3 };
constexpr SHEventIdentifier SH_COMPONENT_REMOVED_EVENT{ 4 };

View File

@ -9,12 +9,31 @@
consent of DigiPen Institute of Technology is prohibited. consent of DigiPen Institute of Technology is prohibited.
*********************************************************************/ *********************************************************************/
//TODO Legacy code. Delete soon
#include <chrono> #include <chrono>
#include <cassert> #include <cassert>
#include <SHpch.h> #include <SHpch.h>
#include "SHFramerateController.h" #include "SHFramerateController.h"
#include "../Tools/SHLogger.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 namespace SHADE
{ {
//Init statics //Init statics
@ -132,3 +151,4 @@ namespace SHADE
} }
} }
} }
#endif

View File

@ -13,6 +13,38 @@
#define SH_FRAMERATECONTROLLER_H #define SH_FRAMERATECONTROLLER_H
#pragma once #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" #include "../Scene/SHScene.h"
namespace SHADE namespace SHADE
@ -56,7 +88,19 @@ namespace SHADE
//halt execution of the current scene and prepare //halt execution of the current scene and prepare
//execution of the next //execution of the next
static inline void SetNextScene(SHScene* const next) { nextScene = next; } static inline void SetNextScene(SHScene* const next) { nextScene = next; }
}; };
} }
#endif
#endif #endif

View File

@ -2,7 +2,6 @@
#include "SHFileSystem.h" #include "SHFileSystem.h"
#include "fileapi.h" #include "fileapi.h"
#include <filesystem> #include <filesystem>
#include <cassert>
#include <queue> #include <queue>
namespace SHADE namespace SHADE
@ -28,7 +27,10 @@ namespace SHADE
auto const count = static_cast<FolderCounter>(folders[here]->subFolders.size()); auto const count = static_cast<FolderCounter>(folders[here]->subFolders.size());
assert(count < FOLDER_MAX_COUNT, "Max subfolders reached\n"); if (count >= FOLDER_MAX_COUNT)
{
SHLOG_ERROR("Max subfolder reached: {}\n", name);
}
auto const location = static_cast<FolderLocation>(count); auto const location = static_cast<FolderLocation>(count);
@ -37,7 +39,10 @@ namespace SHADE
return location; return location;
} }
assert(folders.contains(here), "Folder creation location does not exist/invalid\n"); if (!folders.contains(here))
{
SHLOG_ERROR("Folder creation location does not exist/invalid: {}\n", here);
}
auto const count = static_cast<FolderCounter>(folders[here]->subFolders.size()); auto const count = static_cast<FolderCounter>(folders[here]->subFolders.size());
@ -45,7 +50,11 @@ namespace SHADE
location <<= FOLDER_BIT_ALLOCATE; location <<= FOLDER_BIT_ALLOCATE;
location |= count; location |= count;
assert(count < FOLDER_MAX_COUNT, "Max subfolders reached\n"); if (count >= FOLDER_MAX_COUNT)
{
SHLOG_ERROR("Max subfolder reached: {}\n", name);
}
CreateFolder(folders[0]->path, here, location, name); CreateFolder(folders[0]->path, here, location, name);
return location; return location;
@ -53,7 +62,10 @@ namespace SHADE
bool SHFileSystem::DeleteFolder(FolderPointer location) noexcept bool SHFileSystem::DeleteFolder(FolderPointer location) noexcept
{ {
assert(folders.contains(location->id), "Delete target does not exist/invalid.\n"); if (!folders.contains(location->id))
{
SHLOG_ERROR("Delete target does not exist/invalid: {}\n", location->name);
}
for (auto const& subFolder : folders[location->id]->subFolders) for (auto const& subFolder : folders[location->id]->subFolders)
{ {
@ -116,10 +128,11 @@ namespace SHADE
FolderPointer SHFileSystem::CreateFolder(FolderPath path, FolderLocation parent, FolderHandle location, FolderName name) noexcept FolderPointer SHFileSystem::CreateFolder(FolderPath path, FolderLocation parent, FolderHandle location, FolderName name) noexcept
{ {
assert(
CreateDirectoryA(path.c_str(), nullptr), if (!CreateDirectoryA(path.c_str(), nullptr))
"Failed to create folder\n" {
); SHLOG_ERROR("Failed to create folder: {}\n", path);
}
folders[location] = std::make_unique<SHFolder>(location, name); folders[location] = std::make_unique<SHFolder>(location, name);
folders[location]->path = path; folders[location]->path = path;

View File

@ -24,7 +24,7 @@ namespace SHADE
/***************************************************************************/ /***************************************************************************/
SHVkCommandBuffer::~SHVkCommandBuffer(void) noexcept SHVkCommandBuffer::~SHVkCommandBuffer(void) noexcept
{ {
if (vkCommandBuffer) if (vkCommandBuffer && parentPool)
parentPool->GetLogicalDevice()->GetVkLogicalDevice().freeCommandBuffers(parentPool->GetVkCommandPool(), commandBufferCount, &vkCommandBuffer); parentPool->GetLogicalDevice()->GetVkLogicalDevice().freeCommandBuffers(parentPool->GetVkCommandPool(), commandBufferCount, &vkCommandBuffer);
} }

View File

@ -102,8 +102,6 @@ namespace SHADE
logicalDeviceHdl = rhs.logicalDeviceHdl; logicalDeviceHdl = rhs.logicalDeviceHdl;
transient = rhs.transient; transient = rhs.transient;
static_cast<ISelfHandle<SHVkCommandPool>&>(*this) = static_cast<ISelfHandle<SHVkCommandPool>&>(rhs);
rhs.vkCommandPool = VK_NULL_HANDLE; rhs.vkCommandPool = VK_NULL_HANDLE;
return *this; return *this;

View File

@ -39,8 +39,10 @@ namespace SHADE
std::vector<vk::DescriptorPoolSize> Limits = std::vector<vk::DescriptorPoolSize> Limits =
{ {
{ vk::DescriptorType::eCombinedImageSampler, 100 }, { vk::DescriptorType::eCombinedImageSampler, 100 },
{ vk::DescriptorType::eUniformBuffer, 100 }, { vk::DescriptorType::eUniformBuffer, 100 },
{ vk::DescriptorType::eUniformBufferDynamic, 100 } { vk::DescriptorType::eUniformBufferDynamic, 100 },
{ vk::DescriptorType::eStorageImage, 100},
{ vk::DescriptorType::eStorageBufferDynamic, 100 }
}; };
/// <summary> /// <summary>
/// Maximum number of descriptor sets allowed /// Maximum number of descriptor sets allowed

View File

@ -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 // Find the target writeDescSet
BindingAndSetHash writeHash = binding; BindingAndSetHash writeHash = binding;
@ -170,9 +170,10 @@ namespace SHADE
for (uint32_t i = 0; i < imageViewsAndSamplers.size(); ++i) for (uint32_t i = 0; i < imageViewsAndSamplers.size(); ++i)
{ {
// write sampler and image view // write sampler and image view
auto& ivs = imageViewsAndSamplers[i]; auto& [view, sampler, layout] = imageViewsAndSamplers[i];
writeInfo.descImageInfos[i].imageView = ivs.first->GetImageView(); writeInfo.descImageInfos[i].imageView = view->GetImageView();
writeInfo.descImageInfos[i].sampler = ivs.second->GetVkSampler(); writeInfo.descImageInfos[i].sampler = sampler->GetVkSampler();
writeInfo.descImageInfos[i].imageLayout = layout;
} }
} }
@ -207,7 +208,7 @@ namespace SHADE
BindingAndSetHash bsHash = SHVkUtil::GenBindingSetHash(set, binding); BindingAndSetHash bsHash = SHVkUtil::GenBindingSetHash(set, binding);
// to index a set // to index a set
uint32_t setIndex = setIndexing[bsHash]; uint32_t setIndex = setIndexing[set];
// to index a write for a binding // to index a write for a binding
uint32_t writeInfoIndex = updater.writeHashMap[bsHash]; uint32_t writeInfoIndex = updater.writeHashMap[bsHash];
@ -232,7 +233,7 @@ namespace SHADE
BindingAndSetHash bsHash = SHVkUtil::GenBindingSetHash(set, binding); BindingAndSetHash bsHash = SHVkUtil::GenBindingSetHash(set, binding);
// to index a set // to index a set
uint32_t setIndex = setIndexing[bsHash]; uint32_t setIndex = setIndexing[set];
// to index a write for a binding // to index a write for a binding
uint32_t writeInfoIndex = updater.writeHashMap[bsHash]; uint32_t writeInfoIndex = updater.writeHashMap[bsHash];

View File

@ -1,5 +1,7 @@
#pragma once #pragma once
#include <tuple>
// Project Includes // Project Includes
#include "Graphics/SHVulkanIncludes.h" #include "Graphics/SHVulkanIncludes.h"
#include "Resource/Handle.h" #include "Resource/Handle.h"
@ -63,7 +65,7 @@ namespace SHADE
void UpdateDescriptorSetImages(uint32_t set, uint32_t binding) noexcept; void UpdateDescriptorSetImages(uint32_t set, uint32_t binding) noexcept;
void UpdateDescriptorSetBuffer(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; void ModifyWriteDescBuffer (uint32_t set, uint32_t binding, std::span<Handle<SHVkBuffer>> const& buffers, uint32_t offset, uint32_t range) noexcept;

View File

@ -16,6 +16,7 @@
#include "Graphics/Framebuffer/SHVkFramebuffer.h" #include "Graphics/Framebuffer/SHVkFramebuffer.h"
#include "Graphics/Images/SHVkImageView.h" #include "Graphics/Images/SHVkImageView.h"
#include "Graphics/Descriptors/SHVkDescriptorSetGroup.h" #include "Graphics/Descriptors/SHVkDescriptorSetGroup.h"
#include "Graphics/Images/SHVkSampler.h"
namespace SHADE 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 + static_cast<uint32_t>(alignmentSize) - 1) & ~(alignmentSize - 1);
}
return alignedSize;
}
/***************************************************************************/ /***************************************************************************/
/*! /*!
@ -176,12 +188,15 @@ namespace SHADE
// point and lines fill mode // point and lines fill mode
features.fillModeNonSolid = true; features.fillModeNonSolid = true;
features.samplerAnisotropy = VK_TRUE; features.samplerAnisotropy = VK_TRUE;
features.multiDrawIndirect = true;
// for wide lines // for wide lines
features.wideLines = true; features.wideLines = true;
vk::PhysicalDeviceDescriptorIndexingFeatures descIndexingFeature{}; vk::PhysicalDeviceDescriptorIndexingFeatures descIndexingFeature{};
descIndexingFeature.descriptorBindingVariableDescriptorCount = true; descIndexingFeature.descriptorBindingVariableDescriptorCount = true;
descIndexingFeature.shaderSampledImageArrayNonUniformIndexing = true;
descIndexingFeature.runtimeDescriptorArray = true;
// Prepare to create the device // Prepare to create the device
vk::DeviceCreateInfo deviceCreateInfo vk::DeviceCreateInfo deviceCreateInfo
@ -236,6 +251,22 @@ namespace SHADE
vkLogicalDevice.destroy(nullptr); vkLogicalDevice.destroy(nullptr);
} }
SHVkLogicalDevice& SHVkLogicalDevice::operator=(SHVkLogicalDevice&& rhs) noexcept
{
if (this == &rhs)
return *this;
vkLogicalDevice = std::move (rhs.vkLogicalDevice);
queueFamilyIndices = std::move (rhs.queueFamilyIndices);
vmaAllocator = rhs.vmaAllocator;
nonDedicatedBestIndex = 0;
parentPhysicalDeviceHdl = rhs.parentPhysicalDeviceHdl;
rhs.vkLogicalDevice = VK_NULL_HANDLE;
return *this;
}
/***************************************************************************/ /***************************************************************************/
/*! /*!
@ -288,13 +319,12 @@ namespace SHADE
uint32_t SHVkLogicalDevice::PadUBOSize(uint32_t originalSize) const noexcept uint32_t SHVkLogicalDevice::PadUBOSize(uint32_t originalSize) const noexcept
{ {
uint32_t alignedSize = originalSize; return ComputeAlignedBufferSize(originalSize, uboBufferMemoryAlignment);
//uint32_t minBuffer }
if (uboBufferMemoryAlignment > 0)
{ uint32_t SHVkLogicalDevice::PadSSBOSize(uint32_t originalSize) const noexcept
alignedSize = (alignedSize + uboBufferMemoryAlignment - 1) & ~(uboBufferMemoryAlignment - 1); {
} return ComputeAlignedBufferSize(originalSize, ssboBufferMemoryAlignment);
return alignedSize;
} }
/***************************************************************************/ /***************************************************************************/
@ -499,6 +529,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 Handle<SHVkRenderpass> SHVkLogicalDevice::CreateRenderpass(std::span<vk::AttachmentDescription> const vkDescriptions, std::vector<SHVkSubpassParams> const& subpasses) noexcept
{ {
return SHVkInstance::GetResourceManager().Create <SHVkRenderpass>(GetHandle(), vkDescriptions, subpasses); return SHVkInstance::GetResourceManager().Create <SHVkRenderpass>(GetHandle(), vkDescriptions, subpasses);

View File

@ -21,7 +21,6 @@
#include "Graphics/Descriptors/SHVkDescriptorSetLayout.h" #include "Graphics/Descriptors/SHVkDescriptorSetLayout.h"
#include "Graphics/Images/SHVkImage.h" #include "Graphics/Images/SHVkImage.h"
namespace SHADE namespace SHADE
{ {
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
@ -41,6 +40,8 @@ namespace SHADE
class SHShaderBlockInterface; class SHShaderBlockInterface;
class SHVkDescriptorSetGroup; class SHVkDescriptorSetGroup;
class SHSubpass; class SHSubpass;
class SHVkSampler;
struct SHVkSamplerParams;
/***************************************************************************/ /***************************************************************************/
/*! /*!
@ -102,6 +103,7 @@ namespace SHADE
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
void InitializeVMA (void) noexcept; void InitializeVMA (void) noexcept;
void InitializeQueues (std::initializer_list<SHQueueParams> queueCreateParams) noexcept; void InitializeQueues (std::initializer_list<SHQueueParams> queueCreateParams) noexcept;
uint32_t ComputeAlignedBufferSize(uint32_t originalSize, size_t typeSize) const noexcept;
public: public:
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
@ -113,7 +115,7 @@ namespace SHADE
~SHVkLogicalDevice (void) noexcept; ~SHVkLogicalDevice (void) noexcept;
SHVkLogicalDevice& operator= (SHVkLogicalDevice const& rhs) noexcept = default; SHVkLogicalDevice& operator= (SHVkLogicalDevice const& rhs) noexcept = default;
SHVkLogicalDevice& operator= (SHVkLogicalDevice&& rhs) noexcept = default; SHVkLogicalDevice& operator= (SHVkLogicalDevice&& rhs) noexcept;
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* PUBLIC MEMBER VARIABLES */ /* PUBLIC MEMBER VARIABLES */
@ -121,7 +123,8 @@ namespace SHADE
// Miscellaneous functions // Miscellaneous functions
void WaitIdle (void) noexcept; void WaitIdle (void) noexcept;
uint32_t FindMemoryType (uint32_t typeFilter, vk::MemoryPropertyFlags properties); 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 // creation functions
Handle<SHVkSurface> CreateSurface (HWND const& windowHandle) const noexcept; Handle<SHVkSurface> CreateSurface (HWND const& windowHandle) const noexcept;
@ -178,6 +181,7 @@ namespace SHADE
Handle<SHVkRenderpass> const& renderpassHdl, Handle<SHVkRenderpass> const& renderpassHdl,
Handle<SHSubpass> subpass Handle<SHSubpass> subpass
) noexcept; ) noexcept;
Handle<SHVkSampler> CreateSampler (const SHVkSamplerParams& params) noexcept;
Handle<SHVkRenderpass> CreateRenderpass (std::span<vk::AttachmentDescription> const vkDescriptions, std::vector<SHVkSubpassParams> const& subpasses) noexcept; Handle<SHVkRenderpass> CreateRenderpass (std::span<vk::AttachmentDescription> const vkDescriptions, std::vector<SHVkSubpassParams> const& subpasses) noexcept;
Handle<SHVkRenderpass> CreateRenderpass (std::span<vk::AttachmentDescription> const vkDescriptions, std::span<vk::SubpassDescription> const spDescs, std::span<vk::SubpassDependency> const spDeps) noexcept; Handle<SHVkRenderpass> CreateRenderpass (std::span<vk::AttachmentDescription> const vkDescriptions, std::span<vk::SubpassDescription> const spDescs, std::span<vk::SubpassDependency> const spDeps) noexcept;

View File

@ -98,6 +98,51 @@ namespace SHADE
return *this; return *this;
} }
void SHVkFramebuffer::HandleResize(Handle<SHVkRenderpass> const& renderpassHdl, std::vector<Handle<SHVkImageView>> const& attachments, uint32_t inWidth, uint32_t inHeight) noexcept
{
width = inWidth;
height = inHeight;
for (auto& attachment : attachments)
{
// Not sure if its an error to pass in diff dimension images.
if (attachment->GetParentImage()->GetWidth() != (*attachments.begin())->GetParentImage()->GetWidth() || attachment->GetParentImage()->GetHeight() != (*attachments.begin())->GetParentImage()->GetHeight())
{
SHLOG_ERROR("Dimensions of images not same as each other. Cannot create framebuffer.");
return;
}
}
std::vector<vk::ImageView> vkAttachments(attachments.size());
uint32_t i = 0;
for(auto const& attachment : attachments)
{
vkAttachments[i] = attachment->GetImageView();
++i;
}
vk::FramebufferCreateInfo createInfo
{
.renderPass = renderpassHdl->GetVkRenderpass(),
.attachmentCount = static_cast<uint32_t>(vkAttachments.size()),
.pAttachments = vkAttachments.data(),
.width = width,
.height = height,
.layers = 1 // TODO: Find out why this is 1
};
if (auto result = logicalDeviceHdl->GetVkLogicalDevice().createFramebuffer(&createInfo, nullptr, &vkFramebuffer); result != vk::Result::eSuccess)
{
SHVulkanDebugUtil::ReportVkError(result, "Failed to create framebuffer. ");
return;
}
else
{
SHVulkanDebugUtil::ReportVkSuccess("Successfully created framebuffer. ");
}
}
/***************************************************************************/ /***************************************************************************/
/*! /*!

View File

@ -37,6 +37,8 @@ namespace SHADE
SHVkFramebuffer(SHVkFramebuffer&& rhs) noexcept; SHVkFramebuffer(SHVkFramebuffer&& rhs) noexcept;
SHVkFramebuffer& operator=(SHVkFramebuffer&& rhs) noexcept; SHVkFramebuffer& operator=(SHVkFramebuffer&& rhs) noexcept;
void HandleResize (Handle<SHVkRenderpass> const& renderpassHdl, std::vector<Handle<SHVkImageView>> const& attachments, uint32_t inWidth, uint32_t inHeight) noexcept;
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* SETTERS AND GETTERS */ /* SETTERS AND GETTERS */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/

View File

@ -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 // For creation of buffer
vk::BufferCreateInfo bufferInfo{}; vk::BufferCreateInfo bufferInfo{};
@ -70,7 +70,7 @@ namespace SHADE
vmaMapMemory(*vmaAllocator, stagingAlloc, &stagingBufferMappedPtr); vmaMapMemory(*vmaAllocator, stagingAlloc, &stagingBufferMappedPtr);
if (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 offsets = 0;
const VkDeviceSize sizes = srcSize; const VkDeviceSize sizes = srcSize;
@ -79,10 +79,45 @@ namespace SHADE
vmaUnmapMemory(*vmaAllocator, stagingAlloc); vmaUnmapMemory(*vmaAllocator, stagingAlloc);
} }
void SHVkImage::CreateFramebufferImage(void) noexcept
{
vk::ImageCreateInfo imageCreateInfo{};
imageCreateInfo.imageType = vk::ImageType::e2D;
imageCreateInfo.extent.width = width;
imageCreateInfo.extent.height = height;
imageCreateInfo.extent.depth = depth;
imageCreateInfo.mipLevels = mipLevelCount;
imageCreateInfo.arrayLayers = layerCount;
imageCreateInfo.format = imageFormat;
imageCreateInfo.tiling = vk::ImageTiling::eOptimal;
imageCreateInfo.initialLayout = vk::ImageLayout::eUndefined;
imageCreateInfo.usage = usageFlags;
imageCreateInfo.sharingMode = vk::SharingMode::eExclusive;
imageCreateInfo.samples = vk::SampleCountFlagBits::e1;
imageCreateInfo.flags = createFlags;
// Prepare allocation parameters for call to create images later
VmaAllocationCreateInfo allocCreateInfo{};
allocCreateInfo.usage = VMA_MEMORY_USAGE_AUTO;
allocCreateInfo.flags = {}; // TODO: Make sure the vk::MemoryPropertyFlags returned from vmaGetAllocationMemoryProperties has the device local bit set
VmaAllocationInfo allocInfo{};
VkImage tempImage;
auto result = vmaCreateImage(*vmaAllocator, &imageCreateInfo.operator VkImageCreateInfo & (), &allocCreateInfo, &tempImage, &alloc, &allocInfo);
vkImage = tempImage;
if (result != VK_SUCCESS)
SHVulkanDebugUtil::ReportVkError(vk::Result(result), "Failed to create vulkan image. ");
else
SHVulkanDebugUtil::ReportVkSuccess("Successfully created image. ");
}
SHVkImage::SHVkImage( SHVkImage::SHVkImage(
VmaAllocator const* allocator, VmaAllocator const* allocator,
SHImageCreateParams const& imageDetails, SHImageCreateParams const& imageDetails,
unsigned char* data, const unsigned char* data,
uint32_t dataSize, uint32_t dataSize,
std::span<uint32_t> inMipOffsets, std::span<uint32_t> inMipOffsets,
VmaMemoryUsage memUsage, VmaMemoryUsage memUsage,
@ -196,37 +231,7 @@ namespace SHADE
, createFlags {create} , createFlags {create}
, vmaAllocator {allocator} , vmaAllocator {allocator}
{ {
vk::ImageCreateInfo imageCreateInfo{}; CreateFramebufferImage();
imageCreateInfo.imageType = vk::ImageType::e2D;
imageCreateInfo.extent.width = width;
imageCreateInfo.extent.height = height;
imageCreateInfo.extent.depth = depth;
imageCreateInfo.mipLevels = mipLevelCount;
imageCreateInfo.arrayLayers = layerCount;
imageCreateInfo.format = imageFormat;
imageCreateInfo.tiling = vk::ImageTiling::eOptimal;
imageCreateInfo.initialLayout = vk::ImageLayout::eUndefined;
imageCreateInfo.usage = usageFlags;
imageCreateInfo.sharingMode = vk::SharingMode::eExclusive;
imageCreateInfo.samples = vk::SampleCountFlagBits::e1;
imageCreateInfo.flags = createFlags;
// Prepare allocation parameters for call to create images later
VmaAllocationCreateInfo allocCreateInfo{};
allocCreateInfo.usage = VMA_MEMORY_USAGE_AUTO;
allocCreateInfo.flags = {}; // TODO: Make sure the vk::MemoryPropertyFlags returned from vmaGetAllocationMemoryProperties has the device local bit set
VmaAllocationInfo allocInfo{};
VkImage tempImage;
auto result = vmaCreateImage(*vmaAllocator, &imageCreateInfo.operator VkImageCreateInfo & (), &allocCreateInfo, &tempImage, &alloc, &allocInfo);
vkImage = tempImage;
if (result != VK_SUCCESS)
SHVulkanDebugUtil::ReportVkError(vk::Result(result), "Failed to create vulkan image. ");
else
SHVulkanDebugUtil::ReportVkSuccess("Successfully created image. ");
} }
Handle<SHVkImageView> SHVkImage::CreateImageView(Handle<SHVkLogicalDevice> const& inLogicalDeviceHdl, Handle<SHVkImage> const& parent, SHImageViewDetails const& createParams) const noexcept Handle<SHVkImageView> SHVkImage::CreateImageView(Handle<SHVkLogicalDevice> const& inLogicalDeviceHdl, Handle<SHVkImage> const& parent, SHImageViewDetails const& createParams) const noexcept
@ -288,6 +293,16 @@ namespace SHADE
barrier.subresourceRange.layerCount = layerCount; barrier.subresourceRange.layerCount = layerCount;
} }
void SHVkImage::HandleResizeFramebufferImage(uint32_t newWidth, uint32_t newHeight) noexcept
{
vmaDestroyImage(*vmaAllocator, vkImage, alloc);
width = newWidth;
height = newHeight;
CreateFramebufferImage();
}
void SHVkImage::LinkWithExteriorImage(vk::Image inVkImage, vk::ImageType type, uint32_t inWidth, uint32_t inHeight, uint32_t inDepth, uint32_t layers, uint8_t levels, vk::Format format, vk::ImageUsageFlags flags) noexcept void SHVkImage::LinkWithExteriorImage(vk::Image inVkImage, vk::ImageType type, uint32_t inWidth, uint32_t inHeight, uint32_t inDepth, uint32_t layers, uint8_t levels, vk::Format format, vk::ImageUsageFlags flags) noexcept
{ {
vkImage = inVkImage; vkImage = inVkImage;

View File

@ -107,8 +107,8 @@ namespace SHADE
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* PRIVATE MEMBER FUNCTIONS */ /* PRIVATE MEMBER FUNCTIONS */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
void PrepStagingBuffer(void* data, uint32_t srcSize) noexcept; void PrepStagingBuffer(const void* data, uint32_t srcSize) noexcept;
void CreateFramebufferImage (void) noexcept;
public: public:
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
@ -119,7 +119,7 @@ namespace SHADE
SHVkImage( SHVkImage(
VmaAllocator const* allocator, VmaAllocator const* allocator,
SHImageCreateParams const& imageDetails, SHImageCreateParams const& imageDetails,
unsigned char* data, const unsigned char* data,
uint32_t dataSize, uint32_t dataSize,
std::span<uint32_t> inMipOffsets, std::span<uint32_t> inMipOffsets,
VmaMemoryUsage memUsage, VmaMemoryUsage memUsage,
@ -137,6 +137,7 @@ namespace SHADE
Handle<SHVkImageView> CreateImageView (Handle<SHVkLogicalDevice> const& inLogicalDeviceHdl, Handle<SHVkImage> const& parent, SHImageViewDetails const& createParams) const noexcept; Handle<SHVkImageView> CreateImageView (Handle<SHVkLogicalDevice> const& inLogicalDeviceHdl, Handle<SHVkImage> const& parent, SHImageViewDetails const& createParams) const noexcept;
void TransferToDeviceResource (Handle<SHVkCommandBuffer> cmdBufferHdl) noexcept; void TransferToDeviceResource (Handle<SHVkCommandBuffer> cmdBufferHdl) noexcept;
void PrepareImageTransitionInfo (vk::ImageLayout oldLayout, vk::ImageLayout newLayout, vk::ImageMemoryBarrier& barrier) noexcept; void PrepareImageTransitionInfo (vk::ImageLayout oldLayout, vk::ImageLayout newLayout, vk::ImageMemoryBarrier& barrier) noexcept;
void HandleResizeFramebufferImage(uint32_t newWidth, uint32_t newHeight) noexcept;
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* GETTERS AND SETTERS */ /* GETTERS AND SETTERS */

View File

@ -6,27 +6,13 @@
namespace SHADE namespace SHADE
{ {
/***************************************************************************/
/*!
\brief void SHVkImageView::Create(void) noexcept
Non-default ctor. Initializes image view with image that it is a view of.
\param parent
Parent image the view is a view of.
*/
/***************************************************************************/
SHVkImageView::SHVkImageView(Handle<SHVkLogicalDevice> const& inLogicalDeviceHdl, Handle<SHVkImage> const& parent, SHImageViewDetails const& createParams) noexcept
: parentImage{ }
, vkImageView{}
, imageViewDetails{}
, logicalDeviceHdl {inLogicalDeviceHdl}
{ {
auto parentImageCreateFlags = parent->GetImageeCreateFlags(); auto parentImageCreateFlags = parentImage->GetImageeCreateFlags();
// 2D array image type means parent image must be 2D array compatible // 2D array image type means parent image must be 2D array compatible
if (createParams.viewType == vk::ImageViewType::e2DArray) if (imageViewDetails.viewType == vk::ImageViewType::e2DArray)
{ {
if (!(parentImageCreateFlags & vk::ImageCreateFlagBits::e2DArrayCompatible)) if (!(parentImageCreateFlags & vk::ImageCreateFlagBits::e2DArrayCompatible))
{ {
@ -36,7 +22,7 @@ namespace SHADE
} }
// Check if its possible for the image view to have different format than parent image // Check if its possible for the image view to have different format than parent image
if (createParams.format != parent->GetImageFormat()) if (imageViewDetails.format != parentImage->GetImageFormat())
{ {
if (!(parentImageCreateFlags & vk::ImageCreateFlagBits::eMutableFormat)) if (!(parentImageCreateFlags & vk::ImageCreateFlagBits::eMutableFormat))
{ {
@ -49,9 +35,9 @@ namespace SHADE
vk::ImageViewCreateInfo viewCreateInfo vk::ImageViewCreateInfo viewCreateInfo
{ {
.pNext = nullptr, // Can be used to override with a VkImageViewUsageCreateInfo to override usage. See Vulkan spec page 877 for more information .pNext = nullptr, // Can be used to override with a VkImageViewUsageCreateInfo to override usage. See Vulkan spec page 877 for more information
.image = parent->GetVkImage(), .image = parentImage->GetVkImage(),
.viewType = createParams.viewType, .viewType = imageViewDetails.viewType,
.format = createParams.format, .format = imageViewDetails.format,
.components .components
{ {
.r = vk::ComponentSwizzle::eR, .r = vk::ComponentSwizzle::eR,
@ -61,15 +47,15 @@ namespace SHADE
}, },
.subresourceRange .subresourceRange
{ {
.aspectMask = createParams.imageAspectFlags, .aspectMask = imageViewDetails.imageAspectFlags,
.baseMipLevel = createParams.baseMipLevel, .baseMipLevel = imageViewDetails.baseMipLevel,
.levelCount = createParams.mipLevelCount, .levelCount = imageViewDetails.mipLevelCount,
.baseArrayLayer = createParams.baseArrayLayer, .baseArrayLayer = imageViewDetails.baseArrayLayer,
.layerCount = createParams.layerCount, .layerCount = imageViewDetails.layerCount,
}, },
}; };
if (auto result = inLogicalDeviceHdl->GetVkLogicalDevice().createImageView(&viewCreateInfo, nullptr, &vkImageView); result != vk::Result::eSuccess) if (auto result = logicalDeviceHdl->GetVkLogicalDevice().createImageView(&viewCreateInfo, nullptr, &vkImageView); result != vk::Result::eSuccess)
{ {
SHVulkanDebugUtil::ReportVkError(result, "Failed to create image view! "); SHVulkanDebugUtil::ReportVkError(result, "Failed to create image view! ");
return; return;
@ -79,9 +65,26 @@ namespace SHADE
SHVulkanDebugUtil::ReportVkSuccess("Successfully created image view. "); SHVulkanDebugUtil::ReportVkSuccess("Successfully created image view. ");
} }
// After success, THEN assign variables }
parentImage = parent;
imageViewDetails = createParams; /***************************************************************************/
/*!
\brief
Non-default ctor. Initializes image view with image that it is a view of.
\param parent
Parent image the view is a view of.
*/
/***************************************************************************/
SHVkImageView::SHVkImageView(Handle<SHVkLogicalDevice> const& inLogicalDeviceHdl, Handle<SHVkImage> const& parent, SHImageViewDetails const& createParams) noexcept
: parentImage{ parent }
, vkImageView{}
, imageViewDetails{createParams}
, logicalDeviceHdl {inLogicalDeviceHdl}
{
Create();
} }
SHVkImageView::SHVkImageView(SHVkImageView&& rhs) noexcept SHVkImageView::SHVkImageView(SHVkImageView&& rhs) noexcept
@ -94,6 +97,17 @@ namespace SHADE
} }
void SHVkImageView::ViewNewImage(Handle<SHVkImage> const& parent, SHImageViewDetails const& createParams) noexcept
{
imageViewDetails = createParams;
parentImage = parent;
if (vkImageView)
logicalDeviceHdl->GetVkLogicalDevice().destroyImageView(vkImageView, nullptr);
Create();
}
Handle<SHVkImage> const& SHVkImageView::GetParentImage(void) const noexcept Handle<SHVkImage> const& SHVkImageView::GetParentImage(void) const noexcept
{ {
return parentImage; return parentImage;

View File

@ -25,12 +25,17 @@ namespace SHADE
//! Logical Device needed for creation and destruction //! Logical Device needed for creation and destruction
Handle<SHVkLogicalDevice> logicalDeviceHdl; Handle<SHVkLogicalDevice> logicalDeviceHdl;
//! Create new image view
void Create (void) noexcept;
public: public:
SHVkImageView(Handle<SHVkLogicalDevice> const& inLogicalDeviceHdl, Handle<SHVkImage> const& parent, SHImageViewDetails const& createParams) noexcept; SHVkImageView(Handle<SHVkLogicalDevice> const& inLogicalDeviceHdl, Handle<SHVkImage> const& parent, SHImageViewDetails const& createParams) noexcept;
~SHVkImageView(void) noexcept; ~SHVkImageView(void) noexcept;
SHVkImageView(SHVkImageView&& rhs) noexcept; SHVkImageView(SHVkImageView&& rhs) noexcept;
SHVkImageView& operator=(SHVkImageView&& rhs) noexcept; SHVkImageView& operator=(SHVkImageView&& rhs) noexcept;
void ViewNewImage (Handle<SHVkImage> const& parent, SHImageViewDetails const& createParams) noexcept;
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* GETTERS AND SETTERS */ /* GETTERS AND SETTERS */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/

View File

@ -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 "SHpch.h"
#include "SHVkSampler.h" #include "SHVkSampler.h"
#include "Graphics/Devices/SHVkLogicalDevice.h"
namespace SHADE 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;
}
} }

View File

@ -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 #pragma once
// STL Includes
#include <vector>
// Project Includes
#include "Graphics/SHVulkanIncludes.h" #include "Graphics/SHVulkanIncludes.h"
#include "Resource/Handle.h"
namespace SHADE namespace SHADE
{ {
/*-----------------------------------------------------------------------------------*/
/* Forward Declarations */
/*-----------------------------------------------------------------------------------*/
class SHVkLogicalDevice;
/*-----------------------------------------------------------------------------------*/
/* Type Definitions */
/*-----------------------------------------------------------------------------------*/
/*************************************************************************************/
/*!
\brief
Holds parameters for constructing the SHVkSampler.
*/
/*************************************************************************************/
struct SHVkSamplerParams struct SHVkSamplerParams
{ {
vk::Filter minFilter; vk::Filter minFilter = vk::Filter::eLinear;
vk::Filter maxFilter; vk::Filter magFilter = vk::Filter::eLinear;
//vk::Filter maxFilter; 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 class SHVkSampler
{ {
private: public:
//! The vulkan sampler handler /*---------------------------------------------------------------------------------*/
vk::Sampler vkSampler; /* Constructors */
/*---------------------------------------------------------------------------------*/
SHVkSampler(Handle<SHVkLogicalDevice> logicalDevice, const SHVkSamplerParams& params = {}) noexcept;
SHVkSampler(SHVkSampler&& rhs) noexcept;
~SHVkSampler() noexcept;
public: /*---------------------------------------------------------------------------------*/
SHVkSampler () noexcept; /* Overloaded Operators */
SHVkSampler (SHVkSampler&& rhs) noexcept; /*---------------------------------------------------------------------------------*/
SHVkSampler&& operator=(SHVkSampler&& rhs) noexcept; 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
}; };
} }

View File

@ -22,8 +22,11 @@ of DigiPen Institute of Technology is prohibited.
#include "Graphics/Pipeline/SHVkPipeline.h" #include "Graphics/Pipeline/SHVkPipeline.h"
#include "Graphics/MiddleEnd/Interface/SHGraphicsConstants.h" #include "Graphics/MiddleEnd/Interface/SHGraphicsConstants.h"
#include "Graphics/MiddleEnd/Interface/SHMaterialInstance.h" #include "Graphics/MiddleEnd/Interface/SHMaterialInstance.h"
#include "Graphics/Descriptors/SHVkDescriptorSetGroup.h"
#include "ECS_Base/Managers/SHComponentManager.h" #include "ECS_Base/Managers/SHComponentManager.h"
#include "Math/Transform/SHTransformComponent.h" #include "Math/Transform/SHTransformComponent.h"
#include "Graphics/MiddleEnd/GlobalData/SHGraphicsGlobalData.h"
#include "Graphics/Descriptors/SHVkDescriptorPool.h"
namespace SHADE 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) if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS)
{ {
@ -154,21 +157,17 @@ namespace SHADE
if (!matBufferDirty[frameIndex]) if (!matBufferDirty[frameIndex])
return; return;
// Build CPI Buffer // Build CPU Buffer
char* propsCurrPtr = matPropsData.get(); char* propsCurrPtr = matPropsData.get();
for (auto& subBatch : subBatches) for (auto& subBatch : subBatches)
for (const SHRenderable* renderable : subBatch.Renderables) for (const SHRenderable* renderable : subBatch.Renderables)
{ {
renderable->GetMaterial()->ExportProperties(propsCurrPtr); renderable->GetMaterial()->ExportProperties(propsCurrPtr);
propsCurrPtr += singleMatPropSize; propsCurrPtr += singleMatPropAlignedSize;
} }
// Transfer to GPU // Transfer to GPU
SHVkUtil::EnsureBufferAndCopyHostVisibleData rebuildMaterialBuffers(frameIndex, descPool);
(
device, matPropsBuffer[frameIndex], matPropsData.get(), static_cast<uint32_t>(matPropsDataSize),
vk::BufferUsageFlagBits::eStorageBuffer
);
// This frame is updated // This frame is updated
matBufferDirty[frameIndex] = false; matBufferDirty[frameIndex] = false;
@ -207,7 +206,7 @@ namespace SHADE
transformDataBuffer[frameIndex]->WriteToMemory(transformData.data(), static_cast<uint32_t>(transformData.size() * sizeof(SHMatrix)), 0, 0); 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) if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS)
{ {
@ -215,6 +214,9 @@ namespace SHADE
return; return;
} }
// Save logical device
device = _device;
// No need to build as there are no changes // No need to build as there are no changes
if (!isDirty[frameIndex]) if (!isDirty[frameIndex])
return; return;
@ -247,7 +249,8 @@ namespace SHADE
if (!EMPTY_MAT_PROPS) if (!EMPTY_MAT_PROPS)
{ {
singleMatPropSize = SHADER_INFO->GetBytesRequired(); singleMatPropSize = SHADER_INFO->GetBytesRequired();
matPropTotalBytes = drawData.size() * singleMatPropSize; singleMatPropAlignedSize = device->PadSSBOSize(static_cast<uint32_t>(singleMatPropSize));
matPropTotalBytes = numTotalElements * singleMatPropAlignedSize;
if (matPropsDataSize < matPropTotalBytes) if (matPropsDataSize < matPropTotalBytes)
{ {
matPropsData.reset(new char[matPropTotalBytes]); matPropsData.reset(new char[matPropTotalBytes]);
@ -267,7 +270,7 @@ namespace SHADE
.instanceCount = static_cast<uint32_t>(subBatch.Renderables.size()), .instanceCount = static_cast<uint32_t>(subBatch.Renderables.size()),
.firstIndex = subBatch.Mesh->FirstIndex, .firstIndex = subBatch.Mesh->FirstIndex,
.vertexOffset = subBatch.Mesh->FirstVertex, .vertexOffset = subBatch.Mesh->FirstVertex,
.firstInstance = nextInstanceIndex .firstInstance = nextInstanceIndex++
}); });
// Fill in buffers (CPU) // Fill in buffers (CPU)
@ -289,7 +292,7 @@ namespace SHADE
if (!EMPTY_MAT_PROPS) if (!EMPTY_MAT_PROPS)
{ {
renderable->GetMaterial()->ExportProperties(propsCurrPtr); 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)); const uint32_t DRAW_DATA_BYTES = static_cast<uint32_t>(drawData.size() * sizeof(vk::DrawIndexedIndirectCommand));
SHVkUtil::EnsureBufferAndCopyHostVisibleData SHVkUtil::EnsureBufferAndCopyHostVisibleData
( (
_device, drawDataBuffer[frameIndex], drawData.data(), DRAW_DATA_BYTES, device, drawDataBuffer[frameIndex], drawData.data(), DRAW_DATA_BYTES,
BuffUsage::eIndirectBuffer BuffUsage::eIndirectBuffer
); );
// - Transform Buffer // - Transform Buffer
const uint32_t TF_DATA_BYTES = static_cast<uint32_t>(transformData.size() * sizeof(SHMatrix)); const uint32_t TF_DATA_BYTES = static_cast<uint32_t>(transformData.size() * sizeof(SHMatrix));
SHVkUtil::EnsureBufferAndCopyHostVisibleData SHVkUtil::EnsureBufferAndCopyHostVisibleData
( (
_device, transformDataBuffer[frameIndex], transformData.data(), TF_DATA_BYTES, device, transformDataBuffer[frameIndex], transformData.data(), TF_DATA_BYTES,
BuffUsage::eVertexBuffer BuffUsage::eVertexBuffer
); );
// - Material Properties Buffer // - Material Properties Buffer
if (matPropsData) rebuildMaterialBuffers(frameIndex, descPool);
{
SHVkUtil::EnsureBufferAndCopyHostVisibleData
(
_device, matPropsBuffer[frameIndex], matPropsData.get(), static_cast<uint32_t>(matPropsDataSize),
BuffUsage::eStorageBuffer
);
}
// Mark this frame as no longer dirty
isDirty[frameIndex] = false; isDirty[frameIndex] = false;
// Save logical device
this->device = _device;
} }
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
@ -341,8 +335,20 @@ namespace SHADE
return; return;
} }
// Bind all required objects before drawing
static std::array<uint32_t, 1> dynamicOffset { 0 };
cmdBuffer->BindPipeline(pipeline); cmdBuffer->BindPipeline(pipeline);
cmdBuffer->BindVertexBuffer(SHGraphicsConstants::VertexBufferBindings::TRANSFORM, transformDataBuffer[frameIndex], 0); 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())); cmdBuffer->DrawMultiIndirect(drawDataBuffer[frameIndex], static_cast<uint32_t>(drawData.size()));
} }
@ -355,4 +361,39 @@ namespace SHADE
dirt = true; dirt = true;
isCPUBuffersDirty = true; isCPUBuffersDirty = true;
} }
void SHBatch::rebuildMaterialBuffers(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool)
{
if (matPropsData)
{
SHVkUtil::EnsureBufferAndCopyHostVisibleData
(
device, matPropsBuffer[frameIndex], matPropsData.get(), static_cast<uint32_t>(matPropsDataSize),
vk::BufferUsageFlagBits::eStorageBuffer
);
if (!matPropsDescSet[frameIndex])
{
matPropsDescSet[frameIndex] = descPool->Allocate
(
{ SHGraphicsGlobalData::GetDescSetLayouts()[SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE] },
{ 0 }
);
}
std::array<Handle<SHVkBuffer>, 1> bufferList = { matPropsBuffer[frameIndex] };
matPropsDescSet[frameIndex]->ModifyWriteDescBuffer
(
SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE,
SHGraphicsConstants::DescriptorSetBindings::BATCHED_PER_INST_DATA,
bufferList,
0, static_cast<uint32_t>(matPropsDataSize)
);
matPropsDescSet[frameIndex]->UpdateDescriptorSetBuffer
(
SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE,
SHGraphicsConstants::DescriptorSetBindings::BATCHED_PER_INST_DATA
);
}
}
} }

View File

@ -35,6 +35,8 @@ namespace SHADE
class SHRenderable; class SHRenderable;
class SHVkLogicalDevice; class SHVkLogicalDevice;
class SHMaterialInstance; class SHMaterialInstance;
class SHVkDescriptorSetGroup;
class SHVkDescriptorPool;
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Type Definitions */ /* Type Definitions */
@ -74,9 +76,9 @@ namespace SHADE
void Add(const SHRenderable* renderable); void Add(const SHRenderable* renderable);
void Remove(const SHRenderable* renderable); void Remove(const SHRenderable* renderable);
void Clear(); void Clear();
void UpdateMaterialBuffer(uint32_t frameIndex); void UpdateMaterialBuffer(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool);
void UpdateTransformBuffer(uint32_t frameIndex); 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); void Draw(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex);
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
@ -84,34 +86,44 @@ namespace SHADE
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
Handle<SHVkPipeline> GetPipeline() const noexcept { return pipeline; }; 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 */ /* Data Members */
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
// Resources // Resources
Handle<SHVkLogicalDevice> device; Handle<SHVkLogicalDevice> device;
// Batch Properties // Batch Properties
Handle<SHVkPipeline> pipeline; Handle<SHVkPipeline> pipeline;
std::unordered_set<Handle<SHMaterialInstance>> referencedMatInstances; std::unordered_set<Handle<SHMaterialInstance>> referencedMatInstances;
std::array<bool, SHGraphicsConstants::NUM_FRAME_BUFFERS> matBufferDirty; TripleBool matBufferDirty;
// Batch Tree // Batch Tree
std::vector<SHSubBatch> subBatches; std::vector<SHSubBatch> subBatches;
std::array<bool, SHGraphicsConstants::NUM_FRAME_BUFFERS> isDirty; TripleBool isDirty;
// CPU Buffers // CPU Buffers
std::vector<vk::DrawIndexedIndirectCommand> drawData; std::vector<vk::DrawIndexedIndirectCommand> drawData;
std::vector<SHMatrix> transformData; std::vector<SHMatrix> transformData;
std::unique_ptr<char> matPropsData; std::unique_ptr<char> matPropsData;
Byte matPropsDataSize = 0; Byte matPropsDataSize = 0;
Byte singleMatPropSize = 0; Byte singleMatPropAlignedSize = 0;
bool isCPUBuffersDirty = true; Byte singleMatPropSize = 0;
bool isCPUBuffersDirty = true;
// GPU Buffers // GPU Buffers
std::array<Handle<SHVkBuffer>, SHGraphicsConstants::NUM_FRAME_BUFFERS> drawDataBuffer; TripleBuffer drawDataBuffer;
std::array<Handle<SHVkBuffer>, SHGraphicsConstants::NUM_FRAME_BUFFERS> transformDataBuffer; TripleBuffer transformDataBuffer;
std::array<Handle<SHVkBuffer>, SHGraphicsConstants::NUM_FRAME_BUFFERS> matPropsBuffer; TripleBuffer matPropsBuffer;
TripleDescSet matPropsDescSet;
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* Helper Functions */ /* Helper Functions */
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
void setAllDirtyFlags(); void setAllDirtyFlags();
void rebuildMaterialBuffers(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool);
}; };
} }

View File

@ -91,12 +91,12 @@ namespace SHADE
(*superBatch)->Remove(renderable); (*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 // Build SuperBatches
for (auto& batch : superBatches) for (auto& batch : superBatches)
{ {
batch->Build(device, frameIndex); batch->Build(device, descPool, frameIndex);
} }
} }
@ -109,11 +109,11 @@ namespace SHADE
superBatches.clear(); superBatches.clear();
} }
void SHBatcher::UpdateBuffers(uint32_t frameIndex) void SHBatcher::UpdateBuffers(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool)
{ {
for (auto& batch : superBatches) for (auto& batch : superBatches)
{ {
batch->UpdateBuffers(frameIndex); batch->UpdateBuffers(frameIndex, descPool);
} }
} }

View File

@ -27,6 +27,7 @@ namespace SHADE
class SHSuperBatch; class SHSuperBatch;
class SHVkLogicalDevice; class SHVkLogicalDevice;
class SHVkCommandBuffer; class SHVkCommandBuffer;
class SHVkDescriptorPool;
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Type Definitions */ /* Type Definitions */
@ -51,9 +52,9 @@ namespace SHADE
void PrepareBatches(); void PrepareBatches();
void AddToBatch(SHRenderable const* renderable); void AddToBatch(SHRenderable const* renderable);
void RemoveFromBatch(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 ClearBatches();
void UpdateBuffers(uint32_t frameIndex); void UpdateBuffers(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool);
void RegisterSuperBatch(Handle<SHSuperBatch> superBatch); void RegisterSuperBatch(Handle<SHSuperBatch> superBatch);
void DeregisterSuperBatch(Handle<SHSuperBatch> superBatch); void DeregisterSuperBatch(Handle<SHSuperBatch> superBatch);

View File

@ -16,6 +16,7 @@ of DigiPen Institute of Technology is prohibited.
#include "SHBatch.h" #include "SHBatch.h"
#include "Graphics/MiddleEnd/Interface/SHMaterialInstance.h" #include "Graphics/MiddleEnd/Interface/SHMaterialInstance.h"
#include "Graphics/MiddleEnd/Interface/SHRenderable.h" #include "Graphics/MiddleEnd/Interface/SHRenderable.h"
#include "Graphics/Descriptors/SHVkDescriptorPool.h"
namespace SHADE namespace SHADE
{ {
@ -78,21 +79,21 @@ namespace SHADE
batches.clear(); batches.clear();
} }
void SHSuperBatch::UpdateBuffers(uint32_t frameIndex) void SHSuperBatch::UpdateBuffers(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool)
{ {
for (auto& batch : batches) for (auto& batch : batches)
{ {
batch.UpdateMaterialBuffer(frameIndex); batch.UpdateMaterialBuffer(frameIndex, descPool);
batch.UpdateTransformBuffer(frameIndex); 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 // Build all batches
for (auto& batch : batches) for (auto& batch : batches)
{ {
batch.Build(device, frameIndex); batch.Build(device, descPool, frameIndex);
} }
} }

View File

@ -55,8 +55,8 @@ namespace SHADE
void Add(const SHRenderable* renderable) noexcept; void Add(const SHRenderable* renderable) noexcept;
void Remove(const SHRenderable* renderable) noexcept; void Remove(const SHRenderable* renderable) noexcept;
void Clear() noexcept; void Clear() noexcept;
void UpdateBuffers(uint32_t frameIndex); void UpdateBuffers(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool);
void Build(Handle<SHVkLogicalDevice> device, uint32_t frameIndex) noexcept; void Build(Handle<SHVkLogicalDevice> device, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) noexcept;
void Draw(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept; void Draw(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept;
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/

View File

@ -7,7 +7,22 @@
namespace SHADE 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 void SHGraphicsGlobalData::InitDescSetLayouts(Handle<SHVkLogicalDevice> logicalDevice) noexcept
{ {
SHVkDescriptorSetLayout::Binding genericDataBinding SHVkDescriptorSetLayout::Binding genericDataBinding
@ -87,18 +102,18 @@ namespace SHADE
InitDefaultVertexInputState(); InitDefaultVertexInputState();
} }
std::vector<Handle<SHVkDescriptorSetLayout>> const& SHGraphicsGlobalData::GetDescSetLayouts(void) const noexcept std::vector<Handle<SHVkDescriptorSetLayout>> const& SHGraphicsGlobalData::GetDescSetLayouts(void) noexcept
{ {
return globalDescSetLayouts; return globalDescSetLayouts;
} }
SHVertexInputState const& SHGraphicsGlobalData::GetDefaultViState(void) const noexcept SHVertexInputState const& SHGraphicsGlobalData::GetDefaultViState(void) noexcept
{ {
return defaultVertexInputState; return defaultVertexInputState;
} }
Handle<SHVkPipelineLayout> SHGraphicsGlobalData::GetDummyPipelineLayout(void) const noexcept Handle<SHVkPipelineLayout> SHGraphicsGlobalData::GetDummyPipelineLayout(void) noexcept
{ {
return dummyPipelineLayout; return dummyPipelineLayout;
} }

View File

@ -15,31 +15,38 @@ namespace SHADE
{ {
private: private:
//! Global descriptor set layouts. Used to allocate descriptor sets //! Global descriptor set layouts. Used to allocate descriptor sets
std::vector<Handle<SHVkDescriptorSetLayout>> globalDescSetLayouts; static std::vector<Handle<SHVkDescriptorSetLayout>> globalDescSetLayouts;
//! Global Descriptor sets //! Global Descriptor sets
Handle<SHVkDescriptorSetGroup> globalDescSets; static Handle<SHVkDescriptorSetGroup> globalDescSets;
//! Default vertex input state (used by everything). //! 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, //! 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. //! 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: public:
/*-----------------------------------------------------------------------*/
/* Constructors */
/*-----------------------------------------------------------------------*/
SHGraphicsGlobalData() = delete;
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* PUBLIC MEMBER FUNCTIONS */ /* PUBLIC MEMBER FUNCTIONS */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
void Init (Handle<SHVkLogicalDevice> logicalDevice) noexcept; static void Init (Handle<SHVkLogicalDevice> logicalDevice) noexcept;
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* SETTERS AND GETTERS */ /* SETTERS AND GETTERS */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
std::vector<Handle<SHVkDescriptorSetLayout>> const& GetDescSetLayouts (void) const noexcept; static std::vector<Handle<SHVkDescriptorSetLayout>> const& GetDescSetLayouts (void) noexcept;
SHVertexInputState const& GetDefaultViState (void) const noexcept; static SHVertexInputState const& GetDefaultViState (void) noexcept;
Handle<SHVkPipelineLayout> GetDummyPipelineLayout (void) const noexcept; static Handle<SHVkPipelineLayout> GetDummyPipelineLayout (void) noexcept;
}; };
} }

View File

@ -23,21 +23,39 @@ namespace SHADE
{ {
SHVec3 view = target - pos; view = SHVec3::Normalise(view); SHVec3 view = target - pos; view = SHVec3::Normalise(view);
SHVec3 right = SHVec3::Cross(view, up); right = SHVec3::Normalise(right); 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 = SHMatrix::Identity;
viewMatrix(0, 0) = UP[0]; viewMatrix(0, 0) = right[0];
viewMatrix(1, 0) = UP[1]; viewMatrix(0, 1) = right[1];
viewMatrix(2, 0) = UP[2]; viewMatrix(0, 2) = right[2];
viewMatrix(0, 1) = right[0];
viewMatrix(1, 1) = right[1]; viewMatrix(1, 0) = UP[0];
viewMatrix(2, 1) = right[2]; viewMatrix(1, 1) = UP[1];
viewMatrix(0, 2) = view[0]; viewMatrix(1, 2) = UP[2];
viewMatrix(1, 2) = view[1];
viewMatrix(2, 2) = view[2]; viewMatrix(2, 0) = view[0];
viewMatrix(3, 0) = -UP.Dot(pos); viewMatrix(2, 1) = view[1];
viewMatrix(3, 1) = -right.Dot(pos); viewMatrix(2, 2) = view[2];
viewMatrix(3, 2) = -view.Dot(pos);
viewMatrix(0, 3) = -right.Dot(pos);
viewMatrix(1, 3) = -UP.Dot(pos);
viewMatrix(2, 3) = -view.Dot(pos);
isDirty = true; isDirty = true;
} }

View File

@ -69,7 +69,7 @@ namespace SHADE
SHMatrix inverseViewMatrix; SHMatrix inverseViewMatrix;
SHMatrix inverseProjMatrix; SHMatrix inverseProjMatrix;
SHMatrix inverseVpMatrix; SHMatrix inverseVpMatrix;
bool isDirty; bool isDirty = true;
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* Helper Functions */ /* Helper Functions */

View File

@ -30,6 +30,8 @@ of DigiPen Institute of Technology is prohibited.
#include "SHGraphicsConstants.h" #include "SHGraphicsConstants.h"
#include "Graphics/MiddleEnd/GlobalData/SHGraphicsGlobalData.h" #include "Graphics/MiddleEnd/GlobalData/SHGraphicsGlobalData.h"
#include "Graphics/Buffers/SHVkBuffer.h" #include "Graphics/Buffers/SHVkBuffer.h"
#include "Graphics/Images/SHVkSampler.h"
#include "Assets/Asset Types/SHTextureAsset.h"
namespace SHADE namespace SHADE
{ {
@ -65,9 +67,17 @@ namespace SHADE
// Register callback to notify render context upon a window resize // Register callback to notify render context upon a window resize
window->RegisterWindowSizeCallback([&]([[maybe_unused]] uint32_t width, [[maybe_unused]] uint32_t height) window->RegisterWindowSizeCallback([&]([[maybe_unused]] uint32_t width, [[maybe_unused]] uint32_t height)
{ {
if (width == 0 || height == 0)
return;
renderContext.SetIsResized(true); renderContext.SetIsResized(true);
}); });
window->RegisterWindowCloseCallback([&](void)
{
renderContext.SetWindowIsDead(true);
}
);
// Create graphics queue // Create graphics queue
graphicsQueue = device->GetQueue(SH_Q_FAM::GRAPHICS, 0); graphicsQueue = device->GetQueue(SH_Q_FAM::GRAPHICS, 0);
transferQueue = device->GetQueue(SH_Q_FAM::TRANSFER, 0); transferQueue = device->GetQueue(SH_Q_FAM::TRANSFER, 0);
@ -91,8 +101,10 @@ namespace SHADE
descPool = device->CreateDescriptorPools(); descPool = device->CreateDescriptorPools();
// Create generic command buffer // Create generic command buffer
transferCmdPool = device->CreateCommandPool(SH_QUEUE_FAMILY_ARRAY_INDEX::TRANSFER, SH_CMD_POOL_RESET::POOL_BASED, true); //transferCmdPool = device->CreateCommandPool(SH_QUEUE_FAMILY_ARRAY_INDEX::GRAPHICS, SH_CMD_POOL_RESET::POOL_BASED, true);
transferCmdBuffer = transferCmdPool->RequestCommandBuffer(SH_CMD_BUFFER_TYPE::PRIMARY); 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,23 +118,22 @@ namespace SHADE
- Global data - Global data
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
globalData = resourceManager.Create<SHGraphicsGlobalData>(); SHGraphicsGlobalData::Init(device);
globalData->Init(device);
// Set Up Cameras // Set Up Cameras
screenCamera = resourceManager.Create<SHCamera>(); screenCamera = resourceManager.Create<SHCamera>();
screenCamera->SetLookAt(SHVec3(0.0f, 0.0f, -1.0f), SHVec3(0.0f, 0.0f, 1.0f), SHVec3(0.0f, 1.0f, 0.0f)); screenCamera->SetLookAt(SHVec3(0.0f, 0.0f, -1.0f), SHVec3(0.0f, 0.0f, 1.0f), SHVec3(0.0f, 1.0f, 0.0f));
screenCamera->SetOrthographic(static_cast<float>(windowDims.first), static_cast<float>(windowDims.second), 0.01f, 100.0f); screenCamera->SetOrthographic(static_cast<float>(windowDims.first), static_cast<float>(windowDims.second), 0.01f, 100.0f);
worldCamera = resourceManager.Create<SHCamera>(); 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, 0.0f, 0.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->SetPerspective(90.0f, static_cast<float>(windowDims.first), static_cast<float>(windowDims.second), 0.0f, 100.0f); worldCamera->SetPerspective(90.0f, static_cast<float>(windowDims.first), static_cast<float>(windowDims.second), 0.0f, 100.0f);
// Create Default Viewport // Create Default Viewport
defaultViewport = AddViewport(vk::Viewport(0.0f, 0.0f, static_cast<float>(window->GetWindowSize().first), static_cast<float>(window->GetWindowSize().second), 0.0f, 1.0f)); defaultViewport = AddViewport(vk::Viewport(0.0f, 0.0f, static_cast<float>(window->GetWindowSize().first), static_cast<float>(window->GetWindowSize().second), 0.0f, 1.0f));
// Get render graph from default viewport world renderer // Get render graph from default viewport world renderer
auto worldRenderGraph = resourceManager.Create<SHRenderGraph>(); worldRenderGraph = resourceManager.Create<SHRenderGraph>();
std::vector<Handle<SHVkCommandPool>> renderContextCmdPools{swapchain->GetNumImages()}; std::vector<Handle<SHVkCommandPool>> renderContextCmdPools{swapchain->GetNumImages()};
for (uint32_t i = 0; i < renderContextCmdPools.size(); ++i) for (uint32_t i = 0; i < renderContextCmdPools.size(); ++i)
@ -131,18 +142,20 @@ namespace SHADE
} }
// Initialize world render graph // 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("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("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("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); 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 //First subpass to write to G-Buffer
auto gBufferWriteSubpass = node->AddSubpass("G-Buffer Write"); auto gBufferWriteSubpass = node->AddSubpass("G-Buffer Write");
//gBufferWriteSubpass->AddColorOutput("Scene"); //gBufferWriteSubpass->AddColorOutput("Scene");
gBufferWriteSubpass->AddColorOutput("Present"); gBufferWriteSubpass->AddColorOutput("Present");
gBufferWriteSubpass->AddDepthOutput ("Depth Buffer", SH_ATT_DESC_TYPE::DEPTH_STENCIL);
//writeSubpass->AddColorOutput("Normals"); //writeSubpass->AddColorOutput("Normals");
// //Second subpass to read from G-Buffer // //Second subpass to read from G-Buffer
@ -171,7 +184,7 @@ namespace SHADE
debugWorldRenderer->SetCamera(worldCamera);*/ debugWorldRenderer->SetCamera(worldCamera);*/
// Add world renderer to default viewport // 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); worldRenderer->SetCamera(worldCamera);
@ -184,8 +197,8 @@ namespace SHADE
shaderModuleLibrary.ImportFromSourceLibrary(device, shaderSourceLibrary); shaderModuleLibrary.ImportFromSourceLibrary(device, shaderSourceLibrary);
auto cubeVS = shaderModuleLibrary.GetShaderModule("TestCubeVs.glsl"); auto cubeVS = shaderModuleLibrary.GetShaderModule("TestCubeVs.glsl");
auto cubeFS = shaderModuleLibrary.GetShaderModule("TestCubeFs.glsl"); auto cubeFS = shaderModuleLibrary.GetShaderModule("TestCubeFs.glsl");
//triVS->Reflect(); cubeVS->Reflect();
//triFS->Reflect(); cubeFS->Reflect();
defaultMaterial = AddMaterial(cubeVS, cubeFS, gBufferWriteSubpass); defaultMaterial = AddMaterial(cubeVS, cubeFS, gBufferWriteSubpass);
} }
@ -205,6 +218,15 @@ namespace SHADE
/***************************************************************************/ /***************************************************************************/
void SHGraphicsSystem::Run(double) noexcept void SHGraphicsSystem::Run(double) noexcept
{ {
if (window->IsMinimized() || renderContext.GetWindowIsDead())
return;
if (renderContext.GetResized())
{
return;
}
// Frame data for the current frame // Frame data for the current frame
auto const& frameData = renderContext.GetCurrentFrameData(); auto const& frameData = renderContext.GetCurrentFrameData();
uint32_t frameIndex = renderContext.GetCurrentFrame(); uint32_t frameIndex = renderContext.GetCurrentFrame();
@ -224,6 +246,9 @@ namespace SHADE
renderContext.ResetFence(); renderContext.ResetFence();
// Bind textures
// For every viewport // For every viewport
for (int vpIndex = 0; vpIndex < static_cast<int>(viewports.size()); ++vpIndex) for (int vpIndex = 0; vpIndex < static_cast<int>(viewports.size()); ++vpIndex)
{ {
@ -241,7 +266,11 @@ namespace SHADE
// Begin recording the command buffer // Begin recording the command buffer
currentCmdBuffer->BeginRecording(); currentCmdBuffer->BeginRecording();
currentCmdBuffer->ForceSetPipelineLayout(globalData->GetDummyPipelineLayout()); uint32_t w = static_cast<uint32_t>(viewports[vpIndex]->GetWidth());
uint32_t h = static_cast<uint32_t>(viewports[vpIndex]->GetHeight());
currentCmdBuffer->SetViewportScissor (static_cast<float>(w), static_cast<float>(h), w, h);
currentCmdBuffer->ForceSetPipelineLayout(SHGraphicsGlobalData::GetDummyPipelineLayout());
// Bind all the buffers required for meshes // Bind all the buffers required for meshes
for (auto& [buffer, bindingPoint] : MESH_DATA) for (auto& [buffer, bindingPoint] : MESH_DATA)
@ -252,11 +281,26 @@ namespace SHADE
currentCmdBuffer->BindIndexBuffer(buffer, 0); 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 // bind camera data
renderers[renIndex]->UpdateDataAndBind(currentCmdBuffer, frameIndex); renderers[renIndex]->UpdateDataAndBind(currentCmdBuffer, frameIndex);
// Draw first // Draw first
renderers[renIndex]->Draw(frameIndex); renderers[renIndex]->Draw(frameIndex, descPool);
// End the command buffer recording // End the command buffer recording
currentCmdBuffer->EndRecording(); currentCmdBuffer->EndRecording();
@ -281,13 +325,6 @@ namespace SHADE
void SHGraphicsSystem::Exit(void) void SHGraphicsSystem::Exit(void)
{ {
renderContext.Destroy();
graphicsQueue.Free();
swapchain.Free();
surface.Free();
device.Free();
SHVkInstance::Destroy();
} }
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
@ -305,11 +342,14 @@ namespace SHADE
/***************************************************************************/ /***************************************************************************/
void SHGraphicsSystem::BeginRender() void SHGraphicsSystem::BeginRender()
{ {
if (window->IsMinimized() || renderContext.GetWindowIsDead())
return;
// Finalise all batches // Finalise all batches
for (auto vp : viewports) for (auto vp : viewports)
for (auto renderer : vp->GetRenderers()) for (auto renderer : vp->GetRenderers())
{ {
renderer->GetRenderGraph()->FinaliseBatch(renderContext.GetCurrentFrame()); renderer->GetRenderGraph()->FinaliseBatch(renderContext.GetCurrentFrame(), descPool);
} }
// Resize // Resize
@ -318,10 +358,7 @@ namespace SHADE
{ {
device->WaitIdle(); device->WaitIdle();
// Resize the swapchain HandleResize();
swapchain->Resize(surface, windowDims.first, windowDims.second);
renderContext.HandleResize();
} }
const uint32_t CURR_FRAME_IDX = renderContext.GetCurrentFrame(); const uint32_t CURR_FRAME_IDX = renderContext.GetCurrentFrame();
@ -354,6 +391,16 @@ namespace SHADE
/***************************************************************************/ /***************************************************************************/
void SHGraphicsSystem::EndRender() void SHGraphicsSystem::EndRender()
{ {
if (window->IsMinimized() || renderContext.GetWindowIsDead())
return;
if (renderContext.GetResized())
{
return;
}
const uint32_t CURR_FRAME_IDX = renderContext.GetCurrentFrame(); const uint32_t CURR_FRAME_IDX = renderContext.GetCurrentFrame();
auto& currFrameData = renderContext.GetCurrentFrameData(); auto& currFrameData = renderContext.GetCurrentFrameData();
@ -364,10 +411,8 @@ namespace SHADE
// If swapchain is incompatible/outdated // If swapchain is incompatible/outdated
if (result == vk::Result::eErrorOutOfDateKHR || result == vk::Result::eSuboptimalKHR) if (result == vk::Result::eErrorOutOfDateKHR || result == vk::Result::eSuboptimalKHR)
{ {
auto windowDims = window->GetWindowSize();
swapchain->Resize(surface, windowDims.first, windowDims.second);
renderContext.HandleResize(); HandleResize();
} }
} }
@ -455,7 +500,60 @@ namespace SHADE
transferCmdBuffer->BeginRecording(); transferCmdBuffer->BeginRecording();
meshLibrary.BuildBuffers(device, transferCmdBuffer); meshLibrary.BuildBuffers(device, transferCmdBuffer);
transferCmdBuffer->EndRecording(); 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::HandleResize(void) noexcept
{
if (window->IsMinimized() || renderContext.GetWindowIsDead())
return;
auto windowDims = window->GetWindowSize();
// Resize the swapchain
swapchain->Resize(surface, windowDims.first, windowDims.second);
renderContext.HandleResize();
worldRenderGraph->HandleResize(windowDims.first, windowDims.second);
defaultViewport->SetWidth(static_cast<float>(windowDims.first));
defaultViewport->SetHeight(static_cast<float>(windowDims.second));
worldCamera->SetPerspective(90.0f, static_cast<float>(windowDims.first), static_cast<float>(windowDims.second), 0.0f, 100.0f);
}
void SHGraphicsSystem::AwaitGraphicsExecution()
{
device->WaitIdle();
} }
void SHGraphicsSystem::SetWindow(SHWindow* wind) noexcept void SHGraphicsSystem::SetWindow(SHWindow* wind) noexcept
@ -463,20 +561,49 @@ namespace SHADE
window = wind; window = wind;
} }
/*-----------------------------------------------------------------------------------*/
/* System Routine Functions - BeginRoutine */
/*-----------------------------------------------------------------------------------*/
SHGraphicsSystem::BeginRoutine::BeginRoutine()
: SHSystemRoutine("Graphics System Frame Set Up", false)
{}
void SHGraphicsSystem::BeginRoutine::Execute(double) noexcept void SHGraphicsSystem::BeginRoutine::Execute(double) noexcept
{ {
reinterpret_cast<SHGraphicsSystem*>(system)->BeginRender(); reinterpret_cast<SHGraphicsSystem*>(system)->BeginRender();
} }
/*-----------------------------------------------------------------------------------*/
/* System Routine Functions - RenderRoutine */
/*-----------------------------------------------------------------------------------*/
SHGraphicsSystem::RenderRoutine::RenderRoutine()
: SHSystemRoutine("Graphics System Render", false)
{}
void SHGraphicsSystem::RenderRoutine::Execute(double dt) noexcept void SHGraphicsSystem::RenderRoutine::Execute(double dt) noexcept
{ {
reinterpret_cast<SHGraphicsSystem*>(system)->Run(dt); reinterpret_cast<SHGraphicsSystem*>(system)->Run(dt);
} }
/*-----------------------------------------------------------------------------------*/
/* System Routine Functions - EndRoutine */
/*-----------------------------------------------------------------------------------*/
SHGraphicsSystem::EndRoutine::EndRoutine()
: SHSystemRoutine("Graphics System Frame Clean Up", false)
{}
void SHGraphicsSystem::EndRoutine::Execute(double) noexcept void SHGraphicsSystem::EndRoutine::Execute(double) noexcept
{ {
reinterpret_cast<SHGraphicsSystem*>(system)->EndRender(); reinterpret_cast<SHGraphicsSystem*>(system)->EndRender();
} }
/*-----------------------------------------------------------------------------------*/
/* System Routine Functions - BatcherDispatcherRoutine */
/*-----------------------------------------------------------------------------------*/
SHGraphicsSystem::BatcherDispatcherRoutine::BatcherDispatcherRoutine()
: SHSystemRoutine("Graphics System Batcher Dispatcher", false)
{}
void SHGraphicsSystem::BatcherDispatcherRoutine::Execute(double) noexcept void SHGraphicsSystem::BatcherDispatcherRoutine::Execute(double) noexcept
{ {
auto& renderables = SHComponentManager::GetDense<SHRenderable>(); auto& renderables = SHComponentManager::GetDense<SHRenderable>();
@ -493,9 +620,13 @@ namespace SHADE
oldSuperBatch->Remove(&renderable); oldSuperBatch->Remove(&renderable);
} }
// Add to new SuperBatch // Add to new SuperBatch if there is a material
Handle<SHSuperBatch> newSuperBatch = renderable.GetMaterial()->GetBaseMaterial()->GetPipeline()->GetPipelineState().GetSubpass()->GetSuperBatch(); Handle<SHMaterialInstance> newMatInstance = renderable.GetMaterial();
newSuperBatch->Add(&renderable); if (newMatInstance)
{
Handle<SHSuperBatch> newSuperBatch = newMatInstance->GetBaseMaterial()->GetPipeline()->GetPipelineState().GetSubpass()->GetSuperBatch();
newSuperBatch->Add(&renderable);
}
// Unset change flag // Unset change flag
renderable.ResetChangedFlag(); renderable.ResetChangedFlag();

View File

@ -29,6 +29,8 @@ of DigiPen Institute of Technology is prohibited.
#include "Graphics/MiddleEnd/Shaders/SHShaderModuleLibrary.h" #include "Graphics/MiddleEnd/Shaders/SHShaderModuleLibrary.h"
#include "SHMeshLibrary.h" #include "SHMeshLibrary.h"
#include "Graphics/MiddleEnd/Materials/SHMaterialInstanceCache.h" #include "Graphics/MiddleEnd/Materials/SHMaterialInstanceCache.h"
#include "../Textures/SHTextureLibrary.h"
#include "../Textures/SHVkSamplerCache.h"
namespace SHADE namespace SHADE
{ {
@ -67,21 +69,25 @@ namespace SHADE
class SH_API BeginRoutine final : public SHSystemRoutine class SH_API BeginRoutine final : public SHSystemRoutine
{ {
public: public:
BeginRoutine();
virtual void Execute(double dt) noexcept override final; virtual void Execute(double dt) noexcept override final;
}; };
class SH_API RenderRoutine final : public SHSystemRoutine class SH_API RenderRoutine final : public SHSystemRoutine
{ {
public: public:
RenderRoutine();
virtual void Execute(double dt) noexcept override final; virtual void Execute(double dt) noexcept override final;
}; };
class SH_API EndRoutine final : public SHSystemRoutine class SH_API EndRoutine final : public SHSystemRoutine
{ {
public: public:
EndRoutine();
virtual void Execute(double dt) noexcept override final; virtual void Execute(double dt) noexcept override final;
}; };
class SH_API BatcherDispatcherRoutine final : public SHSystemRoutine class SH_API BatcherDispatcherRoutine final : public SHSystemRoutine
{ {
public: public:
BatcherDispatcherRoutine();
virtual void Execute(double dt) noexcept override final; virtual void Execute(double dt) noexcept override final;
}; };
@ -188,6 +194,65 @@ namespace SHADE
/***************************************************************************/ /***************************************************************************/
void BuildMeshBuffers(); 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();
void HandleResize(void) noexcept;
void AwaitGraphicsExecution();
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* Setters */ /* Setters */
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
@ -220,19 +285,19 @@ namespace SHADE
Handle<SHVkQueue> graphicsQueue; Handle<SHVkQueue> graphicsQueue;
Handle<SHVkQueue> transferQueue; Handle<SHVkQueue> transferQueue;
Handle<SHVkDescriptorPool> descPool; Handle<SHVkDescriptorPool> descPool;
Handle<SHVkCommandPool> transferCmdPool; Handle<SHVkCommandPool> graphicsCmdPool;
Handle<SHVkCommandBuffer> transferCmdBuffer; Handle<SHVkCommandBuffer> transferCmdBuffer;
Handle<SHVkCommandBuffer> graphicsTexCmdBuffer;
SHRenderContext renderContext; SHRenderContext renderContext;
std::array<Handle<SHVkSemaphore>, 2> graphSemaphores; std::array<Handle<SHVkSemaphore>, 2> graphSemaphores;
// Not Owned Resources // Not Owned Resources
SHWindow* window = nullptr; SHWindow* window = nullptr;
// global data (descriptor sets as well)
Handle<SHGraphicsGlobalData> globalData;
// Middle End Resources // Middle End Resources
ResourceManager resourceManager; ResourceManager resourceManager;
SHMeshLibrary meshLibrary; SHMeshLibrary meshLibrary;
SHTextureLibrary texLibrary;
SHSamplerCache samplerCache;
SHMaterialInstanceCache materialInstanceCache; SHMaterialInstanceCache materialInstanceCache;
// Viewports // Viewports
Handle<SHViewport> defaultViewport; // Whole screen Handle<SHViewport> defaultViewport; // Whole screen
@ -255,5 +320,7 @@ namespace SHADE
// Temp Materials // Temp Materials
Handle<SHMaterial> defaultMaterial; Handle<SHMaterial> defaultMaterial;
Handle<SHRenderGraph> worldRenderGraph;
}; };
} }

View File

@ -63,7 +63,7 @@ namespace SHADE
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
Handle<SHVkPipeline> pipeline; Handle<SHVkPipeline> pipeline;
std::unique_ptr<char> propMemory; std::unique_ptr<char> propMemory;
Byte propMemorySize; Byte propMemorySize = 0;
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* Helper Functions */ /* Helper Functions */

View File

@ -40,8 +40,6 @@ namespace SHADE
void SHMaterialInstance::ExportProperties(void* dest) void SHMaterialInstance::ExportProperties(void* dest)
{ {
assert(dataStore != nullptr);
if (!baseMaterial) if (!baseMaterial)
throw std::runtime_error("[SHMaterialInstance] Attempted to set export a Material Instance with no base Material!"); throw std::runtime_error("[SHMaterialInstance] Attempted to set export a Material Instance with no base Material!");

View File

@ -15,6 +15,7 @@ of DigiPen Institute of Technology is prohibited.
// Project Includes // Project Includes
#include "Resource/Handle.h" #include "Resource/Handle.h"
#include "Graphics/Shaders/BlockInterface/SHShaderBlockInterface.h" #include "Graphics/Shaders/BlockInterface/SHShaderBlockInterface.h"
#include "SH_API.h"
namespace SHADE namespace SHADE
{ {
@ -34,7 +35,7 @@ namespace SHADE
a SHRenderable. a SHRenderable.
*/ */
/***********************************************************************************/ /***********************************************************************************/
class SHMaterialInstance class SH_API SHMaterialInstance
{ {
public: public:
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/

View File

@ -48,7 +48,7 @@ namespace SHADE
} }
// Get offset and modify the memory directly // Get offset and modify the memory directly
T* dataPtr = dataStore.get() + od.StoredDataOffset; T* dataPtr = reinterpret_cast<T*>(dataStore.get() + od.StoredDataOffset);
*dataPtr = value; *dataPtr = value;
// Save the override data information // Save the override data information

View File

@ -81,7 +81,7 @@ namespace SHADE
if (!material) if (!material)
{ {
SHGraphicsSystem* gfxSystem = SHSystemManager::GetSystem<SHGraphicsSystem>(); SHGraphicsSystem* gfxSystem = SHSystemManager::GetSystem<SHGraphicsSystem>();
material = gfxSystem->AddOrGetBaseMaterialInstance(sharedMaterial->GetBaseMaterial()); material = gfxSystem->AddMaterialInstanceCopy(sharedMaterial);
} }
return material; return material;

View File

@ -49,6 +49,14 @@ namespace SHADE
cameraDescriptorSet->UpdateDescriptorSetBuffer(SHGraphicsConstants::DescriptorSetIndex::HIGH_FREQUENCY_GLOBALS, SHGraphicsConstants::DescriptorSetBindings::CAMERA_DATA); cameraDescriptorSet->UpdateDescriptorSetBuffer(SHGraphicsConstants::DescriptorSetIndex::HIGH_FREQUENCY_GLOBALS, SHGraphicsConstants::DescriptorSetBindings::CAMERA_DATA);
} }
SHRenderer::~SHRenderer(void)
{
//for (auto& cmdBuffer : commandBuffers)
//{
// cmdBuffer.Free();
//}
}
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Camera Registration */ /* Camera Registration */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
@ -60,9 +68,9 @@ namespace SHADE
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Drawing Functions */ /* 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 void SHRenderer::UpdateDataAndBind(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept

View File

@ -65,6 +65,7 @@ namespace SHADE
/* Constructor/Destructors */ /* Constructor/Destructors */
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
SHRenderer(Handle<SHVkLogicalDevice> logicalDevice, uint32_t numFrames, std::vector<Handle<SHVkCommandPool>>& cmdPools, Handle<SHVkDescriptorPool> descriptorPool, Handle<SHVkDescriptorSetLayout> cameraDescLayout, Handle<SHViewport> viewport, Handle<SHRenderGraph> renderGraph); SHRenderer(Handle<SHVkLogicalDevice> logicalDevice, uint32_t numFrames, std::vector<Handle<SHVkCommandPool>>& cmdPools, Handle<SHVkDescriptorPool> descriptorPool, Handle<SHVkDescriptorSetLayout> cameraDescLayout, Handle<SHViewport> viewport, Handle<SHRenderGraph> renderGraph);
~SHRenderer(void);
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* Camera Registration */ /* Camera Registration */
@ -74,7 +75,7 @@ namespace SHADE
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* Drawing Functions */ /* 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 UpdateDataAndBind (Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept;
void UpdateCameraDataToBuffer (void) noexcept; void UpdateCameraDataToBuffer (void) noexcept;

View File

@ -73,4 +73,16 @@ namespace SHADE
iter->Free(); iter->Free();
renderers.erase(iter); renderers.erase(iter);
} }
void SHViewport::SetWidth(float w) noexcept
{
viewport.width = w;
}
void SHViewport::SetHeight(float h) noexcept
{
viewport.height = h;
}
} }

Some files were not shown because too many files have changed in this diff Show More