From 0d819f2b9a71e862bce8799c6b0c1304e62219b3 Mon Sep 17 00:00:00 2001 From: hachem Date: Fri, 22 Aug 2025 12:24:05 +0200 Subject: [add]: add HDRI --- src/States/ConfigState.h | 1 - src/States/SimulationState.cpp | 39 ++++++++- src/States/WorldBuilderState.cpp | 173 ++++++++++++++++++++++++++++++++++++--- src/States/WorldBuilderState.h | 10 +++ 4 files changed, 209 insertions(+), 14 deletions(-) (limited to 'src/States') diff --git a/src/States/ConfigState.h b/src/States/ConfigState.h index baee8fa..ad7e238 100644 --- a/src/States/ConfigState.h +++ b/src/States/ConfigState.h @@ -42,7 +42,6 @@ namespace Donut bool m_ShowDebugInfo = false; bool m_EnableAntiAliasing = true; - // Theme settings int m_SelectedTheme = 0; // 0=Dark, 1=Light, 2=Blue }; }; \ No newline at end of file diff --git a/src/States/SimulationState.cpp b/src/States/SimulationState.cpp index 4d388fd..12c9397 100644 --- a/src/States/SimulationState.cpp +++ b/src/States/SimulationState.cpp @@ -1,6 +1,7 @@ #include "SimulationState.h" #include "Rendering/Renderer.h" #include "Core/Application.h" +#include "Core/HDRIManager.h" #include "Core/Window.h" #include "Core/Event.h" #include "Core/SettingsManager.h" @@ -10,6 +11,7 @@ #include #include #include +#include namespace Donut { @@ -27,7 +29,6 @@ namespace Donut engine.SetEarlyExitDistance(settings.simulation.earlyExitDistance); engine.GetGravity() = settings.simulation.gravityEnabled; - // Load accretion disk settings engine.SetDiskThickness(settings.simulation.diskThickness); engine.SetDiskDensity(settings.simulation.diskDensity); engine.SetRotationSpeed(settings.simulation.rotationSpeed); @@ -166,9 +167,7 @@ namespace Donut ImGui::Text("Objects: %zu", engine.GetObjects().size()); if (ImGui::Button("Print Object Info")) - { engine.PrintObjectInfo(); - } int computeHeight = engine.GetComputeHeight(); if (ImGui::SliderInt("Compute Height", &computeHeight, 64, 2048)) @@ -282,6 +281,40 @@ namespace Donut ImGui::Spacing(); + ImGui::TextColored(ImVec4(0.9f, 0.9f, 1.0f, 1.0f), "HDRI Environment"); + ImGui::Separator(); + + static int selectedHDRI = 0; + ImGui::PushID("SimulationHDRI"); + auto& hdriManager = HDRIManager::Get(); + const auto& availableHDRI = hdriManager.GetAvailableHDRI(); + + static std::vector hdriOptionNames; + static std::vector hdriOptions; + + if (hdriOptionNames.size() != availableHDRI.size()) + { + hdriOptionNames.clear(); + hdriOptions.clear(); + + for (const auto& path : availableHDRI) + { + hdriOptionNames.push_back(hdriManager.GetHDRIName(path)); + hdriOptions.push_back(hdriOptionNames.back().c_str()); + } + } + + if (ImGui::Combo("HDRI Environment", &selectedHDRI, hdriOptions.data(), static_cast(hdriOptions.size()))) + { + auto& hdriManager = HDRIManager::Get(); + hdriManager.SetCurrentHDRI(availableHDRI[selectedHDRI]); + engine.SetHDRIEnvironment(hdriManager.GetCurrentHDRI()); + } + ImGui::TextDisabled("HDRI provides background and lighting for the simulation"); + ImGui::PopID(); + + ImGui::Spacing(); + ImGui::TextColored(ImVec4(0.9f, 0.9f, 1.0f, 1.0f), "Camera"); ImGui::Separator(); diff --git a/src/States/WorldBuilderState.cpp b/src/States/WorldBuilderState.cpp index 70ef3d4..5a27ea1 100644 --- a/src/States/WorldBuilderState.cpp +++ b/src/States/WorldBuilderState.cpp @@ -2,6 +2,7 @@ #include "Core/Application.h" #include "Core/Window.h" +#include "Core/HDRIManager.h" #include "Rendering/Renderer.h" #include "Rendering/Shader.h" @@ -23,6 +24,7 @@ #include #include #include +#include namespace Donut { @@ -42,13 +44,29 @@ namespace Donut m_Camera.SetElevation(static_cast(std::numbers::pi) / 3.0f); m_Camera.UpdateOrbital(); - // Initialize rendering resources once m_SphereShader = Ref(Shader::Create("Assets/Shaders/Sphere.glsl")); + m_SkyboxShader = Ref(Shader::Create("Assets/Shaders/Skybox.glsl")); + + if (!m_SphereShader) + DONUT_ERROR("Failed to create sphere shader"); + if (!m_SkyboxShader) + DONUT_ERROR("Failed to create skybox shader"); + InitializeSphereGeometry(); + InitializeSkyboxGeometry(); + + auto& hdriManager = HDRIManager::Get(); + m_HDRIEnvironment = hdriManager.GetCurrentHDRI(); + if (!m_HDRIEnvironment) + { + hdriManager.SetCurrentHDRI("Assets/HDRI/HDR_blue_nebulae-1.hdr"); + m_HDRIEnvironment = hdriManager.GetCurrentHDRI(); + if (!m_HDRIEnvironment) + DONUT_WARN("Failed to load default HDRI for WorldBuilder, using fallback"); + } - // Initialize the black hole at the center - Material blackHoleMaterial(glm::vec3(0.0f, 0.0f, 0.0f), 0.0f, 0.0f); // Pure black, no specular, no emission - m_BlackHole = Object(glm::vec3(0.0f, 0.0f, 0.0f), 2.0f, blackHoleMaterial); // Position at origin, radius 2 + Material blackHoleMaterial(glm::vec3(0.0f, 0.0f, 0.0f), 0.0f, 0.0f); + m_BlackHole = Object(glm::vec3(0.0f, 0.0f, 0.0f), 2.0f, blackHoleMaterial); m_BlackHoleInitialized = true; m_Initialized = true; @@ -90,8 +108,15 @@ namespace Donut void WorldBuilderState::OnRender() { + auto& hdriManager = HDRIManager::Get(); + m_HDRIEnvironment = hdriManager.GetCurrentHDRI(); + RenderCommand::SetClearColor(glm::vec4(0.1f, 0.1f, 0.1f, 1.0f)); RenderCommand::Clear(); + + if (m_HDRIEnvironment) + RenderSkybox(); + RenderScene(); } @@ -347,7 +372,6 @@ namespace Donut ImGui::TextColored(ImVec4(0.9f, 0.9f, 1.0f, 1.0f), "New Sphere"); ImGui::Separator(); - // Show object count and limit ImGui::TextColored(ImVec4(0.8f, 0.8f, 0.8f, 1.0f), "Objects: %zu/16", m_Scene.objs.size()); ImGui::Text("Position:"); @@ -367,7 +391,6 @@ namespace Donut ImGui::Spacing(); - // Disable button if object limit reached if (m_Scene.objs.size() >= 16) { ImGui::PushStyleVar(ImGuiStyleVar_Alpha, 0.5f); @@ -468,6 +491,44 @@ namespace Donut ImGui::Spacing(); ImGui::TextColored(ImVec4(0.7f, 0.7f, 0.7f, 1.0f), "White rim around sphere silhouette"); } + + ImGui::Spacing(); + + if (ImGui::CollapsingHeader("HDRI Environment", nullptr)) + { + ImGui::TextColored(ImVec4(0.9f, 0.9f, 1.0f, 1.0f), "HDRI Settings:"); + + static int selectedHDRI = 0; + ImGui::PushID("WorldBuilderHDRI"); + auto& hdriManager = HDRIManager::Get(); + const auto& availableHDRI = hdriManager.GetAvailableHDRI(); + + static std::vector hdriOptionNames; + static std::vector hdriOptions; + + if (hdriOptionNames.size() != availableHDRI.size()) + { + hdriOptionNames.clear(); + hdriOptions.clear(); + + for (const auto& path : availableHDRI) + { + hdriOptionNames.push_back(hdriManager.GetHDRIName(path)); + hdriOptions.push_back(hdriOptionNames.back().c_str()); + } + } + + if (ImGui::Combo("HDRI Environment", &selectedHDRI, hdriOptions.data(), static_cast(hdriOptions.size()))) + { + auto& hdriManager = HDRIManager::Get(); + hdriManager.SetCurrentHDRI(availableHDRI[selectedHDRI]); + m_HDRIEnvironment = hdriManager.GetCurrentHDRI(); + } + + ImGui::Spacing(); + ImGui::TextColored(ImVec4(0.7f, 0.7f, 0.7f, 1.0f), "HDRI provides background skybox and lighting for the scene"); + ImGui::PopID(); + } ImGui::Spacing(); ImGui::Separator(); @@ -486,11 +547,8 @@ namespace Donut if (ImGui::Button("Start Simulation", ImVec2(ImGui::GetWindowWidth() - 20, 30))) { - // Load objects from WorldBuilder scene into Engine auto& engine = Application::Get().GetEngine(); engine.LoadObjectsFromScene(m_Scene.objs); - - // Switch to simulation state Application::Get().GetStateManager().SwitchToState("Simulation"); } @@ -551,7 +609,6 @@ namespace Donut void WorldBuilderState::AddSphere() { - // Check if we've reached the object limit (16 objects) if (m_Scene.objs.size() >= 16) { DONUT_WARN("Cannot add more objects. Maximum of 16 objects reached."); @@ -768,6 +825,12 @@ namespace Donut m_SphereShader->SetFloat3("u_OutlineColor", m_OutlineColor); m_SphereShader->SetFloat("u_OutlineWidth", m_OutlineWidth); + if (m_HDRIEnvironment) + { + m_HDRIEnvironment->Bind(1); + m_SphereShader->SetInt("u_HDRIEnvironment", 1); + } + if (m_BlackHoleInitialized) { glm::mat4 blackHoleTransform = glm::translate(glm::mat4(1.0f), m_BlackHole.m_Centre); @@ -818,4 +881,94 @@ namespace Donut RenderCommand::DisableDepthTest(); } + + + + void WorldBuilderState::InitializeSkyboxGeometry() + { + float skyboxVertices[] = + { + -1.0f, 1.0f, -1.0f, + -1.0f, -1.0f, -1.0f, + 1.0f, -1.0f, -1.0f, + 1.0f, -1.0f, -1.0f, + 1.0f, 1.0f, -1.0f, + -1.0f, 1.0f, -1.0f, + + -1.0f, -1.0f, 1.0f, + -1.0f, -1.0f, -1.0f, + -1.0f, 1.0f, -1.0f, + -1.0f, 1.0f, -1.0f, + -1.0f, 1.0f, 1.0f, + -1.0f, -1.0f, 1.0f, + + 1.0f, -1.0f, -1.0f, + 1.0f, -1.0f, 1.0f, + 1.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 1.0f, + 1.0f, 1.0f, -1.0f, + 1.0f, -1.0f, -1.0f, + + -1.0f, -1.0f, 1.0f, + -1.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 1.0f, + 1.0f, -1.0f, 1.0f, + -1.0f, -1.0f, 1.0f, + + -1.0f, 1.0f, -1.0f, + 1.0f, 1.0f, -1.0f, + 1.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 1.0f, + -1.0f, 1.0f, 1.0f, + -1.0f, 1.0f, -1.0f, + + -1.0f, -1.0f, -1.0f, + -1.0f, -1.0f, 1.0f, + 1.0f, -1.0f, -1.0f, + 1.0f, -1.0f, -1.0f, + -1.0f, -1.0f, 1.0f, + 1.0f, -1.0f, 1.0f + }; + + auto vertexBuffer = Ref(VertexBuffer::Create(skyboxVertices, sizeof(skyboxVertices))); + VertexBufferLayout layout; + layout.Push(3); + vertexBuffer->SetLayout(layout); + + m_SkyboxVAO = Ref(VertexArray::Create()); + m_SkyboxVAO->AddVertexBuffer(vertexBuffer); + } + + void WorldBuilderState::RenderSkybox() + { + if (!m_SkyboxShader || !m_SkyboxVAO || !m_HDRIEnvironment) + { + return; + } + + GLFWwindow* window = static_cast(Application::Get().GetWindow().GetNativeWindow()); + int width, height; + glfwGetFramebufferSize(window, &width, &height); + + RenderCommand::SetViewport(0, 0, width, height); + RenderCommand::DisableDepthTest(); + + glm::mat4 view = m_Camera.GetViewMatrix(); + glm::mat4 projection = m_Camera.GetProjectionMatrix(); + + view = glm::mat4(glm::mat3(view)); + + m_SkyboxShader->Bind(); + m_SkyboxShader->SetMat4("u_View", view); + m_SkyboxShader->SetMat4("u_Projection", projection); + + m_HDRIEnvironment->Bind(0); + m_SkyboxShader->SetInt("u_Skybox", 0); + + m_SkyboxVAO->Bind(); + RenderCommand::DrawArrays(36); + + RenderCommand::EnableDepthTest(); + } }; diff --git a/src/States/WorldBuilderState.h b/src/States/WorldBuilderState.h index cbe8b9e..29662db 100644 --- a/src/States/WorldBuilderState.h +++ b/src/States/WorldBuilderState.h @@ -47,6 +47,10 @@ namespace Donut Ref m_SphereShader; Ref m_SphereVAO; + Ref m_HDRIEnvironment; + + Ref m_SkyboxShader; + Ref m_SkyboxVAO; glm::vec3 m_NewObjectPosition = glm::vec3(0.0f, 0.0f, 0.0f); float m_NewObjectRadius = 1.0f; @@ -72,5 +76,11 @@ namespace Donut Object m_BlackHole; bool m_BlackHoleInitialized = false; + + void SetHDRIEnvironment(Ref hdri) { m_HDRIEnvironment = hdri; } + Ref GetHDRIEnvironment() const { return m_HDRIEnvironment; } + + void InitializeSkyboxGeometry(); + void RenderSkybox(); }; }; -- cgit v1.3