Загрузка PNG с stb_image для текстуры OpenGL дает неправильные цвета

Я использую stb_image для загрузки 32-битного файла PNG (RGBA), и я создаю текстуру OpenGL с ним.

Он отлично работает для 24-битных файлов PNG (без альфа-канала), но когда я использую 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);

Что происходит?

19

Решение

Изменение STBI_rgb на STBI_rgb_alpha в вызове функции stbi_load исправило это.

Наверное, лучше не указывать RGB, когда его RGBA: D

23

Другие решения

Ваша настоящая ошибка в том, что вы используете comp определить свой format (GL_RBA/GL_RGBA) параметр к glTexImage2D, Это происходит потому, что при загрузке изображения с помощью stbi_load, значение возвращается в comp всегда будет соответствовать исходному изображению, а не возвращенным данным изображения.

Более конкретно, ваша ошибка в том, что вы используете STBI_rgb, вызывая stbi_load вернуть 3 байта пикселей, но затем вы загружаете его с glTexImage2D как 4 байта пикселей с GL_RGBA так как comp 4, когда вы загружаете 32-битное изображение.

Вы должны установить формат в вашем звонке glTexImage2D в GL_RGB если вы используете STBI_rgb и к GL_RGBA если вы используете STBI_rgb_alpha,

Бонус другим читателям

У вас есть похожая проблема, и вышеупомянутое все еще не помогает? Тогда ваши данные изображения могут не иметь строк в выравнивании, ожидаемом OpenGL. Пытаться glPixelStorei(GL_UNPACK_ALIGNMENT, 1); прежде чем позвонить glTexImage2D, Увидеть https://www.khronos.org/opengl/wiki/Pixel_Transfer#Pixel_layout для дополнительной информации.

11