ImGui中OpenGL+stb加载的图片显示异常如何修复?
问题排查与修复:ImGui中stb加载OpenGL纹理显示异常
核心问题1:渲染条件逻辑错误
GUI构建函数中,判断图片渲染的条件是CurrentImage.data != NULL,但在loadImage函数里,完成OpenGL纹理上传后立刻调用了stbi_image_free(CurrentImage.data);,释放了CPU端的像素数据,导致CurrentImage.data变为空指针,这个条件永远无法触发,图片根本没被渲染。
核心问题2:OpenGL纹理参数缺失(可选但建议补充)
窗口图标能正常工作,但作为纹理显示时,OpenGL默认的纹理Wrap参数为GL_REPEAT,若图片尺寸不是2的幂次,部分OpenGL环境可能出现显示异常,需补充Wrap参数设置。
修复后的完整代码
修复后的loadImage函数
bool FeatherGUI::loadImage(std::string _path) { //Load texture from file CurrentImage.data = stbi_load(_path.c_str(), &CurrentImage.width, &CurrentImage.height, &CurrentImage.channels, 3); if (!CurrentImage.data) { fprintf(stderr, "Cannot load image '%s'\n", _path.c_str()); CurrentImage.loaded = true; return false; } // Create a OpenGL texture identifier and binding glGenTextures(1, &CurrentImage.texture); glBindTexture(GL_TEXTURE_2D, CurrentImage.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); // 补充纹理Wrap参数,避免非2幂次图片显示异常 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); // Upload pixels into texture #if defined(GL_UNPACK_ROW_LENGTH) && !defined(__EMSCRIPTEN__) glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); #endif glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, CurrentImage.width, CurrentImage.height, 0, GL_RGB, GL_UNSIGNED_BYTE, CurrentImage.data); stbi_image_free(CurrentImage.data); // 释放后置空指针(可选) CurrentImage.data = nullptr; CurrentImage.loaded = true; return true; }
修复后的BuildGUI函数
void FeatherGUI::BuildGUI() { using namespace ImGui; Begin("Imagen Displayer"); Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / GetIO().Framerate, GetIO().Framerate); if (!CurrentImage.loaded) { //load image if (!loadImage("B:/naranja.png")) { Text("Error loading image"); } } //Show CurrentImage data in ImGui if (CurrentImage.loaded) { Text("------------------------------------------------"); Text("Identifier = %p", CurrentImage.texture); Text("Size = %d x %d", CurrentImage.width, CurrentImage.height); Text("Channels: %d", CurrentImage.channels); // 改用loaded状态判断渲染,纹理已创建完成无需依赖CPU端数据 Image((void*)(intptr_t)CurrentImage.texture, ImVec2(CurrentImage.width, CurrentImage.height)); } End(); }
额外说明
- 窗口图标能正常工作,是因为图标加载逻辑未释放CPU端数据,或采用了不同的纹理创建流程,与当前ImGui渲染逻辑无关。
- 确保调用纹理创建函数时OpenGL上下文已初始化,避免上下文无效时创建纹理。
内容的提问来源于stack exchange,提问作者Carlos López Martínez
相关产品推荐
相关产品推荐

