web-dev-qa-db-fra.com

Le chargement de PNG avec stb_image pour la texture OpenGL donne des couleurs incorrectes

J'utilise stb_image pour charger un fichier PNG 32 bits (RGBA) et je crée une texture OpenGL avec.

Cela fonctionne bien pour les fichiers PNG 24 bits (sans canal alpha), mais lorsque j'utilise un fichier PNG 32 bits, quelque chose ne va pas.

Voici à quoi devrait ressembler la texture:

Texture

Et voici à quoi cela ressemble lorsqu'il est rendu avec OpenGL (les parties noires sont censées être transparentes, et le sont lorsque j'active le mélange):

Wrong Texture

Voici comment je charge la 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);

Et ce sont les paramètres de la fenêtre (en utilisant 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);

Qu'est-ce qui se passe?

21
developerbmw

La modification de STBI_rgb en STBI_rgb_alpha dans l'appel de fonction stbi_load l'a corrigé.

Il est probablement préférable de ne pas spécifier RGB lorsque son RGBA: D

24
developerbmw

Votre bogue réel est que vous utilisez comp pour déterminer votre paramètre format (GL_RBA/GL_RGBA) Sur glTexImage2D. Cela se produit car lorsque vous chargez une image à l'aide de stbi_load, La valeur renvoyée dans comp correspondra toujours à l'image source, pas aux données d'image renvoyées.

Plus précisément, votre bogue est que vous utilisez STBI_rgb, Ce qui fait que stbi_load Renvoie 3 pixels d'octets, mais vous le chargez ensuite avec glTexImage2D Comme pixels de 4 octets avec GL_RGBA car comp vaut 4 lorsque vous chargez une image 32 bits.

Vous devez définir le format de votre appel sur glTexImage2D Sur GL_RGB Si vous utilisez STBI_rgb Et sur GL_RGBA Si vous utilisez STBI_rgb_alpha.

Bonus pour les autres lecteurs

Vous rencontrez un problème similaire et ce qui précède n'aide toujours pas? Vos données d'image pourraient alors ne pas avoir de lignes sur l'alignement qu'OpenGL attend. Essayez glPixelStorei(GL_UNPACK_ALIGNMENT, 1); avant d'appeler glTexImage2D. Voir https://www.khronos.org/opengl/wiki/Pixel_Transfer#Pixel_layout pour plus d'informations.

18