diff options
| author | hachem <im@hachem.wtf> | 2025-08-22 12:24:05 +0200 |
|---|---|---|
| committer | hachem <im@hachem.wtf> | 2025-08-22 12:24:05 +0200 |
| commit | 2c8002d30f291cba832a5750212009d48238c308 (patch) | |
| tree | 4aafc468441b3e32c267040830b8e0b5af859faf /src/states/world_builder_state.cpp | |
| parent | b9de06951631d9969c52c6ed95de17a6d8aad121 (diff) | |
feat: add HDRI
Diffstat (limited to 'src/states/world_builder_state.cpp')
| -rw-r--r-- | src/states/world_builder_state.cpp | 162 |
1 files changed, 161 insertions, 1 deletions
diff --git a/src/states/world_builder_state.cpp b/src/states/world_builder_state.cpp index f28f70a..c0999d4 100644 --- a/src/states/world_builder_state.cpp +++ b/src/states/world_builder_state.cpp @@ -2,6 +2,7 @@ #include "core/application.h" #include "core/window.h" +#include "core/hdri_manager.h" #include "rendering/renderer.h" #include "rendering/shader.h" @@ -23,6 +24,7 @@ #include <fstream> #include <sstream> #include <limits> +#include <vector> namespace Donut { @@ -43,7 +45,25 @@ namespace Donut m_camera.update_orbital(); m_sphere_shader = Ref<Shader>(Shader::create("assets/shaders/sphere.glsl")); + m_skybox_shader = Ref<Shader>(Shader::create("assets/shaders/skybox.glsl")); + + if (!m_sphere_shader) + DONUT_ERROR("Failed to create sphere shader"); + if (!m_skybox_shader) + DONUT_ERROR("Failed to create skybox shader"); + initialize_sphere_geometry(); + initialize_skybox_geometry(); + + auto& hdri_manager = HDRIManager::get(); + m_hdri_environment = hdri_manager.get_current_hdri(); + if (!m_hdri_environment) + { + hdri_manager.set_current_hdri("assets/hdri/hdr_blue_nebulae_1.hdr"); + m_hdri_environment = hdri_manager.get_current_hdri(); + if (!m_hdri_environment) + DONUT_WARN("Failed to load default HDRI for WorldBuilder, using fallback"); + } Material black_hole_material(glm::vec3(0.0f, 0.0f, 0.0f), 0.0f, 0.0f); m_black_hole = Object(glm::vec3(0.0f, 0.0f, 0.0f), 2.0f, black_hole_material); @@ -88,8 +108,15 @@ namespace Donut void WorldBuilderState::on_render() { + auto& hdri_manager = HDRIManager::get(); + m_hdri_environment = hdri_manager.get_current_hdri(); + RenderCommand::set_clear_color(glm::vec4(0.1f, 0.1f, 0.1f, 1.0f)); RenderCommand::clear(); + + if (m_hdri_environment) + render_skybox(); + render_scene(); } @@ -464,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 selected_hdri = 0; + ImGui::PushID("WorldBuilderHDRI"); + auto& hdri_manager = HDRIManager::get(); + const auto& available_hdri = hdri_manager.get_available_hdri(); + + static std::vector<std::string> hdri_option_names; + static std::vector<const char*> hdri_options; + + if (hdri_option_names.size() != available_hdri.size()) + { + hdri_option_names.clear(); + hdri_options.clear(); + + for (const auto& path : available_hdri) + { + hdri_option_names.push_back(hdri_manager.get_hdri_name(path)); + hdri_options.push_back(hdri_option_names.back().c_str()); + } + } + + if (ImGui::Combo("HDRI Environment", &selected_hdri, hdri_options.data(), static_cast<int>(hdri_options.size()))) + { + auto& hdri_manager = HDRIManager::get(); + hdri_manager.set_current_hdri(available_hdri[selected_hdri]); + m_hdri_environment = hdri_manager.get_current_hdri(); + } + + 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(); @@ -484,7 +549,6 @@ namespace Donut { auto& engine = Application::get().get_engine(); engine.load_objects_from_scene(m_scene.objs); - Application::get().get_state_manager().switch_to_state("Simulation"); } @@ -761,6 +825,12 @@ namespace Donut m_sphere_shader->set_float3("u_OutlineColor", m_outline_color); m_sphere_shader->set_float("u_OutlineWidth", m_outline_width); + if (m_hdri_environment) + { + m_hdri_environment->bind(1); + m_sphere_shader->set_int("u_HDRIEnvironment", 1); + } + if (m_black_hole_initialized) { glm::mat4 black_hole_transform = glm::translate(glm::mat4(1.0f), m_black_hole.m_centre); @@ -811,4 +881,94 @@ namespace Donut RenderCommand::disable_depth_test(); } + + + + void WorldBuilderState::initialize_skybox_geometry() + { + float skybox_vertices[] = + { + -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 vertex_buffer = Ref<VertexBuffer>(VertexBuffer::create(skybox_vertices, sizeof(skybox_vertices))); + VertexBufferLayout layout; + layout.push<float>(3); + vertex_buffer->set_layout(layout); + + m_skybox_vao = Ref<VertexArray>(VertexArray::create()); + m_skybox_vao->add_vertex_buffer(vertex_buffer); + } + + void WorldBuilderState::render_skybox() + { + if (!m_skybox_shader || !m_skybox_vao || !m_hdri_environment) + { + return; + } + + GLFWwindow* window = static_cast<GLFWwindow*>(Application::get().get_window().get_native_window()); + int width, height; + glfwGetFramebufferSize(window, &width, &height); + + RenderCommand::set_viewport(0, 0, width, height); + RenderCommand::disable_depth_test(); + + glm::mat4 view = m_camera.get_view_matrix(); + glm::mat4 projection = m_camera.get_projection_matrix(); + + view = glm::mat4(glm::mat3(view)); + + m_skybox_shader->bind(); + m_skybox_shader->set_mat4("u_View", view); + m_skybox_shader->set_mat4("u_Projection", projection); + + m_hdri_environment->bind(0); + m_skybox_shader->set_int("u_Skybox", 0); + + m_skybox_vao->bind(); + RenderCommand::draw_arrays(36); + + RenderCommand::enable_depth_test(); + } }; |
