이번은 IMGUI(Immediate Mode GUI)를 사용하여 OpenGL에 GUI를 손쉽게 적용하는 방법에 대해 설명하겠다.
IMGUI는 즉시 모드 방식으로 UI를 구성하며, 별도의 복잡한 GUI 프레임워크 없이 간단하게 그래픽 요소를 그릴 수 있다.
1. OpenGL에서의 GUI 구현의 어려움
OpenGL에서 GUI 요소를 직접 구현하려면 상당한 노력이 필요하다. 기본적인 버튼, 슬라이더, 텍스트 필드 등을 구현하기 위해서는 셰이더(Shader), 프로그램(Program), VBO, VAO, EBO, Uniform, 텍스처(Texture) 등을 모두 관리해야 한다. 이러한 복잡한 과정은 개발자의 부담을 크게 늘릴 수 있다.
GUI를 구현하는 데는 두 가지 방식이 있다:
- 별도의 GUI 프레임워크를 사용하여 화면을 구성하고, 그 위에 OpenGL을 통해 그래픽을 그리는 방식
- OpenGL 내부에 GUI 컴포넌트를 그리는 라이브러리를 사용하여 이벤트를 처리하는 방식
IMGUI는 두 번째 방식에 해당하며, Immediate-Mode GUI 방식을 따른다.
2. IMGUI란?
IMGUI는 Omar Cornut가 만든 오픈 소스 라이브러리로, 그래픽 프로그래밍에 필요한 다양한 GUI 컴포넌트를 제공한다. OpenGL을 포함한 다양한 그래픽 API에서 사용할 수 있으며, Vector Editor나 Color Picker와 같은 컴포넌트도 포함하고 있다. IMGUI는 거의 의존성이 없고, 빌드가 매우 간단하다.
3. Immediate Mode의 개념
Immediate Mode 방식은 매 렌더링 루프마다 UI를 그리는 방식이다. 다음과 같은 코드로 매 프레임마다 UI를 다시 그린다.
// 매 프레임마다 UI를 그린다
ImGui::Text("Hello, world %d", 123);
if (ImGui::Button("Save"))
MySaveFunction();
ImGui::InputText("string", buf, IM_ARRAYSIZE(buf));
ImGui::SliderFloat("float", &f, 0.0f, 1.0f);
이 방식을 통해 UI 요소는 이벤트가 발생할 때마다 매번 재구성되며, 상태를 유지할 필요가 없다. 이로 인해 단순한 UI 동작을 구현하기가 매우 쉽다.
4. IMGUI 설치
- IMGUI를 GitHub에서 다운로드한 후, 프로젝트의
imgui
디렉토리에 소스 코드 및 라이센스 파일을 복사한다. - OpenGL에서 사용하기 위한 백엔드 파일인
imgui_impl_glfw.*
와imgui_impl_opengl3.*
파일을 함께 복사한다. CMake
프로젝트에 IMGUI 라이브러리를 추가하고, 빌드가 잘 되는지 확인한다.
add_library(imgui
imgui/imgui_draw.cpp
imgui/imgui_tables.cpp
imgui/imgui_widgets.cpp
imgui/imgui.cpp
imgui/imgui_impl_glfw.cpp
imgui/imgui_impl_opengl3.cpp
)
이렇게 하면 IMGUI를 사용하기 위한 준비가 완료된다.
5. IMGUI 초기화
IMGUI를 OpenGL과 함께 사용하려면 OpenGL 컨텍스트가 초기화된 후 IMGUI를 초기화해야 한다. 다음은 IMGUI 초기화 과정이다.
auto imguiContext = ImGui::CreateContext();
ImGui::SetCurrentContext(imguiContext);
ImGui_ImplGlfw_InitForOpenGL(window, false);
ImGui_ImplOpenGL3_Init();
ImGui_ImplOpenGL3_CreateFontsTexture();
ImGui_ImplOpenGL3_CreateDeviceObjects();
그 후, 메인 루프에서 IMGUI의 NewFrame
, Render
등의 함수를 호출하여 IMGUI의 렌더링 데이터를 OpenGL로 그리도록 한다.
while (!glfwWindowShouldClose(window)) {
glfwPollEvents();
ImGui_ImplGlfw_NewFrame();
ImGui::NewFrame();
context->ProcessInput(window);
context->Render();
ImGui::Render();
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
glfwSwapBuffers(window);
}
IMGUI는 프레임마다 새로 그려지므로, 매번 ImGui_ImplGlfw_NewFrame()
과 ImGui::Render()
를 호출하여 UI를 갱신한다.
6. UI와 파라미터 연결하기
IMGUI를 사용하여 UI 요소를 OpenGL 파라미터와 연결할 수 있다. 예를 들어, 카메라의 위치, 클리어 색상 등을 UI로 조정할 수 있다.
if (ImGui::Begin("ui window")) {
if (ImGui::ColorEdit4("clear color", glm::value_ptr(m_clearColor))) {
glClearColor(m_clearColor.r, m_clearColor.g, m_clearColor.b, m_clearColor.a);
}
ImGui::Separator();
ImGui::DragFloat3("camera pos", glm::value_ptr(m_cameraPos), 0.01f);
ImGui::DragFloat("camera yaw", &m_cameraYaw, 0.5f);
ImGui::DragFloat("camera pitch", &m_cameraPitch, 0.5f, -89.0f, 89.0f);
ImGui::Separator();
if (ImGui::Button("reset camera")) {
m_cameraYaw = 0.0f;
m_cameraPitch = 0.0f;
m_cameraPos = glm::vec3(0.0f, 0.0f, 3.0f);
}
}
이 코드는 UI 컴포넌트와 OpenGL 파라미터 간의 연결을 보여준다. IMGUI는 매우 직관적인 API를 제공하며, 각 UI 컴포넌트는 함수 호출 하나로 쉽게 추가할 수 있다.
7. 콜백 설정
IMGUI는 기본적으로 키보드 입력을 처리하지 않으므로, 별도의 콜백을 설정해야 한다. 이를 위해 GLFW
콜백 함수와 IMGUI 콜백 함수를 연동한다.
void OnKeyEvent(GLFWwindow* window, int key, int scancode, int action, int mods) {
ImGui_ImplGlfw_KeyCallback(window, key, scancode, action, mods);
}
콜백 설정을 통해 IMGUI에서 키보드 입력, 마우스 스크롤, 탭 이동 등을 지원할 수 있다.
'Computer Graphics > OpenGL' 카테고리의 다른 글
OpenGL 정리 - 15. Texture Map 적용 (0) | 2024.09.23 |
---|---|
OpenGL 정리 - 14. Phong Model 적용 (0) | 2024.09.23 |
OpenGL 정리 - 12. 카메라, View Transform (0) | 2024.09.19 |
OpenGL 정리 - 11. 큐브 그리기, Depth Buffer, 여러 큐브 그리기 (0) | 2024.09.13 |
OpenGL 정리 - 10. GLM을 이용한 선형 변환 (0) | 2024.09.13 |