diff --git a/Engine/Source/Editor/ECWorld/ECWorldConsumer.cpp b/Engine/Source/Editor/ECWorld/ECWorldConsumer.cpp index ae525ce8..c6db5f13 100644 --- a/Engine/Source/Editor/ECWorld/ECWorldConsumer.cpp +++ b/Engine/Source/Editor/ECWorld/ECWorldConsumer.cpp @@ -22,19 +22,19 @@ namespace editor namespace Detail { -const std::unordered_map materialTextureTypeToUber +const std::unordered_map materialTextureTypeToShaderFeature { - { cd::MaterialTextureType::BaseColor, engine::Uber::ALBEDO_MAP }, - { cd::MaterialTextureType::Normal, engine::Uber::NORMAL_MAP }, - { cd::MaterialTextureType::Occlusion, engine::Uber::ORM_MAP }, - { cd::MaterialTextureType::Roughness, engine::Uber::ORM_MAP }, - { cd::MaterialTextureType::Metallic, engine::Uber::ORM_MAP }, - { cd::MaterialTextureType::Emissive, engine::Uber::EMISSIVE_MAP }, + { cd::MaterialTextureType::BaseColor, engine::ShaderFeature::ALBEDO_MAP }, + { cd::MaterialTextureType::Normal, engine::ShaderFeature::NORMAL_MAP }, + { cd::MaterialTextureType::Occlusion, engine::ShaderFeature::ORM_MAP }, + { cd::MaterialTextureType::Roughness, engine::ShaderFeature::ORM_MAP }, + { cd::MaterialTextureType::Metallic, engine::ShaderFeature::ORM_MAP }, + { cd::MaterialTextureType::Emissive, engine::ShaderFeature::EMISSIVE_MAP }, }; CD_FORCEINLINE bool IsMaterialTextureTypeValid(cd::MaterialTextureType type) { - return materialTextureTypeToUber.find(type) != materialTextureTypeToUber.end(); + return materialTextureTypeToShaderFeature.find(type) != materialTextureTypeToShaderFeature.end(); } } // namespace Detail @@ -299,7 +299,7 @@ void ECWorldConsumer::AddMaterial(engine::Entity entity, const cd::Material* pMa if (Detail::IsMaterialTextureTypeValid(optionalTextureType)) { - materialComponent.ActiveUberShaderOption(Detail::materialTextureTypeToUber.at(optionalTextureType)); + materialComponent.ActiveShaderFeature(Detail::materialTextureTypeToShaderFeature.at(optionalTextureType)); } uint8_t textureSlot = optTextureSlot.value(); diff --git a/Engine/Source/Editor/EditorApp.cpp b/Engine/Source/Editor/EditorApp.cpp index c2a4824d..bba08d91 100644 --- a/Engine/Source/Editor/EditorApp.cpp +++ b/Engine/Source/Editor/EditorApp.cpp @@ -22,6 +22,7 @@ #include "Rendering/BloomRenderer.h" #include "Rendering/PostProcessRenderer.h" #include "Rendering/RenderContext.h" +#include "Rendering/SkeletonRenderer.h" #include "Rendering/SkyboxRenderer.h" #include "Rendering/TerrainRenderer.h" #include "Rendering/WorldRenderer.h" @@ -39,6 +40,7 @@ #include "UILayers/MainMenu.h" #include "UILayers/OutputLog.h" #include "UILayers/SceneView.h" +#include "UILayers/SkeletonView.h" #include "UILayers/Splash.h" #include "UILayers/TestNodeEditor.h" #include "Window/Input.h" @@ -171,6 +173,7 @@ void EditorApp::InitEditorUILayers() pSceneView->SetAABBRenderer(m_pAABBRenderer); m_pEditorImGuiContext->AddDynamicLayer(cd::MoveTemp(pSceneView)); + m_pEditorImGuiContext->AddDynamicLayer(std::make_unique("SkeletonView")); m_pEditorImGuiContext->AddDynamicLayer(std::make_unique("Inspector")); auto pAssetBrowser = std::make_unique("AssetBrowser"); @@ -234,25 +237,18 @@ void EditorApp::InitECWorld() { m_pSceneWorld = std::make_unique(); - if (IsAtmosphericScatteringEnable()) - { - m_pSceneWorld->CreatePBRMaterialType(true); - } - else - { - m_pSceneWorld->CreatePBRMaterialType(false); - } - + m_pSceneWorld->CreatePBRMaterialType(IsAtmosphericScatteringEnable()); m_pSceneWorld->CreateAnimationMaterialType(); m_pSceneWorld->CreateTerrainMaterialType(); InitEditorCameraEntity(); + InitSkyEntity(); + InitShaderVariantCollectionEntity(); + #ifdef ENABLE_DDGI m_pSceneWorld->InitDDGISDK(); InitDDGIEntity(); #endif - - InitSkyEntity(); } void EditorApp::InitEditorCameraEntity() @@ -292,21 +288,6 @@ void EditorApp::InitEditorCameraEntity() cameraComponent.BuildViewMatrix(cameraTransform); } -#ifdef ENABLE_DDGI -void EditorApp::InitDDGIEntity() -{ - engine::World* pWorld = m_pSceneWorld->GetWorld(); - - engine::Entity ddgiEntity = pWorld->CreateEntity(); - m_pSceneWorld->SetDDGIEntity(ddgiEntity); - - auto& nameComponent = pWorld->CreateComponent(ddgiEntity); - nameComponent.SetName("DDGI"); - - pWorld->CreateComponent(ddgiEntity); -} -#endif - void EditorApp::InitSkyEntity() { engine::World* pWorld = m_pSceneWorld->GetWorld(); @@ -340,6 +321,34 @@ void EditorApp::InitSkyEntity() meshComponent.Build(); } +void EditorApp::InitShaderVariantCollectionEntity() +{ + engine::World* pWorld = m_pSceneWorld->GetWorld(); + + engine::Entity shaderVariantCollectionEntity = pWorld->CreateEntity(); + m_pSceneWorld->SetShaderVariantCollectionEntity(shaderVariantCollectionEntity); + + auto& nameComponent = pWorld->CreateComponent(shaderVariantCollectionEntity); + nameComponent.SetName("ShaderVariantCollection"); + + auto& shaderVariantCollectionsComponent = pWorld->CreateComponent(shaderVariantCollectionEntity); +} + +#ifdef ENABLE_DDGI +void EditorApp::InitDDGIEntity() +{ + engine::World* pWorld = m_pSceneWorld->GetWorld(); + + engine::Entity ddgiEntity = pWorld->CreateEntity(); + m_pSceneWorld->SetDDGIEntity(ddgiEntity); + + auto& nameComponent = pWorld->CreateComponent(ddgiEntity); + nameComponent.SetName("DDGI"); + + pWorld->CreateComponent(ddgiEntity); +} +#endif + void EditorApp::InitRenderContext(engine::GraphicsBackend backend, void* hwnd) { CD_INFO("Init graphics backend : {}", nameof::nameof_enum(backend)); @@ -410,6 +419,10 @@ void EditorApp::InitEngineRenderers() pParticlerenderer->SetSceneWorld(m_pSceneWorld.get()); AddEngineRenderer(cd::MoveTemp(pParticlerenderer)); + auto pSkeletonRenderer = std::make_unique(m_pRenderContext->CreateView(), pSceneRenderTarget); + pSkeletonRenderer->SetSceneWorld(m_pSceneWorld.get()); + AddEngineRenderer(cd::MoveTemp(pSkeletonRenderer)); + #ifdef ENABLE_DDGI auto pDDGIRenderer = std::make_unique(m_pRenderContext->CreateView(), pSceneRenderTarget); pDDGIRenderer->SetSceneWorld(m_pSceneWorld.get()); diff --git a/Engine/Source/Editor/EditorApp.h b/Engine/Source/Editor/EditorApp.h index 2b907654..d28f2754 100644 --- a/Engine/Source/Editor/EditorApp.h +++ b/Engine/Source/Editor/EditorApp.h @@ -70,8 +70,12 @@ class EditorApp final : public engine::IApplication private: void InitEditorCameraEntity(); - void InitDDGIEntity(); void InitSkyEntity(); + void InitShaderVariantCollectionEntity(); + +#ifdef ENABLE_DDGI + void InitDDGIEntity(); +#endif bool m_bInitEditor = false; engine::EngineInitArgs m_initArgs; diff --git a/Engine/Source/Editor/Resources/ResourceBuilder.cpp b/Engine/Source/Editor/Resources/ResourceBuilder.cpp index 26e835b6..0099406a 100644 --- a/Engine/Source/Editor/Resources/ResourceBuilder.cpp +++ b/Engine/Source/Editor/Resources/ResourceBuilder.cpp @@ -150,7 +150,7 @@ bool ResourceBuilder::AddTask(Process process) return true; } -bool ResourceBuilder::AddShaderBuildTask(ShaderType shaderType, const char* pInputFilePath, const char* pOutputFilePath, const char* pUberOptions) +bool ResourceBuilder::AddShaderBuildTask(ShaderType shaderType, const char* pInputFilePath, const char* pOutputFilePath, const char* pShaderFeatures) { if (s_SkipStatus & static_cast(CheckFileStatus(pInputFilePath, pOutputFilePath))) { @@ -225,10 +225,10 @@ bool ResourceBuilder::AddShaderBuildTask(ShaderType shaderType, const char* pInp assert("Unknown shader compile profile."); } - if (pUberOptions && *pUberOptions != '\0') + if (pShaderFeatures && *pShaderFeatures != '\0') { commandArguments.push_back("--define"); - commandArguments.push_back(shaderLanguageDefine + ";" + pUberOptions); + commandArguments.push_back(shaderLanguageDefine + ";" + pShaderFeatures); } process.SetCommandArguments(cd::MoveTemp(commandArguments)); diff --git a/Engine/Source/Editor/Resources/ResourceBuilder.h b/Engine/Source/Editor/Resources/ResourceBuilder.h index cb3cfe1d..1aaeae1d 100644 --- a/Engine/Source/Editor/Resources/ResourceBuilder.h +++ b/Engine/Source/Editor/Resources/ResourceBuilder.h @@ -59,7 +59,7 @@ class ResourceBuilder final bool AddTask(Process process); bool AddIrradianceCubeMapBuildTask(const char* pInputFilePath, const char* pOutputFilePath); bool AddRadianceCubeMapBuildTask(const char* pInputFilePath, const char* pOutputFilePath); - bool AddShaderBuildTask(ShaderType shaderType, const char* pInputFilePath, const char* pOutputFilePath, const char* pUberOptions = nullptr); + bool AddShaderBuildTask(ShaderType shaderType, const char* pInputFilePath, const char* pOutputFilePath, const char* pShaderFeatures = nullptr); bool AddTextureBuildTask(cd::MaterialTextureType textureType, const char* pInputFilePath, const char* pOutputFilePath); void Update(bool doPrintLog = true); diff --git a/Engine/Source/Editor/Resources/ShaderBuilder.cpp b/Engine/Source/Editor/Resources/ShaderBuilder.cpp index 3ac83b25..5c7a8c25 100644 --- a/Engine/Source/Editor/Resources/ShaderBuilder.cpp +++ b/Engine/Source/Editor/Resources/ShaderBuilder.cpp @@ -12,20 +12,20 @@ void ShaderBuilder::BuildUberShader(engine::MaterialType* pMaterialType) { engine::ShaderSchema& shaderSchema = pMaterialType->GetShaderSchema(); - // No uber option support for VS now. + // No shader feature support for VS now. std::string outputVSFilePath = engine::Path::GetShaderOutputPath(shaderSchema.GetVertexShaderPath()); ResourceBuilder::Get().AddShaderBuildTask(ShaderType::Vertex, shaderSchema.GetVertexShaderPath(), outputVSFilePath.c_str()); - // Compile fragment shaders with uber options. - for (const auto& combine : shaderSchema.GetUberCombines()) + // Compile fragment shaders with shader features. + for (const auto& combine : shaderSchema.GetFeatureCombines()) { std::string outputFSFilePath = engine::Path::GetShaderOutputPath(shaderSchema.GetFragmentShaderPath(), combine); ResourceBuilder::Get().AddShaderBuildTask(ShaderType::Fragment, shaderSchema.GetFragmentShaderPath(), outputFSFilePath.c_str(), combine.c_str()); } - CD_ENGINE_INFO("Shader variant count of material type {0} : {1}", pMaterialType->GetMaterialName(), shaderSchema.GetUberCombines().size()); + CD_ENGINE_INFO("Shader variant count of material type {0} : {1}", pMaterialType->GetMaterialName(), shaderSchema.GetFeatureCombines().size()); } void ShaderBuilder::BuildNonUberShader(std::string folderPath) diff --git a/Engine/Source/Editor/UILayers/AssetBrowser.cpp b/Engine/Source/Editor/UILayers/AssetBrowser.cpp index 1ca52095..898b8c95 100644 --- a/Engine/Source/Editor/UILayers/AssetBrowser.cpp +++ b/Engine/Source/Editor/UILayers/AssetBrowser.cpp @@ -673,7 +673,7 @@ void AssetBrowser::UpdateAssetFileView() ImGui::SliderFloat(" ", &m_gridSize, 40.0f, 160.0f, " ", ImGuiSliderFlags_AlwaysClamp | ImGuiSliderFlags_Logarithmic); } -bool AssetBrowser::UpdateOptionDialog(const char* pTitle, bool& active, bool& importMesh, bool& importMaterial, bool& importTexture, bool& importCamera, bool& importLight) +bool AssetBrowser::UpdateOptionDialog(const char* pTitle, bool& active, bool& importMesh, bool& importMaterial, bool& importTexture, bool& importAnimation, bool& importCamera, bool& importLight) { if (!active) { @@ -715,6 +715,7 @@ bool AssetBrowser::UpdateOptionDialog(const char* pTitle, bool& active, bool& im ImGui::Separator(); if (isOtherOpen) { + ImGuiUtils::ImGuiBoolProperty("Animation", importAnimation); ImGuiUtils::ImGuiBoolProperty("Camera", importCamera); ImGuiUtils::ImGuiBoolProperty("Light", importLight); } @@ -908,26 +909,31 @@ void AssetBrowser::ImportModelFile(const char* pFilePath) if (0 == inputFileExtension.compare(".cdbin")) { cdtools::CDProducer cdProducer(pFilePath); - cdtools::Processor processor(&cdProducer, nullptr, pSceneDatabase); + cd::SceneDatabase newSceneDatabase; + cdtools::Processor processor(&cdProducer, nullptr, &newSceneDatabase); processor.Run(); + pSceneDatabase->Merge(cd::MoveTemp(newSceneDatabase)); } else { #ifdef ENABLE_GENERIC_PRODUCER cdtools::GenericProducer genericProducer(pFilePath); - genericProducer.SetSceneDatabaseIDs(pSceneDatabase->GetNodeCount(), pSceneDatabase->GetMeshCount(), - pSceneDatabase->GetMaterialCount(), pSceneDatabase->GetTextureCount(), pSceneDatabase->GetLightCount()); genericProducer.ActivateBoundingBoxService(); genericProducer.ActivateCleanUnusedService(); genericProducer.ActivateTangentsSpaceService(); genericProducer.ActivateTriangulateService(); genericProducer.ActivateSimpleAnimationService(); - genericProducer.ActivateFlattenHierarchyService(); + if (!m_importOptions.ImportAnimation) + { + genericProducer.ActivateFlattenHierarchyService(); + } - cdtools::Processor processor(&genericProducer, nullptr, pSceneDatabase); + cd::SceneDatabase newSceneDatabase; + cdtools::Processor processor(&genericProducer, nullptr, &newSceneDatabase); processor.SetDumpSceneDatabaseEnable(false); - processor.SetFlattenSceneDatabaseEnable(true); + //processor.SetFlattenSceneDatabaseEnable(true); processor.Run(); + pSceneDatabase->Merge(cd::MoveTemp(newSceneDatabase)); #else assert("Unable to import this file format."); #endif @@ -1146,7 +1152,7 @@ void AssetBrowser::Update() m_importOptions.Active = true; } if (UpdateOptionDialog("Import Options", m_importOptions.Active, m_importOptions.ImportMesh, m_importOptions.ImportMaterial, m_importOptions.ImportTexture, - m_importOptions.ImportCamera, m_importOptions.ImportLight)) + m_importOptions.ImportAnimation, m_importOptions.ImportCamera, m_importOptions.ImportLight)) { ImportAssetFile(m_pImportFileBrowser->GetSelected().string().c_str()); m_pImportFileBrowser->ClearSelected(); @@ -1159,7 +1165,7 @@ void AssetBrowser::Update() } if (UpdateOptionDialog("Export Options", m_exportOptions.Active, m_exportOptions.ExportMesh, m_exportOptions.ExportMaterial, m_exportOptions.ExportTexture, - m_exportOptions.ExportCamera, m_exportOptions.ExportLight)) + m_importOptions.ImportAnimation, m_exportOptions.ExportCamera, m_exportOptions.ExportLight)) { ExportAssetFile(m_pExportFileBrowser->GetSelected().string().c_str()); m_pExportFileBrowser->ClearSelected(); diff --git a/Engine/Source/Editor/UILayers/AssetBrowser.h b/Engine/Source/Editor/UILayers/AssetBrowser.h index 0a2e1f2a..ad18a10c 100644 --- a/Engine/Source/Editor/UILayers/AssetBrowser.h +++ b/Engine/Source/Editor/UILayers/AssetBrowser.h @@ -72,6 +72,7 @@ struct AssetImportOptions bool ImportMaterial = true; bool ImportMesh = true; bool ImportTexture = true; + bool ImportAnimation = false; }; struct AssetExportOptions @@ -129,7 +130,7 @@ class AssetBrowser : public engine::ImGuiBaseLayer void UpdateAssetFolderTree(); void UpdateAssetFileView(); - bool UpdateOptionDialog(const char* pTitle, bool& active, bool& importMesh, bool& importMaterial, bool& importTexture, bool& importCamera, bool& importLight); + bool UpdateOptionDialog(const char* pTitle, bool& active, bool& importMesh, bool& importMaterial, bool& importTexture, bool& importAnimation, bool& importCamera, bool& importLight); private: AssetImportOptions m_importOptions; diff --git a/Engine/Source/Editor/UILayers/EntityList.cpp b/Engine/Source/Editor/UILayers/EntityList.cpp index 1d13c378..318c0a21 100644 --- a/Engine/Source/Editor/UILayers/EntityList.cpp +++ b/Engine/Source/Editor/UILayers/EntityList.cpp @@ -346,6 +346,16 @@ void EntityList::DrawEntity(engine::SceneWorld* pSceneWorld, engine::Entity enti } } } + else + { + if (engine::TransformComponent* pTransform = pSceneWorld->GetTransformComponent(entity)) + { + if (m_pCameraController) + { + m_pCameraController->CameraFocus(pTransform->GetTransform().GetTranslation()); + } + } + } } } diff --git a/Engine/Source/Editor/UILayers/Inspector.cpp b/Engine/Source/Editor/UILayers/Inspector.cpp index 8a21c347..3e0c6f48 100644 --- a/Engine/Source/Editor/UILayers/Inspector.cpp +++ b/Engine/Source/Editor/UILayers/Inspector.cpp @@ -146,12 +146,10 @@ void UpdateComponentWidget(engine::SceneWorld* pScene ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2, 2)); ImGui::Separator(); - std::string uvOffset = std::string(title) + std::string(" UVOffset"); - std::string uvScale = std::string(title) + std::string(" UVScale"); if (isOpen) { - ImGuiUtils::ImGuiVectorProperty(uvOffset.c_str(), pTextureInfo->GetUVOffset()); - ImGuiUtils::ImGuiVectorProperty(uvScale.c_str(), pTextureInfo->GetUVScale()); + ImGuiUtils::ImGuiVectorProperty("UVOffset", pTextureInfo->GetUVOffset()); + ImGuiUtils::ImGuiVectorProperty("UVScale", pTextureInfo->GetUVScale()); } ImGui::Separator(); @@ -171,19 +169,19 @@ void UpdateComponentWidget(engine::SceneWorld* pScene ImGuiUtils::ImGuiStringProperty("Fragment Shader", pMaterialComponent->GetFragmentShaderName()); ImGui::Separator(); - std::vector activeUberOptions; - for (const auto& uber : pMaterialComponent->GetUberShaderOptions()) + std::vector activeShaderFeatures; + for (const auto& feature : pMaterialComponent->GetShaderFeatures()) { - activeUberOptions.emplace_back(nameof::nameof_enum(uber).data()); + activeShaderFeatures.emplace_back(nameof::nameof_enum(feature).data()); } - if (!activeUberOptions.empty()) + if (!activeShaderFeatures.empty()) { - if (ImGui::BeginCombo("##combo", "Active uber options")) + if (ImGui::BeginCombo("##combo", "Active shader features")) { - for (size_t index = 0; index < activeUberOptions.size(); ++index) + for (size_t index = 0; index < activeShaderFeatures.size(); ++index) { - ImGui::Selectable(activeUberOptions[index], false); + ImGui::Selectable(activeShaderFeatures[index], false); } ImGui::EndCombo(); } @@ -513,6 +511,28 @@ void UpdateComponentWidget(engine::SceneWorld* ImGui::PopStyleVar(); } +template<> +void UpdateComponentWidget(engine::SceneWorld* pSceneWorld, engine::Entity entity) +{ + auto* pShaderVariantCollectionsComponent = pSceneWorld->GetShaderVariantCollectionsComponent(entity); + if (!pShaderVariantCollectionsComponent) + { + return; + } + + bool isOpen = ImGui::CollapsingHeader("Shader Variant Collections Component", ImGuiTreeNodeFlags_AllowItemOverlap | ImGuiTreeNodeFlags_DefaultOpen); + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2, 2)); + ImGui::Separator(); + + if (isOpen) + { + + } + + ImGui::Separator(); + ImGui::PopStyleVar(); +} + } namespace editor diff --git a/Engine/Source/Editor/UILayers/SkeletonView.cpp b/Engine/Source/Editor/UILayers/SkeletonView.cpp new file mode 100644 index 00000000..fc488cf6 --- /dev/null +++ b/Engine/Source/Editor/UILayers/SkeletonView.cpp @@ -0,0 +1,75 @@ +#include "SkeletonView.h" + +#include "ECWorld/SceneWorld.h" +#include +#include + +namespace editor +{ + +SkeletonView::~SkeletonView() +{ + +} +void SkeletonView::Init() +{ + +} + +void SkeletonView::DrawBone(cd::SceneDatabase* pSceneDatabase, const cd::Bone& Bone) +{ + if (Bone.GetChildIDs().empty()) + { + ImGui::Selectable(Bone.GetName()); + ImGui::SameLine(); + ImGui::Text(reinterpret_cast(ICON_MDI_BONE)); + return; + } + + bool isOpen = ImGui::TreeNode(Bone.GetName()); + ImGui::SameLine(); + ImGui::Text(reinterpret_cast(ICON_MDI_BONE)); + if(isOpen) + { + for (auto& child : Bone.GetChildIDs()) + { + const cd::Bone& bone = pSceneDatabase->GetBone(child.Data()); + DrawBone(pSceneDatabase, bone); + } + + ImGui::TreePop(); + } +} + +void SkeletonView::DrawSkeleton(engine::SceneWorld* pSceneWorld) +{ + cd::SceneDatabase* pSceneDatabase = pSceneWorld->GetSceneDatabase(); + if (0 == pSceneDatabase->GetBoneCount()) + { + return; + } + const cd::Bone& rootBone = pSceneDatabase->GetBone(0); + DrawBone(pSceneDatabase, rootBone); +} + +void SkeletonView::Update() +{ + constexpr auto flags = ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse; + ImGui::Begin(GetName(), &m_isEnable, flags); + engine::SceneWorld* pSceneWorld = GetSceneWorld(); + engine::Entity selectedEntity = pSceneWorld->GetSelectedEntity(); + if (engine::INVALID_ENTITY == selectedEntity) + { + ImGui::End(); + return; + } + engine::AnimationComponent* pAnimationConponent = pSceneWorld->GetAnimationComponent(selectedEntity); + if (pAnimationConponent) + { + DrawSkeleton(pSceneWorld); + } + + ImGui::End(); +} + +} \ No newline at end of file diff --git a/Engine/Source/Editor/UILayers/SkeletonView.h b/Engine/Source/Editor/UILayers/SkeletonView.h new file mode 100644 index 00000000..21252484 --- /dev/null +++ b/Engine/Source/Editor/UILayers/SkeletonView.h @@ -0,0 +1,23 @@ +#include "ImGui/ImGuiBaseLayer.h" + +#include "Scene/Bone.h" +#include "Scene/SceneDatabase.h" + +namespace editor +{ + +class SkeletonView : public engine::ImGuiBaseLayer +{ +public: + using ImGuiBaseLayer::ImGuiBaseLayer; + virtual ~SkeletonView(); + + virtual void Init() override; + virtual void Update() override; + + void DrawBone(cd::SceneDatabase* pSceneDatabase,const cd::Bone& Bone); + void DrawSkeleton(engine::SceneWorld* pSceneWorld); +}; + +} + diff --git a/Engine/Source/Runtime/Display/CameraController.cpp b/Engine/Source/Runtime/Display/CameraController.cpp index 97b3f983..933b32be 100644 --- a/Engine/Source/Runtime/Display/CameraController.cpp +++ b/Engine/Source/Runtime/Display/CameraController.cpp @@ -365,10 +365,21 @@ void CameraController::CameraFocus(const cd::AABB& aabb) m_movementSpeed = aabb.Size().Length() * 1.5f; } +void CameraController::CameraFocus(const cd::Vec3f& position) +{ + m_isMoving = true; + m_eyeDestination = position - m_lookAt * m_distanceFromLookAt; +} + void CameraController::Moving() { if (m_isMoving) { + if (cd::Math::IsSmallThan((m_eye - m_eyeDestination).Length(), 0.01f)) + { + m_isMoving = false; + return; + } cd::Direction eyeMove = (m_eye - m_eyeDestination).Normalize(); float stepDistance = (m_eye - m_eyeDestination).Length() / 5.0f; m_eye = m_eye - eyeMove * stepDistance; @@ -376,10 +387,6 @@ void CameraController::Moving() SynchronizeTrackingCamera(); ControllerToCamera(); - if (cd::Math::IsSmallThan((m_eye - m_eyeDestination).Length(), 0.01f)) - { - m_isMoving = false; - } } } diff --git a/Engine/Source/Runtime/Display/CameraController.h b/Engine/Source/Runtime/Display/CameraController.h index 1c0ae766..fdca2e55 100644 --- a/Engine/Source/Runtime/Display/CameraController.h +++ b/Engine/Source/Runtime/Display/CameraController.h @@ -55,6 +55,7 @@ class CameraController final // Double Click entity,camera will focus void CameraFocus(const cd::AABB& aabb); + void CameraFocus(const cd::Vec3f& position); // Implement the effect of a translation animation. void Moving(); @@ -94,9 +95,9 @@ class CameraController final float m_mouseScroll = 0.0f; cd::Vec3f m_lookAtPoint = cd::Vec3f::Zero(); - cd::Vec3f m_lookAt; - cd::Vec3f m_up; - cd::Vec3f m_eye; + cd::Vec3f m_lookAt = cd::Vec3f(0.0f, 1.0f, 0.0f); + cd::Vec3f m_up = cd::Vec3f(0.0f, 0.0f, 1.0f); + cd::Vec3f m_eye = cd::Vec3f::Zero(); cd::Vec3f m_eyeDestination; // This is for focusing animation cd::Vec3f m_lookAtDestination; diff --git a/Engine/Source/Runtime/ECWorld/AllComponentsHeader.h b/Engine/Source/Runtime/ECWorld/AllComponentsHeader.h index e94a9427..7ba4a552 100644 --- a/Engine/Source/Runtime/ECWorld/AllComponentsHeader.h +++ b/Engine/Source/Runtime/ECWorld/AllComponentsHeader.h @@ -10,6 +10,7 @@ #include "ECWorld/LightComponent.h" #include "ECWorld/MaterialComponent.h" #include "ECWorld/NameComponent.h" +#include "ECWorld/ShaderVariantCollectionsComponent.h" #include "ECWorld/SkyComponent.h" #include "ECWorld/StaticMeshComponent.h" #include "ECWorld/TerrainComponent.h" diff --git a/Engine/Source/Runtime/ECWorld/MaterialComponent.cpp b/Engine/Source/Runtime/ECWorld/MaterialComponent.cpp index 5ea46869..065dfea7 100644 --- a/Engine/Source/Runtime/ECWorld/MaterialComponent.cpp +++ b/Engine/Source/Runtime/ECWorld/MaterialComponent.cpp @@ -95,15 +95,15 @@ uint64_t GetBGFXTextureFlag(cd::MaterialTextureType textureType, cd::TextureMapM return textureFlag; } -const std::unordered_map skyTypeToUber +const std::unordered_map skyTypeToShaderFeature { - { engine::SkyType::SkyBox, engine::Uber::IBL}, - { engine::SkyType::AtmosphericScattering, engine::Uber::ATM }, + { engine::SkyType::SkyBox, engine::ShaderFeature::IBL}, + { engine::SkyType::AtmosphericScattering, engine::ShaderFeature::ATM }, }; CD_FORCEINLINE bool IsSkyTypeValid(engine::SkyType type) { - return skyTypeToUber.find(type) != skyTypeToUber.end(); + return skyTypeToShaderFeature.find(type) != skyTypeToShaderFeature.end(); } } @@ -138,19 +138,19 @@ const MaterialComponent::TextureInfo* MaterialComponent::GetTextureInfo(cd::Mate return &itTextureInfo->second; } -void MaterialComponent::ActiveUberShaderOption(engine::Uber option) +void MaterialComponent::ActiveShaderFeature(engine::ShaderFeature feature) { - m_uberShaderOptions.insert(option); + m_shaderFeatures.insert(feature); } -void MaterialComponent::DeactiveUberShaderOption(engine::Uber option) +void MaterialComponent::DeactiveShaderFeature(engine::ShaderFeature feature) { - m_uberShaderOptions.erase(option); + m_shaderFeatures.erase(feature); } void MaterialComponent::MatchUberShaderCrc() { - m_uberShaderCrc = m_pMaterialType->GetShaderSchema().GetOptionsCrc(m_uberShaderOptions); + m_uberShaderCrc = m_pMaterialType->GetShaderSchema().GetFeaturesCrc(m_shaderFeatures); } uint16_t MaterialComponent::GetShadreProgram() const @@ -162,7 +162,7 @@ void MaterialComponent::Reset() { m_pMaterialData = nullptr; m_pMaterialType = nullptr; - m_uberShaderOptions.clear(); + m_shaderFeatures.clear(); m_uberShaderCrc = ShaderSchema::DefaultUberShaderCrc; m_name.clear(); m_albedoColor = cd::Vec3f::One(); @@ -264,7 +264,7 @@ void MaterialComponent::Build() void MaterialComponent::SetSkyType(SkyType crtType) { - // SkyType::None is a special case which is not a uber option but means deactive Uber::IBL and Uber::ATM. + // SkyType::None is a special case which is not a shader feature but means deactive ShaderFeature::IBL and ShaderFeature::ATM. if (SkyType::Count == crtType || m_skyType == crtType) { @@ -273,15 +273,15 @@ void MaterialComponent::SetSkyType(SkyType crtType) if (IsSkyTypeValid(m_skyType)) { - m_uberShaderOptions.erase(skyTypeToUber.at(m_skyType)); + m_shaderFeatures.erase(skyTypeToShaderFeature.at(m_skyType)); } if (IsSkyTypeValid(crtType)) { - m_uberShaderOptions.insert(skyTypeToUber.at(crtType)); + m_shaderFeatures.insert(skyTypeToShaderFeature.at(crtType)); } - m_uberShaderCrc = m_pMaterialType->GetShaderSchema().GetOptionsCrc(m_uberShaderOptions); + m_uberShaderCrc = m_pMaterialType->GetShaderSchema().GetFeaturesCrc(m_shaderFeatures); m_skyType = crtType; } diff --git a/Engine/Source/Runtime/ECWorld/MaterialComponent.h b/Engine/Source/Runtime/ECWorld/MaterialComponent.h index 0bcc7156..0d63690f 100644 --- a/Engine/Source/Runtime/ECWorld/MaterialComponent.h +++ b/Engine/Source/Runtime/ECWorld/MaterialComponent.h @@ -93,14 +93,14 @@ class MaterialComponent final const std::string& GetName() const { return m_name; } // Uber shader data. - void ActiveUberShaderOption(engine::Uber option); - void DeactiveUberShaderOption(engine::Uber option); + void ActiveShaderFeature(ShaderFeature feature); + void DeactiveShaderFeature(ShaderFeature feature); void MatchUberShaderCrc(); uint16_t GetShadreProgram() const; - void SetUberShaderOptions(std::unordered_set options) { m_uberShaderOptions = cd::MoveTemp(m_uberShaderOptions); } - std::unordered_set& GetUberShaderOptions() { return m_uberShaderOptions; } - const std::unordered_set& GetUberShaderOptions() const { return m_uberShaderOptions; } + void SetShaderFeatures(std::set options) { m_shaderFeatures = cd::MoveTemp(m_shaderFeatures); } + std::set& GetShaderFeatures() { return m_shaderFeatures; } + const std::set& GetShaderFeatures() const { return m_shaderFeatures; } std::string GetVertexShaderName() const; std::string GetFragmentShaderName() const; @@ -152,7 +152,7 @@ class MaterialComponent final // Input const cd::Material* m_pMaterialData = nullptr; const engine::MaterialType* m_pMaterialType = nullptr; - std::unordered_set m_uberShaderOptions; + std::set m_shaderFeatures; StringCrc m_uberShaderCrc; std::string m_name; diff --git a/Engine/Source/Runtime/ECWorld/SceneWorld.cpp b/Engine/Source/Runtime/ECWorld/SceneWorld.cpp index 92dc251b..a7f17d4d 100644 --- a/Engine/Source/Runtime/ECWorld/SceneWorld.cpp +++ b/Engine/Source/Runtime/ECWorld/SceneWorld.cpp @@ -32,12 +32,13 @@ SceneWorld::SceneWorld() m_pLightComponentStorage = m_pWorld->Register(); m_pMaterialComponentStorage = m_pWorld->Register(); m_pNameComponentStorage = m_pWorld->Register(); + m_pShaderVariantCollectionsComponentStorage = m_pWorld->Register(); m_pSkyComponentStorage = m_pWorld->Register(); m_pStaticMeshComponentStorage = m_pWorld->Register(); m_pTerrainComponentStorage = m_pWorld->Register(); m_pTransformComponentStorage = m_pWorld->Register(); m_pParticleEmitterComponentStorage = m_pWorld->Register(); - + #ifdef ENABLE_DDGI CreateDDGIMaterialType(); #endif @@ -49,17 +50,17 @@ void SceneWorld::CreatePBRMaterialType(bool isAtmosphericScatteringEnable) m_pPBRMaterialType->SetMaterialName("CD_PBR"); ShaderSchema shaderSchema(Path::GetBuiltinShaderInputPath("shaders/vs_PBR"), Path::GetBuiltinShaderInputPath("shaders/fs_PBR")); - shaderSchema.AddUberOption(Uber::ALBEDO_MAP); - shaderSchema.AddUberOption(Uber::NORMAL_MAP); - shaderSchema.AddUberOption(Uber::ORM_MAP); - shaderSchema.AddUberOption(Uber::EMISSIVE_MAP); - shaderSchema.AddUberOption(Uber::IBL); + shaderSchema.AddFeatureSet({ ShaderFeature::ALBEDO_MAP }); + shaderSchema.AddFeatureSet({ ShaderFeature::NORMAL_MAP }); + shaderSchema.AddFeatureSet({ ShaderFeature::ORM_MAP }); + shaderSchema.AddFeatureSet({ ShaderFeature::EMISSIVE_MAP }); + std::set envFeatures = { ShaderFeature::IBL }; if (isAtmosphericScatteringEnable) { // TODO : Compile atm shader in GL/VK mode correctly. - shaderSchema.AddUberOption(Uber::ATM); - shaderSchema.SetConflictOptions(Uber::ATM, Uber::IBL); + envFeatures.insert(ShaderFeature::ATM); } + shaderSchema.AddFeatureSet(cd::MoveTemp(envFeatures)); shaderSchema.Build(); m_pPBRMaterialType->SetShaderSchema(cd::MoveTemp(shaderSchema)); @@ -103,10 +104,10 @@ void SceneWorld::CreateDDGIMaterialType() m_pDDGIMaterialType->SetMaterialName("CD_DDGI"); ShaderSchema shaderSchema(Path::GetBuiltinShaderInputPath("shaders/vs_DDGI"), Path::GetBuiltinShaderInputPath("shaders/fs_DDGI")); - shaderSchema.AddUberOption(Uber::ALBEDO_MAP); - shaderSchema.AddUberOption(Uber::NORMAL_MAP); - shaderSchema.AddUberOption(Uber::ORM_MAP); - shaderSchema.AddUberOption(Uber::EMISSIVE_MAP); + shaderSchema.AddFeatureSet({ ShaderFeature::ALBEDO_MAP }); + shaderSchema.AddFeatureSet({ ShaderFeature::NORMAL_MAP }); + shaderSchema.AddFeatureSet({ ShaderFeature::ORM_MAP }); + shaderSchema.AddFeatureSet({ ShaderFeature::EMISSIVE_MAP }); shaderSchema.Build(); m_pDDGIMaterialType->SetShaderSchema(cd::MoveTemp(shaderSchema)); @@ -169,6 +170,12 @@ void SceneWorld::SetSkyEntity(engine::Entity entity) m_skyEntity = entity; } +void SceneWorld::SetShaderVariantCollectionEntity(engine::Entity entity) +{ + CD_TRACE("Setup Shader Variant Collection entity : {0}", entity); + m_shaderVariantCollectionEntity = entity; +} + void SceneWorld::AddCameraToSceneDatabase(engine::Entity entity) { engine::CameraComponent* pCameraComponent = GetCameraComponent(entity); diff --git a/Engine/Source/Runtime/ECWorld/SceneWorld.h b/Engine/Source/Runtime/ECWorld/SceneWorld.h index 624258f1..7863664b 100644 --- a/Engine/Source/Runtime/ECWorld/SceneWorld.h +++ b/Engine/Source/Runtime/ECWorld/SceneWorld.h @@ -37,11 +37,15 @@ class SceneWorld DEFINE_COMPONENT_STORAGE_WITH_APIS(Light); DEFINE_COMPONENT_STORAGE_WITH_APIS(Material); DEFINE_COMPONENT_STORAGE_WITH_APIS(Name); + DEFINE_COMPONENT_STORAGE_WITH_APIS(ShaderVariantCollections); DEFINE_COMPONENT_STORAGE_WITH_APIS(Sky); DEFINE_COMPONENT_STORAGE_WITH_APIS(StaticMesh); + DEFINE_COMPONENT_STORAGE_WITH_APIS(Particle); DEFINE_COMPONENT_STORAGE_WITH_APIS(Terrain); DEFINE_COMPONENT_STORAGE_WITH_APIS(Transform); DEFINE_COMPONENT_STORAGE_WITH_APIS(ParticleEmitter); + DEFINE_COMPONENT_STORAGE_WITH_APIS(Terrain); + DEFINE_COMPONENT_STORAGE_WITH_APIS(Transform); public: SceneWorld(); @@ -69,6 +73,9 @@ class SceneWorld void SetSkyEntity(engine::Entity entity); CD_FORCEINLINE engine::Entity GetSkyEntity() const { return m_skyEntity; } + void SetShaderVariantCollectionEntity(engine::Entity entity); + CD_FORCEINLINE engine::Entity GetShaderVariantCollectionEntity() const { return m_shaderVariantCollectionEntity; } + void DeleteEntity(engine::Entity entity) { if (entity == m_mainCameraEntity) @@ -93,6 +100,7 @@ class SceneWorld DeleteLightComponent(entity); DeleteMaterialComponent(entity); DeleteNameComponent(entity); + DeleteShaderVariantCollectionsComponent(entity); DeleteSkyComponent(entity); DeleteStaticMeshComponent(entity); DeleteTerrainComponent(entity); @@ -136,10 +144,14 @@ class SceneWorld // TODO : wrap them into another class? engine::Entity m_selectedEntity = engine::INVALID_ENTITY; engine::Entity m_mainCameraEntity = engine::INVALID_ENTITY; + + // TODO : wrap them to project data. + engine::Entity m_skyEntity = engine::INVALID_ENTITY; + engine::Entity m_shaderVariantCollectionEntity = engine::INVALID_ENTITY; + #ifdef ENABLE_DDGI engine::Entity m_ddgiEntity = engine::INVALID_ENTITY; #endif - engine::Entity m_skyEntity = engine::INVALID_ENTITY; }; } \ No newline at end of file diff --git a/Engine/Source/Runtime/ECWorld/ShaderVariantCollectionsComponent.cpp b/Engine/Source/Runtime/ECWorld/ShaderVariantCollectionsComponent.cpp new file mode 100644 index 00000000..c5c90905 --- /dev/null +++ b/Engine/Source/Runtime/ECWorld/ShaderVariantCollectionsComponent.cpp @@ -0,0 +1,8 @@ +#include "ShaderVariantCollectionsComponent.h" + +namespace engine +{ + + + +} \ No newline at end of file diff --git a/Engine/Source/Runtime/ECWorld/ShaderVariantCollectionsComponent.h b/Engine/Source/Runtime/ECWorld/ShaderVariantCollectionsComponent.h new file mode 100644 index 00000000..c90cdc4e --- /dev/null +++ b/Engine/Source/Runtime/ECWorld/ShaderVariantCollectionsComponent.h @@ -0,0 +1,29 @@ +#pragma once + +#include "Base/Template.h" +#include "Core/StringCrc.h" + +namespace engine +{ + +class ShaderVariantCollectionsComponent final +{ +public: + static constexpr StringCrc GetClassName() + { + constexpr StringCrc className("ShaderVariantCollectionsComponent"); + return className; + } + + ShaderVariantCollectionsComponent() = default; + ShaderVariantCollectionsComponent(const ShaderVariantCollectionsComponent&) = default; + ShaderVariantCollectionsComponent& operator=(const ShaderVariantCollectionsComponent&) = default; + ShaderVariantCollectionsComponent(ShaderVariantCollectionsComponent&&) = default; + ShaderVariantCollectionsComponent& operator=(ShaderVariantCollectionsComponent&&) = default; + ~ShaderVariantCollectionsComponent() = default; + +private: + +}; + +} \ No newline at end of file diff --git a/Engine/Source/Runtime/ECWorld/SkinMeshComponent.cpp b/Engine/Source/Runtime/ECWorld/SkinMeshComponent.cpp new file mode 100644 index 00000000..da1fdbf5 --- /dev/null +++ b/Engine/Source/Runtime/ECWorld/SkinMeshComponent.cpp @@ -0,0 +1,19 @@ +#include "SkinMeshComponent.h" +#include "Rendering/Utility/VertexLayoutUtility.h" +#include "Scene/Mesh.h" +#include "Scene/VertexFormat.h" + +namespace engine +{ + +void SkinMeshComponent::Reset() +{ + +} + +void SkinMeshComponent::Build() +{ + +} + +} \ No newline at end of file diff --git a/Engine/Source/Runtime/ECWorld/SkinMeshComponent.h b/Engine/Source/Runtime/ECWorld/SkinMeshComponent.h new file mode 100644 index 00000000..67e4f7ed --- /dev/null +++ b/Engine/Source/Runtime/ECWorld/SkinMeshComponent.h @@ -0,0 +1,48 @@ +#pragma once + +#include "Core/StringCrc.h" +#include "ECWorld/Entity.h" +#include "Scene/Bone.h" + +namespace cd +{ + +class Bone; + +} + +namespace engine +{ + +class SkinMeshComponent final +{ +public: + static constexpr StringCrc GetClassName() + { + constexpr StringCrc className("SkinMeshComponent"); + return className; + } + +public: + SkinMeshComponent() = default; + SkinMeshComponent(const SkinMeshComponent&) = default; + SkinMeshComponent& operator=(const SkinMeshComponent&) = default; + SkinMeshComponent(SkinMeshComponent&&) = default; + SkinMeshComponent& operator=(SkinMeshComponent&&) = default; + ~SkinMeshComponent() = default; + + uint16_t GetBonePositionBuffer() const { return m_boneVBH; } + uint16_t GetIndexBuffer() const { return m_boneIBH; } + + void Reset(); + void Build(); + +private: + //output + std::vector m_vertexBuffer; + std::vector m_indexBuffer; + uint16_t m_boneVBH = UINT16_MAX; + uint16_t m_boneIBH = UINT16_MAX; +}; + +} \ No newline at end of file diff --git a/Engine/Source/Runtime/ECWorld/TransformComponent.cpp b/Engine/Source/Runtime/ECWorld/TransformComponent.cpp index 1a661120..1cc4d05e 100644 --- a/Engine/Source/Runtime/ECWorld/TransformComponent.cpp +++ b/Engine/Source/Runtime/ECWorld/TransformComponent.cpp @@ -19,7 +19,7 @@ void TransformComponent::Build() } } #ifdef EDITOR_MODE -bool TransformComponent::m_doUseUniformScale = false; +bool TransformComponent::m_doUseUniformScale = true; #endif } \ No newline at end of file diff --git a/Engine/Source/Runtime/ImGui/ImGuiContextInstance.cpp b/Engine/Source/Runtime/ImGui/ImGuiContextInstance.cpp index 1136cc6e..65610268 100644 --- a/Engine/Source/Runtime/ImGui/ImGuiContextInstance.cpp +++ b/Engine/Source/Runtime/ImGui/ImGuiContextInstance.cpp @@ -298,7 +298,7 @@ void ImGuiContextInstance::BeginDockSpace() ImGui::DockBuilderDockWindow("EntityList", dockSpaceUpLeftLeft); ImGui::DockBuilderDockWindow("GameView", dockSpaceLeftLeft); ImGui::DockBuilderDockWindow("SceneView", dockSpaceLeftRight); - ImGui::DockBuilderDockWindow("Terrain Editor", dockSpaceUpRight); + ImGui::DockBuilderDockWindow("SkeletonView", dockSpaceUpRight); ImGui::DockBuilderDockWindow("Inspector", dockSpaceUpRight); ImGui::DockBuilderDockWindow("AssetBrowser", dockSpaceBottomLeft); ImGui::DockBuilderDockWindow("OutputLog", dockSpaceBottomRight); diff --git a/Engine/Source/Runtime/ImGui/ImGuiUtils.hpp b/Engine/Source/Runtime/ImGui/ImGuiUtils.hpp index c74ab2dd..6004cce0 100644 --- a/Engine/Source/Runtime/ImGui/ImGuiUtils.hpp +++ b/Engine/Source/Runtime/ImGui/ImGuiUtils.hpp @@ -243,7 +243,7 @@ static void ColorPickerProperty(const char* Name, cd::Vec3f& veccolor) ImGui::SameLine(); ImGui::NextColumn(); ImGui::PushID(Name); - if (ImGui::Button("Change")) + if (ImGui::Button("...")) { showMap[Name] = true; } diff --git a/Engine/Source/Runtime/Material/ShaderSchema.cpp b/Engine/Source/Runtime/Material/ShaderSchema.cpp index d871249e..0cac35a1 100644 --- a/Engine/Source/Runtime/Material/ShaderSchema.cpp +++ b/Engine/Source/Runtime/Material/ShaderSchema.cpp @@ -13,7 +13,7 @@ namespace engine namespace { -constexpr const char* UberNames[] = +constexpr const char* ShaderFeatureNames[] = { "", // Use empty string to represent default shader option in the name so we can reuse non-uber built shader. "ALBEDOMAP;", @@ -25,12 +25,12 @@ constexpr const char* UberNames[] = "AREALLIGHT;", }; -static_assert(static_cast(Uber::COUNT) == sizeof(UberNames) / sizeof(char*), - "Uber and names mismatch."); +static_assert(static_cast(ShaderFeature::COUNT) == sizeof(ShaderFeatureNames) / sizeof(char*), + "Shader features and names mismatch."); -constexpr const char* GetUberName(Uber uber) +CD_FORCEINLINE constexpr const char* GetFeatureName(ShaderFeature feature) { - return UberNames[static_cast(uber)]; + return ShaderFeatureNames[static_cast(feature)]; } } @@ -43,86 +43,80 @@ ShaderSchema::ShaderSchema(std::string vsPath, std::string fsPath) m_isDirty = false; } -void ShaderSchema::AddUberOption(Uber uberOption) +void ShaderSchema::AddFeatureSet(ShaderFeatureSet featureSet) { - if (std::find(m_uberOptions.begin(), m_uberOptions.end(), uberOption) != m_uberOptions.end()) + for (const auto& existingFeatureSet : m_shaderFeatureSets) { - CD_ENGINE_TRACE("Uber option {0} already has been registered!", GetUberName(uberOption)); - return; - } - - m_isDirty = true; - m_uberOptions.emplace_back(uberOption); -} - -void ShaderSchema::SetConflictOptions(Uber a, Uber b) -{ - const auto& range = m_conflictOptions.equal_range(GetUberName(a)); - for (auto conflict = range.first; conflict != range.second; ++conflict) - { - if (conflict->second == GetUberName(b)) + for (const auto& newFeature : featureSet) { - CD_ENGINE_TRACE("Conflict uber option combine ({0}, {1}) are already exist.", GetUberName(a), GetUberName(b)); - return; + if (existingFeatureSet.find(newFeature) != existingFeatureSet.end()) + { + CD_ENGINE_WARN("Shader feature {0} repetitive, skip current feature set adding!", GetFeatureName(newFeature)); + return; + } } } m_isDirty = true; - m_conflictOptions.emplace(GetUberName(a), GetUberName(b)); - m_conflictOptions.emplace(GetUberName(b), GetUberName(a)); + m_shaderFeatureSets.emplace_back(cd::MoveTemp(featureSet)); } void ShaderSchema::Build() { if (!m_isDirty) { - CD_ENGINE_TRACE("Uber shader options have no changes since the last build."); + CD_ENGINE_TRACE("Shader features have no changes since the last build."); return; } CleanBuild(); m_isDirty = false; - for(auto itOption = m_uberOptions.begin(); itOption != m_uberOptions.end(); ++itOption) + for (const auto& featureSet : m_shaderFeatureSets) { - std::string newOption = GetUberName(*itOption); - std::vector newOptions = { newOption }; - const auto& conflictRange = m_conflictOptions.equal_range(newOption); - - for(const auto& cobine : m_uberCombines) + for (const auto& feature : featureSet) { - bool isConflict = false; - for (auto conflict = conflictRange.first; conflict != conflictRange.second; ++conflict) + std::string newFeatureName = GetFeatureName(feature); + std::vector newFeatureCombines = { newFeatureName }; + + for (const auto& combine : m_featureCombines) { - if (cobine.find(conflict->second) != std::string::npos) + // Skip combination which has features in same set. + bool skip = false; + for (const auto& conflict : featureSet) + { + if (conflict == feature) + { + continue; + } + if (combine.find(GetFeatureName(conflict)) != std::string::npos) + { + skip = true; + break; + } + } + if (!skip) { - // Skip conflict uber option combine. - isConflict = true; - break; + newFeatureCombines.emplace_back(combine + newFeatureName); } } - if (!isConflict) + m_featureCombines.insert(m_featureCombines.end(), newFeatureCombines.begin(), newFeatureCombines.end()); + for (const auto& combine : newFeatureCombines) { - newOptions.emplace_back(cobine + newOption); + assert(!IsFeaturesValid(StringCrc(combine))); + m_compiledProgramHandles[StringCrc(combine).Value()] = InvalidProgramHandle; } } - m_uberCombines.insert(m_uberCombines.end(), newOptions.begin(), newOptions.end()); - - for (const auto& newOpt : newOptions) - { - assert(!IsUberOptionsValid(StringCrc(newOpt))); - m_compiledProgramHandles[StringCrc(newOpt).Value()] = InvalidProgramHandle; - } } // ShaderSchema also handle non-uber case. - m_uberCombines.emplace_back(""); + m_featureCombines.emplace_back(""); m_compiledProgramHandles[DefaultUberShaderCrc.Value()] = InvalidProgramHandle; } void ShaderSchema::CleanBuild() { - m_uberCombines.clear(); + m_featureCombines.clear(); m_compiledProgramHandles.clear(); m_isDirty = true; } @@ -132,23 +126,22 @@ void ShaderSchema::CleanAll() CleanBuild(); m_isDirty = false; - m_uberOptions.clear(); - m_conflictOptions.clear(); + m_shaderFeatureSets.clear(); } -void ShaderSchema::SetCompiledProgram(StringCrc uberOption, uint16_t programHandle) +void ShaderSchema::SetCompiledProgram(StringCrc shaderFeaturesCrc, uint16_t programHandle) { - assert(IsUberOptionsValid(uberOption)); - m_compiledProgramHandles[uberOption.Value()] = programHandle; + assert(IsFeaturesValid(shaderFeaturesCrc)); + m_compiledProgramHandles[shaderFeaturesCrc.Value()] = programHandle; } -uint16_t ShaderSchema::GetCompiledProgram(StringCrc uberOption) const +uint16_t ShaderSchema::GetCompiledProgram(StringCrc shaderFeaturesCrc) const { - auto itProgram = m_compiledProgramHandles.find(uberOption.Value()); + auto itProgram = m_compiledProgramHandles.find(shaderFeaturesCrc.Value()); if (itProgram == m_compiledProgramHandles.end()) { - CD_ENGINE_ERROR("Unregistered uber shader options!"); + CD_ENGINE_ERROR("Unregistered shader features!"); return InvalidProgramHandle; } @@ -156,39 +149,43 @@ uint16_t ShaderSchema::GetCompiledProgram(StringCrc uberOption) const if (programHandle == InvalidProgramHandle) { - CD_ENGINE_ERROR("Uncompiled uber shader options!"); + CD_ENGINE_ERROR("Uncompiled shader features"); return InvalidProgramHandle; } return programHandle; } -StringCrc ShaderSchema::GetOptionsCrc(const std::unordered_set& options) const +StringCrc ShaderSchema::GetFeaturesCrc(const ShaderFeatureSet& featureSet) const { - if (options.empty()) + if (m_shaderFeatureSets.empty() || featureSet.empty()) { return DefaultUberShaderCrc; } std::stringstream ss; - // Use the option order in m_uberOptions to ensure that inputs in different orders can get the same optionsCrc. - for (const auto& registered : m_uberOptions) + // Use the option order in m_shaderFeatureSets to ensure that inputs in different orders can get the same optionsCrc. + for (const auto& registeredSet : m_shaderFeatureSets) { - // Ignore option which contain in parameter but not contain in m_uberOptions. - if (options.find(registered) != options.end()) + // Ignore option which contain in parameter but not contain in m_shaderFeatureSets. + for (const auto& registeredFeature : registeredSet) { - ss << GetUberName(registered); + if (featureSet.find(registeredFeature) != featureSet.end()) + { + ss << GetFeatureName(registeredFeature); + } } + } return StringCrc(ss.str()); } -bool ShaderSchema::IsUberOptionsValid(StringCrc uberOption) const +bool ShaderSchema::IsFeaturesValid(StringCrc shaderFeaturesCrc) const { - return m_compiledProgramHandles.find(uberOption.Value()) != m_compiledProgramHandles.end(); + return m_compiledProgramHandles.find(shaderFeaturesCrc.Value()) != m_compiledProgramHandles.end(); } -void ShaderSchema::AddUberOptionVSBlob(ShaderBlob shaderBlob) +void ShaderSchema::AddUberVSBlob(ShaderBlob shaderBlob) { if (m_pVSBlob) { @@ -199,20 +196,20 @@ void ShaderSchema::AddUberOptionVSBlob(ShaderBlob shaderBlob) m_pVSBlob = std::make_unique(cd::MoveTemp(shaderBlob)); } -void ShaderSchema::AddUberOptionFSBlob(StringCrc uberOption, ShaderBlob shaderBlob) +void ShaderSchema::AddUberFSBlob(StringCrc shaderFeaturesCrc, ShaderBlob shaderBlob) { - if (m_uberOptionToFSBlobs.find(uberOption.Value()) != m_uberOptionToFSBlobs.end()) + if (m_shaderFeaturesToFSBlobs.find(shaderFeaturesCrc.Value()) != m_shaderFeaturesToFSBlobs.end()) { return; } - m_uberOptionToFSBlobs[uberOption.Value()] = std::make_unique(cd::MoveTemp(shaderBlob)); + m_shaderFeaturesToFSBlobs[shaderFeaturesCrc.Value()] = std::make_unique(cd::MoveTemp(shaderBlob)); } -const ShaderSchema::ShaderBlob& ShaderSchema::GetFSBlob(StringCrc uberOption) const +const ShaderSchema::ShaderBlob& ShaderSchema::GetFSBlob(StringCrc shaderFeaturesCrc) const { - auto itBlob = m_uberOptionToFSBlobs.find(uberOption.Value()); - assert(itBlob != m_uberOptionToFSBlobs.end()); + auto itBlob = m_shaderFeaturesToFSBlobs.find(shaderFeaturesCrc.Value()); + assert(itBlob != m_shaderFeaturesToFSBlobs.end()); return *(itBlob->second.get()); } diff --git a/Engine/Source/Runtime/Material/ShaderSchema.h b/Engine/Source/Runtime/Material/ShaderSchema.h index c8de0410..0dd92f71 100644 --- a/Engine/Source/Runtime/Material/ShaderSchema.h +++ b/Engine/Source/Runtime/Material/ShaderSchema.h @@ -13,7 +13,7 @@ namespace engine { -enum class Uber : uint32_t +enum class ShaderFeature : uint32_t { DEFAULT = 0, @@ -46,7 +46,9 @@ class ShaderSchema public: static constexpr uint16_t InvalidProgramHandle = UINT16_MAX; static constexpr StringCrc DefaultUberShaderCrc = StringCrc(""); + using ShaderBlob = std::vector; + using ShaderFeatureSet = std::set; public: ShaderSchema() = default; @@ -60,55 +62,46 @@ class ShaderSchema const char* GetVertexShaderPath() const { return m_vertexShaderPath.c_str(); } const char* GetFragmentShaderPath() const { return m_fragmentShaderPath.c_str(); } - void AddUberOption(Uber uberOption); - void SetConflictOptions(Uber a, Uber b); + void AddFeatureSet(ShaderFeatureSet featureSet); - // Calling "AddUberOption/SetConflictOptions and Build" after Build will cause unnecessary performance overhead. + // Calling "AddFeatureSet/SetConflictOptions and Build" after Build will cause unnecessary performance overhead. void Build(); void CleanBuild(); void CleanAll(); - void SetCompiledProgram(StringCrc uberOption, uint16_t programHandle); - uint16_t GetCompiledProgram(StringCrc uberOption) const; - - StringCrc GetOptionsCrc(const std::unordered_set& options) const; - bool IsUberOptionsValid(StringCrc uberOption) const; - - std::vector& GetUberOptions() { return m_uberOptions; } - const std::vector& GetUberOptions() const { return m_uberOptions; } + void SetCompiledProgram(StringCrc shaderFeaturesCrc, uint16_t programHandle); + uint16_t GetCompiledProgram(StringCrc shaderFeaturesCrc) const; - std::vector& GetUberCombines() { return m_uberCombines; } - const std::vector& GetUberCombines() const { return m_uberCombines; } + StringCrc GetFeaturesCrc(const ShaderFeatureSet& featureSet) const; + bool IsFeaturesValid(StringCrc shaderFeaturesCrc) const; - std::map& GetUberPrograms() { return m_compiledProgramHandles; } - const std::map& GetUberPrograms() const { return m_compiledProgramHandles; } + std::vector& GetFeatures() { return m_shaderFeatureSets; } + const std::vector& GetFeatures() const { return m_shaderFeatureSets; } - std::unordered_multimap& GetConflictOptions() { return m_conflictOptions; } - const std::unordered_multimap& GetConflictOptions() const { return m_conflictOptions; } + std::vector& GetFeatureCombines() { return m_featureCombines; } + const std::vector& GetFeatureCombines() const { return m_featureCombines; } // TODO : More generic. - void AddUberOptionVSBlob(ShaderBlob shaderBlob); - void AddUberOptionFSBlob(StringCrc uberOption, ShaderBlob shaderBlob); + void AddUberVSBlob(ShaderBlob shaderBlob); + void AddUberFSBlob(StringCrc shaderFeaturesCrc, ShaderBlob shaderBlob); const ShaderBlob& GetVSBlob() const { return *m_pVSBlob.get(); } - const ShaderBlob& GetFSBlob(StringCrc uberOption) const; + const ShaderBlob& GetFSBlob(StringCrc shaderFeaturesCrc) const; private: std::string m_vertexShaderPath; std::string m_fragmentShaderPath; - bool m_isDirty; - // Registration order of options. - std::vector m_uberOptions; + bool m_isDirty = false; + // Adding order of shaer features. + std::vector m_shaderFeatureSets; // Parameters to compile shaders. - std::vector m_uberCombines; - // Record options that will not be active at the same time to skip permutation. - std::unordered_multimap m_conflictOptions; + std::vector m_featureCombines; - // Key: StringCrc(option combine), Value: shader handle. + // Key: StringCrc(feature combine), Value: shader handle. std::map m_compiledProgramHandles; std::unique_ptr m_pVSBlob; - std::map> m_uberOptionToFSBlobs; + std::map> m_shaderFeaturesToFSBlobs; }; } \ No newline at end of file diff --git a/Engine/Source/Runtime/Rendering/SkeletonRenderer.cpp b/Engine/Source/Runtime/Rendering/SkeletonRenderer.cpp new file mode 100644 index 00000000..be0fb0af --- /dev/null +++ b/Engine/Source/Runtime/Rendering/SkeletonRenderer.cpp @@ -0,0 +1,136 @@ +#include "SkeletonRenderer.h" + +#include "Core/StringCrc.h" +#include "ECWorld/SceneWorld.h" +#include "ECWorld/TransformComponent.h" +#include "RenderContext.h" +#include "Rendering/Utility/VertexLayoutUtility.h" + +namespace engine +{ + +namespace details +{ + +constexpr uint32_t posDataSize = cd::Point::Size * sizeof(cd::Point::ValueType); + +constexpr size_t indexTypeSize = sizeof(uint16_t); + +cd::Vec3f CalculateBoneTranslate(const cd::Bone& bone, cd::Vec3f& translate, const cd::SceneDatabase* pSceneDatabase) +{ + const cd::Bone& parentBone = pSceneDatabase->GetBone(bone.GetParentID().Data()); + translate += parentBone.GetTransform().GetTranslation(); + if (0U != bone.GetParentID().Data()) + { + CalculateBoneTranslate(parentBone, translate, pSceneDatabase); + } + return translate; +} + +void TraverseBone(const cd::Bone& bone, const cd::SceneDatabase* pSceneDatabase, std::byte* currentDataPtr, + std::byte* currentIndexPtr, uint32_t& vertexOffset, uint32_t& indexOffset) +{ + constexpr uint32_t posDataSize = cd::Point::Size * sizeof(cd::Point::ValueType); + for (auto& child : bone.GetChildIDs()) + { + const cd::Bone& currBone = pSceneDatabase->GetBone(child.Data()); + const cd::Bone& parent = pSceneDatabase->GetBone(currBone.GetParentID().Data()); + cd::Vec3f translate = currBone.GetOffset().GetTranslation(); + + //const cd::Vec3f position = details::CalculateBoneTranslate(currBone, translate, pSceneDatabase); + + uint16_t parentID = currBone.GetParentID().Data(); + uint16_t currBoneID = currBone.GetID().Data(); + std::memcpy(¤tDataPtr[vertexOffset], translate.Begin(), posDataSize); + vertexOffset += posDataSize; + std::memcpy(¤tIndexPtr[indexOffset], &parentID, indexTypeSize); + indexOffset += static_cast(indexTypeSize); + std::memcpy(¤tIndexPtr[indexOffset], &currBoneID, indexTypeSize); + indexOffset += static_cast(indexTypeSize); + + TraverseBone(currBone, pSceneDatabase, currentDataPtr, currentIndexPtr, vertexOffset, indexOffset); + } +} + +} + +void SkeletonRenderer::Init() +{ + GetRenderContext()->CreateProgram("SkeletonProgram", "vs_AABB.bin", "fs_AABB.bin"); + bgfx::setViewName(GetViewID(), "SkeletonRenderer"); +} + +void SkeletonRenderer::UpdateView(const float* pViewMatrix, const float* pProjectionMatrix) +{ + UpdateViewRenderTarget(); + bgfx::setViewTransform(GetViewID(), pViewMatrix, pProjectionMatrix); +} + +void SkeletonRenderer::Build() +{ + const cd::SceneDatabase* pSceneDatabase = m_pCurrentSceneWorld->GetSceneDatabase(); + + const uint32_t vertexCount = pSceneDatabase->GetBoneCount(); + if (0 == vertexCount) + { + return; + } + + const cd::Bone& firstBone = pSceneDatabase->GetBone(0); + if (0 != firstBone.GetID().Data()) + { + CD_ENGINE_WARN("First BoneID is not 0"); + return; + } + + bgfx::setTransform(cd::Matrix4x4::Identity().Begin()); + cd::VertexFormat vertexFormat; + vertexFormat.AddAttributeLayout(cd::VertexAttributeType::Position, cd::AttributeValueType::Float, 3); + + constexpr size_t indexTypeSize = sizeof(uint16_t); + m_indexBuffer.resize((vertexCount - 1) * 2 * indexTypeSize); + m_vertexBuffer.resize(vertexCount * vertexFormat.GetStride()); + uint32_t currentVertexOffset = 0U; + uint32_t currentIndexOffset = 0U; + std::byte* pCurrentVertexBuffer = m_vertexBuffer.data(); + const cd::Point& position = firstBone.GetTransform().GetTranslation(); + std::memcpy(&pCurrentVertexBuffer[currentVertexOffset], position.Begin(), details::posDataSize); + currentVertexOffset += details::posDataSize; + + details::TraverseBone(firstBone, pSceneDatabase, m_vertexBuffer.data(), m_indexBuffer.data(), currentVertexOffset, currentIndexOffset); + bgfx::VertexLayout vertexLayout; + VertexLayoutUtility::CreateVertexLayout(vertexLayout, vertexFormat.GetVertexLayout()); + m_boneVBH = bgfx::createVertexBuffer(bgfx::makeRef(m_vertexBuffer.data(), static_cast(m_vertexBuffer.size())), vertexLayout).idx; + m_boneIBH = bgfx::createIndexBuffer(bgfx::makeRef(m_indexBuffer.data(), static_cast(m_indexBuffer.size())), 0U).idx; + +} + +void SkeletonRenderer::Render(float delataTime) +{ + for (Entity entity : m_pCurrentSceneWorld->GetAnimationEntities()) + { + auto pAnimationComponent = m_pCurrentSceneWorld->GetAnimationComponent(entity); + if (!pAnimationComponent) + { + continue; + } + if (!hasBuilt) + { + Build(); + hasBuilt = true; + } + + bgfx::setVertexBuffer(0, bgfx::VertexBufferHandle{ m_boneVBH }); + bgfx::setIndexBuffer(bgfx::IndexBufferHandle{ m_boneIBH }); + + constexpr uint64_t state = BGFX_STATE_WRITE_MASK | BGFX_STATE_MSAA | BGFX_STATE_DEPTH_TEST_LESS | + BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA) | BGFX_STATE_PT_LINES; + + bgfx::setState(state); + constexpr StringCrc SkeletonProgram("SkeletonProgram"); + bgfx::submit(GetViewID(), GetRenderContext()->GetProgram(SkeletonProgram)); + } + +} + +} \ No newline at end of file diff --git a/Engine/Source/Runtime/Rendering/SkeletonRenderer.h b/Engine/Source/Runtime/Rendering/SkeletonRenderer.h new file mode 100644 index 00000000..81632f97 --- /dev/null +++ b/Engine/Source/Runtime/Rendering/SkeletonRenderer.h @@ -0,0 +1,32 @@ +#pragma once + +#include "Renderer.h" +#include + +namespace engine +{ + +class SceneWorld; + +class SkeletonRenderer final : public Renderer +{ +public: + using Renderer::Renderer; + + virtual void Init() override; + virtual void UpdateView(const float* pViewMatrix, const float* pProjectionMatrix) override; + virtual void Render(float deltaTime) override; + void Build(); + void SetSceneWorld(SceneWorld* pSceneWorld) { m_pCurrentSceneWorld = pSceneWorld; } + +private: + SceneWorld* m_pCurrentSceneWorld = nullptr; + std::vector m_vertexBuffer; + std::vector m_indexBuffer; + uint16_t m_boneVBH = UINT16_MAX; + uint16_t m_boneIBH = UINT16_MAX; + + bool hasBuilt = false; +}; + +} \ No newline at end of file diff --git a/Engine/Source/Runtime/Resources/ShaderLoader.cpp b/Engine/Source/Runtime/Resources/ShaderLoader.cpp index 46aeff84..5f265bfd 100644 --- a/Engine/Source/Runtime/Resources/ShaderLoader.cpp +++ b/Engine/Source/Runtime/Resources/ShaderLoader.cpp @@ -10,28 +10,28 @@ namespace engine void ShaderLoader::UploadUberShader(engine::MaterialType* pMaterialType) { - std::map outputFSPathToUberOption; + std::map outputFSPathToShaderFeaturesCrc; engine::ShaderSchema& shaderSchema = pMaterialType->GetShaderSchema(); std::string outputVSFilePath = engine::Path::GetShaderOutputPath(shaderSchema.GetVertexShaderPath()); - for (const auto& combine : shaderSchema.GetUberCombines()) + for (const auto& combine : shaderSchema.GetFeatureCombines()) { std::string outputFSFilePath = engine::Path::GetShaderOutputPath(shaderSchema.GetFragmentShaderPath(), combine); - outputFSPathToUberOption[cd::MoveTemp(outputFSFilePath)] = engine::StringCrc(combine); + outputFSPathToShaderFeaturesCrc[cd::MoveTemp(outputFSFilePath)] = engine::StringCrc(combine); } // Vertex shader. - shaderSchema.AddUberOptionVSBlob(engine::ResourceLoader::LoadFile(outputVSFilePath.c_str())); + shaderSchema.AddUberVSBlob(engine::ResourceLoader::LoadFile(outputVSFilePath.c_str())); const auto& VSBlob = shaderSchema.GetVSBlob(); bgfx::ShaderHandle vsHandle = bgfx::createShader(bgfx::makeRef(VSBlob.data(), static_cast(VSBlob.size()))); bgfx::setName(vsHandle, outputVSFilePath.c_str()); // Fragment shader. - for (const auto& [outputFSFilePath, uberOptionCrc] : outputFSPathToUberOption) + for (const auto& [outputFSFilePath, ShaderFeaturesCrc] : outputFSPathToShaderFeaturesCrc) { - shaderSchema.AddUberOptionFSBlob(uberOptionCrc, engine::ResourceLoader::LoadFile(outputFSFilePath.c_str())); + shaderSchema.AddUberFSBlob(ShaderFeaturesCrc, engine::ResourceLoader::LoadFile(outputFSFilePath.c_str())); - const auto& FSBlob = shaderSchema.GetFSBlob(uberOptionCrc); + const auto& FSBlob = shaderSchema.GetFSBlob(ShaderFeaturesCrc); bgfx::ShaderHandle fsHandle = bgfx::createShader(bgfx::makeRef(FSBlob.data(), static_cast(FSBlob.size()))); bgfx::setName(fsHandle, outputFSFilePath.c_str()); assert(bgfx::isValid(fsHandle)); @@ -39,7 +39,7 @@ void ShaderLoader::UploadUberShader(engine::MaterialType* pMaterialType) // Program. bgfx::ProgramHandle uberProgramHandle = bgfx::createProgram(vsHandle, fsHandle); assert(bgfx::isValid(uberProgramHandle)); - shaderSchema.SetCompiledProgram(uberOptionCrc, uberProgramHandle.idx); + shaderSchema.SetCompiledProgram(ShaderFeaturesCrc, uberProgramHandle.idx); } } diff --git a/Engine/Source/Runtime/Window/Window.cpp b/Engine/Source/Runtime/Window/Window.cpp index d743a466..c40569a7 100644 --- a/Engine/Source/Runtime/Window/Window.cpp +++ b/Engine/Source/Runtime/Window/Window.cpp @@ -222,6 +222,16 @@ void Window::Update() } } +const bool Window::GetInputFocus() const +{ + return SDL_GetWindowFlags(m_pSDLWindow) & SDL_WINDOW_INPUT_FOCUS; +} + +const bool Window::GetMouseFocus() const +{ + return SDL_GetWindowFlags(m_pSDLWindow) & SDL_WINDOW_MOUSE_FOCUS; +} + void Window::SetTitle(const char* pTitle) { SDL_SetWindowTitle(m_pSDLWindow, pTitle); diff --git a/Engine/Source/Runtime/Window/Window.h b/Engine/Source/Runtime/Window/Window.h index a5b68e44..c2477bf8 100644 --- a/Engine/Source/Runtime/Window/Window.h +++ b/Engine/Source/Runtime/Window/Window.h @@ -28,6 +28,9 @@ class Window uint16_t GetWidth() const { return m_width; } uint16_t GetHeight() const { return m_height; } + + const bool GetInputFocus() const; + const bool GetMouseFocus() const; void SetTitle(const char* pTitle); void SetFullScreen(bool flag);