tags:

views:

389

answers:

3

Stemming from this question of mine: http://stackoverflow.com/questions/1191093/im-seeing-artifacts-when-i-attempt-to-rotate-an-image

In the source code there, I am loading a TIF because I can't for the life of me get any other image format to load the transparency parts correctly. I've tried PNG, GIF, & TGA. I'd would like to be able to load PNGs. I hope the source code given in the question above will be enough, if not, then let me know.

For a better description of what happens when I attempt to load some other format -- One of the images I was attempting was a 128*128 orange triangle. Depending on the format, it would either make the entire 128*128 square orange, or make the transparent parts of the image white.

+1  A: 

I'm not familiar with SDL, but since it's SDL that loading the image, I would look closer at their docs. I use .png in my own work along with OpenGL, and transparency works with no problem. (I use a .png parser called LightZPng.)

Also, I just noticed your linked post has:

glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);

instead of:

glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

This would have the affect of adding the pixels that should be transparent to whatever is in the background (assuming the alpha is 0 in those texels).

Jim Buck
Changing that makes the image not appear at all. Even with the TIF now
Justen
Huh, could it be that alpha is simply 0 for all your texels? I would look at your image data before passing it to glTexImage2D to confirm what the alpha values are for some texels. If they are simply RGB images (no alpha at all), then be sure to do a glColor4ub(255, 255, 255, 255) before rendering to be sure your alpha is effectively set to fully opaque.
Jim Buck
+2  A: 

Make sure that you have alpha blending enabled with

glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

otherwise primitives will draw solid colors where there should be transparency. You may need a different blendfunc. This is a common setup.

M84
I have that code in my previous question linked in the first post.
Justen
Actually, you have: glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); // notice the GL_ONE instead of GL_SRC_ALPHA - this can make a difference depending on what you are seeing
Jim Buck
Sorry if you had the code already, I wasn't able to scroll the code block on an iPhone. As Jim was saying, the blendfunc that you have may not be correct. The blendfunc you're using is for blending a texture with pre-multiplied alpha.
M84
Ah, well I tried your code then, and now it just won't draw it at all :(
Justen
Try to load in an image that has a known amount of transparency then look at the loaded buffer in the debugger to make sure that the alpha value contains the transparency you expect. If you don't see anything at all, I suspect that the alpha could be 0.
M84
+1  A: 

OK, I'm new at OpenGL + SDL but here is what I have.. Loads all? formats SDL_image supports except I can't get .xcf to work and don't have a .lbm to test with.

//called earlier..
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

//load texture
SDL_Surface* tex = IMG_Load(file.c_str());
if (tex == 0) {
 std::cout << "Could not load " << file << std::endl;
 return false;
}

glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);

//nearest works but linear is best when scaled?
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

width = tex->w;
height = tex->h;

//IMG_is* doesn't seem to work right, esp for TGA, so use extension instead..
std::string ext = file.substr(file.length() - 4);
bool isBMP = (ext.compare(".bmp") == 0) || (ext.compare(".BMP") == 0);
bool isPNG = (ext.compare(".png") == 0) || (ext.compare(".PNG") == 0);
bool isTGA = (ext.compare(".tga") == 0) || (ext.compare(".TGA") == 0);
bool isTIF = ((ext.compare(".tif") == 0) || (ext.compare(".TIF") == 0) ||
     (ext.compare("tiff") == 0) || (ext.compare("TIFF") == 0));

//default is RGBA but bmp and tga use BGR/A
GLenum format = GL_RGBA;
if(isBMP || isTGA)
 format = (tex->format->BytesPerPixel == 4 ? GL_BGRA : GL_BGR);

//every image except png and bmp need to be converted
if (!(isPNG || isBMP || isTGA || isTIF)) {
 SDL_Surface* fixedSurface = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000);
 SDL_BlitSurface(tex, 0, fixedSurface, 0);
 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, format, GL_UNSIGNED_BYTE, fixedSurface->pixels);
 SDL_FreeSurface(fixedSurface);
} else {
 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, format, GL_UNSIGNED_BYTE, tex->pixels);
}

SDL_FreeSurface(tex);

list = glGenLists(1);
glNewList(list, GL_COMPILE);
 GLint vertices[] = {
   0,0, 0,0,
   0,1, 0,height,
   1,1, width,height,
   1,0, width,0
  };

 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
 glEnableClientState(GL_VERTEX_ARRAY);

 glBindTexture(GL_TEXTURE_2D, texture);
 glTexCoordPointer(2, GL_INT, 4*sizeof(GLint), &vertices[0]);
 glVertexPointer(2, GL_INT, 4*sizeof(GLint), &vertices[2]);
 glDrawArrays(GL_POLYGON, 0, 4);

 glDisableClientState(GL_VERTEX_ARRAY);
 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glEndList();

And then to draw I set the color to opaque white (doesn't affect transparency?) then just call the list..

glColor4f(1,1,1,1);
glCallList(list);

And of course, any help for my code would be much appreciated too! :)

RayOK
I used bits and pieces from your code and it finally worked. Turns out when I was loading the image ( I used my own function instead of IMG_Load() ) it was discarding the alpha layer as it was converting the BPPs. So thanks a lot for your code.
Justen