static int powerOfTwo(int input)
{
int value = 1;
while(value < input)
value <<= 1;
return value;
}
GLuint LoadGLTexture(const char* filename)
{
SDL_Surface *pImage = NULL, *image = NULL;
GLuint texture = 0;
int w = 0, h = 0, ybegin, yend;
SDL_Rect area;
Uint32 saved_flags;
Uint16 pitch;
Uint8 saved_alpha, *pixels, *line;
pImage = IMG_Load(filename);
if(!pImage)
{
printf("Unable to load texture '%s'\n", filename);
return 0;
}
w = powerOfTwo(pImage->w);
h = powerOfTwo(pImage->h);
/*
texcoord[0] = 0.0f;
texcoord[1] = 0.0f;
texcoord[2] = (GLfloat)pImage->w / w;
texcoord[3] = (GLfloat)pImage->h / h;
*/
if(!(image = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 32,
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
0x000000FF,
0x0000FF00,
0x00FF0000,
0xFF000000
#else
0xFF000000,
0x00FF0000,
0x0000FF00,
0x000000FF
#endif
)))
{
printf("SDL_CreateRGBSurface: Unable to create RGB Surface for texture '%s'\n", filename);
return 0;
}
saved_flags = pImage->flags&(SDL_SRCALPHA|SDL_RLEACCELOK);
saved_alpha = pImage->format->alpha;
if((saved_flags & SDL_SRCALPHA) == SDL_SRCALPHA)
SDL_SetAlpha(pImage, 0, 0);
area.x = area.y = 0;
area.w = pImage->w;
area.h = pImage->h;
SDL_BlitSurface(pImage, &area, image, &area);
if((saved_flags & SDL_SRCALPHA) == SDL_SRCALPHA)
SDL_SetAlpha(pImage, saved_flags, saved_alpha);
line = new Uint8[image->pitch];
pixels = static_cast<Uint8*>(image->pixels);
pitch = image->pitch;
ybegin = 0;
yend = image->h - 1;
if(SDL_MUSTLOCK(image))
SDL_LockSurface(image);
while(ybegin < yend)
{
memcpy(line, pixels + pitch * ybegin, pitch);
memcpy(pixels + pitch * ybegin, pixels + pitch * yend, pitch);
memcpy(pixels + pitch * yend, line, pitch);
ybegin++;
yend--;
}
if(SDL_MUSTLOCK(image))
SDL_UnlockSurface(image);
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, image->pixels);
if(pImage)
SDL_FreeSurface(pImage);
if(image)
SDL_FreeSurface(image);
if(line)
delete[] line;
return texture;
}
SDL & OpenGL Texture Transparency
I am using SDL and OpenGL (of course by the topic) and am attempting to make a function that loads a file and returns it as an OpenGL texture with transparency.
Currently, I already have a function that returns an OpenGL texture, but I need it to also make certain parts of it transparent (for example, the color magenta - FF00FF (255,0,255)).
I would like to modify my current function to make the returned textures transparent. Below is my current code for texture loading:
Thanks for any help!
You get a pointer to the pixels (before they are given to OpenGL), and you examine each pixel. If (pixel&0xffffff) is 0xff00ff, then set it to 0x00000000, else set it to ((pixel&0xffffff)|0xff000000). Then upload the data as an actual texture.
When you draw using this transparency, use GL_ONE,GL_ONE_MINUS_SRC_ALPHA blend function, because the color pixels will blend towards black as they blend towards translucency. If you use GL_SRC_ALPHA, then you'll get black fringes.
When you draw using this transparency, use GL_ONE,GL_ONE_MINUS_SRC_ALPHA blend function, because the color pixels will blend towards black as they blend towards translucency. If you use GL_SRC_ALPHA, then you'll get black fringes.
What would be the best way to cycle through each pixel, then?
Also, where in the function? (I am presuming right before the glTexImage2D)
Wouldn't cycling through each pixel, though, be quite slow? Is there any better alternative or something? If not, that's okay, but I am just concerned about speed a little bit.
Also, where in the function? (I am presuming right before the glTexImage2D)
Wouldn't cycling through each pixel, though, be quite slow? Is there any better alternative or something? If not, that's okay, but I am just concerned about speed a little bit.
I think I did this a few years ago. It should be possible to setup a color key. Then (I think) you can use SDL_DisplayFormatAlpha() which will take a surface with a color key set and give you a new surface with transparency using an alpha channel. Then you can just use that to build your OpenGL texture.
There's a few details I can't really remember, but that's the basics.
There's a few details I can't really remember, but that's the basics.
Yes, I've read that all over (and via the documentation), but whenever I try to use it, for some reason, it seems not to work at all.
I found some really old code of mine (IIRC it worked, but I can't be sure) that does what you want:
You'll also need to make sure the proper OpenGL alpha testing stuff is turned on.
Edit: Oh, by the way, if you are using something like .tga or .png or anything else that supports alpha for your textures, you can just include the alpha information in those files and not worry about setting color keys and junk like that.
SDL_Surface * surface = IMG_Load("something.tga");// the color key is a disgusting shade of bright purpleSDL_SetColorKey(surface, SDL_SRCCOLORKEY, SDL_MapRGB(surface->format, 255,0,255));SDL_Surface * alphasurface = SDL_DisplayFormatAlpha(surface);// standard OpenGL stuff hereunsigned int gltex;glGenTextures(1, &gltex);glBindTexture(GL_TEXTURE_2D);glTexImage2D(GL_TEXTURE_2D, 0, 4, alphasurface->w, alphasurface->h, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, alphasurface->pixels);glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );SDL_FreeSurface(alphasurface);SDL_FreeSurface(surface);
You'll also need to make sure the proper OpenGL alpha testing stuff is turned on.
Edit: Oh, by the way, if you are using something like .tga or .png or anything else that supports alpha for your textures, you can just include the alpha information in those files and not worry about setting color keys and junk like that.
As hplus mentioned the best way is to cycle through the SDL_Surface using something like the SDL_GetPixel and SDL_PutPixel functions you can find in the SDL documentation and setting the pixels yourself. This will allow you to set multiple color keys and even change certain colors to different alpha values on load. Since you should only be doing this once when you load the texture the speed shouldn't be an issue unless you plan on loading lots of textures on the fly.
BradDaBug's code didn't seem to work at all for me.
I have blending enabled as below:
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
and I literally copied and pasted his code into my current function (with mild modifying, such as replacing the "something.tga" with filename, correcting his Binding and returning the gltex variable).
evillive2's comment on SDL_GetPixel and SDL_PutPixel sounds like a good idea, but whenever I go to use the two functions, it says that they both are undeclared (I have both SDL.h and SDL_image.h included in the file and I have even checked SDL's documentation for the functions; they don't seem to be actual functions in SDL or something).
Thanks again for all your help; I'll keep trying to crack this darn thing open.
I think, looking at my function, that part of my problem is that it loads the texture into one surface, Blits the surface onto another one after resizing it into a proper texture size (8, 16, 32, 64, 128, ...) and then converts that second surface into the OpenGL texture. I think that somewhere between the conversion between surface to surface or during the conversion from surface to OpenGL texture we have to set the color key and change the surface or the such into a surface with alpha transparency. Just a big brainstorm but so far I don't seem to have any luck with it.
I have blending enabled as below:
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
and I literally copied and pasted his code into my current function (with mild modifying, such as replacing the "something.tga" with filename, correcting his Binding and returning the gltex variable).
evillive2's comment on SDL_GetPixel and SDL_PutPixel sounds like a good idea, but whenever I go to use the two functions, it says that they both are undeclared (I have both SDL.h and SDL_image.h included in the file and I have even checked SDL's documentation for the functions; they don't seem to be actual functions in SDL or something).
Thanks again for all your help; I'll keep trying to crack this darn thing open.
I think, looking at my function, that part of my problem is that it loads the texture into one surface, Blits the surface onto another one after resizing it into a proper texture size (8, 16, 32, 64, 128, ...) and then converts that second surface into the OpenGL texture. I think that somewhere between the conversion between surface to surface or during the conversion from surface to OpenGL texture we have to set the color key and change the surface or the such into a surface with alpha transparency. Just a big brainstorm but so far I don't seem to have any luck with it.
Quote:Original post by codemastermm
evillive2's comment on SDL_GetPixel and SDL_PutPixel sounds like a good idea, but whenever I go to use the two functions, it says that they both are undeclared (I have both SDL.h and SDL_image.h included in the file and I have even checked SDL's documentation for the functions; they don't seem to be actual functions in SDL or something).
They aren't actually part of SDL. See here. You've got to add the functions to your project somewhere.
Edit: Are you blitting the image, then setting the color key and getting the alpha surface, or are you blitting after you do that? IIRC unless you specifically tell SDL to include alpha information when blitting (via SDL_SetAlpha()) it'll ignore it, and the new blitted surface won't have any alpha info.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement