diff --git a/.gitmodules b/.gitmodules index f99f17d6..079d9f2c 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "third-party/SDL"] path = third-party/SDL url = https://github.com/libsdl-org/SDL.git +[submodule "third-party/imgui"] + path = third-party/imgui + url = https://github.com/ocornut/imgui.git diff --git a/CMakeLists.txt b/CMakeLists.txt index 94bc8fbd..224f2049 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,6 +19,24 @@ add_library(${PROJECT_NAME} STATIC ${SOURCES} ${HEADERS}) add_library(glad STATIC third-party/glad/glad.c) +# ImGui setup +set(IMGUI_DIR ${CMAKE_CURRENT_SOURCE_DIR}/third-party/imgui) +add_library(imgui STATIC + ${IMGUI_DIR}/imgui.cpp + ${IMGUI_DIR}/imgui_draw.cpp + ${IMGUI_DIR}/imgui_tables.cpp + ${IMGUI_DIR}/imgui_widgets.cpp + ${IMGUI_DIR}/imgui_demo.cpp + ${IMGUI_DIR}/backends/imgui_impl_sdl3.cpp + ${IMGUI_DIR}/backends/imgui_impl_opengl3.cpp +) +target_include_directories(imgui + PUBLIC + ${IMGUI_DIR} + ${IMGUI_DIR}/backends + ${CMAKE_CURRENT_SOURCE_DIR}/third-party/SDL/include +) + target_include_directories(${PROJECT_NAME} PUBLIC $ @@ -73,6 +91,7 @@ target_include_directories(glad # handles their include paths and other properties for you. target_link_libraries(${PROJECT_NAME} PUBLIC glad) target_link_libraries(${PROJECT_NAME} PUBLIC SDL3::SDL3) +target_link_libraries(${PROJECT_NAME} PUBLIC imgui) # Shaders diff --git a/include/weird-engine.h b/include/weird-engine.h index 26cd0880..f57ea1f6 100644 --- a/include/weird-engine.h +++ b/include/weird-engine.h @@ -4,6 +4,11 @@ #define ENGINE_PATH "../weird-engine" #endif // !ENGINE_PATH +#include +#include +#include +#include + #include "weird-engine/Input.h" #include "weird-engine/Profiler.h" #include "weird-engine/SceneManager.h" @@ -79,6 +84,15 @@ namespace WeirdEngine // Capture window input Input::update(ctx.renderer.getWindow()); + // Suppress game input when ImGui has focus + { + const ImGuiIO& io = ImGui::GetIO(); + if (io.WantCaptureMouse) + Input::suppressMouseInput(); + if (io.WantCaptureKeyboard) + Input::suppressKeyboardInput(); + } + if (Input::GetKeyDown(Input::T)) { WeirdEngine::Profiler::Get().startRecording(); @@ -91,6 +105,8 @@ namespace WeirdEngine SDL_Event event; while (SDL_PollEvent(&event)) { + ImGui_ImplSDL3_ProcessEvent(&event); + if (event.type == SDL_EVENT_QUIT) { ctx.quit = true; diff --git a/include/weird-engine/Input.h b/include/weird-engine/Input.h index e82a3d83..7b986bc4 100644 --- a/include/weird-engine/Input.h +++ b/include/weird-engine/Input.h @@ -258,6 +258,32 @@ namespace WeirdEngine #pragma endregion + static void suppressMouseInput() + { + auto& instance = getInstance(); + for (int i = 0; i < 5; ++i) + { + if (instance.m_mouseKeysTable[i] > NOT_PRESSED) // IS_PRESSED or FIRST_PRESSED + instance.m_mouseKeysTable[i] = RELEASED_THIS_FRAME; // fire key-up + else if (instance.m_mouseKeysTable[i] == RELEASED_THIS_FRAME) + instance.m_mouseKeysTable[i] = NOT_PRESSED; // clear existing key-up + // NOT_PRESSED stays NOT_PRESSED — no spurious key-ups + } + } + + static void suppressKeyboardInput() + { + auto& instance = getInstance(); + for (int i = 0; i < SDL_SCANCODE_COUNT; ++i) + { + if (instance.m_keyTable[i] > NOT_PRESSED) // IS_PRESSED or FIRST_PRESSED + instance.m_keyTable[i] = RELEASED_THIS_FRAME; // fire key-up + else if (instance.m_keyTable[i] == RELEASED_THIS_FRAME) + instance.m_keyTable[i] = NOT_PRESSED; // clear existing key-up + // NOT_PRESSED stays NOT_PRESSED — no spurious key-ups + } + } + #pragma region Keyboard static bool GetKey(KeyCode key) diff --git a/include/weird-renderer/core/SDF2DRenderPipeline.h b/include/weird-renderer/core/SDF2DRenderPipeline.h index df0b59c1..9b3789b0 100644 --- a/include/weird-renderer/core/SDF2DRenderPipeline.h +++ b/include/weird-renderer/core/SDF2DRenderPipeline.h @@ -49,6 +49,7 @@ namespace WeirdEngine double delta, Texture* backgroundTexture = nullptr); void resize(unsigned int newWidth, unsigned int newHeight); void free(); + void handleDebugInputs(); private: Config m_config; @@ -124,8 +125,6 @@ namespace WeirdEngine void blendMaterials(double time); void renderBackground(const Camera& camera, double time); void applyLighting(const Camera& camera, double time, Texture* backgroundTexture); - void handleDebugInputs(); - static int largestPowerOfTwoBelow(int n); }; } // namespace WeirdRenderer diff --git a/include/weird-renderer/core/SDLInitializer.h b/include/weird-renderer/core/SDLInitializer.h index ad20de48..be75865c 100644 --- a/include/weird-renderer/core/SDLInitializer.h +++ b/include/weird-renderer/core/SDLInitializer.h @@ -1,8 +1,9 @@ #pragma once -#include "weird-renderer/audio/AudioEngine.h" #include +#include "weird-renderer/audio/AudioEngine.h" + namespace WeirdEngine { namespace WeirdRenderer diff --git a/src/weird-renderer/core/Renderer.cpp b/src/weird-renderer/core/Renderer.cpp index 5cc2f0e7..dffcc9c2 100644 --- a/src/weird-renderer/core/Renderer.cpp +++ b/src/weird-renderer/core/Renderer.cpp @@ -1,9 +1,14 @@ #include "weird-renderer/core/Renderer.h" -#include "weird-engine/Profiler.h" +#include + #include #include -#include +#include +#include +#include + +#include "weird-engine/Profiler.h" namespace WeirdEngine { @@ -117,6 +122,30 @@ namespace WeirdEngine auto& result = renderScene(scene, time, clampedDelta); output(scene, result, clampedDelta); + static bool showDebugUI = false; + + if(Input::GetKeyDown(Input::F3)) + { + showDebugUI = !showDebugUI; + } + + if(showDebugUI) + { + ImGui_ImplOpenGL3_NewFrame(); + ImGui_ImplSDL3_NewFrame(); + ImGui::NewFrame(); + + ImGui::Begin("Renderer Settings"); + m_worldPipeline->handleDebugInputs(); + m_uiPipeline->handleDebugInputs(); + ImGui::End(); + + ImGui::Render(); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + glViewport(0, 0, m_windowWidth, m_windowHeight); + ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); + } + { PROFILE_SCOPE("Synchronization"); SDL_GL_SwapWindow(m_window); diff --git a/src/weird-renderer/core/SDF2DRenderPipeline.cpp b/src/weird-renderer/core/SDF2DRenderPipeline.cpp index 011f8065..6417f331 100644 --- a/src/weird-renderer/core/SDF2DRenderPipeline.cpp +++ b/src/weird-renderer/core/SDF2DRenderPipeline.cpp @@ -1,7 +1,11 @@ #include "weird-renderer/core/SDF2DRenderPipeline.h" -#include "weird-engine/vec.h" + #include +#include + +#include "weird-engine/vec.h" + namespace WeirdEngine { namespace WeirdRenderer @@ -528,45 +532,62 @@ namespace WeirdEngine void SDF2DRenderPipeline::handleDebugInputs() { - // if (Input::GetKey(Input::LeftCtrl) && Input::GetKeyDown(Input::L)) - // { - // m_2DLightingShader.toggleDefine("SHADOWS_ENABLED"); - // } - // - // if (Input::GetKey(Input::LeftCtrl) && Input::GetKeyDown(Input::D)) - // { - // if (Input::GetKey(Input::LeftShift)) { - // m_finalUIShader.toggleDefine("DITHERING"); - // } else { - // m_finalUIShader.toggleDefine("DEBUG_SHOW_DISTANCE"); - // } - // } - // - // if (Input::GetKey(Input::LeftCtrl) && Input::GetKeyDown(Input::C)) - // { - // m_2DLightingShader.toggleDefine("DEBUG_SHOW_COLORS"); - // } - // - // if (Input::GetKey(Input::LeftCtrl) && Input::GetKeyDown(Input::A)) - // { - // m_2DLightingShader.toggleDefine("ANTIALIASING"); - // } - // - // if (Input::GetKey(Input::LeftCtrl) && Input::GetKeyDown(Input::B)) - // { - // m_2DDistanceShader.toggleDefine("BLEND_SHAPES"); - // } - // - // if (Input::GetKey(Input::LeftCtrl) && Input::GetKeyDown(Input::M)) - // { - // m_2DDistanceShader.toggleDefine("MOTION_BLUR"); - // m_uiDistanceShader.toggleDefine("MOTION_BLUR"); - // } - // - // if (Input::GetKey(Input::LeftCtrl) && Input::GetKeyDown(Input::F)) - // { - // USE_CORRECTED_DISTANCE_TEXTURE = !USE_CORRECTED_DISTANCE_TEXTURE; - // } + const char* label = m_config.isUI ? "UI Pipeline" : "World Pipeline"; + if (!ImGui::CollapsingHeader(label)) + return; + + ImGui::PushID(label); + + ImGui::SeparatorText("Shadows"); + if (ImGui::Checkbox("Shadows", &m_config.enableShadows)) + { + if (m_config.enableShadows) m_lightingShader.addDefine("SHADOWS_ENABLED"); + else m_lightingShader.removeDefine("SHADOWS_ENABLED"); + } + if (ImGui::Checkbox("Long Shadows", &m_config.enableLongShadows)) + { + if (m_config.enableLongShadows) m_lightingShader.addDefine("LONG_SHADOWS"); + else m_lightingShader.removeDefine("LONG_SHADOWS"); + } + + ImGui::SeparatorText("Rendering"); + if (ImGui::Checkbox("Antialiasing", &m_config.enableAntialiasing)) + { + if (m_config.enableAntialiasing) m_lightingShader.addDefine("ANTIALIASING"); + else m_lightingShader.removeDefine("ANTIALIASING"); + } + if (ImGui::Checkbox("Motion Blur", &m_config.enableMotionBlur)) + { + if (m_config.enableMotionBlur) m_distanceShader.addDefine("MOTION_BLUR"); + else m_distanceShader.removeDefine("MOTION_BLUR"); + } + if (ImGui::Checkbox("Refraction", &m_config.enableRefraction)) + { + if (m_config.enableRefraction) m_lightingShader.addDefine("REFRACTION"); + else m_lightingShader.removeDefine("REFRACTION"); + } + + ImGui::SeparatorText("Debug"); + if (ImGui::Checkbox("Show Distance Field", &m_config.debugDistanceField)) + { + if (m_config.debugDistanceField) m_lightingShader.addDefine("DEBUG_SHOW_DISTANCE"); + else m_lightingShader.removeDefine("DEBUG_SHOW_DISTANCE"); + } + if (ImGui::Checkbox("Show Material Colors", &m_config.debugMaterialColors)) + { + if (m_config.debugMaterialColors) m_lightingShader.addDefine("DEBUG_SHOW_COLORS"); + else m_lightingShader.removeDefine("DEBUG_SHOW_COLORS"); + } + + ImGui::SeparatorText("Ambient Occlusion"); + ImGui::SliderFloat("AO Radius", &m_config.ambienOcclusionRadius, 0.0f, 20.0f); + ImGui::SliderFloat("AO Strength", &m_config.ambienOcclusionStrength, 0.0f, 1.0f); + + ImGui::SeparatorText("Materials"); + ImGui::SliderFloat("Blend Speed", &m_config.materialBlendSpeed, 0.0f, 20.0f); + ImGui::SliderFloat("Smooth Factor (k)", &m_config.ballK, 0.0f, 50.0f); + + ImGui::PopID(); } Shader& SDF2DRenderPipeline::getDistanceShader() diff --git a/src/weird-renderer/core/SDLInitializer.cpp b/src/weird-renderer/core/SDLInitializer.cpp index 85aae15a..9a509a63 100644 --- a/src/weird-renderer/core/SDLInitializer.cpp +++ b/src/weird-renderer/core/SDLInitializer.cpp @@ -1,10 +1,14 @@ #include "weird-renderer/core/SDLInitializer.h" -#include "weird-renderer/audio/AudioEngine.h" + #include -#include #include #include +#include +#include +#include +#include + namespace WeirdEngine { namespace WeirdRenderer @@ -91,6 +95,13 @@ namespace WeirdEngine throw std::runtime_error("Failed to initialize GLAD."); } + IMGUI_CHECKVERSION(); + ImGui::CreateContext(); + ImGui::StyleColorsDark(); + + ImGui_ImplSDL3_InitForOpenGL(m_window, m_glContext); + ImGui_ImplOpenGL3_Init("#version 300 es"); // matches your GL ES 3.0 context + #ifndef NDEBUG // Enable debug output via KHR_debug extension if supported if (GLAD_GL_KHR_debug) @@ -134,6 +145,10 @@ namespace WeirdEngine SDLInitializer::~SDLInitializer() { + ImGui_ImplOpenGL3_Shutdown(); + ImGui_ImplSDL3_Shutdown(); + ImGui::DestroyContext(); + SDL_DestroyAudioStream(m_audioStream); SDL_GL_DestroyContext(m_glContext); SDL_DestroyWindow(m_window); diff --git a/third-party/imgui b/third-party/imgui new file mode 160000 index 00000000..691b89ba --- /dev/null +++ b/third-party/imgui @@ -0,0 +1 @@ +Subproject commit 691b89baae95d56df42a59b031c9d19685b7ab2f