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 | 613f99e937e55f73dcec1251fdce4a9fda077a0f (patch) | |
| tree | b86ed54045783b47a0f856476a6465d3777b7005 | |
| parent | e050dce79b67ae6386240567a994454711ab998d (diff) | |
[add]: implement an ImGUI layer
| -rw-r--r-- | .gitmodules | 4 | ||||
| -rw-r--r-- | README.md | 80 | ||||
| m--------- | Vendor/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/StateManager.cpp | 6 | ||||
| -rw-r--r-- | src/Core/StateManager.h | 1 | ||||
| -rw-r--r-- | src/Core/Window.cpp | 62 | ||||
| -rw-r--r-- | src/Core/Window.h | 7 | ||||
| -rw-r--r-- | src/States/ConfigState.cpp | 12 | ||||
| -rw-r--r-- | src/States/ConfigState.h | 1 | ||||
| -rw-r--r-- | src/States/SimulationState.cpp | 311 | ||||
| -rw-r--r-- | src/States/SimulationState.h | 37 |
16 files changed, 261 insertions, 346 deletions
diff --git a/.gitmodules b/.gitmodules index aaa1cbc..b05f8e5 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,7 @@ [submodule "Vendor/glm"] path = Vendor/glm url = https://github.com/g-truc/glm.git +[submodule "Vendor/imgui"] + path = Vendor/imgui + url = https://github.com/ocornut/imgui.git + branch = docking @@ -1,2 +1,78 @@ -# 𝔇𝔬𝔫𝔲𝔱 -A realtime blackhole simulator and renderer written in C.
\ No newline at end of file +# 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
\ No newline at end of file diff --git a/Vendor/imgui b/Vendor/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 3c0ece6..b76f1f4 100644 --- a/premake5.lua +++ b/premake5.lua @@ -24,9 +24,11 @@ workspace "Donut" outputdir = "%{cfg.buildcfg}-%{cfg.system}/%{prj.name}" IncludeDir = {} +IncludeDir["glm"] = "Vendor/glm" IncludeDir["glfw"] = "Vendor/glfw/include" IncludeDir["glad"] = "Vendor/glad/include" -IncludeDir["glm"] = "Vendor/glm" +IncludeDir["imgui"] = "Vendor/imgui" +IncludeDir["imgui_backends"] = "Vendor/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 + { + "Vendor/imgui/imgui.cpp", + "Vendor/imgui/imgui_draw.cpp", + "Vendor/imgui/imgui_tables.cpp", + "Vendor/imgui/imgui_widgets.cpp", + "Vendor/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" "Vendor/glm/glm/**.inl", "src/**.h", - "src/**.cpp" + "src/**.cpp", + + "Vendor/imgui/backends/imgui_impl_glfw.cpp", + "Vendor/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 a886327..9aac646 100644 --- a/src/Core/Application.cpp +++ b/src/Core/Application.cpp @@ -2,8 +2,8 @@ #include "Rendering/Renderer.h" -#include "States/ConfigState.h" #include "States/SimulationState.h" +#include "States/ConfigState.h" #include <GLFW/glfw3.h> @@ -86,12 +86,6 @@ namespace Donut event.Handled = true; return true; } - else if (e.GetKeyCode() == GLFW_KEY_3) - { - m_StateManager->SwitchToState("Menu"); - event.Handled = true; - return true; - } return true; }); @@ -105,12 +99,13 @@ namespace Donut RendererAPI::SetAPI(RendererAPI::API::OpenGL); Renderer::Init(); + m_Window->InitImGui(); Renderer::OnWindowResize(1280, 720); RenderCommand::SetFaceCulling(false); m_StateManager = CreateScope<StateManager>(); - m_StateManager->RegisterState("Config", CreateScope<ConfigState>()); + m_StateManager->RegisterState("Config", CreateScope<ConfigState>()); m_StateManager->RegisterState("Simulation", CreateScope<SimulationState>()); m_StateManager->SwitchToState("Config"); } @@ -136,5 +131,9 @@ namespace Donut void Application::OnRender() { m_StateManager->Render(); + + m_Window->BeginImGuiFrame(); + m_StateManager->OnImUIRender(); + m_Window->EndImGuiFrame(); } }; diff --git a/src/Core/Application.h b/src/Core/Application.h index 3d0ba25..39d28bb 100644 --- a/src/Core/Application.h +++ b/src/Core/Application.h @@ -19,6 +19,7 @@ namespace Donut void Close(); Window& GetWindow() { return *m_Window; } + StateManager& GetStateManager() { return *m_StateManager; } static Application& Get() { return *s_Instance; } private: void OnInit(); diff --git a/src/Core/State.h b/src/Core/State.h index 2d368d7..cd1b7ee 100644 --- a/src/Core/State.h +++ b/src/Core/State.h @@ -13,6 +13,7 @@ namespace Donut virtual void OnExit() = 0; virtual void OnUpdate(float deltaTime) = 0; virtual void OnRender() = 0; + virtual void OnImUIRender() = 0; virtual void OnEvent(Event& event) = 0; }; };
\ No newline at end of file diff --git a/src/Core/StateManager.cpp b/src/Core/StateManager.cpp index 266bafa..e2aba02 100644 --- a/src/Core/StateManager.cpp +++ b/src/Core/StateManager.cpp @@ -74,6 +74,12 @@ namespace Donut m_CurrentState->OnRender(); } + void StateManager::OnImUIRender() + { + if (m_CurrentState) + m_CurrentState->OnImUIRender(); + } + void StateManager::OnEvent(Event& event) { if (m_CurrentState) diff --git a/src/Core/StateManager.h b/src/Core/StateManager.h index c0b2b13..4ffc86d 100644 --- a/src/Core/StateManager.h +++ b/src/Core/StateManager.h @@ -16,6 +16,7 @@ namespace Donut void Update(float deltaTime); void Render(); + void OnImUIRender(); void OnEvent(Event& event); void RegisterState(const std::string& stateName, Scope<State> state); diff --git a/src/Core/Window.cpp b/src/Core/Window.cpp index 73bd8db..d60ebc9 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_GLFWInitialized = false; @@ -66,6 +70,9 @@ namespace Donut void Window::Shutdown() { DONUT_INFO("Shutting down window: ", m_Title); + + ShutdownImGui(); + glfwDestroyWindow(m_Window); s_GLFWWindowCount--; @@ -102,6 +109,61 @@ namespace Donut GLFW_CURSOR_NORMAL : GLFW_CURSOR_HIDDEN); } + void Window::InitImGui() + { + 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::ShutdownImGui() + { + ImGui_ImplOpenGL3_Shutdown(); + ImGui_ImplGlfw_Shutdown(); + ImGui::DestroyContext(); + + DONUT_INFO("ImGUI shutdown"); + } + + void Window::BeginImGuiFrame() + { + ImGui_ImplOpenGL3_NewFrame(); + ImGui_ImplGlfw_NewFrame(); + ImGui::NewFrame(); + } + + void Window::EndImGuiFrame() + { + 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::GLFWErrorCallback(int error, const char* description) { DONUT_ERROR("GLFW Error (", error, "): ", description); diff --git a/src/Core/Window.h b/src/Core/Window.h index c598bf2..26df099 100644 --- a/src/Core/Window.h +++ b/src/Core/Window.h @@ -35,10 +35,15 @@ namespace Donut void SetCursorVisible(bool visible); bool IsCursorLocked() const { return m_CursorLocked; } bool IsCursorVisible() const { return m_CursorVisible; } + + void InitImGui(); + void BeginImGuiFrame(); + void EndImGuiFrame(); private: void Init(); void Shutdown(); - + void ShutdownImGui(); + static void GLFWErrorCallback(int error, const char* description); static void GLFWWindowCloseCallback(GLFWwindow* window); static void GLFWWindowSizeCallback(GLFWwindow* window, int width, int height); diff --git a/src/States/ConfigState.cpp b/src/States/ConfigState.cpp index 5d2e0aa..9f57840 100644 --- a/src/States/ConfigState.cpp +++ b/src/States/ConfigState.cpp @@ -1,5 +1,8 @@ #include "ConfigState.h" #include "Rendering/Renderer.h" +#include "Core/Application.h" + +#include <imgui.h> namespace Donut { @@ -26,4 +29,13 @@ namespace Donut void ConfigState::OnEvent(Event& event) { } + + void ConfigState::OnImUIRender() + { + ImGui::Begin("Configuration"); + ImGui::Text("Configuration State"); + if (ImGui::Button("Start Simulation")) + Application::Get().GetStateManager().SwitchToState("Simulation"); + ImGui::End(); + } } diff --git a/src/States/ConfigState.h b/src/States/ConfigState.h index 756e143..c54500c 100644 --- a/src/States/ConfigState.h +++ b/src/States/ConfigState.h @@ -16,6 +16,7 @@ namespace Donut void OnExit() override; void OnUpdate(float deltaTime) override; void OnRender() override; + void OnImUIRender() override; void OnEvent(Event& event) override; }; };
\ No newline at end of file diff --git a/src/States/SimulationState.cpp b/src/States/SimulationState.cpp index a37e527..349100c 100644 --- a/src/States/SimulationState.cpp +++ b/src/States/SimulationState.cpp @@ -1,330 +1,49 @@ #include "SimulationState.h" #include "Rendering/Renderer.h" -#include "Rendering/VertexArray.h" -#include "Rendering/VertexBuffer.h" -#include "Rendering/IndexBuffer.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::OnEnter() { - m_Camera = CreateScope<Camera>(45.0f, 1280.0f / 720.0f, 0.1f, 100.0f); - m_Camera->SetPosition({ 0.0f, 0.0f, 3.0f }); - m_Camera->SetMouseSensitivity(0.1f); - m_Camera->SetMovementSpeed(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_VertexArray = Ref<VertexArray>(VertexArray::Create()); - m_VertexBuffer = Ref<VertexBuffer>(VertexBuffer::Create(vertices, sizeof(vertices))); - - VertexBufferLayout layout; - layout.Push<float>(3); - layout.Push<float>(4); - layout.Push<float>(2); - m_VertexBuffer->SetLayout(layout); - - m_VertexArray->AddVertexBuffer(m_VertexBuffer); - - m_IndexBuffer = Ref<IndexBuffer>(IndexBuffer::Create(indices, 36)); - m_VertexArray->SetIndexBuffer(m_IndexBuffer); - - m_Shader = Ref<Shader>(Shader::Create("Assets/Textured.glsl")); - m_Texture = Texture2D::Create(256, 256); - - uint32_t* pixelData = 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; - - pixelData[y * 256 + x] = (a << 24) | (b << 16) | (g << 8) | r; - } - } - - m_Texture->SetData(pixelData, 256 * 256 * 4); - delete[] pixelData; - - m_ComputeShader = Ref<Shader>(Shader::Create("Assets/TextureProcessor.glsl")); - - if (!m_ComputeShader) - { - DONUT_WARN("Failed to create compute shader! Falling back to CPU texture generation."); - m_UseComputeShader = false; - } - else - DONUT_INFO("Compute shader created successfully!"); - - m_ProcessedTexture = Texture2D::Create(256, 256); + DONUT_INFO("Entering Simulation State"); } void SimulationState::OnExit() { + DONUT_INFO("Exiting Simulation State"); } void SimulationState::OnUpdate(float deltaTime) { - m_DeltaTime = deltaTime; - HandleKeyInput(deltaTime); - UpdateTexture(); } void SimulationState::OnRender() { Renderer::SetClearColor({ 0.0f, 0.0f, 0.0f, 1.0f }); Renderer::Clear(); - - if (m_UseComputeShader && m_ProcessedTexture) - { - m_ProcessedTexture->Bind(0); - m_Shader->SetInt("u_Texture", 0); - } - else if (m_Texture) - { - m_Texture->Bind(0); - m_Shader->SetInt("u_Texture", 0); - } - - glm::mat4 viewProjection = m_Camera ? m_Camera->GetViewProjectionMatrix() : glm::mat4(1.0f); - - glm::vec3 centerPos(0.0f, 0.0f, 0.0f); - glm::vec3 rightPos(2.0f, 0.0f, 0.0f); - glm::vec3 leftPos(-2.0f, 0.0f, 0.0f); - glm::vec3 upPos(0.0f, 2.0f, 0.0f); - glm::vec3 downPos(0.0f, -2.0f, 0.0f); - glm::vec3 forwardPos(0.0f, 0.0f, 2.0f); - glm::vec3 backPos(0.0f, 0.0f, -2.0f); - - glm::mat4 transform = glm::translate(glm::mat4(1.0f), centerPos); - Renderer::Submit(m_Shader, m_VertexArray, transform, viewProjection); - transform = glm::translate(glm::mat4(1.0f), rightPos); - Renderer::Submit(m_Shader, m_VertexArray, transform, viewProjection); - transform = glm::translate(glm::mat4(1.0f), leftPos); - Renderer::Submit(m_Shader, m_VertexArray, transform, viewProjection); - transform = glm::translate(glm::mat4(1.0f), upPos); - Renderer::Submit(m_Shader, m_VertexArray, transform, viewProjection); - transform = glm::translate(glm::mat4(1.0f), downPos); - Renderer::Submit(m_Shader, m_VertexArray, transform, viewProjection); - transform = glm::translate(glm::mat4(1.0f), forwardPos); - Renderer::Submit(m_Shader, m_VertexArray, transform, viewProjection); - transform = glm::translate(glm::mat4(1.0f), backPos); - Renderer::Submit(m_Shader, m_VertexArray, transform, viewProjection); } void SimulationState::OnEvent(Event& event) { - EventDispatcher dispatcher(event); - - dispatcher.Dispatch<WindowResizeEvent>([this](WindowResizeEvent& e) - { - if (m_Camera) - m_Camera->SetProjection(45.0f, (float)e.GetWidth() / (float)e.GetHeight(), 0.1f, 100.0f); - return true; - }); - - dispatcher.Dispatch<WindowFocusEvent>([this](WindowFocusEvent& e) - { - m_FirstMouse = true; - m_MouseDragging = false; - return true; - }); - - dispatcher.Dispatch<WindowLostFocusEvent>([this](WindowLostFocusEvent& e) - { - m_MouseDragging = false; - return true; - }); - - dispatcher.Dispatch<KeyPressedEvent>([this](KeyPressedEvent& e) - { - m_Keys[e.GetKeyCode()] = true; - return true; - }); - - dispatcher.Dispatch<KeyReleasedEvent>([this](KeyReleasedEvent& e) - { - m_Keys[e.GetKeyCode()] = false; - return true; - }); - - dispatcher.Dispatch<MouseMovedEvent>([this](MouseMovedEvent& e) - { - if (!m_MouseDragging) - return true; - - if (m_FirstMouse) - { - m_LastX = e.GetX(); - m_LastY = e.GetY(); - m_FirstMouse = false; - } - - float xOffset = m_LastX - e.GetX(); - float yOffset = e.GetY() - m_LastY; - - m_LastX = e.GetX(); - m_LastY = e.GetY(); - - if (m_Camera) - m_Camera->OnMouseMove(xOffset, yOffset); - - return true; - }); - - dispatcher.Dispatch<MouseButtonPressedEvent>([this](MouseButtonPressedEvent& e) - { - if (e.GetMouseButton() == GLFW_MOUSE_BUTTON_LEFT) - { - m_MouseDragging = true; - m_FirstMouse = true; - } - return true; - }); - - dispatcher.Dispatch<MouseButtonReleasedEvent>([this](MouseButtonReleasedEvent& e) - { - if (e.GetMouseButton() == GLFW_MOUSE_BUTTON_LEFT) - m_MouseDragging = false; - return true; - }); } - void SimulationState::HandleKeyInput(float deltaTime) + void SimulationState::OnImUIRender() { - if (m_Camera) - { - if (m_Keys[GLFW_KEY_W]) - m_Camera->MoveForward(deltaTime); - if (m_Keys[GLFW_KEY_S]) - m_Camera->MoveBackward(deltaTime); - if (m_Keys[GLFW_KEY_A]) - m_Camera->MoveLeft(deltaTime); - if (m_Keys[GLFW_KEY_D]) - m_Camera->MoveRight(deltaTime); - if (m_Keys[GLFW_KEY_SPACE]) - m_Camera->MoveUp(deltaTime); - if (m_Keys[GLFW_KEY_LEFT_SHIFT]) - m_Camera->MoveDown(deltaTime); - } - - static bool cKeyPressed = false; - if (m_Keys[GLFW_KEY_C] && !cKeyPressed) - { - m_UseComputeShader = !m_UseComputeShader; - DONUT_INFO("Compute shader: {}", (m_UseComputeShader ? "ON" : "OFF")); - cKeyPressed = true; - } - if (!m_Keys[GLFW_KEY_C]) - cKeyPressed = false; - if (m_Keys[GLFW_KEY_UP]) - m_ComputeBrightness += deltaTime * 0.5f; - if (m_Keys[GLFW_KEY_DOWN]) - m_ComputeBrightness -= deltaTime * 0.5f; - if (m_Keys[GLFW_KEY_LEFT]) - m_ComputeContrast -= deltaTime * 0.5f; - if (m_Keys[GLFW_KEY_RIGHT]) - m_ComputeContrast += deltaTime * 0.5f; - if (m_Keys[GLFW_KEY_Q]) - m_ComputeSaturation -= deltaTime * 0.5f; - if (m_Keys[GLFW_KEY_E]) - m_ComputeSaturation += deltaTime * 0.5f; + ImGui::Begin("Simulation Controls"); - m_ComputeBrightness = glm::clamp(m_ComputeBrightness, -1.0f, 1.0f); - m_ComputeContrast = glm::clamp(m_ComputeContrast, 0.1f, 3.0f); - m_ComputeSaturation = glm::clamp(m_ComputeSaturation, 0.0f, 2.0f); + ImGui::Text("Simulation State"); + if (ImGui::Button("Back to Config")) + Application::Get().GetStateManager().SwitchToState("Config"); + + ImGui::Separator(); - static float statusTimer = 0.0f; - statusTimer += deltaTime; - if (statusTimer > 2.0f) - { - DONUT_INFO("Compute Shader Status:\nBrightness: {}\nContrast: {}\nSaturation: {}", - m_ComputeBrightness, m_ComputeContrast, m_ComputeSaturation); - statusTimer = 0.0f; - } - } - - void SimulationState::UpdateTexture() - { - if (!m_Texture) - return; - - m_TextureTime += m_DeltaTime; + ImGui::Text("Simulation Info:"); + ImGui::Text("FPS: %.1f", ImGui::GetIO().Framerate); + ImGui::Text("Frame Time: %.3f ms", 1000.0f / ImGui::GetIO().Framerate); - if (m_UseComputeShader && m_ComputeShader && m_ProcessedTexture) - { - m_ComputeShader->Bind(); - m_Texture->Bind(0); - m_ComputeShader->SetInt("u_InputTexture", 0); - m_ProcessedTexture->BindAsImage(1, false); - m_ComputeShader->SetFloat2("u_TextureSize", glm::vec2(256.0f, 256.0f)); - m_ComputeShader->SetFloat("u_Time", m_TextureTime); - m_ComputeShader->SetFloat("u_Brightness", m_ComputeBrightness); - m_ComputeShader->SetFloat("u_Contrast", m_ComputeContrast); - m_ComputeShader->SetFloat("u_Saturation", m_ComputeSaturation); - m_ComputeShader->Dispatch(16, 16, 1); - m_ComputeShader->MemoryBarrier(IMAGE_ACCESS_BARRIER_BIT); - } - else - { - uint32_t* pixelData = new uint32_t[256 * 256]; - for (int y = 0; y < 256; y++) - { - for (int x = 0; x < 256; x++) - { - float time = m_TextureTime * 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; - - pixelData[y * 256 + x] = (a << 24) | (b << 16) | (g << 8) | r; - } - } - - m_Texture->SetData(pixelData, 256 * 256 * 4); - delete[] pixelData; - } + ImGui::End(); } }; diff --git a/src/States/SimulationState.h b/src/States/SimulationState.h index aa0b15b..3da7bd7 100644 --- a/src/States/SimulationState.h +++ b/src/States/SimulationState.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/VertexArray.h" -#include "Rendering/VertexBuffer.h" -#include "Rendering/IndexBuffer.h" -#include "Rendering/Shader.h" -#include "Rendering/Texture.h" - namespace Donut { class SimulationState @@ -24,34 +16,7 @@ namespace Donut void OnExit() override; void OnUpdate(float deltaTime) override; void OnRender() override; + void OnImUIRender() override; void OnEvent(Event& event) override; - private: - void HandleKeyInput(float deltaTime); - void UpdateTexture(); - private: - Scope<Camera> m_Camera; - - Ref<VertexArray> m_VertexArray; - Ref<VertexBuffer> m_VertexBuffer; - Ref<IndexBuffer> m_IndexBuffer; - Ref<Shader> m_Shader; - Ref<Texture2D> m_Texture; - - Ref<Shader> m_ComputeShader; - Ref<Texture2D> m_ProcessedTexture; - - float m_ComputeBrightness = 0.0f; - float m_ComputeContrast = 1.0f; - float m_ComputeSaturation = 1.0f; - bool m_UseComputeShader = true; - - bool m_Keys[1024] = { false }; - bool m_FirstMouse = true; - float m_LastX = 0.0f; - float m_LastY = 0.0f; - float m_DeltaTime = 0.0f; - float m_LastFrame = 0.0f; - bool m_MouseDragging = false; - float m_TextureTime = 0.0f; }; }; |
