# SDL_image & OpenGL Problem

i've been following tutorials online to load textures using SDL and display them on a opengl quad. but ive been getting weird results that no one else on the internet seems to be getting...

so when i render the texture in opengl i get something like this. http://www.kiddiescissors.com/after.png

when the original .bmp file is this: http://www.kiddiescissors.com/before.bmp

ive tried other images too, so its not that this particular image is corrupt. it seems like my rgb channels are all jumbled or something. im pulling my hair out at this point.

heres the relevant code from my init() function

if ( SDL_Init(SDL_INIT_VIDEO) != 0 ) {
return 1;
}
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
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_MULTISAMPLEBUFFERS, 1);
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 4);

SDL_SetVideoMode(WINDOW_WIDTH, WINDOW_HEIGHT, 32, SDL_HWSURFACE | SDL_GL_DOUBLEBUFFER | SDL_OPENGL);

glMatrixMode(GL_PROJECTION);
gluPerspective(50, (GLfloat)WINDOW_WIDTH/WINDOW_HEIGHT, 1, 50);
glMatrixMode(GL_MODELVIEW);
glEnable(GL_DEPTH_TEST);
glEnable(GL_MULTISAMPLE);
glEnable(GL_TEXTURE_2D);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);


heres the code that is called when my main player object (the one with which this sprite is associated) is initialized

texture = 0;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, surface->w, surface->h, 0, GL_RGB, GL_UNSIGNED_BYTE, surface->pixels);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
SDL_FreeSurface(surface);


and then heres the relevant code from my display function

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor4f(1, 1, 1, 1);
glPushMatrix();
glBindTexture(GL_TEXTURE_2D, texture);
glTranslatef(getCenter().x, getCenter().y, 0);
glRotatef(getAngle()*(180/M_PI), 0, 0, 1);
glTranslatef(-getCenter().x, -getCenter().y, 0);
glTexCoord2f(0, 0);
glVertex3f(getTopLeft().x, getTopLeft().y, 0);
glTexCoord2f(0, 1);
glVertex3f(getTopLeft().x, getTopLeft().y + size.y, 0);
glTexCoord2f(1, 1);
glVertex3f(getTopLeft().x + size.x, getTopLeft().y + size.y, 0);
glTexCoord2f(1, 0);
glVertex3f(getTopLeft().x + size.x, getTopLeft().y, 0);
glEnd();
glPopMatrix();


let me know if i left out anything important... or if you need more info from me.

thanks a ton,

-Dylan

This is my solution for SDL_image to OpenGL RGBA texture. Last I tested, it works with everything except .xcf. The solution is simple, create a SDL_PixelFormat and use SDL_ConvertSurface..


SDL_PixelFormat pf;
pf.palette = 0;
pf.BitsPerPixel = 32;
pf.BytesPerPixel = 4;
pf.alpha = 255;
pf.Rshift = pf.Rloss = pf.Gloss = pf.Bloss = pf.Aloss = pf.colorkey = 0;
pf.Gshift = 8;
pf.Bshift = 16;
pf.Ashift = 24;

SDL_Surface* glSurface = SDL_ConvertSurface(imgSurface, &pf, SDL_SWSURFACE);

//convert width or height to nearest power of 2? you can but seems to work ok without it

//gen and bind

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, glSurface->w, glSurface->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, glSurface->pixels);

//tex parameters

SDL_FreeSurface(glSurface);


I notice the before.bmp file is 4-channel RGBA (32bpp), but you're telling OpenGL that the pixels you're passing are 3-channel RGB (24bpp). I'm not personally familiar with SDL_Image, so it may be cleverly converting the pixel format at load time, but you could try changing the "GL_RGB"s in your 2nd block of code to "GL_RGBA" to see if that fixes things.

In general, you should check the pixel size of the image you loaded (surface->format->BytesPerPixel). If it's 3, use GL_RGB when creating the texture; if it's 4, use GL_RGBA. (It's actually more complicated than that, if you want to correctly handle all possible pixel formats, but that should be enough to get you started).

Also, you have blending enabled; is that really what you want? If you want the image displayed as you see it (no transparency/alpha), try removing these three lines:

glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);

• thanks for the suggestion, i resaved the .bmp it without the alpha channel this time and it still looks the same though... before i did that however, i kept the 4 channel file, and changed the RBG to RBGA as you suggested. it worked kind of (the image looked correct), but it tinted everything else on the screen to the general color of the image (if there is a lot of green in the image, it gives everything a green tint). i am using photoshop to save the images, is there some other better way i should be creating them? – Dylan Nov 2 '12 at 2:18
• That's a separate issue, having to do with alpha blending. I've updated my answer. Photoshop is a fine, fine way to create textures, though removing the alpha channel in Photoshop may not actually change the output BMP to 24-bit; more likely it just sets all the alpha values to 255 (fully opaque). – postgoodism Nov 2 '12 at 2:32
• i actually eventually want .pngs with transparency and everything. ive just been having so much trouble with the blending and getting them working and everything that i thought i might simplify things and just figure out plain RGB files first and then move on to transparency after i get that working. ive tried turning blending off as you suggested, the tinting effect, and the original weird scramble thing (kiddiescissors.com/after.png) are both still there... – Dylan Nov 2 '12 at 2:38
• if i keep RGBA on, blending etc. and display a png file with actual transparency in it, it makes everything else in the entire window black except the image itself, almost as if the transparency is working but a giant black quad is being placed behind it or something... then, if i then switch to a png to one without any transparency in the image, it displays fine and does the tinting effect. does any of that make sense? – Dylan Nov 2 '12 at 2:42
• I'm just trying to fix one problem at a time. The tinting is DEFINITELY due to your blending settings; just disable blending for now until you reliably fix the scrambling. The "scramble" artifact is because you're passing 32 bpp pixel data to OpenGL and claiming that it's 24 bpp, so instead of drawing "RGB RGB RGB RGB ..." it's drawing "RGB ARG BAR GBA ..." – postgoodism Nov 2 '12 at 2:45

i didnt end up figuring out the scramble thing (which seem to only happened to images without transparency and when i was in plain RGB mode without Alpha)... but i did fix the weird tinting issue (mentioned in the comments section). the solution is below:

i was binding the texture to my object before drawing the quad, but not "unbinding" it after it had been rendered. i added

glBindTexture(GL_TEXTURE_2D, 0);


after the glEnd() call and as far as i can tell everything else in the scene is now normal using a .png file with transparency and in RGBA mode