C++ 使用 stb_image 为 OpenGL 纹理加载 PNG 会产生错误的颜色

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/23150123/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 00:20:35  来源:igfitidea点击:

Loading PNG with stb_image for OpenGL texture gives wrong colors

c++openglpngtexturesalpha

提问by developerbmw

I am using stb_image to load a 32-bit PNG file (RGBA) and I am creating an OpenGL texture with it.

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

It works fine for 24-bit PNG files (with no alpha channel), but when I use a 32-bit PNG file, something goes wrong.

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

This is what the texture should look like:

纹理应该是这样的:

Texture

质地

And this is what it looks like when rendered with OpenGL (the black parts are meant to be transparent, and are when I enable blending):

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

Wrong Texture

错误的纹理

This is how I load the texture:

这是我加载纹理的方式:

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);

And these are the window parameters (using SDL)

这些是窗口参数(使用 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);

What is happening?

怎么了?

采纳答案by developerbmw

Changing the STBI_rgb to STBI_rgb_alpha in the stbi_load function call fixed it.

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

Probably best not to specify RGB when its RGBA :D

可能最好不要在其 RGBA 时指定 RGB:D

回答by Sebastian ?rleryd

Your actual bug is that you use compto determine your format(GL_RBA/GL_RGBA) parameter to glTexImage2D. This happens because when you load an image using stbi_load, the value returned in compwill always match the source image, not the image data returned.

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

More specifically, your bug is that you use STBI_rgb, causing stbi_loadto return 3 byte pixels, but then you load it with glTexImage2Das 4 byte pixels with GL_RGBAbecause compis 4 when you load a 32 bit image.

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

You must set the format in your call to glTexImage2Dto GL_RGBif you use STBI_rgband to GL_RGBAif you use STBI_rgb_alpha.

您必须在调用中将格式设置为glTexImage2Dto GL_RGBif you useSTBI_rgb和 to GL_RGBAif you use STBI_rgb_alpha

Bonus to other readers

奖励给其他读者

Are you having a similar problem and the above still doesn't help? Then your image data might not have rows on the alignment OpenGL expects. Try glPixelStorei(GL_UNPACK_ALIGNMENT, 1);before you call glTexImage2D. See https://www.khronos.org/opengl/wiki/Pixel_Transfer#Pixel_layoutfor more information.

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