Merge remote-tracking branch 'origin/SP3-1-Rendering' into SP3-1-Rendering

This commit is contained in:
Brandon Mak 2022-09-27 12:56:19 +08:00
commit 6f3c1ed97b
50 changed files with 4474 additions and 190 deletions

Binary file not shown.

Binary file not shown.

View File

@ -34,6 +34,7 @@ project "SHADE_Application"
"%{IncludeDir.VULKAN}/include", "%{IncludeDir.VULKAN}/include",
"%{IncludeDir.VMA}/include", "%{IncludeDir.VMA}/include",
"%{IncludeDir.VULKAN}/Source/SPIRV-Reflect", "%{IncludeDir.VULKAN}/Source/SPIRV-Reflect",
"%{IncludeDir.RTTR}/include",
"%{IncludeDir.tinyddsloader}" "%{IncludeDir.tinyddsloader}"
} }
@ -72,8 +73,12 @@ project "SHADE_Application"
filter "configurations:Debug" filter "configurations:Debug"
symbols "On" symbols "On"
defines {"_DEBUG"} defines {"_DEBUG", "SHEDITOR"}
filter "configurations:Release" filter "configurations:Release"
optimize "On"
defines{"_RELEASE", "SHEDITOR"}
filter "configurations:Publish"
optimize "On" optimize "On"
defines{"_RELEASE"} defines{"_RELEASE"}

View File

@ -4,7 +4,7 @@
//#define SHEDITOR //#define SHEDITOR
#ifdef SHEDITOR #ifdef SHEDITOR
#include "Editor/SHEditor.h" #include "Editor/SHEditor.hpp"
//#include "Scenes/SBEditorScene.h" //#include "Scenes/SBEditorScene.h"
#endif // SHEDITOR #endif // SHEDITOR
@ -46,14 +46,13 @@ namespace Sandbox
// Set working directory // Set working directory
SHADE::SHFileUtilities::SetWorkDirToExecDir(); SHADE::SHFileUtilities::SetWorkDirToExecDir();
SDL_Init(SDL_INIT_EVERYTHING);
window.Create(hInstance, hPrevInstance, lpCmdLine, nCmdShow); window.Create(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
// Create Systems // Create Systems
SHADE::SHSystemManager::CreateSystem<SHADE::SHGraphicsSystem>();
SHADE::SHSystemManager::CreateSystem<SHADE::SHScriptEngine>(); SHADE::SHSystemManager::CreateSystem<SHADE::SHScriptEngine>();
// TODO(Diren): Create Physics System here // TODO(Diren): Create Physics System here
SHADE::SHSystemManager::CreateSystem<SHADE::SHTransformSystem>(); SHADE::SHSystemManager::CreateSystem<SHADE::SHTransformSystem>();
SHADE::SHSystemManager::CreateSystem<SHADE::SHGraphicsSystem>();
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::SHInputManagerSystem>();
@ -86,12 +85,11 @@ namespace Sandbox
// Set up graphics system and windows // Set up graphics system and windows
graphicsSystem->SetWindow(&window); graphicsSystem->SetWindow(&window);
sdlWindow = SDL_CreateWindowFrom(window.GetHWND());
//auto [w, h] = window.GetWindowSize();
//SDL_SetWindowSize(sdlWindow, w, h);
SHADE::SHSystemManager::Init(); SHADE::SHSystemManager::Init();
#ifdef SHEDITOR #ifdef SHEDITOR
SDL_Init(SDL_INIT_VIDEO);
sdlWindow = SDL_CreateWindowFrom(window.GetHWND());
SHADE::SHEditor::Initialise(sdlWindow); SHADE::SHEditor::Initialise(sdlWindow);
#else #else
#endif #endif
@ -112,13 +110,9 @@ namespace Sandbox
graphicsSystem->BeginRender(); graphicsSystem->BeginRender();
#ifdef SHEDITOR #ifdef SHEDITOR
SHADE::SHEditor::PreRender(); SHADE::SHEditor::Update(0.16f);
//SHADE::SHEditor::Render();
#endif #endif
#ifdef SHEDITOR
SHADE::SHEditor::Render();
#endif
graphicsSystem->Run(1.0f); graphicsSystem->Run(1.0f);
graphicsSystem->EndRender(); graphicsSystem->EndRender();
@ -131,11 +125,12 @@ namespace Sandbox
{ {
#ifdef SHEDITOR #ifdef SHEDITOR
SHADE::SHEditor::Exit(); SHADE::SHEditor::Exit();
#endif
SHSceneManager::Exit();
SHADE::SHSystemManager::Exit();
SDL_DestroyWindow(sdlWindow); SDL_DestroyWindow(sdlWindow);
SDL_Quit(); SDL_Quit();
#endif
SHSceneManager::Exit();
SHADE::SHSystemManager::Exit();
} }
} }

View File

@ -54,6 +54,16 @@ namespace Sandbox
} }
graphicsSystem->BuildMeshBuffers(); graphicsSystem->BuildMeshBuffers();
// Load Textures
auto textures = SHADE::SHAssetManager::GetAllDDS();
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();

View File

@ -117,12 +117,24 @@ project "SHADE_Engine"
filter "configurations:Debug" filter "configurations:Debug"
symbols "On" symbols "On"
defines {"_DEBUG"} 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"} 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"
optimize "On"
defines{"_RELEASE"}
links{"assimp-vc142-mt.lib", "librttr_core.lib", "spdlog.lib"}
excludes
{
"%{prj.location}/src/Editor/**.cpp",
"%{prj.location}/src/Editor/**.h",
"%{prj.location}/src/Editor/**.hpp",
}
--links{"fmodstudio_vc.lib", "fmod_vc.lib"}

View File

@ -2,16 +2,17 @@
#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;
}; };
struct SHMeshAsset struct SH_API SHMeshAsset
{ {
bool compiled; bool compiled;
bool changed; bool changed;
@ -21,9 +22,9 @@ namespace SHADE
std::string meshName; std::string meshName;
std::vector<SHVec3> vertexPosition; std::vector<SHVec3> vertexPosition;
std::vector<SHVec2> texCoords;
std::vector<SHVec3> vertexTangent; std::vector<SHVec3> vertexTangent;
std::vector<SHVec3> vertexNormal; std::vector<SHVec3> vertexNormal;
std::vector<SHVec2> texCoords;
std::vector<uint32_t> indices; std::vector<uint32_t> indices;
}; };
} }

View File

@ -70,7 +70,8 @@ enum class AssetType : uint8_t
#define PREFAB_EXTENSION ".SHPrefab" #define PREFAB_EXTENSION ".SHPrefab"
#define MATERIAL_EXTENSION ".SHMat" #define MATERIAL_EXTENSION ".SHMat"
#define TEXTURE_EXTENSION ".dds" #define TEXTURE_EXTENSION ".dds"
#define MESH_EXTENSION ".fbx" #define FBX_EXTENSION ".fbx"
#define MESH_EXTENSION ".shmesh"
std::string const EXTENSIONS[] = { std::string const EXTENSIONS[] = {
AUDIO_EXTENSION, AUDIO_EXTENSION,
@ -82,7 +83,8 @@ std::string const EXTENSIONS[] = {
SCRIPT_EXTENSION, SCRIPT_EXTENSION,
SCENE_EXTENSION, SCENE_EXTENSION,
PREFAB_EXTENSION, PREFAB_EXTENSION,
AUDIO_WAV_EXTENSION AUDIO_WAV_EXTENSION,
FBX_EXTENSION
}; };
// Error flags // Error flags

View File

@ -199,7 +199,7 @@ namespace SHADE
{ {
AssetPath path{ p }; AssetPath path{ p };
if (path.extension().string() == MESH_EXTENSION) if (path.extension().string() == FBX_EXTENSION)
{ {
LoadGLTF( LoadGLTF(
{ {
@ -236,6 +236,17 @@ namespace SHADE
return result; return result;
} }
std::vector<SHDDSAsset> SHAssetManager::GetAllDDS() noexcept
{
std::vector<SHDDSAsset> result;
for (auto const& dds : ddsCollection)
{
result.push_back(dds.second);
}
return result;
}
/**************************************************************************** /****************************************************************************
* \param Path for meta data file * \param Path for meta data file
* \param Path for asset file * \param Path for asset file

View File

@ -73,6 +73,7 @@ namespace SHADE
//TODO: TEMPORARY FOR TESTING GLTF & DDS //TODO: TEMPORARY FOR TESTING GLTF & DDS
static void LoadDataTemp(std::string path) noexcept; static void LoadDataTemp(std::string path) noexcept;
static std::vector<SHMeshAsset> GetAllMeshes() noexcept; static std::vector<SHMeshAsset> GetAllMeshes() noexcept;
static std::vector<SHDDSAsset> GetAllDDS() noexcept;
private: private:
/**************************************************************************** /****************************************************************************

View File

@ -0,0 +1,51 @@
#pragma once
//#==============================================================#
//|| STL Includes ||
//#==============================================================#
#include <functional>
namespace SHADE
{
class SHBaseCommand
{
public:
virtual ~SHBaseCommand() = default;
virtual void Execute() {}
virtual void Undo() {}
virtual void Merge(std::shared_ptr<SHBaseCommand>) {}
};//struct SHBaseCommand
template <typename T>
class SHCommand : SHBaseCommand
{
public:
typedef std::function<void(T const&)> SetterFunction;
SHCommand(T const& oldVal, T const& value, SetterFunction setFnc)
: oldValue(oldVal), newValue(value), set(setFnc)
{
}
void Execute() override
{
set(newValue);
}
void Undo() override
{
set(oldValue);
}
void Merge(std::shared_ptr<SHBaseCommand> newCommand) override
{
newValue = std::reinterpret_pointer_cast<SHCommand>(newCommand)->newValue;
}
private:
T oldValue;
T newValue;
SetterFunction set;
};
}//namespace SHADE

View File

@ -0,0 +1,57 @@
//#==============================================================#
//|| PCH Include ||
//#==============================================================#
#include "SHpch.h"
//#==============================================================#
//|| SHADE Includes ||
//#==============================================================#
#include "SHCommandManager.h"
namespace SHADE
{
SHCommandManager::CommandStack SHCommandManager::undoStack{};
SHCommandManager::CommandStack SHCommandManager::redoStack{};
void SHCommandManager::PerformCommand(CommandPtr commandPtr, bool const& overrideValue)
{
redoStack = CommandStack();
commandPtr->Execute();
if (overrideValue && !undoStack.empty())
{
undoStack.top()->Merge(commandPtr);
}
else
{
undoStack.push(commandPtr);
}
}
void SHCommandManager::UndoCommand()
{
if (undoStack.empty())
return;
undoStack.top()->Undo();
redoStack.push(undoStack.top());
undoStack.pop();
}
void SHCommandManager::RedoCommand()
{
if (redoStack.empty())
return;
redoStack.top()->Execute();
undoStack.push(redoStack.top());
redoStack.pop();
}
std::size_t SHCommandManager::GetUndoStackSize()
{
return undoStack.size();
}
std::size_t SHCommandManager::GetRedoStackSize()
{
return redoStack.size();
}
}//namespace SHADE

View File

@ -0,0 +1,34 @@
#pragma once
//#==============================================================#
//|| STL Includes ||
//#==============================================================#
#include <stack>
//#==============================================================#
//|| SHADE Includes ||
//#==============================================================#
#include "SHCommand.hpp"
namespace SHADE
{
class SHCommandManager
{
public:
//#==============================================================#
//|| Type Aliases ||
//#==============================================================#
using CommandPtr = std::shared_ptr<SHBaseCommand>;
using CommandStack = std::stack<CommandPtr>;
static void PerformCommand(CommandPtr commandPtr, bool const& overrideValue = false);
static void UndoCommand();
static void RedoCommand();
static std::size_t GetUndoStackSize();
static std::size_t GetRedoStackSize();
private:
static CommandStack undoStack;
static CommandStack redoStack;
};
}//namespace SHADE

View File

@ -0,0 +1,21 @@
#include "SHpch.h"
#include "SHDragDrop.hpp"
namespace SHADE
{
bool SHDragDrop::hasDragDrop = false;
bool SHDragDrop::BeginSource(ImGuiDragDropFlags const flags)
{ return ImGui::BeginDragDropSource(flags); }
void SHDragDrop::EndSource()
{ ImGui::EndDragDropSource();}
bool SHDragDrop::BeginTarget()
{ return ImGui::BeginDragDropTarget(); }
void SHDragDrop::EndTarget()
{ ImGui::EndDragDropTarget(); hasDragDrop = false;}
}

View File

@ -0,0 +1,44 @@
#pragma once
#include <string_view>
#include <imgui.h>
namespace SHADE
{
//TODO: Convert to RTTR?
constexpr auto DRAG_EID = "DragEID";
constexpr auto DRAG_RESOURCE = "DragResource";
struct SHDragDrop
{
static bool BeginSource(ImGuiDragDropFlags const flags = 0);
/**
* \brief Ends the DragDrop Source. ONLY CALL IF BeginSource returns true
*/
static void EndSource();
template<typename T>
static bool SetPayload(std::string_view const type, T* object, ImGuiCond const cond = 0)
{
hasDragDrop = ImGui::SetDragDropPayload(type.data(), static_cast<void*>(object), sizeof(T), cond);
return hasDragDrop;
}
static bool BeginTarget();
/**
* \brief Ends the DragDrop Target. ONLY CALL IF BeginTarget returns true
*/
static void EndTarget();
template<typename T>
static T* AcceptPayload(std::string_view const type, ImGuiDragDropFlags const flags = 0)
{
if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload(type.data(), flags))
return static_cast<T*>(payload->Data);
return nullptr;
}
static bool hasDragDrop;
};
}

View File

@ -0,0 +1,212 @@
//#==============================================================#
//|| PCH Include ||
//#==============================================================#
#include "SHpch.h"
//#==============================================================#
//|| SHADE Includes ||
//#==============================================================#
#include "Editor/SHImGuiHelpers.hpp"
#include "Editor/SHEditorWidgets.hpp"
#include "SHHierarchyPanel.h"
#include "ECS_Base/Managers/SHEntityManager.h"
#include "Editor/SHEditor.hpp"
#include "Scene/SHSceneManager.h"
#include "Editor/DragDrop/SHDragDrop.hpp"
#include "Tools/SHException.h"
#include "Editor/IconsMaterialDesign.h"
//#==============================================================#
//|| Library Includes ||
//#==============================================================#
#include <imgui.h>
namespace SHADE
{
//#==============================================================#
//|| Public Member Functions ||
//#==============================================================#
SHHierarchyPanel::SHHierarchyPanel()
:SHEditorWindow("Hierarchy Panel", ImGuiWindowFlags_MenuBar)
{
}
void SHHierarchyPanel::Init()
{
SHEditorWindow::Init();
}
void SHHierarchyPanel::Update()
{
SHEditorWindow::Update();
isAnyNodeSelected = false;
if (Begin())
{
DrawMenuBar();
auto const& sceneGraph = SHSceneManager::GetCurrentSceneGraph();
if(const auto root = sceneGraph.GetRoot())
{
auto const& children = root->GetChildren();
for (const auto child : children)
{
RecursivelyDrawEntityNode(child);
}
}
else
{
SHLOG_WARNING("Scene Graph root is null! Unable to render hierarchy.")
}
if(ImGui::IsWindowHovered() && !SHDragDrop::hasDragDrop && !ImGui::IsAnyItemHovered() && ImGui::IsMouseReleased(ImGuiMouseButton_Left))
{
SHEditor::selectedEntities.clear();
}
ImGui::SeparatorEx(ImGuiSeparatorFlags_Horizontal);
ImGui::End();
}
}
void SHHierarchyPanel::Exit()
{
SHEditorWindow::Exit();
}
//#==============================================================#
//|| Private Member Functions ||
//#==============================================================#
void SHHierarchyPanel::DrawMenuBar() const noexcept
{
if (ImGui::BeginMenuBar())
{
if (ImGui::SmallButton(ICON_MD_ADD))
{
SHEntityManager::CreateEntity();
}
if (ImGui::IsItemHovered())
{
ImGui::BeginTooltip();
ImGui::Text("Add Entity");
ImGui::EndTooltip();
}
ImGui::EndMenuBar();
}
}
ImRect SHHierarchyPanel::RecursivelyDrawEntityNode(SHSceneNode* currentNode)
{
auto const& sceneGraph = SHSceneManager::GetCurrentSceneGraph();
//Get node data (Children, eid, selected)
auto& children = currentNode->GetChildren();
EntityID eid = currentNode->GetEntityID();
const bool isSelected = (std::ranges::find(SHEditor::selectedEntities, eid) != SHEditor::selectedEntities.end());
const ImGuiTreeNodeFlags nodeFlags = ((isSelected) ? ImGuiTreeNodeFlags_Selected : 0) | ((children.empty()) ? ImGuiTreeNodeFlags_Leaf : ImGuiTreeNodeFlags_OpenOnArrow);
//bool highlighted = false;
//if(highlighted)
//{
// ImGui::PushStyleColor(ImGuiCol_Text, highlightedColor);
//}
auto* entity = SHEntityManager::GetEntityByID(currentNode->GetEntityID());
//Draw Node
bool isNodeOpen = ImGui::TreeNodeEx((void*)eid, nodeFlags, "%u: %s", EntityHandleGenerator::GetIndex(eid), entity->name.c_str());
const ImRect nodeRect = ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax());
//Check For Begin Drag
if (SHDragDrop::BeginSource())
{
ImGui::Text("Moving EID: %zu", eid);
SHDragDrop::SetPayload<EntityID>(DRAG_EID, &eid);
SHDragDrop::EndSource();
}
else if (SHDragDrop::BeginTarget()) //If Received DragDrop
{
if (const EntityID* eidPayload = SHDragDrop::AcceptPayload<EntityID>(DRAG_EID)) //If payload is valid
{
EntityID const dropEID = *eidPayload;
if(!sceneGraph.GetChild(dropEID, eid))
sceneGraph.SetParent(dropEID, eid); //Set dropEID parent to eid (belonging to current Node)
SHDragDrop::EndTarget();
}
}
//Context menu
if(ImGui::BeginPopupContextItem(std::to_string(eid).c_str()))
{
if(!isSelected)
{
SHEditor::selectedEntities.clear();
SHEditor::selectedEntities.push_back(eid);
}
if(ImGui::Selectable(std::format("{} Delete", ICON_MD_DELETE).data()))
{
SHEntityManager::DestroyEntity(eid);
}
if((currentNode->GetParent() != sceneGraph.GetRoot()) && ImGui::Selectable(std::format("{} Unparent Selected", ICON_MD_NORTH_WEST).data()))
{
sceneGraph.SetParent(currentNode->GetEntityID(), nullptr);
}
ImGui::EndPopup();
}
//Handle node selection
if (ImGui::IsItemHovered())
{
if (ImGui::IsMouseReleased(ImGuiMouseButton_Left))
{
if (!isSelected)
{
if (!ImGui::IsKeyDown(ImGuiKey_LeftCtrl))
SHEditor::selectedEntities.clear();
SHEditor::selectedEntities.push_back(eid);
}//if not selected
else
{
if (!ImGui::IsKeyDown(ImGuiKey_LeftCtrl))
{
auto it = std::ranges::remove(SHEditor::selectedEntities, eid).begin();
}//if mod ctrl is not pressed
else
{
SHEditor::selectedEntities.clear();
SHEditor::selectedEntities.push_back(eid);
}
}//if selected
}//if left mouse button released
}//if item hovered
if (isNodeOpen)
{
const ImColor treeLineColor = ImGui::GetColorU32(ImGuiCol_CheckMark);
const float horizontalOffset = 0.0f;
ImDrawList* drawList = ImGui::GetWindowDrawList();
ImVec2 vertLineStart = ImGui::GetCursorScreenPos();
vertLineStart.x += horizontalOffset;
ImVec2 vertLineEnd = vertLineStart;
for (const auto child : children)
{
const float horizontalLineSize = 8.0f;
const ImRect childRect = RecursivelyDrawEntityNode(child);
const float midPoint = (childRect.Min.y + childRect.Max.y) * 0.5f;
drawList->AddLine(ImVec2(vertLineStart.x, midPoint), ImVec2(vertLineStart.x + horizontalLineSize, midPoint), treeLineColor, 2);
vertLineEnd.y = midPoint;
}
drawList->AddLine(vertLineStart, vertLineEnd, treeLineColor, 2);
ImGui::TreePop();
}
return nodeRect;
}
void SHHierarchyPanel::CreateChildEntity(EntityID parentEID) const noexcept
{
SHEntityManager::CreateEntity(MAX_EID, "DefaultChild", parentEID);
}
}//namespace SHADE

View File

@ -0,0 +1,33 @@
#pragma once
//#==============================================================#
//|| Library Includes ||
//#==============================================================#
#include <imgui.h>
//#==============================================================#
//|| SHADE Includes ||
//#==============================================================#
#include "imgui_internal.h"
#include "ECS_Base/SHECSMacros.h"
#include "Editor/EditorWindow/SHEditorWindow.h"
namespace SHADE
{
class SHSceneNode;
constexpr ImVec4 highlightedColor = ImVec4(0.f, 0.7f, 0.0f, 1.0f);
class SHHierarchyPanel final : public SHEditorWindow
{
public:
SHHierarchyPanel();
void Init() override;
void Update() override;
void Exit() override;
private:
void DrawMenuBar() const noexcept;
ImRect RecursivelyDrawEntityNode(SHSceneNode*);
void CreateChildEntity(EntityID parentEID) const noexcept;
std::string filter;
bool isAnyNodeSelected = false;
};//class SHHierarchyPanel
}//namespace SHADE

View File

@ -0,0 +1,70 @@
#pragma once
//#==============================================================#
//|| Library Includes ||
//#==============================================================#
#include <imgui.h>
#include <rttr/type>
//#==============================================================#
//|| SHADE Includes ||
//#==============================================================#
#include "Editor/IconsMaterialDesign.h"
#include "ECS_Base/Components/SHComponent.h"
#include "Editor/SHEditorWidgets.hpp"
namespace SHADE
{
template<typename T, std::enable_if_t<std::is_base_of<SHComponent, T>::value, bool> = true>
static void DrawContextMenu(T* component)
{
if(!component)
return;
rttr::string_view componentName = rttr::type::get<T>().get_name();
if (ImGui::BeginPopupContextItem(componentName.data()))
{
if (ImGui::Selectable(std::format("{} Copy {}", ICON_MD_CONTENT_COPY, componentName.data()).data()))
{
//SHClipboardUtil::WriteStringToClipboard(SHClipboardUtil::CFNAME::CFCOMPONENT, SHComponentToString(component));
}
if (ImGui::Selectable(std::format("{} Paste {}", ICON_MD_CONTENT_PASTE, componentName.data()).data()))
{
//SHStringToComponent(component, SHClipboardUtil::ReadStringFromClipboard(SHClipboardUtil::CFNAME::CFCOMPONENT));
}
if (ImGui::Selectable(std::format("{} Delete {}", ICON_MD_DELETE, componentName.data()).data()))
{
SHComponentManager::RemoveComponent<T>(component->GetEID());
}
ImGui::EndPopup();
}
}
template<typename T, std::enable_if_t<std::is_base_of_v<SHComponent, T>, bool> = true>
static void DrawComponent(T* component)
{
if (!component)
return;
auto componentType = rttr::type::get(*component);
CheckBox("##IsActive", [component]() {return component->isActive; }, [component](bool const& active) {component->isActive = active; });
ImGui::SameLine();
if (ImGui::CollapsingHeader(componentType.get_name().data()))
{
DrawContextMenu(component);
auto const& properties = componentType.get_properties();
for (auto const& property : properties)
{
auto const& type = property.get_type();
if (type == rttr::type::get<SHVec4>())
{
DragVec4(property.get_name().data(), { "X", "Y", "Z", "W" }, [component, property]() {return property.get_value(component).template convert<SHVec4>(); }, [component, property](SHVec4 vec) {return property.set_value(component, vec); });
}
else if (type == rttr::type::get<SHVec3>())
{
DragVec3(property.get_name().data(), { "X", "Y", "Z" }, [component, property]() {return property.get_value(component).template convert<SHVec3>(); }, [component, property](SHVec3 vec) {return property.set_value(component, vec); });
}
}
}
else DrawContextMenu(component);
}
}

View File

@ -0,0 +1,73 @@
#include "SHpch.h"
#include "SHEditorInspector.h"
#include "ECS_Base/SHECSMacros.h"
#include "ECS_Base/Entity/SHEntity.h"
#include "ECS_Base/Managers/SHEntityManager.h"
#include "Math/Transform/SHTransformComponent.h"
#include "Editor/SHEditor.hpp"
#include "Editor/SHImGuiHelpers.hpp"
#include "Editor/SHEditorWidgets.hpp"
#include "SHEditorComponentView.hpp"
#include "Graphics/MiddleEnd/Interface/SHRenderable.h"
namespace SHADE
{
template<typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>
void DrawAddComponentButton(EntityID const& eid)
{
if(!SHComponentManager::HasComponent<ComponentType>(eid) && ImGui::Selectable(std::format("Add {}", rttr::type::get<ComponentType>().get_name().data()).data()))
{
SHComponentManager::AddComponent<ComponentType>(eid);
}
}
SHEditorInspector::SHEditorInspector()
:SHEditorWindow("Inspector", ImGuiWindowFlags_MenuBar)
{
}
void SHEditorInspector::Init()
{
SHEditorWindow::Init();
}
void SHEditorInspector::Update()
{
SHEditorWindow::Update();
if (Begin())
{
if (!SHEditor::selectedEntities.empty())
{
EntityID const& eid = SHEditor::selectedEntities[0];
SHEntity* entity = SHEntityManager::GetEntityByID(eid);
ImGui::TextColored(ImGuiColors::green, "EID: %zu", eid);
CheckBox("##IsActive", [entity]()->bool {return entity->GetActive(); }, [entity](bool const& active) {entity->SetActive(active); });
ImGui::SameLine();
ImGui::InputText("##EntityName", &entity->name);
if (auto transformComponent = SHComponentManager::GetComponent_s<SHTransformComponent>(eid))
{
DrawComponent(transformComponent);
}
ImGui::Separator();
if(ImGui::BeginMenu(std::format("{} Add Component", ICON_MD_LIBRARY_ADD).data()))
{
DrawAddComponentButton<SHTransformComponent>(eid);
DrawAddComponentButton<SHRenderable>(eid);
ImGui::EndMenu();
}
}
ImGui::End();
}
}
void SHEditorInspector::Exit()
{
SHEditorWindow::Exit();
}
}

View File

@ -0,0 +1,30 @@
#pragma once
//#==============================================================#
//|| Library Includes ||
//#==============================================================#
#include <imgui.h>
#include <rttr/type>
//#==============================================================#
//|| SHADE Includes ||
//#==============================================================#
#include "Editor/EditorWindow/SHEditorWindow.h"
namespace SHADE
{
class SHComponent;
class SHEditorInspector final : public SHEditorWindow
{
public:
SHEditorInspector();
void Init() override;
void Update() override;
void Exit() override;
private:
};
}

View File

@ -0,0 +1,130 @@
#include "SHpch.h"
//#==============================================================#
//|| SHADE Includes ||
//#==============================================================#
#include "SHEditorMenuBar.h"
#include "Editor/IconsMaterialDesign.h"
#include "Editor/Command/SHCommandManager.h"
//#==============================================================#
//|| Library Includes ||
//#==============================================================#
#include <imgui.h>
#include <imgui_internal.h>
#include <rttr/type>
#include "Editor/SHEditor.hpp"
namespace SHADE
{
constexpr ImGuiWindowFlags editorMenuBarFlags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse |
ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoDocking |
ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoNavFocus;
constexpr ImGuiWindowFlags dockspaceFlags = ImGuiDockNodeFlags_PassthruCentralNode;
//#==============================================================#
//|| Public Member Functions ||
//#==============================================================#
SHEditorMenuBar::SHEditorMenuBar()
:SHEditorWindow("SHEditorMenuBar", editorMenuBarFlags | ImGuiWindowFlags_NoBackground)
{
}
void SHEditorMenuBar::Init()
{
SHEditorWindow::Init();
}
void SHEditorMenuBar::Update()
{
SHEditorWindow::Update();
DrawMainMenuBar();
DrawSecondaryBar();
DrawStatusBar();
}
//#==============================================================#
//|| Private Member Functions ||
//#==============================================================#
void SHEditorMenuBar::DrawMainMenuBar() noexcept
{
const ImGuiViewport* viewport = ImGui::GetMainViewport();
ImGui::SetNextWindowPos(viewport->WorkPos);
ImGui::SetNextWindowSize(viewport->WorkSize);
ImGui::SetNextWindowViewport(viewport->ID);
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, { ImVec2(0.0f, 0.0f) });
if (Begin())
{
ImGui::PopStyleVar(3);
if (ImGui::BeginMainMenuBar())
{
if (ImGui::BeginMenu("File"))
{
ImGui::EndMenu();
}
if(ImGui::BeginMenu("Edit"))
{
ImGui::BeginDisabled(!SHCommandManager::GetUndoStackSize());
if(ImGui::Button(std::format("{} Undo", ICON_MD_UNDO).data()))
{
SHCommandManager::UndoCommand();
}
ImGui::EndDisabled();
ImGui::BeginDisabled(!SHCommandManager::GetRedoStackSize());
if(ImGui::Button(std::format("{} Redo", ICON_MD_REDO).data()))
{
SHCommandManager::RedoCommand();
}
ImGui::EndDisabled();
ImGui::EndMenu();
}
if(ImGui::BeginMenu("Theme"))
{
auto styles = rttr::type::get<SHEditor::Style>().get_enumeration();
auto values = styles.get_values();
for (auto style : values)
{
if(ImGui::Selectable(style.to_string().c_str()))
{
SHEditor::SetStyle(style.convert<SHEditor::Style>());
}
}
ImGui::EndMenu();
}
ImGui::EndMainMenuBar();
}
const ImGuiID dockspace_id = ImGui::GetID("DockSpace");
ImGui::DockSpace(dockspace_id, ImVec2(0.0f, 0.0f), dockspaceFlags);
ImGui::End();
}
}
void SHEditorMenuBar::DrawSecondaryBar() const noexcept
{
}
void SHEditorMenuBar::DrawStatusBar() const noexcept
{
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, { ImVec2(0.0f, 0.0f) });
if (ImGui::BeginViewportSideBar("MainStatusBar", ImGui::GetMainViewport(), ImGuiDir_Down, menuBarHeight, editorMenuBarFlags))
{
ImGui::Text("Entity count: ");
ImGui::End();
}
ImGui::PopStyleVar(3);
}
}//namespace SHADE

View File

@ -0,0 +1,22 @@
#pragma once
//#==============================================================#
//|| SHADE Includes ||
//#==============================================================#
#include "Editor/EditorWindow/SHEditorWindow.h"
namespace SHADE
{
class SHEditorMenuBar final : public SHEditorWindow
{
public:
SHEditorMenuBar();
virtual void Init() override;
virtual void Update() override;
private:
void DrawMainMenuBar() noexcept;
void DrawSecondaryBar() const noexcept;
void DrawStatusBar() const noexcept;
float menuBarHeight = 20.0f;
};//class SHEditorMenuBar
}//namespace SHADE

View File

@ -0,0 +1,46 @@
//#==============================================================#
//|| PCH Include ||
//#==============================================================#
#include "SHpch.h"
//#==============================================================#
//|| SHADE Includes ||
//#==============================================================#
#include "SHEditorWindow.h"
//#==============================================================#
//|| Library Includes ||
//#==============================================================#
#include <imgui.h>
namespace SHADE
{
//#==============================================================#
//|| Public Member Functions ||
//#==============================================================#
SHEditorWindow::SHEditorWindow(std::string_view const& name, ImGuiWindowFlags const& inFlags)
: isOpen(true), windowName(name), windowFlags(inFlags), io(ImGui::GetIO())
{
}
void SHEditorWindow::Init()
{
}
void SHEditorWindow::Update()
{
}
void SHEditorWindow::Exit()
{
}
//#==============================================================#
//|| Protected Member Functions ||
//#==============================================================#
bool SHEditorWindow::Begin()
{
return ImGui::Begin(windowName.data(), &isOpen, windowFlags);
}
}//namespace SHADE

View File

@ -0,0 +1,31 @@
#pragma once
//#==============================================================#
//|| STL Includes ||
//#==============================================================#
#include <string>
//#==============================================================#
//|| Forward Declarations ||
//#==============================================================#
struct ImGuiIO;
typedef int ImGuiWindowFlags;
namespace SHADE
{
class SHEditorWindow
{
public:
SHEditorWindow(std::string_view const& name, ImGuiWindowFlags const& inFlags);
virtual ~SHEditorWindow() = default;
virtual void Init();
virtual void Update();
virtual void Exit();
bool isOpen = false;
std::string_view windowName;
protected:
virtual bool Begin();
ImGuiWindowFlags windowFlags = 0;
ImGuiIO& io;
};//class SHEditorWindow
}//namespace SHADE

View File

@ -0,0 +1,4 @@
#pragma once
#include "MenuBar/SHEditorMenuBar.h" //Menu Bar
#include "HierarchyPanel/SHHierarchyPanel.h" //Hierarchy Panel
#include "Inspector/SHEditorInspector.h" //Inspector

File diff suppressed because it is too large Load Diff

View File

@ -1,79 +1,125 @@
//#==============================================================#
//|| PCH Include ||
//#==============================================================#
#include "SHpch.h" #include "SHpch.h"
#include "SHEditor.h"
#include <imgui.h> #include "IconsMaterialDesign.h"
#include "DragDrop/SHDragDrop.hpp"
//#==============================================================#
//|| SHADE Includes ||
//#==============================================================#
#include "Tools/SHLogger.h"
#include "Tools/SHException.h"
#include "ECS_Base/Managers/SHSystemManager.h" #include "ECS_Base/Managers/SHSystemManager.h"
#include "Graphics/Instance/SHVkInstance.h" #include "Graphics/Instance/SHVkInstance.h"
#include "Graphics/MiddleEnd/Interface/SHGraphicsSystem.h" #include "Graphics/MiddleEnd/Interface/SHGraphicsSystem.h"
#include "Graphics/Swapchain/SHVkSwapchain.h" #include "Graphics/Swapchain/SHVkSwapchain.h"
#include "Graphics/MiddleEnd/Interface/SHViewport.h"
#include "Graphics/MiddleEnd/Interface/SHRenderer.h"
//IMGUI Backend includes #include "SHEditor.hpp"
#include "SHEditorWidgets.hpp"
//#==============================================================#
//|| Editor Window Includes ||
//#==============================================================#
#include "EditorWindow/SHEditorWindowIncludes.h"
//#==============================================================#
//|| Library Includes ||
//#==============================================================#
#include <imgui.h>
#include <SDL.h>
#include <rttr/registration>
//#==============================================================#
//|| ImGui Backend Includes ||
//#==============================================================#
#include <backends/imgui_impl_sdl.h> #include <backends/imgui_impl_sdl.h>
#include <backends/imgui_impl_vulkan.h> #include <backends/imgui_impl_vulkan.h>
RTTR_REGISTRATION
{
using namespace SHADE;
using namespace rttr;
registration::enumeration<SHEditor::Style>("Style")
(
value("SHADE", SHEditor::Style::SHADE),
value("DARK", SHEditor::Style::DARK),
value("LIGHT", SHEditor::Style::LIGHT),
value("CLASSIC", SHEditor::Style::CLASSIC)
);
}
namespace SHADE namespace SHADE
{ {
//#==============================================================#
//|| Initialise static members ||
//#==============================================================#
Handle<SHVkCommandPool> SHEditor::imguiCommandPool; Handle<SHVkCommandPool> SHEditor::imguiCommandPool;
Handle<SHVkCommandBuffer> SHEditor::imguiCommandBuffer; Handle<SHVkCommandBuffer> SHEditor::imguiCommandBuffer;
SHEditor::EditorWindowMap SHEditor::editorWindows{};
SHEditor::EditorWindowID SHEditor::windowCount{};
std::vector<EntityID> SHEditor::selectedEntities;
void SHEditor::Initialise(SDL_Window* sdlWindow) //#==============================================================#
//|| Public Member Functions ||
//#==============================================================#
void SHEditor::Initialise(SDL_Window* const sdlWindow)
{ {
IMGUI_CHECKVERSION(); IMGUI_CHECKVERSION();
ImGui::CreateContext(); if(auto context = ImGui::CreateContext())
{
if(context == nullptr)
{
SHLOG_CRITICAL("Failed to create ImGui Context")
}
}
ImGuiIO& io = ImGui::GetIO(); (void)io; ImGuiIO& io = ImGui::GetIO(); (void)io;
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; //Enable for Multi-Viewports
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; //Enable docking
ImGui_ImplSDL2_InitForVulkan(sdlWindow); InitFonts();
InitBackend(sdlWindow);
auto* gfxSystem = reinterpret_cast<SHGraphicsSystem*>(SHSystemManager::GetSystem<SHGraphicsSystem>()); SetStyle(Style::SHADE);
ImGui_ImplVulkan_InitInfo initInfo{}; //Add editor windows
initInfo.Instance = SHVkInstance::GetVkInstance(); CreateEditorWindow<SHEditorMenuBar>();
initInfo.PhysicalDevice = gfxSystem->GetPhysicalDevice()->GetVkPhysicalDevice(); CreateEditorWindow<SHHierarchyPanel>();
initInfo.Device = gfxSystem->GetDevice()->GetVkLogicalDevice(); CreateEditorWindow<SHEditorInspector>();
initInfo.Queue = gfxSystem->GetQueue()->GetVkQueue();
initInfo.DescriptorPool = gfxSystem->GetDescriptorPool()->GetVkHandle();
initInfo.MinImageCount = initInfo.ImageCount = gfxSystem->GetSwapchain()->GetNumImages();
initInfo.MSAASamples = VK_SAMPLE_COUNT_1_BIT;
imguiCommandPool = gfxSystem->GetDevice()->CreateCommandPool(SH_QUEUE_FAMILY_ARRAY_INDEX::GRAPHICS, SH_CMD_POOL_RESET::POOL_BASED, true); SHLOG_INFO("Successfully initialised SHADE Engine Editor")
imguiCommandBuffer = imguiCommandPool->RequestCommandBuffer(SH_CMD_BUFFER_TYPE::PRIMARY);
/*auto renderPass = gfxSystem->GetRenderGraph().GetNode("ImGui Node")->GetRenderpass();
ImGui_ImplVulkan_Init(&initInfo, renderPass->GetVkRenderpass());*/
imguiCommandBuffer->BeginRecording();
ImGui_ImplVulkan_CreateFontsTexture(imguiCommandBuffer->GetVkCommandBuffer());
imguiCommandBuffer->EndRecording();
gfxSystem->GetQueue()->SubmitCommandBuffer({imguiCommandBuffer}, {}, {}, vk::PipelineStageFlagBits::eNone, {});
ImGui_ImplVulkan_DestroyFontUploadObjects();
/*gfxSystem->GetRenderGraph().GetNode("ImGui Node")->GetSubpass("ImGui Draw")->AddExteriorDrawCalls([](Handle<SHVkCommandBuffer>& cmd) {
ImGui_ImplVulkan_RenderDrawData(ImGui::GetDrawData(), cmd->GetVkCommandBuffer());
});*/
//ImGuiIO& io = ImGui::GetIO();
//int w, h;
//SDL_GetWindowSize(sdlWindow, &w, &h);
//io.DisplaySize = { static_cast<float>(w),static_cast<float>(h)};
} }
void SHEditor::PreRender() void SHEditor::Update(float const dt)
{ {
(void)dt;
NewFrame(); NewFrame();
ImGui::ShowDemoWindow(); for (const auto& window : editorWindows | std::views::values)
ImGui::Begin("Your mom");
if (ImGui::Button("OP"))
{ {
std::cout << "HEHEHEOHEIOHIEOH\n"; window->Update();
} }
ImGui::End();
if(ImGui::IsKeyDown(ImGuiKey_LeftShift) && ImGui::IsKeyDown(ImGuiKey_LeftCtrl) && ImGui::IsKeyReleased(ImGuiKey_Z))
{
SHCommandManager::RedoCommand();
}
else if(ImGui::IsKeyDown(ImGuiKey_LeftCtrl) && ImGui::IsKeyReleased(ImGuiKey_Z))
{
SHCommandManager::UndoCommand();
}
Render();
} }
void SHEditor::Render() void SHEditor::Render()
@ -87,6 +133,18 @@ namespace SHADE
} }
} }
void SHEditor::InitFonts() noexcept
{
ImGuiIO& io = ImGui::GetIO();
ImFont* mainFont = io.Fonts->AddFontFromFileTTF("../../Assets/Editor/Fonts/Segoe UI.ttf", 20.f);//TODO: Change to config based assets path
static const ImWchar icon_ranges[] = { ICON_MIN_MD, ICON_MAX_16_MD, 0 };
ImFontConfig icons_config{}; icons_config.MergeMode = true; icons_config.PixelSnapH = true;
ImFont* UIFont = io.Fonts->AddFontFromFileTTF("../../Assets/Editor/Fonts/MaterialIcons-Regular.ttf", 20.f, &icons_config, icon_ranges); //TODO: Change to config based assets path
io.Fonts->Build();
}
void SHEditor::Exit() void SHEditor::Exit()
{ {
ImGui_ImplVulkan_Shutdown(); ImGui_ImplVulkan_Shutdown();
@ -94,19 +152,164 @@ namespace SHADE
ImGui::DestroyContext(); ImGui::DestroyContext();
} }
void SHEditor::SetStyle(Style style)
void SHEditor::InitBackend()
{ {
switch (style)
{
default:
case Style::SHADE:
{
ImGuiStyle& imStyle = ImGui::GetStyle();
ImVec4* colors = imStyle.Colors;
colors[ImGuiCol_Text] = ImVec4(0.706f, 0.729f, 0.757f, 1.00f);
colors[ImGuiCol_TextDisabled] = ImVec4(0.50f, 0.50f, 0.50f, 1.00f);
colors[ImGuiCol_WindowBg] = ImVec4(0.172f, 0.184f, 0.203f, 1.f);
colors[ImGuiCol_ChildBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
colors[ImGuiCol_PopupBg] = ImVec4(0.19f, 0.19f, 0.19f, 0.92f);
colors[ImGuiCol_Border] = ImVec4(0.19f, 0.19f, 0.19f, 0.29f);
colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.24f);
colors[ImGuiCol_FrameBg] = ImVec4(0.05f, 0.05f, 0.05f, 0.54f);
colors[ImGuiCol_FrameBgHovered] = ImVec4(0.19f, 0.19f, 0.19f, 0.54f);
colors[ImGuiCol_FrameBgActive] = ImVec4(0.20f, 0.22f, 0.23f, 1.00f);
colors[ImGuiCol_TitleBg] = colors[ImGuiCol_WindowBg];
colors[ImGuiCol_TitleBgActive] = colors[ImGuiCol_WindowBg];
colors[ImGuiCol_TitleBgCollapsed] = colors[ImGuiCol_WindowBg];
colors[ImGuiCol_MenuBarBg] = ImVec4(0.129f, 0.141f, 0.157f, 1.f);
colors[ImGuiCol_ScrollbarBg] = colors[ImGuiCol_WindowBg];
colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.34f, 0.34f, 0.34f, 0.54f);
colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.40f, 0.40f, 0.40f, 0.54f);
colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.56f, 0.56f, 0.56f, 0.54f);
colors[ImGuiCol_CheckMark] = ImVec4(0.627f, 0.239f, 0.761f, 1.00f);
colors[ImGuiCol_SliderGrab] = ImVec4(0.34f, 0.34f, 0.34f, 0.54f);
colors[ImGuiCol_SliderGrabActive] = ImVec4(0.56f, 0.56f, 0.56f, 0.54f);
colors[ImGuiCol_Button] = ImVec4(0.05f, 0.05f, 0.05f, 0.54f);
colors[ImGuiCol_ButtonHovered] = ImVec4(0.15f, 0.15f, 0.15f, 0.54f);
colors[ImGuiCol_ButtonActive] = ImVec4(0.20f, 0.22f, 0.23f, 1.00f);
colors[ImGuiCol_Header] = ImVec4(0.00f, 0.00f, 0.00f, 0.52f);
colors[ImGuiCol_HeaderHovered] = ImVec4(0.00f, 0.00f, 0.00f, 0.36f);
colors[ImGuiCol_HeaderActive] = ImVec4(0.20f, 0.22f, 0.23f, 0.33f);
colors[ImGuiCol_Separator] = colors[ImGuiCol_MenuBarBg];
colors[ImGuiCol_SeparatorHovered] = ImVec4(0.44f, 0.44f, 0.44f, 0.29f);
colors[ImGuiCol_SeparatorActive] = ImVec4(0.40f, 0.44f, 0.47f, 1.00f);
colors[ImGuiCol_ResizeGrip] = ImVec4(0.28f, 0.28f, 0.28f, 0.29f);
colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.44f, 0.44f, 0.44f, 0.29f);
colors[ImGuiCol_ResizeGripActive] = ImVec4(0.40f, 0.44f, 0.47f, 1.00f);
colors[ImGuiCol_Tab] = colors[ImGuiCol_WindowBg];
colors[ImGuiCol_TabHovered] = ImVec4(0.14f, 0.14f, 0.14f, 1.00f);
colors[ImGuiCol_TabActive] = ImVec4(0.14f, 0.14f, 0.14f, 0.8f);
colors[ImGuiCol_TabUnfocused] = colors[ImGuiCol_WindowBg];
colors[ImGuiCol_TabUnfocusedActive] = colors[ImGuiCol_WindowBg];
colors[ImGuiCol_DockingPreview] = ImVec4(0.627f, 0.239f, 0.761f, 1.00f);
colors[ImGuiCol_DockingEmptyBg] = ImVec4(0.855f, 0.6f, 0.941f, 1.00f);
colors[ImGuiCol_PlotLines] = ImVec4(1.00f, 0.00f, 0.00f, 1.00f);
colors[ImGuiCol_PlotLinesHovered] = ImVec4(1.00f, 0.00f, 0.00f, 1.00f);
colors[ImGuiCol_PlotHistogram] = ImVec4(1.00f, 0.00f, 0.00f, 1.00f);
colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.00f, 0.00f, 1.00f);
colors[ImGuiCol_TableHeaderBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.52f);
colors[ImGuiCol_TableBorderStrong] = ImVec4(0.00f, 0.00f, 0.00f, 0.52f);
colors[ImGuiCol_TableBorderLight] = ImVec4(0.28f, 0.28f, 0.28f, 0.29f);
colors[ImGuiCol_TableRowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
colors[ImGuiCol_TableRowBgAlt] = ImVec4(1.00f, 1.00f, 1.00f, 0.06f);
colors[ImGuiCol_TextSelectedBg] = ImVec4(0.20f, 0.22f, 0.23f, 1.00f);
colors[ImGuiCol_DragDropTarget] = ImVec4(0.33f, 0.67f, 0.86f, 1.00f);
colors[ImGuiCol_NavHighlight] = ImVec4(0.73f, 0.73f, 0.73f, 0.7f);
colors[ImGuiCol_NavWindowingHighlight] = ImVec4(0.141f, 0.141f, 0.141f, 0.70f);
colors[ImGuiCol_NavWindowingDimBg] = colors[ImGuiCol_NavHighlight];
colors[ImGuiCol_ModalWindowDimBg] = ImVec4(0.2f, 0.2f, 0.2f, 0.65f);
imStyle.WindowPadding = ImVec2(8.00f, 8.00f);
imStyle.FramePadding = ImVec2(5.00f, 2.00f);
imStyle.CellPadding = ImVec2(6.00f, 8.00f);
imStyle.ItemSpacing = ImVec2(6.00f, 6.00f);
imStyle.ItemInnerSpacing = ImVec2(6.00f, 6.00f);
imStyle.TouchExtraPadding = ImVec2(0.00f, 0.00f);
imStyle.IndentSpacing = 25;
imStyle.ScrollbarSize = 15;
imStyle.GrabMinSize = 10;
imStyle.WindowBorderSize = 0.6f;
imStyle.ChildBorderSize = 1;
imStyle.PopupBorderSize = 1;
imStyle.FrameBorderSize = 1;
imStyle.TabBorderSize = 1;
imStyle.WindowRounding = 7;
imStyle.ChildRounding = 4;
imStyle.FrameRounding = 3;
imStyle.PopupRounding = 4;
imStyle.ScrollbarRounding = 9;
imStyle.GrabRounding = 3;
imStyle.LogSliderDeadzone = 4;
imStyle.TabRounding = 4;
imStyle.WindowMenuButtonPosition = ImGuiDir_None;
}
break;
case Style::DARK: ImGui::StyleColorsDark(); break;
case Style::LIGHT: ImGui::StyleColorsLight(); break;
case Style::CLASSIC: ImGui::StyleColorsClassic(); break;
}
}
//#==============================================================#
//|| Private Member Functions ||
//#==============================================================#
void SHEditor::InitBackend(SDL_Window* sdlWindow)
{
if(ImGui_ImplSDL2_InitForVulkan(sdlWindow) == false)
{
SHLOG_CRITICAL("Editor backend initialisation; Failed to perform SDL initialisation for Vulkan")
}
const auto* gfxSystem = SHSystemManager::GetSystem<SHGraphicsSystem>();
ImGui_ImplVulkan_InitInfo initInfo{};
initInfo.Instance = SHVkInstance::GetVkInstance();
initInfo.PhysicalDevice = gfxSystem->GetPhysicalDevice()->GetVkPhysicalDevice();
initInfo.Device = gfxSystem->GetDevice()->GetVkLogicalDevice();
initInfo.Queue = gfxSystem->GetQueue()->GetVkQueue();
initInfo.DescriptorPool = gfxSystem->GetDescriptorPool()->GetVkHandle();
initInfo.MinImageCount = initInfo.ImageCount = gfxSystem->GetSwapchain()->GetNumImages();
initInfo.MSAASamples = VK_SAMPLE_COUNT_1_BIT;
imguiCommandPool = gfxSystem->GetDevice()->CreateCommandPool(SH_QUEUE_FAMILY_ARRAY_INDEX::GRAPHICS, SH_CMD_POOL_RESET::POOL_BASED, true);
imguiCommandBuffer = imguiCommandPool->RequestCommandBuffer(SH_CMD_BUFFER_TYPE::PRIMARY);
auto const& renderers = gfxSystem->GetDefaultViewport()->GetRenderers();
SHASSERT(!renderers.empty(), "No Renderers available")
auto renderGraph = renderers[0]->GetRenderGraph();
auto renderPass = renderGraph->GetNode("ImGui Node")->GetRenderpass();
if(ImGui_ImplVulkan_Init(&initInfo, renderPass->GetVkRenderpass()) == false)
{
SHLOG_CRITICAL("Editor backend initialisation; Failed to initialise Vulkan backend")
}
imguiCommandBuffer->BeginRecording();
if(ImGui_ImplVulkan_CreateFontsTexture(imguiCommandBuffer->GetVkCommandBuffer()) == false)
{
SHLOG_CRITICAL("Editor backend initialisation; Failed to create fonts texture for Vulkan backend")
}
imguiCommandBuffer->EndRecording();
gfxSystem->GetQueue()->SubmitCommandBuffer({ imguiCommandBuffer }, {}, {}, vk::PipelineStageFlagBits::eNone, {});
ImGui_ImplVulkan_DestroyFontUploadObjects();
renderGraph->GetNode("ImGui Node")->GetSubpass("ImGui Draw")->AddExteriorDrawCalls([](Handle<SHVkCommandBuffer>& cmd) {
ImGui_ImplVulkan_RenderDrawData(ImGui::GetDrawData(), cmd->GetVkCommandBuffer());
});
} }
void SHEditor::NewFrame() void SHEditor::NewFrame()
{ {
SDL_Event event;
while (SDL_PollEvent(&event) != 0)
{
ImGui_ImplSDL2_ProcessEvent(&event);
}
ImGui_ImplVulkan_NewFrame(); ImGui_ImplVulkan_NewFrame();
ImGui_ImplSDL2_NewFrame(); ImGui_ImplSDL2_NewFrame();
ImGui::NewFrame(); ImGui::NewFrame();
} }
void SHEditor::EndFrame()
{ }//namespace SHADE
}
}

View File

@ -1,29 +0,0 @@
#pragma once
#include "SH_API.h"
#include <SDL.h>
#include "Resource/Handle.h"
namespace SHADE
{
class SHVkCommandBuffer;
class SHVkCommandPool;
class SH_API SHEditor
{
public:
static void Initialise(SDL_Window* sdlWindow);
static void PreRender();
static void Render();
static void Exit();
private:
static void InitBackend();
static void NewFrame();
static void EndFrame();
static Handle<SHVkCommandPool> imguiCommandPool;
static Handle<SHVkCommandBuffer> imguiCommandBuffer;
};
}

View File

@ -0,0 +1,168 @@
#pragma once
//#==============================================================#
//|| STL Includes ||
//#==============================================================#
#include <vector>
#include <unordered_map>
//#==============================================================#
//|| SHADE Includes ||
//#==============================================================#
#include "SH_API.h"
#include "ECS_Base/SHECSMacros.h"
#include "Resource/Handle.h"
#include "EditorWindow/SHEditorWindow.h"
#include "Tools/SHLogger.h"
//#==============================================================#
//|| Library Includes ||
//#==============================================================#
#include <SDL_video.h>
namespace SHADE
{
//#==============================================================#
//|| Forward Declarations ||
//#==============================================================#
class SHVkCommandBuffer;
class SHVkCommandPool;
/**
* @brief SHEditor static class contains editor variables and implementation of editor functions.
*
*/
class SH_API SHEditor
{
public:
//#==============================================================#
//|| Type Aliases ||
//#==============================================================#
using EditorWindowID = uint8_t;
using EditorWindowPtr = std::unique_ptr<SHEditorWindow>;
using EditorWindowMap = std::unordered_map<EditorWindowID, EditorWindowPtr>;
/**
* @brief Style options
*
*/
enum class Style : uint8_t
{
SHADE,
DARK,
LIGHT,
CLASSIC
};
/**
* @brief Initialise the editor
*
* @param sdlWindow pointer to SDL_Window object created in application
*/
static void Initialise(SDL_Window* sdlWindow);
/**
* @brief Update the editor and add to ImGui DrawList
*
* @param dt Delta-time of the frame
*/
static void Update(float dt);
/**
* @brief Safely shutdown the editor
*
*/
static void Exit();
/**
* @brief Set the Style for the editor
*
* @param style Desired style
*/
static void SetStyle(Style style);
/**
* @brief Get ID for the Editor Window Type
*
* @tparam T Type of Editor Window
* @return EditorWindowID ID of Editor Window Type
*/
template <typename T, std::enable_if_t<std::is_base_of_v<SHEditorWindow, T>, bool> = true>
static EditorWindowID GetEditorWindowID()
{
static EditorWindowID id;
static bool idCreated = false;
if (!idCreated)
{
id = windowCount++;
idCreated = true;
}
return id;
}
/**
* @brief Get pointer to the Editor Window
*
* @tparam T Type of editor window to retrieve
* @return T* Pointer to the editor window
*/
template <typename T, std::enable_if_t<std::is_base_of_v<SHEditorWindow, T>, bool> = true>
static T* GetEditorWindow()
{
return reinterpret_cast<T*>(editorWindows[GetEditorWindowID<T>()].get());
}
// List of selected entities
static std::vector<EntityID> selectedEntities;
private:
/**
* @brief Initialise Backend for ImGui (SDL and Vulkan backend)
*
* @param sdlWindow Pointer to SDL_Window
*/
static void InitBackend(SDL_Window* sdlWindow);
/**
* @brief Start new frame for editor
*
*/
static void NewFrame();
/**
* @brief Perform ImGui and ImGui Backend Render
*
*/
static void Render();
/**
* @brief Create an Editor Window
*
* @tparam T Type of Editor Window to create
*/
template <typename T, std::enable_if_t<std::is_base_of_v<SHEditorWindow, T>, bool> = true>
static void CreateEditorWindow()
{
static bool isCreated = false;
if (!isCreated)
{
editorWindows[GetEditorWindowID<T>()] = std::make_unique<T>();
isCreated = true;
}
else
{
SHLOG_WARNING("Attempt to create duplicate of Editor window type")
}
}
static void InitFonts() noexcept;
// Handle to command pool used for ImGui Vulkan Backend
static Handle<SHVkCommandPool> imguiCommandPool;
// Handle to command buffer used for ImGui Vulkan Backend
static Handle<SHVkCommandBuffer> imguiCommandBuffer;
// Number of windows; used for Editor Window ID Generation
static EditorWindowID windowCount;
// Map of Editor Windows
static EditorWindowMap editorWindows;
};//class SHEditor
}//namespace SHADE

View File

@ -0,0 +1,187 @@
#pragma once
//#==============================================================#
//|| STL Includes ||
//#==============================================================#
#include <functional>
#include <string>
#include <iterator>
//#==============================================================#
//|| SHADE Includes ||
//#==============================================================#
#include "Math/SHMath.h"
#include "Command/SHCommandManager.h"
#include "SHImGuiHelpers.hpp"
//#==============================================================#
//|| Library Includes ||
//#==============================================================#
#include <imgui.h>
#include <imgui_internal.h>
#include <misc/cpp/imgui_stdlib.h>
#include <rttr/type.h>
namespace SHADE
{
//#==============================================================#
//|| 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();
const ImGuiID id = window->GetID("##Splitter");
ImRect bb;
bb.Min = window->DC.CursorPos + (verticalSplit ? ImVec2(*size1, 0.0f) : ImVec2(0.0f, *size1));
bb.Max = bb.Min + (verticalSplit ? ImVec2(thickness, splitterAxisSize) : ImVec2(splitterAxisSize, thickness));
return ImGui::SplitterBehavior(bb, id, verticalSplit ? ImGuiAxis_X : ImGuiAxis_Y, size1, size2, minSize1, minSize2, 0.0f);
}
template <typename T, std::size_t N>
static bool DragN(const std::string& fieldLabel, std::vector<std::string>const& componentLabels,
std::vector<T*> values, float speed = 0.1f, const char* displayFormat = "", T valueMin = T(), T valueMax = T(),
ImGuiSliderFlags flags = 0)
{
const ImGuiWindow* const window = ImGui::GetCurrentWindow();
if (window->SkipItems)
return false;
const ImGuiContext& g = *GImGui;
bool valueChanged = false;
ImGui::BeginGroup();
ImGui::PushID(fieldLabel.c_str());
PushMultiItemsWidthsAndLabels(componentLabels, 0.0f);
ImGui::BeginColumns("DragVecCol", 2, ImGuiOldColumnFlags_NoBorder | ImGuiOldColumnFlags_NoResize);
ImGui::SetColumnWidth(-1, 80.0f);
ImGui::Text(fieldLabel.c_str());
ImGui::NextColumn();
for (std::size_t i = 0; i < N; ++i)
{
ImGui::PushID(static_cast<int>(i));
ImGui::TextUnformatted(componentLabels[i].c_str(), ImGui::FindRenderedTextEnd(componentLabels[i].c_str())); ImGui::SameLine();
ImGui::SetNextItemWidth(80.0f);
valueChanged |= ImGui::DragFloat("##v", values[i], speed, valueMin, valueMax, displayFormat, flags);
const ImVec2 min = ImGui::GetItemRectMin();
const ImVec2 max = ImGui::GetItemRectMax();
const float spacing = g.Style.FrameRounding;
const float halfSpacing = spacing / 2;
window->DrawList->AddLine({ min.x + spacing, max.y - halfSpacing }, { max.x - spacing, max.y - halfSpacing },
ImGuiColors::colors[i], 4);
ImGui::SameLine(0, g.Style.ItemInnerSpacing.x);
ImGui::PopID();
ImGui::PopItemWidth();
}
ImGui::EndColumns();
ImGui::PopID();
ImGui::EndGroup();
return valueChanged;
}
static bool DragVec2(const std::string& fieldLabel, std::vector<std::string>const& componentLabels, std::function<SHVec2(void)> get,
std::function<void(SHVec2)> set, float speed = 0.1f, const char* displayFormat = "%.3f", float valueMin = 0.0f, float valueMax = 0.0f,
ImGuiSliderFlags flags = 0)
{
SHVec2 values = get();
bool changed = false;
if (DragN<float, 2>(fieldLabel, componentLabels, {&values.x, &values.y}, speed, displayFormat, valueMin, valueMax, flags))
{
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;
}
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;
}
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;
}
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;
}
if (changed)
{
if (ImGui::IsMouseDown(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left, -0.2f))
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec4>>(get(), values, set)), false);
else if(ImGui::IsMouseDragging(ImGuiMouseButton_Left))
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec4>>(get(), values, set)), true);
else if(ImGui::IsItemDeactivatedAfterEdit())
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec4>>(get(), values, set)), false);
}
return changed;
}
//#==============================================================#
//|| Widget Extensions ||
//#==============================================================#
static bool CheckBox(std::string const& label, std::function<bool(void)> get, std::function<void(bool const&)> set)
{
bool value = get();
if (ImGui::Checkbox(label.c_str(), &value))
{
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<bool>>(get(), value, set)), false);
return true;
}
return false;
}
template<typename T>
static bool RadioButton(std::vector<std::string> const& listLabels, std::vector<T> const& listTypes, std::function<T(void)> get, std::function<void(T const&)> set)
{
T type = get();
for (size_t i = 0; i < listTypes.size(); i++)
{
if (ImGui::RadioButton(listLabels[i].c_str(), type == listTypes[i]))
{
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<T>>(get(), listTypes[i], set)), false);
}
ImGui::SameLine();
}
return true;
}
}//namespace SHADE

View File

@ -0,0 +1,69 @@
#pragma once
//#==============================================================#
//|| STL Includes ||
//#==============================================================#
#include <string>
//#==============================================================#
//|| SHADE Includes ||
//#==============================================================#
#include "Math/SHMath.h"
//#==============================================================#
//|| SHADE-ImGui Math Conversions ||
//#==============================================================#
#ifndef SH_IM_MATH
#define IM_VEC2_CLASS_EXTRA \
ImVec2(const SHADE::SHVec2& vec) {x = vec.x; y = vec.y;} \
operator SHADE::SHVec2() const {return SHADE::SHVec2(x,y);}
#define IM_VEC3_CLASS_EXTRA \
ImVec3(const SHADE::SHVec3& vec) {x = vec.x; y = vec.y; z = vec.z;} \
operator SHADE::SHVec3() const {return SHADE::SHVec3(x,y,z);}
#define IM_VEC4_CLASS_EXTRA \
ImVec4(const SHADE::SHVec4& vec) {x = vec.x; y = vec.y; z = vec.z; w = vec.w;} \
operator SHADE::SHVec4() const {return SHADE::SHVec4(x,y,z,w);}
#endif
#define IMGUI_DEFINE_MATH_OPERATORS
//#==============================================================#
//|| Library Includes ||
//#==============================================================#
#include <imgui_internal.h>
#include <imgui.h>
namespace SHADE
{
namespace ImGuiColors
{
constexpr ImVec4 red = {1.0f, 0.0f, 0.0f, 1.f};
constexpr ImVec4 green = {0.0f, 1.0f, 0.0f, 1.f};
constexpr ImVec4 blue = {0.0f, 0.0f, 1.0f, 1.f};
constexpr ImVec4 white = {1.0f, 1.0f, 1.0f, 1.f};
constexpr ImU32 colors[] = {
0xBB0000FF, // red
0xBB00FF00, // green
0xBBFF0000, // blue
0xBBFFFFFF, // white
};
}
static void PushMultiItemsWidthsAndLabels(const std::vector<std::string>& labels, float wFull)
{
ImGuiWindow* window = ImGui::GetCurrentWindow();
const ImGuiStyle& style = GImGui->Style;
if (wFull <= 0.0f)
wFull = ImGui::GetContentRegionAvail().x;
const auto size = labels.size();
const float w_item_one =
ImMax(1.0f, (wFull - (static_cast<float>(size) - 1.0f) * (style.ItemInnerSpacing.x * 2.0f)) / static_cast<float>(
size)) -
style.ItemInnerSpacing.x;
for (int i = 0; i < size; i++)
window->DC.ItemWidthStack.push_back(w_item_one - ImGui::CalcTextSize(labels[i].c_str()).x);
window->DC.ItemWidth = window->DC.ItemWidthStack.back();
}
} //namespace SHADE

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

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 + alignmentSize - 1) & ~(alignmentSize - 1);
}
return alignedSize;
}
/***************************************************************************/ /***************************************************************************/
/*! /*!
@ -288,13 +300,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)
{
alignedSize = (alignedSize + uboBufferMemoryAlignment - 1) & ~(uboBufferMemoryAlignment - 1);
} }
return alignedSize;
uint32_t SHVkLogicalDevice::PadSSBOSize(uint32_t originalSize) const noexcept
{
return ComputeAlignedBufferSize(originalSize, ssboBufferMemoryAlignment);
} }
/***************************************************************************/ /***************************************************************************/
@ -499,6 +510,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:
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
@ -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

@ -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;
@ -82,7 +82,7 @@ namespace SHADE
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,

View File

@ -107,7 +107,7 @@ 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;
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,

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:
//! The vulkan sampler handler
vk::Sampler vkSampler;
public: public:
SHVkSampler () noexcept; /*---------------------------------------------------------------------------------*/
SHVkSampler (SHVkSampler&& rhs) noexcept; /* Constructors */
SHVkSampler&& operator=(SHVkSampler&& rhs) noexcept; /*---------------------------------------------------------------------------------*/
SHVkSampler(Handle<SHVkLogicalDevice> logicalDevice, const SHVkSamplerParams& params = {}) noexcept;
SHVkSampler(SHVkSampler&& rhs) noexcept;
~SHVkSampler() noexcept;
vk::Sampler GetVkSampler (void) const noexcept; /*---------------------------------------------------------------------------------*/
/* Overloaded Operators */
/*---------------------------------------------------------------------------------*/
SHVkSampler& operator=(SHVkSampler&& rhs) 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

@ -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/SHDDSAsset.h"
namespace SHADE namespace SHADE
{ {
@ -91,8 +93,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);
@ -135,11 +139,13 @@ namespace SHADE
//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("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", "Normals",*/ "Present" }, {}); // no predecessors auto node = worldRenderGraph->AddNode("G-Buffer", { /*"Composite", "Position", */"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("Present"); gBufferWriteSubpass->AddColorOutput("Present");
//writeSubpass->AddColorOutput("Normals"); //writeSubpass->AddColorOutput("Normals");
@ -222,6 +228,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)
{ {
@ -250,6 +259,17 @@ namespace SHADE
currentCmdBuffer->BindIndexBuffer(buffer, 0); currentCmdBuffer->BindIndexBuffer(buffer, 0);
} }
std::array<uint32_t, 1> texDynamicOffset {0};
// Bind textures
currentCmdBuffer->BindDescriptorSet
(
texLibrary.GetTextureDescriptorSetGroup(),
vk::PipelineBindPoint::eGraphics,
0,
std::span<uint32_t, 1>{texDynamicOffset.data(), texDynamicOffset.size()}
);
// bind camera data // bind camera data
renderers[renIndex]->UpdateDataAndBind(currentCmdBuffer, frameIndex); renderers[renIndex]->UpdateDataAndBind(currentCmdBuffer, frameIndex);
@ -453,7 +473,36 @@ 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 SHDDSAsset& ddsAsset)
{
auto sampler = samplerCache.GetSampler(device, SHVkSamplerParams { .maxLod = static_cast<float>(ddsAsset.image.GetMipCount()) });
return texLibrary.Add(ddsAsset, 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,
globalData->GetDescSetLayouts()[SHGraphicsConstants::DescriptorSetIndex::STATIC_GLOBALS]
);
} }
void SHGraphicsSystem::SetWindow(SHWindow* wind) noexcept void SHGraphicsSystem::SetWindow(SHWindow* wind) noexcept

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
{ {
@ -188,6 +190,62 @@ 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 SHDDSAsset& ddsAsset);
Handle<SHTexture> Add(uint32_t pixelCount, const SHTexture::PixelChannel* const pixelData, uint32_t width, uint32_t height, SHTexture::TextureFormat format, std::vector<uint32_t> mipOffsets);
/*******************************************************************************/
/*!
\brief
Removes a mesh from the Texture Library. But this does not mean that the
textures have been removed yet. A call to "BuildTextures()" is required to
finalise all changes.
\param mesh
Handle to the Texture to remove.
*/
/*******************************************************************************/
void Remove(Handle<SHTexture> tex);
/***************************************************************************/
/*!
\brief
Finalises all changes to the Texture Library into the GPU buffers.
\param cmdBuffer
Command buffer used to set up transfers of data in the GPU memory. This
call must be preceded by calls to cmdBuffer's BeginRecording() and ended
with EndRecording(). Do recall to also submit the cmdBuffer to a transfer
queue.
*/
/***************************************************************************/
void BuildTextures();
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* Setters */ /* Setters */
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
@ -202,6 +260,7 @@ namespace SHADE
Handle<SHVkPhysicalDevice> GetPhysicalDevice() const { return physicalDevice; } Handle<SHVkPhysicalDevice> GetPhysicalDevice() const { return physicalDevice; }
Handle<SHVkQueue> GetQueue() const { return graphicsQueue; } Handle<SHVkQueue> GetQueue() const { return graphicsQueue; }
Handle<SHVkDescriptorPool> GetDescriptorPool() const { return descPool; } Handle<SHVkDescriptorPool> GetDescriptorPool() const { return descPool; }
Handle<SHViewport> GetDefaultViewport() const {return defaultViewport;}
//SHRenderGraph const& GetRenderGraph(void) const noexcept; //SHRenderGraph const& GetRenderGraph(void) const noexcept;
//Handle<SHVkRenderpass> GetRenderPass() const { return renderPass; } //Handle<SHVkRenderpass> GetRenderPass() const { return renderPass; }
@ -219,8 +278,10 @@ namespace SHADE
Handle<SHVkQueue> graphicsQueue; Handle<SHVkQueue> graphicsQueue;
Handle<SHVkQueue> transferQueue; Handle<SHVkQueue> transferQueue;
Handle<SHVkDescriptorPool> descPool; Handle<SHVkDescriptorPool> descPool;
Handle<SHVkCommandPool> graphicsCmdPool;
Handle<SHVkCommandPool> transferCmdPool; Handle<SHVkCommandPool> transferCmdPool;
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
@ -232,6 +293,8 @@ namespace SHADE
// 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

View File

@ -20,18 +20,51 @@ of DigiPen Institute of Technology is prohibited.
#include "Graphics/Commands/SHVkCommandBuffer.h" #include "Graphics/Commands/SHVkCommandBuffer.h"
#include "Graphics/SHVkUtil.h" #include "Graphics/SHVkUtil.h"
#include "Tools/SHLogger.h" #include "Tools/SHLogger.h"
#include "Graphics/MiddleEnd/Interface/SHGraphicsConstants.h"
#include "Graphics/Descriptors/SHVkDescriptorSetGroup.h"
#include "Assets/Asset Types/SHDDSAsset.h"
#include "Graphics/Images/SHVkImage.h"
namespace SHADE namespace SHADE
{ {
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Usage Functions */ /* Usage Functions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
Handle<SHTexture> SHTextureLibrary::Add(uint32_t pixelCount, const SHTexture::PixelChannel* const pixelData, SHTexture::TextureFormat format, uint32_t mipLevels) Handle<SHTexture> SHTextureLibrary::Add(const SHDDSAsset& ddsAsset, Handle<SHVkSampler> sampler)
{
// Define constants
const uint32_t IMG_WIDTH = ddsAsset.image.GetWidth();
const uint32_t IMG_HEIGHT = ddsAsset.image.GetHeight();
const uint32_t MIPMAP_LEVEL = ddsAsset.image.GetMipCount();
// Compute total texture size and create buffer image copy objects
std::vector<uint32_t> mipOffsets(MIPMAP_LEVEL);
uint32_t texBytes = 0;
for (uint32_t i = 0; i < MIPMAP_LEVEL; i++)
{
mipOffsets[i] = texBytes;
// Get ready for next mip
texBytes += ddsAsset.image.GetImageData(i)->m_memSlicePitch;
}
return Add
(
texBytes,
reinterpret_cast<const SHTexture::PixelChannel*>(ddsAsset.image.m_dds.data()),
IMG_WIDTH, IMG_HEIGHT,
ddsLoaderToVkFormat(ddsAsset.image.GetFormat(), true),
mipOffsets,
sampler
);
}
Handle<SHTexture> SHTextureLibrary::Add(uint32_t pixelCount, const SHTexture::PixelChannel* const pixelData, uint32_t width, uint32_t height, SHTexture::TextureFormat format, std::vector<uint32_t> mipOffsets, Handle<SHVkSampler> sampler)
{ {
isDirty = true; isDirty = true;
auto handle = resourceManager.Create<SHTexture>(); auto handle = resourceManager.Create<SHTexture>();
addJobs.emplace_back(AddJob { pixelCount, pixelData, format, mipLevels }); addJobs.emplace_back(AddJob { pixelCount, pixelData, format, sampler, mipOffsets, width, height, handle });
return handle; return handle;
} }
@ -44,22 +77,48 @@ namespace SHADE
isDirty = true; isDirty = true;
} }
void SHTextureLibrary::BuildImages(Handle<SHVkLogicalDevice> device, Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHVkQueue> graphicsQueue, Handle<SHVkDescriptorPool> descPool, Handle<SHVkDescriptorSetLayout> descLayout) void SHTextureLibrary::BuildTextures(Handle<SHVkLogicalDevice> device, Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHVkQueue> graphicsQueue, Handle<SHVkDescriptorPool> descPool, Handle<SHVkDescriptorSetLayout> descLayout)
{ {
// Don't do anything if there are no updates
if (!isDirty)
return;
/* Remove Textures */ /* Remove Textures */
std::vector<vk::ImageMemoryBarrier> pipelineBarriers(addJobs.size()); // TODO
/* Add Textures */ /* Add Textures */
// Transition // Load Textures - Transitions
std::vector<vk::ImageMemoryBarrier> pipelineBarriers(addJobs.size());
for (int i = 0; auto& job : addJobs) for (int i = 0; auto& job : addJobs)
{ {
job.Image = resourceManager.Create<SHVkImage>(); job.Image = resourceManager.Create<SHVkImage>
(
&device->GetVMAAllocator(),
SHImageCreateParams
{
.imageType = vk::ImageType::e2D,
.width = job.Width,
.height = job.Height,
.depth = 1,
.levels = static_cast<uint8_t>(job.MipOffsets.size()),
.arrayLayers = 1,
.imageFormat = job.TextureFormat,
.usageFlags = vk::ImageUsageFlagBits::eSampled | vk::ImageUsageFlagBits::eTransferDst,
.createFlags = {}
},
job.PixelData,
job.PixelCount,
job.MipOffsets,
VmaMemoryUsage::VMA_MEMORY_USAGE_AUTO,
VmaAllocationCreateFlagBits {}
);
job.Image->PrepareImageTransitionInfo(vk::ImageLayout::eUndefined, vk::ImageLayout::eTransferDstOptimal, pipelineBarriers[i]); job.Image->PrepareImageTransitionInfo(vk::ImageLayout::eUndefined, vk::ImageLayout::eTransferDstOptimal, pipelineBarriers[i]);
++i; ++i;
} }
vk::PipelineStageFlagBits srcStage = vk::PipelineStageFlagBits::eTopOfPipe; vk::PipelineStageFlagBits srcStage = vk::PipelineStageFlagBits::eTopOfPipe;
vk::PipelineStageFlagBits dstStage = vk::PipelineStageFlagBits::eTopOfPipe; vk::PipelineStageFlagBits dstStage = vk::PipelineStageFlagBits::eTopOfPipe;
preparePipelineBarriers(vk::ImageLayout::eUndefined, vk::ImageLayout::eTransferDstOptimal, srcStage, dstStage, pipelineBarriers); preparePipelineBarriers(vk::ImageLayout::eUndefined, vk::ImageLayout::eTransferDstOptimal, srcStage, dstStage, pipelineBarriers);
cmdBuffer->BeginRecording();
cmdBuffer->PipelineBarrier(vk::PipelineStageFlagBits::eTopOfPipe, vk::PipelineStageFlagBits::eTransfer, {}, {}, {}, pipelineBarriers); cmdBuffer->PipelineBarrier(vk::PipelineStageFlagBits::eTopOfPipe, vk::PipelineStageFlagBits::eTransfer, {}, {}, {}, pipelineBarriers);
// Copy // Copy
@ -73,13 +132,16 @@ namespace SHADE
{ {
// Transition // Transition
job.Image->PrepareImageTransitionInfo(vk::ImageLayout::eTransferDstOptimal, vk::ImageLayout::eShaderReadOnlyOptimal, pipelineBarriers[i]); job.Image->PrepareImageTransitionInfo(vk::ImageLayout::eTransferDstOptimal, vk::ImageLayout::eShaderReadOnlyOptimal, pipelineBarriers[i]);
++i;
} }
preparePipelineBarriers(vk::ImageLayout::eTransferDstOptimal, vk::ImageLayout::eShaderReadOnlyOptimal, srcStage, dstStage, pipelineBarriers); preparePipelineBarriers(vk::ImageLayout::eTransferDstOptimal, vk::ImageLayout::eShaderReadOnlyOptimal, srcStage, dstStage, pipelineBarriers);
cmdBuffer->PipelineBarrier(vk::PipelineStageFlagBits::eTopOfPipe, vk::PipelineStageFlagBits::eTransfer, {}, {}, {}, pipelineBarriers); cmdBuffer->PipelineBarrier(vk::PipelineStageFlagBits::eTransfer, vk::PipelineStageFlagBits::eFragmentShader, {}, {}, {}, pipelineBarriers);
// Execute Commands // Execute Commands
cmdBuffer->EndRecording();
graphicsQueue->SubmitCommandBuffer({ cmdBuffer }); graphicsQueue->SubmitCommandBuffer({ cmdBuffer });
device->WaitIdle(); device->WaitIdle();
graphicsQueue->GetVkQueue().waitIdle();
// Create Image View // Create Image View
for (auto& job : addJobs) for (auto& job : addJobs)
@ -90,16 +152,39 @@ namespace SHADE
.format = job.TextureFormat, .format = job.TextureFormat,
.imageAspectFlags = vk::ImageAspectFlagBits::eColor, .imageAspectFlags = vk::ImageAspectFlagBits::eColor,
.baseMipLevel = 0, .baseMipLevel = 0,
.mipLevelCount = job.MipLevels, .mipLevelCount = static_cast<uint32_t>(job.MipOffsets.size()),
.baseArrayLayer = 0, .baseArrayLayer = 0,
.layerCount = 0 .layerCount = 1
}; };
job.Handle->ImageView = job.Image->CreateImageView(device, job.Image, DETAILS); job.TextureHandle->ImageView = job.Image->CreateImageView(device, job.Image, DETAILS);
} }
// Build Descriptor // Add Textures
Handle<SHVkDescriptorSetGroup> descSetGroup = descPool->Allocate({ descLayout }, { 1 }); for (auto& job : addJobs)
{
texOrder.emplace_back(job.TextureHandle);
combinedImageSamplers.emplace_back(std::make_tuple(job.TextureHandle->ImageView, job.Sampler, vk::ImageLayout::eShaderReadOnlyOptimal));
job.TextureHandle->TextureArrayIndex = texOrder.size() - 1;
}
addJobs.clear();
/* Build Descriptor Set with all the Textures */
if (!texDescriptors)
{
texDescriptors = descPool->Allocate({ descLayout }, { static_cast<uint32_t>(texOrder.size()) });
}
const auto ALIGNED_SIZE = device->PadSSBOSize(sizeof(uint32_t));
texDescriptors->ModifyWriteDescImage
(
SHGraphicsConstants::DescriptorSetIndex::STATIC_GLOBALS,
SHGraphicsConstants::DescriptorSetBindings::IMAGE_AND_SAMPLERS_DATA,
combinedImageSamplers
);
texDescriptors->UpdateDescriptorSetImages
(
SHGraphicsConstants::DescriptorSetIndex::STATIC_GLOBALS,
SHGraphicsConstants::DescriptorSetBindings::IMAGE_AND_SAMPLERS_DATA
);
isDirty = false; isDirty = false;
} }
@ -139,4 +224,35 @@ namespace SHADE
} }
} }
vk::Format SHTextureLibrary::ddsLoaderToVkFormat(tinyddsloader::DDSFile::DXGIFormat format, bool isLinear)
{
switch (format)
{
case tinyddsloader::DDSFile::DXGIFormat::BC1_UNorm:
case tinyddsloader::DDSFile::DXGIFormat::BC1_UNorm_SRGB:
return isLinear ? vk::Format::eBc1RgbaUnormBlock : vk::Format::eBc1RgbaSrgbBlock;
case tinyddsloader::DDSFile::DXGIFormat::BC2_UNorm:
case tinyddsloader::DDSFile::DXGIFormat::BC2_UNorm_SRGB:
return isLinear ? vk::Format::eBc2UnormBlock : vk::Format::eBc2SrgbBlock;
case tinyddsloader::DDSFile::DXGIFormat::BC3_UNorm:
case tinyddsloader::DDSFile::DXGIFormat::BC3_UNorm_SRGB:
return isLinear ? vk::Format::eBc3UnormBlock : vk::Format::eBc3SrgbBlock;
case tinyddsloader::DDSFile::DXGIFormat::BC5_UNorm:
case tinyddsloader::DDSFile::DXGIFormat::BC5_SNorm:
return isLinear ? vk::Format::eBc5UnormBlock : vk::Format::eBc5SnormBlock;
case tinyddsloader::DDSFile::DXGIFormat::R8G8B8A8_UNorm:
case tinyddsloader::DDSFile::DXGIFormat::R8G8B8A8_UNorm_SRGB:
return isLinear ? vk::Format::eR8G8B8A8Unorm : vk::Format::eR8G8B8A8Srgb;
case tinyddsloader::DDSFile::DXGIFormat::R8G8B8A8_SNorm:
return vk::Format::eR8G8B8A8Snorm;
case tinyddsloader::DDSFile::DXGIFormat::B8G8R8A8_UNorm:
case tinyddsloader::DDSFile::DXGIFormat::B8G8R8A8_UNorm_SRGB:
return isLinear ? vk::Format::eB8G8R8A8Unorm : vk::Format::eB8G8R8A8Srgb;
case tinyddsloader::DDSFile::DXGIFormat::B8G8R8X8_UNorm:
case tinyddsloader::DDSFile::DXGIFormat::B8G8R8X8_UNorm_SRGB:
return isLinear ? vk::Format::eB8G8R8A8Unorm : vk::Format::eB8G8R8Srgb;
default:
throw std::runtime_error("Unsupported DDS format.");
}
}
} }

View File

@ -14,6 +14,8 @@ of DigiPen Institute of Technology is prohibited.
// STL Includes // STL Includes
#include <vector> #include <vector>
// External Dependencies
#include "tinyddsloader.h"
// Project Includes // Project Includes
#include "Resource/Handle.h" #include "Resource/Handle.h"
#include "Resource/ResourceLibrary.h" #include "Resource/ResourceLibrary.h"
@ -33,6 +35,9 @@ namespace SHADE
class SHVkQueue; class SHVkQueue;
class SHVkDescriptorPool; class SHVkDescriptorPool;
class SHVkDescriptorSetLayout; class SHVkDescriptorSetLayout;
class SHVkDescriptorSetGroup;
class SHVkSampler;
struct SHDDSAsset;
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Type Definitions */ /* Type Definitions */
@ -43,7 +48,7 @@ namespace SHADE
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* Type Definitions */ /* Type Definitions */
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
using PixelChannel = float; using PixelChannel = unsigned char;
using TextureFormat = vk::Format; // TODO: Change using TextureFormat = vk::Format; // TODO: Change
using Index = uint32_t; using Index = uint32_t;
@ -71,7 +76,7 @@ namespace SHADE
\brief \brief
Adds a texture to the Texture Library. But this does not mean that the Adds a texture to the Texture Library. But this does not mean that the
textures have been added yet. A call to "BuildImages()" is required to textures have been added yet. A call to "BuildTextures()" is required to
transfer all textures into the GPU. transfer all textures into the GPU.
\param pixelCount \param pixelCount
@ -88,13 +93,15 @@ namespace SHADE
*/ */
/*******************************************************************************/ /*******************************************************************************/
Handle<SHTexture> Add(uint32_t pixelCount, const SHTexture::PixelChannel* const pixelData, SHTexture::TextureFormat format, uint32_t mipLevels);
Handle<SHTexture> Add(const SHDDSAsset& ddsAsset, Handle<SHVkSampler> sampler);
Handle<SHTexture> Add(uint32_t pixelCount, const SHTexture::PixelChannel* const pixelData, uint32_t width, uint32_t height, SHTexture::TextureFormat format, std::vector<uint32_t> mipOffsets, Handle<SHVkSampler> sampler);
/*******************************************************************************/ /*******************************************************************************/
/*! /*!
\brief \brief
Removes a mesh from the Texture Library. But this does not mean that the Removes a mesh from the Texture Library. But this does not mean that the
textures have been removed yet. A call to "BuildImages()" is required to textures have been removed yet. A call to "BuildTextures()" is required to
finalise all changes. finalise all changes.
\param mesh \param mesh
@ -118,12 +125,12 @@ namespace SHADE
queue. queue.
*/ */
/***************************************************************************/ /***************************************************************************/
void BuildImages(Handle<SHVkLogicalDevice> device, Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHVkQueue> graphicsQueue, Handle<SHVkDescriptorPool> descPool, Handle<SHVkDescriptorSetLayout> descLayout); void BuildTextures(Handle<SHVkLogicalDevice> device, Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHVkQueue> graphicsQueue, Handle<SHVkDescriptorPool> descPool, Handle<SHVkDescriptorSetLayout> descLayout);
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* Getter Functions */ /* Getter Functions */
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
Handle<SHVkBuffer> GetTextureBuffer() const noexcept { return texStorageBuffer; } Handle<SHVkDescriptorSetGroup> GetTextureDescriptorSetGroup() const noexcept { return texDescriptors; }
private: private:
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
@ -134,9 +141,12 @@ namespace SHADE
uint32_t PixelCount = 0; uint32_t PixelCount = 0;
const SHTexture::PixelChannel* PixelData = nullptr; const SHTexture::PixelChannel* PixelData = nullptr;
SHTexture::TextureFormat TextureFormat = {}; SHTexture::TextureFormat TextureFormat = {};
uint32_t MipLevels = 0; Handle<SHVkSampler> Sampler;
std::vector<uint32_t> MipOffsets;
uint32_t Width;
uint32_t Height;
Handle<SHTexture> TextureHandle;
Handle<SHVkImage> Image; Handle<SHVkImage> Image;
Handle<SHTexture> Handle;
}; };
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
@ -149,9 +159,9 @@ namespace SHADE
ResourceManager resourceManager; ResourceManager resourceManager;
std::vector<Handle<SHTexture>> texOrder; std::vector<Handle<SHTexture>> texOrder;
// CPU Storage // CPU Storage
std::vector<SHTexture::PixelChannel> texStorage; std::vector<std::tuple<Handle<SHVkImageView>, Handle<SHVkSampler>, vk::ImageLayout>> combinedImageSamplers;
// GPU Storage // GPU Storage
Handle<SHVkBuffer> texStorageBuffer{}; Handle<SHVkDescriptorSetGroup> texDescriptors;
// Flags // Flags
bool isDirty = true; bool isDirty = true;
@ -159,5 +169,6 @@ namespace SHADE
/* Helper Functions */ /* Helper Functions */
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
void preparePipelineBarriers(vk::ImageLayout oldLayout, vk::ImageLayout newLayout, vk::PipelineStageFlagBits& srcStage, vk::PipelineStageFlagBits& dstStage, std::vector<vk::ImageMemoryBarrier>& barriers); void preparePipelineBarriers(vk::ImageLayout oldLayout, vk::ImageLayout newLayout, vk::PipelineStageFlagBits& srcStage, vk::PipelineStageFlagBits& dstStage, std::vector<vk::ImageMemoryBarrier>& barriers);
vk::Format ddsLoaderToVkFormat(tinyddsloader::DDSFile::DXGIFormat format, bool isLinear);
}; };
} }

View File

@ -0,0 +1,75 @@
/************************************************************************************//*!
\file SHVkSamplerCache.cpp
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Mar 16, 2022
\brief Contains the implementation for the SHVkSamplerCache class.
Copyright (C) 2022 DigiPen Institute of Technology.
Reproduction or disclosure of this file or its contents without the prior written consent
of DigiPen Institute of Technology is prohibited.
*//*************************************************************************************/
#include "SHpch.h"
#include "SHVkSamplerCache.h"
// Standard Library
#include <functional>
// Project Header
#include "Graphics/Images/SHVkSampler.h"
#include "Graphics/Devices/SHVkLogicalDevice.h"
namespace SHADE
{
/*---------------------------------------------------------------------------------*/
/* Utility Functions */
/*---------------------------------------------------------------------------------*/
void SHSamplerCache::Clear()
{
samplersMap.clear();
}
/*---------------------------------------------------------------------------------*/
/* Getter Functions */
/*---------------------------------------------------------------------------------*/
Handle<SHVkSampler> SHSamplerCache::GetSampler(Handle<SHVkLogicalDevice> device, const SHVkSamplerParams& params)
{
// Get the hash to check if it was cached
const RawSamplerHash HASH = calcHash
(
params.minFilter,
params.magFilter,
params.addressMode,
params.mipmapMode,
params.minLod,
params.maxLod
);
// Check if it was cached
auto sampler = samplersMap.find(HASH);
if (sampler == samplersMap.end())
{
const auto BUILD_RESULT = samplersMap.emplace(HASH, device->CreateSampler(params));
sampler = BUILD_RESULT.first;
}
return sampler->second;
}
/*---------------------------------------------------------------------------------*/
/* Helper Functions */
/*---------------------------------------------------------------------------------*/
SHSamplerCache::RawSamplerHash SHSamplerCache::calcHash(vk::Filter minFilter, vk::Filter magFilter, vk::SamplerAddressMode addressMode, vk::SamplerMipmapMode mipmapMode, float minLod, float maxLod)
{
static auto charHasher = std::hash<uint8_t>{};
static auto floatHasher = std::hash<float>{};
const RawSamplerHash H1 = charHasher(static_cast<uint8_t>(minFilter));
const RawSamplerHash H2 = charHasher(static_cast<uint8_t>(magFilter));
const RawSamplerHash H3 = charHasher(static_cast<uint8_t>(addressMode));
const RawSamplerHash H4 = charHasher(static_cast<uint8_t>(mipmapMode));
const RawSamplerHash H5 = floatHasher(minLod);
const RawSamplerHash H6 = floatHasher(maxLod);
return H1 ^ (H2 << 1) ^ (H3 << 2) ^ (H4 << 3) ^ (H5 << 4) ^ (H6 << 5);
}
}

View File

@ -0,0 +1,80 @@
/************************************************************************************//*!
\file SHSamplerCache.h
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Mar 16, 2022
\brief Contains the interface for the SHSamplerCache class.
Copyright (C) 2022 DigiPen Institute of Technology.
Reproduction or disclosure of this file or its contents without the prior written consent
of DigiPen Institute of Technology is prohibited.
*//*************************************************************************************/
#pragma once
// Standard Libraries
#include <unordered_map>
// External Dependencies
#include "Graphics/SHVulkanIncludes.h"
// Project Includes
#include "Resource/Handle.h"
namespace SHADE
{
/*-----------------------------------------------------------------------------------*/
/* Forward Declarations */
/*-----------------------------------------------------------------------------------*/
class SHVkLogicalDevice;
class SHVkSampler;
struct SHVkSamplerParams;
/*-----------------------------------------------------------------------------------*/
/* Type Definitions */
/*-----------------------------------------------------------------------------------*/
/*************************************************************************************/
/*!
\brief
Class that is responsible for caching and providing Samplers to the user for
sampling textures.
*/
/*************************************************************************************/
class SHSamplerCache
{
public:
/*---------------------------------------------------------------------------------*/
/* Utility Functions */
/*---------------------------------------------------------------------------------*/
/// <summary>
/// Clears the cache, destroying all created samplers.
/// </summary>
void Clear();
/*---------------------------------------------------------------------------------*/
/* Getter Functions */
/*---------------------------------------------------------------------------------*/
/// <summary>
/// Retrieves a Vulkan Sampler of the specified type. If this was retrieved
/// before, a cached copy of the Vulkan Sampler will be provided.
/// </summary>
/// <param name="device">Logical device to create the sampler with if needed.</param>
/// <param name="params">Describes the parameters for the sampler.</param>
/// <returns>Handle to the SHVkSampler object specified.</returns>
Handle<SHVkSampler> GetSampler(Handle<SHVkLogicalDevice> device, const SHVkSamplerParams& params);
private:
/*---------------------------------------------------------------------------------*/
/* Type Definitions */
/*---------------------------------------------------------------------------------*/
using RawSamplerHash = size_t;
/*---------------------------------------------------------------------------------*/
/* Data Members */
/*---------------------------------------------------------------------------------*/
// Resources
std::unordered_map<RawSamplerHash, Handle<SHVkSampler>> samplersMap;
/*---------------------------------------------------------------------------------*/
/* Helper Functions */
/*---------------------------------------------------------------------------------*/
static RawSamplerHash calcHash(vk::Filter minFilter, vk::Filter magFilter, vk::SamplerAddressMode addressMode, vk::SamplerMipmapMode mipmapMode, float minLod, float maxLod);
};
}

View File

@ -73,6 +73,7 @@ namespace SHADE
SHRenderGraph(SHRenderGraph&& rhs) noexcept; SHRenderGraph(SHRenderGraph&& rhs) noexcept;
SHRenderGraph& operator=(SHRenderGraph&& rhs) noexcept; SHRenderGraph& operator=(SHRenderGraph&& rhs) noexcept;
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* PUBLIC MEMBER FUNCTIONS */ /* PUBLIC MEMBER FUNCTIONS */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/

View File

@ -182,3 +182,14 @@ namespace SHADE
} }
} // namespace SHADE } // namespace SHADE
RTTR_REGISTRATION
{
using namespace SHADE;
using namespace rttr;
registration::class_<SHTransformComponent>("Transform Component")
.property("Translate", &SHTransformComponent::GetLocalPosition, &SHTransformComponent::SetLocalPosition)
.property("Rotate", &SHTransformComponent::GetLocalRotation, select_overload<void(SHVec3 const&)>(&SHTransformComponent::SetLocalRotation))
.property("Scale", &SHTransformComponent::GetLocalScale, &SHTransformComponent::SetLocalScale);
}

View File

@ -12,6 +12,7 @@
#include <queue> #include <queue>
#include <rttr/registration>
// Project Headers // Project Headers
#include "SH_API.h" #include "SH_API.h"
#include "ECS_Base/Components/SHComponent.h" #include "ECS_Base/Components/SHComponent.h"
@ -116,6 +117,8 @@ namespace SHADE
SHTransform world; SHTransform world;
UpdateQueue updateQueue; UpdateQueue updateQueue;
RTTR_ENABLE()
}; };

View File

@ -66,15 +66,9 @@ namespace SHADE
for (const auto* child : node->GetChildren()) for (const auto* child : node->GetChildren())
{ {
auto* childTransform = SHComponentManager::GetComponent_s<SHTransformComponent>(child->GetEntityID());
if (childTransform)
{
const bool HAS_TRANSFORM = SHComponentManager::HasComponent<SHTransformComponent>(child->GetEntityID());
if (!HAS_TRANSFORM)
continue;
auto* childTransform = SHComponentManager::GetComponent<SHTransformComponent>(child->GetEntityID());
// Only update if node in hierarchy and component are both active // Only update if node in hierarchy and component are both active
const bool IS_NODE_ACTIVE = child->IsActive(); const bool IS_NODE_ACTIVE = child->IsActive();
if (IS_NODE_ACTIVE && childTransform->isActive) if (IS_NODE_ACTIVE && childTransform->isActive)
@ -82,10 +76,12 @@ namespace SHADE
if (childTransform->dirty || HAS_PARENT_CHANGED) if (childTransform->dirty || HAS_PARENT_CHANGED)
UpdateTransform(*childTransform, NODE_TRANSFORM); UpdateTransform(*childTransform, NODE_TRANSFORM);
} }
}
UpdateEntity(child); UpdateEntity(child);
// Clear dirty flag after all children are updated // Clear dirty flag after all children are updated
if (childTransform)
childTransform->dirty = false; childTransform->dirty = false;
} }
} }
@ -144,8 +140,8 @@ namespace SHADE
tf.world.ComputeTRS(); tf.world.ComputeTRS();
// Transpose TRS to column major // Transpose TRS to column major
tf.local.trs.Transpose(); //tf.local.trs.Transpose();
tf.world.trs.Transpose(); //tf.world.trs.Transpose();
} }
} // namespace SHADE } // namespace SHADE

View File

@ -7,7 +7,8 @@ workspace "SHADE"
configurations configurations
{ {
"Debug", "Debug",
"Release" "Release",
"Publish"
} }
flags flags