diff options
| author | hachem <im@hachem.wtf> | 2025-08-14 01:24:24 +0200 |
|---|---|---|
| committer | hachem <im@hachem.wtf> | 2025-08-14 01:24:24 +0200 |
| commit | 4de723231b38d7c7e272e71b9580443874c278ab (patch) | |
| tree | c93be963476510b8af30ffb4af7d69d468926fe3 | |
| parent | 0d8b874c0048ca088bb9e353a5f7c62e1f8cd0e8 (diff) | |
feat: implement an ImGui layer
| -rw-r--r-- | .gitmodules | 4 | ||||
| -rw-r--r-- | README.md | 80 | ||||
| m--------- | ext/imgui | 0 | ||||
| -rw-r--r-- | imgui.ini | 17 | ||||
| -rw-r--r-- | premake5.lua | 52 | ||||
| -rw-r--r-- | src/core/application.cpp | 15 | ||||
| -rw-r--r-- | src/core/application.h | 1 | ||||
| -rw-r--r-- | src/core/state.h | 1 | ||||
| -rw-r--r-- | src/core/state_manager.cpp | 6 | ||||
| -rw-r--r-- | src/core/state_manager.h | 1 | ||||
| -rw-r--r-- | src/core/window.cpp | 62 | ||||
| -rw-r--r-- | src/core/window.h | 7 | ||||
| -rw-r--r-- | src/states/config_state.cpp | 12 | ||||
| -rw-r--r-- | src/states/config_state.h | 1 | ||||
| -rw-r--r-- | src/states/simulation_state.cpp | 311 | ||||
| -rw-r--r-- | src/states/simulation_state.h | 37 |
16 files changed, 261 insertions, 346 deletions
diff --git a/.gitmodules b/.gitmodules index 3167aa9..bd955cb 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,7 @@ [submodule "ext/glm"] path = ext/glm url = https://github.com/g-truc/glm.git +[submodule "ext/imgui"] + path = ext/imgui + url = https://github.com/ocornut/imgui.git + branch = docking @@ -1,2 +1,78 @@ -# 𝔇𝔬𝔫𝔲𝔱 -A realtime blackhole simulator and renderer written in C. +# Donut Engine + +A modern C++ game engine with OpenGL rendering and ImGUI integration. + +## Features + +- **OpenGL Rendering**: Modern OpenGL 4.6 with GLAD loader +- **GLFW Window Management**: Cross-platform window and input handling +- **ImGUI Integration**: Immediate mode GUI for debugging and configuration +- **State Management**: Flexible state system for different application modes +- **Event System**: Comprehensive event handling for input and window events + +## States + +The engine uses a state-based architecture with the following states: + +### Menu State +- Main menu interface +- Navigation to other states +- Application exit functionality + +### Config State +- Simulation configuration +- Parameter adjustment (simulation speed, particle count, gravity) +- Settings reset functionality + +### Simulation State +- Real-time simulation controls +- Performance monitoring (FPS, frame time) +- Debug information display +- Time scale adjustment + +## Controls + +- **Key 1**: Switch to Config State +- **Key 2**: Switch to Simulation State +- **Key 3**: Switch to Main Menu +- **Mouse**: Navigate ImGUI interfaces +- **ImGUI Buttons**: State switching and configuration + +## Building + +The project uses Premake5 for build configuration: + +```bash +# Generate Visual Studio 2022 project +premake5 vs2022 + +# Generate other build systems as needed +premake5 gmake2 +premake5 xcode4 +``` + +## Dependencies + +- **GLFW**: Window management and input handling +- **GLAD**: OpenGL function loading +- **ImGUI**: Immediate mode GUI +- **GLM**: Mathematics library +- **Premake5**: Build system generation + +## Architecture + +The engine follows a modular architecture: + +- **Core**: Application, Window, Event, State management +- **Platform**: Renderer API abstraction (OpenGL, Vulkan) +- **Rendering**: High-level rendering interface +- **States**: Application state implementations + +## ImGUI Integration + +ImGUI is fully integrated into the engine with: + +- Automatic initialization after OpenGL context setup +- Per-state UI rendering through `OnImUIRender()` virtual function +- Proper frame management and cleanup +- Support for docking and viewports diff --git a/ext/imgui b/ext/imgui new file mode 160000 +Subproject 1f7f1f54af38b0350d8c0008b096a9af6de299c diff --git a/imgui.ini b/imgui.ini new file mode 100644 index 0000000..c9d59c2 --- /dev/null +++ b/imgui.ini @@ -0,0 +1,17 @@ +[Window][Debug##Default] +Pos=60,60 +Size=400,400 +Collapsed=0 + +[Window][Configuration] +Pos=60,60 +Size=305,139 +Collapsed=0 + +[Window][Simulation Controls] +Pos=965,39 +Size=230,165 +Collapsed=0 + +[Docking][Data] + diff --git a/premake5.lua b/premake5.lua index 6f31afe..de1ebc2 100644 --- a/premake5.lua +++ b/premake5.lua @@ -24,9 +24,11 @@ workspace "Donut" outputdir = "%{cfg.buildcfg}-%{cfg.system}/%{prj.name}" IncludeDir = {} +IncludeDir["glm"] = "ext/glm" IncludeDir["glfw"] = "ext/glfw/include" IncludeDir["glad"] = "ext/glad/include" -IncludeDir["glm"] = "ext/glm" +IncludeDir["imgui"] = "ext/imgui" +IncludeDir["imgui_backends"] = "ext/imgui/backends" group "Dependencies" @@ -203,6 +205,44 @@ project "GLFW" optimize "speed" symbols "off" +project "ImGui" + kind "StaticLib" + language "C++" + staticruntime "on" + + targetdir ("bin/" .. outputdir) + objdir ("bin-int/" .. outputdir) + + files + { + "ext/imgui/imgui.cpp", + "ext/imgui/imgui_draw.cpp", + "ext/imgui/imgui_tables.cpp", + "ext/imgui/imgui_widgets.cpp", + "ext/imgui/imgui_demo.cpp" + } + + filter "system:windows" + systemversion "latest" + cppdialect "C++17" + + filter "system:linux" + pic "On" + systemversion "latest" + cppdialect "C++17" + + filter "configurations:Debug" + runtime "Debug" + symbols "on" + + filter "configurations:Release" + runtime "Release" + optimize "on" + + filter "configurations:Dist" + runtime "Release" + optimize "on" + symbols "off" group "" project "Donut" @@ -225,22 +265,28 @@ project "Donut" "ext/glm/glm/**.inl", "src/**.h", - "src/**.cpp" + "src/**.cpp", + + "ext/imgui/backends/imgui_impl_glfw.cpp", + "ext/imgui/backends/imgui_impl_opengl3.cpp" } includedirs { "src", + "%{IncludeDir.glm}", "%{IncludeDir.glfw}", "%{IncludeDir.glad}", - "%{IncludeDir.glm}" + "%{IncludeDir.imgui}", + "%{IncludeDir.imgui_backends}", } links { "GLFW", "GLAD", + "ImGui" } filter "system:windows" diff --git a/src/core/application.cpp b/src/core/application.cpp index f2284cd..0698ce3 100644 --- a/src/core/application.cpp +++ b/src/core/application.cpp @@ -2,8 +2,8 @@ #include "rendering/renderer.h" -#include "states/config_state.h" #include "states/simulation_state.h" +#include "states/config_state.h" #include <GLFW/glfw3.h> @@ -86,12 +86,6 @@ namespace Donut event.handled = true; return true; } - else if (e.get_key_code() == GLFW_KEY_3) - { - m_state_manager->switch_to_state("Menu"); - event.handled = true; - return true; - } return true; }); @@ -105,12 +99,13 @@ namespace Donut RendererAPI::set_api(RendererAPI::API::OpenGL); Renderer::init(); + m_window->init_im_gui(); Renderer::on_window_resize(1280, 720); RenderCommand::set_face_culling(false); m_state_manager = create_scope<StateManager>(); - m_state_manager->register_state("Config", create_scope<ConfigState>()); + m_state_manager->register_state("Config", create_scope<ConfigState>()); m_state_manager->register_state("Simulation", create_scope<SimulationState>()); m_state_manager->switch_to_state("Config"); } @@ -136,5 +131,9 @@ namespace Donut void Application::on_render() { m_state_manager->render(); + + m_window->begin_im_gui_frame(); + m_state_manager->on_im_ui_render(); + m_window->end_im_gui_frame(); } }; diff --git a/src/core/application.h b/src/core/application.h index 048503b..d0abac3 100644 --- a/src/core/application.h +++ b/src/core/application.h @@ -19,6 +19,7 @@ namespace Donut void close(); Window& get_window() { return *m_window; } + StateManager& get_state_manager() { return *m_state_manager; } static Application& get() { return *s_instance; } private: void on_init(); diff --git a/src/core/state.h b/src/core/state.h index f5d808a..f4fe9b3 100644 --- a/src/core/state.h +++ b/src/core/state.h @@ -13,6 +13,7 @@ namespace Donut virtual void on_exit() = 0; virtual void on_update(float delta_time) = 0; virtual void on_render() = 0; + virtual void on_im_ui_render() = 0; virtual void on_event(Event& event) = 0; }; }; diff --git a/src/core/state_manager.cpp b/src/core/state_manager.cpp index 728df15..5086ddd 100644 --- a/src/core/state_manager.cpp +++ b/src/core/state_manager.cpp @@ -74,6 +74,12 @@ namespace Donut m_current_state->on_render(); } + void StateManager::on_im_ui_render() + { + if (m_current_state) + m_current_state->on_im_ui_render(); + } + void StateManager::on_event(Event& event) { if (m_current_state) diff --git a/src/core/state_manager.h b/src/core/state_manager.h index 469c48f..584df11 100644 --- a/src/core/state_manager.h +++ b/src/core/state_manager.h @@ -16,6 +16,7 @@ namespace Donut void update(float delta_time); void render(); + void on_im_ui_render(); void on_event(Event& event); void register_state(const std::string& state_name, Scope<State> state); diff --git a/src/core/window.cpp b/src/core/window.cpp index f598357..df19b86 100644 --- a/src/core/window.cpp +++ b/src/core/window.cpp @@ -2,6 +2,10 @@ #include <cstdint> +#include <imgui.h> +#include <imgui_impl_glfw.h> +#include <imgui_impl_opengl3.h> + namespace Donut { static bool s_glfw_initialized = false; @@ -66,6 +70,9 @@ namespace Donut void Window::shutdown() { DONUT_INFO("Shutting down window: ", m_title); + + shutdown_im_gui(); + glfwDestroyWindow(m_window); s_glfw_window_count--; @@ -102,6 +109,61 @@ namespace Donut GLFW_CURSOR_NORMAL : GLFW_CURSOR_HIDDEN); } + void Window::init_im_gui() + { + IMGUI_CHECKVERSION(); + ImGui::CreateContext(); + ImGuiIO& io = ImGui::GetIO(); + io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; + io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; + io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; + + ImGui::StyleColorsDark(); + + ImGuiStyle& style = ImGui::GetStyle(); + if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) + { + style.WindowRounding = 0.0f; + style.Colors[ImGuiCol_WindowBg].w = 1.0f; + } + + ImGui_ImplGlfw_InitForOpenGL(m_window, true); + ImGui_ImplOpenGL3_Init("#version 130"); + + DONUT_INFO("ImGUI initialized successfully"); + } + + void Window::shutdown_im_gui() + { + ImGui_ImplOpenGL3_Shutdown(); + ImGui_ImplGlfw_Shutdown(); + ImGui::DestroyContext(); + + DONUT_INFO("ImGUI shutdown"); + } + + void Window::begin_im_gui_frame() + { + ImGui_ImplOpenGL3_NewFrame(); + ImGui_ImplGlfw_NewFrame(); + ImGui::NewFrame(); + } + + void Window::end_im_gui_frame() + { + ImGui::Render(); + ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); + + ImGuiIO& io = ImGui::GetIO(); + if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) + { + GLFWwindow* backup_current_context = glfwGetCurrentContext(); + ImGui::UpdatePlatformWindows(); + ImGui::RenderPlatformWindowsDefault(); + glfwMakeContextCurrent(backup_current_context); + } + } + void Window::glfw_error_callback(int error, const char* description) { DONUT_ERROR("GLFW Error (", error, "): ", description); diff --git a/src/core/window.h b/src/core/window.h index 256f708..96678f8 100644 --- a/src/core/window.h +++ b/src/core/window.h @@ -35,10 +35,15 @@ namespace Donut void set_cursor_visible(bool visible); bool is_cursor_locked() const { return m_cursor_locked; } bool is_cursor_visible() const { return m_cursor_visible; } + + void init_im_gui(); + void begin_im_gui_frame(); + void end_im_gui_frame(); private: void init(); void shutdown(); - + void shutdown_im_gui(); + static void glfw_error_callback(int error, const char* description); static void glfw_window_close_callback(GLFWwindow* window); static void glfw_window_size_callback(GLFWwindow* window, int width, int height); diff --git a/src/states/config_state.cpp b/src/states/config_state.cpp index 8ea33ca..9d0e626 100644 --- a/src/states/config_state.cpp +++ b/src/states/config_state.cpp @@ -1,5 +1,8 @@ #include "config_state.h" #include "rendering/renderer.h" +#include "core/application.h" + +#include <imgui.h> namespace Donut { @@ -26,4 +29,13 @@ namespace Donut void ConfigState::on_event(Event& event) { } + + void ConfigState::on_im_ui_render() + { + ImGui::Begin("Configuration"); + ImGui::Text("Configuration State"); + if (ImGui::Button("Start Simulation")) + Application::get().get_state_manager().switch_to_state("Simulation"); + ImGui::End(); + } } diff --git a/src/states/config_state.h b/src/states/config_state.h index 35a3001..15aff5c 100644 --- a/src/states/config_state.h +++ b/src/states/config_state.h @@ -16,6 +16,7 @@ namespace Donut void on_exit() override; void on_update(float delta_time) override; void on_render() override; + void on_im_ui_render() override; void on_event(Event& event) override; }; }; diff --git a/src/states/simulation_state.cpp b/src/states/simulation_state.cpp index 6a832cd..7e9cb76 100644 --- a/src/states/simulation_state.cpp +++ b/src/states/simulation_state.cpp @@ -1,330 +1,49 @@ #include "simulation_state.h" #include "rendering/renderer.h" -#include "rendering/vertex_array.h" -#include "rendering/vertex_buffer.h" -#include "rendering/index_buffer.h" -#include "rendering/shader.h" -#include "rendering/texture.h" +#include "core/application.h" -#include <glm/glm.hpp> -#include <glm/gtc/matrix_transform.hpp> -#include <GLFW/glfw3.h> +#include <imgui.h> namespace Donut { void SimulationState::on_enter() { - m_camera = create_scope<Camera>(45.0f, 1280.0f / 720.0f, 0.1f, 100.0f); - m_camera->set_position({ 0.0f, 0.0f, 3.0f }); - m_camera->set_mouse_sensitivity(0.1f); - m_camera->set_movement_speed(5.0f); - - float vertices[] = - { - -0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, - -0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, - -0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 1.0f, - -0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f - }; - - uint32_t indices[] = - { - 0, 1, 2, 2, 3, 0, - 1, 5, 6, 6, 2, 1, - 5, 4, 7, 7, 6, 5, - 4, 0, 3, 3, 7, 4, - 3, 2, 6, 6, 7, 3, - 4, 5, 1, 1, 0, 4 - }; - - m_vertex_array = Ref<VertexArray>(VertexArray::create()); - m_vertex_buffer = Ref<VertexBuffer>(VertexBuffer::create(vertices, sizeof(vertices))); - - VertexBufferLayout layout; - layout.push<float>(3); - layout.push<float>(4); - layout.push<float>(2); - m_vertex_buffer->set_layout(layout); - - m_vertex_array->add_vertex_buffer(m_vertex_buffer); - - m_index_buffer = Ref<IndexBuffer>(IndexBuffer::create(indices, 36)); - m_vertex_array->set_index_buffer(m_index_buffer); - - m_shader = Ref<Shader>(Shader::create("assets/textured.glsl")); - m_texture = Texture2D::create(256, 256); - - uint32_t* pixel_data = new uint32_t[256 * 256]; - for (int y = 0; y < 256; y++) - { - for (int x = 0; x < 256; x++) - { - float u = (float)x / 256.0f; - float v = (float)y / 256.0f; - - float wave = sin(u * 10.0f) * cos(v * 10.0f); - wave = (wave + 1.0f) * 0.5f; - - uint8_t r = (uint8_t)(wave * 255); - uint8_t g = (uint8_t)((1.0f - wave) * 255); - uint8_t b = (uint8_t)((u + v) * 0.5f * 255); - uint8_t a = 255; - - pixel_data[y * 256 + x] = (a << 24) | (b << 16) | (g << 8) | r; - } - } - - m_texture->set_data(pixel_data, 256 * 256 * 4); - delete[] pixel_data; - - m_compute_shader = Ref<Shader>(Shader::create("assets/texture_processor.glsl")); - - if (!m_compute_shader) - { - DONUT_WARN("Failed to create compute shader! Falling back to CPU texture generation."); - m_use_compute_shader = false; - } - else - DONUT_INFO("Compute shader created successfully!"); - - m_processed_texture = Texture2D::create(256, 256); + DONUT_INFO("Entering Simulation State"); } void SimulationState::on_exit() { + DONUT_INFO("Exiting Simulation State"); } void SimulationState::on_update(float delta_time) { - m_delta_time = delta_time; - handle_key_input(delta_time); - update_texture(); } void SimulationState::on_render() { Renderer::set_clear_color({ 0.0f, 0.0f, 0.0f, 1.0f }); Renderer::clear(); - - if (m_use_compute_shader && m_processed_texture) - { - m_processed_texture->bind(0); - m_shader->set_int("u_Texture", 0); - } - else if (m_texture) - { - m_texture->bind(0); - m_shader->set_int("u_Texture", 0); - } - - glm::mat4 view_projection = m_camera ? m_camera->get_view_projection_matrix() : glm::mat4(1.0f); - - glm::vec3 center_pos(0.0f, 0.0f, 0.0f); - glm::vec3 right_pos(2.0f, 0.0f, 0.0f); - glm::vec3 left_pos(-2.0f, 0.0f, 0.0f); - glm::vec3 up_pos(0.0f, 2.0f, 0.0f); - glm::vec3 down_pos(0.0f, -2.0f, 0.0f); - glm::vec3 forward_pos(0.0f, 0.0f, 2.0f); - glm::vec3 back_pos(0.0f, 0.0f, -2.0f); - - glm::mat4 transform = glm::translate(glm::mat4(1.0f), center_pos); - Renderer::submit(m_shader, m_vertex_array, transform, view_projection); - transform = glm::translate(glm::mat4(1.0f), right_pos); - Renderer::submit(m_shader, m_vertex_array, transform, view_projection); - transform = glm::translate(glm::mat4(1.0f), left_pos); - Renderer::submit(m_shader, m_vertex_array, transform, view_projection); - transform = glm::translate(glm::mat4(1.0f), up_pos); - Renderer::submit(m_shader, m_vertex_array, transform, view_projection); - transform = glm::translate(glm::mat4(1.0f), down_pos); - Renderer::submit(m_shader, m_vertex_array, transform, view_projection); - transform = glm::translate(glm::mat4(1.0f), forward_pos); - Renderer::submit(m_shader, m_vertex_array, transform, view_projection); - transform = glm::translate(glm::mat4(1.0f), back_pos); - Renderer::submit(m_shader, m_vertex_array, transform, view_projection); } void SimulationState::on_event(Event& event) { - EventDispatcher dispatcher(event); - - dispatcher.dispatch<WindowResizeEvent>([this](WindowResizeEvent& e) - { - if (m_camera) - m_camera->set_projection(45.0f, (float)e.get_width() / (float)e.get_height(), 0.1f, 100.0f); - return true; - }); - - dispatcher.dispatch<WindowFocusEvent>([this](WindowFocusEvent& e) - { - m_first_mouse = true; - m_mouse_dragging = false; - return true; - }); - - dispatcher.dispatch<WindowLostFocusEvent>([this](WindowLostFocusEvent& e) - { - m_mouse_dragging = false; - return true; - }); - - dispatcher.dispatch<KeyPressedEvent>([this](KeyPressedEvent& e) - { - m_keys[e.get_key_code()] = true; - return true; - }); - - dispatcher.dispatch<KeyReleasedEvent>([this](KeyReleasedEvent& e) - { - m_keys[e.get_key_code()] = false; - return true; - }); - - dispatcher.dispatch<MouseMovedEvent>([this](MouseMovedEvent& e) - { - if (!m_mouse_dragging) - return true; - - if (m_first_mouse) - { - m_last_x = e.get_x(); - m_last_y = e.get_y(); - m_first_mouse = false; - } - - float x_offset = m_last_x - e.get_x(); - float y_offset = e.get_y() - m_last_y; - - m_last_x = e.get_x(); - m_last_y = e.get_y(); - - if (m_camera) - m_camera->on_mouse_move(x_offset, y_offset); - - return true; - }); - - dispatcher.dispatch<MouseButtonPressedEvent>([this](MouseButtonPressedEvent& e) - { - if (e.get_mouse_button() == GLFW_MOUSE_BUTTON_LEFT) - { - m_mouse_dragging = true; - m_first_mouse = true; - } - return true; - }); - - dispatcher.dispatch<MouseButtonReleasedEvent>([this](MouseButtonReleasedEvent& e) - { - if (e.get_mouse_button() == GLFW_MOUSE_BUTTON_LEFT) - m_mouse_dragging = false; - return true; - }); } - void SimulationState::handle_key_input(float delta_time) + void SimulationState::on_im_ui_render() { - if (m_camera) - { - if (m_keys[GLFW_KEY_W]) - m_camera->move_forward(delta_time); - if (m_keys[GLFW_KEY_S]) - m_camera->move_backward(delta_time); - if (m_keys[GLFW_KEY_A]) - m_camera->move_left(delta_time); - if (m_keys[GLFW_KEY_D]) - m_camera->move_right(delta_time); - if (m_keys[GLFW_KEY_SPACE]) - m_camera->move_up(delta_time); - if (m_keys[GLFW_KEY_LEFT_SHIFT]) - m_camera->move_down(delta_time); - } - - static bool c_key_pressed = false; - if (m_keys[GLFW_KEY_C] && !c_key_pressed) - { - m_use_compute_shader = !m_use_compute_shader; - DONUT_INFO("Compute shader: {}", (m_use_compute_shader ? "ON" : "OFF")); - c_key_pressed = true; - } - if (!m_keys[GLFW_KEY_C]) - c_key_pressed = false; - if (m_keys[GLFW_KEY_UP]) - m_compute_brightness += delta_time * 0.5f; - if (m_keys[GLFW_KEY_DOWN]) - m_compute_brightness -= delta_time * 0.5f; - if (m_keys[GLFW_KEY_LEFT]) - m_compute_contrast -= delta_time * 0.5f; - if (m_keys[GLFW_KEY_RIGHT]) - m_compute_contrast += delta_time * 0.5f; - if (m_keys[GLFW_KEY_Q]) - m_compute_saturation -= delta_time * 0.5f; - if (m_keys[GLFW_KEY_E]) - m_compute_saturation += delta_time * 0.5f; + ImGui::Begin("Simulation Controls"); - m_compute_brightness = glm::clamp(m_compute_brightness, -1.0f, 1.0f); - m_compute_contrast = glm::clamp(m_compute_contrast, 0.1f, 3.0f); - m_compute_saturation = glm::clamp(m_compute_saturation, 0.0f, 2.0f); + ImGui::Text("Simulation State"); + if (ImGui::Button("Back to Config")) + Application::get().get_state_manager().switch_to_state("Config"); + + ImGui::Separator(); - static float status_timer = 0.0f; - status_timer += delta_time; - if (status_timer > 2.0f) - { - DONUT_INFO("Compute Shader Status:\nBrightness: {}\nContrast: {}\nSaturation: {}", - m_compute_brightness, m_compute_contrast, m_compute_saturation); - status_timer = 0.0f; - } - } - - void SimulationState::update_texture() - { - if (!m_texture) - return; - - m_texture_time += m_delta_time; + ImGui::Text("Simulation Info:"); + ImGui::Text("FPS: %.1f", ImGui::GetIO().Framerate); + ImGui::Text("Frame Time: %.3f ms", 1000.0f / ImGui::GetIO().Framerate); - if (m_use_compute_shader && m_compute_shader && m_processed_texture) - { - m_compute_shader->bind(); - m_texture->bind(0); - m_compute_shader->set_int("u_InputTexture", 0); - m_processed_texture->bind_as_image(1, false); - m_compute_shader->set_float2("u_TextureSize", glm::vec2(256.0f, 256.0f)); - m_compute_shader->set_float("u_Time", m_texture_time); - m_compute_shader->set_float("u_Brightness", m_compute_brightness); - m_compute_shader->set_float("u_Contrast", m_compute_contrast); - m_compute_shader->set_float("u_Saturation", m_compute_saturation); - m_compute_shader->dispatch(16, 16, 1); - m_compute_shader->memory_barrier(IMAGE_ACCESS_BARRIER_BIT); - } - else - { - uint32_t* pixel_data = new uint32_t[256 * 256]; - for (int y = 0; y < 256; y++) - { - for (int x = 0; x < 256; x++) - { - float time = m_texture_time * 2.0f; - float u = (float)x / 256.0f; - float v = (float)y / 256.0f; - - float wave = sin(u * 10.0f + time) * cos(v * 10.0f + time * 0.5f); - wave = (wave + 1.0f) * 0.5f; - - uint8_t r = (uint8_t)(wave * 255); - uint8_t g = (uint8_t)((1.0f - wave) * 255); - uint8_t b = (uint8_t)((u + v) * 0.5f * 255); - uint8_t a = 255; - - pixel_data[y * 256 + x] = (a << 24) | (b << 16) | (g << 8) | r; - } - } - - m_texture->set_data(pixel_data, 256 * 256 * 4); - delete[] pixel_data; - } + ImGui::End(); } }; diff --git a/src/states/simulation_state.h b/src/states/simulation_state.h index 051edf3..4bb1c1b 100644 --- a/src/states/simulation_state.h +++ b/src/states/simulation_state.h @@ -1,17 +1,9 @@ #pragma once -#include "core/memory.h" #include "core/state.h" #include "core/event.h" -#include "core/camera.h" #include "core/log.h" -#include "rendering/vertex_array.h" -#include "rendering/vertex_buffer.h" -#include "rendering/index_buffer.h" -#include "rendering/shader.h" -#include "rendering/texture.h" - namespace Donut { class SimulationState @@ -24,34 +16,7 @@ namespace Donut void on_exit() override; void on_update(float delta_time) override; void on_render() override; + void on_im_ui_render() override; void on_event(Event& event) override; - private: - void handle_key_input(float delta_time); - void update_texture(); - private: - Scope<Camera> m_camera; - - Ref<VertexArray> m_vertex_array; - Ref<VertexBuffer> m_vertex_buffer; - Ref<IndexBuffer> m_index_buffer; - Ref<Shader> m_shader; - Ref<Texture2D> m_texture; - - Ref<Shader> m_compute_shader; - Ref<Texture2D> m_processed_texture; - - float m_compute_brightness = 0.0f; - float m_compute_contrast = 1.0f; - float m_compute_saturation = 1.0f; - bool m_use_compute_shader = true; - - bool m_keys[1024] = { false }; - bool m_first_mouse = true; - float m_last_x = 0.0f; - float m_last_y = 0.0f; - float m_delta_time = 0.0f; - float m_last_frame = 0.0f; - bool m_mouse_dragging = false; - float m_texture_time = 0.0f; }; }; |
