You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 06:24:31