Compare commits
2 Commits
mono-PhysX
...
forward-re
| Author | SHA1 | Date | |
|---|---|---|---|
| 4266a0b570 | |||
| ef4ea45edc |
@ -24,3 +24,4 @@ endif ()
|
|||||||
add_subdirectory(Prism)
|
add_subdirectory(Prism)
|
||||||
add_subdirectory(Sandbox)
|
add_subdirectory(Sandbox)
|
||||||
add_subdirectory(Editor)
|
add_subdirectory(Editor)
|
||||||
|
add_subdirectory(PrismRuntime)
|
||||||
|
|||||||
@ -12,7 +12,7 @@ file(COPY ${IMGUI_INI} DESTINATION ${CMAKE_BINARY_DIR})
|
|||||||
file(GLOB DOTNET_LIBRARY library)
|
file(GLOB DOTNET_LIBRARY library)
|
||||||
file(COPY ${DOTNET_LIBRARY} DESTINATION ${CMAKE_BINARY_DIR})
|
file(COPY ${DOTNET_LIBRARY} DESTINATION ${CMAKE_BINARY_DIR})
|
||||||
|
|
||||||
file(GLOB_RECURSE SRC_SOURCE ./**.cpp)
|
file(GLOB_RECURSE SRC_SOURCE ./Editor/**.cpp)
|
||||||
|
|
||||||
add_executable(${PROJECT_NAME} ${SRC_SOURCE})
|
add_executable(${PROJECT_NAME} ${SRC_SOURCE})
|
||||||
|
|
||||||
|
|||||||
@ -19,6 +19,7 @@
|
|||||||
#include "Prism/Physics/Physics3D.h"
|
#include "Prism/Physics/Physics3D.h"
|
||||||
#include "Prism/Renderer/Renderer2D.h"
|
#include "Prism/Renderer/Renderer2D.h"
|
||||||
#include "Prism/Script/ScriptEngine.h"
|
#include "Prism/Script/ScriptEngine.h"
|
||||||
|
#include "Prism/Script/ScriptWrappers.h"
|
||||||
|
|
||||||
namespace Prism
|
namespace Prism
|
||||||
{
|
{
|
||||||
@ -51,8 +52,17 @@ namespace Prism
|
|||||||
NewScene();
|
NewScene();
|
||||||
m_CurrentScene = m_EditorScene;
|
m_CurrentScene = m_EditorScene;
|
||||||
|
|
||||||
|
SceneRenderer::GetOptions().ShowGrid = true;
|
||||||
|
|
||||||
AssetEditorPanel::RegisterDefaultEditors();
|
AssetEditorPanel::RegisterDefaultEditors();
|
||||||
FileSystem::StartWatching();
|
FileSystem::StartWatching();
|
||||||
|
|
||||||
|
m_ConsolePanel = CreateScope<ConsolePanel>();
|
||||||
|
Script::SetLogCallback([this](const std::string& message)
|
||||||
|
{
|
||||||
|
if (m_ConsolePanel)
|
||||||
|
m_ConsolePanel->AddMessage(message, ImVec4(1,1,1,1));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void EditorLayer::OnDetach()
|
void EditorLayer::OnDetach()
|
||||||
@ -105,7 +115,7 @@ namespace Prism
|
|||||||
Renderer::BeginRenderPass(SceneRenderer::GetFinalRenderPass(), false);
|
Renderer::BeginRenderPass(SceneRenderer::GetFinalRenderPass(), false);
|
||||||
const auto viewProj = m_EditorCamera.GetViewProjection();
|
const auto viewProj = m_EditorCamera.GetViewProjection();
|
||||||
Renderer2D::BeginScene(viewProj, false);
|
Renderer2D::BeginScene(viewProj, false);
|
||||||
Renderer2D::DrawRotatedRect({ transform.Translation.x + collider.Offset.x, transform.Translation.y + collider.Offset.y }, {transform.Scale.x * collider.Size.x, transform.Scale.y * collider.Size.y}, transform.Rotation.z, { 0.0f, 0.0f, 1.0f, 1.0f });
|
Renderer2D::DrawRotatedRect({ transform.Translation.x + collider.Offset.x, transform.Translation.y + collider.Offset.y , transform.Translation.z}, {transform.Scale.x * collider.Size.x, transform.Scale.y * collider.Size.y}, transform.Rotation.z, { 0.0f, 0.0f, 1.0f, 1.0f });
|
||||||
Renderer2D::EndScene();
|
Renderer2D::EndScene();
|
||||||
Renderer::EndRenderPass();
|
Renderer::EndRenderPass();
|
||||||
}
|
}
|
||||||
@ -117,7 +127,7 @@ namespace Prism
|
|||||||
Renderer::BeginRenderPass(SceneRenderer::GetFinalRenderPass(), false);
|
Renderer::BeginRenderPass(SceneRenderer::GetFinalRenderPass(), false);
|
||||||
const auto viewProj = m_EditorCamera.GetViewProjection();
|
const auto viewProj = m_EditorCamera.GetViewProjection();
|
||||||
Renderer2D::BeginScene(viewProj, false);
|
Renderer2D::BeginScene(viewProj, false);
|
||||||
Renderer2D::DrawCircle({ transform.Translation.x + collider.Offset.x, transform.Translation.y + collider.Offset.y}, collider.Radius, { 0.0f, 1.0f, 1.0f, 1.0f });
|
Renderer2D::DrawCircle({ transform.Translation.x + collider.Offset.x, transform.Translation.y + collider.Offset.y, transform.Translation.z}, collider.Radius, { 0.0f, 1.0f, 1.0f, 1.0f });
|
||||||
Renderer2D::EndScene();
|
Renderer2D::EndScene();
|
||||||
Renderer::EndRenderPass();
|
Renderer::EndRenderPass();
|
||||||
}
|
}
|
||||||
@ -144,6 +154,18 @@ namespace Prism
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (m_SceneState == SceneState::Play)
|
||||||
|
{
|
||||||
|
if (Input::GetCursorMode() != CursorMode::Normal)
|
||||||
|
{
|
||||||
|
if (Input::IsKeyPressed(KeyCode::LEFT_CONTROL) && Input::IsKeyPressed(KeyCode::LEFT_ALT) && Input::IsKeyPressed(KeyCode::GRAVE_ACCENT))
|
||||||
|
{
|
||||||
|
Input::SetCursorMode(CursorMode::Normal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EditorLayer::OnImGuiRender()
|
void EditorLayer::OnImGuiRender()
|
||||||
@ -237,7 +259,7 @@ namespace Prism
|
|||||||
{
|
{
|
||||||
// temp
|
// temp
|
||||||
if (ImGui::MenuItem("Reload C# Assembly"))
|
if (ImGui::MenuItem("Reload C# Assembly"))
|
||||||
ScriptEngine::ReloadAssembly("assets/scripts/ExampleApp.dll");
|
ScriptEngine::ReloadAssembly("assets/scripts/Assembly-Script.dll");
|
||||||
|
|
||||||
ImGui::MenuItem("Reload assembly on play", nullptr, &m_ReloadScriptOnPlay);
|
ImGui::MenuItem("Reload assembly on play", nullptr, &m_ReloadScriptOnPlay);
|
||||||
ImGui::EndMenu();
|
ImGui::EndMenu();
|
||||||
@ -275,8 +297,9 @@ namespace Prism
|
|||||||
Entity selectedEntity = m_SelectionContext.front().Entity;
|
Entity selectedEntity = m_SelectionContext.front().Entity;
|
||||||
if (selectedEntity.HasComponent<MeshComponent>())
|
if (selectedEntity.HasComponent<MeshComponent>())
|
||||||
{
|
{
|
||||||
Ref<Mesh> mesh = selectedEntity.GetComponent<MeshComponent>().Mesh;
|
auto& meshComponent = selectedEntity.GetComponent<MeshComponent>();
|
||||||
if (mesh)
|
|
||||||
|
if (Ref<Mesh> mesh = meshComponent.Mesh)
|
||||||
{
|
{
|
||||||
auto& materials = mesh->GetMaterials();
|
auto& materials = mesh->GetMaterials();
|
||||||
static uint32_t selectedMaterialIndex = 0;
|
static uint32_t selectedMaterialIndex = 0;
|
||||||
@ -304,27 +327,13 @@ namespace Prism
|
|||||||
}
|
}
|
||||||
ImGui::EndChild();
|
ImGui::EndChild();
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
for (uint32_t i = 0; i < materials.size(); i++)
|
|
||||||
{
|
|
||||||
const auto& materialInstance = materials[i];
|
|
||||||
|
|
||||||
ImGuiTreeNodeFlags node_flags = (selectedMaterialIndex == i ? ImGuiTreeNodeFlags_Selected : 0) | ImGuiTreeNodeFlags_Leaf;
|
|
||||||
bool opened = ImGui::TreeNodeEx((void*)(&materialInstance), node_flags, "%s", materialInstance->GetName().c_str());
|
|
||||||
if (ImGui::IsItemClicked())
|
|
||||||
{
|
|
||||||
selectedMaterialIndex = i;
|
|
||||||
}
|
|
||||||
if (opened)
|
|
||||||
ImGui::TreePop();
|
|
||||||
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
|
|
||||||
if (selectedMaterialIndex < materials.size())
|
if (selectedMaterialIndex < materials.size())
|
||||||
{
|
{
|
||||||
|
bool shouldUpdate = false;
|
||||||
|
|
||||||
auto& materialInstance = materials[selectedMaterialIndex];
|
auto& materialInstance = materials[selectedMaterialIndex];
|
||||||
ImGui::Text("Shader: %s", materialInstance->GetShader()->GetName().c_str());
|
ImGui::Text("Shader: %s", materialInstance->GetShader()->GetName().c_str());
|
||||||
// Textures ------------------------------------------------------------------------------
|
// Textures ------------------------------------------------------------------------------
|
||||||
@ -339,6 +348,21 @@ namespace Prism
|
|||||||
Ref<Texture2D> albedoMap = materialInstance->TryGetResource<Texture2D>("u_AlbedoTexture");
|
Ref<Texture2D> albedoMap = materialInstance->TryGetResource<Texture2D>("u_AlbedoTexture");
|
||||||
|
|
||||||
ImGui::Image(albedoMap ? (ImTextureRef)albedoMap->GetRendererID() : (ImTextureRef)m_CheckerboardTex->GetRendererID(), ImVec2(64, 64));
|
ImGui::Image(albedoMap ? (ImTextureRef)albedoMap->GetRendererID() : (ImTextureRef)m_CheckerboardTex->GetRendererID(), ImVec2(64, 64));
|
||||||
|
|
||||||
|
if (ImGui::BeginDragDropTarget())
|
||||||
|
{
|
||||||
|
if (const auto data = ImGui::AcceptDragDropPayload("asset_payload"))
|
||||||
|
{
|
||||||
|
AssetHandle assetHandle = *(AssetHandle*)data->Data;
|
||||||
|
if (AssetsManager::IsAssetType(assetHandle, AssetType::Texture))
|
||||||
|
{
|
||||||
|
albedoMap = AssetsManager::GetAsset<Texture2D>(assetHandle);
|
||||||
|
shouldUpdate = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::EndDragDropTarget();
|
||||||
|
}
|
||||||
|
|
||||||
ImGui::PopStyleVar();
|
ImGui::PopStyleVar();
|
||||||
if (ImGui::IsItemHovered())
|
if (ImGui::IsItemHovered())
|
||||||
{
|
{
|
||||||
@ -351,28 +375,23 @@ namespace Prism
|
|||||||
ImGui::Image((ImTextureRef)albedoMap->GetRendererID(), ImVec2(384, 384));
|
ImGui::Image((ImTextureRef)albedoMap->GetRendererID(), ImVec2(384, 384));
|
||||||
ImGui::EndTooltip();
|
ImGui::EndTooltip();
|
||||||
}
|
}
|
||||||
if (ImGui::IsItemClicked())
|
|
||||||
{
|
|
||||||
if (std::string filename = FileSystem::OpenFileSelector("*.png;*.tga;*.jpg;*.jpeg"); !filename.empty())
|
|
||||||
{
|
|
||||||
albedoMap = Texture2D::Create(filename, true/*m_AlbedoInput.SRGB*/);
|
|
||||||
materialInstance->Set("u_AlbedoTexture", albedoMap);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
ImGui::BeginGroup();
|
ImGui::BeginGroup();
|
||||||
if (ImGui::Checkbox("Use##AlbedoMap", &useAlbedoMap))
|
if (ImGui::Checkbox("Use##AlbedoMap", &useAlbedoMap))
|
||||||
materialInstance->Set<float>("u_AlbedoTexToggle", useAlbedoMap ? 1.0f : 0.0f);
|
|
||||||
|
|
||||||
/*if (ImGui::Checkbox("sRGB##AlbedoMap", &m_AlbedoInput.SRGB))
|
|
||||||
{
|
{
|
||||||
if (m_AlbedoInput.TextureMap)
|
materialInstance->Set<float>("u_AlbedoTexToggle", useAlbedoMap ? 1.0f : 0.0f);
|
||||||
m_AlbedoInput.TextureMap = Texture2D::Create(m_AlbedoInput.TextureMap->GetPath(), m_AlbedoInput.SRGB);
|
shouldUpdate = true;
|
||||||
}*/
|
}
|
||||||
|
|
||||||
|
|
||||||
ImGui::EndGroup();
|
ImGui::EndGroup();
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
ImGui::ColorEdit3("Color##Albedo", glm::value_ptr(albedoColor), ImGuiColorEditFlags_NoInputs);
|
if (ImGui::ColorEdit3("Color##Albedo", glm::value_ptr(albedoColor), ImGuiColorEditFlags_NoInputs))
|
||||||
|
{
|
||||||
|
meshComponent.UpdateMaterials(selectedMaterialIndex);
|
||||||
|
shouldUpdate = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
@ -385,6 +404,21 @@ namespace Prism
|
|||||||
Ref<Texture2D> normalMap = materialInstance->TryGetResource<Texture2D>("u_NormalTexture");
|
Ref<Texture2D> normalMap = materialInstance->TryGetResource<Texture2D>("u_NormalTexture");
|
||||||
|
|
||||||
ImGui::Image(normalMap ? (ImTextureRef)normalMap->GetRendererID() : (ImTextureRef)m_CheckerboardTex->GetRendererID(), ImVec2(64, 64));
|
ImGui::Image(normalMap ? (ImTextureRef)normalMap->GetRendererID() : (ImTextureRef)m_CheckerboardTex->GetRendererID(), ImVec2(64, 64));
|
||||||
|
|
||||||
|
if (ImGui::BeginDragDropTarget())
|
||||||
|
{
|
||||||
|
if (const auto data = ImGui::AcceptDragDropPayload("asset_payload"))
|
||||||
|
{
|
||||||
|
AssetHandle assetHandle = *(AssetHandle*)data->Data;
|
||||||
|
if (AssetsManager::IsAssetType(assetHandle, AssetType::Texture))
|
||||||
|
{
|
||||||
|
normalMap = AssetsManager::GetAsset<Texture2D>(assetHandle);
|
||||||
|
shouldUpdate = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::EndDragDropTarget();
|
||||||
|
}
|
||||||
|
|
||||||
ImGui::PopStyleVar();
|
ImGui::PopStyleVar();
|
||||||
if (ImGui::IsItemHovered())
|
if (ImGui::IsItemHovered())
|
||||||
{
|
{
|
||||||
@ -403,12 +437,16 @@ namespace Prism
|
|||||||
{
|
{
|
||||||
normalMap = Texture2D::Create(filename);
|
normalMap = Texture2D::Create(filename);
|
||||||
materialInstance->Set("u_NormalTexture", normalMap);
|
materialInstance->Set("u_NormalTexture", normalMap);
|
||||||
|
shouldUpdate = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
if (ImGui::Checkbox("Use##NormalMap", &useNormalMap))
|
if (ImGui::Checkbox("Use##NormalMap", &useNormalMap))
|
||||||
|
{
|
||||||
materialInstance->Set<float>("u_NormalTexToggle", useNormalMap ? 1.0f : 0.0f);
|
materialInstance->Set<float>("u_NormalTexToggle", useNormalMap ? 1.0f : 0.0f);
|
||||||
|
shouldUpdate = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
@ -422,6 +460,21 @@ namespace Prism
|
|||||||
Ref<Texture2D> metalnessMap = materialInstance->TryGetResource<Texture2D>("u_MetalnessTexture");
|
Ref<Texture2D> metalnessMap = materialInstance->TryGetResource<Texture2D>("u_MetalnessTexture");
|
||||||
|
|
||||||
ImGui::Image(metalnessMap ? (ImTextureRef)metalnessMap->GetRendererID() : (ImTextureRef)m_CheckerboardTex->GetRendererID(), ImVec2(64, 64));
|
ImGui::Image(metalnessMap ? (ImTextureRef)metalnessMap->GetRendererID() : (ImTextureRef)m_CheckerboardTex->GetRendererID(), ImVec2(64, 64));
|
||||||
|
|
||||||
|
if (ImGui::BeginDragDropTarget())
|
||||||
|
{
|
||||||
|
if (const auto data = ImGui::AcceptDragDropPayload("asset_payload"))
|
||||||
|
{
|
||||||
|
AssetHandle assetHandle = *(AssetHandle*)data->Data;
|
||||||
|
if (AssetsManager::IsAssetType(assetHandle, AssetType::Texture))
|
||||||
|
{
|
||||||
|
metalnessMap = AssetsManager::GetAsset<Texture2D>(assetHandle);
|
||||||
|
shouldUpdate = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::EndDragDropTarget();
|
||||||
|
}
|
||||||
|
|
||||||
ImGui::PopStyleVar();
|
ImGui::PopStyleVar();
|
||||||
if (ImGui::IsItemHovered())
|
if (ImGui::IsItemHovered())
|
||||||
{
|
{
|
||||||
@ -434,20 +487,18 @@ namespace Prism
|
|||||||
ImGui::Image((ImTextureRef)metalnessMap->GetRendererID(), ImVec2(384, 384));
|
ImGui::Image((ImTextureRef)metalnessMap->GetRendererID(), ImVec2(384, 384));
|
||||||
ImGui::EndTooltip();
|
ImGui::EndTooltip();
|
||||||
}
|
}
|
||||||
if (ImGui::IsItemClicked())
|
|
||||||
{
|
|
||||||
if (std::string filename = FileSystem::OpenFileSelector("*.png;*.tga;*.jpg;*.jpeg"); !filename.empty())
|
|
||||||
{
|
|
||||||
metalnessMap = Texture2D::Create(filename);
|
|
||||||
materialInstance->Set("u_MetalnessTexture", metalnessMap);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
if (ImGui::Checkbox("Use##MetalnessMap", &useMetalnessMap))
|
if (ImGui::Checkbox("Use##MetalnessMap", &useMetalnessMap))
|
||||||
|
{
|
||||||
materialInstance->Set<float>("u_MetalnessTexToggle", useMetalnessMap ? 1.0f : 0.0f);
|
materialInstance->Set<float>("u_MetalnessTexToggle", useMetalnessMap ? 1.0f : 0.0f);
|
||||||
|
shouldUpdate = true;
|
||||||
|
}
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
ImGui::SliderFloat("Value##MetalnessInput", &metalnessValue, 0.0f, 1.0f);
|
if (ImGui::SliderFloat("Value##MetalnessInput", &metalnessValue, 0.0f, 1.0f))
|
||||||
|
{
|
||||||
|
shouldUpdate = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
@ -460,6 +511,20 @@ namespace Prism
|
|||||||
Ref<Texture2D> roughnessMap = materialInstance->TryGetResource<Texture2D>("u_RoughnessTexture");
|
Ref<Texture2D> roughnessMap = materialInstance->TryGetResource<Texture2D>("u_RoughnessTexture");
|
||||||
|
|
||||||
ImGui::Image(roughnessMap ? (ImTextureRef)roughnessMap->GetRendererID() : (ImTextureRef)m_CheckerboardTex->GetRendererID(), ImVec2(64, 64));
|
ImGui::Image(roughnessMap ? (ImTextureRef)roughnessMap->GetRendererID() : (ImTextureRef)m_CheckerboardTex->GetRendererID(), ImVec2(64, 64));
|
||||||
|
if (ImGui::BeginDragDropTarget())
|
||||||
|
{
|
||||||
|
if (const auto data = ImGui::AcceptDragDropPayload("asset_payload"))
|
||||||
|
{
|
||||||
|
AssetHandle assetHandle = *(AssetHandle*)data->Data;
|
||||||
|
if (AssetsManager::IsAssetType(assetHandle, AssetType::Texture))
|
||||||
|
{
|
||||||
|
roughnessMap = AssetsManager::GetAsset<Texture2D>(assetHandle);
|
||||||
|
shouldUpdate = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::EndDragDropTarget();
|
||||||
|
}
|
||||||
|
|
||||||
ImGui::PopStyleVar();
|
ImGui::PopStyleVar();
|
||||||
if (ImGui::IsItemHovered())
|
if (ImGui::IsItemHovered())
|
||||||
{
|
{
|
||||||
@ -472,22 +537,21 @@ namespace Prism
|
|||||||
ImGui::Image((ImTextureRef)roughnessMap->GetRendererID(), ImVec2(384, 384));
|
ImGui::Image((ImTextureRef)roughnessMap->GetRendererID(), ImVec2(384, 384));
|
||||||
ImGui::EndTooltip();
|
ImGui::EndTooltip();
|
||||||
}
|
}
|
||||||
if (ImGui::IsItemClicked())
|
|
||||||
{
|
|
||||||
if (std::string filename = FileSystem::OpenFileSelector("*.png;*.tga;*.jpg;*.jpeg"); !filename.empty())
|
|
||||||
{
|
|
||||||
roughnessMap = Texture2D::Create(filename);
|
|
||||||
materialInstance->Set("u_RoughnessTexture", roughnessMap);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
if (ImGui::Checkbox("Use##RoughnessMap", &useRoughnessMap))
|
if (ImGui::Checkbox("Use##RoughnessMap", &useRoughnessMap))
|
||||||
|
{
|
||||||
materialInstance->Set<float>("u_RoughnessTexToggle", useRoughnessMap ? 1.0f : 0.0f);
|
materialInstance->Set<float>("u_RoughnessTexToggle", useRoughnessMap ? 1.0f : 0.0f);
|
||||||
|
shouldUpdate = true;
|
||||||
|
}
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
ImGui::SliderFloat("Value##RoughnessInput", &roughnessValue, 0.0f, 1.0f);
|
if (ImGui::SliderFloat("Value##RoughnessInput", &roughnessValue, 0.0f, 1.0f))
|
||||||
|
{
|
||||||
|
shouldUpdate = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (shouldUpdate) meshComponent.UpdateMaterials(selectedMaterialIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -505,7 +569,8 @@ namespace Prism
|
|||||||
m_ObjectsPanel->OnImGuiRender();
|
m_ObjectsPanel->OnImGuiRender();
|
||||||
|
|
||||||
m_SceneHierarchyPanel->OnImGuiRender();
|
m_SceneHierarchyPanel->OnImGuiRender();
|
||||||
m_EditorCamera.OnImGuiRender();
|
// m_EditorCamera.OnImGuiRender();
|
||||||
|
m_ConsolePanel->OnImGuiRender();
|
||||||
|
|
||||||
// Editor Panel ------------------------------------------------------------------------------
|
// Editor Panel ------------------------------------------------------------------------------
|
||||||
ImGui::Begin("Environment");
|
ImGui::Begin("Environment");
|
||||||
@ -1054,17 +1119,6 @@ namespace Prism
|
|||||||
});
|
});
|
||||||
if (!m_SelectionContext.empty())
|
if (!m_SelectionContext.empty())
|
||||||
{
|
{
|
||||||
if (auto alreadySelectedEntity = m_SceneHierarchyPanel->GetSelected();
|
|
||||||
m_SelectionContext.size() != 1 && alreadySelectedEntity)
|
|
||||||
{
|
|
||||||
const auto alreadySelectedEntityID = alreadySelectedEntity.GetUUID();
|
|
||||||
|
|
||||||
for (const auto& selectedEntity : m_SelectionContext)
|
|
||||||
{
|
|
||||||
if (alreadySelectedEntityID == selectedEntity.Entity.GetUUID()) continue;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
OnSelected(m_SelectionContext[0]);
|
OnSelected(m_SelectionContext[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1164,7 +1218,7 @@ namespace Prism
|
|||||||
UpdateWindowTitle("Untitled Scene");
|
UpdateWindowTitle("Untitled Scene");
|
||||||
m_SceneFilePath = std::string();
|
m_SceneFilePath = std::string();
|
||||||
|
|
||||||
m_EditorCamera = EditorCamera(glm::perspectiveFov(glm::radians(45.0f), 1280.0f, 720.0f, 0.1f, 100.0f));
|
m_EditorCamera = EditorCamera(glm::perspectiveFov(glm::radians(45.0f), 1280.0f, 720.0f, 0.1f, 1000.0f));
|
||||||
m_SelectionContext.clear();
|
m_SelectionContext.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -5,6 +5,7 @@
|
|||||||
#ifndef EDITORLAYER_H
|
#ifndef EDITORLAYER_H
|
||||||
#define EDITORLAYER_H
|
#define EDITORLAYER_H
|
||||||
|
|
||||||
|
#include "Panels/ConsolePanel.h"
|
||||||
#include "Prism.h"
|
#include "Prism.h"
|
||||||
#include "Prism/Editor/ContentBrowserPanel.h"
|
#include "Prism/Editor/ContentBrowserPanel.h"
|
||||||
#include "Prism/Editor/ObjectsPanel.h"
|
#include "Prism/Editor/ObjectsPanel.h"
|
||||||
@ -150,6 +151,9 @@ namespace Prism
|
|||||||
Edit = 0, Play = 1, Pause = 2
|
Edit = 0, Play = 1, Pause = 2
|
||||||
};
|
};
|
||||||
SceneState m_SceneState = SceneState::Edit;
|
SceneState m_SceneState = SceneState::Edit;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Scope<ConsolePanel> m_ConsolePanel;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
66
Editor/Editor/Panels/ConsolePanel.cpp
Normal file
66
Editor/Editor/Panels/ConsolePanel.cpp
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
//
|
||||||
|
// Created by Atdunbg on 2026/3/26.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "ConsolePanel.h"
|
||||||
|
|
||||||
|
namespace Prism
|
||||||
|
{
|
||||||
|
ConsolePanel::ConsolePanel()
|
||||||
|
{
|
||||||
|
// 预留一些空间
|
||||||
|
m_Messages.reserve(1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConsolePanel::OnImGuiRender()
|
||||||
|
{
|
||||||
|
ImGui::Begin("Console");
|
||||||
|
|
||||||
|
// 工具栏
|
||||||
|
if (ImGui::Button("Clear"))
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(m_Mutex);
|
||||||
|
m_Messages.clear();
|
||||||
|
}
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::Checkbox("Auto-scroll", &m_AutoScroll);
|
||||||
|
ImGui::SameLine();
|
||||||
|
m_Filter.Draw("Filter", 200);
|
||||||
|
|
||||||
|
// 消息列表区域
|
||||||
|
ImGui::BeginChild("ScrollingRegion", ImVec2(0, 0), ImGuiChildFlags_Borders, ImGuiWindowFlags_HorizontalScrollbar);
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(m_Mutex);
|
||||||
|
for (const auto& [msg, color] : m_Messages)
|
||||||
|
{
|
||||||
|
if (m_Filter.PassFilter(msg.c_str()))
|
||||||
|
{
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_Text, color);
|
||||||
|
ImGui::TextUnformatted(msg.c_str());
|
||||||
|
ImGui::PopStyleColor();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_ScrollToBottom)
|
||||||
|
{
|
||||||
|
ImGui::SetScrollHereY(1.0f);
|
||||||
|
m_ScrollToBottom = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::EndChild();
|
||||||
|
|
||||||
|
|
||||||
|
ImGui::End();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConsolePanel::AddMessage(const std::string& message, ImVec4 color)
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(m_Mutex);
|
||||||
|
m_Messages.emplace_back(message, color);
|
||||||
|
while (m_Messages.size() > 5000)
|
||||||
|
m_Messages.erase(m_Messages.begin());
|
||||||
|
|
||||||
|
if (m_AutoScroll && !m_ScrollToBottom)
|
||||||
|
m_ScrollToBottom = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
31
Editor/Editor/Panels/ConsolePanel.h
Normal file
31
Editor/Editor/Panels/ConsolePanel.h
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
//
|
||||||
|
// Created by Atdunbg on 2026/3/26.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef PRISM_CONSOLEPANEL_H
|
||||||
|
#define PRISM_CONSOLEPANEL_H
|
||||||
|
#include <mutex>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "imgui.h"
|
||||||
|
|
||||||
|
namespace Prism
|
||||||
|
{
|
||||||
|
class ConsolePanel
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ConsolePanel();
|
||||||
|
void OnImGuiRender();
|
||||||
|
|
||||||
|
void AddMessage(const std::string& message, ImVec4 color = ImVec4(1,1,1,1));
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<std::pair<std::string, ImVec4>> m_Messages;
|
||||||
|
ImGuiTextFilter m_Filter;
|
||||||
|
bool m_AutoScroll = true;
|
||||||
|
bool m_ScrollToBottom = false;
|
||||||
|
std::mutex m_Mutex;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //PRISM_CONSOLEPANEL_H
|
||||||
336
Editor/assets/scenes/FPS.scene
Normal file
336
Editor/assets/scenes/FPS.scene
Normal file
@ -0,0 +1,336 @@
|
|||||||
|
Scene: Scene Name
|
||||||
|
Environment:
|
||||||
|
AssetHandle: 5211537204242875091
|
||||||
|
Entities:
|
||||||
|
- Entity: 8293051279669100759
|
||||||
|
Parent: 0
|
||||||
|
Children:
|
||||||
|
[]
|
||||||
|
TagComponent:
|
||||||
|
Tag: Cube
|
||||||
|
TransformComponent:
|
||||||
|
Position: [1.736814, 1.4724115, -4.2181306]
|
||||||
|
Rotation: [0, 0, 0]
|
||||||
|
Scale: [1, 1, 1]
|
||||||
|
MeshComponent:
|
||||||
|
AssetID: 18328012085543462741
|
||||||
|
AssetPath: assets/meshes/Default/Cube.fbx
|
||||||
|
RigidBodyComponent:
|
||||||
|
BodyType: 1
|
||||||
|
Mass: 1
|
||||||
|
LinearDrag: 0
|
||||||
|
AngularDrag: 0.05
|
||||||
|
DisableGravity: false
|
||||||
|
IsKinematic: false
|
||||||
|
Layer: 0
|
||||||
|
Constraints:
|
||||||
|
LockPositionX: false
|
||||||
|
LockPositionY: false
|
||||||
|
LockPositionZ: false
|
||||||
|
LockRotationX: false
|
||||||
|
LockRotationY: false
|
||||||
|
LockRotationZ: false
|
||||||
|
BoxColliderComponent:
|
||||||
|
Offset: [0, 0, 0]
|
||||||
|
Size: [2, 2, 2]
|
||||||
|
IsTrigger: false
|
||||||
|
Material: 0
|
||||||
|
MaterialPath: ""
|
||||||
|
- Entity: 5834225236589765516
|
||||||
|
Parent: 0
|
||||||
|
Children:
|
||||||
|
[]
|
||||||
|
TagComponent:
|
||||||
|
Tag: Cube
|
||||||
|
TransformComponent:
|
||||||
|
Position: [-2.6417403, 1.4724115, -7.9285727]
|
||||||
|
Rotation: [0.52199936, 0, 0]
|
||||||
|
Scale: [1, 1.0000001, 1.0000001]
|
||||||
|
MeshComponent:
|
||||||
|
AssetID: 18328012085543462741
|
||||||
|
AssetPath: assets/meshes/Default/Cube.fbx
|
||||||
|
RigidBodyComponent:
|
||||||
|
BodyType: 1
|
||||||
|
Mass: 1
|
||||||
|
LinearDrag: 0
|
||||||
|
AngularDrag: 0.05
|
||||||
|
DisableGravity: false
|
||||||
|
IsKinematic: false
|
||||||
|
Layer: 0
|
||||||
|
Constraints:
|
||||||
|
LockPositionX: false
|
||||||
|
LockPositionY: false
|
||||||
|
LockPositionZ: false
|
||||||
|
LockRotationX: false
|
||||||
|
LockRotationY: false
|
||||||
|
LockRotationZ: false
|
||||||
|
BoxColliderComponent:
|
||||||
|
Offset: [0, 0, 0]
|
||||||
|
Size: [2, 2, 2]
|
||||||
|
IsTrigger: false
|
||||||
|
Material: 0
|
||||||
|
MaterialPath: ""
|
||||||
|
- Entity: 8234256119181302872
|
||||||
|
Parent: 0
|
||||||
|
Children:
|
||||||
|
[]
|
||||||
|
TagComponent:
|
||||||
|
Tag: Cube
|
||||||
|
TransformComponent:
|
||||||
|
Position: [1.736814, 1.4724115, -7.9285727]
|
||||||
|
Rotation: [0, 0, 0]
|
||||||
|
Scale: [1, 1, 1]
|
||||||
|
MeshComponent:
|
||||||
|
AssetID: 18328012085543462741
|
||||||
|
AssetPath: assets/meshes/Default/Cube.fbx
|
||||||
|
RigidBodyComponent:
|
||||||
|
BodyType: 1
|
||||||
|
Mass: 1
|
||||||
|
LinearDrag: 0
|
||||||
|
AngularDrag: 0.05
|
||||||
|
DisableGravity: false
|
||||||
|
IsKinematic: false
|
||||||
|
Layer: 0
|
||||||
|
Constraints:
|
||||||
|
LockPositionX: false
|
||||||
|
LockPositionY: false
|
||||||
|
LockPositionZ: false
|
||||||
|
LockRotationX: false
|
||||||
|
LockRotationY: false
|
||||||
|
LockRotationZ: false
|
||||||
|
BoxColliderComponent:
|
||||||
|
Offset: [0, 0, 0]
|
||||||
|
Size: [2, 2, 2]
|
||||||
|
IsTrigger: false
|
||||||
|
Material: 0
|
||||||
|
MaterialPath: ""
|
||||||
|
- Entity: 12935252585493481950
|
||||||
|
Parent: 0
|
||||||
|
Children:
|
||||||
|
[]
|
||||||
|
TagComponent:
|
||||||
|
Tag: Cube
|
||||||
|
TransformComponent:
|
||||||
|
Position: [-1.5106764, 6.237644, -4.2181306]
|
||||||
|
Rotation: [0, 0, 0]
|
||||||
|
Scale: [1, 1, 1]
|
||||||
|
MeshComponent:
|
||||||
|
AssetID: 18328012085543462741
|
||||||
|
AssetPath: assets/meshes/Default/Cube.fbx
|
||||||
|
RigidBodyComponent:
|
||||||
|
BodyType: 1
|
||||||
|
Mass: 1
|
||||||
|
LinearDrag: 0
|
||||||
|
AngularDrag: 0.05
|
||||||
|
DisableGravity: false
|
||||||
|
IsKinematic: false
|
||||||
|
Layer: 0
|
||||||
|
Constraints:
|
||||||
|
LockPositionX: false
|
||||||
|
LockPositionY: false
|
||||||
|
LockPositionZ: false
|
||||||
|
LockRotationX: false
|
||||||
|
LockRotationY: false
|
||||||
|
LockRotationZ: false
|
||||||
|
BoxColliderComponent:
|
||||||
|
Offset: [0, 0, 0]
|
||||||
|
Size: [2, 2, 2]
|
||||||
|
IsTrigger: false
|
||||||
|
Material: 0
|
||||||
|
MaterialPath: ""
|
||||||
|
- Entity: 3328246672296261054
|
||||||
|
Parent: 0
|
||||||
|
Children:
|
||||||
|
[]
|
||||||
|
TagComponent:
|
||||||
|
Tag: Cube
|
||||||
|
TransformComponent:
|
||||||
|
Position: [1.736814, 1.4724115, -0.88378817]
|
||||||
|
Rotation: [0, 0, 0]
|
||||||
|
Scale: [1, 1, 1]
|
||||||
|
MeshComponent:
|
||||||
|
AssetID: 18328012085543462741
|
||||||
|
AssetPath: assets/meshes/Default/Cube.fbx
|
||||||
|
RigidBodyComponent:
|
||||||
|
BodyType: 1
|
||||||
|
Mass: 1
|
||||||
|
LinearDrag: 0
|
||||||
|
AngularDrag: 0.05
|
||||||
|
DisableGravity: false
|
||||||
|
IsKinematic: false
|
||||||
|
Layer: 0
|
||||||
|
Constraints:
|
||||||
|
LockPositionX: false
|
||||||
|
LockPositionY: false
|
||||||
|
LockPositionZ: false
|
||||||
|
LockRotationX: false
|
||||||
|
LockRotationY: false
|
||||||
|
LockRotationZ: false
|
||||||
|
BoxColliderComponent:
|
||||||
|
Offset: [0, 0, 0]
|
||||||
|
Size: [2, 2, 2]
|
||||||
|
IsTrigger: false
|
||||||
|
Material: 0
|
||||||
|
MaterialPath: ""
|
||||||
|
- Entity: 4208267561919679628
|
||||||
|
Parent: 0
|
||||||
|
Children:
|
||||||
|
[]
|
||||||
|
TagComponent:
|
||||||
|
Tag: Cube
|
||||||
|
TransformComponent:
|
||||||
|
Position: [-2.6417403, 1.4724115, -4.8956265]
|
||||||
|
Rotation: [-0.4034239, 0, 0]
|
||||||
|
Scale: [1, 0.99999994, 0.99999994]
|
||||||
|
MeshComponent:
|
||||||
|
AssetID: 18328012085543462741
|
||||||
|
AssetPath: assets/meshes/Default/Cube.fbx
|
||||||
|
RigidBodyComponent:
|
||||||
|
BodyType: 1
|
||||||
|
Mass: 1
|
||||||
|
LinearDrag: 0
|
||||||
|
AngularDrag: 0.05
|
||||||
|
DisableGravity: true
|
||||||
|
IsKinematic: false
|
||||||
|
Layer: 0
|
||||||
|
Constraints:
|
||||||
|
LockPositionX: false
|
||||||
|
LockPositionY: false
|
||||||
|
LockPositionZ: false
|
||||||
|
LockRotationX: false
|
||||||
|
LockRotationY: false
|
||||||
|
LockRotationZ: false
|
||||||
|
BoxColliderComponent:
|
||||||
|
Offset: [0, 0, 0]
|
||||||
|
Size: [2, 2, 2]
|
||||||
|
IsTrigger: false
|
||||||
|
Material: 0
|
||||||
|
MaterialPath: ""
|
||||||
|
- Entity: 8114736924719261351
|
||||||
|
Parent: 0
|
||||||
|
Children:
|
||||||
|
[]
|
||||||
|
TagComponent:
|
||||||
|
Tag: Camera
|
||||||
|
TransformComponent:
|
||||||
|
Position: [0, 0.8097433, 4.573171]
|
||||||
|
Rotation: [0, 0, 0]
|
||||||
|
Scale: [1, 1, 1]
|
||||||
|
CameraComponent:
|
||||||
|
Camera:
|
||||||
|
ProjectionType: 0
|
||||||
|
PerspectiveFOV: 45
|
||||||
|
PerspectiveNear: 0.01
|
||||||
|
PerspectiveFar: 10000
|
||||||
|
OrthographicSize: 10
|
||||||
|
OrthographicNear: -1
|
||||||
|
OrthographicFar: 1
|
||||||
|
Primary: true
|
||||||
|
- Entity: 9267298328378270409
|
||||||
|
Parent: 0
|
||||||
|
Children:
|
||||||
|
[]
|
||||||
|
TagComponent:
|
||||||
|
Tag: Player
|
||||||
|
TransformComponent:
|
||||||
|
Position: [0, 0.70693016, 0]
|
||||||
|
Rotation: [0, 0, 0]
|
||||||
|
Scale: [1, 1, 1]
|
||||||
|
ScriptComponent:
|
||||||
|
ModuleName: FPSExample.FPSPlayer
|
||||||
|
StoredFields:
|
||||||
|
- Name: WalkingSpeed
|
||||||
|
Type: 1
|
||||||
|
Data: 2
|
||||||
|
- Name: RunSpeed
|
||||||
|
Type: 1
|
||||||
|
Data: 5
|
||||||
|
- Name: JumpForce
|
||||||
|
Type: 1
|
||||||
|
Data: 1
|
||||||
|
- Name: MouseSensitivity
|
||||||
|
Type: 1
|
||||||
|
Data: 10
|
||||||
|
- Name: CameraForwardOffset
|
||||||
|
Type: 1
|
||||||
|
Data: -2
|
||||||
|
- Name: CameraYOffset
|
||||||
|
Type: 1
|
||||||
|
Data: 2
|
||||||
|
MeshComponent:
|
||||||
|
AssetID: 3043502408333723884
|
||||||
|
AssetPath: assets/meshes/Default/Capsule.fbx
|
||||||
|
RigidBodyComponent:
|
||||||
|
BodyType: 1
|
||||||
|
Mass: 1
|
||||||
|
LinearDrag: 0
|
||||||
|
AngularDrag: 0.05
|
||||||
|
DisableGravity: false
|
||||||
|
IsKinematic: false
|
||||||
|
Layer: 0
|
||||||
|
Constraints:
|
||||||
|
LockPositionX: false
|
||||||
|
LockPositionY: false
|
||||||
|
LockPositionZ: false
|
||||||
|
LockRotationX: true
|
||||||
|
LockRotationY: false
|
||||||
|
LockRotationZ: true
|
||||||
|
MeshColliderComponent:
|
||||||
|
IsConvex: true
|
||||||
|
IsTrigger: false
|
||||||
|
OverrideMesh: false
|
||||||
|
Material: 0
|
||||||
|
MaterialPath: ""
|
||||||
|
- Entity: 10732070446010033158
|
||||||
|
Parent: 0
|
||||||
|
Children:
|
||||||
|
[]
|
||||||
|
TagComponent:
|
||||||
|
Tag: Cube
|
||||||
|
TransformComponent:
|
||||||
|
Position: [0, -2.6466873, 0]
|
||||||
|
Rotation: [0, 0, 0]
|
||||||
|
Scale: [100, 1, 100]
|
||||||
|
MeshComponent:
|
||||||
|
AssetID: 18328012085543462741
|
||||||
|
AssetPath: assets/meshes/Default/Cube.fbx
|
||||||
|
RigidBodyComponent:
|
||||||
|
BodyType: 0
|
||||||
|
Mass: 1
|
||||||
|
LinearDrag: 0
|
||||||
|
AngularDrag: 0.05
|
||||||
|
DisableGravity: false
|
||||||
|
IsKinematic: false
|
||||||
|
Layer: 0
|
||||||
|
Constraints:
|
||||||
|
LockPositionX: false
|
||||||
|
LockPositionY: false
|
||||||
|
LockPositionZ: false
|
||||||
|
LockRotationX: false
|
||||||
|
LockRotationY: false
|
||||||
|
LockRotationZ: false
|
||||||
|
BoxColliderComponent:
|
||||||
|
Offset: [0, 0, 0]
|
||||||
|
Size: [2, 2, 2]
|
||||||
|
IsTrigger: false
|
||||||
|
Material: 0
|
||||||
|
MaterialPath: ""
|
||||||
|
- Entity: 5099152432245948441
|
||||||
|
Parent: 0
|
||||||
|
Children:
|
||||||
|
[]
|
||||||
|
TagComponent:
|
||||||
|
Tag: venice_dawn_1_4k
|
||||||
|
TransformComponent:
|
||||||
|
Position: [0, 0, 0]
|
||||||
|
Rotation: [0, 0, 0]
|
||||||
|
Scale: [1, 1, 1]
|
||||||
|
SkyLightComponent:
|
||||||
|
EnvironmentMap: 5211537204242875091
|
||||||
|
EnvironmentAssetPath: assets/env/venice_dawn_1_4k.hdr
|
||||||
|
Intensity: 1
|
||||||
|
Angle: 0
|
||||||
|
DynamicSky: false
|
||||||
|
TurbidityAzimuthInclination: [2, 0, 0]
|
||||||
|
PhysicsLayers:
|
||||||
|
[]
|
||||||
@ -1,11 +1,50 @@
|
|||||||
Scene: Scene Name
|
Scene: Scene Name
|
||||||
Environment:
|
Environment:
|
||||||
AssetHandle: 10549690553241162923
|
AssetHandle: 6095149963749185931
|
||||||
Light:
|
|
||||||
Direction: [-0.314, -0.941, -0.209]
|
|
||||||
Radiance: [0, 0, 0]
|
|
||||||
Multiplier: 1
|
|
||||||
Entities:
|
Entities:
|
||||||
|
- Entity: 6421668200759325475
|
||||||
|
Parent: 0
|
||||||
|
Children:
|
||||||
|
[]
|
||||||
|
TagComponent:
|
||||||
|
Tag: M1911Materials
|
||||||
|
TransformComponent:
|
||||||
|
Position: [0, 3.159583, 0]
|
||||||
|
Rotation: [0, 0, 0]
|
||||||
|
Scale: [1, 1, 1]
|
||||||
|
MeshComponent:
|
||||||
|
AssetID: 7219694555758922702
|
||||||
|
AssetPath: assets/models/m1911/M1911Materials.fbx
|
||||||
|
- Entity: 16992665426857995732
|
||||||
|
Parent: 0
|
||||||
|
Children:
|
||||||
|
[]
|
||||||
|
TagComponent:
|
||||||
|
Tag: Cube
|
||||||
|
TransformComponent:
|
||||||
|
Position: [0, 0, 0]
|
||||||
|
Rotation: [0, 0, 0]
|
||||||
|
Scale: [50, 1, 50]
|
||||||
|
MeshComponent:
|
||||||
|
AssetID: 18328012085543462741
|
||||||
|
AssetPath: assets/meshes/Default/Cube.fbx
|
||||||
|
- Entity: 18182275256052989728
|
||||||
|
Parent: 0
|
||||||
|
Children:
|
||||||
|
[]
|
||||||
|
TagComponent:
|
||||||
|
Tag: Sky Light
|
||||||
|
TransformComponent:
|
||||||
|
Position: [0, 0, 0]
|
||||||
|
Rotation: [0, 0, 0]
|
||||||
|
Scale: [1, 1, 1]
|
||||||
|
SkyLightComponent:
|
||||||
|
EnvironmentMap: 6095149963749185931
|
||||||
|
EnvironmentAssetPath: ""
|
||||||
|
Intensity: 1
|
||||||
|
Angle: 0
|
||||||
|
DynamicSky: true
|
||||||
|
TurbidityAzimuthInclination: [2, 0.15, 0.71]
|
||||||
- Entity: 17803125207910630398
|
- Entity: 17803125207910630398
|
||||||
Parent: 0
|
Parent: 0
|
||||||
Children:
|
Children:
|
||||||
@ -20,30 +59,6 @@ Entities:
|
|||||||
Radiance: [1, 1, 1]
|
Radiance: [1, 1, 1]
|
||||||
CastShadows: true
|
CastShadows: true
|
||||||
SoftShadows: true
|
SoftShadows: true
|
||||||
LightSize: 0.5
|
LightSize: 0.9
|
||||||
- Entity: 4315886439647742331
|
|
||||||
Parent: 0
|
|
||||||
Children:
|
|
||||||
[]
|
|
||||||
TagComponent:
|
|
||||||
Tag: Cube
|
|
||||||
TransformComponent:
|
|
||||||
Position: [0, 2.048974, 0]
|
|
||||||
Rotation: [0, 0, 0]
|
|
||||||
Scale: [1, 1, 1]
|
|
||||||
MeshComponent:
|
|
||||||
AssetID: 3580169978473467053
|
|
||||||
- Entity: 16992665426857995732
|
|
||||||
Parent: 0
|
|
||||||
Children:
|
|
||||||
[]
|
|
||||||
TagComponent:
|
|
||||||
Tag: Cube
|
|
||||||
TransformComponent:
|
|
||||||
Position: [0, 0, 0]
|
|
||||||
Rotation: [0, 0, 0]
|
|
||||||
Scale: [50, 1, 50]
|
|
||||||
MeshComponent:
|
|
||||||
AssetID: 3580169978473467053
|
|
||||||
PhysicsLayers:
|
PhysicsLayers:
|
||||||
[]
|
[]
|
||||||
@ -1,12 +1,21 @@
|
|||||||
Scene: Scene Name
|
Scene: Scene Name
|
||||||
Environment:
|
Environment:
|
||||||
AssetHandle: 17073147362577408906
|
AssetHandle: 5211537204242875091
|
||||||
Light:
|
|
||||||
Direction: [-0.314, -0.941, -0.209]
|
|
||||||
Radiance: [0, 0, 0]
|
|
||||||
Multiplier: 1
|
|
||||||
Entities:
|
Entities:
|
||||||
- Entity: 3696833073589069488
|
- Entity: 15706224176559717512
|
||||||
|
Parent: 0
|
||||||
|
Children:
|
||||||
|
[]
|
||||||
|
TagComponent:
|
||||||
|
Tag: Cube
|
||||||
|
TransformComponent:
|
||||||
|
Position: [0, 0, 0]
|
||||||
|
Rotation: [0, 0, 0]
|
||||||
|
Scale: [1, 1, 1]
|
||||||
|
MeshComponent:
|
||||||
|
AssetID: 18328012085543462741
|
||||||
|
AssetPath: assets/meshes/Default/Cube.fbx
|
||||||
|
- Entity: 8041206185299282567
|
||||||
Parent: 0
|
Parent: 0
|
||||||
Children:
|
Children:
|
||||||
[]
|
[]
|
||||||
@ -17,8 +26,11 @@ Entities:
|
|||||||
Rotation: [0, 0, 0]
|
Rotation: [0, 0, 0]
|
||||||
Scale: [1, 1, 1]
|
Scale: [1, 1, 1]
|
||||||
SkyLightComponent:
|
SkyLightComponent:
|
||||||
EnvironmentMap: 17073147362577408906
|
EnvironmentMap: 5211537204242875091
|
||||||
|
EnvironmentAssetPath: assets/env/venice_dawn_1_4k.hdr
|
||||||
Intensity: 1
|
Intensity: 1
|
||||||
Angle: 0
|
Angle: 0
|
||||||
|
DynamicSky: false
|
||||||
|
TurbidityAzimuthInclination: [2, 0, 0]
|
||||||
PhysicsLayers:
|
PhysicsLayers:
|
||||||
[]
|
[]
|
||||||
@ -24,16 +24,16 @@ uniform sampler2D u_Texture;
|
|||||||
uniform bool u_Horizontal; // 未使用,可保留或移除
|
uniform bool u_Horizontal; // 未使用,可保留或移除
|
||||||
uniform bool u_FirstPass; // 是否进行阈值处理
|
uniform bool u_FirstPass; // 是否进行阈值处理
|
||||||
uniform float u_Threshold; // 亮度阈值
|
uniform float u_Threshold; // 亮度阈值
|
||||||
uniform int u_Quality;
|
|
||||||
uniform float u_Directions; // 模糊方向数
|
|
||||||
uniform float u_Size; // 模糊半径
|
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
float Pi = 6.28318530718; // 2*PI
|
float Pi = 6.28318530718; // 2*PI
|
||||||
|
|
||||||
|
float Directions = 32.0; // 模糊方向数
|
||||||
|
float Quality = 6.0; // 每个方向上的采样质量(采样次数)
|
||||||
|
float Size = 16.0; // 模糊半径
|
||||||
|
|
||||||
vec2 Radius = u_Size / textureSize(u_Texture, 0);
|
vec2 Radius = Size / textureSize(u_Texture, 0);
|
||||||
|
|
||||||
// 中心像素采样
|
// 中心像素采样
|
||||||
vec3 centerColor = texture(u_Texture, v_TexCoord).rgb;
|
vec3 centerColor = texture(u_Texture, v_TexCoord).rgb;
|
||||||
@ -50,9 +50,9 @@ void main()
|
|||||||
float totalSamples = 1.0; // 有效采样计数(中心像素已计入)
|
float totalSamples = 1.0; // 有效采样计数(中心像素已计入)
|
||||||
|
|
||||||
// 周围像素采样
|
// 周围像素采样
|
||||||
for (float d = 0.0; d < Pi; d += Pi / u_Directions)
|
for (float d = 0.0; d < Pi; d += Pi / Directions)
|
||||||
{
|
{
|
||||||
for (float i = 1.0 / u_Quality; i <= 1.0; i += 1.0 / u_Quality)
|
for (float i = 1.0 / Quality; i <= 1.0; i += 1.0 / Quality)
|
||||||
{
|
{
|
||||||
vec2 offset = vec2(cos(d), sin(d)) * Radius * i;
|
vec2 offset = vec2(cos(d), sin(d)) * Radius * i;
|
||||||
vec3 sampleColor = texture(u_Texture, v_TexCoord + offset).rgb;
|
vec3 sampleColor = texture(u_Texture, v_TexCoord + offset).rgb;
|
||||||
|
|||||||
@ -1,348 +0,0 @@
|
|||||||
#type vertex
|
|
||||||
#version 430 core
|
|
||||||
|
|
||||||
layout(location = 0) in vec3 a_Position;
|
|
||||||
layout(location = 1) in vec2 a_TexCoord;
|
|
||||||
|
|
||||||
out vec2 v_TexCoord;
|
|
||||||
|
|
||||||
void main()
|
|
||||||
{
|
|
||||||
v_TexCoord = a_TexCoord;
|
|
||||||
gl_Position = vec4(a_Position.xy, 0.0, 1.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#type fragment
|
|
||||||
#version 430 core
|
|
||||||
|
|
||||||
// ==================== 输入 ====================
|
|
||||||
in vec2 v_TexCoord;
|
|
||||||
|
|
||||||
// G-buffer 纹理
|
|
||||||
uniform sampler2D u_AlbedoMetallic; // RGB: albedo, A: metallic
|
|
||||||
uniform sampler2D u_NormalRoughness; // RGB: normal (encoded), A: roughness
|
|
||||||
uniform sampler2D u_EmissiveAO; // RGB: emissive, A: AO
|
|
||||||
uniform sampler2D u_Depth; // depth
|
|
||||||
|
|
||||||
// 相机参数
|
|
||||||
uniform mat4 u_InvViewProj; // 逆视图投影矩阵,用于重建世界坐标
|
|
||||||
uniform vec3 u_CameraPosition;
|
|
||||||
|
|
||||||
// 光源结构体(与你的PBR着色器一致)
|
|
||||||
struct DirectionalLight {
|
|
||||||
vec3 Direction;
|
|
||||||
vec3 Radiance;
|
|
||||||
float Intensity;
|
|
||||||
bool CastShadows;
|
|
||||||
};
|
|
||||||
struct PointLight {
|
|
||||||
vec3 Position;
|
|
||||||
vec3 Radiance;
|
|
||||||
float Intensity;
|
|
||||||
float Range;
|
|
||||||
bool CastShadows;
|
|
||||||
};
|
|
||||||
struct SpotLight {
|
|
||||||
vec3 Position;
|
|
||||||
vec3 Direction;
|
|
||||||
vec3 Radiance;
|
|
||||||
float Intensity;
|
|
||||||
float Range;
|
|
||||||
float InnerConeCos;
|
|
||||||
float OuterConeCos;
|
|
||||||
bool CastShadows;
|
|
||||||
};
|
|
||||||
|
|
||||||
uniform DirectionalLight u_DirectionalLights; // 仅一个方向光
|
|
||||||
uniform int u_PointLightCount;
|
|
||||||
uniform PointLight u_PointLights[16]; // 假设最多16个点光源
|
|
||||||
uniform int u_SpotLightCount;
|
|
||||||
uniform SpotLight u_SpotLights[16]; // 最多16个聚光源
|
|
||||||
|
|
||||||
// IBL 相关
|
|
||||||
uniform samplerCube u_EnvRadianceTex;
|
|
||||||
uniform samplerCube u_EnvIrradianceTex;
|
|
||||||
uniform sampler2D u_BRDFLUTTexture;
|
|
||||||
uniform float u_IBLContribution;
|
|
||||||
uniform float u_EnvMapRotation;
|
|
||||||
|
|
||||||
// 阴影相关
|
|
||||||
uniform sampler2D u_ShadowMap;
|
|
||||||
uniform float u_ShadowBias;
|
|
||||||
uniform float u_ShadowSoftness;
|
|
||||||
uniform int u_ShadowEnabled;
|
|
||||||
uniform float u_ShadowIntensity; // 阴影强度(0-1)
|
|
||||||
uniform mat4 u_LightSpaceMatrix; // 方向光光源空间矩阵
|
|
||||||
|
|
||||||
// 天空盒(可选)
|
|
||||||
uniform samplerCube u_Skybox; // 如果深度为1.0则采样天空盒
|
|
||||||
uniform float u_SkyIntensity;
|
|
||||||
uniform float u_SkyTextureLod;
|
|
||||||
|
|
||||||
// 输出
|
|
||||||
layout(location = 0) out vec4 o_Color;
|
|
||||||
|
|
||||||
// ==================== 常量 ====================
|
|
||||||
const float PI = 3.14159265359;
|
|
||||||
const float Epsilon = 0.00001;
|
|
||||||
const vec3 Fdielectric = vec3(0.04);
|
|
||||||
|
|
||||||
|
|
||||||
// ==================== 工具函数 ====================
|
|
||||||
// 从深度重建世界坐标
|
|
||||||
vec3 worldPosFromDepth(vec2 uv, float depth) {
|
|
||||||
vec4 clipPos = vec4(uv * 2.0 - 1.0, depth * 2.0 - 1.0, 1.0);
|
|
||||||
vec4 worldPos = u_InvViewProj * clipPos;
|
|
||||||
return worldPos.xyz / worldPos.w;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 从深度重建世界空间方向(用于天空盒采样)
|
|
||||||
vec3 worldDirFromUV(vec2 uv) {
|
|
||||||
// 假设深度为1.0时,得到远平面方向
|
|
||||||
vec4 clipPos = vec4(uv * 2.0 - 1.0, 1.0, 1.0);
|
|
||||||
vec4 worldPos = u_InvViewProj * clipPos;
|
|
||||||
return normalize(worldPos.xyz / worldPos.w);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 旋转向量(绕Y轴)
|
|
||||||
vec3 RotateVectorAboutY(float angle, vec3 vec) {
|
|
||||||
angle = radians(angle);
|
|
||||||
mat3 rotationMatrix = mat3(
|
|
||||||
vec3(cos(angle), 0.0, sin(angle)),
|
|
||||||
vec3(0.0, 1.0, 0.0),
|
|
||||||
vec3(-sin(angle), 0.0, cos(angle))
|
|
||||||
);
|
|
||||||
return rotationMatrix * vec;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ==================== PBR 函数(复用你的代码) ====================
|
|
||||||
float ndfGGX(float cosLh, float roughness) {
|
|
||||||
float alpha = roughness * roughness;
|
|
||||||
float alphaSq = alpha * alpha;
|
|
||||||
float denom = (cosLh * cosLh) * (alphaSq - 1.0) + 1.0;
|
|
||||||
return alphaSq / (PI * denom * denom);
|
|
||||||
}
|
|
||||||
|
|
||||||
float GeometrySchlickGGX(float NdotV, float roughness) {
|
|
||||||
float r = (roughness + 1.0);
|
|
||||||
float k = (r * r) / 8.0;
|
|
||||||
float nom = NdotV;
|
|
||||||
float denom = NdotV * (1.0 - k) + k;
|
|
||||||
return nom / denom;
|
|
||||||
}
|
|
||||||
|
|
||||||
float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness) {
|
|
||||||
float NdotV = max(dot(N, V), 0.0);
|
|
||||||
float NdotL = max(dot(N, L), 0.0);
|
|
||||||
float ggx2 = GeometrySchlickGGX(NdotV, roughness);
|
|
||||||
float ggx1 = GeometrySchlickGGX(NdotL, roughness);
|
|
||||||
return ggx1 * ggx2;
|
|
||||||
}
|
|
||||||
|
|
||||||
vec3 fresnelSchlick(vec3 F0, float cosTheta) {
|
|
||||||
return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
vec3 fresnelSchlickRoughness(vec3 F0, float cosTheta, float roughness) {
|
|
||||||
return F0 + (max(vec3(1.0 - roughness), F0) - F0) * pow(1.0 - cosTheta, 5.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------- 方向光 ----------
|
|
||||||
vec3 ComputeDirectionalLight(DirectionalLight light, vec3 F0, vec3 N, vec3 V, float NdotV, vec3 albedo, float roughness, float metallic) {
|
|
||||||
vec3 L = normalize(-light.Direction);
|
|
||||||
vec3 Lradiance = light.Radiance * light.Intensity;
|
|
||||||
|
|
||||||
vec3 Lh = normalize(L + V);
|
|
||||||
float cosLi = max(dot(N, L), 0.0);
|
|
||||||
float cosLh = max(dot(N, Lh), 0.0);
|
|
||||||
|
|
||||||
vec3 F = fresnelSchlick(F0, max(dot(Lh, V), 0.0));
|
|
||||||
float D = ndfGGX(cosLh, roughness);
|
|
||||||
float G = GeometrySmith(N, V, L, roughness);
|
|
||||||
|
|
||||||
vec3 kd = (1.0 - F) * (1.0 - metallic);
|
|
||||||
vec3 diffuseBRDF = kd * albedo;
|
|
||||||
vec3 specularBRDF = (F * D * G) / max(Epsilon, 4.0 * cosLi * NdotV);
|
|
||||||
|
|
||||||
return (diffuseBRDF + specularBRDF) * Lradiance * cosLi;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------- 点光源 ----------
|
|
||||||
vec3 ComputePointLight(PointLight light, vec3 F0, vec3 N, vec3 V, float NdotV, vec3 albedo, float roughness, float metallic, vec3 worldPos) {
|
|
||||||
vec3 lightVec = light.Position - worldPos;
|
|
||||||
float dist = length(lightVec);
|
|
||||||
if (dist > light.Range) return vec3(0.0);
|
|
||||||
|
|
||||||
vec3 L = lightVec / dist;
|
|
||||||
vec3 Lradiance = light.Radiance * light.Intensity;
|
|
||||||
|
|
||||||
float attenuation = 1.0 / (dist * dist + 0.0001);
|
|
||||||
float rangeFactor = clamp(1.0 - (dist / light.Range), 0.0, 1.0);
|
|
||||||
rangeFactor = rangeFactor * rangeFactor;
|
|
||||||
attenuation *= rangeFactor;
|
|
||||||
|
|
||||||
vec3 Lh = normalize(L + V);
|
|
||||||
float cosLi = max(dot(N, L), 0.0);
|
|
||||||
float cosLh = max(dot(N, Lh), 0.0);
|
|
||||||
|
|
||||||
vec3 F = fresnelSchlick(F0, max(dot(Lh, V), 0.0));
|
|
||||||
float D = ndfGGX(cosLh, roughness);
|
|
||||||
float G = GeometrySmith(N, V, L, roughness);
|
|
||||||
|
|
||||||
vec3 kd = (1.0 - F) * (1.0 - metallic);
|
|
||||||
vec3 diffuseBRDF = kd * albedo;
|
|
||||||
vec3 specularBRDF = (F * D * G) / max(Epsilon, 4.0 * cosLi * NdotV);
|
|
||||||
|
|
||||||
return (diffuseBRDF + specularBRDF) * Lradiance * cosLi * attenuation;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------- 聚光源 ----------
|
|
||||||
vec3 ComputeSpotLight(SpotLight light, vec3 F0, vec3 N, vec3 V, float NdotV, vec3 albedo, float roughness, float metallic, vec3 worldPos) {
|
|
||||||
vec3 lightVec = light.Position - worldPos;
|
|
||||||
float dist = length(lightVec);
|
|
||||||
if (dist > light.Range) return vec3(0.0);
|
|
||||||
|
|
||||||
vec3 L = lightVec / dist;
|
|
||||||
vec3 Lradiance = light.Radiance * light.Intensity;
|
|
||||||
|
|
||||||
float attenuation = 1.0 / (dist * dist + 0.0001);
|
|
||||||
float rangeFactor = clamp(1.0 - (dist / light.Range), 0.0, 1.0);
|
|
||||||
rangeFactor = rangeFactor * rangeFactor;
|
|
||||||
attenuation *= rangeFactor;
|
|
||||||
|
|
||||||
float cosAngle = dot(-L, normalize(light.Direction));
|
|
||||||
if (cosAngle < light.OuterConeCos) return vec3(0.0);
|
|
||||||
float angleFalloff = (cosAngle - light.OuterConeCos) / (light.InnerConeCos - light.OuterConeCos);
|
|
||||||
angleFalloff = clamp(angleFalloff, 0.0, 1.0);
|
|
||||||
attenuation *= angleFalloff;
|
|
||||||
|
|
||||||
vec3 Lh = normalize(L + V);
|
|
||||||
float cosLi = max(dot(N, L), 0.0);
|
|
||||||
float cosLh = max(dot(N, Lh), 0.0);
|
|
||||||
|
|
||||||
vec3 F = fresnelSchlick(F0, max(dot(Lh, V), 0.0));
|
|
||||||
float D = ndfGGX(cosLh, roughness);
|
|
||||||
float G = GeometrySmith(N, V, L, roughness);
|
|
||||||
|
|
||||||
vec3 kd = (1.0 - F) * (1.0 - metallic);
|
|
||||||
vec3 diffuseBRDF = kd * albedo;
|
|
||||||
vec3 specularBRDF = (F * D * G) / max(Epsilon, 4.0 * cosLi * NdotV);
|
|
||||||
|
|
||||||
return (diffuseBRDF + specularBRDF) * Lradiance * cosLi * attenuation;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------- IBL ----------
|
|
||||||
vec3 IBL(vec3 F0, vec3 N, vec3 V, float NdotV, float roughness, float metallic, vec3 albedo) {
|
|
||||||
vec3 irradiance = texture(u_EnvIrradianceTex, N).rgb;
|
|
||||||
vec3 F = fresnelSchlickRoughness(F0, NdotV, roughness);
|
|
||||||
vec3 kd = (1.0 - F) * (1.0 - metallic);
|
|
||||||
vec3 diffuseIBL = albedo * irradiance;
|
|
||||||
|
|
||||||
vec3 R = 2.0 * NdotV * N - V; // 反射向量
|
|
||||||
int u_EnvRadianceTexLevels = textureQueryLevels(u_EnvRadianceTex);
|
|
||||||
vec3 specularIrradiance = textureLod(
|
|
||||||
u_EnvRadianceTex,
|
|
||||||
RotateVectorAboutY(u_EnvMapRotation, R),
|
|
||||||
roughness * u_EnvRadianceTexLevels
|
|
||||||
).rgb;
|
|
||||||
|
|
||||||
vec2 specularBRDF = texture(u_BRDFLUTTexture, vec2(NdotV, 1.0 - roughness)).rg;
|
|
||||||
vec3 specularIBL = specularIrradiance * (F * specularBRDF.x + specularBRDF.y);
|
|
||||||
|
|
||||||
return kd * diffuseIBL + specularIBL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------- 阴影 ----------
|
|
||||||
float calculateShadow(vec4 fragPosLightSpace, vec3 normal, vec3 lightDir) {
|
|
||||||
if (u_ShadowEnabled == 0) return 0.0;
|
|
||||||
|
|
||||||
vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w;
|
|
||||||
projCoords = projCoords * 0.5 + 0.5;
|
|
||||||
|
|
||||||
if (projCoords.z > 1.0 || projCoords.x < 0.0 || projCoords.x > 1.0 || projCoords.y < 0.0 || projCoords.y > 1.0)
|
|
||||||
return 0.0;
|
|
||||||
|
|
||||||
float closestDepth = texture(u_ShadowMap, projCoords.xy).r;
|
|
||||||
float currentDepth = projCoords.z;
|
|
||||||
|
|
||||||
float bias = max(u_ShadowBias * (1.0 - dot(normal, lightDir)), u_ShadowBias * 0.1);
|
|
||||||
|
|
||||||
float shadow = 0.0;
|
|
||||||
vec2 texelSize = 1.0 / textureSize(u_ShadowMap, 0);
|
|
||||||
int pcfRange = int(u_ShadowSoftness);
|
|
||||||
int sampleCount = 0;
|
|
||||||
|
|
||||||
for (int x = -pcfRange; x <= pcfRange; ++x) {
|
|
||||||
for (int y = -pcfRange; y <= pcfRange; ++y) {
|
|
||||||
float pcfDepth = texture(u_ShadowMap, projCoords.xy + vec2(x, y) * texelSize).r;
|
|
||||||
shadow += (currentDepth - bias > pcfDepth) ? 1.0 : 0.0;
|
|
||||||
sampleCount++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
shadow /= float(sampleCount);
|
|
||||||
|
|
||||||
return shadow * u_ShadowIntensity; // 应用阴影强度
|
|
||||||
}
|
|
||||||
|
|
||||||
// ==================== 主函数 ====================
|
|
||||||
void main() {
|
|
||||||
vec2 uv = v_TexCoord;
|
|
||||||
float depth = texture(u_Depth, uv).r;
|
|
||||||
|
|
||||||
if (depth >= 1.0) {
|
|
||||||
vec3 dir = worldDirFromUV(uv);
|
|
||||||
vec3 skyColor = textureLod(u_Skybox, dir, u_SkyTextureLod).rgb * u_SkyIntensity;
|
|
||||||
o_Color = vec4(skyColor, 1.0);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
vec4 albedoMetal = texture(u_AlbedoMetallic, uv);
|
|
||||||
vec4 normalRough = texture(u_NormalRoughness, uv);
|
|
||||||
vec4 emissiveAO = texture(u_EmissiveAO, uv);
|
|
||||||
|
|
||||||
vec3 albedo = albedoMetal.rgb;
|
|
||||||
float metallic = albedoMetal.a;
|
|
||||||
vec3 normal = normalRough.rgb * 2.0 - 1.0;
|
|
||||||
float roughness = normalRough.a;
|
|
||||||
vec3 emissive = emissiveAO.rgb;
|
|
||||||
float ao = emissiveAO.a;
|
|
||||||
|
|
||||||
vec3 worldPos = worldPosFromDepth(uv, depth);
|
|
||||||
vec3 V = normalize(u_CameraPosition - worldPos);
|
|
||||||
float NdotV = clamp(dot(normal, V), 0.0, 1.0);
|
|
||||||
|
|
||||||
vec3 F0 = mix(Fdielectric, albedo, metallic);
|
|
||||||
|
|
||||||
vec3 Lo = vec3(0.0);
|
|
||||||
|
|
||||||
// Direction Light
|
|
||||||
if (u_DirectionalLights.Intensity > 0.0) {
|
|
||||||
Lo += ComputeDirectionalLight(u_DirectionalLights, F0, normal, V, NdotV, albedo, roughness, metallic);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Point Light
|
|
||||||
for (int i = 0; i < u_PointLightCount; ++i) {
|
|
||||||
Lo += ComputePointLight(u_PointLights[i], F0, normal, V, NdotV, albedo, roughness, metallic, worldPos);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Spot light
|
|
||||||
for (int i = 0; i < u_SpotLightCount; ++i) {
|
|
||||||
Lo += ComputeSpotLight(u_SpotLights[i], F0, normal, V, NdotV, albedo, roughness, metallic, worldPos);
|
|
||||||
}
|
|
||||||
|
|
||||||
float shadowFactor = 1.0;
|
|
||||||
if (u_ShadowEnabled > 0 && u_DirectionalLights.CastShadows && u_DirectionalLights.Intensity > 0.0) {
|
|
||||||
vec4 fragPosLightSpace = u_LightSpaceMatrix * vec4(worldPos, 1.0);
|
|
||||||
float shadow = calculateShadow(fragPosLightSpace, normal, u_DirectionalLights.Direction);
|
|
||||||
shadowFactor = 1.0 - shadow;
|
|
||||||
}
|
|
||||||
Lo *= shadowFactor;
|
|
||||||
|
|
||||||
// 计算 IBL
|
|
||||||
vec3 ibl = IBL(F0, normal, V, NdotV, roughness, metallic, albedo) * u_IBLContribution;
|
|
||||||
|
|
||||||
vec3 finalColor = Lo + ibl + emissive;
|
|
||||||
|
|
||||||
o_Color = vec4(finalColor, 1.0);
|
|
||||||
}
|
|
||||||
@ -161,13 +161,6 @@ uniform float u_ShadowSoftness;
|
|||||||
uniform float u_ShadowIntensity;
|
uniform float u_ShadowIntensity;
|
||||||
uniform int u_ShadowEnabled;
|
uniform int u_ShadowEnabled;
|
||||||
|
|
||||||
// Emissive
|
|
||||||
uniform sampler2D u_EmissiveTexture;
|
|
||||||
uniform float u_EmissiveTexToggle;
|
|
||||||
uniform vec3 u_EmissiveColor;
|
|
||||||
uniform float u_EmissiveIntensity;
|
|
||||||
|
|
||||||
|
|
||||||
struct PBRParameters
|
struct PBRParameters
|
||||||
{
|
{
|
||||||
vec3 Albedo;
|
vec3 Albedo;
|
||||||
@ -432,16 +425,7 @@ float ComputeShadow(vec4 fragPosLightSpace, float NdotL)
|
|||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
float alpha = 1.0;
|
m_Params.Albedo = u_AlbedoTexToggle > 0.5 ? texture(u_AlbedoTexture, vs_Input.TexCoord).rgb : u_AlbedoColor;
|
||||||
if (u_AlbedoTexToggle > 0.5) {
|
|
||||||
vec4 albedoWithAlpha = texture(u_AlbedoTexture, vs_Input.TexCoord);
|
|
||||||
m_Params.Albedo = albedoWithAlpha.rgb;
|
|
||||||
alpha = albedoWithAlpha.a;
|
|
||||||
} else {
|
|
||||||
m_Params.Albedo = u_AlbedoColor;
|
|
||||||
alpha = 1.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_Params.Metalness = u_MetalnessTexToggle > 0.5 ? texture(u_MetalnessTexture, vs_Input.TexCoord).r : u_Metalness;
|
m_Params.Metalness = u_MetalnessTexToggle > 0.5 ? texture(u_MetalnessTexture, vs_Input.TexCoord).r : u_Metalness;
|
||||||
m_Params.Roughness = u_RoughnessTexToggle > 0.5 ? texture(u_RoughnessTexture, vs_Input.TexCoord).r : u_Roughness;
|
m_Params.Roughness = u_RoughnessTexToggle > 0.5 ? texture(u_RoughnessTexture, vs_Input.TexCoord).r : u_Roughness;
|
||||||
m_Params.Roughness = max(m_Params.Roughness, 0.05);
|
m_Params.Roughness = max(m_Params.Roughness, 0.05);
|
||||||
@ -479,16 +463,7 @@ void main()
|
|||||||
|
|
||||||
vec3 iblContribution = IBL(F0, Lr) * u_IBLContribution;
|
vec3 iblContribution = IBL(F0, Lr) * u_IBLContribution;
|
||||||
|
|
||||||
vec3 emissive = u_EmissiveColor;
|
color = vec4(lightContribution + iblContribution, 1.0);
|
||||||
if (u_EmissiveTexToggle > 0.5) {
|
|
||||||
emissive = texture(u_EmissiveTexture, vs_Input.TexCoord).rgb;
|
|
||||||
}
|
|
||||||
emissive *= u_EmissiveIntensity;
|
|
||||||
|
|
||||||
vec3 finalRGB = lightContribution + iblContribution + emissive;
|
|
||||||
vec4 finalColor = vec4(finalRGB, alpha);
|
|
||||||
|
|
||||||
color = finalColor;
|
|
||||||
|
|
||||||
// Bloom
|
// Bloom
|
||||||
float brightness = dot(color.rgb, vec3(0.2126, 0.7152, 0.0722));
|
float brightness = dot(color.rgb, vec3(0.2126, 0.7152, 0.0722));
|
||||||
|
|||||||
@ -55,12 +55,6 @@ void main()
|
|||||||
#type fragment
|
#type fragment
|
||||||
#version 430 core
|
#version 430 core
|
||||||
|
|
||||||
layout(location = 0) out vec4 outAlbedoMetal;
|
|
||||||
layout(location = 1) out vec4 outNormalRoughness;
|
|
||||||
layout(location = 2) out vec4 outEmissiveAO;
|
|
||||||
layout(location = 3) out vec4 outColor;
|
|
||||||
layout(location = 4) out vec4 outBloomColor;
|
|
||||||
|
|
||||||
const float PI = 3.141592;
|
const float PI = 3.141592;
|
||||||
const float Epsilon = 0.00001;
|
const float Epsilon = 0.00001;
|
||||||
|
|
||||||
@ -106,8 +100,8 @@ in VertexOutput
|
|||||||
vec4 FragPosLightSpace;
|
vec4 FragPosLightSpace;
|
||||||
} vs_Input;
|
} vs_Input;
|
||||||
|
|
||||||
|
layout(location = 0) out vec4 color;
|
||||||
uniform bool u_GBufferMode;
|
layout(location = 1) out vec4 o_BloomColor;
|
||||||
|
|
||||||
uniform DirectionalLight u_DirectionalLights;
|
uniform DirectionalLight u_DirectionalLights;
|
||||||
|
|
||||||
@ -155,12 +149,6 @@ uniform float u_ShadowSoftness;
|
|||||||
uniform float u_ShadowIntensity;
|
uniform float u_ShadowIntensity;
|
||||||
uniform int u_ShadowEnabled;
|
uniform int u_ShadowEnabled;
|
||||||
|
|
||||||
// Emissive
|
|
||||||
uniform sampler2D u_EmissiveTexture;
|
|
||||||
uniform float u_EmissiveTexToggle;
|
|
||||||
uniform vec3 u_EmissiveColor;
|
|
||||||
uniform float u_EmissiveIntensity;
|
|
||||||
|
|
||||||
struct PBRParameters
|
struct PBRParameters
|
||||||
{
|
{
|
||||||
vec3 Albedo;
|
vec3 Albedo;
|
||||||
@ -423,44 +411,19 @@ float ComputeShadow(vec4 fragPosLightSpace, float NdotL)
|
|||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
// === 1. 采样基础属性(所有模式都需要) ===
|
m_Params.Albedo = u_AlbedoTexToggle > 0.5 ? texture(u_AlbedoTexture, vs_Input.TexCoord).rgb : u_AlbedoColor;
|
||||||
vec4 albedoWithAlpha = texture(u_AlbedoTexture, vs_Input.TexCoord);
|
m_Params.Metalness = u_MetalnessTexToggle > 0.5 ? texture(u_MetalnessTexture, vs_Input.TexCoord).r : u_Metalness;
|
||||||
vec3 albedo = u_AlbedoTexToggle > 0.5 ? albedoWithAlpha.rgb : u_AlbedoColor;
|
m_Params.Roughness = u_RoughnessTexToggle > 0.5 ? texture(u_RoughnessTexture, vs_Input.TexCoord).r : u_Roughness;
|
||||||
float alpha = u_AlbedoTexToggle > 0.5 ? albedoWithAlpha.a : 1.0;
|
m_Params.Roughness = max(m_Params.Roughness, 0.05);
|
||||||
|
|
||||||
float metallic = u_MetalnessTexToggle > 0.5 ? texture(u_MetalnessTexture, vs_Input.TexCoord).r : u_Metalness;
|
// normal
|
||||||
float roughness = u_RoughnessTexToggle > 0.5 ? texture(u_RoughnessTexture, vs_Input.TexCoord).r : u_Roughness;
|
m_Params.Normal = normalize(vs_Input.Normal);
|
||||||
roughness = max(roughness, 0.05);
|
|
||||||
|
|
||||||
// === 2. 法线计算(世界空间) ===
|
|
||||||
vec3 normal = normalize(vs_Input.Normal);
|
|
||||||
if (u_NormalTexToggle > 0.5)
|
if (u_NormalTexToggle > 0.5)
|
||||||
{
|
{
|
||||||
vec3 tangentNormal = texture(u_NormalTexture, vs_Input.TexCoord).rgb * 2.0 - 1.0;
|
m_Params.Normal = normalize(2.0 * texture(u_NormalTexture, vs_Input.TexCoord).rgb - 1.0);
|
||||||
normal = normalize(vs_Input.WorldNormals * tangentNormal);
|
m_Params.Normal = normalize(vs_Input.WorldNormals * m_Params.Normal);
|
||||||
}
|
}
|
||||||
|
|
||||||
// === 3. 自发光计算 ===
|
|
||||||
vec3 emissive = u_EmissiveColor;
|
|
||||||
if (u_EmissiveTexToggle > 0.5)
|
|
||||||
emissive = texture(u_EmissiveTexture, vs_Input.TexCoord).rgb;
|
|
||||||
emissive *= u_EmissiveIntensity;
|
|
||||||
|
|
||||||
// === 4. GBuffer 模式:直接输出到多个目标 ===
|
|
||||||
if (u_GBufferMode)
|
|
||||||
{
|
|
||||||
outAlbedoMetal = vec4(albedo, metallic);
|
|
||||||
outNormalRoughness = vec4(normal * 0.5 + 0.5, roughness);
|
|
||||||
outEmissiveAO = vec4(emissive, 1.0); // AO 暂设为 1.0
|
|
||||||
return; // 提前结束
|
|
||||||
}
|
|
||||||
|
|
||||||
// === 5. 非 GBuffer 模式:继续 PBR 光照计算 ===
|
|
||||||
// 填充 PBRParameters
|
|
||||||
m_Params.Albedo = albedo;
|
|
||||||
m_Params.Metalness = metallic;
|
|
||||||
m_Params.Roughness = roughness;
|
|
||||||
m_Params.Normal = normal;
|
|
||||||
m_Params.View = normalize(u_CameraPosition - vs_Input.WorldPosition);
|
m_Params.View = normalize(u_CameraPosition - vs_Input.WorldPosition);
|
||||||
m_Params.NdotV = max(dot(m_Params.Normal, m_Params.View), 0.0);
|
m_Params.NdotV = max(dot(m_Params.Normal, m_Params.View), 0.0);
|
||||||
|
|
||||||
@ -486,12 +449,9 @@ void main()
|
|||||||
|
|
||||||
vec3 iblContribution = IBL(F0, Lr) * u_IBLContribution;
|
vec3 iblContribution = IBL(F0, Lr) * u_IBLContribution;
|
||||||
|
|
||||||
vec3 finalRGB = lightContribution + iblContribution + emissive;
|
color = vec4(lightContribution + iblContribution, 1.0);
|
||||||
vec4 finalColor = vec4(finalRGB, alpha);
|
|
||||||
|
|
||||||
outColor = finalColor;
|
|
||||||
|
|
||||||
// Bloom
|
// Bloom
|
||||||
float brightness = dot(finalColor.rgb, vec3(0.2126, 0.7152, 0.0722));
|
float brightness = dot(color.rgb, vec3(0.2126, 0.7152, 0.0722));
|
||||||
outBloomColor = brightness > u_BloomThreshold ? finalColor : vec4(0.0, 0.0, 0.0, 1.0);
|
o_BloomColor = brightness > u_BloomThreshold ? color : vec4(0.0, 0.0, 0.0, 1.0);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,11 +17,13 @@ void main()
|
|||||||
#version 430
|
#version 430
|
||||||
|
|
||||||
layout(location = 0) out vec4 o_Color;
|
layout(location = 0) out vec4 o_Color;
|
||||||
|
layout(location = 1) out vec4 o_BloomTexture;
|
||||||
|
|
||||||
in vec2 v_TexCoord;
|
in vec2 v_TexCoord;
|
||||||
|
|
||||||
uniform sampler2D u_HDRTexture; // 来自 LightingPass 的 HDR 颜色
|
uniform sampler2DMS u_Texture;
|
||||||
uniform sampler2D u_BloomTexture; // 来自 BloomBlendPass 的 Bloom 纹理
|
uniform sampler2D u_BloomTexture;
|
||||||
|
|
||||||
|
|
||||||
uniform bool u_EnableAutoExposure;
|
uniform bool u_EnableAutoExposure;
|
||||||
uniform float u_ManualExposure;
|
uniform float u_ManualExposure;
|
||||||
@ -30,36 +32,73 @@ layout(std430, binding = 2) buffer Exposure
|
|||||||
float u_Exposure;
|
float u_Exposure;
|
||||||
};
|
};
|
||||||
|
|
||||||
uniform bool u_EnableBloom;
|
uniform int u_TextureSamples;
|
||||||
|
|
||||||
const float gamma = 2.2;
|
uniform bool u_EnableBloom;
|
||||||
const float pureWhite = 1.0;
|
uniform float u_BloomThreshold;
|
||||||
|
|
||||||
|
const float uFar = 1.0;
|
||||||
|
|
||||||
|
vec4 SampleTexture(sampler2D tex, vec2 texCoord)
|
||||||
|
{
|
||||||
|
return texture(tex, texCoord);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 MultiSampleTexture(sampler2DMS tex, vec2 tc)
|
||||||
|
{
|
||||||
|
ivec2 texSize = textureSize(tex);
|
||||||
|
ivec2 texCoord = ivec2(tc * texSize);
|
||||||
|
vec4 result = vec4(0.0);
|
||||||
|
for (int i = 0; i < u_TextureSamples; i++)
|
||||||
|
result += texelFetch(tex, texCoord, i);
|
||||||
|
|
||||||
|
result /= float(u_TextureSamples);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
float MultiSampleDepth(sampler2DMS tex, vec2 tc)
|
||||||
|
{
|
||||||
|
ivec2 texSize = textureSize(tex);
|
||||||
|
ivec2 texCoord = ivec2(tc * texSize);
|
||||||
|
float result = 0.0;
|
||||||
|
for (int i = 0; i < u_TextureSamples; i++)
|
||||||
|
result += texelFetch(tex, texCoord, i).r;
|
||||||
|
result /= float(u_TextureSamples);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
// 采样 HDR 颜色(单样本)
|
const float gamma = 2.2;
|
||||||
vec3 color = texture(u_HDRTexture, v_TexCoord).rgb;
|
const float pureWhite = 1.0;
|
||||||
|
|
||||||
|
// Tonemapping
|
||||||
|
vec4 msColor = MultiSampleTexture(u_Texture, v_TexCoord);
|
||||||
|
vec3 color = msColor.rgb;
|
||||||
|
|
||||||
// 混合 Bloom(如果启用)
|
|
||||||
if (u_EnableBloom)
|
if (u_EnableBloom)
|
||||||
{
|
{
|
||||||
vec3 bloomColor = texture(u_BloomTexture, v_TexCoord).rgb;
|
vec3 bloomColor = texture(u_BloomTexture, v_TexCoord).rgb;
|
||||||
color += bloomColor; // 在 HDR 空间混合
|
color += bloomColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 应用曝光
|
if(u_EnableAutoExposure)
|
||||||
if (u_EnableAutoExposure)
|
color *= u_Exposure;
|
||||||
color *= u_Exposure;
|
|
||||||
else
|
else
|
||||||
color *= u_ManualExposure;
|
color *= u_ManualExposure;
|
||||||
|
|
||||||
// Reinhard 色调映射
|
// Reinhard tonemapping operator.
|
||||||
|
// see: "Photographic Tone Reproduction for Digital Images", eq. 4
|
||||||
float luminance = dot(color, vec3(0.2126, 0.7152, 0.0722));
|
float luminance = dot(color, vec3(0.2126, 0.7152, 0.0722));
|
||||||
float mappedLuminance = (luminance * (1.0 + luminance / (pureWhite * pureWhite))) / (1.0 + luminance);
|
float mappedLuminance = (luminance * (1.0 + luminance / (pureWhite * pureWhite))) / (1.0 + luminance);
|
||||||
|
|
||||||
// 按亮度比例缩放颜色
|
// Scale color by ratio of average luminances.
|
||||||
vec3 mappedColor = (mappedLuminance / luminance) * color;
|
vec3 mappedColor = (mappedLuminance / luminance) * color;
|
||||||
|
|
||||||
// Gamma 校正
|
// Gamma correction.
|
||||||
o_Color = vec4(pow(mappedColor, vec3(1.0 / gamma)), 1.0);
|
o_Color = vec4(pow(mappedColor, vec3(1.0 / gamma)), 1.0);
|
||||||
|
|
||||||
|
// Show over-exposed areas
|
||||||
|
// if (o_Color.r > 1.0 || o_Color.g > 1.0 || o_Color.b > 1.0)
|
||||||
|
// o_Color.rgb *= vec3(1.0, 0.25, 0.25);
|
||||||
}
|
}
|
||||||
@ -1,6 +1,6 @@
|
|||||||
[Window][DockSpace Demo]
|
[Window][DockSpace Demo]
|
||||||
Pos=0,0
|
Pos=0,0
|
||||||
Size=2560,1566
|
Size=1920,1080
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
|
|
||||||
[Window][Debug##Default]
|
[Window][Debug##Default]
|
||||||
@ -9,32 +9,32 @@ Size=400,400
|
|||||||
Collapsed=0
|
Collapsed=0
|
||||||
|
|
||||||
[Window][Scene Hierarchy]
|
[Window][Scene Hierarchy]
|
||||||
Pos=2089,24
|
Pos=1449,24
|
||||||
Size=471,563
|
Size=471,385
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000009,0
|
DockId=0x00000009,0
|
||||||
|
|
||||||
[Window][Properties]
|
[Window][Properties]
|
||||||
Pos=2089,589
|
Pos=1449,411
|
||||||
Size=471,977
|
Size=471,669
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x0000000A,0
|
DockId=0x0000000A,0
|
||||||
|
|
||||||
[Window][Scene Renderer]
|
[Window][Scene Renderer]
|
||||||
Pos=0,843
|
Pos=0,585
|
||||||
Size=481,723
|
Size=481,495
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000006,0
|
DockId=0x00000006,0
|
||||||
|
|
||||||
[Window][Materials]
|
[Window][Materials]
|
||||||
Pos=0,24
|
Pos=0,24
|
||||||
Size=481,817
|
Size=481,559
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000005,0
|
DockId=0x00000005,0
|
||||||
|
|
||||||
[Window][Script Engine Debug]
|
[Window][Script Engine Debug]
|
||||||
Pos=2089,589
|
Pos=1449,411
|
||||||
Size=471,977
|
Size=471,669
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x0000000A,2
|
DockId=0x0000000A,2
|
||||||
|
|
||||||
@ -52,25 +52,25 @@ DockId=0x00000001,0
|
|||||||
|
|
||||||
[Window][Viewport]
|
[Window][Viewport]
|
||||||
Pos=483,58
|
Pos=483,58
|
||||||
Size=1604,955
|
Size=964,647
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x0000000B,0
|
DockId=0x0000000B,0
|
||||||
|
|
||||||
[Window][Environment]
|
[Window][Environment]
|
||||||
Pos=2089,589
|
Pos=1449,411
|
||||||
Size=471,977
|
Size=471,669
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x0000000A,1
|
DockId=0x0000000A,1
|
||||||
|
|
||||||
[Window][Project]
|
[Window][Project]
|
||||||
Pos=483,1015
|
Pos=483,707
|
||||||
Size=1604,551
|
Size=964,373
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x0000000C,0
|
DockId=0x0000000C,0
|
||||||
|
|
||||||
[Window][Objects]
|
[Window][Objects]
|
||||||
Pos=483,1015
|
Pos=483,707
|
||||||
Size=1604,551
|
Size=964,373
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x0000000C,1
|
DockId=0x0000000C,1
|
||||||
|
|
||||||
@ -81,12 +81,18 @@ Collapsed=0
|
|||||||
|
|
||||||
[Window][##tool_bar]
|
[Window][##tool_bar]
|
||||||
Pos=483,24
|
Pos=483,24
|
||||||
Size=1604,32
|
Size=964,32
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000001,0
|
DockId=0x00000001,0
|
||||||
|
|
||||||
|
[Window][Console]
|
||||||
|
Pos=483,707
|
||||||
|
Size=964,373
|
||||||
|
Collapsed=0
|
||||||
|
DockId=0x0000000C,2
|
||||||
|
|
||||||
[Docking][Data]
|
[Docking][Data]
|
||||||
DockSpace ID=0xC0DFADC4 Window=0xD0388BC8 Pos=0,58 Size=2560,1542 Split=X Selected=0x0C01D6D5
|
DockSpace ID=0xC0DFADC4 Window=0xD0388BC8 Pos=268,189 Size=1920,1056 Split=X Selected=0x0C01D6D5
|
||||||
DockNode ID=0x00000007 Parent=0xC0DFADC4 SizeRef=1557,1542 Split=X
|
DockNode ID=0x00000007 Parent=0xC0DFADC4 SizeRef=1557,1542 Split=X
|
||||||
DockNode ID=0x00000003 Parent=0x00000007 SizeRef=481,1542 Split=Y Selected=0x5D711C2C
|
DockNode ID=0x00000003 Parent=0x00000007 SizeRef=481,1542 Split=Y Selected=0x5D711C2C
|
||||||
DockNode ID=0x00000005 Parent=0x00000003 SizeRef=481,817 Selected=0x5D711C2C
|
DockNode ID=0x00000005 Parent=0x00000003 SizeRef=481,817 Selected=0x5D711C2C
|
||||||
|
|||||||
@ -4,6 +4,7 @@
|
|||||||
<TargetFramework>net9.0</TargetFramework>
|
<TargetFramework>net9.0</TargetFramework>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
|
<InvariantGlobalization>true</InvariantGlobalization>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
using System.Runtime.InteropServices;
|
||||||
using Prism;
|
using Prism;
|
||||||
|
|
||||||
namespace FPSExample
|
namespace FPSExample
|
||||||
@ -8,6 +9,8 @@ namespace FPSExample
|
|||||||
public float RunSpeed = 20.0f;
|
public float RunSpeed = 20.0f;
|
||||||
public float JumpForce = 50.0f;
|
public float JumpForce = 50.0f;
|
||||||
|
|
||||||
|
public float m_Radius = 0.5f;
|
||||||
|
public float TorqueStrength = 10.0f;
|
||||||
|
|
||||||
[NonSerialized]
|
[NonSerialized]
|
||||||
public float MouseSensitivity = 10.0f;
|
public float MouseSensitivity = 10.0f;
|
||||||
@ -46,6 +49,9 @@ namespace FPSExample
|
|||||||
m_LastMousePosition = Input.GetMousePosition();
|
m_LastMousePosition = Input.GetMousePosition();
|
||||||
|
|
||||||
Input.SetCursorMode(Input.CursorMode.Locked);
|
Input.SetCursorMode(Input.CursorMode.Locked);
|
||||||
|
|
||||||
|
int size = Marshal.SizeOf<Transform>();
|
||||||
|
Console.WriteLine($"C# size of Transform: {size}");
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnUpdate(float ts)
|
void OnUpdate(float ts)
|
||||||
@ -65,14 +71,19 @@ namespace FPSExample
|
|||||||
UpdateCameraTransform();
|
UpdateCameraTransform();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OnPhysicsUpdate(float fixedTimeStep)
|
||||||
|
{
|
||||||
|
UpdateMovement();
|
||||||
|
}
|
||||||
|
|
||||||
private void UpdateRotation(float ts)
|
private void UpdateRotation(float ts)
|
||||||
{
|
{
|
||||||
Vec2 currentMousePosition = Input.GetMousePosition();
|
Vec2 currentMousePosition = Input.GetMousePosition();
|
||||||
Vec2 delta = m_LastMousePosition - currentMousePosition;
|
Vec2 delta = m_LastMousePosition - currentMousePosition;
|
||||||
|
|
||||||
float m_CurrentYMovement = delta.X * MouseSensitivity * ts;
|
m_CurrentYMovement = delta.X * MouseSensitivity * ts;
|
||||||
float xRotation = delta.Y * MouseSensitivity * ts;
|
float xRotation = delta.Y * MouseSensitivity * ts;
|
||||||
m_RigidBody.Rotate(new Vec3(0.0f, m_CurrentYMovement, 0.0f));
|
// m_RigidBody.Rotate(new Vec3(0.0f, m_CurrentYMovement, 0.0f));
|
||||||
|
|
||||||
if (delta.X != 0 || delta.Y != 0)
|
if (delta.X != 0 || delta.Y != 0)
|
||||||
{
|
{
|
||||||
@ -86,17 +97,25 @@ namespace FPSExample
|
|||||||
|
|
||||||
private void UpdateMovementInput()
|
private void UpdateMovementInput()
|
||||||
{
|
{
|
||||||
if (Input.IsKeyPressed(KeyCode.W))
|
if (Input.IsKeyPressed(KeyCode.W)){
|
||||||
m_MovementDirection.Y += 1.0f;
|
|
||||||
else if (Input.IsKeyPressed(KeyCode.S))
|
|
||||||
m_MovementDirection.Y -= 1.0f;
|
m_MovementDirection.Y -= 1.0f;
|
||||||
|
Debug.Log("KeyPressed: W");
|
||||||
|
}
|
||||||
|
else if (Input.IsKeyPressed(KeyCode.S)){
|
||||||
|
m_MovementDirection.Y += 1.0f;
|
||||||
|
Debug.Log("KeyPressed: S");
|
||||||
|
}
|
||||||
else
|
else
|
||||||
m_MovementDirection.Y = 0.0f;
|
m_MovementDirection.Y = 0.0f;
|
||||||
|
|
||||||
if(Input.IsKeyPressed(KeyCode.A))
|
if(Input.IsKeyPressed(KeyCode.A)){
|
||||||
m_MovementDirection.X -= 1.0f;
|
|
||||||
else if (Input.IsKeyPressed(KeyCode.D))
|
|
||||||
m_MovementDirection.X += 1.0f;
|
m_MovementDirection.X += 1.0f;
|
||||||
|
Debug.Log("KeyPressed: A");
|
||||||
|
}
|
||||||
|
else if (Input.IsKeyPressed(KeyCode.D)){
|
||||||
|
m_MovementDirection.X -= 1.0f;
|
||||||
|
Debug.Log("KeyPressed: D");
|
||||||
|
}
|
||||||
else
|
else
|
||||||
m_MovementDirection.X = 0.0f;
|
m_MovementDirection.X = 0.0f;
|
||||||
|
|
||||||
@ -132,26 +151,64 @@ namespace FPSExample
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnPhysicsUpdate(float fixedTimeStep)
|
|
||||||
{
|
|
||||||
UpdateMovement();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void UpdateMovement()
|
private void UpdateMovement()
|
||||||
{
|
{
|
||||||
m_RigidBody.Rotate(new Vec3(0.0f, m_CurrentYMovement, 0.0f));
|
// 2. 计算期望的移动方向(世界坐标系)
|
||||||
|
Vec3 desiredDirection = Vec3.Zero;
|
||||||
|
|
||||||
Vec3 movement = m_CameraTransform.Transform.Right * m_MovementDirection.X + m_CameraTransform.Transform.Forward * m_MovementDirection.Y;
|
|
||||||
if (m_MovementDirection.LengthSquared() != 0.0f)
|
if (m_MovementDirection.LengthSquared() != 0.0f)
|
||||||
{
|
{
|
||||||
|
Vec3 right = m_CameraTransform.Transform.Right;
|
||||||
|
Vec3 forward = m_CameraTransform.Transform.Forward;
|
||||||
|
right.Y = 0; forward.Y = 0;
|
||||||
|
right.Normalize(); forward.Normalize();
|
||||||
|
|
||||||
|
desiredDirection = right * m_MovementDirection.X + forward * m_MovementDirection.Y;
|
||||||
|
desiredDirection.Normalize();
|
||||||
|
|
||||||
|
/*
|
||||||
|
Vec3 movement = right * m_MovementDirection.X + forward * m_MovementDirection.Y;
|
||||||
movement.Normalize();
|
movement.Normalize();
|
||||||
Vec3 velocity = movement * m_CurrentSpeed;
|
Vec3 velocity = movement * m_CurrentSpeed;
|
||||||
velocity.Y = m_RigidBody.GetLinearVelocity().Y;
|
velocity.Y = m_RigidBody.GetLinearVelocity().Y;
|
||||||
m_RigidBody.SetLinearVelocity(velocity);
|
m_RigidBody.SetLinearVelocity(velocity);
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
Vec3 targetAngularVelocity = Vec3.Zero;
|
||||||
|
if (desiredDirection.LengthSquared() > 0.01f)
|
||||||
|
{
|
||||||
|
Vec3 up = Vec3.Up;
|
||||||
|
Vec3 rotationAxis = Vec3.Cross(desiredDirection, up).Normalized();
|
||||||
|
float angularSpeed = 2 * (m_CurrentSpeed / m_Radius);
|
||||||
|
targetAngularVelocity = rotationAxis * angularSpeed;
|
||||||
|
|
||||||
|
Vec3 currentAngular = m_RigidBody.GetAngularVelocity();
|
||||||
|
Vec3 angularDiff = targetAngularVelocity - currentAngular;
|
||||||
|
|
||||||
|
float inertia = 0.4f * m_RigidBody.Mass * m_Radius * m_Radius;
|
||||||
|
Vec3 torque = angularDiff * inertia * TorqueStrength;
|
||||||
|
m_RigidBody.AddTorque(torque, RigidBodyComponent.ForceMode.Force);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
// 3. 获取当前角速度,计算需要调整的差值
|
||||||
|
Vec3 currentAngular = m_RigidBody.GetAngularVelocity();
|
||||||
|
Vec3 angularDiff = targetAngularVelocity - currentAngular;
|
||||||
|
|
||||||
|
// 4. 施加扭矩:扭矩 = 转动惯量 * 角加速度
|
||||||
|
// 球体的转动惯量 I = (2/5) * m * r^2 (实心球)
|
||||||
|
float inertia = TorqueStrength * m_RigidBody.Mass * m_Radius * m_Radius;
|
||||||
|
// 设定一个系数控制响应速度(可调)
|
||||||
|
float torqueStrength = 5.0f;
|
||||||
|
Vec3 torque = angularDiff * inertia * torqueStrength;
|
||||||
|
m_RigidBody.AddTorque(-torque, RigidBodyComponent.ForceMode.Force);
|
||||||
|
*/
|
||||||
|
|
||||||
if (m_ShouldJump && m_Colliding)
|
if (m_ShouldJump && m_Colliding)
|
||||||
{
|
{
|
||||||
|
Debug.Log("Jump");
|
||||||
m_RigidBody.AddForce(Vec3.Up * JumpForce, RigidBodyComponent.ForceMode.Impulse);
|
m_RigidBody.AddForce(Vec3.Up * JumpForce, RigidBodyComponent.ForceMode.Impulse);
|
||||||
m_ShouldJump = false;
|
m_ShouldJump = false;
|
||||||
}
|
}
|
||||||
@ -159,7 +216,7 @@ namespace FPSExample
|
|||||||
|
|
||||||
private void UpdateCameraTransform(){
|
private void UpdateCameraTransform(){
|
||||||
Vec3 position = m_Transform.Translation + m_CameraTransform.Transform.Forward * CameraForwardOffset;
|
Vec3 position = m_Transform.Translation + m_CameraTransform.Transform.Forward * CameraForwardOffset;
|
||||||
position.Y += m_Transform.Translation.Y + CameraYOffset;
|
position.Y += CameraYOffset;
|
||||||
m_CameraTransform.Translation = position;
|
m_CameraTransform.Translation = position;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,6 +5,7 @@
|
|||||||
<RootNamespace>Prism_ScriptCore</RootNamespace>
|
<RootNamespace>Prism_ScriptCore</RootNamespace>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
|
<InvariantGlobalization>true</InvariantGlobalization>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
15
Prism-ScriptCore/Src/Prism/Engine/Engine.cs
Normal file
15
Prism-ScriptCore/Src/Prism/Engine/Engine.cs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
|
namespace Prism
|
||||||
|
{
|
||||||
|
public class Debug
|
||||||
|
{
|
||||||
|
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||||
|
private static extern void Log_Native(string message);
|
||||||
|
|
||||||
|
public static void Log(string message)
|
||||||
|
{
|
||||||
|
Log_Native(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -9,8 +9,8 @@ namespace Prism
|
|||||||
public Vec3 Rotation;
|
public Vec3 Rotation;
|
||||||
public Vec3 Scale;
|
public Vec3 Scale;
|
||||||
|
|
||||||
public Vec3 Up { get; }
|
public Vec3 Up;
|
||||||
public Vec3 Right { get; }
|
public Vec3 Right;
|
||||||
public Vec3 Forward { get; }
|
public Vec3 Forward;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -53,6 +53,15 @@ namespace Prism
|
|||||||
Z = vec.Z;
|
Z = vec.Z;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Vec3 Cross(Vec3 a, Vec3 b)
|
||||||
|
{
|
||||||
|
return new Vec3(
|
||||||
|
a.Y * b.Z - a.Z * b.Y,
|
||||||
|
a.Z * b.X - a.X * b.Z,
|
||||||
|
a.X * b.Y - a.Y * b.X
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
public void Clamp(Vec3 min, Vec3 max)
|
public void Clamp(Vec3 min, Vec3 max)
|
||||||
{
|
{
|
||||||
X = Mathf.Clamp(X, min.X, max.X);
|
X = Mathf.Clamp(X, min.X, max.X);
|
||||||
@ -60,6 +69,7 @@ namespace Prism
|
|||||||
Z = Mathf.Clamp(Z, min.Z, max.Z);
|
Z = Mathf.Clamp(Z, min.Z, max.Z);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public float LengthSquared()
|
public float LengthSquared()
|
||||||
{
|
{
|
||||||
return X * X + Y * Y + Z * Z;
|
return X * X + Y * Y + Z * Z;
|
||||||
|
|||||||
@ -197,7 +197,45 @@ set_target_properties(${SHARED_LIBRARY} PROPERTIES
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# static runtime library
|
||||||
|
set(RUNTIME_LIBRARY ${PROJECT_NAME}-Runtime)
|
||||||
|
|
||||||
|
add_library(${RUNTIME_LIBRARY} STATIC ${SRC_SOURCE})
|
||||||
|
|
||||||
|
target_compile_definitions(${RUNTIME_LIBRARY} PRIVATE
|
||||||
|
PRISM_RUNTIME
|
||||||
|
INTERFACE
|
||||||
|
PRISM_STATIC
|
||||||
|
)
|
||||||
|
|
||||||
|
target_include_directories(${RUNTIME_LIBRARY} PUBLIC
|
||||||
|
${TARGET_INCLUDE_DIR}
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_directories(${RUNTIME_LIBRARY} INTERFACE
|
||||||
|
${PHYSX_LIB_DIR}
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(${RUNTIME_LIBRARY}
|
||||||
|
PRIVATE
|
||||||
|
${LINK_LIBRARIES_PRIVATE}
|
||||||
|
PUBLIC
|
||||||
|
${LINK_LIBRARIES_PUBLIC}
|
||||||
|
)
|
||||||
|
target_precompile_headers(${RUNTIME_LIBRARY} PRIVATE
|
||||||
|
src/pmpch.h
|
||||||
|
)
|
||||||
|
|
||||||
|
set_target_properties(${RUNTIME_LIBRARY} PROPERTIES
|
||||||
|
OUTPUT_NAME ${PROJECT_NAME}
|
||||||
|
ARCHIVE_OUTPUT_NAME ${PROJECT_NAME}rd
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# alias
|
# alias
|
||||||
add_library(Prism::static ALIAS Prism-static)
|
add_library(Prism::static ALIAS Prism-static)
|
||||||
add_library(Prism::shared ALIAS Prism-shared)
|
add_library(Prism::shared ALIAS Prism-shared)
|
||||||
add_library(Prism ALIAS Prism-shared)
|
add_library(Prism ALIAS Prism-shared)
|
||||||
|
|
||||||
|
add_library(Prism::Runtime ALIAS Prism-Runtime)
|
||||||
|
|||||||
25
Prism/src/Prism/Asset/Asset.cpp
Normal file
25
Prism/src/Prism/Asset/Asset.cpp
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
//
|
||||||
|
// Created by Atdunbg on 2026/3/26.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "Asset.h"
|
||||||
|
#include "Prism/Renderer/Texture.h"
|
||||||
|
|
||||||
|
namespace Prism
|
||||||
|
{
|
||||||
|
PhysicsMaterialAsset::PhysicsMaterialAsset(): StaticFriction(0), DynamicFriction(0), Bounciness(0)
|
||||||
|
{
|
||||||
|
Type = AssetType::PhysicsMaterial;
|
||||||
|
}
|
||||||
|
|
||||||
|
PhysicsMaterialAsset::PhysicsMaterialAsset(const float staticFriction, const float dynamicFriction,
|
||||||
|
const float bounciness): StaticFriction(staticFriction), DynamicFriction(dynamicFriction), Bounciness(bounciness)
|
||||||
|
{
|
||||||
|
Type = AssetType::PhysicsMaterial;
|
||||||
|
}
|
||||||
|
|
||||||
|
PBRMaterialAsset::PBRMaterialAsset()
|
||||||
|
{
|
||||||
|
Type = AssetType::Material;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -5,14 +5,20 @@
|
|||||||
#ifndef PRISM_ASSET_H
|
#ifndef PRISM_ASSET_H
|
||||||
#define PRISM_ASSET_H
|
#define PRISM_ASSET_H
|
||||||
|
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
#include "Prism/Core/UUID.h"
|
#include "Prism/Core/UUID.h"
|
||||||
#include "Prism/Core/Ref.h"
|
#include "Prism/Core/Ref.h"
|
||||||
|
|
||||||
namespace Prism
|
namespace Prism
|
||||||
{
|
{
|
||||||
|
class Texture2D;
|
||||||
|
class Shader;
|
||||||
|
class MaterialInstance;
|
||||||
|
|
||||||
enum class AssetType
|
enum class AssetType
|
||||||
{
|
{
|
||||||
Scene = 0, Mesh, Texture, EnvMap, Audio, Script, PhysicsMaterial, Directory, Other, None
|
Scene = 0, Mesh, Texture, EnvMap, Audio, Script, Material, PhysicsMaterial, Directory, Other, None
|
||||||
};
|
};
|
||||||
|
|
||||||
using AssetHandle = UUID;
|
using AssetHandle = UUID;
|
||||||
@ -35,20 +41,17 @@ namespace Prism
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class PRISM_API PhysicsMaterial : public Asset
|
class PRISM_API PhysicsMaterialAsset : public Asset
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
float StaticFriction;
|
float StaticFriction;
|
||||||
float DynamicFriction;
|
float DynamicFriction;
|
||||||
float Bounciness;
|
float Bounciness;
|
||||||
|
|
||||||
PhysicsMaterial() = default;
|
PhysicsMaterialAsset();
|
||||||
|
|
||||||
|
PhysicsMaterialAsset(const float staticFriction, const float dynamicFriction, const float bounciness);
|
||||||
|
|
||||||
PhysicsMaterial(const float staticFriction, const float dynamicFriction, const float bounciness)
|
|
||||||
: StaticFriction(staticFriction), DynamicFriction(dynamicFriction), Bounciness(bounciness)
|
|
||||||
{
|
|
||||||
Type = AssetType::PhysicsMaterial;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Treating directories as assets simplifies the asset manager window rendering by a lot
|
// Treating directories as assets simplifies the asset manager window rendering by a lot
|
||||||
@ -63,6 +66,34 @@ namespace Prism
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class PBRMaterialAsset : public Asset
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PBRMaterialAsset();
|
||||||
|
virtual ~PBRMaterialAsset() = default;
|
||||||
|
// Albedo
|
||||||
|
glm::vec3 AlbedoColor = glm::vec3(1.0f);
|
||||||
|
float AlbedoTexToggle = 0.0f;
|
||||||
|
Ref<Texture2D> AlbedoTexture;
|
||||||
|
|
||||||
|
// Normal
|
||||||
|
float NormalTexToggle = 0.0f;
|
||||||
|
Ref<Texture2D> NormalTexture;
|
||||||
|
|
||||||
|
// Metalness
|
||||||
|
float Metalness = 0.8f;
|
||||||
|
float MetalnessTexToggle = 0.0f;
|
||||||
|
Ref<Texture2D> MetalnessTexture;
|
||||||
|
|
||||||
|
// Roughness
|
||||||
|
float Roughness = 0.1f;
|
||||||
|
float RoughnessTexToggle = 0.0f;
|
||||||
|
Ref<Texture2D> RoughnessTexture;
|
||||||
|
|
||||||
|
bool IsDirty = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif //PRISM_ASSET_H
|
#endif //PRISM_ASSET_H
|
||||||
|
|||||||
@ -12,6 +12,7 @@
|
|||||||
#include "Prism/Renderer/SceneRenderer.h"
|
#include "Prism/Renderer/SceneRenderer.h"
|
||||||
|
|
||||||
#include "yaml-cpp/yaml.h"
|
#include "yaml-cpp/yaml.h"
|
||||||
|
#include "Prism/Utilities/SerializeUtils.h"
|
||||||
|
|
||||||
namespace Prism
|
namespace Prism
|
||||||
{
|
{
|
||||||
@ -40,15 +41,114 @@ namespace Prism
|
|||||||
{
|
{
|
||||||
case Prism::AssetType::PhysicsMaterial:
|
case Prism::AssetType::PhysicsMaterial:
|
||||||
{
|
{
|
||||||
Ref<PhysicsMaterial> material = Ref<PhysicsMaterial>(asset);
|
Ref<PhysicsMaterialAsset> physicsMaterial = Ref<PhysicsMaterialAsset>(asset);
|
||||||
out << YAML::Key << "StaticFriction" << material->StaticFriction;
|
out << YAML::Key << "StaticFriction" << physicsMaterial->StaticFriction;
|
||||||
out << YAML::Key << "DynamicFriction" << material->DynamicFriction;
|
out << YAML::Key << "DynamicFriction" << physicsMaterial->DynamicFriction;
|
||||||
out << YAML::Key << "Bounciness" << material->Bounciness;
|
out << YAML::Key << "Bounciness" << physicsMaterial->Bounciness;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case AssetType::Material:
|
||||||
|
{
|
||||||
|
const auto& material = Ref<PBRMaterialAsset>(asset);
|
||||||
|
|
||||||
|
// Albedo
|
||||||
|
out << YAML::Key << "Albedo";
|
||||||
|
out << YAML::BeginMap;
|
||||||
|
{
|
||||||
|
out << YAML::Key << "Color" << YAML::Value << material->AlbedoColor;
|
||||||
|
out << YAML::Key << "TexToggle" << YAML::Value << material->AlbedoTexToggle;
|
||||||
|
|
||||||
|
out << YAML::Key << "Texture";
|
||||||
|
out << YAML::BeginMap;
|
||||||
|
if (material->AlbedoTexture)
|
||||||
|
{
|
||||||
|
out << YAML::Key << "AssetHandle" << YAML::Value << material->AlbedoTexture->Handle;
|
||||||
|
out << YAML::Key << "AssetPath" << YAML::Value << material->AlbedoTexture->FilePath;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
out << YAML::Key << "AssetHandle" << YAML::Value << 0;
|
||||||
|
out << YAML::Key << "AssetPath" << YAML::Value << "";
|
||||||
|
}
|
||||||
|
out << YAML::EndMap;
|
||||||
|
}
|
||||||
|
out << YAML::EndMap;
|
||||||
|
|
||||||
|
// Normal
|
||||||
|
out << YAML::Key << "Normal";
|
||||||
|
out << YAML::BeginMap;
|
||||||
|
{
|
||||||
|
out << YAML::Key << "TexToggle" << YAML::Value << material->NormalTexToggle;
|
||||||
|
|
||||||
|
out << YAML::Key << "Texture";
|
||||||
|
out << YAML::BeginMap;
|
||||||
|
if (material->NormalTexture)
|
||||||
|
{
|
||||||
|
out << YAML::Key << "AssetHandle" << YAML::Value << material->NormalTexture->Handle;
|
||||||
|
out << YAML::Key << "AssetPath" << YAML::Value << material->NormalTexture->FilePath;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
out << YAML::Key << "AssetHandle" << YAML::Value << 0;
|
||||||
|
out << YAML::Key << "AssetPath" << YAML::Value << "";
|
||||||
|
}
|
||||||
|
out << YAML::EndMap;
|
||||||
|
}
|
||||||
|
out << YAML::EndMap;
|
||||||
|
|
||||||
|
// Metalness
|
||||||
|
out << YAML::Key << "Metalness";
|
||||||
|
out << YAML::BeginMap;
|
||||||
|
{
|
||||||
|
out << YAML::Key << "Value" << YAML::Value << material->Metalness; // 金属度数值
|
||||||
|
out << YAML::Key << "TexToggle" << YAML::Value << material->MetalnessTexToggle;
|
||||||
|
|
||||||
|
out << YAML::Key << "Texture";
|
||||||
|
out << YAML::BeginMap;
|
||||||
|
if (material->MetalnessTexture)
|
||||||
|
{
|
||||||
|
out << YAML::Key << "AssetHandle" << YAML::Value << material->MetalnessTexture->Handle;
|
||||||
|
out << YAML::Key << "AssetPath" << YAML::Value << material->MetalnessTexture->FilePath;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
out << YAML::Key << "AssetHandle" << YAML::Value << 0;
|
||||||
|
out << YAML::Key << "AssetPath" << YAML::Value << "";
|
||||||
|
}
|
||||||
|
out << YAML::EndMap;
|
||||||
|
}
|
||||||
|
out << YAML::EndMap;
|
||||||
|
|
||||||
|
// Roughness
|
||||||
|
out << YAML::Key << "Roughness";
|
||||||
|
out << YAML::BeginMap;
|
||||||
|
{
|
||||||
|
out << YAML::Key << "Value" << YAML::Value << material->Roughness; // 粗糙度数值
|
||||||
|
out << YAML::Key << "TexToggle" << YAML::Value << material->RoughnessTexToggle;
|
||||||
|
|
||||||
|
out << YAML::Key << "Texture";
|
||||||
|
out << YAML::BeginMap;
|
||||||
|
if (material->RoughnessTexture)
|
||||||
|
{
|
||||||
|
out << YAML::Key << "AssetHandle" << YAML::Value << material->RoughnessTexture->Handle;
|
||||||
|
out << YAML::Key << "AssetPath" << YAML::Value << material->RoughnessTexture->FilePath;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
out << YAML::Key << "AssetHandle" << YAML::Value << 0;
|
||||||
|
out << YAML::Key << "AssetPath" << YAML::Value << "";
|
||||||
|
}
|
||||||
|
out << YAML::EndMap;
|
||||||
|
}
|
||||||
|
out << YAML::EndMap;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
out << YAML::EndMap;
|
out << YAML::EndMap;
|
||||||
|
|
||||||
|
PM_CORE_INFO("Save Asset change...");
|
||||||
std::ofstream fout(asset->FilePath);
|
std::ofstream fout(asset->FilePath);
|
||||||
fout << out.c_str();
|
fout << out.c_str();
|
||||||
}
|
}
|
||||||
@ -61,13 +161,125 @@ namespace Prism
|
|||||||
|
|
||||||
YAML::Node data = YAML::Load(strStream.str());
|
YAML::Node data = YAML::Load(strStream.str());
|
||||||
|
|
||||||
if (asset->Type == AssetType::PhysicsMaterial)
|
switch (asset->Type)
|
||||||
{
|
{
|
||||||
float staticFriction = data["StaticFriction"].as<float>();
|
case AssetType::PhysicsMaterial:
|
||||||
float dynamicFriction = data["DynamicFriction"].as<float>();
|
{
|
||||||
float bounciness = data["Bounciness"].as<float>();
|
float staticFriction = data["StaticFriction"].as<float>();
|
||||||
|
float dynamicFriction = data["DynamicFriction"].as<float>();
|
||||||
|
float bounciness = data["Bounciness"].as<float>();
|
||||||
|
|
||||||
return Ref<PhysicsMaterial>::Create(staticFriction, dynamicFriction, bounciness);
|
return Ref<PhysicsMaterialAsset>::Create(staticFriction, dynamicFriction, bounciness);
|
||||||
|
}
|
||||||
|
case AssetType::Material:
|
||||||
|
{
|
||||||
|
Ref<PBRMaterialAsset> material = Ref<PBRMaterialAsset>::Create();
|
||||||
|
|
||||||
|
// ==================== Albedo ====================
|
||||||
|
if (data["Albedo"])
|
||||||
|
{
|
||||||
|
auto albedoNode = data["Albedo"];
|
||||||
|
material->AlbedoColor = albedoNode["Color"].as<glm::vec3>();
|
||||||
|
material->AlbedoTexToggle = albedoNode["TexToggle"].as<float>();
|
||||||
|
|
||||||
|
if (albedoNode["Texture"])
|
||||||
|
{
|
||||||
|
auto texNode = albedoNode["Texture"];
|
||||||
|
UUID texHandle = 0;
|
||||||
|
std::string texPath;
|
||||||
|
if (texNode["AssetHandle"])
|
||||||
|
texHandle = texNode["AssetHandle"].as<uint64_t>();
|
||||||
|
if (texNode["AssetPath"])
|
||||||
|
texPath = texNode["AssetPath"].as<std::string>();
|
||||||
|
|
||||||
|
if (texHandle != 0 && AssetsManager::IsAssetHandleValid(texHandle))
|
||||||
|
material->AlbedoTexture = AssetsManager::GetAsset<Texture2D>(texHandle);
|
||||||
|
else if (!texPath.empty())
|
||||||
|
material->AlbedoTexture = Texture2D::Create(texPath);
|
||||||
|
else
|
||||||
|
material->AlbedoTexture = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== Normal ====================
|
||||||
|
if (data["Normal"])
|
||||||
|
{
|
||||||
|
auto normalNode = data["Normal"];
|
||||||
|
material->NormalTexToggle = normalNode["TexToggle"].as<float>();
|
||||||
|
|
||||||
|
if (normalNode["Texture"])
|
||||||
|
{
|
||||||
|
auto texNode = normalNode["Texture"];
|
||||||
|
UUID texHandle = 0;
|
||||||
|
std::string texPath;
|
||||||
|
if (texNode["AssetHandle"])
|
||||||
|
texHandle = texNode["AssetHandle"].as<uint64_t>();
|
||||||
|
if (texNode["AssetPath"])
|
||||||
|
texPath = texNode["AssetPath"].as<std::string>();
|
||||||
|
|
||||||
|
if (texHandle != 0 && AssetsManager::IsAssetHandleValid(texHandle))
|
||||||
|
material->NormalTexture = AssetsManager::GetAsset<Texture2D>(texHandle);
|
||||||
|
else if (!texPath.empty())
|
||||||
|
material->NormalTexture = Texture2D::Create(texPath);
|
||||||
|
else
|
||||||
|
material->NormalTexture = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== Metalness ====================
|
||||||
|
if (data["Metalness"])
|
||||||
|
{
|
||||||
|
auto metalNode = data["Metalness"];
|
||||||
|
material->Metalness = metalNode["Value"].as<float>();
|
||||||
|
material->MetalnessTexToggle = metalNode["TexToggle"].as<float>();
|
||||||
|
|
||||||
|
if (metalNode["Texture"])
|
||||||
|
{
|
||||||
|
auto texNode = metalNode["Texture"];
|
||||||
|
UUID texHandle = 0;
|
||||||
|
std::string texPath;
|
||||||
|
if (texNode["AssetHandle"])
|
||||||
|
texHandle = texNode["AssetHandle"].as<uint64_t>();
|
||||||
|
if (texNode["AssetPath"])
|
||||||
|
texPath = texNode["AssetPath"].as<std::string>();
|
||||||
|
|
||||||
|
if (texHandle != 0 && AssetsManager::IsAssetHandleValid(texHandle))
|
||||||
|
material->MetalnessTexture = AssetsManager::GetAsset<Texture2D>(texHandle);
|
||||||
|
else if (!texPath.empty())
|
||||||
|
material->MetalnessTexture = Texture2D::Create(texPath);
|
||||||
|
else
|
||||||
|
material->MetalnessTexture = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== Roughness ====================
|
||||||
|
if (data["Roughness"])
|
||||||
|
{
|
||||||
|
auto roughNode = data["Roughness"];
|
||||||
|
material->Roughness = roughNode["Value"].as<float>();
|
||||||
|
material->RoughnessTexToggle = roughNode["TexToggle"].as<float>();
|
||||||
|
|
||||||
|
if (roughNode["Texture"])
|
||||||
|
{
|
||||||
|
auto texNode = roughNode["Texture"];
|
||||||
|
UUID texHandle = 0;
|
||||||
|
std::string texPath;
|
||||||
|
if (texNode["AssetHandle"])
|
||||||
|
texHandle = texNode["AssetHandle"].as<uint64_t>();
|
||||||
|
if (texNode["AssetPath"])
|
||||||
|
texPath = texNode["AssetPath"].as<std::string>();
|
||||||
|
|
||||||
|
if (texHandle != 0 && AssetsManager::IsAssetHandleValid(texHandle))
|
||||||
|
material->RoughnessTexture = AssetsManager::GetAsset<Texture2D>(texHandle);
|
||||||
|
else if (!texPath.empty())
|
||||||
|
material->RoughnessTexture = Texture2D::Create(texPath);
|
||||||
|
else
|
||||||
|
material->RoughnessTexture = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return material;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@ -106,8 +318,10 @@ namespace Prism
|
|||||||
asset->ParentDirectory = parentHandle;
|
asset->ParentDirectory = parentHandle;
|
||||||
asset->IsDataLoaded = false;
|
asset->IsDataLoaded = false;
|
||||||
|
|
||||||
|
#ifndef PRISM_RUNTIME
|
||||||
if (!hasMeta)
|
if (!hasMeta)
|
||||||
CreateMetaFile(asset);
|
CreateMetaFile(asset);
|
||||||
|
#endif
|
||||||
|
|
||||||
return asset;
|
return asset;
|
||||||
}
|
}
|
||||||
@ -191,7 +405,9 @@ namespace Prism
|
|||||||
if (asset->FileName == "assets" && asset->Handle == 0)
|
if (asset->FileName == "assets" && asset->Handle == 0)
|
||||||
{
|
{
|
||||||
asset->Handle = AssetHandle();
|
asset->Handle = AssetHandle();
|
||||||
|
#ifndef PRISM_RUNTIME
|
||||||
CreateMetaFile(asset);
|
CreateMetaFile(asset);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -208,4 +424,17 @@ namespace Prism
|
|||||||
std::ofstream fout(asset->FilePath + ".meta");
|
std::ofstream fout(asset->FilePath + ".meta");
|
||||||
fout << out.c_str();
|
fout << out.c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AssetSerializer::UpdateMetaFile(const Ref<Asset>& asset)
|
||||||
|
{
|
||||||
|
YAML::Emitter out;
|
||||||
|
out << YAML::BeginMap;
|
||||||
|
out << YAML::Key << "Asset" << YAML::Value << asset->Handle;
|
||||||
|
out << YAML::Key << "FilePath" << YAML::Value << asset->FilePath;
|
||||||
|
out << YAML::Key << "Type" << YAML::Value << (int)asset->Type;
|
||||||
|
out << YAML::EndMap;
|
||||||
|
|
||||||
|
std::ofstream fout(asset->FilePath + ".meta");
|
||||||
|
fout << out.c_str();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -28,6 +28,7 @@ namespace Prism
|
|||||||
static Ref<Asset> DeserializeYAML(const Ref<Asset>& asset);
|
static Ref<Asset> DeserializeYAML(const Ref<Asset>& asset);
|
||||||
static void LoadMetaData(Ref<Asset>& asset);
|
static void LoadMetaData(Ref<Asset>& asset);
|
||||||
static void CreateMetaFile(const Ref<Asset>& asset);
|
static void CreateMetaFile(const Ref<Asset>& asset);
|
||||||
|
static void UpdateMetaFile(const Ref<Asset>& asset);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class AssetsManager;
|
friend class AssetsManager;
|
||||||
|
|||||||
@ -13,6 +13,7 @@
|
|||||||
#include <yaml-cpp/yaml.h>
|
#include <yaml-cpp/yaml.h>
|
||||||
|
|
||||||
#include "AssetSerializer.h"
|
#include "AssetSerializer.h"
|
||||||
|
#include "Prism/Core/Application.h"
|
||||||
#include "Prism/Renderer/SceneEnvironment.h"
|
#include "Prism/Renderer/SceneEnvironment.h"
|
||||||
#include "Prism/Utilities/StringUtils.h"
|
#include "Prism/Utilities/StringUtils.h"
|
||||||
|
|
||||||
@ -26,9 +27,13 @@ namespace Prism
|
|||||||
s_Types["dae"] = AssetType::Mesh;
|
s_Types["dae"] = AssetType::Mesh;
|
||||||
s_Types["obj"] = AssetType::Mesh;
|
s_Types["obj"] = AssetType::Mesh;
|
||||||
s_Types["png"] = AssetType::Texture;
|
s_Types["png"] = AssetType::Texture;
|
||||||
|
s_Types["jpg"] = AssetType::Texture;
|
||||||
|
s_Types["jpeg"] = AssetType::Texture;
|
||||||
|
s_Types["bmp"] = AssetType::Texture;
|
||||||
s_Types["tga"] = AssetType::Texture;
|
s_Types["tga"] = AssetType::Texture;
|
||||||
s_Types["hdr"] = AssetType::EnvMap;
|
s_Types["hdr"] = AssetType::EnvMap;
|
||||||
s_Types["blend"] = AssetType::Mesh;
|
s_Types["blend"] = AssetType::Mesh;
|
||||||
|
s_Types["pmat"] = AssetType::Material;
|
||||||
s_Types["hpm"] = AssetType::PhysicsMaterial;
|
s_Types["hpm"] = AssetType::PhysicsMaterial;
|
||||||
s_Types["wav"] = AssetType::Audio;
|
s_Types["wav"] = AssetType::Audio;
|
||||||
s_Types["ogg"] = AssetType::Audio;
|
s_Types["ogg"] = AssetType::Audio;
|
||||||
@ -132,25 +137,6 @@ namespace Prism
|
|||||||
return assetHandle != 0 && s_LoadedAssets.find(assetHandle) != s_LoadedAssets.end();
|
return assetHandle != 0 && s_LoadedAssets.find(assetHandle) != s_LoadedAssets.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AssetsManager::Rename(Ref<Asset>& asset, const std::string& newName)
|
|
||||||
{
|
|
||||||
const std::string newFilePath = FileSystem::Rename(asset->FilePath, newName);
|
|
||||||
const std::string oldFilePath = asset->FilePath;
|
|
||||||
asset->FilePath = newFilePath;
|
|
||||||
asset->FileName = newName;
|
|
||||||
|
|
||||||
if (FileSystem::Exists(oldFilePath + ".meta"))
|
|
||||||
{
|
|
||||||
std::string metaFileName = oldFilePath;
|
|
||||||
|
|
||||||
if (!asset->Extension.empty())
|
|
||||||
metaFileName += "." + asset->Extension;
|
|
||||||
|
|
||||||
FileSystem::PrismDeleteFile(oldFilePath + ".meta");
|
|
||||||
AssetSerializer::CreateMetaFile(asset);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
Ref<T> AssetsManager::GetAsset(AssetHandle assetHandle, bool loadData)
|
Ref<T> AssetsManager::GetAsset(AssetHandle assetHandle, bool loadData)
|
||||||
{
|
{
|
||||||
@ -169,7 +155,7 @@ namespace Prism
|
|||||||
|
|
||||||
template PRISM_API Ref<Asset> AssetsManager::GetAsset(AssetHandle, bool);
|
template PRISM_API Ref<Asset> AssetsManager::GetAsset(AssetHandle, bool);
|
||||||
template PRISM_API Ref<Mesh> AssetsManager::GetAsset(AssetHandle, bool);
|
template PRISM_API Ref<Mesh> AssetsManager::GetAsset(AssetHandle, bool);
|
||||||
template PRISM_API Ref<PhysicsMaterial> AssetsManager::GetAsset(AssetHandle, bool);
|
template PRISM_API Ref<PhysicsMaterialAsset> AssetsManager::GetAsset(AssetHandle, bool);
|
||||||
template PRISM_API Ref<Environment> AssetsManager::GetAsset(AssetHandle, bool);
|
template PRISM_API Ref<Environment> AssetsManager::GetAsset(AssetHandle, bool);
|
||||||
template PRISM_API Ref<Directory> AssetsManager::GetAsset(AssetHandle, bool);
|
template PRISM_API Ref<Directory> AssetsManager::GetAsset(AssetHandle, bool);
|
||||||
template PRISM_API Ref<Texture2D> AssetsManager::GetAsset(AssetHandle, bool);
|
template PRISM_API Ref<Texture2D> AssetsManager::GetAsset(AssetHandle, bool);
|
||||||
@ -180,35 +166,30 @@ namespace Prism
|
|||||||
return GetAsset<T>(GetAssetHandleFromFilePath(filepath), loadData);
|
return GetAsset<T>(GetAssetHandleFromFilePath(filepath), loadData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template PRISM_API Ref<Asset> AssetsManager::GetAsset(const std::string&, bool);
|
template PRISM_API Ref<Asset> AssetsManager::GetAsset(const std::string&, bool);
|
||||||
template PRISM_API Ref<Mesh> AssetsManager::GetAsset(const std::string&, bool);
|
template PRISM_API Ref<Mesh> AssetsManager::GetAsset(const std::string&, bool);
|
||||||
template PRISM_API Ref<PhysicsMaterial> AssetsManager::GetAsset(const std::string&, bool);
|
template PRISM_API Ref<PhysicsMaterialAsset> AssetsManager::GetAsset(const std::string&, bool);
|
||||||
|
template PRISM_API Ref<PBRMaterialAsset> AssetsManager::GetAsset(const std::string&, bool);
|
||||||
template PRISM_API Ref<Environment> AssetsManager::GetAsset(const std::string&, bool);
|
template PRISM_API Ref<Environment> AssetsManager::GetAsset(const std::string&, bool);
|
||||||
template PRISM_API Ref<Directory> AssetsManager::GetAsset(const std::string&, bool);
|
template PRISM_API Ref<Directory> AssetsManager::GetAsset(const std::string&, bool);
|
||||||
template PRISM_API Ref<Texture2D> AssetsManager::GetAsset(const std::string&, bool);
|
template PRISM_API Ref<Texture2D> AssetsManager::GetAsset(const std::string&, bool);
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
// temp
|
Ref<T> AssetsManager::TryGetAsset(const std::string& filepath, const bool loadData)
|
||||||
Ref<PhysicsMaterial> AssetsManager::CreateAssetPhysicsMaterial(const std::string& filename, const AssetType type, const AssetHandle& directoryHandle, float v1, float v2, float v3)
|
|
||||||
{
|
{
|
||||||
|
AssetHandle assetHandle = GetAssetHandleFromFilePath(filepath);
|
||||||
const auto& directory = GetAsset<Directory>(directoryHandle);
|
if (!assetHandle) return Ref<T>();
|
||||||
|
return GetAsset<T>(assetHandle, loadData);
|
||||||
Ref<PhysicsMaterial> asset = Ref<PhysicsMaterial>::Create(v1, v2, v3);
|
|
||||||
asset->Type = type;
|
|
||||||
asset->FilePath = directory->FilePath + "/" + filename;
|
|
||||||
asset->FileName = Utils::RemoveExtension(Utils::GetFilename(asset->FilePath));
|
|
||||||
asset->Extension = Utils::GetFilename(filename);
|
|
||||||
asset->ParentDirectory = directoryHandle;
|
|
||||||
asset->Handle = std::hash<std::string>()(asset->FilePath);
|
|
||||||
asset->IsDataLoaded = true;
|
|
||||||
s_LoadedAssets[asset->Handle] = asset;
|
|
||||||
|
|
||||||
AssetSerializer::SerializeAsset(asset);
|
|
||||||
AssetSerializer::CreateMetaFile(asset);
|
|
||||||
|
|
||||||
return asset;
|
|
||||||
}
|
}
|
||||||
|
template PRISM_API Ref<Asset> AssetsManager::TryGetAsset(const std::string&, bool);
|
||||||
|
template PRISM_API Ref<Mesh> AssetsManager::TryGetAsset(const std::string&, bool);
|
||||||
|
template PRISM_API Ref<PhysicsMaterialAsset> AssetsManager::TryGetAsset(const std::string&, bool);
|
||||||
|
template PRISM_API Ref<PBRMaterialAsset> AssetsManager::TryGetAsset(const std::string&, bool);
|
||||||
|
template PRISM_API Ref<Environment> AssetsManager::TryGetAsset(const std::string&, bool);
|
||||||
|
template PRISM_API Ref<Directory> AssetsManager::TryGetAsset(const std::string&, bool);
|
||||||
|
template PRISM_API Ref<Texture2D> AssetsManager::TryGetAsset(const std::string&, bool);
|
||||||
|
|
||||||
|
|
||||||
void AssetsManager::RemoveAsset(AssetHandle assetHandle)
|
void AssetsManager::RemoveAsset(AssetHandle assetHandle)
|
||||||
{
|
{
|
||||||
@ -252,7 +233,8 @@ namespace Prism
|
|||||||
asset->FileName = Utils::RemoveExtension(Utils::GetFilename(asset->FilePath));
|
asset->FileName = Utils::RemoveExtension(Utils::GetFilename(asset->FilePath));
|
||||||
asset->Extension = Utils::GetFilename(filename);
|
asset->Extension = Utils::GetFilename(filename);
|
||||||
asset->ParentDirectory = directoryHandle;
|
asset->ParentDirectory = directoryHandle;
|
||||||
asset->Handle = std::hash<std::string>()(asset->FilePath);
|
asset->Handle = std::hash<std::string>()(asset->FilePath + std::to_string(Application::Get().GetTime()));
|
||||||
|
|
||||||
asset->IsDataLoaded = true;
|
asset->IsDataLoaded = true;
|
||||||
s_LoadedAssets[asset->Handle] = asset;
|
s_LoadedAssets[asset->Handle] = asset;
|
||||||
|
|
||||||
@ -262,6 +244,10 @@ namespace Prism
|
|||||||
return asset;
|
return asset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template PRISM_API Ref<PhysicsMaterialAsset> AssetsManager::CreateAsset<PhysicsMaterialAsset, float, float, float>(const std::string&, AssetType, AssetHandle, float&&, float&&, float&&);
|
||||||
|
template PRISM_API Ref<PhysicsMaterialAsset> AssetsManager::CreateAsset<PhysicsMaterialAsset>( const std::string&, AssetType, AssetHandle);
|
||||||
|
|
||||||
|
template PRISM_API Ref<PBRMaterialAsset> AssetsManager::CreateAsset<PBRMaterialAsset>( const std::string&, AssetType, AssetHandle);
|
||||||
|
|
||||||
|
|
||||||
bool AssetsManager::IsAssetType(const AssetHandle assetHandle, const AssetType type)
|
bool AssetsManager::IsAssetType(const AssetHandle assetHandle, const AssetType type)
|
||||||
@ -307,7 +293,7 @@ namespace Prism
|
|||||||
{
|
{
|
||||||
const std::string extension = Utils::GetExtension(filepath);
|
const std::string extension = Utils::GetExtension(filepath);
|
||||||
if (extension == "meta")
|
if (extension == "meta")
|
||||||
return Ref<Asset>();
|
return {};
|
||||||
|
|
||||||
const AssetType type = AssetTypes::GetAssetTypeFromExtension(extension);
|
const AssetType type = AssetTypes::GetAssetTypeFromExtension(extension);
|
||||||
Ref<Asset> asset = AssetSerializer::LoadAssetInfo(filepath, parentHandle, type);
|
Ref<Asset> asset = AssetSerializer::LoadAssetInfo(filepath, parentHandle, type);
|
||||||
@ -368,7 +354,9 @@ namespace Prism
|
|||||||
ProcessDirectory(e.FilePath, parentHandle);
|
ProcessDirectory(e.FilePath, parentHandle);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Ref<Asset> asset = ImportAsset(e.FilePath, parentHandle);
|
AssetHandle assetHandle = GetAssetHandleFromFilePath(e.FilePath);
|
||||||
|
if (!assetHandle)
|
||||||
|
ImportAsset(e.FilePath, parentHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -383,41 +371,32 @@ namespace Prism
|
|||||||
break;
|
break;
|
||||||
case FileSystemAction::Rename:
|
case FileSystemAction::Rename:
|
||||||
{
|
{
|
||||||
Ref<Asset> asset;
|
Ref<Asset> asset = nullptr;
|
||||||
|
|
||||||
for (auto it = s_LoadedAssets.begin(); it != s_LoadedAssets.end(); it++)
|
|
||||||
{
|
{
|
||||||
if (it->second->FileName == e.OldName)
|
const std::string oldFilePath = Utils::ReplaceFilePathName(e.FilePath, e.OldName);
|
||||||
|
for (auto& [handle, existingAsset] : s_LoadedAssets)
|
||||||
{
|
{
|
||||||
asset = it->second;
|
if (existingAsset->FilePath == oldFilePath)
|
||||||
|
{
|
||||||
|
asset = existingAsset;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (asset)
|
if (asset)
|
||||||
{
|
{
|
||||||
if (asset->Type != AssetTypes::GetAssetTypeFromExtension(Utils::GetExtension(e.FilePath)))
|
std::string extension = Utils::GetExtension(asset->FilePath);
|
||||||
{
|
std::string oldMetaPath = asset->FilePath + ".meta";
|
||||||
RemoveAsset(asset->Handle);
|
|
||||||
FileSystem::PrismDeleteFile(asset->FilePath + ".meta");
|
|
||||||
asset = ImportAsset(e.FilePath, parentHandle);
|
|
||||||
}else
|
|
||||||
{
|
|
||||||
std::string oldMetaPath = asset->FilePath + ".meta";
|
|
||||||
std::string newMetaPath = e.FilePath + ".meta";
|
|
||||||
|
|
||||||
std::error_code ec;
|
FileSystem::Rename(oldMetaPath, e.NewName + "." + extension);
|
||||||
std::filesystem::rename(oldMetaPath, newMetaPath, ec);
|
|
||||||
if (ec)
|
|
||||||
{
|
|
||||||
PM_CORE_ERROR("Failed to rename meta file: {}", ec.message());
|
|
||||||
}
|
|
||||||
|
|
||||||
asset->FilePath = e.FilePath;
|
asset->FilePath = e.FilePath;
|
||||||
asset->FileName = e.NewName;
|
asset->FileName = e.NewName;
|
||||||
}
|
asset->Extension = extension;
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
AssetSerializer::UpdateMetaFile(asset);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case FileSystemAction::Delete:
|
case FileSystemAction::Delete:
|
||||||
|
|||||||
@ -45,9 +45,8 @@ namespace Prism
|
|||||||
static AssetHandle GetAssetHandleFromFilePath(const std::string& filepath);
|
static AssetHandle GetAssetHandleFromFilePath(const std::string& filepath);
|
||||||
static bool IsAssetHandleValid(const AssetHandle& assetHandle);
|
static bool IsAssetHandleValid(const AssetHandle& assetHandle);
|
||||||
|
|
||||||
static void Rename(Ref<Asset>& asset, const std::string& newName);
|
|
||||||
|
|
||||||
static Ref<PhysicsMaterial> CreateAssetPhysicsMaterial(const std::string& filename, AssetType type, const AssetHandle& directoryHandle, float v1, float v2, float v3);
|
static Ref<PhysicsMaterialAsset> CreateAssetPhysicsMaterial(const std::string& filename, AssetType type, const AssetHandle& directoryHandle, float v1, float v2, float v3);
|
||||||
|
|
||||||
static void RemoveAsset(AssetHandle assetHandle);
|
static void RemoveAsset(AssetHandle assetHandle);
|
||||||
|
|
||||||
@ -59,6 +58,8 @@ namespace Prism
|
|||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static Ref<T> GetAsset(const std::string& filepath, bool loadData = true);
|
static Ref<T> GetAsset(const std::string& filepath, bool loadData = true);
|
||||||
|
template <class T>
|
||||||
|
static Ref<T> TryGetAsset(const std::string& filepath, bool loadData = true);
|
||||||
|
|
||||||
static bool IsAssetType(AssetHandle assetHandle, AssetType type);
|
static bool IsAssetType(AssetHandle assetHandle, AssetType type);
|
||||||
|
|
||||||
|
|||||||
@ -36,7 +36,6 @@ namespace Prism
|
|||||||
m_Window = std::unique_ptr<Window>(Window::Create(WindowProps{props.Name, props.Width, props.Height}));
|
m_Window = std::unique_ptr<Window>(Window::Create(WindowProps{props.Name, props.Width, props.Height}));
|
||||||
m_Window->SetEventCallback(BIND_EVENT_FN(OnEvent));
|
m_Window->SetEventCallback(BIND_EVENT_FN(OnEvent));
|
||||||
m_Window->SetVSync(true);
|
m_Window->SetVSync(true);
|
||||||
m_Window->Maximize();
|
|
||||||
|
|
||||||
m_ImGuiLayer = new ImGuiLayer("ImGui Layer");
|
m_ImGuiLayer = new ImGuiLayer("ImGui Layer");
|
||||||
PushOverlay(m_ImGuiLayer);
|
PushOverlay(m_ImGuiLayer);
|
||||||
@ -107,6 +106,7 @@ namespace Prism
|
|||||||
for (Layer* layer : m_LayerStack)
|
for (Layer* layer : m_LayerStack)
|
||||||
layer->OnImGuiRender();
|
layer->OnImGuiRender();
|
||||||
|
|
||||||
|
/*
|
||||||
ImGui::Begin("Renderer");
|
ImGui::Begin("Renderer");
|
||||||
const auto& caps = RendererAPI::GetCapabilities();
|
const auto& caps = RendererAPI::GetCapabilities();
|
||||||
ImGui::Text("Vendor: %s", caps.Vendor.c_str());
|
ImGui::Text("Vendor: %s", caps.Vendor.c_str());
|
||||||
@ -114,6 +114,7 @@ namespace Prism
|
|||||||
ImGui::Text("Version: %s", caps.Version.c_str());
|
ImGui::Text("Version: %s", caps.Version.c_str());
|
||||||
ImGui::Text("Frame Time: %.2fms\n", m_TimeStep.GetMilliseconds());
|
ImGui::Text("Frame Time: %.2fms\n", m_TimeStep.GetMilliseconds());
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
|
*/
|
||||||
|
|
||||||
m_ImGuiLayer->End();
|
m_ImGuiLayer->End();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,7 +12,19 @@
|
|||||||
|
|
||||||
extern Prism::Application* Prism::CreateApplication(CommandArgs args);
|
extern Prism::Application* Prism::CreateApplication(CommandArgs args);
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
#ifdef PRISM_GUI
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <windows.h>
|
||||||
|
int MainEntry(int argc, char* argv[]);
|
||||||
|
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
|
||||||
|
{
|
||||||
|
return MainEntry(__argc, __argv);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
int MainEntry(int argc, char** argv)
|
||||||
|
#else
|
||||||
|
int main(int argc, char** argv)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
//TODO: this will use other method to impl
|
//TODO: this will use other method to impl
|
||||||
std::cout << std::filesystem::current_path() << std::endl;
|
std::cout << std::filesystem::current_path() << std::endl;
|
||||||
@ -33,6 +45,7 @@ int main(int argc, char** argv)
|
|||||||
Prism::ShutdownCore();
|
Prism::ShutdownCore();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif //ENTRYPOINT_H
|
#endif //ENTRYPOINT_H
|
||||||
|
|||||||
@ -45,6 +45,49 @@ namespace Prism {
|
|||||||
EVENT_CLASS_CATEGORY(EventCategoryApplication)
|
EVENT_CLASS_CATEGORY(EventCategoryApplication)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class PRISM_API WindowFocusEvent : public Event
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
WindowFocusEvent() = default;
|
||||||
|
|
||||||
|
EVENT_CLASS_TYPE(WindowFocus)
|
||||||
|
EVENT_CLASS_CATEGORY(EventCategoryApplication)
|
||||||
|
};
|
||||||
|
|
||||||
|
class PRISM_API WindowLostFocusEvent : public Event
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
WindowLostFocusEvent() = default;
|
||||||
|
|
||||||
|
EVENT_CLASS_TYPE(WindowLostFocus)
|
||||||
|
EVENT_CLASS_CATEGORY(EventCategoryApplication)
|
||||||
|
};
|
||||||
|
|
||||||
|
class PRISM_API WindowMovedEvent : public Event
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
WindowMovedEvent(const int32_t x, const int32_t y)
|
||||||
|
: m_X(x), m_Y(y)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int32_t GetX() const { return m_X; }
|
||||||
|
inline int32_t GetY() const { return m_Y; }
|
||||||
|
|
||||||
|
std::string ToString() const override
|
||||||
|
{
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << "WindowMovedEvent: " << m_X << ", " << m_Y;
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
EVENT_CLASS_TYPE(WindowMoved)
|
||||||
|
EVENT_CLASS_CATEGORY(EventCategoryApplication)
|
||||||
|
|
||||||
|
private:
|
||||||
|
int32_t m_X, m_Y;
|
||||||
|
};
|
||||||
|
|
||||||
class PRISM_API AppTickEvent : public Event
|
class PRISM_API AppTickEvent : public Event
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|||||||
@ -24,7 +24,6 @@ namespace Prism
|
|||||||
static std::shared_ptr<spdlog::logger> s_CoreLogger;
|
static std::shared_ptr<spdlog::logger> s_CoreLogger;
|
||||||
static std::shared_ptr<spdlog::logger> s_ClientLogger;
|
static std::shared_ptr<spdlog::logger> s_ClientLogger;
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
#define PM_CORE_TRACE(...) SPDLOG_LOGGER_TRACE(::Prism::Log::GetCoreLogger(), __VA_ARGS__)
|
#define PM_CORE_TRACE(...) SPDLOG_LOGGER_TRACE(::Prism::Log::GetCoreLogger(), __VA_ARGS__)
|
||||||
@ -41,6 +40,8 @@ namespace Prism
|
|||||||
#define PM_CORE_ERROR(...) ::Prism::Log::GetCoreLogger()->error(__VA_ARGS__)
|
#define PM_CORE_ERROR(...) ::Prism::Log::GetCoreLogger()->error(__VA_ARGS__)
|
||||||
#define PM_CORE_FATAL(...) ::Prism::Log::GetCoreLogger()->critical(__VA_ARGS__)
|
#define PM_CORE_FATAL(...) ::Prism::Log::GetCoreLogger()->critical(__VA_ARGS__)
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define PM_CLIENT_TRACE(...) ::Prism::Log::GetClientLogger()->trace(__VA_ARGS__)
|
#define PM_CLIENT_TRACE(...) ::Prism::Log::GetClientLogger()->trace(__VA_ARGS__)
|
||||||
|
|||||||
@ -19,6 +19,10 @@ namespace Prism
|
|||||||
AABB(const glm::vec3& min, const glm::vec3& max)
|
AABB(const glm::vec3& min, const glm::vec3& max)
|
||||||
: Min(min), Max(max) {}
|
: Min(min), Max(max) {}
|
||||||
|
|
||||||
|
bool IsValid() const {
|
||||||
|
return Min.x <= Max.x && Min.y <= Max.y && Min.z <= Max.z;
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -21,7 +21,7 @@ namespace Prism
|
|||||||
operator float() { return m_Time; }
|
operator float() { return m_Time; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
float m_Time;
|
float m_Time = 0.0f;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -10,6 +10,7 @@
|
|||||||
#include "Ref.h"
|
#include "Ref.h"
|
||||||
#include "Events/Event.h"
|
#include "Events/Event.h"
|
||||||
#include "Prism/Core/Core.h"
|
#include "Prism/Core/Core.h"
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
|
|
||||||
namespace Prism
|
namespace Prism
|
||||||
@ -39,8 +40,8 @@ namespace Prism
|
|||||||
virtual void SetEventCallback(const EventCallbackFn& callback) = 0;
|
virtual void SetEventCallback(const EventCallbackFn& callback) = 0;
|
||||||
virtual uint32_t GetWidth() const = 0;
|
virtual uint32_t GetWidth() const = 0;
|
||||||
virtual uint32_t GetHeight() const = 0;
|
virtual uint32_t GetHeight() const = 0;
|
||||||
virtual std::pair<uint32_t, uint32_t> GetSize() const = 0;
|
virtual glm::ivec2 GetSize() const = 0;
|
||||||
virtual std::pair<float, float> GetWindowPos() const = 0;
|
virtual glm::vec2 GetWindowPos() const = 0;
|
||||||
|
|
||||||
virtual void SetVSync(bool enable) = 0;
|
virtual void SetVSync(bool enable) = 0;
|
||||||
virtual bool const IsVSync() const = 0;
|
virtual bool const IsVSync() const = 0;
|
||||||
|
|||||||
@ -52,6 +52,7 @@ namespace Prism
|
|||||||
{
|
{
|
||||||
RegisterEditor<TextureViewer>(AssetType::Texture);
|
RegisterEditor<TextureViewer>(AssetType::Texture);
|
||||||
RegisterEditor<PhysicsMaterialEditor>(AssetType::PhysicsMaterial);
|
RegisterEditor<PhysicsMaterialEditor>(AssetType::PhysicsMaterial);
|
||||||
|
RegisterEditor<PBRMaterialEditor>(AssetType::Material);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AssetEditorPanel::OnImGuiRender()
|
void AssetEditorPanel::OnImGuiRender()
|
||||||
@ -62,6 +63,11 @@ namespace Prism
|
|||||||
|
|
||||||
void AssetEditorPanel::OpenEditor(const Ref<Asset>& asset)
|
void AssetEditorPanel::OpenEditor(const Ref<Asset>& asset)
|
||||||
{
|
{
|
||||||
|
if (!asset)
|
||||||
|
{
|
||||||
|
PM_CORE_WARN("asset is Invalid!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (s_Editors.find(asset->Type) == s_Editors.end())
|
if (s_Editors.find(asset->Type) == s_Editors.end())
|
||||||
{
|
{
|
||||||
PM_CORE_WARN("No editor registered for {0} assets", asset->Extension);
|
PM_CORE_WARN("No editor registered for {0} assets", asset->Extension);
|
||||||
|
|||||||
@ -11,6 +11,7 @@
|
|||||||
#include "Prism/Core/Application.h"
|
#include "Prism/Core/Application.h"
|
||||||
#include "Prism/Core/Input.h"
|
#include "Prism/Core/Input.h"
|
||||||
#include "Prism/Core/Log.h"
|
#include "Prism/Core/Log.h"
|
||||||
|
#include "Prism/Utilities/StringUtils.h"
|
||||||
|
|
||||||
namespace Prism
|
namespace Prism
|
||||||
{
|
{
|
||||||
@ -32,7 +33,9 @@ namespace Prism
|
|||||||
m_AssetIconMap["blend"] = AssetsManager::GetAsset<Texture2D>("assets/editor/blend.png");
|
m_AssetIconMap["blend"] = AssetsManager::GetAsset<Texture2D>("assets/editor/blend.png");
|
||||||
|
|
||||||
// TODO: get a logo for this project
|
// TODO: get a logo for this project
|
||||||
m_AssetIconMap["scene"] = Texture2D::Create("assets/editor/asset.png");
|
m_AssetIconMap["scene"] = AssetsManager::GetAsset<Texture2D>("assets/editor/asset.png");
|
||||||
|
|
||||||
|
m_AssetIconMap["pmat"] = AssetsManager::GetAsset<Texture2D>("assets/editor/asset.png");
|
||||||
|
|
||||||
m_BackbtnTex = AssetsManager::GetAsset<Texture2D>("assets/editor/btn_back.png");
|
m_BackbtnTex = AssetsManager::GetAsset<Texture2D>("assets/editor/btn_back.png");
|
||||||
m_FwrdbtnTex = AssetsManager::GetAsset<Texture2D>("assets/editor/btn_fwrd.png");
|
m_FwrdbtnTex = AssetsManager::GetAsset<Texture2D>("assets/editor/btn_fwrd.png");
|
||||||
@ -101,16 +104,56 @@ namespace Prism
|
|||||||
if (ImGui::MenuItem("Folder"))
|
if (ImGui::MenuItem("Folder"))
|
||||||
{
|
{
|
||||||
PM_CORE_INFO("Creating Folder...");
|
PM_CORE_INFO("Creating Folder...");
|
||||||
const bool created = FileSystem::CreateFolder(m_CurrentDirectory->FilePath + "/New Folder");
|
const std::string filePath = m_CurrentDirectory->FilePath + "/new folder";
|
||||||
if (created)
|
FileSystem::CreateFolder(filePath);
|
||||||
|
UpdateCurrentDirectory(m_CurrentDirHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ImGui::MenuItem("PBRMaterial"))
|
||||||
|
{
|
||||||
|
|
||||||
|
const std::string fileName = "Material.pmat";
|
||||||
|
const auto& directory = AssetsManager::GetAsset<Directory>(m_CurrentDirHandle);
|
||||||
|
|
||||||
|
// for hash UUID use
|
||||||
|
std::string baseName = Utils::RemoveExtension(fileName);
|
||||||
|
std::string extension = Utils::GetExtension(fileName, true);
|
||||||
|
std::string finalFilename = fileName;
|
||||||
|
std::string finalPath = directory->FilePath + "/" + finalFilename;
|
||||||
|
|
||||||
|
int counter = 1;
|
||||||
|
while (AssetsManager::GetAssetHandleFromFilePath(finalPath) != 0)
|
||||||
{
|
{
|
||||||
UpdateCurrentDirectory(m_CurrentDirHandle);
|
finalFilename = baseName + "_" + std::to_string(counter++) + extension;
|
||||||
const auto& createdDirectory = AssetsManager::GetAsset<Directory>(AssetsManager::GetAssetHandleFromFilePath(m_CurrentDirectory->FilePath + "/New Folder"));
|
finalPath = directory->FilePath + "/" + finalFilename;
|
||||||
m_SelectedAssets.Select(createdDirectory->Handle);
|
|
||||||
memset(m_InputBuffer, 0, MAX_INPUT_BUFFER_LENGTH);
|
|
||||||
memcpy(m_InputBuffer, createdDirectory->FileName.c_str(), createdDirectory->FileName.size());
|
|
||||||
m_RenamingSelected = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
AssetsManager::CreateAsset<PBRMaterialAsset>(finalFilename, AssetType::Material, m_CurrentDirHandle);
|
||||||
|
UpdateCurrentDirectory(m_CurrentDirHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ImGui::MenuItem("Physics Material"))
|
||||||
|
{
|
||||||
|
const std::string fileName = "PhysicsMaterial.hpm";
|
||||||
|
const auto& directory = AssetsManager::GetAsset<Directory>(m_CurrentDirHandle);
|
||||||
|
|
||||||
|
// for hash UUID use
|
||||||
|
std::string baseName = Utils::RemoveExtension(fileName);
|
||||||
|
std::string extension = Utils::GetExtension(fileName, true);
|
||||||
|
std::string finalFilename = fileName;
|
||||||
|
std::string finalPath = directory->FilePath + "/" + finalFilename;
|
||||||
|
|
||||||
|
int counter = 1;
|
||||||
|
while (AssetsManager::GetAssetHandleFromFilePath(finalPath) != 0)
|
||||||
|
{
|
||||||
|
finalFilename = baseName + "_" + std::to_string(counter++) + extension;
|
||||||
|
finalPath = directory->FilePath + "/" + finalFilename;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
AssetsManager::CreateAsset<PhysicsMaterialAsset>(finalFilename, AssetType::PhysicsMaterial, m_CurrentDirHandle, 0.6f, 0.6f, 0.0f);
|
||||||
|
UpdateCurrentDirectory(m_CurrentDirHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ImGui::MenuItem("Scene"))
|
if (ImGui::MenuItem("Scene"))
|
||||||
@ -123,13 +166,23 @@ namespace Prism
|
|||||||
PM_CORE_INFO("Creating Script...");
|
PM_CORE_INFO("Creating Script...");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
if (ImGui::MenuItem("Prefab"))
|
if (ImGui::MenuItem("Prefab"))
|
||||||
{
|
{
|
||||||
PM_CORE_INFO("Creating Prefab...");
|
PM_CORE_INFO("Creating Prefab...");
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
ImGui::EndMenu();
|
ImGui::EndMenu();
|
||||||
}
|
}
|
||||||
|
ImGui::Separator();
|
||||||
|
|
||||||
|
if (ImGui::MenuItem("Open In Explorer"))
|
||||||
|
{
|
||||||
|
Ref<Asset> asset = AssetsManager::GetAsset<Asset>(m_CurrentDirHandle);
|
||||||
|
FileSystem::OpenInExplorer(asset->FilePath);
|
||||||
|
}
|
||||||
|
ImGui::Separator();
|
||||||
|
|
||||||
if (ImGui::MenuItem("Import"))
|
if (ImGui::MenuItem("Import"))
|
||||||
{
|
{
|
||||||
@ -141,12 +194,6 @@ namespace Prism
|
|||||||
UpdateCurrentDirectory(m_CurrentDirHandle);
|
UpdateCurrentDirectory(m_CurrentDirHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ImGui::MenuItem("Physics Material"))
|
|
||||||
{
|
|
||||||
// TODO: use template
|
|
||||||
AssetsManager::CreateAssetPhysicsMaterial("New Physics Material.hpm", AssetType::PhysicsMaterial, m_CurrentDirHandle, 0.6f, 0.6f, 0.0f);
|
|
||||||
UpdateCurrentDirectory(m_CurrentDirHandle);
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::EndPopup();
|
ImGui::EndPopup();
|
||||||
}
|
}
|
||||||
@ -300,6 +347,12 @@ namespace Prism
|
|||||||
|
|
||||||
if (ImGui::BeginPopupContextItem())
|
if (ImGui::BeginPopupContextItem())
|
||||||
{
|
{
|
||||||
|
if (ImGui::MenuItem("Open In Explorer"))
|
||||||
|
{
|
||||||
|
FileSystem::OpenInExplorer(asset->FilePath);
|
||||||
|
}
|
||||||
|
ImGui::Separator();
|
||||||
|
|
||||||
if (ImGui::MenuItem("Rename"))
|
if (ImGui::MenuItem("Rename"))
|
||||||
{
|
{
|
||||||
m_SelectedAssets.Select(assetHandle);
|
m_SelectedAssets.Select(assetHandle);
|
||||||
@ -523,7 +576,8 @@ namespace Prism
|
|||||||
if (ImGui::InputText("##rename_dummy", m_InputBuffer, MAX_INPUT_BUFFER_LENGTH, ImGuiInputTextFlags_EnterReturnsTrue))
|
if (ImGui::InputText("##rename_dummy", m_InputBuffer, MAX_INPUT_BUFFER_LENGTH, ImGuiInputTextFlags_EnterReturnsTrue))
|
||||||
{
|
{
|
||||||
PM_CORE_INFO("Renaming to {0}", m_InputBuffer);
|
PM_CORE_INFO("Renaming to {0}", m_InputBuffer);
|
||||||
AssetsManager::Rename(asset, m_InputBuffer);
|
const std::string filename = m_InputBuffer;
|
||||||
|
FileSystem::Rename(asset->FilePath, filename);
|
||||||
m_RenamingSelected = false;
|
m_RenamingSelected = false;
|
||||||
m_SelectedAssets.Clear();
|
m_SelectedAssets.Clear();
|
||||||
m_UpdateDirectoryNextFrame = true;
|
m_UpdateDirectoryNextFrame = true;
|
||||||
|
|||||||
@ -13,6 +13,12 @@ namespace Prism
|
|||||||
PhysicsMaterialEditor::PhysicsMaterialEditor()
|
PhysicsMaterialEditor::PhysicsMaterialEditor()
|
||||||
: AssetEditor("Edit Physics Material") {}
|
: AssetEditor("Edit Physics Material") {}
|
||||||
|
|
||||||
|
void PhysicsMaterialEditor::SetAsset(const Ref<Asset>& asset)
|
||||||
|
{
|
||||||
|
if (m_Asset) AssetSerializer::SerializeAsset(m_Asset);
|
||||||
|
m_Asset = static_cast<Ref<PhysicsMaterialAsset>>(asset);
|
||||||
|
}
|
||||||
|
|
||||||
void PhysicsMaterialEditor::Render()
|
void PhysicsMaterialEditor::Render()
|
||||||
{
|
{
|
||||||
if (!m_Asset)
|
if (!m_Asset)
|
||||||
@ -37,6 +43,12 @@ namespace Prism
|
|||||||
SetMaxSize(500, 1000);
|
SetMaxSize(500, 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TextureViewer::SetAsset(const Ref<Asset>& asset)
|
||||||
|
{
|
||||||
|
if (m_Asset) AssetSerializer::SerializeAsset(m_Asset);
|
||||||
|
m_Asset = static_cast<Ref<Texture>>(asset);
|
||||||
|
}
|
||||||
|
|
||||||
void TextureViewer::Render()
|
void TextureViewer::Render()
|
||||||
{
|
{
|
||||||
if (!m_Asset)
|
if (!m_Asset)
|
||||||
@ -58,4 +70,214 @@ namespace Prism
|
|||||||
UI::EndPropertyGrid();
|
UI::EndPropertyGrid();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PBRMaterialEditor::PBRMaterialEditor() : AssetEditor("Material Editor")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 辅助函数:绘制纹理拖拽槽
|
||||||
|
void DrawTextureSlot(Ref<Texture2D>& texture, const std::function<void(Ref<Texture2D>)>& onDrop)
|
||||||
|
{
|
||||||
|
static Ref<Texture2D> s_Checkerboard = nullptr;
|
||||||
|
if (!s_Checkerboard)
|
||||||
|
s_Checkerboard = AssetsManager::GetAsset<Texture2D>("assets/editor/Checkerboard.tga");
|
||||||
|
|
||||||
|
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(10, 10));
|
||||||
|
ImGui::Image(texture ? (ImTextureID)(intptr_t)texture->GetRendererID() : (ImTextureID)(intptr_t)s_Checkerboard->GetRendererID(),
|
||||||
|
ImVec2(64, 64));
|
||||||
|
ImGui::PopStyleVar();
|
||||||
|
|
||||||
|
if (ImGui::BeginDragDropTarget())
|
||||||
|
{
|
||||||
|
if (const auto data = ImGui::AcceptDragDropPayload("asset_payload"))
|
||||||
|
{
|
||||||
|
AssetHandle assetHandle = *(AssetHandle*)data->Data;
|
||||||
|
if (AssetsManager::IsAssetType(assetHandle, AssetType::Texture))
|
||||||
|
{
|
||||||
|
Ref<Texture2D> newTex = AssetsManager::GetAsset<Texture2D>(assetHandle);
|
||||||
|
if (onDrop) onDrop(newTex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::EndDragDropTarget();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ImGui::IsItemHovered())
|
||||||
|
{
|
||||||
|
if (texture)
|
||||||
|
{
|
||||||
|
ImGui::BeginTooltip();
|
||||||
|
ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f);
|
||||||
|
ImGui::TextUnformatted(texture->GetPath().c_str());
|
||||||
|
ImGui::PopTextWrapPos();
|
||||||
|
ImGui::Image((ImTextureID)(intptr_t)texture->GetRendererID(), ImVec2(384, 384));
|
||||||
|
ImGui::EndTooltip();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
// TODO: how to solve this
|
||||||
|
if (ImGui::IsItemClicked(ImGuiMouseButton_Left))
|
||||||
|
{
|
||||||
|
std::string filename = FileSystem::OpenFileSelector("*.png;*.tga;*.jpg;*.jpeg");
|
||||||
|
if (!filename.empty())
|
||||||
|
{
|
||||||
|
Ref<Texture2D> newTex = Texture2D::Create(filename);
|
||||||
|
if (onDrop) onDrop(newTex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PBRMaterialEditor::SetAsset(const Ref<Asset>& asset)
|
||||||
|
{
|
||||||
|
if (m_Asset)
|
||||||
|
{
|
||||||
|
if (m_Asset->Handle == asset->Handle) return;
|
||||||
|
if (AssetsManager::IsAssetHandleValid(m_Asset->Handle))
|
||||||
|
AssetSerializer::SerializeAsset(m_Asset);
|
||||||
|
}
|
||||||
|
m_Asset = static_cast<Ref<PBRMaterialAsset>>(asset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PBRMaterialEditor::Render()
|
||||||
|
{
|
||||||
|
if (!m_Asset) return;
|
||||||
|
|
||||||
|
auto& material = m_Asset;
|
||||||
|
|
||||||
|
if (ImGui::BeginTabBar("MaterialProperties", ImGuiTabBarFlags_None))
|
||||||
|
{
|
||||||
|
// ==================== Parameters ====================
|
||||||
|
if (ImGui::BeginTabItem("Parameters"))
|
||||||
|
{
|
||||||
|
ImGui::Spacing();
|
||||||
|
|
||||||
|
if (ImGui::CollapsingHeader("Albedo", ImGuiTreeNodeFlags_DefaultOpen))
|
||||||
|
{
|
||||||
|
ImGui::Indent();
|
||||||
|
|
||||||
|
if (ImGui::ColorEdit3("Color##Albedo", glm::value_ptr(material->AlbedoColor)))
|
||||||
|
{
|
||||||
|
m_Asset->IsDirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool useAlbedoMap = (material->AlbedoTexToggle > 0.5f);
|
||||||
|
if (ImGui::Checkbox("Use Texture##Albedo", &useAlbedoMap))
|
||||||
|
{
|
||||||
|
material->AlbedoTexToggle = useAlbedoMap ? 1.0f : 0.0f;
|
||||||
|
m_Asset->IsDirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
DrawTextureSlot(material->AlbedoTexture, [&](const Ref<Texture2D>& newTex) {
|
||||||
|
material->AlbedoTexture = newTex;
|
||||||
|
material->AlbedoTexToggle = true;
|
||||||
|
m_Asset->IsDirty = true;
|
||||||
|
});
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::Text("Albedo Texture");
|
||||||
|
|
||||||
|
ImGui::Unindent();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Normal Map
|
||||||
|
if (ImGui::CollapsingHeader("Normal Map", ImGuiTreeNodeFlags_DefaultOpen))
|
||||||
|
{
|
||||||
|
ImGui::Indent();
|
||||||
|
|
||||||
|
bool useNormalMap = (material->NormalTexToggle > 0.5f);
|
||||||
|
if (ImGui::Checkbox("Use Texture##Normal", &useNormalMap))
|
||||||
|
{
|
||||||
|
material->NormalTexToggle = useNormalMap ? 1.0f : 0.0f;
|
||||||
|
m_Asset->IsDirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
DrawTextureSlot(material->NormalTexture, [&](const Ref<Texture2D>& newTex) {
|
||||||
|
material->NormalTexture = newTex;
|
||||||
|
material->NormalTexToggle = true;
|
||||||
|
m_Asset->IsDirty = true;
|
||||||
|
});
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::Text("Normal Texture");
|
||||||
|
|
||||||
|
ImGui::Unindent();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Metalness
|
||||||
|
if (ImGui::CollapsingHeader("Metalness", ImGuiTreeNodeFlags_DefaultOpen))
|
||||||
|
{
|
||||||
|
ImGui::Indent();
|
||||||
|
|
||||||
|
if (ImGui::SliderFloat("Value##Metalness", &material->Metalness, 0.0f, 1.0f))
|
||||||
|
{
|
||||||
|
// 自动保存
|
||||||
|
m_Asset->IsDirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool useMetalnessMap = (material->MetalnessTexToggle > 0.5f);
|
||||||
|
if (ImGui::Checkbox("Use Texture##Metalness", &useMetalnessMap))
|
||||||
|
{
|
||||||
|
material->MetalnessTexToggle = useMetalnessMap ? 1.0f : 0.0f;
|
||||||
|
m_Asset->IsDirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
DrawTextureSlot(material->MetalnessTexture, [&](const Ref<Texture2D>& newTex) {
|
||||||
|
material->MetalnessTexture = newTex;
|
||||||
|
material->MetalnessTexToggle = true;
|
||||||
|
m_Asset->IsDirty = true;
|
||||||
|
});
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::Text("Metalness Texture");
|
||||||
|
|
||||||
|
ImGui::Unindent();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Roughness
|
||||||
|
if (ImGui::CollapsingHeader("Roughness", ImGuiTreeNodeFlags_DefaultOpen))
|
||||||
|
{
|
||||||
|
ImGui::Indent();
|
||||||
|
|
||||||
|
if (ImGui::SliderFloat("Value##Roughness", &material->Roughness, 0.0f, 1.0f))
|
||||||
|
{
|
||||||
|
// 自动保存
|
||||||
|
m_Asset->IsDirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool useRoughnessMap = (material->RoughnessTexToggle > 0.5f);
|
||||||
|
if (ImGui::Checkbox("Use Texture##Roughness", &useRoughnessMap))
|
||||||
|
{
|
||||||
|
material->RoughnessTexToggle = useRoughnessMap ? 1.0f : 0.0f;
|
||||||
|
m_Asset->IsDirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
DrawTextureSlot(material->RoughnessTexture, [&](const Ref<Texture2D>& newTex) {
|
||||||
|
material->RoughnessTexture = newTex;
|
||||||
|
material->RoughnessTexToggle = true;
|
||||||
|
m_Asset->IsDirty = true;
|
||||||
|
});
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::Text("Roughness Texture");
|
||||||
|
|
||||||
|
ImGui::Unindent();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::EndTabItem();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== 预览 ====================
|
||||||
|
if (ImGui::BeginTabItem("Preview"))
|
||||||
|
{
|
||||||
|
// 简单显示纹理预览
|
||||||
|
if (material->AlbedoTexture)
|
||||||
|
{
|
||||||
|
ImGui::Text("Albedo Preview");
|
||||||
|
ImGui::Image((ImTextureID)(intptr_t)material->AlbedoTexture->GetRendererID(), ImVec2(128, 128));
|
||||||
|
}
|
||||||
|
ImGui::EndTabItem();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::EndTabBar();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,14 +15,14 @@ namespace Prism
|
|||||||
public:
|
public:
|
||||||
PhysicsMaterialEditor();
|
PhysicsMaterialEditor();
|
||||||
|
|
||||||
virtual Ref<Asset> GetAsset() override { return m_Asset; }
|
Ref<Asset> GetAsset() override { return m_Asset; }
|
||||||
virtual void SetAsset(const Ref<Asset>& asset) override { m_Asset = (Ref<PhysicsMaterial>)asset; }
|
void SetAsset(const Ref<Asset>& asset) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual void Render() override;
|
void Render() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ref<PhysicsMaterial> m_Asset;
|
Ref<PhysicsMaterialAsset> m_Asset;
|
||||||
};
|
};
|
||||||
|
|
||||||
class TextureViewer : public AssetEditor
|
class TextureViewer : public AssetEditor
|
||||||
@ -30,16 +30,31 @@ namespace Prism
|
|||||||
public:
|
public:
|
||||||
TextureViewer();
|
TextureViewer();
|
||||||
|
|
||||||
virtual Ref<Asset> GetAsset() override { return m_Asset; }
|
Ref<Asset> GetAsset() override { return m_Asset; }
|
||||||
virtual void SetAsset(const Ref<Asset>& asset) override { m_Asset = static_cast<Ref<Texture>>(asset); }
|
void SetAsset(const Ref<Asset>& asset) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual void Render() override;
|
void Render() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ref<Texture> m_Asset;
|
Ref<Texture> m_Asset;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class PBRMaterialEditor : public AssetEditor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PBRMaterialEditor();
|
||||||
|
|
||||||
|
Ref<Asset> GetAsset() override { return m_Asset; }
|
||||||
|
void SetAsset(const Ref<Asset>& asset) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void Render() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Ref<PBRMaterialAsset> m_Asset;
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif //PRISM_DEFAULTASSETEDITORS_H
|
#endif //PRISM_DEFAULTASSETEDITORS_H
|
||||||
@ -14,6 +14,7 @@
|
|||||||
#include <glm/gtx/quaternion.hpp>
|
#include <glm/gtx/quaternion.hpp>
|
||||||
#include <glm/gtx/matrix_decompose.hpp>
|
#include <glm/gtx/matrix_decompose.hpp>
|
||||||
|
|
||||||
|
#include "AssetEditorPanel.h"
|
||||||
#include "Prism/Core/Application.h"
|
#include "Prism/Core/Application.h"
|
||||||
#include "Prism/Core/Math/Math.h"
|
#include "Prism/Core/Math/Math.h"
|
||||||
#include "Prism/Physics/PhysicsLayer.h"
|
#include "Prism/Physics/PhysicsLayer.h"
|
||||||
@ -547,7 +548,7 @@ namespace Prism
|
|||||||
template<typename T, typename UIFunction>
|
template<typename T, typename UIFunction>
|
||||||
static void DrawComponent(const std::string& name, Entity entity, UIFunction uiFunction)
|
static void DrawComponent(const std::string& name, Entity entity, UIFunction uiFunction)
|
||||||
{
|
{
|
||||||
const ImGuiTreeNodeFlags treeNodeFlags = ImGuiTreeNodeFlags_DefaultOpen |
|
constexpr ImGuiTreeNodeFlags treeNodeFlags = ImGuiTreeNodeFlags_DefaultOpen |
|
||||||
ImGuiTreeNodeFlags_Framed |
|
ImGuiTreeNodeFlags_Framed |
|
||||||
ImGuiTreeNodeFlags_SpanAvailWidth |
|
ImGuiTreeNodeFlags_SpanAvailWidth |
|
||||||
ImGuiTreeNodeFlags_AllowOverlap |
|
ImGuiTreeNodeFlags_AllowOverlap |
|
||||||
@ -886,13 +887,50 @@ namespace Prism
|
|||||||
DrawComponent<MeshComponent>("Mesh", entity, [](MeshComponent& meshComponent) {
|
DrawComponent<MeshComponent>("Mesh", entity, [](MeshComponent& meshComponent) {
|
||||||
|
|
||||||
UI::BeginPropertyGrid();
|
UI::BeginPropertyGrid();
|
||||||
UI::PropertyAssetReference("Mesh", meshComponent.Mesh, AssetType::Mesh);
|
|
||||||
// UI::Property("AnimationPlaying", meshComponent.Mesh->m_AnimationPlaying);
|
|
||||||
// UI::Property("TimeMultiple", meshComponent.Mesh->m_TimeMultiplier);
|
|
||||||
// UI::Property("AnimationTime", meshComponent.Mesh->m_AnimationTime);
|
|
||||||
// UI::Property("WorldTime", meshComponent.Mesh->m_WorldTime);
|
|
||||||
|
|
||||||
|
if (UI::PropertyAssetReference("Mesh", meshComponent.Mesh, AssetType::Mesh))
|
||||||
|
{
|
||||||
|
meshComponent.MaterialInstances.clear();
|
||||||
|
meshComponent.MaterialDescs.clear();
|
||||||
|
const auto& materialInstances = meshComponent.Mesh->GetMaterials();
|
||||||
|
for (uint32_t i = 0; i < materialInstances.size(); i++)
|
||||||
|
{
|
||||||
|
Ref<MaterialInstance> materialInstance = MaterialInstance::Copy(materialInstances[i]);
|
||||||
|
meshComponent.MaterialInstances.push_back(materialInstance);
|
||||||
|
}
|
||||||
|
meshComponent.MaterialDescs.resize(materialInstances.size());
|
||||||
|
}
|
||||||
UI::EndPropertyGrid();
|
UI::EndPropertyGrid();
|
||||||
|
|
||||||
|
for (auto i = 0; i < meshComponent.MaterialDescs.size(); i++)
|
||||||
|
{
|
||||||
|
|
||||||
|
// TODO: 这里通过 MaterialDesc进行存储信息,然后修改后由此处更新MaterialInstances,同时还缺少一个在MeshComponent中MaterialDesc的序列化
|
||||||
|
if (UI::BeginTreeNode((std::string("Slot ") + std::to_string(i)).c_str()))
|
||||||
|
{
|
||||||
|
UI::BeginPropertyGrid();
|
||||||
|
if (meshComponent.MaterialDescs[i])
|
||||||
|
{
|
||||||
|
if (ImGui::Button("X"))
|
||||||
|
{
|
||||||
|
meshComponent.MaterialDescs[i] = nullptr;
|
||||||
|
meshComponent.UpdateMaterials(i);
|
||||||
|
}
|
||||||
|
ImGui::SameLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ImGui::Button("Edit")) AssetEditorPanel::OpenEditor(meshComponent.MaterialDescs[i]);
|
||||||
|
ImGui::SameLine();
|
||||||
|
if (UI::PropertyAssetReference(meshComponent.MaterialInstances[i]->GetName().c_str(), meshComponent.MaterialDescs[i], AssetType::Material))
|
||||||
|
{
|
||||||
|
meshComponent.UpdateMaterials(-1, true);
|
||||||
|
}
|
||||||
|
UI::EndPropertyGrid();
|
||||||
|
|
||||||
|
UI::EndTreeNode();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
DrawComponent<AnimationComponent>("AnimatorController", entity, [this](AnimationComponent& animatorComponent)
|
DrawComponent<AnimationComponent>("AnimatorController", entity, [this](AnimationComponent& animatorComponent)
|
||||||
@ -1090,18 +1128,33 @@ namespace Prism
|
|||||||
});
|
});
|
||||||
|
|
||||||
DrawComponent<ScriptComponent>("Script", entity, [=](ScriptComponent& scriptComponent) mutable {
|
DrawComponent<ScriptComponent>("Script", entity, [=](ScriptComponent& scriptComponent) mutable {
|
||||||
UI::BeginPropertyGrid();
|
|
||||||
const std::string oldName = scriptComponent.ModuleName;
|
|
||||||
if (UI::Property("Module Name", scriptComponent.ModuleName, !ScriptEngine::ModuleExists(scriptComponent.ModuleName))) // TODO: no live edit
|
|
||||||
{
|
|
||||||
// Shutdown old script
|
|
||||||
if (ScriptEngine::ModuleExists(oldName))
|
|
||||||
ScriptEngine::ShutdownScriptEntity(entity, oldName);
|
|
||||||
|
|
||||||
if (ScriptEngine::ModuleExists(scriptComponent.ModuleName))
|
const std::string oldName = scriptComponent.ModuleName;
|
||||||
ScriptEngine::InitScriptEntity(entity);
|
|
||||||
|
if (ImGui::BeginCombo("Module Name", scriptComponent.ModuleName.c_str()))
|
||||||
|
{
|
||||||
|
const auto& availableScripts = ScriptEngine::GetAvailableScripts();
|
||||||
|
|
||||||
|
for (const auto& script : availableScripts)
|
||||||
|
{
|
||||||
|
const bool isSelected = (scriptComponent.ModuleName == script);
|
||||||
|
if (ImGui::Selectable(script.c_str(), isSelected))
|
||||||
|
{
|
||||||
|
// 切换逻辑
|
||||||
|
if (ScriptEngine::ModuleExists(oldName))
|
||||||
|
ScriptEngine::ShutdownScriptEntity(entity, oldName);
|
||||||
|
scriptComponent.ModuleName = script;
|
||||||
|
if (ScriptEngine::ModuleExists(scriptComponent.ModuleName))
|
||||||
|
ScriptEngine::InitScriptEntity(entity);
|
||||||
|
}
|
||||||
|
if (isSelected)
|
||||||
|
ImGui::SetItemDefaultFocus();
|
||||||
|
}
|
||||||
|
ImGui::EndCombo();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UI::BeginPropertyGrid();
|
||||||
|
|
||||||
// Public Fields
|
// Public Fields
|
||||||
if (ScriptEngine::ModuleExists(scriptComponent.ModuleName))
|
if (ScriptEngine::ModuleExists(scriptComponent.ModuleName))
|
||||||
{
|
{
|
||||||
@ -1345,7 +1398,7 @@ namespace Prism
|
|||||||
|
|
||||||
if (UI::Property("Size", bcc.Size))
|
if (UI::Property("Size", bcc.Size))
|
||||||
{
|
{
|
||||||
bcc.DebugMesh = MeshFactory::CreateBox(bcc.Size);
|
bcc.DebugMesh = MeshFactory::CreateBox(bcc.Size * 2.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
UI::Property("IsTrigger", bcc.IsTrigger);
|
UI::Property("IsTrigger", bcc.IsTrigger);
|
||||||
|
|||||||
@ -85,7 +85,8 @@ namespace Prism
|
|||||||
|
|
||||||
void Physics3D::Simulate(const TimeStep ts)
|
void Physics3D::Simulate(const TimeStep ts)
|
||||||
{
|
{
|
||||||
|
auto& time = s_SimulationTime;
|
||||||
|
auto& sett = s_Settings;
|
||||||
// TODO: Allow projects to control the fixed step amount
|
// TODO: Allow projects to control the fixed step amount
|
||||||
s_SimulationTime += ts.GetMilliseconds();
|
s_SimulationTime += ts.GetMilliseconds();
|
||||||
|
|
||||||
@ -106,7 +107,7 @@ namespace Prism
|
|||||||
|
|
||||||
void Physics3D::DestroyScene()
|
void Physics3D::DestroyScene()
|
||||||
{
|
{
|
||||||
PM_CORE_ASSERT(s_Scene);
|
if (!s_Scene) return;
|
||||||
|
|
||||||
s_Actors.clear();
|
s_Actors.clear();
|
||||||
s_Scene->release();
|
s_Scene->release();
|
||||||
|
|||||||
@ -11,6 +11,8 @@
|
|||||||
#include "Prism/Script/ScriptEngine.h"
|
#include "Prism/Script/ScriptEngine.h"
|
||||||
#include <glm/gtx/compatibility.hpp>
|
#include <glm/gtx/compatibility.hpp>
|
||||||
|
|
||||||
|
#include "glm/gtx/euler_angles.hpp"
|
||||||
|
|
||||||
namespace Prism
|
namespace Prism
|
||||||
{
|
{
|
||||||
PhysicsActor::PhysicsActor(Entity entity)
|
PhysicsActor::PhysicsActor(Entity entity)
|
||||||
@ -177,15 +179,24 @@ namespace Prism
|
|||||||
Ref<Scene> scene = Scene::GetScene(m_Entity.GetSceneUUID());
|
Ref<Scene> scene = Scene::GetScene(m_Entity.GetSceneUUID());
|
||||||
glm::mat4 transform = scene->GetTransformRelativeToParent(m_Entity);
|
glm::mat4 transform = scene->GetTransformRelativeToParent(m_Entity);
|
||||||
|
|
||||||
if (m_RigidBody.BodyType == RigidBodyComponent::Type::Static)
|
glm::vec3 translation, rotationEuler, scale;
|
||||||
{
|
Math::DecomposeTransform(transform, translation, rotationEuler, scale);
|
||||||
m_ActorInternal = physics.createRigidStatic(ToPhysXTransform(transform));
|
|
||||||
}
|
const glm::mat4 rotMat = glm::eulerAngleYXZ(rotationEuler.y, rotationEuler.x, rotationEuler.z);
|
||||||
else
|
const glm::quat rotationQuat = glm::quat_cast(rotMat);
|
||||||
|
|
||||||
|
physx::PxTransform pxTransform(ToPhysXVector(translation), ToPhysXQuat(rotationQuat));
|
||||||
|
|
||||||
|
// PhysicsActor::Initialize 中
|
||||||
|
m_WorldScale = scale;
|
||||||
|
|
||||||
|
|
||||||
|
if (IsDynamic())
|
||||||
{
|
{
|
||||||
|
|
||||||
const PhysicsSettings& settings = Physics3D::GetSettings();
|
const PhysicsSettings& settings = Physics3D::GetSettings();
|
||||||
|
|
||||||
physx::PxRigidDynamic* actor = physics.createRigidDynamic(ToPhysXTransform(transform));
|
physx::PxRigidDynamic* actor = physics.createRigidDynamic(pxTransform);
|
||||||
actor->setLinearDamping(m_RigidBody.LinearDrag);
|
actor->setLinearDamping(m_RigidBody.LinearDrag);
|
||||||
actor->setAngularDamping(m_RigidBody.AngularDrag);
|
actor->setAngularDamping(m_RigidBody.AngularDrag);
|
||||||
actor->setRigidBodyFlag(physx::PxRigidBodyFlag::eKINEMATIC, m_RigidBody.IsKinematic);
|
actor->setRigidBodyFlag(physx::PxRigidBodyFlag::eKINEMATIC, m_RigidBody.IsKinematic);
|
||||||
@ -198,15 +209,26 @@ namespace Prism
|
|||||||
actor->setActorFlag(physx::PxActorFlag::eDISABLE_GRAVITY, m_RigidBody.DisableGravity);
|
actor->setActorFlag(physx::PxActorFlag::eDISABLE_GRAVITY, m_RigidBody.DisableGravity);
|
||||||
actor->setSolverIterationCounts(settings.SolverIterations, settings.SolverVelocityIterations);
|
actor->setSolverIterationCounts(settings.SolverIterations, settings.SolverVelocityIterations);
|
||||||
|
|
||||||
physx::PxRigidBodyExt::setMassAndUpdateInertia(*actor, m_RigidBody.Mass);
|
|
||||||
m_ActorInternal = actor;
|
m_ActorInternal = actor;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_ActorInternal = physics.createRigidStatic(pxTransform);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add Collider
|
||||||
if (m_Entity.HasComponent<BoxColliderComponent>()) PhysicsWrappers::AddBoxCollider(*this);
|
if (m_Entity.HasComponent<BoxColliderComponent>()) PhysicsWrappers::AddBoxCollider(*this);
|
||||||
if (m_Entity.HasComponent<SphereColliderComponent>()) PhysicsWrappers::AddSphereCollider(*this);
|
if (m_Entity.HasComponent<SphereColliderComponent>()) PhysicsWrappers::AddSphereCollider(*this);
|
||||||
if (m_Entity.HasComponent<CapsuleColliderComponent>()) PhysicsWrappers::AddCapsuleCollider(*this);
|
if (m_Entity.HasComponent<CapsuleColliderComponent>()) PhysicsWrappers::AddCapsuleCollider(*this);
|
||||||
if (m_Entity.HasComponent<MeshColliderComponent>()) PhysicsWrappers::AddMeshCollider(*this);
|
if (m_Entity.HasComponent<MeshColliderComponent>()) PhysicsWrappers::AddMeshCollider(*this);
|
||||||
|
|
||||||
|
|
||||||
|
if (IsDynamic())
|
||||||
|
{
|
||||||
|
auto* dynamicActor = static_cast<physx::PxRigidDynamic*>(m_ActorInternal);
|
||||||
|
physx::PxRigidBodyExt::setMassAndUpdateInertia(*dynamicActor, m_RigidBody.Mass);
|
||||||
|
}
|
||||||
|
|
||||||
if (!PhysicsLayerManager::IsLayerValid(m_RigidBody.Layer))
|
if (!PhysicsLayerManager::IsLayerValid(m_RigidBody.Layer))
|
||||||
m_RigidBody.Layer = 0;
|
m_RigidBody.Layer = 0;
|
||||||
|
|
||||||
|
|||||||
@ -49,6 +49,8 @@ namespace Prism
|
|||||||
|
|
||||||
Entity& GetEntity() { return m_Entity; }
|
Entity& GetEntity() { return m_Entity; }
|
||||||
|
|
||||||
|
glm::vec3 GetWorldScale() const { return m_WorldScale; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void Initialize();
|
void Initialize();
|
||||||
void Spawn() const;
|
void Spawn() const;
|
||||||
@ -64,6 +66,8 @@ namespace Prism
|
|||||||
|
|
||||||
physx::PxRigidActor* m_ActorInternal;
|
physx::PxRigidActor* m_ActorInternal;
|
||||||
|
|
||||||
|
glm::vec3 m_WorldScale = glm::vec3(1.0f);
|
||||||
|
|
||||||
friend class Physics3D;
|
friend class Physics3D;
|
||||||
friend class PhysicsWrappers;
|
friend class PhysicsWrappers;
|
||||||
|
|
||||||
|
|||||||
@ -36,12 +36,12 @@ namespace Prism
|
|||||||
|
|
||||||
physx::PxVec3 ToPhysXVector(const glm::vec3& vector)
|
physx::PxVec3 ToPhysXVector(const glm::vec3& vector)
|
||||||
{
|
{
|
||||||
return *(physx::PxVec3*)&vector;
|
return physx::PxVec3(vector.x, vector.y, vector.z);
|
||||||
}
|
}
|
||||||
|
|
||||||
physx::PxVec4 ToPhysXVector(const glm::vec4& vector)
|
physx::PxVec4 ToPhysXVector(const glm::vec4& vector)
|
||||||
{
|
{
|
||||||
return *(physx::PxVec4*)&vector;
|
return physx::PxVec4(vector.x, vector.y, vector.z, vector.w);
|
||||||
}
|
}
|
||||||
|
|
||||||
physx::PxQuat ToPhysXQuat(const glm::quat& quat)
|
physx::PxQuat ToPhysXQuat(const glm::quat& quat)
|
||||||
|
|||||||
@ -184,16 +184,11 @@ namespace Prism
|
|||||||
auto& collider = actor.m_Entity.GetComponent<BoxColliderComponent>();
|
auto& collider = actor.m_Entity.GetComponent<BoxColliderComponent>();
|
||||||
|
|
||||||
if (!collider.Material)
|
if (!collider.Material)
|
||||||
collider.Material = Ref<PhysicsMaterial>::Create(0.6F, 0.6F, 0.0f);
|
collider.Material = Ref<PhysicsMaterialAsset>::Create(0.6F, 0.6F, 0.0f);
|
||||||
|
|
||||||
const glm::vec3 scale = actor.m_Entity.Transform().Scale;
|
glm::vec3 colliderSize = collider.Size * actor.GetWorldScale();
|
||||||
glm::vec3 colliderSize = collider.Size;
|
|
||||||
|
|
||||||
if (scale.x != 0.0f) colliderSize.x *= scale.x;
|
const auto boxGeometry = physx::PxBoxGeometry(colliderSize.x, colliderSize.y, colliderSize.z);
|
||||||
if (scale.y != 0.0f) colliderSize.y *= scale.y;
|
|
||||||
if (scale.z != 0.0f) colliderSize.z *= scale.z;
|
|
||||||
|
|
||||||
const auto boxGeometry = physx::PxBoxGeometry(colliderSize.x / 2.0f, colliderSize.y / 2.0f, colliderSize.z / 2.0f);
|
|
||||||
const physx::PxMaterial* material = s_Physics->createMaterial(collider.Material->StaticFriction, collider.Material->DynamicFriction, collider.Material->Bounciness);
|
const physx::PxMaterial* material = s_Physics->createMaterial(collider.Material->StaticFriction, collider.Material->DynamicFriction, collider.Material->Bounciness);
|
||||||
physx::PxShape* shape = physx::PxRigidActorExt::createExclusiveShape(*actor.m_ActorInternal, boxGeometry, *material);
|
physx::PxShape* shape = physx::PxRigidActorExt::createExclusiveShape(*actor.m_ActorInternal, boxGeometry, *material);
|
||||||
|
|
||||||
@ -207,7 +202,7 @@ namespace Prism
|
|||||||
{
|
{
|
||||||
auto& collider = actor.m_Entity.GetComponent<SphereColliderComponent>();
|
auto& collider = actor.m_Entity.GetComponent<SphereColliderComponent>();
|
||||||
if (!collider.Material)
|
if (!collider.Material)
|
||||||
collider.Material = Ref<PhysicsMaterial>::Create(0.6F, 0.6F, 0.0f);
|
collider.Material = Ref<PhysicsMaterialAsset>::Create(0.6F, 0.6F, 0.0f);
|
||||||
|
|
||||||
const glm::vec3 scale = actor.m_Entity.Transform().Scale;
|
const glm::vec3 scale = actor.m_Entity.Transform().Scale;
|
||||||
float colliderRadius = collider.Radius;
|
float colliderRadius = collider.Radius;
|
||||||
@ -227,7 +222,7 @@ namespace Prism
|
|||||||
{
|
{
|
||||||
auto& collider = actor.m_Entity.GetComponent<CapsuleColliderComponent>();
|
auto& collider = actor.m_Entity.GetComponent<CapsuleColliderComponent>();
|
||||||
if (!collider.Material)
|
if (!collider.Material)
|
||||||
collider.Material = Ref<PhysicsMaterial>::Create(0.6F, 0.6F, 0.0f);
|
collider.Material = Ref<PhysicsMaterialAsset>::Create(0.6F, 0.6F, 0.0f);
|
||||||
|
|
||||||
const glm::vec3 scale = actor.m_Entity.Transform().Scale;
|
const glm::vec3 scale = actor.m_Entity.Transform().Scale;
|
||||||
float colliderRadius = collider.Radius;
|
float colliderRadius = collider.Radius;
|
||||||
@ -255,7 +250,7 @@ namespace Prism
|
|||||||
{
|
{
|
||||||
auto& collider = actor.m_Entity.GetComponent<MeshColliderComponent>();
|
auto& collider = actor.m_Entity.GetComponent<MeshColliderComponent>();
|
||||||
if (!collider.Material)
|
if (!collider.Material)
|
||||||
collider.Material = Ref<PhysicsMaterial>::Create(0.6f, 0.6f, 0.0f);
|
collider.Material = Ref<PhysicsMaterialAsset>::Create(0.6f, 0.6f, 0.0f);
|
||||||
|
|
||||||
glm::vec3 scale = actor.m_Entity.Transform().Scale;
|
glm::vec3 scale = actor.m_Entity.Transform().Scale;
|
||||||
physx::PxMaterial* material = s_Physics->createMaterial(collider.Material->StaticFriction, collider.Material->DynamicFriction, collider.Material->Bounciness);
|
physx::PxMaterial* material = s_Physics->createMaterial(collider.Material->StaticFriction, collider.Material->DynamicFriction, collider.Material->Bounciness);
|
||||||
|
|||||||
@ -75,8 +75,8 @@ namespace Prism
|
|||||||
{
|
{
|
||||||
glTexStorage2D(GL_TEXTURE_2D, 1, format, width, height);
|
glTexStorage2D(GL_TEXTURE_2D, 1, format, width, height);
|
||||||
|
|
||||||
glTexParameteri(TextureTarget(multisampled), GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
glTexParameteri(TextureTarget(multisampled), GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
glTexParameteri(TextureTarget(multisampled), GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
glTexParameteri(TextureTarget(multisampled), GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
glTexParameteri(TextureTarget(multisampled), GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
glTexParameteri(TextureTarget(multisampled), GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
glTexParameteri(TextureTarget(multisampled), GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
glTexParameteri(TextureTarget(multisampled), GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
}
|
}
|
||||||
@ -230,4 +230,12 @@ namespace Prism
|
|||||||
glBindTextureUnit(slot, instance->m_ColorAttachments[attachmentIndex]);
|
glBindTextureUnit(slot, instance->m_ColorAttachments[attachmentIndex]);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OpenGLFrameBuffer::BindDepthTexture(uint32_t slot) const
|
||||||
|
{
|
||||||
|
Ref<const OpenGLFrameBuffer> instance = this;
|
||||||
|
Renderer::Submit([instance, slot]() {
|
||||||
|
glBindTextureUnit(slot, instance->m_DepthAttachment);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,6 +21,7 @@ namespace Prism
|
|||||||
void Resize(uint32_t width, uint32_t height, bool forceReCreate) override;
|
void Resize(uint32_t width, uint32_t height, bool forceReCreate) override;
|
||||||
|
|
||||||
void BindTexture(uint32_t attachmentIndex, uint32_t slot) const override;
|
void BindTexture(uint32_t attachmentIndex, uint32_t slot) const override;
|
||||||
|
void BindDepthTexture(uint32_t slot = 0) const override;
|
||||||
|
|
||||||
uint32_t GetWidth() const override { return m_Specification.Width; }
|
uint32_t GetWidth() const override { return m_Specification.Width; }
|
||||||
uint32_t GetHeight() const override { return m_Specification.Height; }
|
uint32_t GetHeight() const override { return m_Specification.Height; }
|
||||||
|
|||||||
@ -15,8 +15,8 @@ namespace Prism
|
|||||||
OpenGLRenderPass(const RenderPassSpecification& spec);
|
OpenGLRenderPass(const RenderPassSpecification& spec);
|
||||||
virtual ~OpenGLRenderPass();
|
virtual ~OpenGLRenderPass();
|
||||||
|
|
||||||
virtual RenderPassSpecification& GetSpecification() override { return m_Spec; }
|
RenderPassSpecification& GetSpecification() override { return m_Spec; }
|
||||||
virtual const RenderPassSpecification& GetSpecification() const override { return m_Spec; }
|
const RenderPassSpecification& GetSpecification() const override { return m_Spec; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
RenderPassSpecification m_Spec;
|
RenderPassSpecification m_Spec;
|
||||||
|
|||||||
@ -157,10 +157,13 @@ namespace Prism
|
|||||||
glClearColor(r, g, b, a);
|
glClearColor(r, g, b, a);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RendererAPI::DrawIndexed(uint32_t count, PrimitiveType type, bool depthTest, bool faceCulling)
|
void RendererAPI::DrawIndexed(const uint32_t count, const PrimitiveType type, const bool depthTest, const bool faceCulling)
|
||||||
{
|
{
|
||||||
if (!depthTest)
|
if (!depthTest)
|
||||||
|
{
|
||||||
glDisable(GL_DEPTH_TEST);
|
glDisable(GL_DEPTH_TEST);
|
||||||
|
glDisable(GL_BLEND);
|
||||||
|
}
|
||||||
|
|
||||||
GLenum glPrimitiveType = 0;
|
GLenum glPrimitiveType = 0;
|
||||||
switch (type)
|
switch (type)
|
||||||
@ -181,7 +184,10 @@ namespace Prism
|
|||||||
glDrawElements(glPrimitiveType, count, GL_UNSIGNED_INT, nullptr);
|
glDrawElements(glPrimitiveType, count, GL_UNSIGNED_INT, nullptr);
|
||||||
|
|
||||||
if (!depthTest)
|
if (!depthTest)
|
||||||
|
{
|
||||||
|
glEnable(GL_BLEND);
|
||||||
glEnable(GL_DEPTH_TEST);
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RendererAPI::SetLineThickness(const float thickness)
|
void RendererAPI::SetLineThickness(const float thickness)
|
||||||
|
|||||||
@ -54,7 +54,7 @@ namespace Prism
|
|||||||
// Texture2D
|
// Texture2D
|
||||||
// ******************************************
|
// ******************************************
|
||||||
|
|
||||||
OpenGLTexture2D::OpenGLTexture2D(TextureFormat format, uint32_t width, uint32_t height, TextureWrap wrap)
|
OpenGLTexture2D::OpenGLTexture2D(const TextureFormat format, const uint32_t width, const uint32_t height, const TextureWrap wrap)
|
||||||
: m_Format(format), m_Width(width), m_Height(height), m_Wrap(wrap)
|
: m_Format(format), m_Width(width), m_Height(height), m_Wrap(wrap)
|
||||||
{
|
{
|
||||||
Ref<OpenGLTexture2D> instance = this;
|
Ref<OpenGLTexture2D> instance = this;
|
||||||
@ -83,6 +83,53 @@ namespace Prism
|
|||||||
m_ImageData.Allocate(width * height * GetBPP(m_Format));
|
m_ImageData.Allocate(width * height * GetBPP(m_Format));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
OpenGLTexture2D::OpenGLTexture2D(const TextureFormat format, const uint32_t width, const uint32_t height, const void* data, const TextureWrap wrap)
|
||||||
|
: m_Format(format), m_Width(width), m_Height(height), m_Wrap(wrap)
|
||||||
|
{
|
||||||
|
// 计算图像数据大小(假设是 RGBA8,或根据格式动态计算)
|
||||||
|
uint32_t bpp = GetBPP(format);
|
||||||
|
uint32_t dataSize = width * height * bpp;
|
||||||
|
|
||||||
|
// 保存一份数据到 CPU 缓冲区(供后续可能的读取)
|
||||||
|
if (data)
|
||||||
|
{
|
||||||
|
m_ImageData.Allocate(dataSize);
|
||||||
|
memcpy(m_ImageData.Data, data, dataSize);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_ImageData.Allocate(dataSize);
|
||||||
|
memset(m_ImageData.Data, 0, dataSize); // 可选:初始化为0
|
||||||
|
}
|
||||||
|
|
||||||
|
Ref<OpenGLTexture2D> instance = this;
|
||||||
|
Renderer::Submit([instance]() mutable {
|
||||||
|
glGenTextures(1, &instance->m_RendererID);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, instance->m_RendererID);
|
||||||
|
|
||||||
|
// 设置纹理参数
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
GLint wrap = instance->m_Wrap == TextureWrap::Clamp ? GL_CLAMP_TO_EDGE : GL_REPEAT;
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap);
|
||||||
|
glTextureParameterf(instance->m_RendererID, GL_TEXTURE_MAX_ANISOTROPY, RendererAPI::GetCapabilities().MaxAnisotropy);
|
||||||
|
|
||||||
|
// 上传数据(如果已有数据则使用,否则传 nullptr 创建空纹理)
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0,
|
||||||
|
SizedInternalFormat(instance->m_Format),
|
||||||
|
(GLint)instance->m_Width, (GLint)instance->m_Height, 0,
|
||||||
|
ImageFormat(instance->m_Format),
|
||||||
|
DataType(instance->m_Format),
|
||||||
|
instance->m_ImageData.Data); // 这里传入数据指针
|
||||||
|
|
||||||
|
// 如果需要生成 mipmap,取消注释下一行
|
||||||
|
// glGenerateMipmap(GL_TEXTURE_2D);
|
||||||
|
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
OpenGLTexture2D::OpenGLTexture2D(const std::string& path, bool srgb)
|
OpenGLTexture2D::OpenGLTexture2D(const std::string& path, bool srgb)
|
||||||
: m_FilePath(path)
|
: m_FilePath(path)
|
||||||
@ -186,7 +233,7 @@ namespace Prism
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLTexture2D::SetData(const void* data, int count)
|
void OpenGLTexture2D::SetData(const void* data, uint32_t count)
|
||||||
{
|
{
|
||||||
Lock();
|
Lock();
|
||||||
|
|
||||||
|
|||||||
@ -14,6 +14,7 @@ namespace Prism
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
OpenGLTexture2D(TextureFormat format, uint32_t width, uint32_t height, TextureWrap wrap);
|
OpenGLTexture2D(TextureFormat format, uint32_t width, uint32_t height, TextureWrap wrap);
|
||||||
|
OpenGLTexture2D(TextureFormat format, uint32_t width, uint32_t height, const void* data, TextureWrap wrap = TextureWrap::Clamp);
|
||||||
OpenGLTexture2D(const std::string& path, bool srgb);
|
OpenGLTexture2D(const std::string& path, bool srgb);
|
||||||
virtual ~OpenGLTexture2D();
|
virtual ~OpenGLTexture2D();
|
||||||
|
|
||||||
@ -30,7 +31,7 @@ namespace Prism
|
|||||||
virtual void Lock() override;
|
virtual void Lock() override;
|
||||||
virtual void Unlock() override;
|
virtual void Unlock() override;
|
||||||
|
|
||||||
virtual void SetData(const void* data, int count) override;
|
virtual void SetData(const void* data, uint32_t count) override;
|
||||||
|
|
||||||
virtual void Resize(uint32_t width, uint32_t height) override;
|
virtual void Resize(uint32_t width, uint32_t height) override;
|
||||||
virtual Buffer GetWriteableBuffer() override;
|
virtual Buffer GetWriteableBuffer() override;
|
||||||
|
|||||||
@ -16,6 +16,7 @@
|
|||||||
#include "Prism/Core/Application.h"
|
#include "Prism/Core/Application.h"
|
||||||
|
|
||||||
#include "efsw/efsw.hpp"
|
#include "efsw/efsw.hpp"
|
||||||
|
#include "Prism/Utilities/StringUtils.h"
|
||||||
|
|
||||||
namespace Prism
|
namespace Prism
|
||||||
{
|
{
|
||||||
@ -30,20 +31,22 @@ namespace Prism
|
|||||||
public:
|
public:
|
||||||
void handleFileAction(efsw::WatchID watchid,
|
void handleFileAction(efsw::WatchID watchid,
|
||||||
const std::string& dir,
|
const std::string& dir,
|
||||||
const std::string& filename,
|
const std::string& filepath,
|
||||||
efsw::Action action,
|
efsw::Action action,
|
||||||
std::string oldFilename = "") override
|
std::string oldFilepath = "") override
|
||||||
{
|
{
|
||||||
// 如果引擎自身操作设置了忽略标志,则跳过本次事件
|
// 如果引擎自身操作设置了忽略标志,则跳过本次事件
|
||||||
if (FileSystem::s_IgnoreNextChange.load())
|
if (FileSystem::s_IgnoreNextChange.load())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
std::filesystem::path fullPath = std::filesystem::path(dir) / filename;
|
std::string fullPath = (std::filesystem::path(dir) / filepath).string();
|
||||||
|
|
||||||
|
fullPath = Utils::NormalizePath(fullPath);
|
||||||
|
|
||||||
FileSystemChangedEvent e;
|
FileSystemChangedEvent e;
|
||||||
e.FilePath = fullPath.string();
|
e.FilePath = fullPath;
|
||||||
e.NewName = filename;
|
e.NewName = Utils::GetFilename(filepath);
|
||||||
e.OldName = oldFilename; // efsw 在重命名时会提供旧文件名
|
e.OldName = Utils::GetFilename(oldFilepath); // efsw 在重命名时会提供旧文件名
|
||||||
e.IsDirectory = false; // 稍后根据实际情况判断
|
e.IsDirectory = false; // 稍后根据实际情况判断
|
||||||
|
|
||||||
// 判断是否为目录(可能抛出异常,使用 error_code 版本)
|
// 判断是否为目录(可能抛出异常,使用 error_code 版本)
|
||||||
@ -161,6 +164,30 @@ namespace Prism
|
|||||||
return result ? std::string(result) : std::string();
|
return result ? std::string(result) : std::string();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FileSystem::OpenInExplorer(const std::string& path)
|
||||||
|
{
|
||||||
|
const std::filesystem::path absPath = std::filesystem::absolute(path);
|
||||||
|
if (!std::filesystem::exists(absPath))
|
||||||
|
{
|
||||||
|
PM_CORE_WARN("Path does not exist: {}", path);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string cmd;
|
||||||
|
if (std::filesystem::is_directory(absPath))
|
||||||
|
{
|
||||||
|
// 打开目录
|
||||||
|
cmd = absPath.string();
|
||||||
|
ShellExecuteA(nullptr, "open", "explorer.exe", cmd.c_str(), NULL, SW_SHOW);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 打开并选中文件
|
||||||
|
cmd = "/select, \"" + absPath.string() + "\"";
|
||||||
|
ShellExecuteA(nullptr, "open", "explorer.exe", cmd.c_str(), NULL, SW_SHOW);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool FileSystem::CreateFolder(const std::filesystem::path& filepath)
|
bool FileSystem::CreateFolder(const std::filesystem::path& filepath)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -62,7 +62,7 @@ namespace Prism
|
|||||||
m_Data.VSync = enable;
|
m_Data.VSync = enable;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<float, float> WindowsWindow::GetWindowPos() const
|
glm::vec2 WindowsWindow::GetWindowPos() const
|
||||||
{
|
{
|
||||||
int x, y;
|
int x, y;
|
||||||
glfwGetWindowPos(m_Window, &x, &y);
|
glfwGetWindowPos(m_Window, &x, &y);
|
||||||
@ -91,6 +91,8 @@ namespace Prism
|
|||||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 5);
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 5);
|
||||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||||
|
|
||||||
|
glfwWindowHint(GLFW_DEPTH_BITS, 24);
|
||||||
|
|
||||||
s_GLFWInitialized = true;
|
s_GLFWInitialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -119,16 +121,37 @@ namespace Prism
|
|||||||
|
|
||||||
glfwSetWindowCloseCallback(m_Window, [](GLFWwindow* window)
|
glfwSetWindowCloseCallback(m_Window, [](GLFWwindow* window)
|
||||||
{
|
{
|
||||||
auto& data = *((WindowData*)glfwGetWindowUserPointer(window));
|
const auto& data = *((WindowData*)glfwGetWindowUserPointer(window));
|
||||||
|
|
||||||
WindowCloseEvent event;
|
WindowCloseEvent event;
|
||||||
data.EventCallback(event);
|
data.EventCallback(event);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
glfwSetWindowFocusCallback(m_Window, [](GLFWwindow* window, const int focused) {
|
||||||
|
const auto& data = *((WindowData*)glfwGetWindowUserPointer(window));
|
||||||
|
|
||||||
|
if (focused)
|
||||||
|
{
|
||||||
|
WindowFocusEvent event;
|
||||||
|
data.EventCallback(event);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
WindowLostFocusEvent event;
|
||||||
|
data.EventCallback(event);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
glfwSetWindowPosCallback(m_Window, [](GLFWwindow* window, int xpos, int ypos) {
|
||||||
|
const auto& data = *((WindowData*)glfwGetWindowUserPointer(window));
|
||||||
|
|
||||||
|
WindowMovedEvent event(xpos, ypos);
|
||||||
|
data.EventCallback(event);
|
||||||
|
});
|
||||||
|
|
||||||
glfwSetKeyCallback(m_Window, [](GLFWwindow* window, int key, int scancode, int action, int mods)
|
glfwSetKeyCallback(m_Window, [](GLFWwindow* window, int key, int scancode, int action, int mods)
|
||||||
{
|
{
|
||||||
auto& data = *((WindowData*)glfwGetWindowUserPointer(window));
|
const auto& data = *((WindowData*)glfwGetWindowUserPointer(window));
|
||||||
|
|
||||||
switch (action)
|
switch (action)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -27,8 +27,8 @@ namespace Prism
|
|||||||
|
|
||||||
bool const IsVSync() const override { return m_Data.VSync; }
|
bool const IsVSync() const override { return m_Data.VSync; }
|
||||||
void SetVSync(bool enable) override;
|
void SetVSync(bool enable) override;
|
||||||
virtual std::pair<uint32_t, uint32_t> GetSize() const override { return { m_Data.Width, m_Data.Height }; }
|
virtual glm::ivec2 GetSize() const override { return { m_Data.Width, m_Data.Height }; }
|
||||||
virtual std::pair<float, float> GetWindowPos() const override;
|
virtual glm::vec2 GetWindowPos() const override;
|
||||||
|
|
||||||
virtual const std::string& GetTitle() const override { return m_Data.Title; }
|
virtual const std::string& GetTitle() const override { return m_Data.Title; }
|
||||||
virtual void SetTitle(const std::string& title) override;
|
virtual void SetTitle(const std::string& title) override;
|
||||||
|
|||||||
@ -78,6 +78,7 @@ namespace Prism
|
|||||||
virtual void Resize(uint32_t width, uint32_t height, bool forceReCreate = false) = 0;
|
virtual void Resize(uint32_t width, uint32_t height, bool forceReCreate = false) = 0;
|
||||||
|
|
||||||
virtual void BindTexture(uint32_t attachmentIndex = 0, uint32_t slot = 0) const = 0;
|
virtual void BindTexture(uint32_t attachmentIndex = 0, uint32_t slot = 0) const = 0;
|
||||||
|
virtual void BindDepthTexture(uint32_t slot = 0) const = 0;
|
||||||
|
|
||||||
virtual uint32_t GetWidth() const = 0;
|
virtual uint32_t GetWidth() const = 0;
|
||||||
virtual uint32_t GetHeight() const = 0;
|
virtual uint32_t GetHeight() const = 0;
|
||||||
|
|||||||
@ -140,6 +140,27 @@ namespace Prism
|
|||||||
return Ref<MaterialInstance>::Create(material);
|
return Ref<MaterialInstance>::Create(material);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Ref<MaterialInstance> MaterialInstance::Copy(Ref<MaterialInstance> other)
|
||||||
|
{
|
||||||
|
if (!other) return nullptr;
|
||||||
|
|
||||||
|
auto newInstance = Create(other->m_Material);
|
||||||
|
newInstance->m_Name = other->m_Name + "_Override";
|
||||||
|
|
||||||
|
// 复制 uniform 缓冲区
|
||||||
|
newInstance->m_VSUniformStorageBuffer = Buffer::Copy(other->m_VSUniformStorageBuffer.Data, other->m_VSUniformStorageBuffer.GetSize());
|
||||||
|
newInstance->m_PSUniformStorageBuffer = Buffer::Copy(other->m_PSUniformStorageBuffer.Data, other->m_PSUniformStorageBuffer.GetSize());
|
||||||
|
|
||||||
|
// 复制纹理列表(共享纹理引用)
|
||||||
|
newInstance->m_Textures = other->m_Textures;
|
||||||
|
|
||||||
|
// 复制覆盖标记集合
|
||||||
|
newInstance->m_OverriddenValues = other->m_OverriddenValues;
|
||||||
|
|
||||||
|
return newInstance;
|
||||||
|
}
|
||||||
|
|
||||||
void MaterialInstance::OnShaderReloaded()
|
void MaterialInstance::OnShaderReloaded()
|
||||||
{
|
{
|
||||||
AllocateStorage();
|
AllocateStorage();
|
||||||
|
|||||||
@ -119,6 +119,11 @@ namespace Prism
|
|||||||
|
|
||||||
static Ref<MaterialInstance> Create(const Ref<Material>& material);
|
static Ref<MaterialInstance> Create(const Ref<Material>& material);
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param other copy other data to a new Data
|
||||||
|
* @return the new Data will as Ref return
|
||||||
|
*/
|
||||||
static Ref<MaterialInstance> Copy(Ref<MaterialInstance> other);
|
static Ref<MaterialInstance> Copy(Ref<MaterialInstance> other);
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
|||||||
@ -64,6 +64,13 @@ namespace Prism
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static AABB UnionAABB(const AABB& a, const AABB& b) {
|
||||||
|
AABB result;
|
||||||
|
result.Min = glm::min(a.Min, b.Min);
|
||||||
|
result.Max = glm::max(a.Max, b.Max);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void AnimatedVertex::AddBoneData(uint32_t BoneID, float Weight)
|
void AnimatedVertex::AddBoneData(uint32_t BoneID, float Weight)
|
||||||
{
|
{
|
||||||
@ -300,9 +307,9 @@ namespace Prism
|
|||||||
std::string texturePath = parentPath.string();
|
std::string texturePath = parentPath.string();
|
||||||
|
|
||||||
PM_MESH_LOG(" Albedo map path = {0}", texturePath);
|
PM_MESH_LOG(" Albedo map path = {0}", texturePath);
|
||||||
auto texture = AssetsManager::GetAsset<Texture2D>(texturePath);
|
auto texture = AssetsManager::TryGetAsset<Texture2D>(texturePath);
|
||||||
// auto texture = Texture2D::Create(texturePath, true);
|
// auto texture = Texture2D::Create(texturePath, true);
|
||||||
if (texture->Loaded())
|
if (texture && texture->Loaded())
|
||||||
{
|
{
|
||||||
m_Textures[i] = texture;
|
m_Textures[i] = texture;
|
||||||
mi->Set("u_AlbedoTexture", m_Textures[i]);
|
mi->Set("u_AlbedoTexture", m_Textures[i]);
|
||||||
@ -333,9 +340,9 @@ namespace Prism
|
|||||||
std::string texturePath = parentPath.string();
|
std::string texturePath = parentPath.string();
|
||||||
|
|
||||||
PM_MESH_LOG(" Normal map path = {0}", texturePath);
|
PM_MESH_LOG(" Normal map path = {0}", texturePath);
|
||||||
auto texture = AssetsManager::GetAsset<Texture2D>(texturePath);
|
auto texture = AssetsManager::TryGetAsset<Texture2D>(texturePath);
|
||||||
// auto texture = Texture2D::Create(texturePath);
|
// auto texture = Texture2D::Create(texturePath);
|
||||||
if (texture->Loaded())
|
if (texture && texture->Loaded())
|
||||||
{
|
{
|
||||||
mi->Set("u_NormalTexture", texture);
|
mi->Set("u_NormalTexture", texture);
|
||||||
mi->Set("u_NormalTexToggle", 1.0f);
|
mi->Set("u_NormalTexToggle", 1.0f);
|
||||||
@ -362,9 +369,9 @@ namespace Prism
|
|||||||
std::string texturePath = parentPath.string();
|
std::string texturePath = parentPath.string();
|
||||||
|
|
||||||
PM_MESH_LOG(" Roughness map path = {0}", texturePath);
|
PM_MESH_LOG(" Roughness map path = {0}", texturePath);
|
||||||
auto texture = AssetsManager::GetAsset<Texture2D>(texturePath);
|
auto texture = AssetsManager::TryGetAsset<Texture2D>(texturePath);
|
||||||
// auto texture = Texture2D::Create(texturePath);
|
// auto texture = Texture2D::Create(texturePath);
|
||||||
if (texture->Loaded())
|
if (texture && texture->Loaded())
|
||||||
{
|
{
|
||||||
PM_CORE_TRACE(" Roughness map path = {0}", texturePath);
|
PM_CORE_TRACE(" Roughness map path = {0}", texturePath);
|
||||||
mi->Set("u_RoughnessTexture", texture);
|
mi->Set("u_RoughnessTexture", texture);
|
||||||
@ -458,9 +465,9 @@ namespace Prism
|
|||||||
|
|
||||||
|
|
||||||
PM_MESH_LOG(" Metalness map path = {0}", texturePath);
|
PM_MESH_LOG(" Metalness map path = {0}", texturePath);
|
||||||
auto texture = AssetsManager::GetAsset<Texture2D>(texturePath);
|
auto texture = AssetsManager::TryGetAsset<Texture2D>(texturePath);
|
||||||
// auto texture = Texture2D::Create(texturePath);
|
// auto texture = Texture2D::Create(texturePath);
|
||||||
if (texture->Loaded())
|
if (texture && texture->Loaded())
|
||||||
{
|
{
|
||||||
mi->Set("u_MetalnessTexture", texture);
|
mi->Set("u_MetalnessTexture", texture);
|
||||||
mi->Set("u_MetalnessTexToggle", 1.0f);
|
mi->Set("u_MetalnessTexToggle", 1.0f);
|
||||||
@ -517,6 +524,32 @@ namespace Prism
|
|||||||
PipelineSpecification pipelineSpecification;
|
PipelineSpecification pipelineSpecification;
|
||||||
pipelineSpecification.Layout = vertexBufferLayout;
|
pipelineSpecification.Layout = vertexBufferLayout;
|
||||||
m_Pipeline = Pipeline::Create(pipelineSpecification);
|
m_Pipeline = Pipeline::Create(pipelineSpecification);
|
||||||
|
|
||||||
|
|
||||||
|
if (!m_IsAnimated)
|
||||||
|
{
|
||||||
|
for (const auto& submesh : m_Submeshes) {
|
||||||
|
glm::vec3 corners[8];
|
||||||
|
corners[0] = submesh.Transform * glm::vec4(submesh.BoundingBox.Min, 1.0f);
|
||||||
|
corners[1] = submesh.Transform * glm::vec4(submesh.BoundingBox.Max, 1.0f);
|
||||||
|
corners[2] = submesh.Transform * glm::vec4(glm::vec3(submesh.BoundingBox.Min.x, submesh.BoundingBox.Min.y, submesh.BoundingBox.Max.z), 1.0f);
|
||||||
|
corners[3] = submesh.Transform * glm::vec4(glm::vec3(submesh.BoundingBox.Min.x, submesh.BoundingBox.Max.y, submesh.BoundingBox.Min.z), 1.0f);
|
||||||
|
corners[4] = submesh.Transform * glm::vec4(glm::vec3(submesh.BoundingBox.Min.x, submesh.BoundingBox.Max.y, submesh.BoundingBox.Max.z), 1.0f);
|
||||||
|
corners[5] = submesh.Transform * glm::vec4(glm::vec3(submesh.BoundingBox.Max.x, submesh.BoundingBox.Min.y, submesh.BoundingBox.Min.z), 1.0f);
|
||||||
|
corners[6] = submesh.Transform * glm::vec4(glm::vec3(submesh.BoundingBox.Max.x, submesh.BoundingBox.Min.y, submesh.BoundingBox.Max.z), 1.0f);
|
||||||
|
corners[7] = submesh.Transform * glm::vec4(glm::vec3(submesh.BoundingBox.Max.x, submesh.BoundingBox.Max.y, submesh.BoundingBox.Min.z), 1.0f);
|
||||||
|
|
||||||
|
AABB transformedAABB;
|
||||||
|
transformedAABB.Min = corners[0];
|
||||||
|
transformedAABB.Max = corners[0];
|
||||||
|
for (int i = 1; i < 8; ++i) {
|
||||||
|
transformedAABB.Min = glm::min(transformedAABB.Min, corners[i]);
|
||||||
|
transformedAABB.Max = glm::max(transformedAABB.Max, corners[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_BoundingBox = UnionAABB(m_BoundingBox, transformedAABB);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Mesh::Mesh(const std::vector<Vertex>& vertices, const std::vector<Index>& indices, const glm::mat4& transform)
|
Mesh::Mesh(const std::vector<Vertex>& vertices, const std::vector<Index>& indices, const glm::mat4& transform)
|
||||||
@ -541,6 +574,16 @@ namespace Prism
|
|||||||
{ ShaderDataType::Float2, "a_TexCoord" },
|
{ ShaderDataType::Float2, "a_TexCoord" },
|
||||||
};
|
};
|
||||||
m_Pipeline = Pipeline::Create(pipelineSpecification);
|
m_Pipeline = Pipeline::Create(pipelineSpecification);
|
||||||
|
|
||||||
|
|
||||||
|
// boundingbox
|
||||||
|
m_BoundingBox.Min = glm::vec3(FLT_MAX);
|
||||||
|
m_BoundingBox.Max = glm::vec3(-FLT_MAX);
|
||||||
|
for (const auto& vertex : vertices) {
|
||||||
|
glm::vec3 transformedPos = transform * glm::vec4(vertex.Position, 1.0f);
|
||||||
|
m_BoundingBox.Min = glm::min(m_BoundingBox.Min, transformedPos);
|
||||||
|
m_BoundingBox.Max = glm::max(m_BoundingBox.Max, transformedPos);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Mesh::~Mesh() = default;
|
Mesh::~Mesh() = default;
|
||||||
@ -569,6 +612,24 @@ namespace Prism
|
|||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Mesh::TraverseNodes(const aiNode* node, const glm::mat4& parentTransform, uint32_t level)
|
||||||
|
{
|
||||||
|
const glm::mat4 localTransform = parentTransform * Mat4FromAssimpMat4(node->mTransformation);
|
||||||
|
glm::mat4 transform = parentTransform * localTransform;
|
||||||
|
for (uint32_t i = 0; i < node->mNumMeshes; i++)
|
||||||
|
{
|
||||||
|
const uint32_t mesh = node->mMeshes[i];
|
||||||
|
auto& submesh = m_Submeshes[mesh];
|
||||||
|
submesh.NodeName = node->mName.C_Str();
|
||||||
|
submesh.Transform = transform;
|
||||||
|
submesh.LocalTransform = localTransform;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < node->mNumChildren; i++)
|
||||||
|
{
|
||||||
|
TraverseNodes(node->mChildren[i], localTransform, level + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Mesh::DumpVertexBuffer()
|
void Mesh::DumpVertexBuffer()
|
||||||
{
|
{
|
||||||
@ -657,24 +718,6 @@ namespace Prism
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void Mesh::TraverseNodes(const aiNode* node, const glm::mat4& parentTransform, uint32_t level)
|
|
||||||
{
|
|
||||||
const glm::mat4 localTransform = parentTransform * Mat4FromAssimpMat4(node->mTransformation);
|
|
||||||
glm::mat4 transform = parentTransform * localTransform;
|
|
||||||
for (uint32_t i = 0; i < node->mNumMeshes; i++)
|
|
||||||
{
|
|
||||||
const uint32_t mesh = node->mMeshes[i];
|
|
||||||
auto& submesh = m_Submeshes[mesh];
|
|
||||||
submesh.NodeName = node->mName.C_Str();
|
|
||||||
submesh.Transform = transform;
|
|
||||||
submesh.LocalTransform = localTransform;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < node->mNumChildren; i++)
|
|
||||||
{
|
|
||||||
TraverseNodes(node->mChildren[i], localTransform, level + 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
const aiNodeAnim* Mesh::FindNodeAnim(const aiAnimation* animation, const std::string& nodeName)
|
const aiNodeAnim* Mesh::FindNodeAnim(const aiAnimation* animation, const std::string& nodeName)
|
||||||
|
|||||||
@ -141,6 +141,9 @@ namespace Prism
|
|||||||
{
|
{
|
||||||
return m_AnimatorController ? m_AnimatorController->GetFinalBoneTransforms() : m_EmptyTransforms;
|
return m_AnimatorController ? m_AnimatorController->GetFinalBoneTransforms() : m_EmptyTransforms;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const AABB& GetBoundingBox() const { return m_BoundingBox; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void TraverseNodes(const aiNode* node, const glm::mat4& parentTransform = glm::mat4(1.0f), uint32_t level = 0);
|
void TraverseNodes(const aiNode* node, const glm::mat4& parentTransform = glm::mat4(1.0f), uint32_t level = 0);
|
||||||
|
|
||||||
@ -182,6 +185,9 @@ namespace Prism
|
|||||||
// float m_TimeMultiplier = 1.0f;
|
// float m_TimeMultiplier = 1.0f;
|
||||||
|
|
||||||
std::string m_FilePath;
|
std::string m_FilePath;
|
||||||
|
|
||||||
|
AABB m_BoundingBox;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class Renderer;
|
friend class Renderer;
|
||||||
friend class SceneHierarchyPanel;
|
friend class SceneHierarchyPanel;
|
||||||
|
|||||||
@ -42,8 +42,8 @@ namespace Prism
|
|||||||
// FullScreen Quad
|
// FullScreen Quad
|
||||||
static float fullScreenQuadVertex[] = {
|
static float fullScreenQuadVertex[] = {
|
||||||
-1.0f, -1.0f, 0.1f, 0.0f, 0.0f,
|
-1.0f, -1.0f, 0.1f, 0.0f, 0.0f,
|
||||||
1.0f, -1.0f, 0.1f, 1.0f, 0.0f,
|
1.0f, -1.0f, 0.1f, 1.0f, 0.0f,
|
||||||
1.0f, 1.0f, 0.1f, 1.0f, 1.0f,
|
1.0f, 1.0f, 0.1f, 1.0f, 1.0f,
|
||||||
-1.0f, 1.0f, 0.1f, 0.0f, 1.0f
|
-1.0f, 1.0f, 0.1f, 0.0f, 1.0f
|
||||||
};
|
};
|
||||||
static uint32_t fullScreenQuadIndices[] = {
|
static uint32_t fullScreenQuadIndices[] = {
|
||||||
@ -66,7 +66,7 @@ namespace Prism
|
|||||||
{
|
{
|
||||||
Submit([]()
|
Submit([]()
|
||||||
{
|
{
|
||||||
RendererAPI::Clear(0.0f, 0.0f, 0.0f, 1.0f);
|
RendererAPI::Clear(0.0f, 0.0f, 0.0f, 1.0f);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,6 +81,13 @@ namespace Prism
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ref<ShaderLibrary> Renderer::GetShaderLibrary()
|
||||||
|
{
|
||||||
|
return s_Data.m_ShaderLibrary;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void Renderer::DrawIndexed(const uint32_t count, const PrimitiveType type, const bool depthTest, bool cullFace)
|
void Renderer::DrawIndexed(const uint32_t count, const PrimitiveType type, const bool depthTest, bool cullFace)
|
||||||
{
|
{
|
||||||
Submit([=]() {
|
Submit([=]() {
|
||||||
@ -88,13 +95,6 @@ namespace Prism
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Ref<ShaderLibrary> Renderer::GetShaderLibrary()
|
|
||||||
{
|
|
||||||
return s_Data.m_ShaderLibrary;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Renderer::SetLineThickness(const float thickness)
|
void Renderer::SetLineThickness(const float thickness)
|
||||||
{
|
{
|
||||||
Submit([=]() {
|
Submit([=]() {
|
||||||
@ -135,7 +135,7 @@ namespace Prism
|
|||||||
void Renderer::SubmitQuad(Ref<MaterialInstance>& material, const glm::mat4& transform)
|
void Renderer::SubmitQuad(Ref<MaterialInstance>& material, const glm::mat4& transform)
|
||||||
{
|
{
|
||||||
bool depthTest = true;
|
bool depthTest = true;
|
||||||
bool cullFace = true;
|
bool cullFace = true;
|
||||||
|
|
||||||
if (material)
|
if (material)
|
||||||
{
|
{
|
||||||
@ -172,6 +172,55 @@ namespace Prism
|
|||||||
Renderer::DrawIndexed(6, PrimitiveType::Triangles, depthTest, cullFace);
|
Renderer::DrawIndexed(6, PrimitiveType::Triangles, depthTest, cullFace);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Renderer::SubmitMesh(Ref<Mesh>& mesh, const glm::mat4& transform, const std::vector<Ref<MaterialInstance>>& overrideMaterials)
|
||||||
|
{
|
||||||
|
// auto material = overrideMaterial ? overrideMaterial : mesh->GetMaterialInstance();
|
||||||
|
// auto shader = material->GetShader();
|
||||||
|
|
||||||
|
// TODO: Sort this out
|
||||||
|
mesh->m_VertexBuffer->Bind();
|
||||||
|
mesh->m_Pipeline->Bind();
|
||||||
|
mesh->m_IndexBuffer->Bind();
|
||||||
|
|
||||||
|
const auto& materials = mesh->GetMaterials();
|
||||||
|
for (Submesh& submesh : mesh->m_Submeshes)
|
||||||
|
{
|
||||||
|
// Material
|
||||||
|
auto material = overrideMaterials.empty() ? materials[submesh.MaterialIndex] : overrideMaterials[submesh.MaterialIndex];
|
||||||
|
auto shader = material->GetShader();
|
||||||
|
material->Bind();
|
||||||
|
|
||||||
|
if (mesh->m_IsAnimated)
|
||||||
|
{
|
||||||
|
const auto& boneTransform = mesh->GetBoneTransforms();
|
||||||
|
for (size_t i = 0; i < boneTransform.size(); i++)
|
||||||
|
{
|
||||||
|
std::string uniformName = std::string("u_BoneTransforms[") + std::to_string(i) + std::string("]");
|
||||||
|
shader->SetMat4(uniformName, boneTransform[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
shader->SetMat4("u_Transform", transform * submesh.Transform);
|
||||||
|
|
||||||
|
Renderer::Submit([submesh, material]() {
|
||||||
|
if (material->GetFlag(MaterialFlag::DepthTest))
|
||||||
|
{
|
||||||
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
glDepthFunc(GL_LEQUAL);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
glDisable(GL_DEPTH_TEST);
|
||||||
|
|
||||||
|
if (!material->GetFlag(MaterialFlag::TwoSided))
|
||||||
|
glEnable(GL_CULL_FACE);
|
||||||
|
else
|
||||||
|
glDisable(GL_CULL_FACE);
|
||||||
|
|
||||||
|
|
||||||
|
glDrawElementsBaseVertex(GL_TRIANGLES, submesh.IndexCount, GL_UNSIGNED_INT, (void*)(sizeof(uint32_t) * submesh.BaseIndex), submesh.BaseVertex);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Renderer::SubmitMesh(Ref<Mesh>& mesh, const glm::mat4& transform, const Ref<MaterialInstance>& overrideMaterial)
|
void Renderer::SubmitMesh(Ref<Mesh>& mesh, const glm::mat4& transform, const Ref<MaterialInstance>& overrideMaterial)
|
||||||
{
|
{
|
||||||
// auto material = overrideMaterial ? overrideMaterial : mesh->GetMaterialInstance();
|
// auto material = overrideMaterial ? overrideMaterial : mesh->GetMaterialInstance();
|
||||||
@ -203,7 +252,10 @@ namespace Prism
|
|||||||
|
|
||||||
Renderer::Submit([submesh, material]() {
|
Renderer::Submit([submesh, material]() {
|
||||||
if (material->GetFlag(MaterialFlag::DepthTest))
|
if (material->GetFlag(MaterialFlag::DepthTest))
|
||||||
|
{
|
||||||
glEnable(GL_DEPTH_TEST);
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
glDepthFunc(GL_LEQUAL);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
glDisable(GL_DEPTH_TEST);
|
glDisable(GL_DEPTH_TEST);
|
||||||
|
|
||||||
@ -243,32 +295,6 @@ namespace Prism
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::DrawAABB(const Ref<Mesh>& mesh, const glm::mat4& transform, const glm::vec4& color)
|
|
||||||
{
|
|
||||||
for (const Submesh& submesh : mesh->m_Submeshes)
|
|
||||||
{
|
|
||||||
const auto& aabb = submesh.BoundingBox;
|
|
||||||
auto aabbTransform = transform * submesh.Transform;
|
|
||||||
DrawAABB(aabb, aabbTransform, color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Renderer::DispatchCompute(int x, int y, int z)
|
|
||||||
{
|
|
||||||
Submit([x, y, z]()
|
|
||||||
{
|
|
||||||
RendererAPI::DispatchCompute(x, y, z);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void Renderer::MemoryBarrier(int barrier)
|
|
||||||
{
|
|
||||||
Submit([barrier]()
|
|
||||||
{
|
|
||||||
RendererAPI::MemoryBarrier(barrier);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void Renderer::DrawAABB(const AABB& aabb, const glm::mat4& transform, const glm::vec4& color)
|
void Renderer::DrawAABB(const AABB& aabb, const glm::mat4& transform, const glm::vec4& color)
|
||||||
{
|
{
|
||||||
glm::vec4 min = { aabb.Min.x, aabb.Min.y, aabb.Min.z, 1.0f };
|
glm::vec4 min = { aabb.Min.x, aabb.Min.y, aabb.Min.z, 1.0f };
|
||||||
@ -297,6 +323,32 @@ namespace Prism
|
|||||||
Renderer2D::DrawLine(corners[i], corners[i + 4], color);
|
Renderer2D::DrawLine(corners[i], corners[i + 4], color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Renderer::DrawAABB(const Ref<Mesh>& mesh, const glm::mat4& transform, const glm::vec4& color)
|
||||||
|
{
|
||||||
|
for (const Submesh& submesh : mesh->m_Submeshes)
|
||||||
|
{
|
||||||
|
const auto& aabb = submesh.BoundingBox;
|
||||||
|
auto aabbTransform = transform * submesh.Transform;
|
||||||
|
DrawAABB(aabb, aabbTransform, color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::DispatchCompute(int x, int y, int z)
|
||||||
|
{
|
||||||
|
Submit([x, y, z]()
|
||||||
|
{
|
||||||
|
RendererAPI::DispatchCompute(x, y, z);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::MemoryBarrier(int barrier)
|
||||||
|
{
|
||||||
|
Submit([barrier]()
|
||||||
|
{
|
||||||
|
RendererAPI::MemoryBarrier(barrier);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
RenderCommandQueue& Renderer::GetRenderCommandQueue()
|
RenderCommandQueue& Renderer::GetRenderCommandQueue()
|
||||||
{
|
{
|
||||||
return s_Data.m_CommandQueue;
|
return s_Data.m_CommandQueue;
|
||||||
|
|||||||
@ -54,7 +54,8 @@ namespace Prism
|
|||||||
|
|
||||||
static void SubmitQuad(Ref<MaterialInstance>& material, const glm::mat4& transform = glm::mat4(1.0f));
|
static void SubmitQuad(Ref<MaterialInstance>& material, const glm::mat4& transform = glm::mat4(1.0f));
|
||||||
static void SubmitFullscreenQuad(Ref<MaterialInstance> material);
|
static void SubmitFullscreenQuad(Ref<MaterialInstance> material);
|
||||||
static void SubmitMesh(Ref<Mesh>& mesh, const glm::mat4& transform, const Ref<MaterialInstance>& overrideMaterial = nullptr);
|
static void SubmitMesh(Ref<Mesh>& mesh, const glm::mat4& transform, const std::vector<Ref<MaterialInstance>>& overrideMaterials = {});
|
||||||
|
static void SubmitMesh(Ref<Mesh>& mesh, const glm::mat4& transform, const Ref<MaterialInstance>& overrideMaterial = nullptr);
|
||||||
static void SubmitMeshWithShader(Ref<Mesh> mesh, const glm::mat4& transform, Ref<Shader> shader);
|
static void SubmitMeshWithShader(Ref<Mesh> mesh, const glm::mat4& transform, Ref<Shader> shader);
|
||||||
|
|
||||||
static void DrawAABB(const AABB& aabb, const glm::mat4& transform, const glm::vec4& color = glm::vec4(1.0f));
|
static void DrawAABB(const AABB& aabb, const glm::mat4& transform, const glm::vec4& color = glm::vec4(1.0f));
|
||||||
|
|||||||
@ -25,28 +25,20 @@ namespace Prism
|
|||||||
LightEnvironment SceneLightEnvironment;
|
LightEnvironment SceneLightEnvironment;
|
||||||
|
|
||||||
// Resources
|
// Resources
|
||||||
|
Ref<MaterialInstance> SkyboxMaterial;
|
||||||
Ref<Environment> SceneEnvironment;
|
Ref<Environment> SceneEnvironment;
|
||||||
Ref<TextureCube> SkyboxTexture;
|
|
||||||
float SkyboxLoad;
|
|
||||||
} SceneData;
|
} SceneData;
|
||||||
|
|
||||||
Ref<Texture2D> BRDFLUT;
|
Ref<Texture2D> BRDFLUT;
|
||||||
Ref<Shader> CompositeShader;
|
Ref<Shader> CompositeShader;
|
||||||
Ref<Shader> BloomBlurShader;
|
Ref<Shader> BloomBlurShader;
|
||||||
// Ref<Shader> BloomBlendShader;
|
Ref<Shader> BloomBlendShader;
|
||||||
|
|
||||||
Ref<RenderPass> GeoPass;
|
Ref<RenderPass> GeoPass;
|
||||||
|
|
||||||
Ref<RenderPass> LightingPass;
|
|
||||||
Ref<Shader> LightingShader;
|
|
||||||
|
|
||||||
// Ref<RenderPass> CompositePass;
|
// Ref<RenderPass> CompositePass;
|
||||||
Ref<RenderPass> BloomBlurPass[2];
|
Ref<RenderPass> BloomBlurPass[2];
|
||||||
Ref<RenderPass> BloomBlendPass;
|
Ref<RenderPass> BloomBlendPass;
|
||||||
Ref<Texture2D> ResolvedHDRTexture; // 解析后的单样本 HDR 颜色
|
Ref<Texture2D> ResolvedHDRTexture; // 解析后的单样本 HDR 颜色
|
||||||
int Quality = 6;
|
|
||||||
float Directions = 32.0f;
|
|
||||||
float Size = 16.0f;
|
|
||||||
|
|
||||||
struct AutoExposureData
|
struct AutoExposureData
|
||||||
{
|
{
|
||||||
@ -57,7 +49,7 @@ namespace Prism
|
|||||||
bool EnableAutoExposure = true;
|
bool EnableAutoExposure = true;
|
||||||
float Key = 0.3f;
|
float Key = 0.3f;
|
||||||
Timer ExposureTimer;
|
Timer ExposureTimer;
|
||||||
float MaxExposure = 5.0f;
|
float MaxExposure = 1.5f;
|
||||||
float MinExposure = 0.01f;
|
float MinExposure = 0.01f;
|
||||||
|
|
||||||
// 直方图模式参数
|
// 直方图模式参数
|
||||||
@ -103,12 +95,12 @@ namespace Prism
|
|||||||
bool ShadowEnabled = true;
|
bool ShadowEnabled = true;
|
||||||
float ShadowBias = 0.001f;
|
float ShadowBias = 0.001f;
|
||||||
float ShadowIntensity = 0.0f;
|
float ShadowIntensity = 0.0f;
|
||||||
float ShadowSoftness = 0.0f;
|
int ShadowSoftness = 0;
|
||||||
|
|
||||||
struct DrawCommand
|
struct DrawCommand
|
||||||
{
|
{
|
||||||
Ref<Mesh> mesh;
|
Ref<Mesh> mesh;
|
||||||
Ref<MaterialInstance> Material;
|
std::vector<Ref<MaterialInstance>> MaterialInstances;
|
||||||
glm::mat4 Transform;
|
glm::mat4 Transform;
|
||||||
};
|
};
|
||||||
std::vector<DrawCommand> DrawList;
|
std::vector<DrawCommand> DrawList;
|
||||||
@ -136,21 +128,18 @@ namespace Prism
|
|||||||
SceneRendererOptions Options;
|
SceneRendererOptions Options;
|
||||||
|
|
||||||
Ref<TextureCube> BlackCubeTexture;
|
Ref<TextureCube> BlackCubeTexture;
|
||||||
|
Ref<Texture2D> BlackTexture;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Renderer3DStats
|
struct Renderer3DStats
|
||||||
{
|
{
|
||||||
float ShadowPass = 0.0f;
|
float ShadowPass = 0.0f;
|
||||||
float GeometryPass = 0.0f;
|
float GeometryPass = 0.0f;
|
||||||
float LightingPass = 0.0f;
|
|
||||||
float BloomPass = 0.0f;
|
|
||||||
float CompositePass = 0.0f;
|
float CompositePass = 0.0f;
|
||||||
float AutoExposurePass = 0.0f;
|
float AutoExposurePass = 0.0f;
|
||||||
|
|
||||||
Timer ShadowPassTimer;
|
Timer ShadowPassTimer;
|
||||||
Timer GeometryPassTimer;
|
Timer GeometryPassTimer;
|
||||||
Timer LightingPassTimer;
|
|
||||||
Timer BloomPassTimer;
|
|
||||||
Timer CompositePassTimer;
|
Timer CompositePassTimer;
|
||||||
Timer AutoExposurePassTimer;
|
Timer AutoExposurePassTimer;
|
||||||
};
|
};
|
||||||
@ -165,15 +154,9 @@ namespace Prism
|
|||||||
//////////////// GeoPass ////////////////
|
//////////////// GeoPass ////////////////
|
||||||
{
|
{
|
||||||
FramebufferSpecification geoFramebufferSpec;
|
FramebufferSpecification geoFramebufferSpec;
|
||||||
geoFramebufferSpec.Attachments = {
|
geoFramebufferSpec.Attachments = { FramebufferTextureFormat::RGBA32F, FramebufferTextureFormat::DEPTH24STENCIL8 };
|
||||||
FramebufferTextureFormat::RGBA16F, // Albedo + Metallic
|
geoFramebufferSpec.Samples = 8;
|
||||||
FramebufferTextureFormat::RGBA16F, // Normal + Roughness
|
geoFramebufferSpec.ClearColor = { 0.1f, 0.1f, 0.1f, 1.0f };
|
||||||
FramebufferTextureFormat::RGBA16F, // Emissive+AO
|
|
||||||
FramebufferTextureFormat::DEPTH24STENCIL8 // Depth
|
|
||||||
};
|
|
||||||
|
|
||||||
geoFramebufferSpec.Samples = 1;
|
|
||||||
geoFramebufferSpec.ClearColor = { 0.0f, 0.0f, 0.0f, 0.0f };
|
|
||||||
|
|
||||||
RenderPassSpecification geoRenderPassSpec;
|
RenderPassSpecification geoRenderPassSpec;
|
||||||
geoRenderPassSpec.TargetFramebuffer = FrameBuffer::Create(geoFramebufferSpec);
|
geoRenderPassSpec.TargetFramebuffer = FrameBuffer::Create(geoFramebufferSpec);
|
||||||
@ -182,18 +165,6 @@ namespace Prism
|
|||||||
/////////////////////////////////////////////
|
/////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
//////////////// GeoPass ////////////////
|
|
||||||
FramebufferSpecification spec;
|
|
||||||
spec.Attachments = { FramebufferTextureFormat::RGBA16F }; // HDR 颜色输出
|
|
||||||
spec.Samples = 1;
|
|
||||||
spec.ClearColor = { 0.0f, 0.0f, 0.0f, 0.0f };
|
|
||||||
RenderPassSpecification rpSpec;
|
|
||||||
rpSpec.TargetFramebuffer = FrameBuffer::Create(spec);
|
|
||||||
s_Data.LightingPass = RenderPass::Create(rpSpec);
|
|
||||||
s_Data.LightingShader = Shader::Create("assets/shaders/Lighting.glsl");
|
|
||||||
/////////////////////////////////////////////
|
|
||||||
|
|
||||||
|
|
||||||
//////////////// BloomPass ////////////////
|
//////////////// BloomPass ////////////////
|
||||||
{
|
{
|
||||||
FramebufferSpecification bloomBlurFramebufferSpec;
|
FramebufferSpecification bloomBlurFramebufferSpec;
|
||||||
@ -215,7 +186,7 @@ namespace Prism
|
|||||||
s_Data.BloomBlendPass = RenderPass::Create(bloomBlendRenderPassSpec);
|
s_Data.BloomBlendPass = RenderPass::Create(bloomBlendRenderPassSpec);
|
||||||
|
|
||||||
s_Data.BloomBlurShader = Shader::Create("assets/shaders/BloomBlur.glsl");
|
s_Data.BloomBlurShader = Shader::Create("assets/shaders/BloomBlur.glsl");
|
||||||
// s_Data.BloomBlendShader = Shader::Create("assets/shaders/BloomBlend.glsl");
|
s_Data.BloomBlendShader = Shader::Create("assets/shaders/BloomBlend.glsl");
|
||||||
}
|
}
|
||||||
/////////////////////////////////////////////
|
/////////////////////////////////////////////
|
||||||
|
|
||||||
@ -297,6 +268,7 @@ namespace Prism
|
|||||||
|
|
||||||
uint32_t blackTextureData[6] = { 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000 };
|
uint32_t blackTextureData[6] = { 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000 };
|
||||||
s_Data.BlackCubeTexture = TextureCube::Create(TextureFormat::RGBA, 1, 1, &blackTextureData);
|
s_Data.BlackCubeTexture = TextureCube::Create(TextureFormat::RGBA, 1, 1, &blackTextureData);
|
||||||
|
s_Data.BlackTexture = Texture2D::Create(TextureFormat::RGBA, 1, 1, &blackTextureData[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer3D::SetViewportSize(const uint32_t width, const uint32_t height)
|
void Renderer3D::SetViewportSize(const uint32_t width, const uint32_t height)
|
||||||
@ -314,8 +286,7 @@ namespace Prism
|
|||||||
void Renderer3D::BeginScene(const Scene* scene, const SceneRendererCamera& camera)
|
void Renderer3D::BeginScene(const Scene* scene, const SceneRendererCamera& camera)
|
||||||
{
|
{
|
||||||
s_Data.SceneData.SceneCamera = camera;
|
s_Data.SceneData.SceneCamera = camera;
|
||||||
s_Data.SceneData.SkyboxTexture = scene->m_SkyboxTexture;
|
s_Data.SceneData.SkyboxMaterial = scene->m_SkyboxMaterial;
|
||||||
s_Data.SceneData.SkyboxLoad = scene->m_SkyboxLod;
|
|
||||||
s_Data.SceneData.SceneEnvironment = scene->m_Environment;
|
s_Data.SceneData.SceneEnvironment = scene->m_Environment;
|
||||||
s_Data.SceneData.SceneEnvironmentIntensity = scene->m_EnvironmentIntensity;
|
s_Data.SceneData.SceneEnvironmentIntensity = scene->m_EnvironmentIntensity;
|
||||||
s_Data.SceneData.SceneLightEnvironment = scene->m_LightEnvironment;
|
s_Data.SceneData.SceneLightEnvironment = scene->m_LightEnvironment;
|
||||||
@ -326,39 +297,39 @@ namespace Prism
|
|||||||
FlushDrawList(renderPass);
|
FlushDrawList(renderPass);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer3D::SubmitMesh(const Ref<Mesh>& mesh, const glm::mat4& transform, const Ref<MaterialInstance>& overrideMaterial)
|
void Renderer3D::SubmitMesh(const Ref<Mesh>& mesh, const glm::mat4& transform, const std::vector<Ref<MaterialInstance>>& overrideMaterials)
|
||||||
{
|
{
|
||||||
// TODO: Culling, sorting, etc.
|
// TODO: Culling, sorting, etc.
|
||||||
|
|
||||||
s_Data.DrawList.push_back({ mesh, overrideMaterial, transform });
|
s_Data.DrawList.push_back({ mesh, overrideMaterials, transform });
|
||||||
s_Data.ShadowPassDrawList.push_back({ mesh, overrideMaterial, transform });
|
s_Data.ShadowPassDrawList.push_back({ mesh, overrideMaterials, transform });
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer3D::SubmitSelectedMesh(const Ref<Mesh>& mesh, const glm::mat4& transform)
|
void Renderer3D::SubmitSelectedMesh(const Ref<Mesh>& mesh, const glm::mat4& transform, const std::vector<Ref<MaterialInstance>>& overrideMaterials)
|
||||||
{
|
{
|
||||||
s_Data.SelectedMeshDrawList.push_back({ mesh, nullptr, transform });
|
s_Data.SelectedMeshDrawList.push_back({ mesh, overrideMaterials, transform });
|
||||||
s_Data.ShadowPassDrawList.push_back({ mesh, nullptr, transform });
|
s_Data.ShadowPassDrawList.push_back({ mesh, overrideMaterials, transform });
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer3D::SubmitColliderMesh(const BoxColliderComponent& component, const glm::mat4& parentTransform)
|
void Renderer3D::SubmitColliderMesh(const BoxColliderComponent& component, const glm::mat4& parentTransform)
|
||||||
{
|
{
|
||||||
s_Data.ColliderDrawList.push_back({ component.DebugMesh, nullptr, glm::translate(parentTransform, component.Offset)});
|
s_Data.ColliderDrawList.push_back({ component.DebugMesh, {}, glm::translate(parentTransform, component.Offset)});
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer3D::SubmitColliderMesh(const SphereColliderComponent& component, const glm::mat4& parentTransform)
|
void Renderer3D::SubmitColliderMesh(const SphereColliderComponent& component, const glm::mat4& parentTransform)
|
||||||
{
|
{
|
||||||
s_Data.ColliderDrawList.push_back({ component.DebugMesh, nullptr, parentTransform });
|
s_Data.ColliderDrawList.push_back({ component.DebugMesh, {}, parentTransform });
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer3D::SubmitColliderMesh(const CapsuleColliderComponent& component, const glm::mat4& parentTransform)
|
void Renderer3D::SubmitColliderMesh(const CapsuleColliderComponent& component, const glm::mat4& parentTransform)
|
||||||
{
|
{
|
||||||
s_Data.ColliderDrawList.push_back({ component.DebugMesh, nullptr, parentTransform });
|
s_Data.ColliderDrawList.push_back({ component.DebugMesh, {}, parentTransform });
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer3D::SubmitColliderMesh(const MeshColliderComponent& component, const glm::mat4& parentTransform)
|
void Renderer3D::SubmitColliderMesh(const MeshColliderComponent& component, const glm::mat4& parentTransform)
|
||||||
{
|
{
|
||||||
for (const auto debugMesh : component.ProcessedMeshes)
|
for (const auto& debugMesh : component.ProcessedMeshes)
|
||||||
s_Data.ColliderDrawList.push_back({ debugMesh, nullptr, parentTransform });
|
s_Data.ColliderDrawList.push_back({ debugMesh, {}, parentTransform });
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: temp
|
// TODO: temp
|
||||||
@ -482,6 +453,11 @@ namespace Prism
|
|||||||
return s_Data.BlackCubeTexture;
|
return s_Data.BlackCubeTexture;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ref<Texture2D> Renderer3D::GetBlackTexture()
|
||||||
|
{
|
||||||
|
return s_Data.BlackTexture;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Renderer3D::FlushDrawList(Ref<RenderPass>& outRenderPass)
|
void Renderer3D::FlushDrawList(Ref<RenderPass>& outRenderPass)
|
||||||
{
|
{
|
||||||
@ -499,34 +475,22 @@ namespace Prism
|
|||||||
Renderer::Submit([] { s_Stats.GeometryPass = s_Stats.GeometryPassTimer.ElapsedMillis(); });
|
Renderer::Submit([] { s_Stats.GeometryPass = s_Stats.GeometryPassTimer.ElapsedMillis(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
|
||||||
Renderer::Submit([]() { s_Stats.LightingPassTimer.Reset(); });
|
|
||||||
LightingPass();
|
|
||||||
Renderer::Submit([] { s_Stats.LightingPass = s_Stats.LightingPassTimer.ElapsedMillis(); });
|
|
||||||
}
|
|
||||||
|
|
||||||
// ResolveMSAA();
|
|
||||||
|
|
||||||
// Compute average luminance and update exposure (GPU-copy + mipmap -> read 1 texel)
|
|
||||||
{
|
{
|
||||||
Renderer::Submit([]() { s_Stats.AutoExposurePassTimer.Reset(); });
|
Renderer::Submit([]() { s_Stats.AutoExposurePassTimer.Reset(); });
|
||||||
AutoExposurePass();
|
AutoExposurePass();
|
||||||
Renderer::Submit([] { s_Stats.AutoExposurePass = s_Stats.AutoExposurePassTimer.ElapsedMillis(); });
|
Renderer::Submit([] { s_Stats.AutoExposurePass = s_Stats.AutoExposurePassTimer.ElapsedMillis(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
ResolveMSAA();
|
||||||
Renderer::Submit([]() { s_Stats.BloomPassTimer.Reset(); });
|
|
||||||
BloomBlurPass();
|
|
||||||
Renderer::Submit([] { s_Stats.BloomPass = s_Stats.BloomPassTimer.ElapsedMillis(); });
|
|
||||||
}
|
|
||||||
|
|
||||||
|
BloomBlurPass();
|
||||||
|
|
||||||
|
GridPass();
|
||||||
|
|
||||||
{
|
{
|
||||||
Renderer::Submit([]() { s_Stats.CompositePassTimer.Reset(); });
|
Renderer::Submit([]() { s_Stats.CompositePassTimer.Reset(); });
|
||||||
CompositePass(outRenderPass);
|
CompositePass(outRenderPass);
|
||||||
OverlayPass(outRenderPass);
|
|
||||||
Renderer::Submit([] { s_Stats.CompositePass = s_Stats.CompositePassTimer.ElapsedMillis(); });
|
Renderer::Submit([] { s_Stats.CompositePass = s_Stats.CompositePassTimer.ElapsedMillis(); });
|
||||||
// BloomBlurPass();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
s_Data.DrawList.clear();
|
s_Data.DrawList.clear();
|
||||||
@ -542,8 +506,7 @@ namespace Prism
|
|||||||
if (!ae.EnableAutoExposure)
|
if (!ae.EnableAutoExposure)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto srcFB = s_Data.LightingPass->GetSpecification().TargetFramebuffer;
|
auto srcFB = s_Data.GeoPass->GetSpecification().TargetFramebuffer;
|
||||||
// auto srcFB = s_Data.GeoPass->GetSpecification().TargetFramebuffer;
|
|
||||||
auto dstFB = ae.LuminancePass->GetSpecification().TargetFramebuffer;
|
auto dstFB = ae.LuminancePass->GetSpecification().TargetFramebuffer;
|
||||||
if (!srcFB || !dstFB) return;
|
if (!srcFB || !dstFB) return;
|
||||||
|
|
||||||
@ -681,36 +644,22 @@ namespace Prism
|
|||||||
const glm::vec3 cameraPosition = glm::inverse(s_Data.SceneData.SceneCamera.ViewMatrix)[3]; // TODO: Negate instead
|
const glm::vec3 cameraPosition = glm::inverse(s_Data.SceneData.SceneCamera.ViewMatrix)[3]; // TODO: Negate instead
|
||||||
|
|
||||||
|
|
||||||
// Render entities
|
// Skybox
|
||||||
Renderer::Submit([]()
|
s_Data.SceneData.SkyboxMaterial->Set("u_InverseVP", glm::inverse(cameraViewProjection));
|
||||||
{
|
s_Data.SceneData.SkyboxMaterial->Set("u_SkyIntensity", s_Data.SceneData.SceneEnvironmentIntensity);
|
||||||
glEnable(GL_DEPTH_TEST);
|
// s_Data.SceneInfo.EnvironmentIrradianceMap->Bind(0);
|
||||||
glDisable(GL_BLEND);
|
Renderer::SubmitFullscreenQuad(s_Data.SceneData.SkyboxMaterial);
|
||||||
});
|
|
||||||
|
|
||||||
|
// const float aspectRatio = (float)s_Data.GeoPass->GetSpecification().TargetFramebuffer->GetWidth() / (float)s_Data.GeoPass->GetSpecification().TargetFramebuffer->GetHeight();
|
||||||
|
// float frustumSize = 2.0f * sceneCamera.Near * glm::tan(sceneCamera.FOV * 0.5f) * aspectRatio;
|
||||||
|
|
||||||
|
// Render entities
|
||||||
for (auto& dc : s_Data.DrawList)
|
for (auto& dc : s_Data.DrawList)
|
||||||
{
|
{
|
||||||
auto baseMaterial = dc.mesh->GetMaterial();
|
auto baseMaterial = dc.mesh->GetMaterial();
|
||||||
baseMaterial->Set("u_GBufferMode", true);
|
|
||||||
baseMaterial->Set("u_ViewProjectionMatrix", cameraViewProjection);
|
baseMaterial->Set("u_ViewProjectionMatrix", cameraViewProjection);
|
||||||
baseMaterial->Set("u_ViewMatrix", sceneCamera.ViewMatrix);
|
baseMaterial->Set("u_ViewMatrix", sceneCamera.ViewMatrix);
|
||||||
baseMaterial->Set("u_CameraPosition", cameraPosition);
|
baseMaterial->Set("u_CameraPosition", cameraPosition);
|
||||||
baseMaterial->Set("u_EmissiveColor", 1.0f);
|
|
||||||
baseMaterial->Set("u_EmissiveIntensity", 0.0f);
|
|
||||||
baseMaterial->Set("u_EmissiveTexToggle", 0.0f);
|
|
||||||
// baseMaterial->Set("u_LightMatrixCascade0", s_Data.LightMatrices[0]);
|
|
||||||
// baseMaterial->Set("u_LightMatrixCascade1", s_Data.LightMatrices[1]);
|
|
||||||
// baseMaterial->Set("u_LightMatrixCascade2", s_Data.LightMatrices[2]);
|
|
||||||
// baseMaterial->Set("u_LightMatrixCascade3", s_Data.LightMatrices[3]);
|
|
||||||
// baseMaterial->Set("u_ShowCascades", s_Data.ShowCascades);
|
|
||||||
// baseMaterial->Set("u_LightView", s_Data.LightViewMatrix);
|
|
||||||
// baseMaterial->Set("u_CascadeSplits", s_Data.CascadeSplits);
|
|
||||||
// baseMaterial->Set("u_SoftShadows", s_Data.SoftShadows);
|
|
||||||
// baseMaterial->Set("u_LightSize", s_Data.LightSize);
|
|
||||||
// baseMaterial->Set("u_MaxShadowDistance", s_Data.MaxShadowDistance);
|
|
||||||
// baseMaterial->Set("u_ShadowFade", s_Data.ShadowFade);
|
|
||||||
// baseMaterial->Set("u_CascadeFading", s_Data.CascadeFading);
|
|
||||||
// baseMaterial->Set("u_CascadeTransitionFade", s_Data.CascadeTransitionFade);
|
|
||||||
baseMaterial->Set("u_IBLContribution", s_Data.SceneData.SceneEnvironmentIntensity);
|
baseMaterial->Set("u_IBLContribution", s_Data.SceneData.SceneEnvironmentIntensity);
|
||||||
|
|
||||||
// Environment (TODO: don't do this per mesh)
|
// Environment (TODO: don't do this per mesh)
|
||||||
@ -747,38 +696,7 @@ namespace Prism
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
Renderer::SubmitMesh(dc.mesh, dc.Transform, dc.MaterialInstances);
|
||||||
auto rd = baseMaterial->FindResourceDeclaration("u_ShadowMapTexture");
|
|
||||||
if (rd)
|
|
||||||
{
|
|
||||||
auto reg = rd->GetRegister();
|
|
||||||
|
|
||||||
auto tex = s_Data.ShadowMapRenderPass[0]->GetSpecification().TargetFramebuffer->GetDepthAttachmentRendererID();
|
|
||||||
auto tex1 = s_Data.ShadowMapRenderPass[1]->GetSpecification().TargetFramebuffer->GetDepthAttachmentRendererID();
|
|
||||||
auto tex2 = s_Data.ShadowMapRenderPass[2]->GetSpecification().TargetFramebuffer->GetDepthAttachmentRendererID();
|
|
||||||
auto tex3 = s_Data.ShadowMapRenderPass[3]->GetSpecification().TargetFramebuffer->GetDepthAttachmentRendererID();
|
|
||||||
|
|
||||||
Renderer::Submit([reg, tex, tex1, tex2, tex3]() mutable
|
|
||||||
{
|
|
||||||
// 4 cascades
|
|
||||||
glBindTextureUnit(reg, tex);
|
|
||||||
glBindSampler(reg++, s_Data.ShadowMapSampler);
|
|
||||||
|
|
||||||
glBindTextureUnit(reg, tex1);
|
|
||||||
glBindSampler(reg++, s_Data.ShadowMapSampler);
|
|
||||||
|
|
||||||
glBindTextureUnit(reg, tex2);
|
|
||||||
glBindSampler(reg++, s_Data.ShadowMapSampler);
|
|
||||||
|
|
||||||
glBindTextureUnit(reg, tex3);
|
|
||||||
glBindSampler(reg++, s_Data.ShadowMapSampler);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
constexpr auto overrideMaterial = nullptr; // dc.Material;
|
|
||||||
Renderer::SubmitMesh(dc.mesh, dc.Transform, overrideMaterial);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (outline)
|
if (outline)
|
||||||
@ -795,17 +713,6 @@ namespace Prism
|
|||||||
baseMaterial->Set("u_ViewProjectionMatrix", cameraViewProjection);
|
baseMaterial->Set("u_ViewProjectionMatrix", cameraViewProjection);
|
||||||
baseMaterial->Set("u_ViewMatrix", sceneCamera.ViewMatrix);
|
baseMaterial->Set("u_ViewMatrix", sceneCamera.ViewMatrix);
|
||||||
baseMaterial->Set("u_CameraPosition", cameraPosition);
|
baseMaterial->Set("u_CameraPosition", cameraPosition);
|
||||||
baseMaterial->Set("u_EmissiveColor", 1.0f);
|
|
||||||
baseMaterial->Set("u_EmissiveIntensity", 0.0f);
|
|
||||||
baseMaterial->Set("u_EmissiveTexToggle", 0.0f);
|
|
||||||
// baseMaterial->Set("u_CascadeSplits", s_Data.CascadeSplits);
|
|
||||||
// baseMaterial->Set("u_ShowCascades", s_Data.ShowCascades);
|
|
||||||
// baseMaterial->Set("u_SoftShadows", s_Data.SoftShadows);
|
|
||||||
// baseMaterial->Set("u_LightSize", s_Data.LightSize);
|
|
||||||
// baseMaterial->Set("u_MaxShadowDistance", s_Data.MaxShadowDistance);
|
|
||||||
// baseMaterial->Set("u_ShadowFade", s_Data.ShadowFade);
|
|
||||||
// baseMaterial->Set("u_CascadeFading", s_Data.CascadeFading);
|
|
||||||
// baseMaterial->Set("u_CascadeTransitionFade", s_Data.CascadeTransitionFade);
|
|
||||||
baseMaterial->Set("u_IBLContribution", s_Data.SceneData.SceneEnvironmentIntensity);
|
baseMaterial->Set("u_IBLContribution", s_Data.SceneData.SceneEnvironmentIntensity);
|
||||||
|
|
||||||
|
|
||||||
@ -814,11 +721,6 @@ namespace Prism
|
|||||||
baseMaterial->Set("u_EnvIrradianceTex", s_Data.SceneData.SceneEnvironment->IrradianceMap);
|
baseMaterial->Set("u_EnvIrradianceTex", s_Data.SceneData.SceneEnvironment->IrradianceMap);
|
||||||
baseMaterial->Set("u_BRDFLUTTexture", s_Data.BRDFLUT);
|
baseMaterial->Set("u_BRDFLUTTexture", s_Data.BRDFLUT);
|
||||||
|
|
||||||
// baseMaterial->Set("u_LightMatrixCascade0", s_Data.LightMatrices[0]);
|
|
||||||
// baseMaterial->Set("u_LightMatrixCascade1", s_Data.LightMatrices[1]);
|
|
||||||
// baseMaterial->Set("u_LightMatrixCascade2", s_Data.LightMatrices[2]);
|
|
||||||
// baseMaterial->Set("u_LightMatrixCascade3", s_Data.LightMatrices[3]);
|
|
||||||
|
|
||||||
// Set lights (TODO: move to light environment and don't do per mesh)
|
// Set lights (TODO: move to light environment and don't do per mesh)
|
||||||
baseMaterial->Set("u_DirectionalLights", s_Data.SceneData.SceneLightEnvironment.DirectionalLights[0]);
|
baseMaterial->Set("u_DirectionalLights", s_Data.SceneData.SceneLightEnvironment.DirectionalLights[0]);
|
||||||
baseMaterial->Set("u_PointLightCount", s_Data.SceneData.SceneLightEnvironment.PointLightCount);
|
baseMaterial->Set("u_PointLightCount", s_Data.SceneData.SceneLightEnvironment.PointLightCount);
|
||||||
@ -847,37 +749,8 @@ namespace Prism
|
|||||||
glBindSampler(reg, s_Data.ShadowMapSampler);
|
glBindSampler(reg, s_Data.ShadowMapSampler);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
auto rd = baseMaterial->FindResourceDeclaration("u_ShadowMapTexture");
|
|
||||||
if (rd)
|
|
||||||
{
|
|
||||||
auto reg = rd->GetRegister();
|
|
||||||
|
|
||||||
auto tex = s_Data.ShadowMapRenderPass[0]->GetSpecification().TargetFramebuffer->GetDepthAttachmentRendererID();
|
Renderer::SubmitMesh(dc.mesh, dc.Transform, dc.MaterialInstances);
|
||||||
auto tex1 = s_Data.ShadowMapRenderPass[1]->GetSpecification().TargetFramebuffer->GetDepthAttachmentRendererID();
|
|
||||||
auto tex2 = s_Data.ShadowMapRenderPass[2]->GetSpecification().TargetFramebuffer->GetDepthAttachmentRendererID();
|
|
||||||
auto tex3 = s_Data.ShadowMapRenderPass[3]->GetSpecification().TargetFramebuffer->GetDepthAttachmentRendererID();
|
|
||||||
|
|
||||||
Renderer::Submit([reg, tex, tex1, tex2, tex3]() mutable
|
|
||||||
{
|
|
||||||
// 4 cascades
|
|
||||||
glBindTextureUnit(reg, tex);
|
|
||||||
glBindSampler(reg++, s_Data.ShadowMapSampler);
|
|
||||||
|
|
||||||
glBindTextureUnit(reg, tex1);
|
|
||||||
glBindSampler(reg++, s_Data.ShadowMapSampler);
|
|
||||||
|
|
||||||
glBindTextureUnit(reg, tex2);
|
|
||||||
glBindSampler(reg++, s_Data.ShadowMapSampler);
|
|
||||||
|
|
||||||
glBindTextureUnit(reg, tex3);
|
|
||||||
glBindSampler(reg++, s_Data.ShadowMapSampler);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
constexpr auto overrideMaterial = nullptr; // dc.Material;
|
|
||||||
Renderer::SubmitMesh(dc.mesh, dc.Transform, overrideMaterial);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -927,9 +800,6 @@ namespace Prism
|
|||||||
{
|
{
|
||||||
Renderer::Submit([]()
|
Renderer::Submit([]()
|
||||||
{
|
{
|
||||||
// glStencilFunc(GL_NOTEQUAL, 1, 0xff);
|
|
||||||
// glStencilMask(0);
|
|
||||||
|
|
||||||
glLineWidth(1);
|
glLineWidth(1);
|
||||||
glEnable(GL_LINE_SMOOTH);
|
glEnable(GL_LINE_SMOOTH);
|
||||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||||
@ -958,14 +828,15 @@ namespace Prism
|
|||||||
Renderer::Submit([]()
|
Renderer::Submit([]()
|
||||||
{
|
{
|
||||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||||
// glStencilMask(0xff);
|
|
||||||
// glStencilFunc(GL_ALWAYS, 1, 0xff);
|
|
||||||
glEnable(GL_DEPTH_TEST);
|
glEnable(GL_DEPTH_TEST);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (const auto option = GetOptions(); option.ShowBoundingBoxes)
|
// Grid
|
||||||
|
const auto option = GetOptions();
|
||||||
|
|
||||||
|
if (option.ShowBoundingBoxes)
|
||||||
{
|
{
|
||||||
Renderer2D::BeginScene(cameraViewProjection);
|
Renderer2D::BeginScene(cameraViewProjection);
|
||||||
for (auto& dc : s_Data.DrawList)
|
for (auto& dc : s_Data.DrawList)
|
||||||
@ -976,112 +847,6 @@ namespace Prism
|
|||||||
Renderer::EndRenderPass();
|
Renderer::EndRenderPass();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer3D::LightingPass()
|
|
||||||
{
|
|
||||||
Renderer::BeginRenderPass(s_Data.LightingPass);
|
|
||||||
s_Data.LightingShader->Bind();
|
|
||||||
|
|
||||||
// uniform
|
|
||||||
const glm::mat4 invViewProj = glm::inverse(s_Data.SceneData.SceneCamera.Camera.GetProjectionMatrix() * s_Data.SceneData.SceneCamera.ViewMatrix);
|
|
||||||
s_Data.LightingShader->SetMat4("u_InvViewProj", invViewProj);
|
|
||||||
const glm::vec3 cameraPosition = glm::inverse(s_Data.SceneData.SceneCamera.ViewMatrix)[3];
|
|
||||||
s_Data.LightingShader->SetFloat3("u_CameraPosition", cameraPosition);
|
|
||||||
|
|
||||||
|
|
||||||
// G-buffer
|
|
||||||
auto fb = s_Data.GeoPass->GetSpecification().TargetFramebuffer;
|
|
||||||
Renderer::Submit([fb]() {
|
|
||||||
glActiveTexture(GL_TEXTURE0);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, fb->GetColorAttachmentRendererID(0)); // AlbedoMetallic
|
|
||||||
glActiveTexture(GL_TEXTURE1);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, fb->GetColorAttachmentRendererID(1)); // NormalRoughness
|
|
||||||
glActiveTexture(GL_TEXTURE2);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, fb->GetColorAttachmentRendererID(2)); // EmissiveAO
|
|
||||||
glActiveTexture(GL_TEXTURE3);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, fb->GetDepthAttachmentRendererID()); // Depth
|
|
||||||
});
|
|
||||||
s_Data.LightingShader->SetInt("u_AlbedoMetallic", 0);
|
|
||||||
s_Data.LightingShader->SetInt("u_NormalRoughness", 1);
|
|
||||||
s_Data.LightingShader->SetInt("u_EmissiveAO", 2);
|
|
||||||
s_Data.LightingShader->SetInt("u_Depth", 3);
|
|
||||||
|
|
||||||
|
|
||||||
// uniform
|
|
||||||
const auto& lights = s_Data.SceneData.SceneLightEnvironment;
|
|
||||||
// s_Data.LightingShader->SetStruct("u_DirectionalLights", lights.DirectionalLights[0]); // 需确保 SetStruct 支持
|
|
||||||
s_Data.LightingShader->SetFloat3("u_DirectionalLights.Direction", lights.DirectionalLights[0].Direction);
|
|
||||||
s_Data.LightingShader->SetFloat3("u_DirectionalLights.Radiance", lights.DirectionalLights[0].Radiance);
|
|
||||||
s_Data.LightingShader->SetFloat("u_DirectionalLights.Intensity", lights.DirectionalLights[0].Intensity);
|
|
||||||
s_Data.LightingShader->SetBool("u_DirectionalLights.CastShadows", lights.DirectionalLights[0].CastShadows);
|
|
||||||
|
|
||||||
s_Data.LightingShader->SetInt("u_PointLightCount", lights.PointLightCount);
|
|
||||||
// s_Data.LightingShader->SetStructArray("u_PointLights", lights.PointLights, lights.PointLightCount);
|
|
||||||
for (int i = 0; i < lights.PointLightCount; i++) {
|
|
||||||
std::string base = "u_PointLights[" + std::to_string(i) + "]";
|
|
||||||
s_Data.LightingShader->SetFloat3(base + ".Position", lights.PointLights[i].Position);
|
|
||||||
s_Data.LightingShader->SetFloat3(base + ".Radiance", lights.PointLights[i].Radiance);
|
|
||||||
s_Data.LightingShader->SetFloat(base + ".Intensity", lights.PointLights[i].Intensity);
|
|
||||||
s_Data.LightingShader->SetFloat(base + ".Range", lights.PointLights[i].Radius);
|
|
||||||
s_Data.LightingShader->SetBool(base + ".CastShadows", lights.PointLights[i].CastShadows);
|
|
||||||
}
|
|
||||||
|
|
||||||
s_Data.LightingShader->SetInt("u_SpotLightCount", lights.SpotLightCount);
|
|
||||||
for (int i = 0; i < lights.SpotLightCount; i++) {
|
|
||||||
std::string base = "u_SpotLights[" + std::to_string(i) + "]";
|
|
||||||
s_Data.LightingShader->SetFloat3(base + ".Position", lights.SpotLights[i].Position);
|
|
||||||
s_Data.LightingShader->SetFloat3(base + ".Direction", lights.SpotLights[i].Direction);
|
|
||||||
s_Data.LightingShader->SetFloat3(base + ".Radiance", lights.SpotLights[i].Radiance);
|
|
||||||
s_Data.LightingShader->SetFloat(base + ".Intensity", lights.SpotLights[i].Intensity);
|
|
||||||
s_Data.LightingShader->SetFloat(base + ".Range", lights.SpotLights[i].Range);
|
|
||||||
s_Data.LightingShader->SetFloat(base + ".InnerConeCos", lights.SpotLights[i].InnerConeCos);
|
|
||||||
s_Data.LightingShader->SetFloat(base + ".OuterConeCos", lights.SpotLights[i].OuterConeCos);
|
|
||||||
s_Data.LightingShader->SetBool(base + ".CastShadows", lights.SpotLights[i].CastShadows);
|
|
||||||
}
|
|
||||||
|
|
||||||
// IBL
|
|
||||||
s_Data.LightingShader->SetInt("u_EnvRadianceTex", 4);
|
|
||||||
s_Data.LightingShader->SetInt("u_EnvIrradianceTex", 5);
|
|
||||||
s_Data.LightingShader->SetInt("u_BRDFLUTTexture", 6);
|
|
||||||
s_Data.LightingShader->SetFloat("u_IBLContribution", s_Data.SceneData.SceneEnvironmentIntensity);
|
|
||||||
s_Data.LightingShader->SetFloat("u_EnvMapRotation", 0.0f); // 若需要可调整
|
|
||||||
|
|
||||||
const auto& sceneEnvironment = s_Data.SceneData.SceneEnvironment;
|
|
||||||
const auto& BRDFLUT = s_Data.BRDFLUT;
|
|
||||||
Renderer::Submit([sceneEnvironment, BRDFLUT]() {
|
|
||||||
glActiveTexture(GL_TEXTURE4);
|
|
||||||
glBindTexture(GL_TEXTURE_CUBE_MAP, sceneEnvironment->RadianceMap->GetRendererID());
|
|
||||||
glActiveTexture(GL_TEXTURE5);
|
|
||||||
glBindTexture(GL_TEXTURE_CUBE_MAP, sceneEnvironment->IrradianceMap->GetRendererID());
|
|
||||||
glActiveTexture(GL_TEXTURE6);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, BRDFLUT->GetRendererID());
|
|
||||||
});
|
|
||||||
|
|
||||||
s_Data.LightingShader->SetMat4("u_LightSpaceMatrix", s_Data.LightMatrices);
|
|
||||||
s_Data.LightingShader->SetBool("u_ShadowEnabled", s_Data.ShadowEnabled);
|
|
||||||
s_Data.LightingShader->SetFloat("u_ShadowBias", s_Data.ShadowBias);
|
|
||||||
s_Data.LightingShader->SetFloat("u_ShadowIntensity", s_Data.ShadowIntensity);
|
|
||||||
s_Data.LightingShader->SetFloat("u_ShadowSoftness", s_Data.ShadowSoftness);
|
|
||||||
|
|
||||||
if (s_Data.ShadowEnabled) {
|
|
||||||
s_Data.LightingShader->SetInt("u_ShadowMap", 7);
|
|
||||||
Renderer::Submit([]() {
|
|
||||||
glActiveTexture(GL_TEXTURE7);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, s_Data.ShadowMapRenderPass->GetSpecification().TargetFramebuffer->GetDepthAttachmentRendererID());
|
|
||||||
glBindSampler(7, s_Data.ShadowMapSampler);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (s_Data.SceneData.SkyboxTexture) {
|
|
||||||
s_Data.LightingShader->SetFloat("u_SkyTextureLod", s_Data.SceneData.SkyboxLoad);
|
|
||||||
s_Data.SceneData.SkyboxTexture->Bind(8);
|
|
||||||
s_Data.LightingShader->SetInt("u_Skybox", 8); // 使用纹理单元 8(确保不与其他单元冲突)
|
|
||||||
s_Data.LightingShader->SetFloat("u_SkyIntensity", s_Data.SceneData.SceneEnvironmentIntensity);
|
|
||||||
}
|
|
||||||
|
|
||||||
Renderer::SubmitFullscreenQuad(nullptr);
|
|
||||||
Renderer::EndRenderPass();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Renderer3D::BloomBlurPass()
|
void Renderer3D::BloomBlurPass()
|
||||||
{
|
{
|
||||||
if (!s_Data.EnableBloom)
|
if (!s_Data.EnableBloom)
|
||||||
@ -1092,76 +857,62 @@ namespace Prism
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// uint32_t srcTex = s_Data.ResolvedHDRTexture->GetRendererID();
|
const int iterations = 5; // 模糊迭代次数,可调
|
||||||
uint32_t srcTex = s_Data.LightingPass->GetSpecification().TargetFramebuffer->GetColorAttachmentRendererID();
|
|
||||||
|
|
||||||
// 第一次:提取高光 + 水平模糊
|
// 第一次:提取高光 + 水平模糊
|
||||||
{
|
{
|
||||||
Renderer::BeginRenderPass(s_Data.BloomBlurPass[0]);
|
Renderer::BeginRenderPass(s_Data.BloomBlurPass[0]);
|
||||||
|
|
||||||
s_Data.BloomBlurShader->Bind();
|
s_Data.BloomBlurShader->Bind();
|
||||||
s_Data.BloomBlurShader->SetInt("u_Texture", 0);
|
s_Data.BloomBlurShader->SetInt("u_Texture", 0);
|
||||||
s_Data.BloomBlurShader->SetBool("u_FirstPass", true);
|
s_Data.BloomBlurShader->SetBool("u_FirstPass", true);
|
||||||
s_Data.BloomBlurShader->SetFloat("u_Threshold", s_Data.BloomThreshold);
|
s_Data.BloomBlurShader->SetFloat("u_Threshold", s_Data.BloomThreshold);
|
||||||
s_Data.BloomBlurShader->SetInt("u_Quality", s_Data.Quality);
|
s_Data.ResolvedHDRTexture->Bind();
|
||||||
s_Data.BloomBlurShader->SetFloat("u_Directions", s_Data.Directions);
|
|
||||||
s_Data.BloomBlurShader->SetFloat("u_Size", s_Data.Size);
|
|
||||||
Renderer::Submit([srcTex]() { glBindTextureUnit(0, srcTex); });
|
|
||||||
Renderer::SubmitFullscreenQuad(nullptr);
|
Renderer::SubmitFullscreenQuad(nullptr);
|
||||||
Renderer::EndRenderPass();
|
Renderer::EndRenderPass();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t finalBlurTex = s_Data.BloomBlurPass[0]->GetSpecification().TargetFramebuffer->GetColorAttachmentRendererID();
|
// 后续迭代
|
||||||
|
for (int i = 1; i < iterations; ++i)
|
||||||
|
{
|
||||||
|
auto outputPass = (i % 2 == 1) ? s_Data.BloomBlurPass[1] : s_Data.BloomBlurPass[0];
|
||||||
|
|
||||||
|
Renderer::BeginRenderPass(outputPass);
|
||||||
|
s_Data.BloomBlurShader->Bind();
|
||||||
|
s_Data.BloomBlurShader->SetInt("u_Texture", 0);
|
||||||
|
s_Data.BloomBlurShader->SetBool("u_FirstPass", false);
|
||||||
|
if (i%2 == 1)
|
||||||
|
s_Data.BloomBlurPass[0]->GetSpecification().TargetFramebuffer->BindTexture();
|
||||||
|
else
|
||||||
|
s_Data.BloomBlurPass[1]->GetSpecification().TargetFramebuffer->BindTexture();
|
||||||
|
|
||||||
|
Renderer::SubmitFullscreenQuad(nullptr);
|
||||||
|
Renderer::EndRenderPass();
|
||||||
|
}
|
||||||
|
|
||||||
Renderer::BeginRenderPass(s_Data.BloomBlendPass);
|
Renderer::BeginRenderPass(s_Data.BloomBlendPass);
|
||||||
s_Data.BloomBlurShader->Bind();
|
s_Data.BloomBlurShader->Bind();
|
||||||
s_Data.BloomBlurShader->SetInt("u_Texture", 0);
|
s_Data.BloomBlurShader->SetInt("u_Texture", 0);
|
||||||
|
if (iterations % 2 == 0)
|
||||||
|
s_Data.BloomBlurPass[1]->GetSpecification().TargetFramebuffer->BindTexture();
|
||||||
|
else
|
||||||
|
s_Data.BloomBlurPass[0]->GetSpecification().TargetFramebuffer->BindTexture();
|
||||||
|
|
||||||
s_Data.BloomBlurShader->SetBool("u_FirstPass", false);
|
s_Data.BloomBlurShader->SetBool("u_FirstPass", false);
|
||||||
s_Data.BloomBlurShader->SetInt("u_Quality", s_Data.Quality);
|
|
||||||
s_Data.BloomBlurShader->SetFloat("u_Directions", s_Data.Directions);
|
|
||||||
s_Data.BloomBlurShader->SetFloat("u_Size", s_Data.Size);
|
|
||||||
Renderer::Submit([finalBlurTex]() { glBindTextureUnit(0, finalBlurTex); });
|
|
||||||
Renderer::SubmitFullscreenQuad(nullptr);
|
Renderer::SubmitFullscreenQuad(nullptr);
|
||||||
Renderer::EndRenderPass();
|
Renderer::EndRenderPass();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Renderer3D::GridPass()
|
||||||
void Renderer3D::CompositePass(const Ref<RenderPass>& outRenderPass)
|
|
||||||
{
|
{
|
||||||
Renderer::BeginRenderPass(outRenderPass);
|
Renderer::BeginRenderPass(s_Data.GeoPass, false);
|
||||||
|
|
||||||
s_Data.CompositeShader->Bind();
|
|
||||||
|
|
||||||
s_Data.CompositeShader->SetBool("u_EnableAutoExposure", s_Data.AutoExposureData.EnableAutoExposure);
|
|
||||||
s_Data.CompositeShader->SetFloat("u_ManualExposure", s_Data.SceneData.SceneCamera.Camera.GetExposure());
|
|
||||||
|
|
||||||
s_Data.CompositeShader->SetBool("u_EnableBloom", s_Data.EnableBloom);
|
|
||||||
s_Data.LightingPass->GetSpecification().TargetFramebuffer->BindTexture(); // 通常绑定到单元0
|
|
||||||
Renderer::Submit([]() {
|
|
||||||
glBindTextureUnit(1, s_Data.GeoPass->GetSpecification().TargetFramebuffer->GetColorAttachmentRendererID());
|
|
||||||
});
|
|
||||||
|
|
||||||
if (s_Data.EnableBloom)
|
|
||||||
{
|
|
||||||
uint32_t bloomTex = s_Data.BloomBlendPass->GetSpecification().TargetFramebuffer->GetColorAttachmentRendererID();
|
|
||||||
Renderer::Submit([bloomTex]() {
|
|
||||||
glBindTextureUnit(2, bloomTex);
|
|
||||||
});
|
|
||||||
s_Data.CompositeShader->SetInt("u_BloomTexture", 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
s_Data.AutoExposureData.ExposureSSBO->BindBase(2);
|
|
||||||
|
|
||||||
|
|
||||||
Renderer::SubmitFullscreenQuad(nullptr);
|
|
||||||
Renderer::EndRenderPass();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Renderer3D::OverlayPass(const Ref<RenderPass>& outRenderPass)
|
|
||||||
{
|
|
||||||
Renderer::BeginRenderPass(outRenderPass, false);
|
|
||||||
|
|
||||||
if (const auto option = GetOptions(); option.ShowGrid)
|
if (const auto option = GetOptions(); option.ShowGrid)
|
||||||
{
|
{
|
||||||
|
Renderer::Submit([]() {
|
||||||
|
glDepthMask(GL_FALSE);
|
||||||
|
});
|
||||||
|
|
||||||
const auto& sceneCamera = s_Data.SceneData.SceneCamera;
|
const auto& sceneCamera = s_Data.SceneData.SceneCamera;
|
||||||
|
|
||||||
const auto cameraProjection = sceneCamera.Camera.GetProjectionMatrix();
|
const auto cameraProjection = sceneCamera.Camera.GetProjectionMatrix();
|
||||||
@ -1181,11 +932,71 @@ namespace Prism
|
|||||||
s_Data.GridData.GridMaterial->Set("u_FadeDistance", s_Data.GridData.FadeDistance);
|
s_Data.GridData.GridMaterial->Set("u_FadeDistance", s_Data.GridData.FadeDistance);
|
||||||
|
|
||||||
Renderer::SubmitFullscreenQuad(s_Data.GridData.GridMaterial);
|
Renderer::SubmitFullscreenQuad(s_Data.GridData.GridMaterial);
|
||||||
|
|
||||||
|
Renderer::Submit([]() {
|
||||||
|
glDepthMask(GL_TRUE);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Renderer::EndRenderPass();
|
Renderer::EndRenderPass();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CopyDepthBuffer(Ref<FrameBuffer> src, Ref<FrameBuffer> dst)
|
||||||
|
{
|
||||||
|
uint32_t srcID = src->GetRendererID(); // 假设 FrameBuffer 有此方法
|
||||||
|
uint32_t dstID = dst->GetRendererID();
|
||||||
|
|
||||||
|
int srcWidth = src->GetWidth();
|
||||||
|
int srcHeight = src->GetHeight();
|
||||||
|
int dstWidth = dst->GetWidth();
|
||||||
|
int dstHeight = dst->GetHeight();
|
||||||
|
|
||||||
|
glBindFramebuffer(GL_READ_FRAMEBUFFER, srcID);
|
||||||
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, dstID);
|
||||||
|
glBlitFramebuffer(0, 0, srcWidth, srcHeight, 0, 0, dstWidth, dstHeight,
|
||||||
|
GL_DEPTH_BUFFER_BIT, GL_NEAREST);
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, 0); // 可选恢复
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer3D::CompositePass(const Ref<RenderPass>& outRenderPass)
|
||||||
|
{
|
||||||
|
|
||||||
|
Renderer::Submit([srcFB = s_Data.GeoPass->GetSpecification().TargetFramebuffer,
|
||||||
|
dstFB = outRenderPass->GetSpecification().TargetFramebuffer]()
|
||||||
|
{
|
||||||
|
glBindFramebuffer(GL_READ_FRAMEBUFFER, srcFB->GetRendererID());
|
||||||
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, dstFB->GetRendererID());
|
||||||
|
glBlitFramebuffer(0, 0, srcFB->GetWidth(), srcFB->GetHeight(),
|
||||||
|
0, 0, dstFB->GetWidth(), dstFB->GetHeight(),
|
||||||
|
GL_DEPTH_BUFFER_BIT, GL_NEAREST);
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
|
});
|
||||||
|
|
||||||
|
Renderer::BeginRenderPass(outRenderPass);
|
||||||
|
|
||||||
|
s_Data.CompositeShader->Bind();
|
||||||
|
|
||||||
|
s_Data.AutoExposureData.ExposureSSBO->BindBase(2);
|
||||||
|
s_Data.CompositeShader->SetBool("u_EnableAutoExposure", s_Data.AutoExposureData.EnableAutoExposure);
|
||||||
|
s_Data.CompositeShader->SetFloat("u_ManualExposure", s_Data.SceneData.SceneCamera.Camera.GetExposure());
|
||||||
|
s_Data.CompositeShader->SetInt("u_TextureSamples", s_Data.GeoPass->GetSpecification().TargetFramebuffer->GetSpecification().Samples);
|
||||||
|
s_Data.CompositeShader->SetBool("u_EnableBloom", s_Data.EnableBloom);
|
||||||
|
|
||||||
|
// 绑定几何阶段颜色纹理(多重采样)
|
||||||
|
s_Data.GeoPass->GetSpecification().TargetFramebuffer->BindTexture();
|
||||||
|
s_Data.GeoPass->GetSpecification().TargetFramebuffer->BindDepthTexture(1);
|
||||||
|
|
||||||
|
if (s_Data.EnableBloom)
|
||||||
|
{
|
||||||
|
s_Data.BloomBlendPass->GetSpecification().TargetFramebuffer->BindTexture(0, 2);
|
||||||
|
s_Data.CompositeShader->SetInt("u_BloomTexture", 2); // 告诉着色器使用单元2
|
||||||
|
}
|
||||||
|
|
||||||
|
Renderer::SubmitFullscreenQuad(nullptr);
|
||||||
|
|
||||||
|
Renderer::EndRenderPass();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
std::vector<glm::vec3> GetFrustumCornersWorldSpace(const SceneRendererCamera& sceneCamera)
|
std::vector<glm::vec3> GetFrustumCornersWorldSpace(const SceneRendererCamera& sceneCamera)
|
||||||
{
|
{
|
||||||
@ -1212,6 +1023,39 @@ namespace Prism
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Renderer3D::ResolveMSAA()
|
||||||
|
{
|
||||||
|
auto srcFB = s_Data.GeoPass->GetSpecification().TargetFramebuffer;
|
||||||
|
const uint32_t width = srcFB->GetWidth();
|
||||||
|
const uint32_t height = srcFB->GetHeight();
|
||||||
|
|
||||||
|
if (!s_Data.ResolvedHDRTexture ||
|
||||||
|
s_Data.ResolvedHDRTexture->GetWidth() != width ||
|
||||||
|
s_Data.ResolvedHDRTexture->GetHeight() != height)
|
||||||
|
{
|
||||||
|
s_Data.ResolvedHDRTexture = Texture2D::Create(TextureFormat::RGBA16F, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
Renderer::Submit([srcFB, resolvedTex = s_Data.ResolvedHDRTexture]() {
|
||||||
|
GLuint resolveFBO;
|
||||||
|
glGenFramebuffers(1, &resolveFBO);
|
||||||
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO);
|
||||||
|
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolvedTex->GetRendererID(), 0);
|
||||||
|
|
||||||
|
glBindFramebuffer(GL_READ_FRAMEBUFFER, srcFB->GetRendererID());
|
||||||
|
glReadBuffer(GL_COLOR_ATTACHMENT0);
|
||||||
|
|
||||||
|
glBlitFramebuffer(0, 0, srcFB->GetWidth(), srcFB->GetHeight(),
|
||||||
|
0, 0, srcFB->GetWidth(), srcFB->GetHeight(),
|
||||||
|
GL_COLOR_BUFFER_BIT, GL_LINEAR);
|
||||||
|
|
||||||
|
glDeleteFramebuffers(1, &resolveFBO);
|
||||||
|
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
|
||||||
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void SceneRenderer::OnImGuiRender()
|
void SceneRenderer::OnImGuiRender()
|
||||||
{
|
{
|
||||||
ImGui::Begin("Scene Renderer");
|
ImGui::Begin("Scene Renderer");
|
||||||
@ -1219,37 +1063,9 @@ namespace Prism
|
|||||||
|
|
||||||
UI::Property("Geometry Pass time", s_Stats.GeometryPass);
|
UI::Property("Geometry Pass time", s_Stats.GeometryPass);
|
||||||
UI::Property("Composite Pass time", s_Stats.CompositePass);
|
UI::Property("Composite Pass time", s_Stats.CompositePass);
|
||||||
UI::Property("Bloom Pass time", s_Stats.BloomPass);
|
|
||||||
UI::Property("Shadow Pass time", s_Stats.ShadowPass);
|
UI::Property("Shadow Pass time", s_Stats.ShadowPass);
|
||||||
UI::Property("AutoExposure Pass time", s_Stats.AutoExposurePass);
|
UI::Property("AutoExposure Pass time", s_Stats.AutoExposurePass);
|
||||||
|
|
||||||
if (UI::BeginTreeNode("Geometry", false))
|
|
||||||
{
|
|
||||||
const float size = ImGui::GetContentRegionAvail().x; // (float)fb->GetWidth() * 0.5f, (float)fb->GetHeight() * 0.5f
|
|
||||||
float w = size;
|
|
||||||
auto fb = s_Data.GeoPass->GetSpecification().TargetFramebuffer;
|
|
||||||
auto image1 = fb->GetColorAttachmentRendererID(0);
|
|
||||||
auto image2 = fb->GetColorAttachmentRendererID(1);
|
|
||||||
auto image3 = fb->GetColorAttachmentRendererID(2);
|
|
||||||
float h = w / ((float)fb->GetWidth() / (float)fb->GetHeight());
|
|
||||||
ImGui::Image((ImTextureID)image1, { w, h }, { 0, 1 }, { 1, 0 });
|
|
||||||
ImGui::Image((ImTextureID)image2, { w, h }, { 0, 1 }, { 1, 0 });
|
|
||||||
ImGui::Image((ImTextureID)image3, { w, h }, { 0, 1 }, { 1, 0 });
|
|
||||||
|
|
||||||
auto lightFB = s_Data.LightingPass->GetSpecification().TargetFramebuffer;
|
|
||||||
auto lightImage = lightFB->GetColorAttachmentRendererID();
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
ImGui::Image((ImTextureID)lightImage, { w, h }, { 0, 1 }, { 1, 0 });
|
|
||||||
|
|
||||||
auto depthfb = s_Data.GeoPass->GetSpecification().TargetFramebuffer;
|
|
||||||
uint32_t depthID = depthfb->GetDepthAttachmentRendererID();
|
|
||||||
ImGui::Image((ImTextureID)depthID, {w, h}, {0, 1}, {1, 0});
|
|
||||||
|
|
||||||
UI::EndTreeNode();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (UI::BeginTreeNode("Grid Config", false))
|
if (UI::BeginTreeNode("Grid Config", false))
|
||||||
{
|
{
|
||||||
// Grid plane: 0 = XZ (Y up), 1 = XY (Z forward), 2 = YZ (X right)
|
// Grid plane: 0 = XZ (Y up), 1 = XY (Z forward), 2 = YZ (X right)
|
||||||
@ -1310,10 +1126,6 @@ namespace Prism
|
|||||||
UI::BeginPropertyGrid();
|
UI::BeginPropertyGrid();
|
||||||
UI::Property("Bloom", s_Data.EnableBloom);
|
UI::Property("Bloom", s_Data.EnableBloom);
|
||||||
UI::Property("Bloom threshold", s_Data.BloomThreshold, 0.05f);
|
UI::Property("Bloom threshold", s_Data.BloomThreshold, 0.05f);
|
||||||
UI::Property("Directions", s_Data.Directions);
|
|
||||||
UI::Property("Quality", s_Data.Quality);
|
|
||||||
UI::Property("Size", s_Data.Size);
|
|
||||||
|
|
||||||
UI::EndPropertyGrid();
|
UI::EndPropertyGrid();
|
||||||
|
|
||||||
auto fb = s_Data.BloomBlurPass[0]->GetSpecification().TargetFramebuffer;
|
auto fb = s_Data.BloomBlurPass[0]->GetSpecification().TargetFramebuffer;
|
||||||
@ -1327,9 +1139,11 @@ namespace Prism
|
|||||||
float h = w / ((float)fb->GetWidth() / (float)fb->GetHeight());
|
float h = w / ((float)fb->GetWidth() / (float)fb->GetHeight());
|
||||||
ImGui::Image((ImTextureID)id, { w, h }, { 0, 1 }, { 1, 0 });
|
ImGui::Image((ImTextureID)id, { w, h }, { 0, 1 }, { 1, 0 });
|
||||||
ImGui::Image((ImTextureID)id2, { w, h }, { 0, 1 }, { 1, 0 });
|
ImGui::Image((ImTextureID)id2, { w, h }, { 0, 1 }, { 1, 0 });
|
||||||
|
ImGui::Image((ImTextureID)s_Data.ResolvedHDRTexture->GetRendererID(), { w, h }, { 0, 1 }, { 1, 0 });
|
||||||
UI::EndTreeNode();
|
UI::EndTreeNode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (UI::BeginTreeNode("Auto Exposure", false))
|
if (UI::BeginTreeNode("Auto Exposure", false))
|
||||||
{
|
{
|
||||||
UI::BeginPropertyGrid();
|
UI::BeginPropertyGrid();
|
||||||
@ -1362,4 +1176,5 @@ namespace Prism
|
|||||||
|
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -33,8 +33,8 @@ namespace Prism
|
|||||||
static void BeginScene(const Scene* scene, const SceneRendererCamera& camera);
|
static void BeginScene(const Scene* scene, const SceneRendererCamera& camera);
|
||||||
static void EndScene(Ref<RenderPass>& renderPass);
|
static void EndScene(Ref<RenderPass>& renderPass);
|
||||||
|
|
||||||
static void SubmitMesh(const Ref<Mesh>& mesh, const glm::mat4& transform = glm::mat4(1.0f), const Ref<MaterialInstance>& overrideMaterial = nullptr);
|
static void SubmitMesh(const Ref<Mesh>& mesh, const glm::mat4& transform = glm::mat4(1.0f), const std::vector<Ref<MaterialInstance>>& overrideMaterials = {});
|
||||||
static void SubmitSelectedMesh(const Ref<Mesh>& mesh, const glm::mat4& transform = glm::mat4(1.0f));
|
static void SubmitSelectedMesh(const Ref<Mesh>& mesh, const glm::mat4& transform = glm::mat4(1.0f), const std::vector<Ref<MaterialInstance>>& overrideMaterials = {});
|
||||||
|
|
||||||
static void SubmitColliderMesh(const BoxColliderComponent& component, const glm::mat4& parentTransform = glm::mat4(1.0f));
|
static void SubmitColliderMesh(const BoxColliderComponent& component, const glm::mat4& parentTransform = glm::mat4(1.0f));
|
||||||
static void SubmitColliderMesh(const SphereColliderComponent& component, const glm::mat4& parentTransform = glm::mat4(1.0f));
|
static void SubmitColliderMesh(const SphereColliderComponent& component, const glm::mat4& parentTransform = glm::mat4(1.0f));
|
||||||
@ -54,6 +54,7 @@ namespace Prism
|
|||||||
|
|
||||||
static SceneRendererOptions& GetOptions();
|
static SceneRendererOptions& GetOptions();
|
||||||
static Ref<TextureCube> GetBlackCubeTexture();
|
static Ref<TextureCube> GetBlackCubeTexture();
|
||||||
|
static Ref<Texture2D> GetBlackTexture();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void FlushDrawList(Ref<RenderPass>& outRenderPass);
|
static void FlushDrawList(Ref<RenderPass>& outRenderPass);
|
||||||
@ -61,15 +62,13 @@ namespace Prism
|
|||||||
static void AutoExposurePass();
|
static void AutoExposurePass();
|
||||||
static void ShadowMapPass();
|
static void ShadowMapPass();
|
||||||
static void GeometryPass();
|
static void GeometryPass();
|
||||||
static void LightingPass();
|
|
||||||
static void BloomBlurPass();
|
static void BloomBlurPass();
|
||||||
|
static void GridPass();
|
||||||
static void OverlayPass(const Ref<RenderPass>& outRenderPass);
|
|
||||||
|
|
||||||
static void CompositePass(const Ref<RenderPass>& outRenderPass);
|
static void CompositePass(const Ref<RenderPass>& outRenderPass);
|
||||||
|
|
||||||
|
|
||||||
// static void ResolveMSAA();
|
static void ResolveMSAA();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -12,6 +12,7 @@
|
|||||||
#include "Renderer3D.h"
|
#include "Renderer3D.h"
|
||||||
|
|
||||||
#include "RenderPass.h"
|
#include "RenderPass.h"
|
||||||
|
#include "glad/glad.h"
|
||||||
|
|
||||||
|
|
||||||
namespace Prism
|
namespace Prism
|
||||||
@ -26,7 +27,7 @@ namespace Prism
|
|||||||
void SceneRenderer::Init()
|
void SceneRenderer::Init()
|
||||||
{
|
{
|
||||||
FramebufferSpecification finalFramebufferSpec;
|
FramebufferSpecification finalFramebufferSpec;
|
||||||
finalFramebufferSpec.Attachments = { FramebufferTextureFormat::RGBA16F, FramebufferTextureFormat::DEPTH24STENCIL8};
|
finalFramebufferSpec.Attachments = { FramebufferTextureFormat::RGBA32F, FramebufferTextureFormat::DEPTH24STENCIL8};
|
||||||
finalFramebufferSpec.ClearColor = { 0.1f, 0.1f, 0.1f, 1.0f };
|
finalFramebufferSpec.ClearColor = { 0.1f, 0.1f, 0.1f, 1.0f };
|
||||||
|
|
||||||
RenderPassSpecification finalRenderPassSpec;
|
RenderPassSpecification finalRenderPassSpec;
|
||||||
@ -141,14 +142,14 @@ namespace Prism
|
|||||||
|
|
||||||
//////////////////// 3D API ////////////////////
|
//////////////////// 3D API ////////////////////
|
||||||
|
|
||||||
void SceneRenderer::SubmitMesh(const Ref<Mesh>& mesh, const glm::mat4& transform, const Ref<MaterialInstance>& overrideMaterial)
|
void SceneRenderer::SubmitMesh(const Ref<Mesh>& mesh, const glm::mat4& transform, const std::vector<Ref<MaterialInstance>>& overrideMaterials)
|
||||||
{
|
{
|
||||||
Renderer3D::SubmitMesh(mesh, transform, overrideMaterial);
|
Renderer3D::SubmitMesh(mesh, transform, overrideMaterials);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SceneRenderer::SubmitSelectedMesh(const Ref<Mesh>& mesh, const glm::mat4& transform)
|
void SceneRenderer::SubmitSelectedMesh(const Ref<Mesh>& mesh, const glm::mat4& transform, const std::vector<Ref<MaterialInstance>>& overrideMaterials)
|
||||||
{
|
{
|
||||||
Renderer3D::SubmitSelectedMesh(mesh, transform);
|
Renderer3D::SubmitSelectedMesh(mesh, transform, overrideMaterials);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SceneRenderer::SubmitColliderMesh(const BoxColliderComponent& component, const glm::mat4& parentTransform)
|
void SceneRenderer::SubmitColliderMesh(const BoxColliderComponent& component, const glm::mat4& parentTransform)
|
||||||
@ -207,4 +208,24 @@ namespace Prism
|
|||||||
{
|
{
|
||||||
return Renderer3D::GetOptions();
|
return Renderer3D::GetOptions();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SceneRenderer::FlushToScreen()
|
||||||
|
{
|
||||||
|
const auto fb = s_Data.FinalPass->GetSpecification().TargetFramebuffer;
|
||||||
|
const auto fbWidth = fb->GetWidth();
|
||||||
|
const auto fbHeight = fb->GetHeight();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Renderer::Submit([fb, fbWidth, fbHeight]()
|
||||||
|
{
|
||||||
|
glBindFramebuffer(GL_READ_FRAMEBUFFER, fb->GetColorAttachmentRendererID());
|
||||||
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||||
|
|
||||||
|
glBlitFramebuffer(0, 0, fbWidth, fbHeight,
|
||||||
|
0, 0, fbWidth, fbHeight,
|
||||||
|
GL_COLOR_BUFFER_BIT,
|
||||||
|
GL_NEAREST);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,7 +15,7 @@ namespace Prism
|
|||||||
{
|
{
|
||||||
struct SceneRendererOptions
|
struct SceneRendererOptions
|
||||||
{
|
{
|
||||||
bool ShowGrid = true;
|
bool ShowGrid = false;
|
||||||
bool ShowBoundingBoxes = false;
|
bool ShowBoundingBoxes = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -70,8 +70,8 @@ namespace Prism
|
|||||||
|
|
||||||
|
|
||||||
// Renderer3D
|
// Renderer3D
|
||||||
static void SubmitMesh(const Ref<Mesh>& mesh, const glm::mat4& transform = glm::mat4(1.0f), const Ref<MaterialInstance>& overrideMaterial = nullptr);
|
static void SubmitMesh(const Ref<Mesh>& mesh, const glm::mat4& transform = glm::mat4(1.0f), const std::vector<Ref<MaterialInstance>>& overrideMaterials = {});
|
||||||
static void SubmitSelectedMesh(const Ref<Mesh>& mesh, const glm::mat4& transform = glm::mat4(1.0f));
|
static void SubmitSelectedMesh(const Ref<Mesh>& mesh, const glm::mat4& transform = glm::mat4(1.0f), const std::vector<Ref<MaterialInstance>>& overrideMaterials = {});
|
||||||
|
|
||||||
static void SubmitColliderMesh(const BoxColliderComponent& component, const glm::mat4& parentTransform = glm::mat4(1.0f));
|
static void SubmitColliderMesh(const BoxColliderComponent& component, const glm::mat4& parentTransform = glm::mat4(1.0f));
|
||||||
static void SubmitColliderMesh(const SphereColliderComponent& component, const glm::mat4& parentTransform = glm::mat4(1.0f));
|
static void SubmitColliderMesh(const SphereColliderComponent& component, const glm::mat4& parentTransform = glm::mat4(1.0f));
|
||||||
@ -90,7 +90,9 @@ namespace Prism
|
|||||||
static uint32_t GetFinalColorBufferRendererID();
|
static uint32_t GetFinalColorBufferRendererID();
|
||||||
static SceneRendererOptions& GetOptions();
|
static SceneRendererOptions& GetOptions();
|
||||||
static void OnImGuiRender();
|
static void OnImGuiRender();
|
||||||
private:
|
|
||||||
|
|
||||||
|
static void FlushToScreen();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -38,6 +38,16 @@ namespace Prism
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ref<Texture2D> Texture2D::Create(TextureFormat format, unsigned int width, unsigned int height, const void* data, TextureWrap wrap)
|
||||||
|
{
|
||||||
|
switch (RendererAPI::Current())
|
||||||
|
{
|
||||||
|
case RendererAPIType::None: return nullptr;
|
||||||
|
case RendererAPIType::OpenGL: return Ref<OpenGLTexture2D>::Create(format, width, height, data, wrap);
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Ref<Texture2D> Texture2D::Create(const std::string& path, bool srgb)
|
Ref<Texture2D> Texture2D::Create(const std::string& path, bool srgb)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -5,9 +5,9 @@
|
|||||||
#ifndef TEXTURE_H
|
#ifndef TEXTURE_H
|
||||||
#define TEXTURE_H
|
#define TEXTURE_H
|
||||||
#include "RendererAPI.h"
|
#include "RendererAPI.h"
|
||||||
|
#include "Prism/Asset/Asset.h"
|
||||||
#include "Prism/Core/Buffer.h"
|
#include "Prism/Core/Buffer.h"
|
||||||
#include "Prism/Core/Ref.h"
|
#include "Prism/Core/Ref.h"
|
||||||
#include "../Asset/Asset.h"
|
|
||||||
|
|
||||||
|
|
||||||
namespace Prism
|
namespace Prism
|
||||||
@ -53,6 +53,7 @@ namespace Prism
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static Ref<Texture2D> Create(TextureFormat format, unsigned int width, unsigned int height, TextureWrap wrap = TextureWrap::Clamp);
|
static Ref<Texture2D> Create(TextureFormat format, unsigned int width, unsigned int height, TextureWrap wrap = TextureWrap::Clamp);
|
||||||
|
static Ref<Texture2D> Create(TextureFormat format, unsigned int width, unsigned int height, const void* data, TextureWrap wrap = TextureWrap::Clamp);
|
||||||
static Ref<Texture2D> Create(const std::string& path, bool srgb = false);
|
static Ref<Texture2D> Create(const std::string& path, bool srgb = false);
|
||||||
|
|
||||||
|
|
||||||
@ -62,7 +63,7 @@ namespace Prism
|
|||||||
|
|
||||||
virtual void Lock() = 0;
|
virtual void Lock() = 0;
|
||||||
virtual void Unlock() = 0;
|
virtual void Unlock() = 0;
|
||||||
virtual void SetData(const void* data, int count) = 0;
|
virtual void SetData(const void* data, uint32_t count) = 0;
|
||||||
virtual void Resize(uint32_t width, uint32_t height) = 0;
|
virtual void Resize(uint32_t width, uint32_t height) = 0;
|
||||||
virtual Buffer GetWriteableBuffer() = 0;
|
virtual Buffer GetWriteableBuffer() = 0;
|
||||||
|
|
||||||
|
|||||||
@ -81,8 +81,9 @@ namespace Prism
|
|||||||
}
|
}
|
||||||
glm::mat4 GetTransform() const
|
glm::mat4 GetTransform() const
|
||||||
{
|
{
|
||||||
|
|
||||||
return glm::translate(glm::mat4(1.0f), Translation)
|
return glm::translate(glm::mat4(1.0f), Translation)
|
||||||
* glm::toMat4(glm::quat((Rotation)))
|
* glm::toMat4(glm::quat(Rotation))
|
||||||
* glm::scale(glm::mat4(1.0f), Scale);
|
* glm::scale(glm::mat4(1.0f), Scale);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -91,32 +92,112 @@ namespace Prism
|
|||||||
struct MeshComponent
|
struct MeshComponent
|
||||||
{
|
{
|
||||||
Ref<Mesh> Mesh;
|
Ref<Mesh> Mesh;
|
||||||
// std::vector<Ref<MaterialInstance>> Materials;
|
std::vector<Ref<MaterialInstance>> MaterialInstances;
|
||||||
|
std::vector<Ref<PBRMaterialAsset>> MaterialDescs;
|
||||||
|
|
||||||
MeshComponent() = default;
|
MeshComponent() = default;
|
||||||
MeshComponent(const MeshComponent& other) = default;
|
MeshComponent(const MeshComponent& other)
|
||||||
|
: Mesh(other.Mesh)
|
||||||
|
{
|
||||||
|
MaterialInstances.clear();
|
||||||
|
MaterialDescs.clear();
|
||||||
|
for (auto i = 0; i < other.MaterialInstances.size(); i ++)
|
||||||
|
{
|
||||||
|
Ref<MaterialInstance> materialInstance = MaterialInstance::Copy(other.MaterialInstances[i]);
|
||||||
|
MaterialInstances.push_back(materialInstance);
|
||||||
|
MaterialDescs.push_back(other.MaterialDescs[i]);
|
||||||
|
}
|
||||||
|
UpdateMaterials();
|
||||||
|
}
|
||||||
MeshComponent(const Ref<Prism::Mesh>& mesh)
|
MeshComponent(const Ref<Prism::Mesh>& mesh)
|
||||||
: Mesh(mesh) {}
|
|
||||||
|
|
||||||
operator Ref<Prism::Mesh> () { return Mesh; }
|
|
||||||
|
|
||||||
/*
|
|
||||||
MeshComponent(Ref<Prism::Mesh> mesh)
|
|
||||||
: Mesh(mesh)
|
: Mesh(mesh)
|
||||||
{
|
{
|
||||||
// 复制 Mesh 的材质实例,每个实体拥有独立副本
|
MaterialInstances.clear();
|
||||||
if (mesh)
|
MaterialDescs.clear();
|
||||||
|
const auto& materialInstances = Mesh->GetMaterials();
|
||||||
|
for (const auto & i : materialInstances)
|
||||||
{
|
{
|
||||||
const auto& srcMaterials = mesh->GetMaterials();
|
Ref<MaterialInstance> materialInstance = MaterialInstance::Copy(i);
|
||||||
Materials.reserve(srcMaterials.size());
|
MaterialInstances.push_back(materialInstance);
|
||||||
for (auto& srcMat : srcMaterials)
|
}
|
||||||
|
MaterialDescs.resize(materialInstances.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateMaterials(const int index = -1, bool forceUpdate = false)
|
||||||
|
{
|
||||||
|
if (index <= -1)
|
||||||
|
{
|
||||||
|
for (uint32_t i = 0; i < MaterialInstances.size(); i++)
|
||||||
{
|
{
|
||||||
auto newMat = MaterialInstance::Copy(srcMat);
|
if (auto& desc = MaterialDescs[i])
|
||||||
Materials.push_back(newMat);
|
{
|
||||||
|
if (!desc->IsDirty && !forceUpdate) continue;
|
||||||
|
MaterialInstances[i]->Set("u_AlbedoColor", desc->AlbedoColor);
|
||||||
|
MaterialInstances[i]->Set("u_AlbedoTexToggle", desc->AlbedoTexToggle);
|
||||||
|
MaterialInstances[i]->Set("u_AlbedoTexture", desc->AlbedoTexture);
|
||||||
|
MaterialInstances[i]->Set("u_NormalTexToggle", desc->NormalTexToggle);
|
||||||
|
MaterialInstances[i]->Set("u_NormalTexture", desc->NormalTexture);
|
||||||
|
MaterialInstances[i]->Set("u_Metalness", desc->Metalness);
|
||||||
|
MaterialInstances[i]->Set("u_MetalnessTexToggle", desc->MetalnessTexToggle);
|
||||||
|
MaterialInstances[i]->Set("u_MetalnessTexture", desc->MetalnessTexture);
|
||||||
|
MaterialInstances[i]->Set("u_Roughness", desc->Roughness);
|
||||||
|
MaterialInstances[i]->Set("u_RoughnessTexToggle", desc->RoughnessTexToggle);
|
||||||
|
MaterialInstances[i]->Set("u_RoughnessTexture", desc->RoughnessTexture);
|
||||||
|
}else
|
||||||
|
{
|
||||||
|
auto& baseMaterial = Mesh->GetMaterials();
|
||||||
|
|
||||||
|
MaterialInstances[i]->Set("u_AlbedoColor", baseMaterial[i]->Get<glm::vec3>("u_AlbedoColor"));
|
||||||
|
MaterialInstances[i]->Set("u_AlbedoTexToggle", baseMaterial[i]->Get<float>("u_AlbedoTexToggle"));
|
||||||
|
MaterialInstances[i]->Set("u_AlbedoTexture", baseMaterial[i]->TryGetResource<Texture2D>("u_AlbedoTexture"));
|
||||||
|
MaterialInstances[i]->Set("u_NormalTexToggle", baseMaterial[i]->Get<float>("u_NormalTexToggle"));
|
||||||
|
MaterialInstances[i]->Set("u_NormalTexture", baseMaterial[i]->TryGetResource<Texture2D>("u_NormalTexture"));
|
||||||
|
MaterialInstances[i]->Set("u_Metalness", baseMaterial[i]->Get<float>("u_Metalness"));
|
||||||
|
MaterialInstances[i]->Set("u_MetalnessTexToggle", baseMaterial[i]->Get<float>("u_MetalnessTexToggle"));
|
||||||
|
MaterialInstances[i]->Set("u_MetalnessTexture", baseMaterial[i]->TryGetResource<Texture2D>("u_MetalnessTexture"));
|
||||||
|
MaterialInstances[i]->Set("u_Roughness", baseMaterial[0]->Get<float>("u_Roughness"));
|
||||||
|
MaterialInstances[i]->Set("u_RoughnessTexToggle", baseMaterial[i]->Get<float>("u_RoughnessTexToggle"));
|
||||||
|
MaterialInstances[i]->Set("u_RoughnessTexture", baseMaterial[i]->TryGetResource<Texture2D>("u_RoughnessTexture"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}else
|
||||||
|
{
|
||||||
|
if (index >= MaterialInstances.size()) return;
|
||||||
|
const auto& desc = MaterialDescs[index];
|
||||||
|
if (desc)
|
||||||
|
{
|
||||||
|
MaterialInstances[index]->Set("u_AlbedoColor", desc->AlbedoColor);
|
||||||
|
MaterialInstances[index]->Set("u_AlbedoTexToggle", desc->AlbedoTexToggle);
|
||||||
|
MaterialInstances[index]->Set("u_AlbedoTexture", desc->AlbedoTexture);
|
||||||
|
MaterialInstances[index]->Set("u_NormalTexToggle", desc->NormalTexToggle);
|
||||||
|
MaterialInstances[index]->Set("u_NormalTexture", desc->NormalTexture);
|
||||||
|
MaterialInstances[index]->Set("u_Metalness", desc->Metalness);
|
||||||
|
MaterialInstances[index]->Set("u_MetalnessTexToggle", desc->MetalnessTexToggle);
|
||||||
|
MaterialInstances[index]->Set("u_MetalnessTexture", desc->MetalnessTexture);
|
||||||
|
MaterialInstances[index]->Set("u_Roughness", desc->Roughness);
|
||||||
|
MaterialInstances[index]->Set("u_RoughnessTexToggle", desc->RoughnessTexToggle);
|
||||||
|
MaterialInstances[index]->Set("u_RoughnessTexture", desc->RoughnessTexture);
|
||||||
|
}else
|
||||||
|
{
|
||||||
|
auto& baseMaterial = Mesh->GetMaterials();
|
||||||
|
|
||||||
|
MaterialInstances[index]->Set("u_AlbedoColor", baseMaterial[index]->Get<glm::vec3>("u_AlbedoColor"));
|
||||||
|
MaterialInstances[index]->Set("u_AlbedoTexToggle", baseMaterial[index]->Get<float>("u_AlbedoTexToggle"));
|
||||||
|
MaterialInstances[index]->Set("u_AlbedoTexture", baseMaterial[index]->TryGetResource<Texture2D>("u_AlbedoTexture"));
|
||||||
|
MaterialInstances[index]->Set("u_NormalTexToggle", baseMaterial[index]->Get<float>("u_NormalTexToggle"));
|
||||||
|
MaterialInstances[index]->Set("u_NormalTexture", baseMaterial[index]->TryGetResource<Texture2D>("u_NormalTexture"));
|
||||||
|
MaterialInstances[index]->Set("u_Metalness", baseMaterial[index]->Get<float>("u_Metalness"));
|
||||||
|
MaterialInstances[index]->Set("u_MetalnessTexToggle", baseMaterial[index]->Get<float>("u_MetalnessTexToggle"));
|
||||||
|
MaterialInstances[index]->Set("u_MetalnessTexture", baseMaterial[index]->TryGetResource<Texture2D>("u_MetalnessTexture"));
|
||||||
|
MaterialInstances[index]->Set("u_Roughness", baseMaterial[0]->Get<float>("u_Roughness"));
|
||||||
|
MaterialInstances[index]->Set("u_RoughnessTexToggle", baseMaterial[index]->Get<float>("u_RoughnessTexToggle"));
|
||||||
|
MaterialInstances[index]->Set("u_RoughnessTexture", baseMaterial[index]->TryGetResource<Texture2D>("u_RoughnessTexture"));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
operator Ref<Prism::Mesh> () { return Mesh; }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct AnimationComponent
|
struct AnimationComponent
|
||||||
@ -305,7 +386,7 @@ namespace Prism
|
|||||||
{
|
{
|
||||||
float Radius = 0.5f;
|
float Radius = 0.5f;
|
||||||
bool IsTrigger = false;
|
bool IsTrigger = false;
|
||||||
Ref<PhysicsMaterial> Material;
|
Ref<PhysicsMaterialAsset> Material;
|
||||||
|
|
||||||
// The mesh that will be drawn in the editor to show the collision bounds
|
// The mesh that will be drawn in the editor to show the collision bounds
|
||||||
Ref<Mesh> DebugMesh;
|
Ref<Mesh> DebugMesh;
|
||||||
@ -344,7 +425,7 @@ namespace Prism
|
|||||||
glm::vec3 Size = { 1.0f, 1.0f, 1.0f };
|
glm::vec3 Size = { 1.0f, 1.0f, 1.0f };
|
||||||
glm::vec3 Offset = { 0.0f, 0.0f, 0.0f };
|
glm::vec3 Offset = { 0.0f, 0.0f, 0.0f };
|
||||||
bool IsTrigger = false;
|
bool IsTrigger = false;
|
||||||
Ref<PhysicsMaterial> Material;
|
Ref<PhysicsMaterialAsset> Material;
|
||||||
|
|
||||||
// The mesh that will be drawn in the editor to show the collision bounds
|
// The mesh that will be drawn in the editor to show the collision bounds
|
||||||
Ref<Mesh> DebugMesh;
|
Ref<Mesh> DebugMesh;
|
||||||
@ -358,7 +439,7 @@ namespace Prism
|
|||||||
float Radius = 0.5f;
|
float Radius = 0.5f;
|
||||||
float Height = 1.0f;
|
float Height = 1.0f;
|
||||||
bool IsTrigger = false;
|
bool IsTrigger = false;
|
||||||
Ref<PhysicsMaterial> Material;
|
Ref<PhysicsMaterialAsset> Material;
|
||||||
|
|
||||||
Ref<Mesh> DebugMesh;
|
Ref<Mesh> DebugMesh;
|
||||||
|
|
||||||
@ -373,7 +454,7 @@ namespace Prism
|
|||||||
bool IsConvex = false;
|
bool IsConvex = false;
|
||||||
bool IsTrigger = false;
|
bool IsTrigger = false;
|
||||||
bool OverrideMesh = false;
|
bool OverrideMesh = false;
|
||||||
Ref<PhysicsMaterial> Material;
|
Ref<PhysicsMaterialAsset> Material;
|
||||||
|
|
||||||
MeshColliderComponent() = default;
|
MeshColliderComponent() = default;
|
||||||
MeshColliderComponent(const MeshColliderComponent& other) = default;
|
MeshColliderComponent(const MeshColliderComponent& other) = default;
|
||||||
@ -431,7 +512,7 @@ namespace Prism
|
|||||||
bool ShowIcon = false;
|
bool ShowIcon = false;
|
||||||
|
|
||||||
bool DynamicSky = false;
|
bool DynamicSky = false;
|
||||||
glm::vec3 TurbidityAzimuthInclination = { 2.0, 0.0, 0.0 };
|
glm::vec3 TurbidityAzimuthInclination = { 2.0, 0.0, 1.0 };
|
||||||
|
|
||||||
SkyLightComponent(const Ref<Environment>& environment)
|
SkyLightComponent(const Ref<Environment>& environment)
|
||||||
: SceneEnvironment(environment)
|
: SceneEnvironment(environment)
|
||||||
@ -452,7 +533,7 @@ namespace Prism
|
|||||||
MeshComponent,
|
MeshComponent,
|
||||||
RigidBodyComponent, BoxColliderComponent, SphereColliderComponent, CapsuleColliderComponent, MeshColliderComponent,
|
RigidBodyComponent, BoxColliderComponent, SphereColliderComponent, CapsuleColliderComponent, MeshColliderComponent,
|
||||||
AnimationComponent,
|
AnimationComponent,
|
||||||
DirectionalLightComponent, SkyLightComponent, PointLightComponent, SpotLightComponent,
|
DirectionalLightComponent, SkyLightComponent,
|
||||||
ScriptComponent,
|
ScriptComponent,
|
||||||
CameraComponent
|
CameraComponent
|
||||||
>;
|
>;
|
||||||
|
|||||||
@ -32,12 +32,7 @@ namespace Prism
|
|||||||
|
|
||||||
static uint32_t s_SceneIDCounter = 0;
|
static uint32_t s_SceneIDCounter = 0;
|
||||||
|
|
||||||
|
Scene::Scene(const std::string& debugName, const bool isEditorScene, const bool runtime)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Scene::Scene(const std::string& debugName, const bool isEditorScene)
|
|
||||||
: m_SceneID(++s_SceneIDCounter), m_DebugName(debugName)
|
: m_SceneID(++s_SceneIDCounter), m_DebugName(debugName)
|
||||||
{
|
{
|
||||||
m_Registry.on_construct<TransformComponent>().connect<&Physics2D::OnTransformConstruct>();
|
m_Registry.on_construct<TransformComponent>().connect<&Physics2D::OnTransformConstruct>();
|
||||||
@ -56,10 +51,11 @@ namespace Prism
|
|||||||
Physics3D::CreateScene();
|
Physics3D::CreateScene();
|
||||||
}
|
}
|
||||||
|
|
||||||
Init();
|
Init(runtime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Scene::~Scene()
|
Scene::~Scene()
|
||||||
{
|
{
|
||||||
m_Registry.on_destroy<ScriptComponent>().disconnect();
|
m_Registry.on_destroy<ScriptComponent>().disconnect();
|
||||||
@ -68,20 +64,24 @@ namespace Prism
|
|||||||
s_ActiveScenes.erase(m_SceneID);
|
s_ActiveScenes.erase(m_SceneID);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scene::Init()
|
void Scene::Init(const bool runtime)
|
||||||
{
|
{
|
||||||
// const auto skyboxShader = Shader::Create("assets/shaders/Skybox.glsl");
|
const auto skyboxShader = Shader::Create("assets/shaders/Skybox.glsl");
|
||||||
// m_SkyboxMaterial = MaterialInstance::Create(Material::Create(skyboxShader));
|
m_SkyboxMaterial = MaterialInstance::Create(Material::Create(skyboxShader));
|
||||||
// m_SkyboxMaterial->SetFlag(MaterialFlag::DepthTest, false);
|
m_SkyboxMaterial->SetFlag(MaterialFlag::DepthTest, false);
|
||||||
|
|
||||||
m_CameraIcon = AssetsManager::GetAsset<Texture2D>("assets/editor/Camera.png");
|
|
||||||
m_LightIcon = AssetsManager::GetAsset<Texture2D>("assets/editor/light.png");
|
|
||||||
|
|
||||||
|
if (!runtime)
|
||||||
|
{
|
||||||
|
m_CameraIcon = AssetsManager::GetAsset<Texture2D>("assets/editor/Camera.png");
|
||||||
|
m_LightIcon = AssetsManager::GetAsset<Texture2D>("assets/editor/light.png");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scene::OnShutdown()
|
void Scene::OnShutdown()
|
||||||
{
|
{
|
||||||
b2DestroyWorld(m_Registry.get<Box2DWorldComponent>(m_SceneEntity).World);
|
b2DestroyWorld(m_Registry.get<Box2DWorldComponent>(m_SceneEntity).World);
|
||||||
|
Physics3D::DestroyScene();
|
||||||
|
ScriptEngine::OnSceneDestruct(m_SceneID);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scene::OnUpdate(TimeStep ts)
|
void Scene::OnUpdate(TimeStep ts)
|
||||||
@ -91,14 +91,14 @@ namespace Prism
|
|||||||
|
|
||||||
const auto sceneView = m_Registry.view<Box2DWorldComponent>();
|
const auto sceneView = m_Registry.view<Box2DWorldComponent>();
|
||||||
const auto& box2DWorld = m_Registry.get<Box2DWorldComponent>(sceneView.front()).World;
|
const auto& box2DWorld = m_Registry.get<Box2DWorldComponent>(sceneView.front()).World;
|
||||||
int32_t velocityIterations = 6;
|
|
||||||
constexpr int32_t positionIterations = 2;
|
constexpr int32_t positionIterations = 2;
|
||||||
// box2DWorld->Step(ts, velocityIterations, positionIterations);
|
|
||||||
b2World_Step(box2DWorld, ts, positionIterations);
|
b2World_Step(box2DWorld, ts, positionIterations);
|
||||||
|
|
||||||
// Process Contact Envents box2d version 3.0^ should impl contact event after b2World_Step
|
// Process Contact Envents box2d version 3.0^ should impl contact event after b2World_Step
|
||||||
Physics2D::ProcessContactEvents(box2DWorld);
|
Physics2D::ProcessContactEvents(box2DWorld);
|
||||||
|
|
||||||
|
// Physics3D
|
||||||
|
Physics3D::Simulate(ts);
|
||||||
|
|
||||||
{
|
{
|
||||||
const auto view = m_Registry.view<RigidBody2DComponent>();
|
const auto view = m_Registry.view<RigidBody2DComponent>();
|
||||||
for (const auto entity : view)
|
for (const auto entity : view)
|
||||||
@ -138,8 +138,6 @@ namespace Prism
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Physics3D::Simulate(ts);
|
|
||||||
|
|
||||||
// Update all entities
|
// Update all entities
|
||||||
{
|
{
|
||||||
const auto view = m_Registry.view<ScriptComponent>();
|
const auto view = m_Registry.view<ScriptComponent>();
|
||||||
@ -150,6 +148,7 @@ namespace Prism
|
|||||||
ScriptEngine::OnUpdateEntity(e, ts);
|
ScriptEngine::OnUpdateEntity(e, ts);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scene::OnRenderRuntime(const TimeStep ts)
|
void Scene::OnRenderRuntime(const TimeStep ts)
|
||||||
@ -171,8 +170,7 @@ namespace Prism
|
|||||||
|
|
||||||
// TODO: only one sky light at the moment!
|
// TODO: only one sky light at the moment!
|
||||||
{
|
{
|
||||||
if (!m_Environment)
|
m_Environment = Ref<Environment>::Create();
|
||||||
m_Environment = Ref<Environment>::Create(Renderer3D::GetBlackCubeTexture(), Renderer3D::GetBlackCubeTexture());
|
|
||||||
const auto lights = m_Registry.group<SkyLightComponent>(entt::get<TransformComponent>);
|
const auto lights = m_Registry.group<SkyLightComponent>(entt::get<TransformComponent>);
|
||||||
for (const auto entity : lights)
|
for (const auto entity : lights)
|
||||||
{
|
{
|
||||||
@ -185,23 +183,40 @@ namespace Prism
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
m_SkyboxMaterial->Set("u_TextureLod", m_SkyboxLod);
|
||||||
|
|
||||||
SceneRenderer::BeginScene(this, { static_cast<Camera>(camera), cameraViewMatrix }, false);
|
SceneRenderer::BeginScene(this, { static_cast<Camera>(camera), cameraViewMatrix }, false);
|
||||||
{
|
{
|
||||||
const auto group = m_Registry.group<MeshComponent>(entt::get<TransformComponent>);
|
const auto group = m_Registry.group<MeshComponent>(entt::get<TransformComponent>);
|
||||||
|
|
||||||
|
// this maybe not to set
|
||||||
|
// in Editor actually only one materialdesc will be changed
|
||||||
|
Ref<PBRMaterialAsset> materialAsset;
|
||||||
|
|
||||||
for (const auto entity : group)
|
for (const auto entity : group)
|
||||||
{
|
{
|
||||||
const auto& [transformComponent, meshComponent] = group.get<TransformComponent, MeshComponent>(entity);
|
const auto& [transformComponent, meshComponent] = group.get<TransformComponent, MeshComponent>(entity);
|
||||||
if (meshComponent.Mesh)
|
if (meshComponent.Mesh)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
for (auto i = 0; i < meshComponent.MaterialInstances.size(); i++)
|
||||||
|
{
|
||||||
|
if (meshComponent.MaterialDescs[i] && meshComponent.MaterialDescs[i]->IsDirty)
|
||||||
|
{
|
||||||
|
materialAsset = meshComponent.MaterialDescs[i];
|
||||||
|
meshComponent.UpdateMaterials(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
meshComponent.Mesh->OnUpdate(ts);
|
meshComponent.Mesh->OnUpdate(ts);
|
||||||
|
|
||||||
glm::mat4 transform = GetTransformRelativeToParent(Entity(entity, this));
|
glm::mat4 transform = GetTransformRelativeToParent(Entity(entity, this));
|
||||||
|
|
||||||
// TODO: Should we render (logically)
|
// TODO: Should we render (logically)
|
||||||
SceneRenderer::SubmitMesh(meshComponent, transform);
|
SceneRenderer::SubmitMesh(meshComponent, transform, meshComponent.MaterialInstances);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (materialAsset) materialAsset->IsDirty = false;
|
||||||
/////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////
|
||||||
@ -224,7 +239,9 @@ namespace Prism
|
|||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////
|
||||||
}
|
}
|
||||||
|
SceneRenderer::FlushToScreen();
|
||||||
SceneRenderer::EndScene();
|
SceneRenderer::EndScene();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scene::OnRenderEditor(const TimeStep ts, const EditorCamera& editorCamera)
|
void Scene::OnRenderEditor(const TimeStep ts, const EditorCamera& editorCamera)
|
||||||
@ -236,7 +253,7 @@ namespace Prism
|
|||||||
// TODO: only one sky light at the moment!
|
// TODO: only one sky light at the moment!
|
||||||
{
|
{
|
||||||
const auto lights = m_Registry.group<SkyLightComponent>(entt::get<TransformComponent>);
|
const auto lights = m_Registry.group<SkyLightComponent>(entt::get<TransformComponent>);
|
||||||
if (!m_Environment)
|
if (lights.empty())
|
||||||
m_Environment = Ref<Environment>::Create(Renderer3D::GetBlackCubeTexture(), Renderer3D::GetBlackCubeTexture());
|
m_Environment = Ref<Environment>::Create(Renderer3D::GetBlackCubeTexture(), Renderer3D::GetBlackCubeTexture());
|
||||||
if (!lights.empty())
|
if (!lights.empty())
|
||||||
{
|
{
|
||||||
@ -251,14 +268,13 @@ namespace Prism
|
|||||||
|
|
||||||
m_Environment = skyLightComponent.SceneEnvironment;
|
m_Environment = skyLightComponent.SceneEnvironment;
|
||||||
m_EnvironmentIntensity = skyLightComponent.Intensity;
|
m_EnvironmentIntensity = skyLightComponent.Intensity;
|
||||||
|
if (m_Environment)
|
||||||
break; //TODO: this only support one environment
|
SetSkybox(m_Environment->RadianceMap);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (m_Environment)
|
|
||||||
SetSkybox(m_Environment->RadianceMap);
|
|
||||||
|
|
||||||
|
m_SkyboxMaterial->Set("u_TextureLod", m_SkyboxLod);
|
||||||
|
|
||||||
// TODO: this value should be storage and can modify
|
// TODO: this value should be storage and can modify
|
||||||
// TODO: Renderer2D cannot blend with Renderer3D
|
// TODO: Renderer2D cannot blend with Renderer3D
|
||||||
@ -271,21 +287,35 @@ namespace Prism
|
|||||||
|
|
||||||
const auto group = m_Registry.group<MeshComponent>(entt::get<TransformComponent>);
|
const auto group = m_Registry.group<MeshComponent>(entt::get<TransformComponent>);
|
||||||
{
|
{
|
||||||
|
|
||||||
|
// in Editor actually only one materialdesc will be changed
|
||||||
|
Ref<PBRMaterialAsset> materialAsset;
|
||||||
|
|
||||||
for (const auto [entity, meshComponent, transformComponent]: group.each())
|
for (const auto [entity, meshComponent, transformComponent]: group.each())
|
||||||
{
|
{
|
||||||
Entity e = {entity, this};
|
Entity e = {entity, this};
|
||||||
|
|
||||||
if (meshComponent.Mesh)
|
if (meshComponent.Mesh)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
for (auto i = 0; i < meshComponent.MaterialInstances.size(); i++)
|
||||||
|
{
|
||||||
|
if (meshComponent.MaterialDescs[i] && meshComponent.MaterialDescs[i]->IsDirty)
|
||||||
|
{
|
||||||
|
materialAsset = meshComponent.MaterialDescs[i];
|
||||||
|
meshComponent.UpdateMaterials(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
meshComponent.Mesh->OnUpdate(ts);
|
meshComponent.Mesh->OnUpdate(ts);
|
||||||
|
|
||||||
glm::mat4 transform = GetTransformRelativeToParent(e);
|
glm::mat4 transform = GetTransformRelativeToParent(e);
|
||||||
|
|
||||||
// TODO: Should we render (logically)
|
// TODO: Should we render (logically)
|
||||||
if (m_SelectedEntity == entity)
|
if (m_SelectedEntity == entity)
|
||||||
SceneRenderer::SubmitSelectedMesh(meshComponent, transform);
|
SceneRenderer::SubmitSelectedMesh(meshComponent, transform, meshComponent.MaterialInstances);
|
||||||
else
|
else
|
||||||
SceneRenderer::SubmitMesh(meshComponent, transform);
|
SceneRenderer::SubmitMesh(meshComponent, transform, meshComponent.MaterialInstances);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Renderer Collider
|
// Renderer Collider
|
||||||
@ -303,6 +333,8 @@ namespace Prism
|
|||||||
SceneRenderer::SubmitColliderMesh(*collider, transform);
|
SceneRenderer::SubmitColliderMesh(*collider, transform);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (materialAsset) materialAsset->IsDirty = false;
|
||||||
}
|
}
|
||||||
/////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@ -432,6 +464,12 @@ namespace Prism
|
|||||||
m_IsPlaying = false;
|
m_IsPlaying = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Scene::SetViewportSize(const glm::ivec2& viewportSize)
|
||||||
|
{
|
||||||
|
m_ViewportWidth = viewportSize.x;
|
||||||
|
m_ViewportHeight = viewportSize.y;
|
||||||
|
}
|
||||||
|
|
||||||
void Scene::SetViewportSize(const uint32_t width, const uint32_t height)
|
void Scene::SetViewportSize(const uint32_t width, const uint32_t height)
|
||||||
{
|
{
|
||||||
m_ViewportWidth = width;
|
m_ViewportWidth = width;
|
||||||
@ -441,6 +479,7 @@ namespace Prism
|
|||||||
void Scene::SetSkybox(const Ref<TextureCube>& skybox)
|
void Scene::SetSkybox(const Ref<TextureCube>& skybox)
|
||||||
{
|
{
|
||||||
m_SkyboxTexture = skybox;
|
m_SkyboxTexture = skybox;
|
||||||
|
m_SkyboxMaterial->Set("u_Texture", skybox);
|
||||||
}
|
}
|
||||||
|
|
||||||
Entity Scene::GetMainCameraEntity()
|
Entity Scene::GetMainCameraEntity()
|
||||||
@ -579,8 +618,8 @@ namespace Prism
|
|||||||
{
|
{
|
||||||
target->m_Environment = m_Environment;
|
target->m_Environment = m_Environment;
|
||||||
target->m_SkyboxTexture = m_SkyboxTexture;
|
target->m_SkyboxTexture = m_SkyboxTexture;
|
||||||
|
target->m_SkyboxMaterial = m_SkyboxMaterial;
|
||||||
target->m_SkyboxLod = m_SkyboxLod;
|
target->m_SkyboxLod = m_SkyboxLod;
|
||||||
target->m_EnvironmentIntensity = m_EnvironmentIntensity;
|
|
||||||
|
|
||||||
std::unordered_map<UUID, entt::entity> enttMap;
|
std::unordered_map<UUID, entt::entity> enttMap;
|
||||||
auto idComponents = m_Registry.view<IDComponent>();
|
auto idComponents = m_Registry.view<IDComponent>();
|
||||||
@ -646,33 +685,35 @@ namespace Prism
|
|||||||
// Point Light
|
// Point Light
|
||||||
{
|
{
|
||||||
const auto pointLights = m_Registry.group<PointLightComponent>(entt::get<TransformComponent>);
|
const auto pointLights = m_Registry.group<PointLightComponent>(entt::get<TransformComponent>);
|
||||||
m_LightEnvironment.PointLightCount = 0;
|
uint32_t pointLightIndex = 0;
|
||||||
for (const auto entity : pointLights)
|
for (const auto entity : pointLights)
|
||||||
{
|
{
|
||||||
if (m_LightEnvironment.PointLightCount >= 16) break;
|
if (pointLightIndex >= 8) break;
|
||||||
auto [transform, light] = pointLights.get<TransformComponent, PointLightComponent>(entity);
|
auto [transform, light] = pointLights.get<TransformComponent, PointLightComponent>(entity);
|
||||||
m_LightEnvironment.PointLights[m_LightEnvironment.PointLightCount++] = {
|
m_LightEnvironment.PointLights[pointLightIndex++] = {
|
||||||
transform.Translation,
|
transform.Translation,
|
||||||
light.Radiance,
|
light.Radiance,
|
||||||
light.Radius,
|
light.Radius,
|
||||||
light.Intensity,
|
light.Intensity,
|
||||||
light.CastShadows,
|
light.CastShadows,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
m_LightEnvironment.PointLightCount ++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Spot Light
|
// Spot Light
|
||||||
{
|
{
|
||||||
const auto spotLights = m_Registry.group<SpotLightComponent>(entt::get<TransformComponent>);
|
const auto spotLights = m_Registry.group<SpotLightComponent>(entt::get<TransformComponent>);
|
||||||
m_LightEnvironment.SpotLightCount = 0;
|
uint32_t pointLightIndex = 0;
|
||||||
for (const auto entity : spotLights)
|
for (const auto entity : spotLights)
|
||||||
{
|
{
|
||||||
if (m_LightEnvironment.SpotLightCount >= 16) break;
|
if (pointLightIndex >= 8) break;
|
||||||
auto [transform, light] = spotLights.get<TransformComponent, SpotLightComponent>(entity);
|
auto [transform, light] = spotLights.get<TransformComponent, SpotLightComponent>(entity);
|
||||||
const glm::vec3 direction = glm::normalize(glm::mat3(transform.GetTransform()) * glm::vec3(0.0f, 0.0f, 1.0f));
|
const glm::vec3 direction = glm::normalize(glm::mat3(transform.GetTransform()) * glm::vec3(0.0f, 0.0f, 1.0f));
|
||||||
const float innerCos = glm::cos(glm::radians(light.InnerConeAngle));
|
const float innerCos = glm::cos(glm::radians(light.InnerConeAngle));
|
||||||
const float outerCos = glm::cos(glm::radians(light.OuterConeAngle));
|
const float outerCos = glm::cos(glm::radians(light.OuterConeAngle));
|
||||||
m_LightEnvironment.SpotLights[m_LightEnvironment.SpotLightCount++] = {
|
m_LightEnvironment.SpotLights[pointLightIndex++] = {
|
||||||
transform.Translation,
|
transform.Translation,
|
||||||
direction,
|
direction,
|
||||||
light.Radiance,
|
light.Radiance,
|
||||||
@ -682,6 +723,7 @@ namespace Prism
|
|||||||
outerCos,
|
outerCos,
|
||||||
light.CastShadows,
|
light.CastShadows,
|
||||||
};
|
};
|
||||||
|
m_LightEnvironment.SpotLightCount ++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -54,10 +54,10 @@ namespace Prism
|
|||||||
{
|
{
|
||||||
GPUDirectionalLight DirectionalLights[4];
|
GPUDirectionalLight DirectionalLights[4];
|
||||||
|
|
||||||
GPUPointLight PointLights[16]{};
|
GPUPointLight PointLights[8]{};
|
||||||
int PointLightCount = 0;
|
int PointLightCount = 0;
|
||||||
|
|
||||||
GPUSpotLight SpotLights[16]{};
|
GPUSpotLight SpotLights[8]{};
|
||||||
int SpotLightCount = 0;
|
int SpotLightCount = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -74,10 +74,10 @@ namespace Prism
|
|||||||
class PRISM_API Scene : public RefCounted
|
class PRISM_API Scene : public RefCounted
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Scene(const std::string& debugName = "Scene", bool isEditorScene = false);
|
Scene(const std::string& debugName = "Scene", bool isEditorScene = false, bool runtime = false);
|
||||||
~Scene();
|
~Scene();
|
||||||
|
|
||||||
void Init();
|
void Init(bool runtime);
|
||||||
void OnShutdown();
|
void OnShutdown();
|
||||||
|
|
||||||
void OnUpdate(TimeStep ts);
|
void OnUpdate(TimeStep ts);
|
||||||
@ -88,6 +88,7 @@ namespace Prism
|
|||||||
void OnRuntimeStart();
|
void OnRuntimeStart();
|
||||||
void OnRuntimeStop();
|
void OnRuntimeStop();
|
||||||
|
|
||||||
|
void SetViewportSize(const glm::ivec2& viewportSize);
|
||||||
void SetViewportSize(uint32_t width, uint32_t height);
|
void SetViewportSize(uint32_t width, uint32_t height);
|
||||||
|
|
||||||
const Ref<Environment>& GetEnvironment() const { return m_Environment; }
|
const Ref<Environment>& GetEnvironment() const { return m_Environment; }
|
||||||
@ -164,10 +165,11 @@ namespace Prism
|
|||||||
bool m_IsPlaying = false;
|
bool m_IsPlaying = false;
|
||||||
|
|
||||||
Ref<Environment> m_Environment;
|
Ref<Environment> m_Environment;
|
||||||
|
float m_EnvironmentIntensity = 1.0f;
|
||||||
Ref<TextureCube> m_SkyboxTexture;
|
Ref<TextureCube> m_SkyboxTexture;
|
||||||
|
Ref<MaterialInstance> m_SkyboxMaterial;
|
||||||
|
|
||||||
float m_SkyboxLod = 0.0f;
|
float m_SkyboxLod = 0.0f;
|
||||||
float m_EnvironmentIntensity = 1.0f;
|
|
||||||
|
|
||||||
|
|
||||||
Ref<Texture2D> m_CameraIcon;
|
Ref<Texture2D> m_CameraIcon;
|
||||||
|
|||||||
@ -13,142 +13,13 @@
|
|||||||
#include "Prism/Physics/PhysicsLayer.h"
|
#include "Prism/Physics/PhysicsLayer.h"
|
||||||
#include "Prism/Physics/PhysicsWrappers.h"
|
#include "Prism/Physics/PhysicsWrappers.h"
|
||||||
#include "Prism/Renderer/Meshfactory.h"
|
#include "Prism/Renderer/Meshfactory.h"
|
||||||
#include "../Asset/AssetsManager.h"
|
#include "Prism/Asset/AssetsManager.h"
|
||||||
|
|
||||||
namespace YAML
|
#include "Prism/Utilities/SerializeUtils.h"
|
||||||
{
|
|
||||||
|
|
||||||
template<>
|
|
||||||
struct convert<glm::vec2>
|
|
||||||
{
|
|
||||||
static Node encode(const glm::vec2& rhs)
|
|
||||||
{
|
|
||||||
Node node;
|
|
||||||
node.push_back(rhs.x);
|
|
||||||
node.push_back(rhs.y);
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool decode(const Node& node, glm::vec2& rhs)
|
|
||||||
{
|
|
||||||
if (!node.IsSequence() || node.size() != 2)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
rhs.x = node[0].as<float>();
|
|
||||||
rhs.y = node[1].as<float>();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<>
|
|
||||||
struct convert<glm::vec3>
|
|
||||||
{
|
|
||||||
static Node encode(const glm::vec3& rhs)
|
|
||||||
{
|
|
||||||
Node node;
|
|
||||||
node.push_back(rhs.x);
|
|
||||||
node.push_back(rhs.y);
|
|
||||||
node.push_back(rhs.z);
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool decode(const Node& node, glm::vec3& rhs)
|
|
||||||
{
|
|
||||||
if (!node.IsSequence() || node.size() != 3)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
rhs.x = node[0].as<float>();
|
|
||||||
rhs.y = node[1].as<float>();
|
|
||||||
rhs.z = node[2].as<float>();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<>
|
|
||||||
struct convert<glm::vec4>
|
|
||||||
{
|
|
||||||
static Node encode(const glm::vec4& rhs)
|
|
||||||
{
|
|
||||||
Node node;
|
|
||||||
node.push_back(rhs.x);
|
|
||||||
node.push_back(rhs.y);
|
|
||||||
node.push_back(rhs.z);
|
|
||||||
node.push_back(rhs.w);
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool decode(const Node& node, glm::vec4& rhs)
|
|
||||||
{
|
|
||||||
if (!node.IsSequence() || node.size() != 4)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
rhs.x = node[0].as<float>();
|
|
||||||
rhs.y = node[1].as<float>();
|
|
||||||
rhs.z = node[2].as<float>();
|
|
||||||
rhs.w = node[3].as<float>();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<>
|
|
||||||
struct convert<glm::quat>
|
|
||||||
{
|
|
||||||
static Node encode(const glm::quat& rhs)
|
|
||||||
{
|
|
||||||
Node node;
|
|
||||||
node.push_back(rhs.w);
|
|
||||||
node.push_back(rhs.x);
|
|
||||||
node.push_back(rhs.y);
|
|
||||||
node.push_back(rhs.z);
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool decode(const Node& node, glm::quat& rhs)
|
|
||||||
{
|
|
||||||
if (!node.IsSequence() || node.size() != 4)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
rhs.w = node[0].as<float>();
|
|
||||||
rhs.x = node[1].as<float>();
|
|
||||||
rhs.y = node[2].as<float>();
|
|
||||||
rhs.z = node[3].as<float>();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace Prism
|
namespace Prism
|
||||||
{
|
{
|
||||||
|
|
||||||
YAML::Emitter& operator<<(YAML::Emitter& out, const glm::vec2& v)
|
|
||||||
{
|
|
||||||
out << YAML::Flow;
|
|
||||||
out << YAML::BeginSeq << v.x << v.y << YAML::EndSeq;
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
YAML::Emitter& operator<<(YAML::Emitter& out, const glm::vec3& v)
|
|
||||||
{
|
|
||||||
out << YAML::Flow;
|
|
||||||
out << YAML::BeginSeq << v.x << v.y << v.z << YAML::EndSeq;
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
YAML::Emitter& operator<<(YAML::Emitter& out, const glm::vec4& v)
|
|
||||||
{
|
|
||||||
out << YAML::Flow;
|
|
||||||
out << YAML::BeginSeq << v.x << v.y << v.z << v.w << YAML::EndSeq;
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
YAML::Emitter& operator<<(YAML::Emitter& out, const glm::quat& v)
|
|
||||||
{
|
|
||||||
out << YAML::Flow;
|
|
||||||
out << YAML::BeginSeq << v.w << v.x << v.y << v.z << YAML::EndSeq;
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
SceneSerializer::SceneSerializer(const Ref<Scene>& scene)
|
SceneSerializer::SceneSerializer(const Ref<Scene>& scene)
|
||||||
: m_Scene(scene)
|
: m_Scene(scene)
|
||||||
{
|
{
|
||||||
@ -163,7 +34,7 @@ namespace Prism
|
|||||||
|
|
||||||
if (entity.HasComponent<RelationshipComponent>())
|
if (entity.HasComponent<RelationshipComponent>())
|
||||||
{
|
{
|
||||||
auto& relationshipComponent = entity.GetComponent<RelationshipComponent>();
|
const auto& relationshipComponent = entity.GetComponent<RelationshipComponent>();
|
||||||
out << YAML::Key << "Parent" << YAML::Value << relationshipComponent.ParentHandle;
|
out << YAML::Key << "Parent" << YAML::Value << relationshipComponent.ParentHandle;
|
||||||
|
|
||||||
out << YAML::Key << "Children";
|
out << YAML::Key << "Children";
|
||||||
@ -258,11 +129,44 @@ namespace Prism
|
|||||||
out << YAML::Key << "MeshComponent";
|
out << YAML::Key << "MeshComponent";
|
||||||
out << YAML::BeginMap; // MeshComponent
|
out << YAML::BeginMap; // MeshComponent
|
||||||
|
|
||||||
const auto mesh = entity.GetComponent<MeshComponent>().Mesh;
|
const auto& meshComponent = entity.GetComponent<MeshComponent>();
|
||||||
if (mesh)
|
if (meshComponent.Mesh)
|
||||||
|
{
|
||||||
|
const auto& mesh = meshComponent.Mesh;
|
||||||
out << YAML::Key << "AssetID" << YAML::Value << mesh->Handle;
|
out << YAML::Key << "AssetID" << YAML::Value << mesh->Handle;
|
||||||
|
out << YAML::Key << "AssetPath" << YAML::Value << mesh->FilePath;
|
||||||
|
|
||||||
|
if (!meshComponent.MaterialDescs.empty())
|
||||||
|
{
|
||||||
|
|
||||||
|
out << YAML::Key << "Materials";
|
||||||
|
out << YAML::BeginMap;
|
||||||
|
for (auto i = 0; i < meshComponent.MaterialDescs.size(); ++i)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
std::string slots = "Slot " + std::to_string(i);
|
||||||
|
out << YAML::Key << slots;
|
||||||
|
out << YAML::BeginMap;
|
||||||
|
if (meshComponent.MaterialDescs[i])
|
||||||
|
{
|
||||||
|
out << YAML::Key << "AssetHandle" << YAML::Value << meshComponent.MaterialDescs[i]->Handle;
|
||||||
|
out << YAML::Key << "AssetPath" << YAML::Value << meshComponent.MaterialDescs[i]->FilePath;
|
||||||
|
}else
|
||||||
|
{
|
||||||
|
out << YAML::Key << "AssetHandle" << YAML::Value << 0;
|
||||||
|
out << YAML::Key << "AssetPath" << YAML::Value << "";
|
||||||
|
}
|
||||||
|
out << YAML::EndMap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out << YAML::EndMap;
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
out << YAML::Key << "AssetID" << YAML::Value << 0;
|
out << YAML::Key << "AssetID" << YAML::Value << 0;
|
||||||
|
out << YAML::Key << "AssetPath" << YAML::Value << "";
|
||||||
|
}
|
||||||
|
|
||||||
out << YAML::EndMap; // MeshComponent
|
out << YAML::EndMap; // MeshComponent
|
||||||
}
|
}
|
||||||
@ -287,7 +191,16 @@ namespace Prism
|
|||||||
out << YAML::BeginMap; // SkyLightComponent
|
out << YAML::BeginMap; // SkyLightComponent
|
||||||
|
|
||||||
const auto& skyLightComponent = entity.GetComponent<SkyLightComponent>();
|
const auto& skyLightComponent = entity.GetComponent<SkyLightComponent>();
|
||||||
out << YAML::Key << "EnvironmentMap" << YAML::Value << skyLightComponent.SceneEnvironment->Handle;
|
if (skyLightComponent.SceneEnvironment)
|
||||||
|
{
|
||||||
|
out << YAML::Key << "EnvironmentMap" << YAML::Value << skyLightComponent.SceneEnvironment->Handle;
|
||||||
|
out << YAML::Key << "EnvironmentAssetPath" << YAML::Value << skyLightComponent.SceneEnvironment->FilePath;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
out << YAML::Key << "EnvironmentMap" << YAML::Value << 0;
|
||||||
|
out << YAML::Key << "EnvironmentAssetPath" << YAML::Value << "";
|
||||||
|
}
|
||||||
out << YAML::Key << "Intensity" << YAML::Value << skyLightComponent.Intensity;
|
out << YAML::Key << "Intensity" << YAML::Value << skyLightComponent.Intensity;
|
||||||
out << YAML::Key << "Angle" << YAML::Value << skyLightComponent.Angle;
|
out << YAML::Key << "Angle" << YAML::Value << skyLightComponent.Angle;
|
||||||
|
|
||||||
@ -518,9 +431,16 @@ namespace Prism
|
|||||||
out << YAML::Key << "IsTrigger" << YAML::Value << boxColliderComponent.IsTrigger;
|
out << YAML::Key << "IsTrigger" << YAML::Value << boxColliderComponent.IsTrigger;
|
||||||
|
|
||||||
if (boxColliderComponent.Material)
|
if (boxColliderComponent.Material)
|
||||||
|
{
|
||||||
out << YAML::Key << "Material" << YAML::Value << boxColliderComponent.Material->Handle;
|
out << YAML::Key << "Material" << YAML::Value << boxColliderComponent.Material->Handle;
|
||||||
|
out << YAML::Key << "MaterialPath" << YAML::Value << boxColliderComponent.Material->FilePath;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
out << YAML::Key << "Material" << YAML::Value << 0;
|
out << YAML::Key << "Material" << YAML::Value << 0;
|
||||||
|
out << YAML::Key << "MaterialPath" << YAML::Value << "";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
out << YAML::EndMap; // BoxColliderComponent
|
out << YAML::EndMap; // BoxColliderComponent
|
||||||
}
|
}
|
||||||
@ -535,9 +455,16 @@ namespace Prism
|
|||||||
out << YAML::Key << "IsTrigger" << YAML::Value << sphereColliderComponent.IsTrigger;
|
out << YAML::Key << "IsTrigger" << YAML::Value << sphereColliderComponent.IsTrigger;
|
||||||
|
|
||||||
if (sphereColliderComponent.Material)
|
if (sphereColliderComponent.Material)
|
||||||
|
{
|
||||||
out << YAML::Key << "Material" << YAML::Value << sphereColliderComponent.Material->Handle;
|
out << YAML::Key << "Material" << YAML::Value << sphereColliderComponent.Material->Handle;
|
||||||
|
out << YAML::Key << "MaterialPath" << YAML::Value << sphereColliderComponent.Material->FilePath;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
out << YAML::Key << "Material" << YAML::Value << 0;
|
out << YAML::Key << "Material" << YAML::Value << 0;
|
||||||
|
out << YAML::Key << "MaterialPath" << YAML::Value << "";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
out << YAML::EndMap; // SphereColliderComponent
|
out << YAML::EndMap; // SphereColliderComponent
|
||||||
}
|
}
|
||||||
@ -552,10 +479,18 @@ namespace Prism
|
|||||||
out << YAML::Key << "Height" << YAML::Value << capsuleColliderComponent.Height;
|
out << YAML::Key << "Height" << YAML::Value << capsuleColliderComponent.Height;
|
||||||
out << YAML::Key << "IsTrigger" << YAML::Value << capsuleColliderComponent.IsTrigger;
|
out << YAML::Key << "IsTrigger" << YAML::Value << capsuleColliderComponent.IsTrigger;
|
||||||
|
|
||||||
|
|
||||||
if (capsuleColliderComponent.Material)
|
if (capsuleColliderComponent.Material)
|
||||||
|
{
|
||||||
out << YAML::Key << "Material" << YAML::Value << capsuleColliderComponent.Material->Handle;
|
out << YAML::Key << "Material" << YAML::Value << capsuleColliderComponent.Material->Handle;
|
||||||
|
out << YAML::Key << "MaterialPath" << YAML::Value << capsuleColliderComponent.Material->FilePath;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
out << YAML::Key << "Material" << YAML::Value << 0;
|
out << YAML::Key << "Material" << YAML::Value << 0;
|
||||||
|
out << YAML::Key << "MaterialPath" << YAML::Value << "";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
out << YAML::EndMap; // CapsuleColliderComponent
|
out << YAML::EndMap; // CapsuleColliderComponent
|
||||||
}
|
}
|
||||||
@ -565,19 +500,27 @@ namespace Prism
|
|||||||
out << YAML::Key << "MeshColliderComponent";
|
out << YAML::Key << "MeshColliderComponent";
|
||||||
out << YAML::BeginMap; // MeshColliderComponent
|
out << YAML::BeginMap; // MeshColliderComponent
|
||||||
|
|
||||||
auto meshColliderComponent = entity.GetComponent<MeshColliderComponent>();
|
const auto& meshColliderComponent = entity.GetComponent<MeshColliderComponent>();
|
||||||
|
if (meshColliderComponent.OverrideMesh && meshColliderComponent.CollisionMesh)
|
||||||
if (meshColliderComponent.OverrideMesh)
|
{
|
||||||
out << YAML::Key << "AssetID" << YAML::Value << meshColliderComponent.CollisionMesh->Handle;
|
out << YAML::Key << "AssetID" << YAML::Value << meshColliderComponent.CollisionMesh->Handle;
|
||||||
|
out << YAML::Key << "AssetPath" << YAML::Value << meshColliderComponent.CollisionMesh->FilePath;
|
||||||
|
}
|
||||||
|
|
||||||
out << YAML::Key << "IsConvex" << YAML::Value << meshColliderComponent.IsConvex;
|
out << YAML::Key << "IsConvex" << YAML::Value << meshColliderComponent.IsConvex;
|
||||||
out << YAML::Key << "IsTrigger" << YAML::Value << meshColliderComponent.IsTrigger;
|
out << YAML::Key << "IsTrigger" << YAML::Value << meshColliderComponent.IsTrigger;
|
||||||
out << YAML::Key << "OverrideMesh" << YAML::Value << meshColliderComponent.OverrideMesh;
|
out << YAML::Key << "OverrideMesh" << YAML::Value << meshColliderComponent.OverrideMesh;
|
||||||
|
|
||||||
if (meshColliderComponent.Material)
|
if (meshColliderComponent.Material)
|
||||||
|
{
|
||||||
out << YAML::Key << "Material" << YAML::Value << meshColliderComponent.Material->Handle;
|
out << YAML::Key << "Material" << YAML::Value << meshColliderComponent.Material->Handle;
|
||||||
|
out << YAML::Key << "MaterialPath" << YAML::Value << meshColliderComponent.Material->FilePath;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
out << YAML::Key << "Material" << YAML::Value << 0;
|
out << YAML::Key << "Material" << YAML::Value << 0;
|
||||||
|
out << YAML::Key << "MaterialPath" << YAML::Value << "";
|
||||||
|
}
|
||||||
|
|
||||||
out << YAML::EndMap; // MeshColliderComponent
|
out << YAML::EndMap; // MeshColliderComponent
|
||||||
}
|
}
|
||||||
@ -829,7 +772,7 @@ namespace Prism
|
|||||||
if (meshComponent["AssetPath"])
|
if (meshComponent["AssetPath"])
|
||||||
{
|
{
|
||||||
const std::string assetFilePath = meshComponent["AssetPath"].as<std::string>();
|
const std::string assetFilePath = meshComponent["AssetPath"].as<std::string>();
|
||||||
assetID = AssetsManager::GetAssetHandleFromFilePath(filepath);
|
assetID = AssetsManager::GetAssetHandleFromFilePath(assetFilePath);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -838,7 +781,46 @@ namespace Prism
|
|||||||
|
|
||||||
if (AssetsManager::IsAssetHandleValid(assetID) && !deserializedEntity.HasComponent<MeshComponent>())
|
if (AssetsManager::IsAssetHandleValid(assetID) && !deserializedEntity.HasComponent<MeshComponent>())
|
||||||
{
|
{
|
||||||
deserializedEntity.AddComponent<MeshComponent>(AssetsManager::GetAsset<Mesh>(assetID));
|
auto& mc = deserializedEntity.AddComponent<MeshComponent>(AssetsManager::GetAsset<Mesh>(assetID));
|
||||||
|
|
||||||
|
if (meshComponent["Materials"])
|
||||||
|
{
|
||||||
|
auto materialsNode = meshComponent["Materials"];
|
||||||
|
// 遍历 "Slot X" 键
|
||||||
|
for (auto it = materialsNode.begin(); it != materialsNode.end(); ++it)
|
||||||
|
{
|
||||||
|
std::string slotKey = it->first.as<std::string>();
|
||||||
|
if (slotKey.rfind("Slot ", 0) == 0) // 确保是 "Slot X"
|
||||||
|
{
|
||||||
|
int slotIndex = std::stoi(slotKey.substr(5));
|
||||||
|
auto slotNode = it->second;
|
||||||
|
|
||||||
|
// 获取材质资产的 Handle
|
||||||
|
UUID materialHandle = 0;
|
||||||
|
if (slotNode["AssetPath"])
|
||||||
|
{
|
||||||
|
std::string matPath = slotNode["AssetPath"].as<std::string>();
|
||||||
|
if (!matPath.empty())
|
||||||
|
materialHandle = AssetsManager::GetAssetHandleFromFilePath(matPath);
|
||||||
|
}
|
||||||
|
else if (slotNode["AssetHandle"])
|
||||||
|
{
|
||||||
|
materialHandle = slotNode["AssetHandle"].as<uint64_t>();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 调整 MaterialDescs 大小(确保索引有效)
|
||||||
|
if (slotIndex >= mc.MaterialDescs.size())
|
||||||
|
mc.MaterialDescs.resize(slotIndex + 1);
|
||||||
|
|
||||||
|
// 加载材质资产并赋值
|
||||||
|
if (materialHandle != 0 && AssetsManager::IsAssetHandleValid(materialHandle))
|
||||||
|
mc.MaterialDescs[slotIndex] = AssetsManager::GetAsset<PBRMaterialAsset>(materialHandle);
|
||||||
|
else
|
||||||
|
mc.MaterialDescs[slotIndex] = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mc.UpdateMaterials(-1, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -858,8 +840,8 @@ namespace Prism
|
|||||||
AssetHandle assetHandle;
|
AssetHandle assetHandle;
|
||||||
if (skyLightComponent["EnvironmentAssetPath"])
|
if (skyLightComponent["EnvironmentAssetPath"])
|
||||||
{
|
{
|
||||||
const auto filePath = skyLightComponent["EnvironmentAssetPath"].as<std::string>();
|
const auto assetFilePath = skyLightComponent["EnvironmentAssetPath"].as<std::string>();
|
||||||
assetHandle = AssetsManager::GetAssetHandleFromFilePath(filepath);
|
assetHandle = AssetsManager::GetAssetHandleFromFilePath(assetFilePath);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1054,10 +1036,18 @@ namespace Prism
|
|||||||
auto material = boxColliderComponent["Material"];
|
auto material = boxColliderComponent["Material"];
|
||||||
if (material && AssetsManager::IsAssetHandleValid(material.as<uint64_t>()))
|
if (material && AssetsManager::IsAssetHandleValid(material.as<uint64_t>()))
|
||||||
{
|
{
|
||||||
component.Material = AssetsManager::GetAsset<PhysicsMaterial>(material.as<uint64_t>());
|
component.Material = AssetsManager::GetAsset<PhysicsMaterialAsset>(material.as<uint64_t>());
|
||||||
|
}else
|
||||||
|
{
|
||||||
|
const auto materialPath = boxColliderComponent["MaterialPath"].as<std::string>();
|
||||||
|
if (const auto assetId = AssetsManager::GetAssetHandleFromFilePath(materialPath); assetId != 0)
|
||||||
|
{
|
||||||
|
component.Material = AssetsManager::GetAsset<PhysicsMaterialAsset>(assetId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
component.DebugMesh = MeshFactory::CreateBox(component.Size);
|
|
||||||
|
component.DebugMesh = MeshFactory::CreateBox(component.Size * 2.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (auto sphereColliderComponent = entity["SphereColliderComponent"])
|
if (auto sphereColliderComponent = entity["SphereColliderComponent"])
|
||||||
@ -1068,7 +1058,17 @@ namespace Prism
|
|||||||
|
|
||||||
auto material = sphereColliderComponent["Material"];
|
auto material = sphereColliderComponent["Material"];
|
||||||
if (material && AssetsManager::IsAssetHandleValid(material.as<uint64_t>()))
|
if (material && AssetsManager::IsAssetHandleValid(material.as<uint64_t>()))
|
||||||
component.Material = AssetsManager::GetAsset<PhysicsMaterial>(material.as<uint64_t>());
|
{
|
||||||
|
component.Material = AssetsManager::GetAsset<PhysicsMaterialAsset>(material.as<uint64_t>());
|
||||||
|
}else
|
||||||
|
{
|
||||||
|
const auto materialPath = sphereColliderComponent["MaterialPath"].as<std::string>();
|
||||||
|
if (const auto assetId = AssetsManager::GetAssetHandleFromFilePath(materialPath); assetId != 0)
|
||||||
|
{
|
||||||
|
component.Material = AssetsManager::GetAsset<PhysicsMaterialAsset>(assetId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
component.DebugMesh = MeshFactory::CreateSphere(component.Radius);
|
component.DebugMesh = MeshFactory::CreateSphere(component.Radius);
|
||||||
}
|
}
|
||||||
@ -1082,7 +1082,16 @@ namespace Prism
|
|||||||
|
|
||||||
auto material = capsuleColliderComponent["Material"];
|
auto material = capsuleColliderComponent["Material"];
|
||||||
if (material && AssetsManager::IsAssetHandleValid(material.as<uint64_t>()))
|
if (material && AssetsManager::IsAssetHandleValid(material.as<uint64_t>()))
|
||||||
component.Material = AssetsManager::GetAsset<PhysicsMaterial>(material.as<uint64_t>());
|
{
|
||||||
|
component.Material = AssetsManager::GetAsset<PhysicsMaterialAsset>(material.as<uint64_t>());
|
||||||
|
}else
|
||||||
|
{
|
||||||
|
const auto materialPath = capsuleColliderComponent["MaterialPath"].as<std::string>();
|
||||||
|
if (const auto assetId = AssetsManager::GetAssetHandleFromFilePath(materialPath); assetId != 0)
|
||||||
|
{
|
||||||
|
component.Material = AssetsManager::GetAsset<PhysicsMaterialAsset>(assetId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
component.DebugMesh = MeshFactory::CreateCapsule(component.Radius, component.Height);
|
component.DebugMesh = MeshFactory::CreateCapsule(component.Radius, component.Height);
|
||||||
}
|
}
|
||||||
@ -1095,14 +1104,14 @@ namespace Prism
|
|||||||
if (overrideMesh)
|
if (overrideMesh)
|
||||||
{
|
{
|
||||||
UUID assetID;
|
UUID assetID;
|
||||||
if (meshComponent["AssetPath"])
|
if (meshColliderComponent["AssetPath"])
|
||||||
{
|
{
|
||||||
const auto assetFilePath = meshComponent["AssetPath"].as<std::string>();
|
const auto assetFilePath = meshColliderComponent["AssetPath"].as<std::string>();
|
||||||
assetID = AssetsManager::GetAssetHandleFromFilePath(filepath);
|
assetID = AssetsManager::GetAssetHandleFromFilePath(assetFilePath);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
assetID = meshComponent["AssetID"].as<uint64_t>();
|
assetID = meshColliderComponent["AssetID"].as<uint64_t>();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (AssetsManager::IsAssetHandleValid(assetID))
|
if (AssetsManager::IsAssetHandleValid(assetID))
|
||||||
@ -1116,16 +1125,33 @@ namespace Prism
|
|||||||
component.IsTrigger = meshColliderComponent["IsTrigger"] ? meshColliderComponent["IsTrigger"].as<bool>() : false;
|
component.IsTrigger = meshColliderComponent["IsTrigger"] ? meshColliderComponent["IsTrigger"].as<bool>() : false;
|
||||||
component.OverrideMesh = overrideMesh;
|
component.OverrideMesh = overrideMesh;
|
||||||
|
|
||||||
auto material = meshColliderComponent["Material"];
|
if (meshColliderComponent["Material"])
|
||||||
if (material && AssetsManager::IsAssetHandleValid(material.as<uint64_t>()))
|
|
||||||
{
|
{
|
||||||
component.Material = AssetsManager::GetAsset<PhysicsMaterial>(material.as<uint64_t>());
|
auto material = meshColliderComponent["Material"];
|
||||||
|
if (material && AssetsManager::IsAssetHandleValid(material.as<uint64_t>()))
|
||||||
|
{
|
||||||
|
component.Material = AssetsManager::GetAsset<PhysicsMaterialAsset>(material.as<uint64_t>());
|
||||||
|
|
||||||
if (component.IsConvex)
|
if (component.IsConvex)
|
||||||
PhysicsWrappers::CreateConvexMesh(component, deserializedEntity.Transform().Scale);
|
PhysicsWrappers::CreateConvexMesh(component, deserializedEntity.Transform().Scale);
|
||||||
else
|
else
|
||||||
PhysicsWrappers::CreateTriangleMesh(component, deserializedEntity.Transform().Scale);
|
PhysicsWrappers::CreateTriangleMesh(component, deserializedEntity.Transform().Scale);
|
||||||
|
}else
|
||||||
|
{
|
||||||
|
const auto materialPath = meshColliderComponent["MaterialPath"].as<std::string>();
|
||||||
|
if (const auto assetId = AssetsManager::GetAssetHandleFromFilePath(materialPath); assetId != 0)
|
||||||
|
{
|
||||||
|
component.Material = AssetsManager::GetAsset<PhysicsMaterialAsset>(assetId);
|
||||||
|
|
||||||
|
if (component.IsConvex)
|
||||||
|
PhysicsWrappers::CreateConvexMesh(component, deserializedEntity.Transform().Scale);
|
||||||
|
else
|
||||||
|
PhysicsWrappers::CreateTriangleMesh(component, deserializedEntity.Transform().Scale);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1139,7 +1165,7 @@ namespace Prism
|
|||||||
if (physicsMaterialComponent)
|
if (physicsMaterialComponent)
|
||||||
{
|
{
|
||||||
//auto& component = deserializedEntity.AddComponent<PhysicsMaterialComponent>();
|
//auto& component = deserializedEntity.AddComponent<PhysicsMaterialComponent>();
|
||||||
Ref<PhysicsMaterial> material = Ref<PhysicsMaterial>::Create();
|
Ref<PhysicsMaterialAsset> material = Ref<PhysicsMaterialAsset>::Create();
|
||||||
material->StaticFriction = physicsMaterialComponent["StaticFriction"].as<float>();
|
material->StaticFriction = physicsMaterialComponent["StaticFriction"].as<float>();
|
||||||
material->DynamicFriction = physicsMaterialComponent["DynamicFriction"].as<float>();
|
material->DynamicFriction = physicsMaterialComponent["DynamicFriction"].as<float>();
|
||||||
material->Bounciness = physicsMaterialComponent["Bounciness"].as<float>();
|
material->Bounciness = physicsMaterialComponent["Bounciness"].as<float>();
|
||||||
|
|||||||
@ -3,6 +3,7 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
#include "ScriptEngine.h"
|
#include "ScriptEngine.h"
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
|
||||||
@ -35,6 +36,10 @@ namespace Prism
|
|||||||
MonoImage* s_AppAssemblyImage = nullptr;
|
MonoImage* s_AppAssemblyImage = nullptr;
|
||||||
MonoImage* s_CoreAssemblyImage = nullptr;
|
MonoImage* s_CoreAssemblyImage = nullptr;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
std::vector<std::string> ScriptEngine::s_AvailableScripts;
|
||||||
|
|
||||||
#ifdef ENABLE_MONO_DEBUG
|
#ifdef ENABLE_MONO_DEBUG
|
||||||
static bool s_EnableMonoPDBDebug = true;
|
static bool s_EnableMonoPDBDebug = true;
|
||||||
#else
|
#else
|
||||||
@ -87,6 +92,7 @@ namespace Prism
|
|||||||
static std::unordered_map<std::string, EntityScriptClass> s_EntityClassMap;
|
static std::unordered_map<std::string, EntityScriptClass> s_EntityClassMap;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
MonoAssembly* LoadAssemblyFromFile(const char* filepath)
|
MonoAssembly* LoadAssemblyFromFile(const char* filepath)
|
||||||
{
|
{
|
||||||
if (!filepath) {
|
if (!filepath) {
|
||||||
@ -390,6 +396,12 @@ namespace Prism
|
|||||||
|
|
||||||
void ScriptEngine::Init(const std::string& assemblyPath)
|
void ScriptEngine::Init(const std::string& assemblyPath)
|
||||||
{
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
_putenv("DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1");
|
||||||
|
#else
|
||||||
|
setenv("DOTNET_SYSTEM_GLOBALIZATION_INVARIANT", "1", 1);
|
||||||
|
#endif
|
||||||
|
|
||||||
s_AssemblyPath = assemblyPath;
|
s_AssemblyPath = assemblyPath;
|
||||||
|
|
||||||
InitMono();
|
InitMono();
|
||||||
@ -429,8 +441,8 @@ namespace Prism
|
|||||||
s_CoreAssembly = LoadAssembly("assets/scripts/Prism-ScriptCore.dll");
|
s_CoreAssembly = LoadAssembly("assets/scripts/Prism-ScriptCore.dll");
|
||||||
s_CoreAssemblyImage = GetAssemblyImage(s_CoreAssembly);
|
s_CoreAssemblyImage = GetAssemblyImage(s_CoreAssembly);
|
||||||
|
|
||||||
auto appAssembly = LoadAssembly(path);
|
const auto appAssembly = LoadAssembly(path);
|
||||||
auto appAssemblyImage = GetAssemblyImage(appAssembly);
|
const auto appAssemblyImage = GetAssemblyImage(appAssembly);
|
||||||
ScriptEngineRegistry::RegisterAll();
|
ScriptEngineRegistry::RegisterAll();
|
||||||
|
|
||||||
if (cleanup)
|
if (cleanup)
|
||||||
@ -441,6 +453,8 @@ namespace Prism
|
|||||||
|
|
||||||
s_AppAssembly = appAssembly;
|
s_AppAssembly = appAssembly;
|
||||||
s_AppAssemblyImage = appAssemblyImage;
|
s_AppAssemblyImage = appAssemblyImage;
|
||||||
|
|
||||||
|
RefreshAvailableScripts();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScriptEngine::ReloadAssembly(const std::string& path)
|
void ScriptEngine::ReloadAssembly(const std::string& path)
|
||||||
@ -845,6 +859,43 @@ namespace Prism
|
|||||||
return entityIDMap.at(entityID);
|
return entityIDMap.at(entityID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ScriptEngine::RefreshAvailableScripts()
|
||||||
|
{
|
||||||
|
if (!s_AppAssemblyImage) return;
|
||||||
|
s_AvailableScripts.clear();
|
||||||
|
|
||||||
|
// 获取类型定义表
|
||||||
|
const MonoTableInfo *tableInfo = mono_image_get_table_info(s_AppAssemblyImage, MONO_TABLE_TYPEDEF);
|
||||||
|
int rows = mono_image_get_table_rows(s_AppAssemblyImage, MONO_TABLE_TYPEDEF);
|
||||||
|
|
||||||
|
for (int i = 0; i < rows; i++)
|
||||||
|
{
|
||||||
|
uint32_t cols[MONO_TYPEDEF_SIZE];
|
||||||
|
mono_metadata_decode_row(tableInfo, i, cols, MONO_TYPEDEF_SIZE);
|
||||||
|
|
||||||
|
// 获取类名和命名空间
|
||||||
|
const char* name = mono_metadata_string_heap(s_AppAssemblyImage, cols[MONO_TYPEDEF_NAME]);
|
||||||
|
const char* nameSpace = mono_metadata_string_heap(s_AppAssemblyImage, cols[MONO_TYPEDEF_NAMESPACE]);
|
||||||
|
|
||||||
|
if (!name || strlen(name) == 0) continue;
|
||||||
|
|
||||||
|
// 构建全名
|
||||||
|
std::string fullName;
|
||||||
|
if (nameSpace && strlen(nameSpace) > 0)
|
||||||
|
fullName = std::string(nameSpace) + "." + name;
|
||||||
|
else
|
||||||
|
fullName = name;
|
||||||
|
|
||||||
|
s_AvailableScripts.push_back(fullName);
|
||||||
|
PM_CORE_DEBUG("Script Class: {}", fullName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<std::string>& ScriptEngine::GetAvailableScripts()
|
||||||
|
{
|
||||||
|
return s_AvailableScripts;
|
||||||
|
}
|
||||||
|
|
||||||
void ScriptEngine::OnImGuiRender()
|
void ScriptEngine::OnImGuiRender()
|
||||||
{
|
{
|
||||||
ImGui::Begin("Script Engine Debug");
|
ImGui::Begin("Script Engine Debug");
|
||||||
|
|||||||
@ -150,8 +150,15 @@ namespace Prism
|
|||||||
static EntityInstanceMap& GetEntityInstanceMap();
|
static EntityInstanceMap& GetEntityInstanceMap();
|
||||||
static EntityInstanceData& GetEntityInstanceData(UUID sceneID, UUID entityID);
|
static EntityInstanceData& GetEntityInstanceData(UUID sceneID, UUID entityID);
|
||||||
|
|
||||||
|
// GetAll Script Clas s
|
||||||
|
static const std::vector<std::string>& GetAvailableScripts();
|
||||||
|
static void RefreshAvailableScripts();
|
||||||
|
|
||||||
// Debug
|
// Debug
|
||||||
static void OnImGuiRender();
|
static void OnImGuiRender();
|
||||||
|
|
||||||
|
private:
|
||||||
|
static std::vector<std::string> s_AvailableScripts;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -49,6 +49,8 @@ namespace Prism
|
|||||||
{
|
{
|
||||||
InitComponentTypes();
|
InitComponentTypes();
|
||||||
|
|
||||||
|
mono_add_internal_call("Prism.Debug::Log_Native", (const void*)Prism::Script::Prism_Log_Native);
|
||||||
|
|
||||||
mono_add_internal_call("Prism.Noise::PerlinNoise_Native", (const void*)Prism::Script::Prism_Noise_PerlinNoise);
|
mono_add_internal_call("Prism.Noise::PerlinNoise_Native", (const void*)Prism::Script::Prism_Noise_PerlinNoise);
|
||||||
|
|
||||||
mono_add_internal_call("Prism.Physics::Raycast_Native", (const void*)Prism::Script::Prism_Physics_Raycast);
|
mono_add_internal_call("Prism.Physics::Raycast_Native", (const void*)Prism::Script::Prism_Physics_Raycast);
|
||||||
|
|||||||
@ -10,6 +10,7 @@
|
|||||||
#include <mono/metadata/object.h>
|
#include <mono/metadata/object.h>
|
||||||
#include <mono/metadata/reflection.h>
|
#include <mono/metadata/reflection.h>
|
||||||
#include <mono/metadata/appdomain.h>
|
#include <mono/metadata/appdomain.h>
|
||||||
|
#include <mono/utils/mono-publib.h>
|
||||||
|
|
||||||
#include "Prism/Core/Input.h"
|
#include "Prism/Core/Input.h"
|
||||||
#include "Prism/Core/Math/Noise.h"
|
#include "Prism/Core/Math/Noise.h"
|
||||||
@ -32,6 +33,31 @@ namespace Prism { namespace Script {
|
|||||||
SpriteRenderer = 4
|
SpriteRenderer = 4
|
||||||
};
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////
|
||||||
|
// Debug ////////////////////////////////////////////////////////
|
||||||
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
static LogCallback s_LogCallback = nullptr;
|
||||||
|
|
||||||
|
void SetLogCallback(const LogCallback& callback)
|
||||||
|
{
|
||||||
|
s_LogCallback = callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Prism_Log_Native(MonoString* message)
|
||||||
|
{
|
||||||
|
if (message)
|
||||||
|
{
|
||||||
|
if (char* utf8 = mono_string_to_utf8(message))
|
||||||
|
{
|
||||||
|
PM_CLIENT_INFO("[c#]: {}", utf8);
|
||||||
|
if (s_LogCallback) s_LogCallback(utf8);
|
||||||
|
mono_free(utf8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////
|
||||||
// Math ////////////////////////////////////////////////////////
|
// Math ////////////////////////////////////////////////////////
|
||||||
////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////
|
||||||
@ -385,7 +411,8 @@ namespace Prism { namespace Script {
|
|||||||
|
|
||||||
Entity entity = entityMap.at(entityID);
|
Entity entity = entityMap.at(entityID);
|
||||||
|
|
||||||
auto& transform = entity.GetComponent<TransformComponent>() = *inTransform;
|
auto& transform = entity.GetComponent<TransformComponent>();
|
||||||
|
transform = *inTransform;
|
||||||
transform.Rotation = glm::radians(transform.Rotation);
|
transform.Rotation = glm::radians(transform.Rotation);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -454,7 +481,13 @@ namespace Prism { namespace Script {
|
|||||||
PM_CORE_ASSERT(entityMap.find(entityID) != entityMap.end(), "Invalid entity ID or entity doesn't exist in scene!");
|
PM_CORE_ASSERT(entityMap.find(entityID) != entityMap.end(), "Invalid entity ID or entity doesn't exist in scene!");
|
||||||
|
|
||||||
Entity entity = entityMap.at(entityID);
|
Entity entity = entityMap.at(entityID);
|
||||||
entity.GetComponent<TransformComponent>().Rotation = glm::radians(*inRotation);
|
auto& transformComponent = entity.GetComponent<TransformComponent>();
|
||||||
|
transformComponent.Rotation = glm::radians(*inRotation);
|
||||||
|
|
||||||
|
const auto rotationQuat = glm::quat(transformComponent.Rotation);
|
||||||
|
transformComponent.Up = glm::normalize(glm::rotate(rotationQuat, glm::vec3(0.0f, 1.0f, 0.0f)));
|
||||||
|
transformComponent.Right = glm::normalize(glm::rotate(rotationQuat, glm::vec3(1.0f, 0.0f, 0.0f)));
|
||||||
|
transformComponent.Forward = glm::normalize(glm::rotate(rotationQuat, glm::vec3(0.0f, 0.0f, -1.0f)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Prism_TransformComponent_GetScale(uint64_t entityID, glm::vec3* outScale)
|
void Prism_TransformComponent_GetScale(uint64_t entityID, glm::vec3* outScale)
|
||||||
|
|||||||
@ -14,7 +14,11 @@ extern "C" {
|
|||||||
typedef struct _MonoArray MonoArray;
|
typedef struct _MonoArray MonoArray;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Prism { namespace Script {
|
namespace Prism::Script
|
||||||
|
{
|
||||||
|
|
||||||
|
using LogCallback = std::function<void(const char*)>;
|
||||||
|
void SetLogCallback(const LogCallback& callback);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
struct ScriptTransform
|
struct ScriptTransform
|
||||||
@ -26,6 +30,9 @@ namespace Prism { namespace Script {
|
|||||||
};
|
};
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// Debug
|
||||||
|
void Prism_Log_Native(MonoString* message);
|
||||||
|
|
||||||
// Math
|
// Math
|
||||||
float Prism_Noise_PerlinNoise(float x, float y);
|
float Prism_Noise_PerlinNoise(float x, float y);
|
||||||
|
|
||||||
@ -114,7 +121,7 @@ namespace Prism { namespace Script {
|
|||||||
|
|
||||||
void* Prism_MeshComponent_GetMesh(uint64_t entityID);
|
void* Prism_MeshComponent_GetMesh(uint64_t entityID);
|
||||||
void Prism_MeshComponent_SetMesh(uint64_t entityID, const Ref<Mesh>* inMesh);
|
void Prism_MeshComponent_SetMesh(uint64_t entityID, const Ref<Mesh>* inMesh);
|
||||||
} }
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif //SCRIPTWRAPPERS_H
|
#endif //SCRIPTWRAPPERS_H
|
||||||
|
|||||||
@ -38,6 +38,8 @@ namespace Prism
|
|||||||
static std::string OpenFileSelector(const std::string& filter = "");
|
static std::string OpenFileSelector(const std::string& filter = "");
|
||||||
static std::string SaveFileSelector(const std::string& filter = "");
|
static std::string SaveFileSelector(const std::string& filter = "");
|
||||||
|
|
||||||
|
static void OpenInExplorer(const std::string& path);
|
||||||
|
|
||||||
static bool CreateFolder(const std::filesystem::path& filepath);
|
static bool CreateFolder(const std::filesystem::path& filepath);
|
||||||
static bool Exists(const std::string& filepath);
|
static bool Exists(const std::string& filepath);
|
||||||
static std::string Rename(const std::string& filepath, const std::string& newName);
|
static std::string Rename(const std::string& filepath, const std::string& newName);
|
||||||
|
|||||||
145
Prism/src/Prism/Utilities/SerializeUtils.h
Normal file
145
Prism/src/Prism/Utilities/SerializeUtils.h
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
//
|
||||||
|
// Created by Atdunbg on 2026/3/25.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef PRISM_SERIALIZEUTILS_H
|
||||||
|
#define PRISM_SERIALIZEUTILS_H
|
||||||
|
|
||||||
|
#include <yaml-cpp/yaml.h>
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
|
namespace YAML
|
||||||
|
{
|
||||||
|
template<>
|
||||||
|
struct convert<glm::vec2>
|
||||||
|
{
|
||||||
|
static Node encode(const glm::vec2& rhs)
|
||||||
|
{
|
||||||
|
Node node;
|
||||||
|
node.push_back(rhs.x);
|
||||||
|
node.push_back(rhs.y);
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool decode(const Node& node, glm::vec2& rhs)
|
||||||
|
{
|
||||||
|
if (!node.IsSequence() || node.size() != 2)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
rhs.x = node[0].as<float>();
|
||||||
|
rhs.y = node[1].as<float>();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct convert<glm::vec3>
|
||||||
|
{
|
||||||
|
static Node encode(const glm::vec3& rhs)
|
||||||
|
{
|
||||||
|
Node node;
|
||||||
|
node.push_back(rhs.x);
|
||||||
|
node.push_back(rhs.y);
|
||||||
|
node.push_back(rhs.z);
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool decode(const Node& node, glm::vec3& rhs)
|
||||||
|
{
|
||||||
|
if (!node.IsSequence() || node.size() != 3)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
rhs.x = node[0].as<float>();
|
||||||
|
rhs.y = node[1].as<float>();
|
||||||
|
rhs.z = node[2].as<float>();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct convert<glm::vec4>
|
||||||
|
{
|
||||||
|
static Node encode(const glm::vec4& rhs)
|
||||||
|
{
|
||||||
|
Node node;
|
||||||
|
node.push_back(rhs.x);
|
||||||
|
node.push_back(rhs.y);
|
||||||
|
node.push_back(rhs.z);
|
||||||
|
node.push_back(rhs.w);
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool decode(const Node& node, glm::vec4& rhs)
|
||||||
|
{
|
||||||
|
if (!node.IsSequence() || node.size() != 4)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
rhs.x = node[0].as<float>();
|
||||||
|
rhs.y = node[1].as<float>();
|
||||||
|
rhs.z = node[2].as<float>();
|
||||||
|
rhs.w = node[3].as<float>();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct convert<glm::quat>
|
||||||
|
{
|
||||||
|
static Node encode(const glm::quat& rhs)
|
||||||
|
{
|
||||||
|
Node node;
|
||||||
|
node.push_back(rhs.w);
|
||||||
|
node.push_back(rhs.x);
|
||||||
|
node.push_back(rhs.y);
|
||||||
|
node.push_back(rhs.z);
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool decode(const Node& node, glm::quat& rhs)
|
||||||
|
{
|
||||||
|
if (!node.IsSequence() || node.size() != 4)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
rhs.w = node[0].as<float>();
|
||||||
|
rhs.x = node[1].as<float>();
|
||||||
|
rhs.y = node[2].as<float>();
|
||||||
|
rhs.z = node[3].as<float>();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Prism
|
||||||
|
{
|
||||||
|
inline YAML::Emitter& operator<<(YAML::Emitter& out, const glm::vec2& v)
|
||||||
|
{
|
||||||
|
out << YAML::Flow;
|
||||||
|
out << YAML::BeginSeq << v.x << v.y << YAML::EndSeq;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline YAML::Emitter& operator<<(YAML::Emitter& out, const glm::vec3& v)
|
||||||
|
{
|
||||||
|
out << YAML::Flow;
|
||||||
|
out << YAML::BeginSeq << v.x << v.y << v.z << YAML::EndSeq;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline YAML::Emitter& operator<<(YAML::Emitter& out, const glm::vec4& v)
|
||||||
|
{
|
||||||
|
out << YAML::Flow;
|
||||||
|
out << YAML::BeginSeq << v.x << v.y << v.z << v.w << YAML::EndSeq;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline YAML::Emitter& operator<<(YAML::Emitter& out, const glm::quat& v)
|
||||||
|
{
|
||||||
|
out << YAML::Flow;
|
||||||
|
out << YAML::BeginSeq << v.w << v.x << v.y << v.z << YAML::EndSeq;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif //PRISM_SERIALIZEUTILS_H
|
||||||
@ -4,6 +4,8 @@
|
|||||||
|
|
||||||
#include "StringUtils.h"
|
#include "StringUtils.h"
|
||||||
|
|
||||||
|
#include <filesystem>
|
||||||
|
|
||||||
namespace Prism::Utils
|
namespace Prism::Utils
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -17,10 +19,16 @@ namespace Prism::Utils
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string ReplaceFilePathName(const std::string& filepath, const std::string& newName)
|
||||||
|
{
|
||||||
|
const std::string extension = GetExtension(filepath, true);
|
||||||
|
return std::filesystem::path(filepath).parent_path().string() + "/" + newName + extension;
|
||||||
|
}
|
||||||
|
|
||||||
std::string GetExtension(const std::string& filename, const bool includeDot)
|
std::string GetExtension(const std::string& filename, const bool includeDot)
|
||||||
{
|
{
|
||||||
if (const std::vector<std::string> parts = SplitString(filename, '.'); parts.size() > 1)
|
if (const std::vector<std::string> parts = SplitString(filename, '.'); parts.size() > 1)
|
||||||
return parts[ includeDot ? parts.size() - 1 : parts.size()];
|
return (includeDot ? "." : "") + parts[parts.size() - 1];
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -9,8 +9,10 @@
|
|||||||
|
|
||||||
namespace Prism::Utils
|
namespace Prism::Utils
|
||||||
{
|
{
|
||||||
|
std::string ReplaceFilePathName(const std::string& filepath, const std::string& newName);
|
||||||
|
|
||||||
std::string GetFilename(const std::string& filepath);
|
std::string GetFilename(const std::string& filepath);
|
||||||
std::string GetExtension(const std::string& filename, bool includeDot = true);
|
std::string GetExtension(const std::string& filename, bool includeDot = false);
|
||||||
std::string RemoveExtension(const std::string& filename);
|
std::string RemoveExtension(const std::string& filename);
|
||||||
std::string NormalizePath(std::string path);
|
std::string NormalizePath(std::string path);
|
||||||
std::string StringToLower(const std::string& str);
|
std::string StringToLower(const std::string& str);
|
||||||
|
|||||||
11
PrismRuntime/CMakeLists.txt
Normal file
11
PrismRuntime/CMakeLists.txt
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
project(PrismRuntime)
|
||||||
|
|
||||||
|
file(GLOB_RECURSE SRC_SOURCE ./PrismRuntime/**.cpp)
|
||||||
|
|
||||||
|
add_executable(${PROJECT_NAME} WIN32 ${SRC_SOURCE})
|
||||||
|
target_compile_definitions(${PROJECT_NAME} PRIVATE PRISM_GUI)
|
||||||
|
target_link_libraries(${PROJECT_NAME} PRIVATE Prism-Runtime)
|
||||||
|
|
||||||
|
|
||||||
|
add_executable(${PROJECT_NAME}-Console ${SRC_SOURCE})
|
||||||
|
target_link_libraries(${PROJECT_NAME}-Console PRIVATE Prism-Runtime)
|
||||||
90
PrismRuntime/PrismRuntime/PrismRuntime.cpp
Normal file
90
PrismRuntime/PrismRuntime/PrismRuntime.cpp
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
//
|
||||||
|
// Created by Atdunbg on 2026/3/23.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "PrismRuntime.h"
|
||||||
|
|
||||||
|
#include "Prism/Core/Input.h"
|
||||||
|
#include "Prism/Renderer/Renderer.h"
|
||||||
|
#include "Prism/Renderer/SceneRenderer.h"
|
||||||
|
#include "Prism/Scene/SceneSerializer.h"
|
||||||
|
|
||||||
|
|
||||||
|
void PrismRuntime::OnAttach()
|
||||||
|
{
|
||||||
|
PM_CLIENT_INFO("App init");
|
||||||
|
|
||||||
|
AppInstance = &Prism::Application::Get();
|
||||||
|
|
||||||
|
sceneName.emplace_back("assets/scenes/FPS.scene");
|
||||||
|
sceneName.emplace_back("assets/scenes/FPSdemo.scene");
|
||||||
|
|
||||||
|
LoadScene(sceneName[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrismRuntime::OnDetach()
|
||||||
|
{
|
||||||
|
PM_CLIENT_INFO("Scene Shutdown");
|
||||||
|
m_CurrentScene->OnShutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrismRuntime::LoadScene(const std::string& scene)
|
||||||
|
{
|
||||||
|
if (m_CurrentScene)
|
||||||
|
{
|
||||||
|
PM_CLIENT_INFO("Scene Shutdown");
|
||||||
|
m_CurrentScene->OnShutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
const Prism::Ref<Prism::Scene> newScene = Prism::Ref<Prism::Scene>::Create("runtime Scene", false, true);
|
||||||
|
Prism::SceneSerializer serializer(newScene);
|
||||||
|
|
||||||
|
PM_CLIENT_INFO("loading Scene: ", scene);
|
||||||
|
serializer.Deserialize(scene);
|
||||||
|
|
||||||
|
m_CurrentScene = newScene;
|
||||||
|
|
||||||
|
const glm::ivec2 windowSize = AppInstance->GetWindow().GetSize();
|
||||||
|
if (m_CurrentScene && windowSize.x > 0 && windowSize.y > 0)
|
||||||
|
{
|
||||||
|
Prism::SceneRenderer::SetViewportSize(windowSize.x, windowSize.y);
|
||||||
|
m_CurrentScene->SetViewportSize(windowSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_CurrentScene->OnRuntimeStart();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrismRuntime::OnUpdate(const Prism::TimeStep deltaTime)
|
||||||
|
{
|
||||||
|
m_CurrentScene->OnUpdate(deltaTime);
|
||||||
|
m_CurrentScene->OnRenderRuntime(deltaTime);
|
||||||
|
|
||||||
|
const glm::vec2 windowSize = AppInstance->GetWindow().GetSize();
|
||||||
|
if (m_CurrentScene && windowSize.x > 0 && windowSize.y > 0)
|
||||||
|
{
|
||||||
|
m_CurrentScene->SetViewportSize(windowSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shouldChangeScene)
|
||||||
|
{
|
||||||
|
LoadScene(sceneName[nextScene]);
|
||||||
|
shouldChangeScene = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrismRuntime::OnEvent(Prism::Event& e)
|
||||||
|
{
|
||||||
|
if (Prism::Input::IsKeyPressed(Prism::KeyCode::L) && nextScene == 0)
|
||||||
|
{
|
||||||
|
shouldChangeScene = true;
|
||||||
|
nextScene++;
|
||||||
|
} else if (Prism::Input::IsKeyPressed(Prism::KeyCode::K) && nextScene == 1)
|
||||||
|
{
|
||||||
|
shouldChangeScene = true;
|
||||||
|
nextScene--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrismRuntime::OnImGuiRender()
|
||||||
|
{
|
||||||
|
}
|
||||||
38
PrismRuntime/PrismRuntime/PrismRuntime.h
Normal file
38
PrismRuntime/PrismRuntime/PrismRuntime.h
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
//
|
||||||
|
// Created by Atdunbg on 2026/3/23.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef PRISM_PRISMRUNTIME_H
|
||||||
|
#define PRISM_PRISMRUNTIME_H
|
||||||
|
#include "Prism/Core/Application.h"
|
||||||
|
#include "Prism/Core/Layer.h"
|
||||||
|
#include "Prism/Scene/Scene.h"
|
||||||
|
|
||||||
|
|
||||||
|
class PrismRuntime : public Prism::Layer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void OnAttach() override;
|
||||||
|
void OnDetach() override;
|
||||||
|
|
||||||
|
void LoadScene(const std::string& scene);
|
||||||
|
|
||||||
|
void OnUpdate(Prism::TimeStep deltaTime) override;
|
||||||
|
void OnEvent(Prism::Event& e) override;
|
||||||
|
void OnImGuiRender() override;
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
Prism::Ref<Prism::Scene> m_CurrentScene;
|
||||||
|
|
||||||
|
Prism::Application* AppInstance = nullptr;
|
||||||
|
|
||||||
|
bool shouldChangeScene = false;
|
||||||
|
|
||||||
|
// debug
|
||||||
|
std::vector<std::string> sceneName;
|
||||||
|
int nextScene = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif //PRISM_PRISMRUNTIME_H
|
||||||
25
PrismRuntime/PrismRuntime/PrismRuntimeApp.cpp
Normal file
25
PrismRuntime/PrismRuntime/PrismRuntimeApp.cpp
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
//
|
||||||
|
// Created by Atdunbg on 2026/3/23.
|
||||||
|
//
|
||||||
|
#include "Prism.h"
|
||||||
|
#include "PrismRuntime.h"
|
||||||
|
#include "Prism/Core/EntryPoint.h"
|
||||||
|
|
||||||
|
class PrismRuntimeApp : public Prism::Application
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit PrismRuntimeApp(const Prism::ApplicationProps& props)
|
||||||
|
: Application(props)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void OnInit() override
|
||||||
|
{
|
||||||
|
PushLayer(new PrismRuntime());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Prism::Application* Prism::CreateApplication(const CommandArgs args)
|
||||||
|
{
|
||||||
|
return new PrismRuntimeApp({"Game", 1920, 1080, args});
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user