【问题标题】:Loading PNG with stb_image for OpenGL texture gives wrong colors为 OpenGL 纹理加载带有 stb_image 的 PNG 会给出错误的颜色
【发布时间】:2014-06-02 17:27:15
【问题描述】:

我正在使用 stb_image 加载一个 32 位 PNG 文件 (RGBA),并使用它创建一个 OpenGL 纹理。

它适用于 24 位 PNG 文件(没有 alpha 通道),但是当我使用 32 位 PNG 文件时,出现问题。

纹理应该是这样的:

这是使用 OpenGL 渲染时的样子(黑色部分是透明的,当我启用混合时):

这是我加载纹理的方式:

int w;
int h;
int comp;
unsigned char* image = stbi_load(filename.c_str(), &w, &h, &comp, STBI_rgb);

if(image == nullptr)
    throw(std::string("Failed to load texture"));

glGenTextures(1, &m_texture);

glBindTexture(GL_TEXTURE_2D, m_texture);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

if(comp == 3)
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
else if(comp == 4)
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, image);

glBindTexture(GL_TEXTURE_2D, 0);

stbi_image_free(image);

这些是窗口参数(使用 SDL)

SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE, 32);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);

发生了什么?

【问题讨论】:

    标签: c++ opengl png textures alpha


    【解决方案1】:

    您的实际错误是您使用compformat (GL_RBA/GL_RGBA) 参数确定为glTexImage2D。发生这种情况是因为当您使用 stbi_load 加载图像时,comp 中返回的值将始终与源图像匹配,而不是返回的图像数据。

    更具体地说,您的错误是您使用STBI_rgb,导致stbi_load 返回3 字节像素,但随后您将glTexImage2D 加载为4 字节像素和GL_RGBA,因为comp 是4 时你加载一个 32 位图像。

    如果使用STBI_rgb,则必须将调用中的格式设置为glTexImage2DGL_RGB;如果使用STBI_rgb_alpha,则必须设置GL_RGBA

    其他读者的奖励

    您是否有类似的问题,而上述方法仍然没有帮助?那么您的图像数据可能在 OpenGL 期望的对齐上没有行。在致电 glTexImage2D 之前尝试 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);。请参阅https://www.khronos.org/opengl/wiki/Pixel_Transfer#Pixel_layout 了解更多信息。

    【讨论】:

    • 我曾多次遇到需要 GL_UNPACK_ALIGNMENT 和 stb_image 的情况。 stb_image 文档表明它不会尝试执行任何类型的对齐 - 并且在没有所述对齐的情况下将 NPOT(非二次幂)纹理交给 OpengGL 时,这一点肯定会变得清晰。 POT 纹理将自然对齐,而 NPOT 纹理则不会。
    【解决方案2】:

    在 stbi_load 函数调用中将 STBI_rgb 更改为 STBI_rgb_alpha 修复了它。

    当它的 RGBA :D 时最好不要指定 RGB

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-11
      • 2015-05-09
      • 1970-01-01
      • 2011-02-09
      • 2014-01-28
      • 1970-01-01
      相关资源
      最近更新 更多