text: #include <filesystem>
  #include <string>
  
  #include <fmt/core.h>
  #include <spdlog/spdlog.h>
  #include <imgui.h>
  #include <imgui_impl_sdl.h>
  #include <imgui_impl_opengl3.h>
  #include <SDL2/SDL.h>
  #include <glad/glad.h>
  
  #include "demo.h"
  
  int main(int, char* argv[])
  {
      const std::string progname{std::filesystem::path{argv[0]}.filename().string()};
  
      if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) < 0) {
          spdlog::critical("unable to initialize SDL: {}", SDL_GetError());
          return 1;
      }
  
      // Decide GL + GLSL versions
  #if defined(IMGUI_IMPL_OPENGL_ES2)
      // GL ES 2.0 + GLSL 100
      const char* glsl_version = "#version 100";
      SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0);
      SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
      SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
      SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
  #else
      // GL 3.2 + GLSL 150
      const char* glsl_version = "#version 150";
      SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
      SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
      SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG);
      SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
  #endif
  
      SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
      SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
      SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
      SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI);
  
      SDL_Window* window = SDL_CreateWindow(progname.c_str(), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1024, 768, window_flags);
  
      if (!window) {
          spdlog::critical("unable to create window: {}", SDL_GetError());
          return 1;
      }
  
      SDL_GLContext gl_context = SDL_GL_CreateContext(window);
      SDL_GL_MakeCurrent(window, gl_context);
      SDL_GL_SetSwapInterval(1);
  
      if (!gladLoadGL()) {
          spdlog::error("failed to initialize OpenGL loader");
          return 1;
      }
  
      auto renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
  
      if (!renderer) {
          spdlog::critical("unable to create renderer: {}", SDL_GetError());
          return 1;
      }
  
      // setup ImGui
      IMGUI_CHECKVERSION();
      ImGui::CreateContext();
      ImGuiIO& io = ImGui::GetIO();
      ImGui::StyleColorsDark();
  
      // setup ImGui Platform/Renderer backends
      ImGui_ImplSDL2_InitForOpenGL(window, gl_context);
      ImGui_ImplOpenGL3_Init(glsl_version);
  
      bool running = true;
  
      while (running) {
          SDL_Event event;
  
          while (SDL_PollEvent(&event)) {
              ImGui_ImplSDL2_ProcessEvent(&event);
  
              if (event.type == SDL_QUIT)
                  running = false;
              else if (event.type == SDL_KEYUP && event.key.keysym.sym == SDLK_ESCAPE)
                  running = false;
          }
  
          // start ImGui frame
          ImGui_ImplOpenGL3_NewFrame();
          ImGui_ImplSDL2_NewFrame(window);
          ImGui::NewFrame();
  
          auto clear_color = imgui_demo();
  
          // render app content
          const int width = (int) io.DisplaySize.x;
          const int height = (int) io.DisplaySize.y;
  
          const auto fps = 1.0 / ImGui::GetIO().DeltaTime;
          const auto title = fmt::format("{} {}x{} FPS: {:.0f}", progname, width, height, fps);
          SDL_SetWindowTitle(window, title.c_str());
  
          glViewport(0, 0, width, height);
          glClearColor(clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w);
          glClear(GL_COLOR_BUFFER_BIT);
  
          ImGui::Render();
          ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
          SDL_GL_SwapWindow(window);
      }
  
      // ImGui cleanup
      ImGui_ImplOpenGL3_Shutdown();
      ImGui_ImplSDL2_Shutdown();
      ImGui::DestroyContext();
  
      SDL_DestroyRenderer(renderer);
      SDL_GL_DeleteContext(gl_context);
      SDL_DestroyWindow(window);
  
      SDL_Quit();
  
      return 0;
  }
  