SDL_Surface -> OpenGL texture only works with RGBA?

Hello list,

I’ve recently updated a routine of mine which converts SDL_Surfaces to
OpenGL Textures - so that it could also process RGB surfaces
(previously, all of them where RGBA which is a waste when I don’t need
an alpha channel). However I noticed that surfaces which are RGB are all
defective (distorted, looking like parts of unallocated memory are
rendered) - the RGBA texture conversion works fine, however. Could you
maybe take a look at my code? It should be pretty self-explanatory:

Thank you in advance,
Greetings,
Johannes

--------------- Code ------------------------------------

GLuint Renderer::Convert_Texture(SDL_Surface *Image, bool Tileable, bool
MipMaps, bool TextureFiltering) {
EXCEPTIONASSERTION((Image->format->BytesPerPixel == 3) ||
(Image->format->BytesPerPixel == 4), “Only RGB and RGBA surfaces are
supported.”);

int Texture_Size = Image->w * Image->h * Image->format->BytesPerPixel;
EXCEPTIONASSERTION(Texture_Size > 0, “Texture size <= 0”);

GLubyte *Data = new GLubyte[Texture_Size];

// Traverse through surface and grab the pixels
int Pos = 0;
bool Alpha = (Image->format->BytesPerPixel == 4);
for (int y = Image->h - 1; y >= 0; y–) {
for (int x = 0; x < Image->w; x++) {
Uint8 R, G, B, A;

     Uint32 Color = SDLOps::GetPixel(Image, x, y);

     if (!Alpha) {
        SDL_GetRGB(Color, Image->format, &R, &G, &B);
     } else {
        SDL_GetRGBA(Color, Image->format, &R, &G, &B, &A);
     }

     Data[Pos++] = R;
     Data[Pos++] = G;
     Data[Pos++] = B;
     if (Alpha) Data[Pos++] = A;
  }

}

GLuint Texture;
int Texture_Type = Alpha ? GL_RGBA : GL_RGB;
glGenTextures(1, &Texture); // Generate texture ID
glBindTexture(GL_TEXTURE_2D, Texture);

glTexImage2D(GL_TEXTURE_2D, 0, Texture_Type, Image->w, Image->h, 0,
Texture_Type, GL_UNSIGNED_BYTE, Data);
int Filter_Minify, Filter_Magnification;
if (TextureFiltering) {
Filter_Minify = MipMaps ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
Filter_Magnification = GL_LINEAR;
} else {
Filter_Minify = MipMaps ? GL_NEAREST_MIPMAP_NEAREST : GL_NEAREST;
Filter_Magnification = GL_NEAREST;
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, Filter_Minify);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
Filter_Magnification);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, Tileable ?
GL_REPEAT : GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, Tileable ?
GL_REPEAT : GL_CLAMP);
if (MipMaps) {
gluBuild2DMipmaps(GL_TEXTURE_2D, Texture_Type, Image->w, Image->h,
Texture_Type, GL_UNSIGNED_BYTE, Data);
}

delete[] Data;
return Texture;
}

Hi,

I think you have a problem with the GL_UNPACK_ALIGNMENT parameter of
glPixelStore. Your color data is tightly packed within memory. OpenGL
defaults to unpack image rows with a 4 byte alignment, which is given in
case of RGBA data.

Try to set the GL_UNPACK_ALIGNMENT to 1.

If this doesn’t help, a more detailed description of the the observed
distortion would be helpful.

Matthias

Johannes Bauer schrieb:> Hello list,

I’ve recently updated a routine of mine which converts SDL_Surfaces to
OpenGL Textures - so that it could also process RGB surfaces
(previously, all of them where RGBA which is a waste when I don’t need
an alpha channel). However I noticed that surfaces which are RGB are all
defective (distorted, looking like parts of unallocated memory are
rendered) - the RGBA texture conversion works fine, however. Could you
maybe take a look at my code? It should be pretty self-explanatory:

Thank you in advance,
Greetings,
Johannes

--------------- Code ------------------------------------

GLuint Renderer::Convert_Texture(SDL_Surface *Image, bool Tileable, bool
MipMaps, bool TextureFiltering) {
EXCEPTIONASSERTION((Image->format->BytesPerPixel == 3) ||
(Image->format->BytesPerPixel == 4), “Only RGB and RGBA surfaces are
supported.”);

int Texture_Size = Image->w * Image->h * Image->format->BytesPerPixel;
EXCEPTIONASSERTION(Texture_Size > 0, “Texture size <= 0”);

GLubyte *Data = new GLubyte[Texture_Size];

// Traverse through surface and grab the pixels
int Pos = 0;
bool Alpha = (Image->format->BytesPerPixel == 4);
for (int y = Image->h - 1; y >= 0; y–) {
for (int x = 0; x < Image->w; x++) {
Uint8 R, G, B, A;

     Uint32 Color = SDLOps::GetPixel(Image, x, y);

     if (!Alpha) {
        SDL_GetRGB(Color, Image->format, &R, &G, &B);
     } else {
        SDL_GetRGBA(Color, Image->format, &R, &G, &B, &A);
     }

     Data[Pos++] = R;
     Data[Pos++] = G;
     Data[Pos++] = B;
     if (Alpha) Data[Pos++] = A;
  }

}

GLuint Texture;
int Texture_Type = Alpha ? GL_RGBA : GL_RGB;
glGenTextures(1, &Texture); // Generate texture ID
glBindTexture(GL_TEXTURE_2D, Texture);

glTexImage2D(GL_TEXTURE_2D, 0, Texture_Type, Image->w, Image->h, 0,
Texture_Type, GL_UNSIGNED_BYTE, Data);
int Filter_Minify, Filter_Magnification;
if (TextureFiltering) {
Filter_Minify = MipMaps ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
Filter_Magnification = GL_LINEAR;
} else {
Filter_Minify = MipMaps ? GL_NEAREST_MIPMAP_NEAREST : GL_NEAREST;
Filter_Magnification = GL_NEAREST;
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, Filter_Minify);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
Filter_Magnification);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, Tileable ?
GL_REPEAT : GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, Tileable ?
GL_REPEAT : GL_CLAMP);
if (MipMaps) {
gluBuild2DMipmaps(GL_TEXTURE_2D, Texture_Type, Image->w, Image->h,
Texture_Type, GL_UNSIGNED_BYTE, Data);
}

delete[] Data;
return Texture;
}


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

Matthias Weigand schrieb:

I think you have a problem with the GL_UNPACK_ALIGNMENT parameter of
glPixelStore. Your color data is tightly packed within memory. OpenGL
defaults to unpack image rows with a 4 byte alignment, which is given in
case of RGBA data.

Try to set the GL_UNPACK_ALIGNMENT to 1.

That was it! Thank you so much, that’s awesome! :slight_smile:

Greetings,
Johannes