如何同时渲染OpenGL三角形与ImGui窗口?
问题:OpenGL三角形与ImGui窗口无法同时渲染
当不在主循环中调用ImguiOnUpdate(width, height)时,窗口可正常显示三角形;但调用该函数后,三角形仅在初始时闪一下,之后只能看到ImGui窗口,无法同时渲染两者。
原代码如下:
#include <iostream> #include <imgui/imgui.h> #include <imgui/backends/imgui_impl_glfw.h> #include <imgui/backends/imgui_impl_opengl3.h> #include <glad/glad.h> #include <GLFW/glfw3.h> void ImguiOnUpdate(int width, int height){ // 1.1 set window size for imgui ImGuiIO& io = ImGui::GetIO(); io.DisplaySize = ImVec2(width, height); // 1.2 new frame ImGui_ImplOpenGL3_NewFrame(); ImGui::NewFrame(); // 1.3 imgui demo window static bool show = true; ImGui::ShowDemoWindow(&show); // 1.4 imgui render ImGui::Render(); ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); } int main() { // ===OPENGL=== int width = 1600; int height = 900; glfwInit(); GLFWwindow *window = glfwCreateWindow(width, height, "LearnOpenGL", nullptr, nullptr); if (window == nullptr) { std::cerr << "failed to create GLFW window\n"; } glfwMakeContextCurrent(window); glfwSetFramebufferSizeCallback(window, [](GLFWwindow *_, int width, int height) { glViewport(0, 0, width, height); }); if (!gladLoadGLLoader((GLADloadproc) glfwGetProcAddress)) { std::cerr << "failed to initialize GLAD\n"; } uint32_t va_, vb_, ib_; glGenVertexArrays(1, &va_); glBindVertexArray(va_); glGenBuffers(1, &vb_); glBindBuffer(GL_ARRAY_BUFFER, vb_); float vertices[] = { -0.5f, -0.5f, 0.0f, 0.5f, -0.5f, 0.0f, 0.0f, 0.5f, 0.0f }; glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), nullptr); glGenBuffers(1, &ib_); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ib_); int indices[] = {0, 1, 2}; glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); // ===IMGUI=== // 1.1 Imgui Context ImGui::CreateContext(); ImGui::StyleColorsDark(); // 1.2 Imgui flags ImGuiIO& io = ImGui::GetIO(); io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // 1.3 Imgui init for opengl ImGui_ImplOpenGL3_Init("#version 330"); while(!glfwWindowShouldClose(window)){ glClearColor(0.1f, 0.1f, 0.1f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); glBindVertexArray(va_); glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, nullptr); ImguiOnUpdate(width, height); glfwSwapBuffers(window); glfwPollEvents(); } }
解决方案
问题核心
- 缺少GLFW后端绑定:仅初始化了ImGui的OpenGL3后端,未将其与GLFW窗口关联,导致ImGui无法正确处理窗口输入、尺寸变化,渲染状态出现异常。
- 手动设置窗口尺寸干扰逻辑:强制修改
io.DisplaySize会覆盖GLFW后端自动获取的窗口数据,导致渲染坐标系错位。 - ImGui帧流程不完整:缺少
ImGui_ImplGlfw_NewFrame()调用,无法正确启动ImGui的帧循环处理输入事件。
修改步骤
- 添加GLFW后端初始化:在OpenGL3后端初始化前,调用
ImGui_ImplGlfw_InitForOpenGL绑定GLFW窗口。 - 修正ImGui帧流程:移除手动设置
io.DisplaySize的代码,添加ImGui_ImplGlfw_NewFrame()以正确处理输入。 - 优化主循环调用:
ImguiOnUpdate无需传入窗口尺寸,由GLFW后端自动处理。 - 添加资源清理:程序退出前清理ImGui后端资源,避免内存泄漏。
修改后的完整代码
#include <iostream> #include <imgui/imgui.h> #include <imgui/backends/imgui_impl_glfw.h> #include <imgui/backends/imgui_impl_opengl3.h> #include <glad/glad.h> #include <GLFW/glfw3.h> void ImguiOnUpdate(){ // 1. 启动ImGui帧循环:先处理GLFW输入事件 ImGui_ImplGlfw_NewFrame(); ImGui_ImplOpenGL3_NewFrame(); ImGui::NewFrame(); // 2. 绘制ImGui窗口 static bool show = true; ImGui::ShowDemoWindow(&show); // 3. 渲染ImGui到屏幕 ImGui::Render(); ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); } int main() { // ===OPENGL=== int width = 1600; int height = 900; glfwInit(); GLFWwindow *window = glfwCreateWindow(width, height, "LearnOpenGL", nullptr, nullptr); if (window == nullptr) { std::cerr << "failed to create GLFW window\n"; glfwTerminate(); return -1; } glfwMakeContextCurrent(window); glfwSetFramebufferSizeCallback(window, [](GLFWwindow *_, int width, int height) { glViewport(0, 0, width, height); }); if (!gladLoadGLLoader((GLADloadproc) glfwGetProcAddress)) { std::cerr << "failed to initialize GLAD\n"; glfwTerminate(); return -1; } uint32_t va_, vb_, ib_; glGenVertexArrays(1, &va_); glBindVertexArray(va_); glGenBuffers(1, &vb_); glBindBuffer(GL_ARRAY_BUFFER, vb_); float vertices[] = { -0.5f, -0.5f, 0.0f, 0.5f, -0.5f, 0.0f, 0.0f, 0.5f, 0.0f }; glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), nullptr); glGenBuffers(1, &ib_); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ib_); int indices[] = {0, 1, 2}; glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); // ===IMGUI=== ImGui::CreateContext(); ImGui::StyleColorsDark(); ImGuiIO& io = ImGui::GetIO(); io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // 初始化GLFW后端(绑定当前窗口,第二个参数表示是否让ImGui接管GLFW输入回调) ImGui_ImplGlfw_InitForOpenGL(window, true); // 初始化OpenGL3后端 ImGui_ImplOpenGL3_Init("#version 330"); while(!glfwWindowShouldClose(window)){ glClearColor(0.1f, 0.1f, 0.1f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); // 渲染OpenGL三角形 glBindVertexArray(va_); glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, nullptr); // 渲染ImGui窗口 ImguiOnUpdate(); glfwSwapBuffers(window); glfwPollEvents(); } // 清理ImGui资源 ImGui_ImplOpenGL3_Shutdown(); ImGui_ImplGlfw_Shutdown(); ImGui::DestroyContext(); glfwTerminate(); return 0; }
效果说明
修改后,主循环先渲染OpenGL三角形,再渲染ImGui窗口,ImGui会自动层叠在3D内容上方,实现两者同时显示。GLFW后端会自动处理窗口尺寸变化和输入事件,无需手动干预窗口尺寸参数。
内容的提问来源于stack exchange,提问作者milanHrabos
相关产品推荐
相关产品推荐

