Arch Linux下ImGui渲染OpenGL纹理显示全黑的问题求助
OpenGL纹理在ImGui中显示全黑问题
在Arch Linux系统中使用OpenGL 4.6(兼容OpenGL ES 3.2,已通过glxinfo -B验证),参照ImGui官方Wiki示例代码实现图片转OpenGL纹理并在ImGui中渲染时,遇到纹理显示全黑的问题。
基于Wiki代码修改了使用STB加载图片并生成纹理的辅助函数load_texture_from_file,STB加载图片无报错,该函数也未检测到OpenGL错误,但渲染时纹理全黑。以下是相关代码实现及调用逻辑:
纹理加载函数
// Simple helper function to load an image into a OpenGL texture with common settings bool load_texture_from_file(const char* filename, GLuint* out_texture, unsigned char **out_raw_image, int* out_width, int* out_height, int* out_channels) { unsigned char* image_data = stbi_load(filename, out_width, out_height, out_channels, 4); if (image_data == NULL) { printf("Failed to load image: %s\n", stbi_failure_reason()); return false; } // Create a OpenGL texture identifier GLuint image_texture; glGenTextures(1, &image_texture); glBindTexture(GL_TEXTURE_2D, image_texture); // Setup filtering parameters for display glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); // This is required on WebGL for non power-of-two textures glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); // Same GLenum format; if (*out_channels == 3) format = GL_RGB; else if (*out_channels == 4) format = GL_RGBA; else { // Handle unsupported channel count printf("Unsupported number of channels: %d\n", *out_channels); stbi_image_free(image_data); return false; } // Upload pixels into texture #if defined(GL_UNPACK_ROW_LENGTH) && !defined(__EMSCRIPTEN__) glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); #endif glTexImage2D(GL_TEXTURE_2D, 0, format, *out_width, *out_height, 0, format, GL_UNSIGNED_BYTE, image_data); GLenum error = glGetError(); if (error != GL_NO_ERROR) { printf("OpenGL error after glTexImage2D: %x\n", error); stbi_image_free(image_data); return false; } *out_raw_image = image_data; *out_texture = image_texture; assert(image_texture != 0 && *out_texture != 0); return true; }
UI显示函数
void display_ui(const GLFWvidmode *mode) { static int width, height, channels; static char input[256] = ""; static bool show_original = false; static bool show_preview = false; static unsigned char *image_data = NULL; static GLuint texture = 0; ImGui::Begin("Workshop", nullptr, ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoCollapse); ImVec2 main_panel_size = ImVec2(2 * ImGui::GetContentRegionAvail().x / 3, ImGui::GetContentRegionAvail().y - 75); ImVec2 side_panel_size = ImVec2(ImGui::GetContentRegionAvail().x / 3, (ImGui::GetContentRegionAvail().y - 80) / 2); ImGui::SetWindowSize(main_panel_size); ImVec2 parent_cursor_start = ImGui::GetCursorPos(); ImGui::BeginChild("Main panel", main_panel_size, true); ImGui::SetNextItemWidth(200.0f); if (ImGui::BeginTabBar("tab_bar", ImGuiTabBarFlags_none)) { if (ImGui::BeginTabItem("Original image")) { if(show_original) { ImGui::Text("pointer = %p", texture); ImGui::Text("size = %d x %d", width, height); ImGui::Image((void*)(intptr_t)&texture, ImVec2(width, height)); } ImGui::EndTabItem(); } } // ... irrelevant code is omitted for brevity // mostly just unrelated gui stuff if (ImGuiFileDialog::Instance()->Display("ChooseFileDlgKey")) { if (ImGuiFileDialog::Instance()->IsOk()) { std::string file_path_name = ImGuiFileDialog::Instance()->GetFilePathName(); std::string file_path = ImGuiFileDialog::Instance()->GetCurrentPath(); sprintf(input, "%s", file_path_name.c_str()); } ImGuiFileDialog::Instance()->Close(); } // process file path image if user clicks button if(ImGui::Button("Open input file")) { if(!load_texture_from_file(input, &texture, &image_data, &width, &height, &channels)) { ImGui::OpenPopup("Error loading image"); show_original = false; } else { show_original = true; } } if(ImGui::BeginPopup("Error loading image")) { ImGui::Text("Error loading image, select a valid path"); if(ImGui::Button("OK")) { ImGui::CloseCurrentPopup(); } ImGui::EndPopup(); } ImGui::End(); }
渲染循环
void framebuffer_size_callback(GLFWwindow* window, int width, int height) { glViewport(0, 0, width, height); } void render_gui() { glfwSetErrorCallback(glfw_error_callback); if (!glfwInit()) return; // Decide GL+GLSL versions #if defined(IMGUI_IMPL_OPENGL_ES2) // GL ES 2.0 + GLSL 100 const char* glsl_version = "#version 100"; glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0); glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API); #elif defined(__APPLE__) // GL 3.2 + GLSL 150 const char* glsl_version = "#version 150"; glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // 3.2+ only glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // Required on Mac #else // GL 3.0 + GLSL 130 const char* glsl_version = "#version 130"; glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0); #endif // Create window with graphics context GLFWmonitor *monitor = glfwGetPrimaryMonitor(); const GLFWvidmode *mode = glfwGetVideoMode(monitor); GLFWwindow* window = glfwCreateWindow(mode->width, mode->height, "Pixelify", nullptr, nullptr); if (window == nullptr) return; glfwMakeContextCurrent(window); glfwSetFramebufferSizeCallback(window, framebuffer_size_callback); glfwSwapInterval(1); // Enable vsync // Setup Dear ImGui context IMGUI_CHECKVERSION(); ImGui::CreateContext(); ImGuiIO& io = ImGui::GetIO(); (void)io; // Setup Dear ImGui style ImGui::StyleColorsDark(); // Setup Platform/Renderer backends ImGui_ImplGlfw_InitForOpenGL(window, true); ImGui_ImplOpenGL3_Init(glsl_version); // Main loop while (!glfwWindowShouldClose(window)) { glfwPollEvents(); // Start the Dear ImGui frame ImGui_ImplOpenGL3_NewFrame(); ImGui_ImplGlfw_NewFrame(); ImGui::NewFrame(); ImGui::SetNextWindowPos(ImVec2(0, 0)); ImGui::SetNextWindowSize(ImVec2(mode->width, mode->height)); display_ui(mode); // Rendering ImGui::Render(); int display_w, display_h; glfwGetFramebufferSize(window, &display_w, &display_h); glViewport(0, 0, display_w, display_h); glClear(GL_COLOR_BUFFER_BIT); ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) { GLFWwindow* backup_current_context = glfwGetCurrentContext(); ImGui::UpdatePlatformWindows(); ImGui::RenderPlatformWindowsDefault(); glfwMakeContextCurrent(backup_current_context); } glfwSwapBuffers(window); } // Cleanup ImGui_ImplOpenGL3_Shutdown(); ImGui_ImplGlfw_Shutdown(); ImGui::DestroyContext(); glfwDestroyWindow(window); glfwTerminate(); return; }
测试时使用一张PNG示例图片,渲染结果为全黑纹理。
内容的提问来源于stack exchange,提问作者Robert Motrogeanu
相关产品推荐
相关产品推荐

