Compare commits
15 Commits
mono-PhysX
...
forward-re
| Author | SHA1 | Date | |
|---|---|---|---|
| 76ebcc8f66 | |||
| f50824bdb1 | |||
| d11f8bb0c9 | |||
| 79707b77f5 | |||
| 971f16d526 | |||
| 5058d6a3a9 | |||
| f53d9134aa | |||
| 1b5fa1002d | |||
| d6d735900a | |||
| 230957f728 | |||
| 3c64abd77e | |||
| 1f4d7eff71 | |||
| b4d9dee045 | |||
| 4266a0b570 | |||
| ef4ea45edc |
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -35,3 +35,6 @@
|
||||
[submodule "Prism/vendor/efsw"]
|
||||
path = Prism/vendor/efsw
|
||||
url = https://github.com/SpartanJ/efsw
|
||||
[submodule "Prism/vendor/imgui-node-editor"]
|
||||
path = Prism/vendor/imgui-node-editor
|
||||
url = https://github.com/thedmd/imgui-node-editor.git
|
||||
|
||||
@ -24,3 +24,4 @@ endif ()
|
||||
add_subdirectory(Prism)
|
||||
add_subdirectory(Sandbox)
|
||||
add_subdirectory(Editor)
|
||||
add_subdirectory(PrismRuntime)
|
||||
|
||||
@ -12,7 +12,7 @@ file(COPY ${IMGUI_INI} DESTINATION ${CMAKE_BINARY_DIR})
|
||||
file(GLOB DOTNET_LIBRARY library)
|
||||
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})
|
||||
|
||||
|
||||
@ -15,10 +15,14 @@
|
||||
#include "Prism/Core/Input.h"
|
||||
#include "Prism/Core/Math/Math.h"
|
||||
#include "Prism/Editor/AssetEditorPanel.h"
|
||||
#include "Prism/Editor/DefaultAssetEditors/PBRMaterialAssetEditor.h"
|
||||
#include "Prism/Editor/PhysicsSettingsWindow.h"
|
||||
#include "Prism/Asset/AssetsManager.h"
|
||||
#include "Prism/Physics/Physics3D.h"
|
||||
#include "Prism/Renderer/Renderer2D.h"
|
||||
#include "Prism/Renderer/Renderer3D.h"
|
||||
#include "Prism/Script/ScriptEngine.h"
|
||||
#include "Prism/Script/ScriptWrappers.h"
|
||||
|
||||
namespace Prism
|
||||
{
|
||||
@ -51,8 +55,18 @@ namespace Prism
|
||||
NewScene();
|
||||
m_CurrentScene = m_EditorScene;
|
||||
|
||||
SceneRenderer::GetOptions().ShowGrid = true;
|
||||
|
||||
AssetEditorPanel::RegisterDefaultEditors();
|
||||
PBRMaterialEditor::InitPreviewRenderer();
|
||||
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()
|
||||
@ -63,6 +77,8 @@ namespace Prism
|
||||
|
||||
void EditorLayer::OnUpdate(const TimeStep deltaTime)
|
||||
{
|
||||
FileSystem::ProcessPendingEvents();
|
||||
|
||||
auto [x, y] = GetMouseViewportSpace();
|
||||
|
||||
SceneRenderer::SetFocusPoint({ x * 0.5f + 0.5f, y * 0.5f + 0.5f });
|
||||
@ -105,7 +121,7 @@ namespace Prism
|
||||
Renderer::BeginRenderPass(SceneRenderer::GetFinalRenderPass(), false);
|
||||
const auto viewProj = m_EditorCamera.GetViewProjection();
|
||||
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();
|
||||
Renderer::EndRenderPass();
|
||||
}
|
||||
@ -117,7 +133,7 @@ namespace Prism
|
||||
Renderer::BeginRenderPass(SceneRenderer::GetFinalRenderPass(), false);
|
||||
const auto viewProj = m_EditorCamera.GetViewProjection();
|
||||
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();
|
||||
Renderer::EndRenderPass();
|
||||
}
|
||||
@ -144,6 +160,37 @@ 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto editingAsset = PBRMaterialEditor::GetEditingAsset();
|
||||
if (editingAsset && (editingAsset->PreviewIsDirty || !editingAsset->PreviewTexture))
|
||||
{
|
||||
PBRMaterialEditor::RenderMaterialPreview(editingAsset);
|
||||
}
|
||||
else
|
||||
{
|
||||
bool renderedPreviewThisFrame = false;
|
||||
AssetsManager::ForEachAsset<PBRMaterialAsset>([&](Ref<PBRMaterialAsset> mat)
|
||||
{
|
||||
if (renderedPreviewThisFrame) return;
|
||||
if (mat->PreviewIsDirty || !mat->PreviewTexture)
|
||||
{
|
||||
PBRMaterialEditor::RenderMaterialPreview(mat);
|
||||
renderedPreviewThisFrame = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void EditorLayer::OnImGuiRender()
|
||||
@ -237,7 +284,7 @@ namespace Prism
|
||||
{
|
||||
// temp
|
||||
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::EndMenu();
|
||||
@ -246,7 +293,6 @@ namespace Prism
|
||||
if (ImGui::BeginMenu("Edit"))
|
||||
{
|
||||
ImGui::MenuItem("Physics Settings", nullptr, &m_ShowPhysicsSettings);
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
@ -262,6 +308,9 @@ namespace Prism
|
||||
Physics3D::DisconnectPVD();
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
ImGui::MenuItem("GamePad View", nullptr, &m_ShowGamePadSettings);
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
@ -275,8 +324,9 @@ namespace Prism
|
||||
Entity selectedEntity = m_SelectionContext.front().Entity;
|
||||
if (selectedEntity.HasComponent<MeshComponent>())
|
||||
{
|
||||
Ref<Mesh> mesh = selectedEntity.GetComponent<MeshComponent>().Mesh;
|
||||
if (mesh)
|
||||
auto& meshComponent = selectedEntity.GetComponent<MeshComponent>();
|
||||
|
||||
if (Ref<Mesh> mesh = meshComponent.Mesh)
|
||||
{
|
||||
auto& materials = mesh->GetMaterials();
|
||||
static uint32_t selectedMaterialIndex = 0;
|
||||
@ -304,27 +354,13 @@ namespace Prism
|
||||
}
|
||||
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();
|
||||
|
||||
if (selectedMaterialIndex < materials.size())
|
||||
{
|
||||
bool shouldUpdate = false;
|
||||
|
||||
auto& materialInstance = materials[selectedMaterialIndex];
|
||||
ImGui::Text("Shader: %s", materialInstance->GetShader()->GetName().c_str());
|
||||
// Textures ------------------------------------------------------------------------------
|
||||
@ -334,11 +370,26 @@ namespace Prism
|
||||
{
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(10, 10));
|
||||
|
||||
auto& albedoColor = materialInstance->Get<glm::vec3>("u_AlbedoColor");
|
||||
auto& albedoColor = materialInstance->Get<glm::vec4>("u_AlbedoColor");
|
||||
bool useAlbedoMap = materialInstance->Get<float>("u_AlbedoTexToggle");
|
||||
Ref<Texture2D> albedoMap = materialInstance->TryGetResource<Texture2D>("u_AlbedoTexture");
|
||||
|
||||
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();
|
||||
if (ImGui::IsItemHovered())
|
||||
{
|
||||
@ -351,28 +402,23 @@ namespace Prism
|
||||
ImGui::Image((ImTextureRef)albedoMap->GetRendererID(), ImVec2(384, 384));
|
||||
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::BeginGroup();
|
||||
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)
|
||||
m_AlbedoInput.TextureMap = Texture2D::Create(m_AlbedoInput.TextureMap->GetPath(), m_AlbedoInput.SRGB);
|
||||
}*/
|
||||
materialInstance->Set<float>("u_AlbedoTexToggle", useAlbedoMap ? 1.0f : 0.0f);
|
||||
shouldUpdate = true;
|
||||
}
|
||||
|
||||
|
||||
ImGui::EndGroup();
|
||||
ImGui::SameLine();
|
||||
ImGui::ColorEdit3("Color##Albedo", glm::value_ptr(albedoColor), ImGuiColorEditFlags_NoInputs);
|
||||
if (ImGui::ColorEdit4("Color##Albedo", glm::value_ptr(albedoColor), ImGuiColorEditFlags_NoInputs))
|
||||
{
|
||||
meshComponent.UpdateMaterials(selectedMaterialIndex);
|
||||
shouldUpdate = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
@ -385,6 +431,21 @@ namespace Prism
|
||||
Ref<Texture2D> normalMap = materialInstance->TryGetResource<Texture2D>("u_NormalTexture");
|
||||
|
||||
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();
|
||||
if (ImGui::IsItemHovered())
|
||||
{
|
||||
@ -403,12 +464,16 @@ namespace Prism
|
||||
{
|
||||
normalMap = Texture2D::Create(filename);
|
||||
materialInstance->Set("u_NormalTexture", normalMap);
|
||||
shouldUpdate = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Checkbox("Use##NormalMap", &useNormalMap))
|
||||
{
|
||||
materialInstance->Set<float>("u_NormalTexToggle", useNormalMap ? 1.0f : 0.0f);
|
||||
shouldUpdate = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
@ -422,6 +487,21 @@ namespace Prism
|
||||
Ref<Texture2D> metalnessMap = materialInstance->TryGetResource<Texture2D>("u_MetalnessTexture");
|
||||
|
||||
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();
|
||||
if (ImGui::IsItemHovered())
|
||||
{
|
||||
@ -434,20 +514,18 @@ namespace Prism
|
||||
ImGui::Image((ImTextureRef)metalnessMap->GetRendererID(), ImVec2(384, 384));
|
||||
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();
|
||||
if (ImGui::Checkbox("Use##MetalnessMap", &useMetalnessMap))
|
||||
{
|
||||
materialInstance->Set<float>("u_MetalnessTexToggle", useMetalnessMap ? 1.0f : 0.0f);
|
||||
shouldUpdate = true;
|
||||
}
|
||||
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 +538,20 @@ namespace Prism
|
||||
Ref<Texture2D> roughnessMap = materialInstance->TryGetResource<Texture2D>("u_RoughnessTexture");
|
||||
|
||||
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();
|
||||
if (ImGui::IsItemHovered())
|
||||
{
|
||||
@ -472,23 +564,72 @@ namespace Prism
|
||||
ImGui::Image((ImTextureRef)roughnessMap->GetRendererID(), ImVec2(384, 384));
|
||||
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();
|
||||
if (ImGui::Checkbox("Use##RoughnessMap", &useRoughnessMap))
|
||||
{
|
||||
materialInstance->Set<float>("u_RoughnessTexToggle", useRoughnessMap ? 1.0f : 0.0f);
|
||||
shouldUpdate = true;
|
||||
}
|
||||
ImGui::SameLine();
|
||||
ImGui::SliderFloat("Value##RoughnessInput", &roughnessValue, 0.0f, 1.0f);
|
||||
if (ImGui::SliderFloat("Value##RoughnessInput", &roughnessValue, 0.0f, 1.0f))
|
||||
{
|
||||
shouldUpdate = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
// AO
|
||||
if (ImGui::CollapsingHeader("AO", nullptr, ImGuiTreeNodeFlags_DefaultOpen))
|
||||
{
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(10, 10));
|
||||
float& aoValue = materialInstance->Get<float>("u_AO");
|
||||
bool useAOMap = materialInstance->Get<float>("u_AOTexToggle");
|
||||
Ref<Texture2D> aoMap = materialInstance->TryGetResource<Texture2D>("u_AOTexture");
|
||||
|
||||
ImGui::Image(aoMap ? (ImTextureRef)aoMap->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))
|
||||
{
|
||||
aoMap = AssetsManager::GetAsset<Texture2D>(assetHandle);
|
||||
shouldUpdate = true;
|
||||
}
|
||||
}
|
||||
ImGui::EndDragDropTarget();
|
||||
}
|
||||
|
||||
ImGui::PopStyleVar();
|
||||
if (ImGui::IsItemHovered())
|
||||
{
|
||||
if (aoMap)
|
||||
{
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f);
|
||||
ImGui::TextUnformatted(aoMap->GetPath().c_str());
|
||||
ImGui::PopTextWrapPos();
|
||||
ImGui::Image((ImTextureRef)aoMap->GetRendererID(), ImVec2(384, 384));
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Checkbox("Use##AOMap", &useAOMap))
|
||||
{
|
||||
materialInstance->Set<float>("u_AOTexToggle", useAOMap ? 1.0f : 0.0f);
|
||||
shouldUpdate = true;
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::SliderFloat("Value##AOInput", &aoValue, 0.0f, 1.0f))
|
||||
{
|
||||
shouldUpdate = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (shouldUpdate) meshComponent.UpdateMaterials(selectedMaterialIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -505,7 +646,11 @@ namespace Prism
|
||||
m_ObjectsPanel->OnImGuiRender();
|
||||
|
||||
m_SceneHierarchyPanel->OnImGuiRender();
|
||||
m_EditorCamera.OnImGuiRender();
|
||||
// m_EditorCamera.OnImGuiRender();
|
||||
m_ConsolePanel->OnImGuiRender();
|
||||
|
||||
// GamePad
|
||||
DrawGamepadDebugPanel(m_ShowGamePadSettings);
|
||||
|
||||
// Editor Panel ------------------------------------------------------------------------------
|
||||
ImGui::Begin("Environment");
|
||||
@ -517,6 +662,20 @@ namespace Prism
|
||||
|
||||
UI::PropertySlider("Exposure", m_EditorCamera.GetExposure(), 0.0f, 5.0f);
|
||||
|
||||
ImGui::Separator();
|
||||
float near = m_EditorCamera.GetNear();
|
||||
float far = m_EditorCamera.GetFar();
|
||||
|
||||
if (UI::Property("Near", near))
|
||||
{
|
||||
m_EditorCamera.SetNearFar(near, far);
|
||||
}
|
||||
if (UI::Property("Far", far))
|
||||
{
|
||||
m_EditorCamera.SetNearFar(near, far);
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
float physics2DGravity = m_EditorScene->GetPhysics2DGravity();
|
||||
if (UI::Property("2D World Gravity", physics2DGravity, -100.0f, 100.0f))
|
||||
@ -599,7 +758,6 @@ namespace Prism
|
||||
{
|
||||
SceneRenderer::SetViewportSize((uint32_t)viewportSize.x, (uint32_t)viewportSize.y);
|
||||
m_EditorScene->SetViewportSize((uint32_t)viewportSize.x, (uint32_t)viewportSize.y);
|
||||
m_EditorCamera.SetProjectionMatrix(glm::perspectiveFov(glm::radians(45.0f), viewportSize.x, viewportSize.y, 0.1f, 10000.0f));
|
||||
m_EditorCamera.SetViewportSize((uint32_t)viewportSize.x, (uint32_t)viewportSize.y);
|
||||
ImGui::Image((ImTextureRef)SceneRenderer::GetFinalColorBufferRendererID(), viewportSize, { 0, 1 }, { 1, 0 });
|
||||
|
||||
@ -654,7 +812,7 @@ namespace Prism
|
||||
m_ViewportBounds[1] = { maxBound.x, maxBound.y };
|
||||
|
||||
// ImGuizmo
|
||||
if (m_GizmoType != -1 && !m_SelectionContext.empty() && m_SceneState == SceneState::Edit)
|
||||
if ((m_ViewportPanelFocused || m_ViewportPanelHovered) && m_GizmoType != -1 && !m_SelectionContext.empty() && m_SceneState == SceneState::Edit)
|
||||
{
|
||||
auto& selection = m_SelectionContext[0];
|
||||
|
||||
@ -856,7 +1014,8 @@ namespace Prism
|
||||
|
||||
if (ImViewGuizmo::Rotate(cameraPos, cameraRot, glm::vec3(0.0f), gizmoCenter))
|
||||
{
|
||||
|
||||
if (m_ViewportPanelFocused || m_ViewportPanelHovered)
|
||||
{
|
||||
glm::vec3 forward = cameraRot * glm::vec3(0.0f, 0.0f, -1.0f);
|
||||
float newPitch = glm::asin(glm::clamp(-forward.y, -1.0f, 1.0f));
|
||||
float newYaw = -glm::atan(forward.x, -forward.z);
|
||||
@ -865,6 +1024,9 @@ namespace Prism
|
||||
m_EditorCamera.SetDistance(distance);
|
||||
m_EditorCamera.SetFocusPosition(focusPosition);
|
||||
m_EditorCamera.SetYawPitch(newYaw, newPitch);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -929,7 +1091,6 @@ namespace Prism
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch (e.GetKeyCode())
|
||||
{
|
||||
@ -944,6 +1105,7 @@ namespace Prism
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (Input::IsKeyPressed(KeyCode::LEFT_CONTROL))
|
||||
{
|
||||
@ -1020,7 +1182,6 @@ namespace Prism
|
||||
continue;
|
||||
|
||||
auto& submeshes = mesh->GetSubmeshes();
|
||||
float lastT = std::numeric_limits<float>::max();
|
||||
for (uint32_t i = 0; i < submeshes.size(); i++)
|
||||
{
|
||||
auto& submesh = submeshes[i];
|
||||
@ -1054,17 +1215,6 @@ namespace Prism
|
||||
});
|
||||
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]);
|
||||
}
|
||||
}
|
||||
@ -1105,6 +1255,249 @@ namespace Prism
|
||||
Application::Get().GetWindow().SetTitle(title);
|
||||
}
|
||||
|
||||
void EditorLayer::DrawGamepadDebugPanel(bool& p_open)
|
||||
{
|
||||
if (!p_open)
|
||||
return;
|
||||
|
||||
ImGui::Begin("Gamepad Debug", &p_open);
|
||||
ImDrawList* drawList = ImGui::GetWindowDrawList();
|
||||
|
||||
bool anyConnected = false;
|
||||
for (int jid = 0; jid <= 15; ++jid)
|
||||
{
|
||||
if (!Input::IsGamepadConnected(jid))
|
||||
continue;
|
||||
|
||||
anyConnected = true;
|
||||
const char* name = Input::GetGamepadName(jid);
|
||||
bool isGamepad = Input::IsGamepad(jid);
|
||||
|
||||
// 使用 CollapsingHeader 或 TreeNodeEx 均可,这里用 TreeNodeEx 保持与之前类似
|
||||
if (ImGui::TreeNodeEx((void*)(intptr_t)jid, ImGuiTreeNodeFlags_DefaultOpen,
|
||||
"Joystick %d: %s%s", jid, name, isGamepad ? " (mapped)" : ""))
|
||||
{
|
||||
// ---------- 1. 摇杆与主要按钮行 ----------
|
||||
const float stickRadius = 40.0f; // 圆形摇杆半径
|
||||
const ImVec2 stickSize(stickRadius * 2, stickRadius * 2);
|
||||
const float buttonSize = 30.0f; // 普通按钮(ABXY)的大小
|
||||
const float dpadButtonSize = 30.0f; // 十字键按钮稍小
|
||||
|
||||
// 左摇杆区域
|
||||
auto drawStick = [&](const char* label, float x, float y)
|
||||
{
|
||||
// 注意:GLFW 左 Y 向上为负,右 Y 向上为负,统一取反
|
||||
y = -y;
|
||||
ImGui::BeginGroup();
|
||||
ImGui::Text("%s", label);
|
||||
const ImVec2 pos = ImGui::GetCursorScreenPos();
|
||||
const ImVec2 center(pos.x + stickRadius, pos.y + stickRadius);
|
||||
|
||||
// 圆形底板
|
||||
drawList->AddCircleFilled(center, stickRadius, IM_COL32(30,30,30,255));
|
||||
drawList->AddCircle(center, stickRadius, IM_COL32(100,100,100,255), 0, 2.0f);
|
||||
// 十字参考线
|
||||
drawList->AddLine(ImVec2(center.x - stickRadius, center.y), ImVec2(center.x + stickRadius, center.y), IM_COL32(70,70,70,255));
|
||||
drawList->AddLine(ImVec2(center.x, center.y - stickRadius), ImVec2(center.x, center.y + stickRadius), IM_COL32(70,70,70,255));
|
||||
|
||||
// 摇杆位置点
|
||||
const float len = sqrtf(x*x + y*y);
|
||||
float clampX = x, clampY = y;
|
||||
if (len > 1.0f) { clampX /= len; clampY /= len; }
|
||||
const float dotX = center.x + clampX * stickRadius;
|
||||
const float dotY = center.y - clampY * stickRadius; // 屏幕Y向下,故用减
|
||||
drawList->AddCircleFilled(ImVec2(dotX, dotY), 6.0f, IM_COL32(255,80,80,255));
|
||||
if (len > 0.99f)
|
||||
drawList->AddCircle(center, stickRadius, IM_COL32(255,255,0,150), 0, 3.0f);
|
||||
|
||||
ImGui::Dummy(stickSize);
|
||||
ImGui::EndGroup();
|
||||
};
|
||||
|
||||
// 十字键(上下左右)
|
||||
auto drawDPad = [&]()
|
||||
{
|
||||
ImGui::BeginGroup();
|
||||
ImGui::Text("DPad");
|
||||
ImVec2 base = ImGui::GetCursorScreenPos();
|
||||
// 上
|
||||
bool up = Prism::Input::IsGamepadButtonPressed(jid, Prism::GamepadButton::DPAD_UP);
|
||||
ImGui::SetCursorScreenPos(ImVec2(base.x + dpadButtonSize, base.y));
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, up ? ImVec4(0.0f,1.0f,0.0f,1.0f) : ImVec4(0.3f,0.3f,0.3f,1.0f));
|
||||
ImGui::Button("U", ImVec2(dpadButtonSize, dpadButtonSize));
|
||||
ImGui::PopStyleColor();
|
||||
// 左
|
||||
bool left = Prism::Input::IsGamepadButtonPressed(jid, Prism::GamepadButton::DPAD_LEFT);
|
||||
ImGui::SetCursorScreenPos(ImVec2(base.x, base.y + dpadButtonSize));
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, left ? ImVec4(0.0f,1.0f,0.0f,1.0f) : ImVec4(0.3f,0.3f,0.3f,1.0f));
|
||||
ImGui::Button("L", ImVec2(dpadButtonSize, dpadButtonSize));
|
||||
ImGui::PopStyleColor();
|
||||
// 右
|
||||
bool right = Prism::Input::IsGamepadButtonPressed(jid, Prism::GamepadButton::DPAD_RIGHT);
|
||||
ImGui::SetCursorScreenPos(ImVec2(base.x + 2*dpadButtonSize, base.y + dpadButtonSize));
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, right ? ImVec4(0.0f,1.0f,0.0f,1.0f) : ImVec4(0.3f,0.3f,0.3f,1.0f));
|
||||
ImGui::Button("R", ImVec2(dpadButtonSize, dpadButtonSize));
|
||||
ImGui::PopStyleColor();
|
||||
// 下
|
||||
bool down = Prism::Input::IsGamepadButtonPressed(jid, Prism::GamepadButton::DPAD_DOWN);
|
||||
ImGui::SetCursorScreenPos(ImVec2(base.x + dpadButtonSize, base.y + 2*dpadButtonSize));
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, down ? ImVec4(0.0f,1.0f,0.0f,1.0f) : ImVec4(0.3f,0.3f,0.3f,1.0f));
|
||||
ImGui::Button("D", ImVec2(dpadButtonSize, dpadButtonSize));
|
||||
ImGui::PopStyleColor();
|
||||
|
||||
// 让 Group 大小包含整个十字区域
|
||||
ImGui::SetCursorScreenPos(ImVec2(base.x, base.y + 3*dpadButtonSize));
|
||||
ImGui::Dummy(ImVec2(3*dpadButtonSize, 0));
|
||||
ImGui::EndGroup();
|
||||
};
|
||||
|
||||
// ABXY 按钮组(按手柄实际位置排列:X左 Y上 B右 A下)
|
||||
auto drawABXY = [&]()
|
||||
{
|
||||
ImGui::BeginGroup();
|
||||
ImGui::Text("Buttons");
|
||||
ImVec2 base = ImGui::GetCursorScreenPos();
|
||||
// Y 上
|
||||
bool y = Prism::Input::IsGamepadButtonPressed(jid, Prism::GamepadButton::Y);
|
||||
ImGui::SetCursorScreenPos(ImVec2(base.x + buttonSize, base.y));
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, y ? ImVec4(1.0f,0.8f,0.0f,1.0f) : ImVec4(0.3f,0.3f,0.3f,1.0f));
|
||||
ImGui::Button("Y", ImVec2(buttonSize, buttonSize));
|
||||
ImGui::PopStyleColor();
|
||||
// X 左
|
||||
bool x = Prism::Input::IsGamepadButtonPressed(jid, Prism::GamepadButton::X);
|
||||
ImGui::SetCursorScreenPos(ImVec2(base.x, base.y + buttonSize));
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, x ? ImVec4(0.0f,0.7f,1.0f,1.0f) : ImVec4(0.3f,0.3f,0.3f,1.0f));
|
||||
ImGui::Button("X", ImVec2(buttonSize, buttonSize));
|
||||
ImGui::PopStyleColor();
|
||||
// B 右
|
||||
bool b = Prism::Input::IsGamepadButtonPressed(jid, Prism::GamepadButton::B);
|
||||
ImGui::SetCursorScreenPos(ImVec2(base.x + 2*buttonSize, base.y + buttonSize));
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, b ? ImVec4(1.0f,0.0f,0.0f,1.0f) : ImVec4(0.3f,0.3f,0.3f,1.0f));
|
||||
ImGui::Button("B", ImVec2(buttonSize, buttonSize));
|
||||
ImGui::PopStyleColor();
|
||||
// A 下
|
||||
bool a = Prism::Input::IsGamepadButtonPressed(jid, Prism::GamepadButton::A);
|
||||
ImGui::SetCursorScreenPos(ImVec2(base.x + buttonSize, base.y + 2*buttonSize));
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, a ? ImVec4(0.0f,1.0f,0.0f,1.0f) : ImVec4(0.3f,0.3f,0.3f,1.0f));
|
||||
ImGui::Button("A", ImVec2(buttonSize, buttonSize));
|
||||
ImGui::PopStyleColor();
|
||||
|
||||
ImGui::SetCursorScreenPos(ImVec2(base.x, base.y + 3*buttonSize));
|
||||
ImGui::Dummy(ImVec2(3*buttonSize, 0));
|
||||
ImGui::EndGroup();
|
||||
};
|
||||
|
||||
// 右摇杆区域
|
||||
auto drawRightStick = [&](float x, float y)
|
||||
{
|
||||
y = -y;
|
||||
ImGui::BeginGroup();
|
||||
ImGui::Text("R Stick");
|
||||
ImVec2 pos = ImGui::GetCursorScreenPos();
|
||||
ImVec2 center(pos.x + stickRadius, pos.y + stickRadius);
|
||||
drawList->AddCircleFilled(center, stickRadius, IM_COL32(30,30,30,255));
|
||||
drawList->AddCircle(center, stickRadius, IM_COL32(100,100,100,255), 0, 2.0f);
|
||||
drawList->AddLine(ImVec2(center.x - stickRadius, center.y), ImVec2(center.x + stickRadius, center.y), IM_COL32(70,70,70,255));
|
||||
drawList->AddLine(ImVec2(center.x, center.y - stickRadius), ImVec2(center.x, center.y + stickRadius), IM_COL32(70,70,70,255));
|
||||
|
||||
float len = sqrtf(x*x + y*y);
|
||||
float clampX = x, clampY = y;
|
||||
if (len > 1.0f) { clampX /= len; clampY /= len; }
|
||||
float dotX = center.x + clampX * stickRadius;
|
||||
float dotY = center.y - clampY * stickRadius;
|
||||
drawList->AddCircleFilled(ImVec2(dotX, dotY), 6.0f, IM_COL32(255,80,80,255));
|
||||
if (len > 0.99f)
|
||||
drawList->AddCircle(center, stickRadius, IM_COL32(255,255,0,150), 0, 3.0f);
|
||||
|
||||
ImGui::Dummy(stickSize);
|
||||
ImGui::EndGroup();
|
||||
};
|
||||
|
||||
// 获取摇杆当前值
|
||||
const float lx = Input::GetGamepadAxis(jid, GamepadAxis::LEFT_X);
|
||||
const float ly = Input::GetGamepadAxis(jid, GamepadAxis::LEFT_Y);
|
||||
const float rx = Input::GetGamepadAxis(jid, GamepadAxis::RIGHT_X);
|
||||
const float ry = Input::GetGamepadAxis(jid, GamepadAxis::RIGHT_Y);
|
||||
|
||||
// ----- 第一行:左摇杆 | 十字键 | ABXY | 右摇杆 -----
|
||||
ImGui::BeginGroup();
|
||||
// 缩进稍微调整
|
||||
ImGui::Columns(4, "MainControls", false);
|
||||
ImGui::SetColumnWidth(0, stickSize.x + 10);
|
||||
ImGui::SetColumnWidth(1, 3*dpadButtonSize + 10);
|
||||
ImGui::SetColumnWidth(2, 3*buttonSize + 10);
|
||||
ImGui::SetColumnWidth(3, stickSize.x + 10);
|
||||
|
||||
drawStick("L Stick", lx, ly);
|
||||
ImGui::NextColumn();
|
||||
drawDPad();
|
||||
ImGui::NextColumn();
|
||||
drawABXY();
|
||||
ImGui::NextColumn();
|
||||
drawRightStick(rx, ry);
|
||||
ImGui::Columns(1);
|
||||
ImGui::EndGroup();
|
||||
|
||||
ImGui::Spacing();
|
||||
|
||||
// ----- 第二行:肩键 LB/RB 和扳机轴 -----
|
||||
ImGui::Text("Bumpers & Triggers");
|
||||
bool lb = Input::IsGamepadButtonPressed(jid, Prism::GamepadButton::LEFT_BUMPER);
|
||||
bool rb = Input::IsGamepadButtonPressed(jid, Prism::GamepadButton::RIGHT_BUMPER);
|
||||
float lt = Input::GetGamepadAxis(jid, Prism::GamepadAxis::LEFT_TRIGGER);
|
||||
float rt = Input::GetGamepadAxis(jid, Prism::GamepadAxis::RIGHT_TRIGGER);
|
||||
|
||||
ImGui::BeginGroup();
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, lb ? ImVec4(0.0f,1.0f,0.0f,1.0f) : ImVec4(0.3f,0.3f,0.3f,1.0f));
|
||||
ImGui::Button("LB", ImVec2(40, 20));
|
||||
ImGui::PopStyleColor();
|
||||
ImGui::SameLine();
|
||||
ImGui::ProgressBar(lt, ImVec2(100, 20), "");
|
||||
ImGui::SameLine();
|
||||
ImGui::Text("LT %.2f", lt);
|
||||
|
||||
ImGui::SameLine(0, 30);
|
||||
|
||||
ImGui::ProgressBar(rt, ImVec2(100, 20), "");
|
||||
ImGui::SameLine();
|
||||
ImGui::Text("RT %.2f", rt);
|
||||
ImGui::SameLine();
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, rb ? ImVec4(0.0f,1.0f,0.0f,1.0f) : ImVec4(0.3f,0.3f,0.3f,1.0f));
|
||||
ImGui::Button("RB", ImVec2(40, 20));
|
||||
ImGui::PopStyleColor();
|
||||
ImGui::EndGroup();
|
||||
|
||||
ImGui::Spacing();
|
||||
|
||||
// ----- 第三行:功能键 Back, Guide, Start, LThumb, RThumb -----
|
||||
ImGui::Text("Function Keys");
|
||||
auto drawFuncBtn = [&](const char* label, Prism::GamepadButton btn)
|
||||
{
|
||||
bool pressed = Input::IsGamepadButtonPressed(jid, btn);
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, pressed ? ImVec4(0.0f,1.0f,0.0f,1.0f) : ImVec4(0.3f,0.3f,0.3f,1.0f));
|
||||
ImGui::Button(label, ImVec2(60, 25));
|
||||
ImGui::PopStyleColor();
|
||||
ImGui::SameLine(0, 4);
|
||||
};
|
||||
|
||||
drawFuncBtn("Back", GamepadButton::BACK);
|
||||
drawFuncBtn("Guide", GamepadButton::GUIDE);
|
||||
drawFuncBtn("Start", GamepadButton::START);
|
||||
ImGui::SameLine(0, 20);
|
||||
drawFuncBtn("LThumb", GamepadButton::LEFT_THUMB);
|
||||
drawFuncBtn("RThumb", GamepadButton::RIGHT_THUMB);
|
||||
ImGui::NewLine();
|
||||
|
||||
ImGui::TreePop();
|
||||
}
|
||||
}
|
||||
|
||||
if (!anyConnected)
|
||||
ImGui::Text("No gamepads connected.");
|
||||
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
std::pair<float, float> EditorLayer::GetMouseViewportSpace() const
|
||||
{
|
||||
auto [mx, my] = ImGui::GetMousePos(); // Input::GetMousePosition();
|
||||
@ -1166,6 +1559,14 @@ namespace Prism
|
||||
|
||||
m_EditorCamera = EditorCamera(glm::perspectiveFov(glm::radians(45.0f), 1280.0f, 720.0f, 0.1f, 1000.0f));
|
||||
m_SelectionContext.clear();
|
||||
|
||||
// new Scene with a default sky light
|
||||
auto newEntity = m_EditorScene->CreateEntity("Sky Light");
|
||||
auto& slc = newEntity.AddComponent<SkyLightComponent>();
|
||||
slc.DynamicSky = true;
|
||||
|
||||
Ref<TextureCube> preethamEnv = Renderer3D::CreatePreethamSky(slc.TurbidityAzimuthInclination);
|
||||
slc.SceneEnvironment = Ref<Environment>::Create(preethamEnv, preethamEnv);
|
||||
}
|
||||
|
||||
void EditorLayer::OpenScene()
|
||||
@ -1232,7 +1633,7 @@ namespace Prism
|
||||
m_SceneState = SceneState::Play;
|
||||
|
||||
if (m_ReloadScriptOnPlay)
|
||||
ScriptEngine::ReloadAssembly("assets/scripts/ExampleApp.dll");
|
||||
ScriptEngine::ReloadAssembly("assets/Scripts/Assembly-CSharp.dll");
|
||||
|
||||
m_RuntimeScene = Ref<Scene>::Create();
|
||||
m_EditorScene->CopyTo(m_RuntimeScene);
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
#ifndef EDITORLAYER_H
|
||||
#define EDITORLAYER_H
|
||||
|
||||
#include "Panels/ConsolePanel.h"
|
||||
#include "Prism.h"
|
||||
#include "Prism/Editor/ContentBrowserPanel.h"
|
||||
#include "Prism/Editor/ObjectsPanel.h"
|
||||
@ -32,6 +33,10 @@ namespace Prism
|
||||
void SelectEntity(Entity entity);
|
||||
|
||||
void UpdateWindowTitle(const std::string& sceneName);
|
||||
|
||||
// GamePad Utils
|
||||
void DrawGamepadDebugPanel(bool& p_open);
|
||||
|
||||
private:
|
||||
std::pair<float, float> GetMouseViewportSpace() const;
|
||||
std::pair<glm::vec3, glm::vec3> CastRay(float mx, float my);
|
||||
@ -144,12 +149,16 @@ namespace Prism
|
||||
bool m_ViewportPanelHovered = false;
|
||||
bool m_ViewportPanelFocused = false;
|
||||
bool m_ShowPhysicsSettings = false;
|
||||
bool m_ShowGamePadSettings = false;
|
||||
|
||||
enum class SceneState
|
||||
{
|
||||
Edit = 0, Play = 1, Pause = 2
|
||||
};
|
||||
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
|
||||
BIN
Editor/assets/editor/model.png
Normal file
BIN
Editor/assets/editor/model.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 64 KiB |
BIN
Editor/assets/editor/texture.png
Normal file
BIN
Editor/assets/editor/texture.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 64 KiB |
Binary file not shown.
389
Editor/assets/scenes/FPS.scene
Normal file
389
Editor/assets/scenes/FPS.scene
Normal file
@ -0,0 +1,389 @@
|
||||
Scene: Scene Name
|
||||
Environment:
|
||||
AssetHandle: 10745193190519058183
|
||||
Entities:
|
||||
- Entity: 4944419254382500800
|
||||
Parent: 0
|
||||
Children:
|
||||
[]
|
||||
TagComponent:
|
||||
Tag: Directional Light
|
||||
TransformComponent:
|
||||
Position: [0, 0, 0]
|
||||
Rotation: [-2.2312348, 0, 0]
|
||||
Scale: [1, 1, 1]
|
||||
DirectionalLightComponent:
|
||||
Radiance: [1, 1, 1]
|
||||
CastShadows: true
|
||||
SoftShadows: true
|
||||
LightSize: 0.5
|
||||
- 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: 10745193190519058183
|
||||
EnvironmentAssetPath: assets/env/venice_dawn_1_4k.hdr
|
||||
Intensity: 1
|
||||
Angle: 0
|
||||
DynamicSky: false
|
||||
TurbidityAzimuthInclination: [2, 0, 0]
|
||||
- Entity: 10732070446010033158
|
||||
Parent: 0
|
||||
Children:
|
||||
[]
|
||||
TagComponent:
|
||||
Tag: Cube
|
||||
TransformComponent:
|
||||
Position: [0, -2.6466873, 0]
|
||||
Rotation: [0, 0, 0]
|
||||
Scale: [100, 1, 100]
|
||||
MeshComponent:
|
||||
AssetID: 14957733959243172548
|
||||
AssetPath: assets/meshes/Default/Cube.fbx
|
||||
Materials:
|
||||
Slot 0:
|
||||
AssetHandle: 0
|
||||
AssetPath: ""
|
||||
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: 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: m_Radius
|
||||
Type: 1
|
||||
Data: 0
|
||||
- Name: WalkingSpeed
|
||||
Type: 1
|
||||
Data: 2
|
||||
- Name: RunSpeed
|
||||
Type: 1
|
||||
Data: 5
|
||||
- Name: JumpForce
|
||||
Type: 1
|
||||
Data: 1
|
||||
- Name: TorqueStrength
|
||||
Type: 1
|
||||
Data: 0
|
||||
- Name: MouseSensitivity
|
||||
Type: 1
|
||||
Data: 10
|
||||
- Name: CameraForwardOffset
|
||||
Type: 1
|
||||
Data: -2
|
||||
- Name: CameraYOffset
|
||||
Type: 1
|
||||
Data: 2
|
||||
MeshComponent:
|
||||
AssetID: 8763440120556133680
|
||||
AssetPath: assets/meshes/Default/Capsule.fbx
|
||||
Materials:
|
||||
Slot 0:
|
||||
AssetHandle: 0
|
||||
AssetPath: ""
|
||||
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: 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: 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: 14957733959243172548
|
||||
AssetPath: assets/meshes/Default/Cube.fbx
|
||||
Materials:
|
||||
Slot 0:
|
||||
AssetHandle: 0
|
||||
AssetPath: ""
|
||||
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: 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: 14957733959243172548
|
||||
AssetPath: assets/meshes/Default/Cube.fbx
|
||||
Materials:
|
||||
Slot 0:
|
||||
AssetHandle: 0
|
||||
AssetPath: ""
|
||||
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: 14957733959243172548
|
||||
AssetPath: assets/meshes/Default/Cube.fbx
|
||||
Materials:
|
||||
Slot 0:
|
||||
AssetHandle: 0
|
||||
AssetPath: ""
|
||||
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: 14957733959243172548
|
||||
AssetPath: assets/meshes/Default/Cube.fbx
|
||||
Materials:
|
||||
Slot 0:
|
||||
AssetHandle: 0
|
||||
AssetPath: ""
|
||||
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: 14957733959243172548
|
||||
AssetPath: assets/meshes/Default/Cube.fbx
|
||||
Materials:
|
||||
Slot 0:
|
||||
AssetHandle: 0
|
||||
AssetPath: ""
|
||||
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: 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: 14957733959243172548
|
||||
AssetPath: assets/meshes/Default/Cube.fbx
|
||||
Materials:
|
||||
Slot 0:
|
||||
AssetHandle: 0
|
||||
AssetPath: ""
|
||||
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: ""
|
||||
PhysicsLayers:
|
||||
[]
|
||||
@ -1,11 +1,50 @@
|
||||
Scene: Scene Name
|
||||
Environment:
|
||||
AssetHandle: 10549690553241162923
|
||||
Light:
|
||||
Direction: [-0.314, -0.941, -0.209]
|
||||
Radiance: [0, 0, 0]
|
||||
Multiplier: 1
|
||||
AssetHandle: 6095149963749185931
|
||||
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
|
||||
Parent: 0
|
||||
Children:
|
||||
@ -20,30 +59,6 @@ Entities:
|
||||
Radiance: [1, 1, 1]
|
||||
CastShadows: true
|
||||
SoftShadows: true
|
||||
LightSize: 0.5
|
||||
- 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
|
||||
LightSize: 0.9
|
||||
PhysicsLayers:
|
||||
[]
|
||||
@ -1,12 +1,21 @@
|
||||
Scene: Scene Name
|
||||
Environment:
|
||||
AssetHandle: 17073147362577408906
|
||||
Light:
|
||||
Direction: [-0.314, -0.941, -0.209]
|
||||
Radiance: [0, 0, 0]
|
||||
Multiplier: 1
|
||||
AssetHandle: 5211537204242875091
|
||||
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
|
||||
Children:
|
||||
[]
|
||||
@ -17,8 +26,11 @@ Entities:
|
||||
Rotation: [0, 0, 0]
|
||||
Scale: [1, 1, 1]
|
||||
SkyLightComponent:
|
||||
EnvironmentMap: 17073147362577408906
|
||||
EnvironmentMap: 5211537204242875091
|
||||
EnvironmentAssetPath: assets/env/venice_dawn_1_4k.hdr
|
||||
Intensity: 1
|
||||
Angle: 0
|
||||
DynamicSky: false
|
||||
TurbidityAzimuthInclination: [2, 0, 0]
|
||||
PhysicsLayers:
|
||||
[]
|
||||
@ -1,4 +1,4 @@
|
||||
// -----------------------------
|
||||
// -----------------------------
|
||||
// -- Based on Hazel PBR shader --
|
||||
// -----------------------------
|
||||
// Note: this shader is still very much in progress. There are likely many bugs and future additions that will go in.
|
||||
@ -28,8 +28,6 @@ uniform mat4 u_ViewProjectionMatrix;
|
||||
uniform mat4 u_ViewMatrix;
|
||||
uniform mat4 u_Transform;
|
||||
|
||||
uniform mat4 u_LightSpaceMatrix;
|
||||
|
||||
out VertexOutput
|
||||
{
|
||||
vec3 WorldPosition;
|
||||
@ -39,7 +37,7 @@ out VertexOutput
|
||||
mat3 WorldTransform;
|
||||
vec3 Binormal;
|
||||
vec3 ViewPosition;
|
||||
vec4 FragPosLightSpace;
|
||||
float ViewZ;
|
||||
} vs_Output;
|
||||
|
||||
void main()
|
||||
@ -58,9 +56,8 @@ void main()
|
||||
vs_Output.WorldTransform = mat3(u_Transform);
|
||||
vs_Output.Binormal = a_Binormal;
|
||||
|
||||
vs_Output.FragPosLightSpace = u_LightSpaceMatrix * u_Transform * localPosition;
|
||||
|
||||
vs_Output.ViewPosition = vec3(u_ViewMatrix * vec4(vs_Output.WorldPosition, 1.0));
|
||||
vs_Output.ViewZ = vs_Output.ViewPosition.z;
|
||||
|
||||
// gl_Position = u_ViewProjectionMatrix * u_Transform * vec4(a_Position, 1.0);
|
||||
gl_Position = u_ViewProjectionMatrix * u_Transform * localPosition;
|
||||
@ -75,6 +72,10 @@ const float Epsilon = 0.00001;
|
||||
const int LightCount = 1;
|
||||
const vec3 Fdielectric = vec3(0.04);
|
||||
|
||||
layout(location = 0) out vec4 color;
|
||||
layout(location = 1) out vec4 o_MaterialInfo;
|
||||
layout(location = 2) out vec4 o_BloomColor;
|
||||
|
||||
struct DirectionalLight {
|
||||
vec3 Direction;
|
||||
vec3 Radiance;
|
||||
@ -110,20 +111,18 @@ in VertexOutput
|
||||
mat3 WorldTransform;
|
||||
vec3 Binormal;
|
||||
vec3 ViewPosition;
|
||||
vec4 FragPosLightSpace;
|
||||
float ViewZ;
|
||||
} vs_Input;
|
||||
|
||||
layout(location = 0) out vec4 color;
|
||||
layout(location = 1) out vec4 o_BloomColor;
|
||||
|
||||
uniform DirectionalLight u_DirectionalLights;
|
||||
uniform vec3 u_CameraPosition;
|
||||
|
||||
uniform int u_PointLightCount;
|
||||
uniform PointLight u_PointLights;
|
||||
uniform PointLight u_PointLights[8];
|
||||
|
||||
uniform int u_SpotLightCount;
|
||||
uniform SpotLight u_SpotLights;
|
||||
uniform SpotLight u_SpotLights[8];
|
||||
|
||||
|
||||
// PBR
|
||||
@ -131,6 +130,7 @@ uniform sampler2D u_AlbedoTexture;
|
||||
uniform sampler2D u_NormalTexture;
|
||||
uniform sampler2D u_MetalnessTexture;
|
||||
uniform sampler2D u_RoughnessTexture;
|
||||
uniform sampler2D u_AOTexture;
|
||||
|
||||
// environment
|
||||
uniform samplerCube u_EnvRadianceTex;
|
||||
@ -144,18 +144,28 @@ uniform float u_BloomThreshold;
|
||||
uniform float u_EnvMapRotation;
|
||||
|
||||
// baseColor
|
||||
uniform vec3 u_AlbedoColor;
|
||||
uniform vec4 u_AlbedoColor;
|
||||
uniform float u_Metalness;
|
||||
uniform float u_Roughness;
|
||||
uniform float u_AO;
|
||||
|
||||
// textureToggle
|
||||
uniform float u_AlbedoTexToggle;
|
||||
uniform float u_NormalTexToggle;
|
||||
uniform float u_MetalnessTexToggle;
|
||||
uniform float u_RoughnessTexToggle;
|
||||
uniform float u_AOTexToggle;
|
||||
|
||||
// shadow
|
||||
uniform sampler2D u_ShadowMap;
|
||||
const int CSM_CASCADE_COUNT = 4;
|
||||
uniform sampler2D u_ShadowMap[4];
|
||||
uniform mat4 u_LightSpaceMatrix0;
|
||||
uniform mat4 u_LightSpaceMatrix1;
|
||||
uniform mat4 u_LightSpaceMatrix2;
|
||||
uniform mat4 u_LightSpaceMatrix3;
|
||||
uniform vec4 u_CascadeSplits;
|
||||
uniform float u_ShadowFar;
|
||||
uniform float u_ShadowNear;
|
||||
uniform float u_ShadowBias;
|
||||
uniform float u_ShadowSoftness;
|
||||
uniform float u_ShadowIntensity;
|
||||
@ -163,7 +173,7 @@ uniform int u_ShadowEnabled;
|
||||
|
||||
struct PBRParameters
|
||||
{
|
||||
vec3 Albedo;
|
||||
vec4 Albedo;
|
||||
float Roughness;
|
||||
float Metalness;
|
||||
vec3 Normal;
|
||||
@ -225,7 +235,7 @@ vec3 ComputeDirectionalLight(DirectionalLight light, vec3 F0, PBRParameters para
|
||||
float G = GeometrySmith(params.Normal, params.View, L, params.Roughness);
|
||||
|
||||
vec3 kd = (1.0 - F) * (1.0 - params.Metalness);
|
||||
vec3 diffuseBRDF = kd * params.Albedo;
|
||||
vec3 diffuseBRDF = kd * params.Albedo.rgb;
|
||||
vec3 specularBRDF = (F * D * G) / max(Epsilon, 4.0 * cosLi * params.NdotV);
|
||||
|
||||
return (diffuseBRDF + specularBRDF) * Lradiance * cosLi;
|
||||
@ -257,7 +267,7 @@ vec3 ComputePointLight(PointLight light, vec3 F0, PBRParameters params, vec3 wor
|
||||
float G = GeometrySmith(params.Normal, params.View, L, params.Roughness);
|
||||
|
||||
vec3 kd = (1.0 - F) * (1.0 - params.Metalness);
|
||||
vec3 diffuseBRDF = kd * params.Albedo;
|
||||
vec3 diffuseBRDF = kd * params.Albedo.rgb;
|
||||
vec3 specularBRDF = (F * D * G) / max(Epsilon, 4.0 * cosLi * params.NdotV);
|
||||
|
||||
return (diffuseBRDF + specularBRDF) * Lradiance * cosLi * attenuation;
|
||||
@ -294,7 +304,7 @@ vec3 ComputeSpotLight(SpotLight light, vec3 F0, PBRParameters params, vec3 world
|
||||
float G = GeometrySmith(params.Normal, params.View, L, params.Roughness);
|
||||
|
||||
vec3 kd = (1.0 - F) * (1.0 - params.Metalness);
|
||||
vec3 diffuseBRDF = kd * params.Albedo;
|
||||
vec3 diffuseBRDF = kd * params.Albedo.rgb;
|
||||
vec3 specularBRDF = (F * D * G) / max(Epsilon, 4.0 * cosLi * params.NdotV);
|
||||
|
||||
return (diffuseBRDF + specularBRDF) * Lradiance * cosLi * attenuation;
|
||||
@ -319,7 +329,7 @@ vec3 Lighting(vec3 F0)
|
||||
float G = GeometrySmith(m_Params.Normal, m_Params.View, Li, m_Params.Roughness);
|
||||
|
||||
vec3 kd = (1.0 - F) * (1.0 - m_Params.Metalness);
|
||||
vec3 diffuseBRDF = kd * m_Params.Albedo;
|
||||
vec3 diffuseBRDF = kd * m_Params.Albedo.rgb;
|
||||
|
||||
vec3 specularBRDF = (F * D * G) / max(Epsilon, 4.0 * cosLi * m_Params.NdotV);
|
||||
|
||||
@ -345,7 +355,7 @@ vec3 IBL(vec3 F0, vec3 Lr)
|
||||
vec3 irradiance = texture(u_EnvIrradianceTex, m_Params.Normal).rgb;
|
||||
vec3 F = fresnelSchlickRoughness(F0, m_Params.NdotV, m_Params.Roughness);
|
||||
vec3 kd = (1.0 - F) * (1.0 - m_Params.Metalness);
|
||||
vec3 diffuseIBL = m_Params.Albedo * irradiance;
|
||||
vec3 diffuseIBL = m_Params.Albedo.rgb * irradiance;
|
||||
|
||||
int u_EnvRadianceTexLevels = textureQueryLevels(u_EnvRadianceTex);
|
||||
vec3 specularIrradiance = textureLod(
|
||||
@ -361,75 +371,125 @@ vec3 IBL(vec3 F0, vec3 Lr)
|
||||
}
|
||||
|
||||
// shadow
|
||||
|
||||
float calculateShadow(vec4 fragPosLightSpace, vec3 normal, vec3 lightDir)
|
||||
int selectCascade(float viewZ)
|
||||
{
|
||||
// Perspective divide
|
||||
vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w;
|
||||
|
||||
// Transform to [0,1] range
|
||||
projCoords = projCoords * 0.5 + 0.5;
|
||||
|
||||
// If outside shadow map bounds, assume no shadow
|
||||
if(projCoords.z > 1.0 || projCoords.x < 0.0 || projCoords.x > 1.0 || projCoords.y < 0.0 || projCoords.y > 1.0)
|
||||
return 0.0;
|
||||
|
||||
// Get closest depth value from light's perspective
|
||||
float closestDepth = texture(u_ShadowMap, projCoords.xy).r;
|
||||
float currentDepth = projCoords.z;
|
||||
|
||||
// Calculate bias based on surface angle
|
||||
float bias = max(u_ShadowBias * (1.0 - dot(normal, lightDir)), u_ShadowBias * 0.1);
|
||||
|
||||
// PCF (Percentage Closer Filtering) for soft shadows
|
||||
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;
|
||||
float depth = -viewZ;
|
||||
float linearDepth = (depth - u_ShadowNear) / (u_ShadowFar - u_ShadowNear);
|
||||
if (linearDepth < u_CascadeSplits.x) return 0;
|
||||
if (linearDepth < u_CascadeSplits.y) return 1;
|
||||
if (linearDepth < u_CascadeSplits.z) return 2;
|
||||
return 3;
|
||||
}
|
||||
|
||||
|
||||
float ComputeShadow(vec4 fragPosLightSpace, float NdotL)
|
||||
mat4 getLightSpaceMatrix(int cascade)
|
||||
{
|
||||
if (u_ShadowEnabled == 0) return 1.0;
|
||||
if (cascade == 0) return u_LightSpaceMatrix0;
|
||||
else if (cascade == 1) return u_LightSpaceMatrix1;
|
||||
else if (cascade == 2) return u_LightSpaceMatrix2;
|
||||
else return u_LightSpaceMatrix3;
|
||||
}
|
||||
|
||||
float getCascadeSplit(int cascade)
|
||||
{
|
||||
if (cascade == 0) return u_CascadeSplits.x;
|
||||
else if (cascade == 1) return u_CascadeSplits.y;
|
||||
else if (cascade == 2) return u_CascadeSplits.z;
|
||||
else return u_CascadeSplits.w;
|
||||
}
|
||||
|
||||
float sampleShadow(int cascade, vec2 uv, float compareDepth, float bias)
|
||||
{
|
||||
float depth;
|
||||
if (cascade == 0) depth = texture(u_ShadowMap[0], uv).r;
|
||||
else if (cascade == 1) depth = texture(u_ShadowMap[1], uv).r;
|
||||
else if (cascade == 2) depth = texture(u_ShadowMap[2], uv).r;
|
||||
else depth = texture(u_ShadowMap[3], uv).r;
|
||||
return (compareDepth - bias) > depth ? 1.0 : 0.0;
|
||||
}
|
||||
|
||||
vec2 getTexelSize(int cascade)
|
||||
{
|
||||
if (cascade == 0) return 1.0 / vec2(textureSize(u_ShadowMap[0], 0));
|
||||
else if (cascade == 1) return 1.0 / vec2(textureSize(u_ShadowMap[1], 0));
|
||||
else if (cascade == 2) return 1.0 / vec2(textureSize(u_ShadowMap[2], 0));
|
||||
else return 1.0 / vec2(textureSize(u_ShadowMap[3], 0));
|
||||
}
|
||||
|
||||
float pcfShadow(int cascade, vec3 projCoords, float bias)
|
||||
{
|
||||
vec2 texelSize = getTexelSize(cascade);
|
||||
int pcfRange = clamp(int(u_ShadowSoftness), 0, 3);
|
||||
float shadow = 0.0;
|
||||
int samples = 0;
|
||||
|
||||
for (int x = -pcfRange; x <= pcfRange; ++x)
|
||||
{
|
||||
for (int y = -pcfRange; y <= pcfRange; ++y)
|
||||
{
|
||||
vec2 offset = vec2(x, y) * texelSize;
|
||||
shadow += sampleShadow(cascade, projCoords.xy + offset, projCoords.z, bias);
|
||||
samples++;
|
||||
}
|
||||
}
|
||||
return shadow / float(samples);
|
||||
}
|
||||
|
||||
float calculateCSMShadow(vec3 worldPos, vec3 normal, vec3 lightDir, float viewZ)
|
||||
{
|
||||
int cascade = selectCascade(viewZ);
|
||||
|
||||
vec4 fragPosLightSpace = getLightSpaceMatrix(cascade) * vec4(worldPos, 1.0);
|
||||
|
||||
vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w;
|
||||
projCoords = projCoords * 0.5 + 0.5;
|
||||
|
||||
if (projCoords.x < 0.0 || projCoords.x > 1.0 ||
|
||||
projCoords.y < 0.0 || projCoords.y > 1.0 ||
|
||||
projCoords.z > 1.0) return 1.0;
|
||||
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 = pcfShadow(cascade, projCoords, bias);
|
||||
|
||||
float bias = max(u_ShadowBias * (1.0 - NdotL), u_ShadowBias * 0.5);
|
||||
float cascadeEdge = 0.0;
|
||||
if (cascade < CSM_CASCADE_COUNT - 1)
|
||||
{
|
||||
float depth = -viewZ;
|
||||
float linearDepth = (depth - u_ShadowNear) / (u_ShadowFar - u_ShadowNear);
|
||||
float splitDist = getCascadeSplit(cascade);
|
||||
float prevSplit = (cascade > 0) ? getCascadeSplit(cascade - 1) : 0.0;
|
||||
float blendStart = splitDist - (splitDist - prevSplit) * 0.1;
|
||||
if (linearDepth > blendStart)
|
||||
{
|
||||
cascadeEdge = (linearDepth - blendStart) / (splitDist - blendStart);
|
||||
|
||||
float shadow = (currentDepth - bias) > closestDepth ? 1.0 : 0.0;
|
||||
return mix(1.0, 1.0 - u_ShadowIntensity, shadow);
|
||||
int nextCascade = cascade + 1;
|
||||
vec4 fragPosNext = getLightSpaceMatrix(nextCascade) * vec4(worldPos, 1.0);
|
||||
|
||||
vec3 projCoordsNext = fragPosNext.xyz / fragPosNext.w;
|
||||
projCoordsNext = projCoordsNext * 0.5 + 0.5;
|
||||
|
||||
if (!(projCoordsNext.z > 1.0 || projCoordsNext.x < 0.0 || projCoordsNext.x > 1.0 ||
|
||||
projCoordsNext.y < 0.0 || projCoordsNext.y > 1.0))
|
||||
{
|
||||
float nextShadow = pcfShadow(nextCascade, projCoordsNext, bias);
|
||||
shadow = mix(shadow, nextShadow, cascadeEdge);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return shadow * u_ShadowIntensity;
|
||||
}
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
m_Params.Albedo = u_AlbedoTexToggle > 0.5 ? texture(u_AlbedoTexture, vs_Input.TexCoord).rgb : u_AlbedoColor;
|
||||
m_Params.Albedo = u_AlbedoTexToggle > 0.5 ? texture(u_AlbedoTexture, vs_Input.TexCoord) : u_AlbedoColor;
|
||||
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 = max(m_Params.Roughness, 0.05);
|
||||
|
||||
float ao = u_AOTexToggle > 0.5 ? texture(u_AOTexture, vs_Input.TexCoord).r : u_AO;
|
||||
|
||||
// normal
|
||||
m_Params.Normal = normalize(vs_Input.Normal);
|
||||
if (u_NormalTexToggle > 0.5)
|
||||
@ -443,11 +503,11 @@ void main()
|
||||
|
||||
vec3 Lr = 2.0 * m_Params.NdotV * m_Params.Normal - m_Params.View;
|
||||
|
||||
vec3 F0 = mix(Fdielectric, m_Params.Albedo, m_Params.Metalness);
|
||||
vec3 F0 = mix(Fdielectric, m_Params.Albedo.rgb, m_Params.Metalness);
|
||||
|
||||
float shadowFactor = 1.0;
|
||||
if (u_ShadowEnabled > 0.5) {
|
||||
float shadow = calculateShadow(vs_Input.FragPosLightSpace, m_Params.Normal, u_DirectionalLights.Direction);
|
||||
float shadow = calculateCSMShadow(vs_Input.WorldPosition, m_Params.Normal, u_DirectionalLights.Direction, vs_Input.ViewZ);
|
||||
shadowFactor = 1.0 - shadow;
|
||||
}
|
||||
|
||||
@ -455,17 +515,27 @@ void main()
|
||||
vec3 lightContribution = u_DirectionalLights.Intensity > 0.0 ? Lighting(F0) * shadowFactor : vec3(0.0);
|
||||
|
||||
if(u_PointLightCount > 0)
|
||||
lightContribution += ComputePointLight(u_PointLights, F0, m_Params, vs_Input.WorldPosition);
|
||||
{
|
||||
for( int i = 0; i < u_PointLightCount; i ++) {
|
||||
lightContribution += ComputePointLight(u_PointLights[i], F0, m_Params, vs_Input.WorldPosition);
|
||||
}
|
||||
}
|
||||
|
||||
if(u_SpotLightCount > 0)
|
||||
lightContribution += ComputeSpotLight(u_SpotLights, F0, m_Params, vs_Input.WorldPosition);
|
||||
{
|
||||
for(int i = 0; i < u_SpotLightCount; i ++)
|
||||
{
|
||||
lightContribution += ComputeSpotLight(u_SpotLights[i], F0, m_Params, vs_Input.WorldPosition);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
vec3 iblContribution = IBL(F0, Lr) * u_IBLContribution;
|
||||
vec3 iblContribution = IBL(F0, Lr) * u_IBLContribution * ao;
|
||||
|
||||
color = vec4(lightContribution + iblContribution, 1.0);
|
||||
|
||||
// Bloom
|
||||
float brightness = dot(color.rgb, vec3(0.2126, 0.7152, 0.0722));
|
||||
o_BloomColor = brightness > u_BloomThreshold ? color : vec4(0.0, 0.0, 0.0, 1.0);
|
||||
|
||||
o_MaterialInfo = vec4(m_Params.Metalness, m_Params.Roughness, 0.0, 1.0);
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
// -----------------------------
|
||||
// -----------------------------
|
||||
// -- Based on Hazel PBR shader --
|
||||
// -----------------------------
|
||||
// Note: this shader is still very much in progress. There are likely many bugs and future additions that will go in.
|
||||
@ -22,8 +22,6 @@ uniform mat4 u_ViewProjectionMatrix;
|
||||
uniform mat4 u_ViewMatrix;
|
||||
uniform mat4 u_Transform;
|
||||
|
||||
uniform mat4 u_LightSpaceMatrix;
|
||||
|
||||
out VertexOutput
|
||||
{
|
||||
vec3 WorldPosition;
|
||||
@ -33,7 +31,7 @@ out VertexOutput
|
||||
mat3 WorldTransform;
|
||||
vec3 Binormal;
|
||||
vec3 ViewPosition;
|
||||
vec4 FragPosLightSpace;
|
||||
float ViewZ;
|
||||
} vs_Output;
|
||||
|
||||
void main()
|
||||
@ -45,9 +43,8 @@ void main()
|
||||
vs_Output.WorldTransform = mat3(u_Transform);
|
||||
vs_Output.Binormal = a_Binormal;
|
||||
|
||||
vs_Output.FragPosLightSpace = u_LightSpaceMatrix * u_Transform * vec4(a_Position, 1.0);
|
||||
|
||||
vs_Output.ViewPosition = vec3(u_ViewMatrix * vec4(vs_Output.WorldPosition, 1.0));
|
||||
vs_Output.ViewZ = vs_Output.ViewPosition.z;
|
||||
|
||||
gl_Position = u_ViewProjectionMatrix * u_Transform * vec4(a_Position, 1.0);
|
||||
}
|
||||
@ -61,6 +58,10 @@ const float Epsilon = 0.00001;
|
||||
const int LightCount = 1;
|
||||
const vec3 Fdielectric = vec3(0.04);
|
||||
|
||||
layout(location = 0) out vec4 color;
|
||||
layout(location = 1) out vec4 o_MaterialInfo;
|
||||
layout(location = 2) out vec4 o_BloomColor;
|
||||
|
||||
struct DirectionalLight {
|
||||
vec3 Direction;
|
||||
vec3 Radiance;
|
||||
@ -97,19 +98,16 @@ in VertexOutput
|
||||
mat3 WorldTransform;
|
||||
vec3 Binormal;
|
||||
vec3 ViewPosition;
|
||||
vec4 FragPosLightSpace;
|
||||
float ViewZ;
|
||||
} vs_Input;
|
||||
|
||||
layout(location = 0) out vec4 color;
|
||||
layout(location = 1) out vec4 o_BloomColor;
|
||||
|
||||
uniform DirectionalLight u_DirectionalLights;
|
||||
|
||||
uniform int u_PointLightCount;
|
||||
uniform PointLight u_PointLights;
|
||||
uniform PointLight u_PointLights[8];
|
||||
|
||||
uniform int u_SpotLightCount;
|
||||
uniform SpotLight u_SpotLights;
|
||||
uniform SpotLight u_SpotLights[8];
|
||||
|
||||
|
||||
uniform vec3 u_CameraPosition;
|
||||
@ -119,6 +117,7 @@ uniform sampler2D u_AlbedoTexture;
|
||||
uniform sampler2D u_NormalTexture;
|
||||
uniform sampler2D u_MetalnessTexture;
|
||||
uniform sampler2D u_RoughnessTexture;
|
||||
uniform sampler2D u_AOTexture;
|
||||
|
||||
// environment
|
||||
uniform samplerCube u_EnvRadianceTex;
|
||||
@ -132,18 +131,28 @@ uniform float u_BloomThreshold;
|
||||
uniform float u_EnvMapRotation;
|
||||
|
||||
// baseColor
|
||||
uniform vec3 u_AlbedoColor;
|
||||
uniform vec4 u_AlbedoColor;
|
||||
uniform float u_Metalness;
|
||||
uniform float u_Roughness;
|
||||
uniform float u_AO;
|
||||
|
||||
// textureToggle
|
||||
uniform float u_AlbedoTexToggle;
|
||||
uniform float u_NormalTexToggle;
|
||||
uniform float u_MetalnessTexToggle;
|
||||
uniform float u_RoughnessTexToggle;
|
||||
uniform float u_AOTexToggle;
|
||||
|
||||
// shadow
|
||||
uniform sampler2D u_ShadowMap;
|
||||
const int CSM_CASCADE_COUNT = 4;
|
||||
uniform sampler2D u_ShadowMap[4];
|
||||
uniform mat4 u_LightSpaceMatrix0;
|
||||
uniform mat4 u_LightSpaceMatrix1;
|
||||
uniform mat4 u_LightSpaceMatrix2;
|
||||
uniform mat4 u_LightSpaceMatrix3;
|
||||
uniform vec4 u_CascadeSplits;
|
||||
uniform float u_ShadowFar;
|
||||
uniform float u_ShadowNear;
|
||||
uniform float u_ShadowBias;
|
||||
uniform float u_ShadowSoftness;
|
||||
uniform float u_ShadowIntensity;
|
||||
@ -151,7 +160,7 @@ uniform int u_ShadowEnabled;
|
||||
|
||||
struct PBRParameters
|
||||
{
|
||||
vec3 Albedo;
|
||||
vec4 Albedo;
|
||||
float Roughness;
|
||||
float Metalness;
|
||||
vec3 Normal;
|
||||
@ -213,7 +222,7 @@ vec3 ComputeDirectionalLight(DirectionalLight light, vec3 F0, PBRParameters para
|
||||
float G = GeometrySmith(params.Normal, params.View, L, params.Roughness);
|
||||
|
||||
vec3 kd = (1.0 - F) * (1.0 - params.Metalness);
|
||||
vec3 diffuseBRDF = kd * params.Albedo;
|
||||
vec3 diffuseBRDF = kd * params.Albedo.rgb;
|
||||
vec3 specularBRDF = (F * D * G) / max(Epsilon, 4.0 * cosLi * params.NdotV);
|
||||
|
||||
return (diffuseBRDF + specularBRDF) * Lradiance * cosLi;
|
||||
@ -245,7 +254,7 @@ vec3 ComputePointLight(PointLight light, vec3 F0, PBRParameters params, vec3 wor
|
||||
float G = GeometrySmith(params.Normal, params.View, L, params.Roughness);
|
||||
|
||||
vec3 kd = (1.0 - F) * (1.0 - params.Metalness);
|
||||
vec3 diffuseBRDF = kd * params.Albedo;
|
||||
vec3 diffuseBRDF = kd * params.Albedo.rgb;
|
||||
vec3 specularBRDF = (F * D * G) / max(Epsilon, 4.0 * cosLi * params.NdotV);
|
||||
|
||||
return (diffuseBRDF + specularBRDF) * Lradiance * cosLi * attenuation;
|
||||
@ -282,7 +291,7 @@ vec3 ComputeSpotLight(SpotLight light, vec3 F0, PBRParameters params, vec3 world
|
||||
float G = GeometrySmith(params.Normal, params.View, L, params.Roughness);
|
||||
|
||||
vec3 kd = (1.0 - F) * (1.0 - params.Metalness);
|
||||
vec3 diffuseBRDF = kd * params.Albedo;
|
||||
vec3 diffuseBRDF = kd * params.Albedo.rgb;
|
||||
vec3 specularBRDF = (F * D * G) / max(Epsilon, 4.0 * cosLi * params.NdotV);
|
||||
|
||||
return (diffuseBRDF + specularBRDF) * Lradiance * cosLi * attenuation;
|
||||
@ -305,7 +314,7 @@ vec3 Lighting(vec3 F0)
|
||||
float G = GeometrySmith(m_Params.Normal, m_Params.View, Li, m_Params.Roughness);
|
||||
|
||||
vec3 kd = (1.0 - F) * (1.0 - m_Params.Metalness);
|
||||
vec3 diffuseBRDF = kd * m_Params.Albedo;
|
||||
vec3 diffuseBRDF = kd * m_Params.Albedo.rgb;
|
||||
|
||||
vec3 specularBRDF = (F * D * G) / max(Epsilon, 4.0 * cosLi * m_Params.NdotV);
|
||||
|
||||
@ -331,14 +340,14 @@ vec3 IBL(vec3 F0, vec3 Lr)
|
||||
vec3 irradiance = texture(u_EnvIrradianceTex, m_Params.Normal).rgb;
|
||||
vec3 F = fresnelSchlickRoughness(F0, m_Params.NdotV, m_Params.Roughness);
|
||||
vec3 kd = (1.0 - F) * (1.0 - m_Params.Metalness);
|
||||
vec3 diffuseIBL = m_Params.Albedo * irradiance;
|
||||
vec3 diffuseIBL = m_Params.Albedo.rgb * irradiance;
|
||||
|
||||
int u_EnvRadianceTexLevels = textureQueryLevels(u_EnvRadianceTex);
|
||||
vec3 specularIrradiance = textureLod(
|
||||
u_EnvRadianceTex,
|
||||
RotateVectorAboutY(u_EnvMapRotation, Lr),
|
||||
m_Params.Roughness * u_EnvRadianceTexLevels
|
||||
).rgb;
|
||||
).rgb;
|
||||
|
||||
vec2 specularBRDF = texture(u_BRDFLUTTexture, vec2(m_Params.NdotV, 1.0 - m_Params.Roughness)).rg;
|
||||
vec3 specularIBL = specularIrradiance * (F * specularBRDF.x + specularBRDF.y);
|
||||
@ -347,75 +356,125 @@ vec3 IBL(vec3 F0, vec3 Lr)
|
||||
}
|
||||
|
||||
// shadow
|
||||
|
||||
float calculateShadow(vec4 fragPosLightSpace, vec3 normal, vec3 lightDir)
|
||||
int selectCascade(float viewZ)
|
||||
{
|
||||
// Perspective divide
|
||||
vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w;
|
||||
|
||||
// Transform to [0,1] range
|
||||
projCoords = projCoords * 0.5 + 0.5;
|
||||
|
||||
// If outside shadow map bounds, assume no shadow
|
||||
if(projCoords.z > 1.0 || projCoords.x < 0.0 || projCoords.x > 1.0 || projCoords.y < 0.0 || projCoords.y > 1.0)
|
||||
return 0.0;
|
||||
|
||||
// Get closest depth value from light's perspective
|
||||
float closestDepth = texture(u_ShadowMap, projCoords.xy).r;
|
||||
float currentDepth = projCoords.z;
|
||||
|
||||
// Calculate bias based on surface angle
|
||||
float bias = max(u_ShadowBias * (1.0 - dot(normal, lightDir)), u_ShadowBias * 0.1);
|
||||
|
||||
// PCF (Percentage Closer Filtering) for soft shadows
|
||||
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;
|
||||
float depth = -viewZ;
|
||||
float linearDepth = (depth - u_ShadowNear) / (u_ShadowFar - u_ShadowNear);
|
||||
if (linearDepth < u_CascadeSplits.x) return 0;
|
||||
if (linearDepth < u_CascadeSplits.y) return 1;
|
||||
if (linearDepth < u_CascadeSplits.z) return 2;
|
||||
return 3;
|
||||
}
|
||||
|
||||
|
||||
float ComputeShadow(vec4 fragPosLightSpace, float NdotL)
|
||||
mat4 getLightSpaceMatrix(int cascade)
|
||||
{
|
||||
if (u_ShadowEnabled == 0) return 1.0;
|
||||
if (cascade == 0) return u_LightSpaceMatrix0;
|
||||
else if (cascade == 1) return u_LightSpaceMatrix1;
|
||||
else if (cascade == 2) return u_LightSpaceMatrix2;
|
||||
else return u_LightSpaceMatrix3;
|
||||
}
|
||||
|
||||
float getCascadeSplit(int cascade)
|
||||
{
|
||||
if (cascade == 0) return u_CascadeSplits.x;
|
||||
else if (cascade == 1) return u_CascadeSplits.y;
|
||||
else if (cascade == 2) return u_CascadeSplits.z;
|
||||
else return u_CascadeSplits.w;
|
||||
}
|
||||
|
||||
float sampleShadow(int cascade, vec2 uv, float compareDepth, float bias)
|
||||
{
|
||||
float depth;
|
||||
if (cascade == 0) depth = texture(u_ShadowMap[0], uv).r;
|
||||
else if (cascade == 1) depth = texture(u_ShadowMap[1], uv).r;
|
||||
else if (cascade == 2) depth = texture(u_ShadowMap[2], uv).r;
|
||||
else depth = texture(u_ShadowMap[3], uv).r;
|
||||
return (compareDepth - bias) > depth ? 1.0 : 0.0;
|
||||
}
|
||||
|
||||
vec2 getTexelSize(int cascade)
|
||||
{
|
||||
if (cascade == 0) return 1.0 / vec2(textureSize(u_ShadowMap[0], 0));
|
||||
else if (cascade == 1) return 1.0 / vec2(textureSize(u_ShadowMap[1], 0));
|
||||
else if (cascade == 2) return 1.0 / vec2(textureSize(u_ShadowMap[2], 0));
|
||||
else return 1.0 / vec2(textureSize(u_ShadowMap[3], 0));
|
||||
}
|
||||
|
||||
float pcfShadow(int cascade, vec3 projCoords, float bias)
|
||||
{
|
||||
vec2 texelSize = getTexelSize(cascade);
|
||||
int pcfRange = clamp(int(u_ShadowSoftness), 0, 3);
|
||||
float shadow = 0.0;
|
||||
int samples = 0;
|
||||
|
||||
for (int x = -pcfRange; x <= pcfRange; ++x)
|
||||
{
|
||||
for (int y = -pcfRange; y <= pcfRange; ++y)
|
||||
{
|
||||
vec2 offset = vec2(x, y) * texelSize;
|
||||
shadow += sampleShadow(cascade, projCoords.xy + offset, projCoords.z, bias);
|
||||
samples++;
|
||||
}
|
||||
}
|
||||
return shadow / float(samples);
|
||||
}
|
||||
|
||||
float calculateCSMShadow(vec3 worldPos, vec3 normal, vec3 lightDir, float viewZ)
|
||||
{
|
||||
int cascade = selectCascade(viewZ);
|
||||
|
||||
vec4 fragPosLightSpace = getLightSpaceMatrix(cascade) * vec4(worldPos, 1.0);
|
||||
|
||||
vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w;
|
||||
projCoords = projCoords * 0.5 + 0.5;
|
||||
|
||||
if (projCoords.x < 0.0 || projCoords.x > 1.0 ||
|
||||
projCoords.y < 0.0 || projCoords.y > 1.0 ||
|
||||
projCoords.z > 1.0) return 1.0;
|
||||
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 = pcfShadow(cascade, projCoords, bias);
|
||||
|
||||
float bias = max(u_ShadowBias * (1.0 - NdotL), u_ShadowBias * 0.5);
|
||||
float cascadeEdge = 0.0;
|
||||
if (cascade < CSM_CASCADE_COUNT - 1)
|
||||
{
|
||||
float depth = -viewZ;
|
||||
float linearDepth = (depth - u_ShadowNear) / (u_ShadowFar - u_ShadowNear);
|
||||
float splitDist = getCascadeSplit(cascade);
|
||||
float prevSplit = (cascade > 0) ? getCascadeSplit(cascade - 1) : 0.0;
|
||||
float blendStart = splitDist - (splitDist - prevSplit) * 0.1;
|
||||
if (linearDepth > blendStart)
|
||||
{
|
||||
cascadeEdge = (linearDepth - blendStart) / (splitDist - blendStart);
|
||||
|
||||
float shadow = (currentDepth - bias) > closestDepth ? 1.0 : 0.0;
|
||||
return mix(1.0, 1.0 - u_ShadowIntensity, shadow);
|
||||
int nextCascade = cascade + 1;
|
||||
vec4 fragPosNext = getLightSpaceMatrix(nextCascade) * vec4(worldPos, 1.0);
|
||||
|
||||
vec3 projCoordsNext = fragPosNext.xyz / fragPosNext.w;
|
||||
projCoordsNext = projCoordsNext * 0.5 + 0.5;
|
||||
|
||||
if (!(projCoordsNext.z > 1.0 || projCoordsNext.x < 0.0 || projCoordsNext.x > 1.0 ||
|
||||
projCoordsNext.y < 0.0 || projCoordsNext.y > 1.0))
|
||||
{
|
||||
float nextShadow = pcfShadow(nextCascade, projCoordsNext, bias);
|
||||
shadow = mix(shadow, nextShadow, cascadeEdge);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return shadow * u_ShadowIntensity;
|
||||
}
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
m_Params.Albedo = u_AlbedoTexToggle > 0.5 ? texture(u_AlbedoTexture, vs_Input.TexCoord).rgb : u_AlbedoColor;
|
||||
m_Params.Albedo = u_AlbedoTexToggle > 0.5 ? texture(u_AlbedoTexture, vs_Input.TexCoord) : u_AlbedoColor;
|
||||
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 = max(m_Params.Roughness, 0.05);
|
||||
|
||||
float ao = u_AOTexToggle > 0.5 ? texture(u_AOTexture, vs_Input.TexCoord).r : u_AO;
|
||||
|
||||
// normal
|
||||
m_Params.Normal = normalize(vs_Input.Normal);
|
||||
if (u_NormalTexToggle > 0.5)
|
||||
@ -429,29 +488,42 @@ void main()
|
||||
|
||||
vec3 Lr = 2.0 * m_Params.NdotV * m_Params.Normal - m_Params.View;
|
||||
|
||||
vec3 F0 = mix(Fdielectric, m_Params.Albedo, m_Params.Metalness);
|
||||
vec3 F0 = mix(Fdielectric, m_Params.Albedo.rgb, m_Params.Metalness);
|
||||
|
||||
// Shadow
|
||||
float shadowFactor = 1.0;
|
||||
if (u_ShadowEnabled > 0.5) {
|
||||
float shadow = calculateShadow(vs_Input.FragPosLightSpace, m_Params.Normal, u_DirectionalLights.Direction);
|
||||
float shadow = calculateCSMShadow(vs_Input.WorldPosition, m_Params.Normal, u_DirectionalLights.Direction, vs_Input.ViewZ);
|
||||
shadowFactor = 1.0 - shadow;
|
||||
}
|
||||
|
||||
// directional light with with shadow
|
||||
vec3 lightContribution = u_DirectionalLights.Intensity > 0.0 ? Lighting(F0) * shadowFactor : vec3(0.0);
|
||||
|
||||
|
||||
if(u_PointLightCount > 0)
|
||||
lightContribution += ComputePointLight(u_PointLights, F0, m_Params, vs_Input.WorldPosition);
|
||||
{
|
||||
for( int i = 0; i < u_PointLightCount; i ++) {
|
||||
lightContribution += ComputePointLight(u_PointLights[i], F0, m_Params, vs_Input.WorldPosition);
|
||||
}
|
||||
}
|
||||
|
||||
if(u_SpotLightCount > 0)
|
||||
lightContribution += ComputeSpotLight(u_SpotLights, F0, m_Params, vs_Input.WorldPosition);
|
||||
{
|
||||
for(int i = 0; i < u_SpotLightCount; i ++)
|
||||
{
|
||||
lightContribution += ComputeSpotLight(u_SpotLights[i], F0, m_Params, vs_Input.WorldPosition);
|
||||
}
|
||||
}
|
||||
|
||||
vec3 iblContribution = IBL(F0, Lr) * u_IBLContribution * ao;
|
||||
|
||||
vec3 iblContribution = IBL(F0, Lr) * u_IBLContribution;
|
||||
|
||||
color = vec4(lightContribution + iblContribution, 1.0);
|
||||
|
||||
// Bloom
|
||||
float brightness = dot(color.rgb, vec3(0.2126, 0.7152, 0.0722));
|
||||
o_BloomColor = brightness > u_BloomThreshold ? color : vec4(0.0, 0.0, 0.0, 1.0);
|
||||
|
||||
o_MaterialInfo = vec4(m_Params.Metalness, m_Params.Roughness, 0.0, 1.0);
|
||||
}
|
||||
|
||||
178
Editor/assets/shaders/SSR.glsl
Normal file
178
Editor/assets/shaders/SSR.glsl
Normal file
@ -0,0 +1,178 @@
|
||||
#type vertex
|
||||
#version 430
|
||||
|
||||
layout(location = 0) in vec3 a_Position;
|
||||
layout(location = 1) in vec2 a_TexCoord;
|
||||
|
||||
out vec2 v_TexCoord;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 position = vec4(a_Position.xy, 0.0, 1.0);
|
||||
v_TexCoord = a_TexCoord;
|
||||
gl_Position = position;
|
||||
}
|
||||
|
||||
#type fragment
|
||||
#version 430
|
||||
|
||||
layout(location = 0) out vec4 o_Color;
|
||||
|
||||
in vec2 v_TexCoord;
|
||||
|
||||
uniform sampler2D u_ColorTexture;
|
||||
uniform sampler2D u_DepthTexture;
|
||||
uniform sampler2D u_MaterialInfoTexture;
|
||||
|
||||
uniform mat4 u_Projection;
|
||||
uniform mat4 u_View;
|
||||
uniform mat4 u_InvViewProjection;
|
||||
|
||||
uniform vec3 u_CameraPosition;
|
||||
|
||||
uniform vec2 u_ScreenSize;
|
||||
uniform float u_CameraNear;
|
||||
uniform float u_CameraFar;
|
||||
|
||||
uniform int u_Steps = 32;
|
||||
uniform float u_Thickness = 0.5;
|
||||
uniform float u_MaxDistance = 30.0;
|
||||
uniform float u_StepSize = 0.5;
|
||||
uniform float u_RayOffset = 0.1;
|
||||
uniform float u_Intensity = 1.0;
|
||||
|
||||
float saturate(float x)
|
||||
{
|
||||
return clamp(x, 0.0, 1.0);
|
||||
}
|
||||
|
||||
float LinearizeDepth(float depth)
|
||||
{
|
||||
float z = depth * 2.0 - 1.0;
|
||||
return (2.0 * u_CameraNear * u_CameraFar) / (u_CameraFar + u_CameraNear - z * (u_CameraFar - u_CameraNear));
|
||||
}
|
||||
|
||||
vec3 ComputeWorldSpacePosition(vec2 uv, float depth)
|
||||
{
|
||||
vec4 clipPos = vec4(uv * 2.0 - 1.0, depth * 2.0 - 1.0, 1.0);
|
||||
vec4 worldPos = u_InvViewProjection * clipPos;
|
||||
return worldPos.xyz / worldPos.w;
|
||||
}
|
||||
|
||||
vec3 ReconstructNormalFromDepth(vec2 tc, float depth)
|
||||
{
|
||||
vec2 texelSize = 1.0 / u_ScreenSize;
|
||||
|
||||
vec2 tcL = tc - vec2(texelSize.x, 0.0);
|
||||
vec2 tcR = tc + vec2(texelSize.x, 0.0);
|
||||
vec2 tcB = tc - vec2(0.0, texelSize.y);
|
||||
vec2 tcT = tc + vec2(0.0, texelSize.y);
|
||||
|
||||
float depthL = texture(u_DepthTexture, tcL).r;
|
||||
float depthR = texture(u_DepthTexture, tcR).r;
|
||||
float depthB = texture(u_DepthTexture, tcB).r;
|
||||
float depthT = texture(u_DepthTexture, tcT).r;
|
||||
|
||||
vec3 pC = ComputeWorldSpacePosition(tc, depth);
|
||||
vec3 pR = ComputeWorldSpacePosition(tcR, depthR);
|
||||
vec3 pT = ComputeWorldSpacePosition(tcT, depthT);
|
||||
|
||||
vec3 dx = pR - pC;
|
||||
vec3 dy = pT - pC;
|
||||
|
||||
return normalize(cross(dx, dy));
|
||||
}
|
||||
|
||||
vec3 ComputeNDCWithZ(vec3 worldPos)
|
||||
{
|
||||
vec4 clipPos = u_Projection * u_View * vec4(worldPos, 1.0);
|
||||
vec3 ndc = clipPos.xyz / clipPos.w;
|
||||
ndc.xy = ndc.xy * 0.5 + 0.5;
|
||||
return ndc;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
float depth = texture(u_DepthTexture, v_TexCoord).r;
|
||||
|
||||
if (depth >= 1.0)
|
||||
{
|
||||
o_Color = vec4(0.0);
|
||||
return;
|
||||
}
|
||||
|
||||
vec4 matInfo = texture(u_MaterialInfoTexture, v_TexCoord);
|
||||
float metalness = matInfo.r;
|
||||
float roughness = matInfo.g;
|
||||
|
||||
if (roughness > 0.9)
|
||||
{
|
||||
o_Color = vec4(0.0);
|
||||
return;
|
||||
}
|
||||
|
||||
vec3 positionWS = ComputeWorldSpacePosition(v_TexCoord, depth);
|
||||
vec3 viewWS = normalize(u_CameraPosition - positionWS);
|
||||
vec3 normalWS = ReconstructNormalFromDepth(v_TexCoord, depth);
|
||||
vec3 reflectionWS = normalize(reflect(-viewWS, normalWS));
|
||||
|
||||
if (dot(reflectionWS, normalWS) < 0.0)
|
||||
{
|
||||
o_Color = vec4(0.0);
|
||||
return;
|
||||
}
|
||||
|
||||
vec3 rayWS = positionWS + normalWS * u_RayOffset;
|
||||
|
||||
for (int i = 0; i < u_Steps; i++)
|
||||
{
|
||||
rayWS += reflectionWS * u_StepSize;
|
||||
|
||||
vec3 rayNDC = ComputeNDCWithZ(rayWS);
|
||||
float rayDepth = rayNDC.z;
|
||||
|
||||
vec2 raySS = rayNDC.xy * u_ScreenSize;
|
||||
|
||||
if (rayNDC.x < 0.0 || rayNDC.x > 1.0 || rayNDC.y < 0.0 || rayNDC.y > 1.0)
|
||||
break;
|
||||
|
||||
float sceneDepth = texture(u_DepthTexture, rayNDC.xy).r;
|
||||
float sceneDepthLinear = LinearizeDepth(sceneDepth);
|
||||
float rayDepthLinear = LinearizeDepth(rayDepth * 0.5 + 0.5);
|
||||
|
||||
float delta = rayDepthLinear - sceneDepthLinear;
|
||||
|
||||
if (delta >= 0.0 && delta <= u_Thickness)
|
||||
{
|
||||
vec3 hitNormalWS = ReconstructNormalFromDepth(rayNDC.xy, sceneDepth);
|
||||
if (dot(hitNormalWS, reflectionWS) > 0.0)
|
||||
break;
|
||||
|
||||
float ssrStrength = saturate(1.0 - roughness * roughness);
|
||||
|
||||
float dist = distance(positionWS, rayWS);
|
||||
float fadeFactor = 1.0 - smoothstep(u_MaxDistance * 0.3, u_MaxDistance, dist);
|
||||
|
||||
float edgeFade = 1.0;
|
||||
edgeFade *= smoothstep(0.0, 0.1, rayNDC.x);
|
||||
edgeFade *= smoothstep(0.0, 0.1, rayNDC.y);
|
||||
edgeFade *= smoothstep(0.0, 0.1, 1.0 - rayNDC.x);
|
||||
edgeFade *= smoothstep(0.0, 0.1, 1.0 - rayNDC.y);
|
||||
|
||||
float NdotV = max(dot(normalWS, viewWS), 0.0);
|
||||
vec3 F0 = mix(vec3(0.04), vec3(1.0), metalness);
|
||||
vec3 Fresnel = F0 + (1.0 - F0) * pow(1.0 - NdotV, 5.0);
|
||||
|
||||
ssrStrength *= fadeFactor * edgeFade * u_Intensity;
|
||||
|
||||
vec4 color = texture(u_ColorTexture, rayNDC.xy);
|
||||
color.rgb *= ssrStrength * Fresnel;
|
||||
color.a = ssrStrength * dot(Fresnel, vec3(0.333));
|
||||
|
||||
o_Color = color;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
o_Color = vec4(0.0);
|
||||
}
|
||||
85
Editor/assets/shaders/SSRBlur.glsl
Normal file
85
Editor/assets/shaders/SSRBlur.glsl
Normal file
@ -0,0 +1,85 @@
|
||||
#type vertex
|
||||
#version 430
|
||||
|
||||
layout(location = 0) in vec3 a_Position;
|
||||
layout(location = 1) in vec2 a_TexCoord;
|
||||
|
||||
out vec2 v_TexCoord;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 position = vec4(a_Position.xy, 0.0, 1.0);
|
||||
v_TexCoord = a_TexCoord;
|
||||
gl_Position = position;
|
||||
}
|
||||
|
||||
#type fragment
|
||||
#version 430
|
||||
|
||||
layout(location = 0) out vec4 o_Color;
|
||||
|
||||
in vec2 v_TexCoord;
|
||||
|
||||
uniform sampler2D u_SSRTexture;
|
||||
uniform sampler2D u_DepthTexture;
|
||||
uniform sampler2D u_MaterialInfoTexture;
|
||||
|
||||
uniform vec2 u_ScreenSize;
|
||||
uniform float u_BlurRadius = 4.0;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 texelSize = 1.0 / u_ScreenSize;
|
||||
|
||||
vec4 center = texture(u_SSRTexture, v_TexCoord);
|
||||
if (center.a <= 0.001)
|
||||
{
|
||||
o_Color = vec4(0.0);
|
||||
return;
|
||||
}
|
||||
|
||||
float roughness = texture(u_MaterialInfoTexture, v_TexCoord).g;
|
||||
float effectiveBlurRadius = max(u_BlurRadius * roughness * roughness, 1.0);
|
||||
|
||||
float centerDepth = texture(u_DepthTexture, v_TexCoord).r;
|
||||
vec3 result = vec3(0.0);
|
||||
float totalWeight = 0.0;
|
||||
|
||||
const int kRadius = 6;
|
||||
float sigma = effectiveBlurRadius * 0.5;
|
||||
|
||||
for (int x = -kRadius; x <= kRadius; x++)
|
||||
{
|
||||
for (int y = -kRadius; y <= kRadius; y++)
|
||||
{
|
||||
vec2 offset = vec2(float(x), float(y)) * texelSize * effectiveBlurRadius / float(kRadius);
|
||||
vec2 sampleUV = v_TexCoord + offset;
|
||||
|
||||
if (sampleUV.x < 0.0 || sampleUV.x > 1.0 || sampleUV.y < 0.0 || sampleUV.y > 1.0)
|
||||
continue;
|
||||
|
||||
float sampleDepth = texture(u_DepthTexture, sampleUV).r;
|
||||
float depthDiff = abs(centerDepth - sampleDepth);
|
||||
|
||||
float depthWeight = exp(-depthDiff * 200.0);
|
||||
|
||||
float spatialWeight = exp(-(float(x * x + y * y)) / (2.0 * sigma * sigma));
|
||||
|
||||
vec4 sampleColor = texture(u_SSRTexture, sampleUV);
|
||||
|
||||
float alphaWeight = sampleColor.a > 0.01 ? 1.0 : 0.0;
|
||||
|
||||
float weight = spatialWeight * depthWeight * alphaWeight;
|
||||
|
||||
result += sampleColor.rgb * weight;
|
||||
totalWeight += weight;
|
||||
}
|
||||
}
|
||||
|
||||
if (totalWeight > 0.0)
|
||||
result /= totalWeight;
|
||||
else
|
||||
result = center.rgb;
|
||||
|
||||
o_Color = vec4(result, center.a);
|
||||
}
|
||||
@ -22,8 +22,20 @@ layout(location = 1) out vec4 o_BloomTexture;
|
||||
in vec2 v_TexCoord;
|
||||
|
||||
uniform sampler2DMS u_Texture;
|
||||
uniform sampler2DMS u_DepthTexture;
|
||||
uniform sampler2D u_BloomTexture;
|
||||
|
||||
uniform mat4 u_InvProjection;
|
||||
uniform mat4 u_InvView;
|
||||
|
||||
// Fog
|
||||
uniform float u_FogEnabled;
|
||||
uniform vec3 u_FogColor;
|
||||
uniform float u_FogDensity; // 雾密度,典型值 0.01~0.05
|
||||
uniform float u_FogHeight; // 雾的起始高度(世界 Y 坐标),低于此高度雾最浓
|
||||
uniform float u_FogHeightFalloff; // 高度衰减系数,值越大高度影响越剧烈(典型 0.5~2.0)
|
||||
|
||||
|
||||
|
||||
uniform bool u_EnableAutoExposure;
|
||||
uniform float u_ManualExposure;
|
||||
@ -37,6 +49,9 @@ uniform int u_TextureSamples;
|
||||
uniform bool u_EnableBloom;
|
||||
uniform float u_BloomThreshold;
|
||||
|
||||
uniform bool u_EnableSSR;
|
||||
uniform sampler2D u_SSRTexture;
|
||||
|
||||
const float uFar = 1.0;
|
||||
|
||||
vec4 SampleTexture(sampler2D tex, vec2 texCoord)
|
||||
@ -70,7 +85,6 @@ float MultiSampleDepth(sampler2DMS tex, vec2 tc)
|
||||
void main()
|
||||
{
|
||||
const float gamma = 2.2;
|
||||
const float pureWhite = 1.0;
|
||||
|
||||
// Tonemapping
|
||||
vec4 msColor = MultiSampleTexture(u_Texture, v_TexCoord);
|
||||
@ -82,18 +96,75 @@ void main()
|
||||
color += bloomColor;
|
||||
}
|
||||
|
||||
if (u_EnableSSR)
|
||||
{
|
||||
vec4 ssrSample = texture(u_SSRTexture, v_TexCoord);
|
||||
color = mix(color, ssrSample.rgb, ssrSample.a);
|
||||
}
|
||||
|
||||
|
||||
float exposure = 1.0f;
|
||||
if(u_EnableAutoExposure)
|
||||
color *= u_Exposure;
|
||||
exposure = u_Exposure;
|
||||
else
|
||||
color *= u_ManualExposure;
|
||||
exposure = u_ManualExposure;
|
||||
color *= exposure;
|
||||
|
||||
// Reinhard tonemapping operator.
|
||||
// see: "Photographic Tone Reproduction for Digital Images", eq. 4
|
||||
float luminance = dot(color, vec3(0.2126, 0.7152, 0.0722));
|
||||
float mappedLuminance = (luminance * (1.0 + luminance / (pureWhite * pureWhite))) / (1.0 + luminance);
|
||||
vec3 mappedColor = color;
|
||||
|
||||
// Scale color by ratio of average luminances.
|
||||
vec3 mappedColor = (mappedLuminance / luminance) * color;
|
||||
float luminance = dot(mappedColor, vec3(0.2126, 0.7152, 0.0722));
|
||||
if (luminance > 0.00001)
|
||||
{
|
||||
float a = 2.51;
|
||||
float b = 0.03;
|
||||
float c = 2.43;
|
||||
float d = 0.59;
|
||||
float e = 0.14;
|
||||
mappedColor = clamp((mappedColor * (a * mappedColor + b)) / (mappedColor * (c * mappedColor + d) + e), 0.0, 1.0);
|
||||
}
|
||||
|
||||
if (u_FogEnabled > 0.5)
|
||||
{
|
||||
// 1. 获取深度并重建视空间坐标
|
||||
float depth = MultiSampleDepth(u_DepthTexture, v_TexCoord);
|
||||
vec4 clipPos = vec4(v_TexCoord * 2.0 - 1.0, depth * 2.0 - 1.0, 1.0);
|
||||
vec4 viewPos4 = u_InvProjection * clipPos;
|
||||
viewPos4 /= viewPos4.w;
|
||||
vec3 viewPos = viewPos4.xyz; // 视空间坐标(相机为原点,Z 轴向内)
|
||||
|
||||
// 2. 距离雾因子(指数雾)
|
||||
float distance = length(viewPos);
|
||||
float distanceFactor = 1.0 - exp(-distance * u_FogDensity);
|
||||
// 可选:指数平方雾(更平滑)
|
||||
// float distanceFactor = 1.0 - exp(-pow(distance * u_FogDensity, 2.0));
|
||||
|
||||
// 3. 高度雾因子(基于世界 Y)
|
||||
// 将视空间坐标转换到世界空间
|
||||
vec4 worldPos4 = u_InvView* vec4(viewPos, 1.0);
|
||||
vec3 worldPos = worldPos4.xyz / worldPos4.w;
|
||||
float worldY = worldPos.y;
|
||||
|
||||
float heightFactor = 0.0;
|
||||
if (worldY < u_FogHeight)
|
||||
{
|
||||
// 低于起始高度:雾最浓,因子为 1
|
||||
heightFactor = 1.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 高于起始高度:指数衰减,高度越高雾越淡
|
||||
float deltaY = worldY - u_FogHeight;
|
||||
heightFactor = exp(-deltaY * u_FogHeightFalloff);
|
||||
}
|
||||
// 可选:使用 clamp 限制范围
|
||||
heightFactor = clamp(heightFactor, 0.0, 1.0);
|
||||
|
||||
// 4. 综合雾因子(可相乘,也可取最大值,通常相乘)
|
||||
float fogFactor = distanceFactor * heightFactor;
|
||||
|
||||
// 5. 混合雾颜色(雾颜色直接使用 u_FogColor,已在 LDR 空间)
|
||||
mappedColor = mix(mappedColor, u_FogColor, fogFactor);
|
||||
}
|
||||
|
||||
// Gamma correction.
|
||||
o_Color = vec4(pow(mappedColor, vec3(1.0 / gamma)), 1.0);
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
[Window][DockSpace Demo]
|
||||
Pos=0,0
|
||||
Size=2560,1566
|
||||
Size=1920,1080
|
||||
Collapsed=0
|
||||
|
||||
[Window][Debug##Default]
|
||||
@ -9,32 +9,32 @@ Size=400,400
|
||||
Collapsed=0
|
||||
|
||||
[Window][Scene Hierarchy]
|
||||
Pos=2089,24
|
||||
Size=471,563
|
||||
Pos=1449,24
|
||||
Size=471,385
|
||||
Collapsed=0
|
||||
DockId=0x00000009,0
|
||||
|
||||
[Window][Properties]
|
||||
Pos=2089,589
|
||||
Size=471,977
|
||||
Pos=1449,411
|
||||
Size=471,669
|
||||
Collapsed=0
|
||||
DockId=0x0000000A,0
|
||||
|
||||
[Window][Scene Renderer]
|
||||
Pos=0,843
|
||||
Size=481,723
|
||||
Pos=0,585
|
||||
Size=481,495
|
||||
Collapsed=0
|
||||
DockId=0x00000006,0
|
||||
|
||||
[Window][Materials]
|
||||
Pos=0,24
|
||||
Size=481,817
|
||||
Size=481,559
|
||||
Collapsed=0
|
||||
DockId=0x00000005,0
|
||||
|
||||
[Window][Script Engine Debug]
|
||||
Pos=2089,589
|
||||
Size=471,977
|
||||
Pos=1449,411
|
||||
Size=471,669
|
||||
Collapsed=0
|
||||
DockId=0x0000000A,2
|
||||
|
||||
@ -52,25 +52,25 @@ DockId=0x00000001,0
|
||||
|
||||
[Window][Viewport]
|
||||
Pos=483,58
|
||||
Size=1604,955
|
||||
Size=964,647
|
||||
Collapsed=0
|
||||
DockId=0x0000000B,0
|
||||
|
||||
[Window][Environment]
|
||||
Pos=2089,589
|
||||
Size=471,977
|
||||
Pos=1449,411
|
||||
Size=471,669
|
||||
Collapsed=0
|
||||
DockId=0x0000000A,1
|
||||
|
||||
[Window][Project]
|
||||
Pos=483,1015
|
||||
Size=1604,551
|
||||
Pos=483,707
|
||||
Size=964,373
|
||||
Collapsed=0
|
||||
DockId=0x0000000C,0
|
||||
|
||||
[Window][Objects]
|
||||
Pos=483,1015
|
||||
Size=1604,551
|
||||
Pos=483,707
|
||||
Size=964,373
|
||||
Collapsed=0
|
||||
DockId=0x0000000C,1
|
||||
|
||||
@ -81,12 +81,18 @@ Collapsed=0
|
||||
|
||||
[Window][##tool_bar]
|
||||
Pos=483,24
|
||||
Size=1604,32
|
||||
Size=964,32
|
||||
Collapsed=0
|
||||
DockId=0x00000001,0
|
||||
|
||||
[Window][Console]
|
||||
Pos=483,707
|
||||
Size=964,373
|
||||
Collapsed=0
|
||||
DockId=0x0000000C,2
|
||||
|
||||
[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=0x00000003 Parent=0x00000007 SizeRef=481,1542 Split=Y Selected=0x5D711C2C
|
||||
DockNode ID=0x00000005 Parent=0x00000003 SizeRef=481,817 Selected=0x5D711C2C
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Editor/library/mono/lib/mono/4.5/Facades/System.AppContext.dll
Normal file
BIN
Editor/library/mono/lib/mono/4.5/Facades/System.AppContext.dll
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Editor/library/mono/lib/mono/4.5/Facades/System.Collections.dll
Normal file
BIN
Editor/library/mono/lib/mono/4.5/Facades/System.Collections.dll
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Editor/library/mono/lib/mono/4.5/Facades/System.Console.dll
Normal file
BIN
Editor/library/mono/lib/mono/4.5/Facades/System.Console.dll
Normal file
Binary file not shown.
BIN
Editor/library/mono/lib/mono/4.5/Facades/System.Data.Common.dll
Normal file
BIN
Editor/library/mono/lib/mono/4.5/Facades/System.Data.Common.dll
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Editor/library/mono/lib/mono/4.5/Facades/System.IO.Pipes.dll
Normal file
BIN
Editor/library/mono/lib/mono/4.5/Facades/System.IO.Pipes.dll
Normal file
Binary file not shown.
Binary file not shown.
BIN
Editor/library/mono/lib/mono/4.5/Facades/System.IO.dll
Normal file
BIN
Editor/library/mono/lib/mono/4.5/Facades/System.IO.dll
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Editor/library/mono/lib/mono/4.5/Facades/System.Linq.dll
Normal file
BIN
Editor/library/mono/lib/mono/4.5/Facades/System.Linq.dll
Normal file
Binary file not shown.
Binary file not shown.
BIN
Editor/library/mono/lib/mono/4.5/Facades/System.Net.Cache.dll
Normal file
BIN
Editor/library/mono/lib/mono/4.5/Facades/System.Net.Cache.dll
Normal file
Binary file not shown.
BIN
Editor/library/mono/lib/mono/4.5/Facades/System.Net.Http.Rtc.dll
Normal file
BIN
Editor/library/mono/lib/mono/4.5/Facades/System.Net.Http.Rtc.dll
Normal file
Binary file not shown.
Binary file not shown.
BIN
Editor/library/mono/lib/mono/4.5/Facades/System.Net.Mail.dll
Normal file
BIN
Editor/library/mono/lib/mono/4.5/Facades/System.Net.Mail.dll
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Editor/library/mono/lib/mono/4.5/Facades/System.Net.Ping.dll
Normal file
BIN
Editor/library/mono/lib/mono/4.5/Facades/System.Net.Ping.dll
Normal file
Binary file not shown.
Binary file not shown.
BIN
Editor/library/mono/lib/mono/4.5/Facades/System.Net.Requests.dll
Normal file
BIN
Editor/library/mono/lib/mono/4.5/Facades/System.Net.Requests.dll
Normal file
Binary file not shown.
BIN
Editor/library/mono/lib/mono/4.5/Facades/System.Net.Security.dll
Normal file
BIN
Editor/library/mono/lib/mono/4.5/Facades/System.Net.Security.dll
Normal file
Binary file not shown.
Binary file not shown.
BIN
Editor/library/mono/lib/mono/4.5/Facades/System.Net.Sockets.dll
Normal file
BIN
Editor/library/mono/lib/mono/4.5/Facades/System.Net.Sockets.dll
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Editor/library/mono/lib/mono/4.5/Facades/System.ObjectModel.dll
Normal file
BIN
Editor/library/mono/lib/mono/4.5/Facades/System.ObjectModel.dll
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Editor/library/mono/lib/mono/4.5/Facades/System.Reflection.dll
Normal file
BIN
Editor/library/mono/lib/mono/4.5/Facades/System.Reflection.dll
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user