PDA

View Full Version : Transparent backgrounds



ti83magic
05-12-2009, 11:51 AM
Hey hey :)

I read the LazyFoo tutorial about colorkeying in SDL, which I got working without much trouble. However, I'm trying to get the same effect in openGL, drawing 2d graphics- and with this I seem to have a LOT more trouble. Here goes:

This is how I load a texture into openGL, code which I got from another site. First I load the PNG into an SDL surface, and then convert that to an opengl texture:



uint cTextureManager::LoadTextureFromFile(std::string Filename) {
SDL_Surface * surface = NULL;
int x,y,
offset;
Uint32 * rawPixels;

surface = IMG_Load(Filename.c_str());

if(surface == NULL) {
cout << "Failed to load the image: " << Filename << ", Error: " << SDL_GetError() << endl;
return 0;
} // if

return LoadTextureFromMemory(surface, Filename);
} // LoadTextureFromFile()


uint cTextureManager::LoadTextureFromMemory(SDL_Surface * Surface,
std::string Filename) {
GLuint texture;

glEnable(GL_TEXTURE_2D);

glPixelStorei(GL_UNPACK_ALIGNMENT,4);

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

glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);

glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTE R, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTE R, GL_NEAREST);

SDL_PixelFormat *fmt = Surface->format;

//if there is alpha
if (fmt->Amask) {
/// \note Used to be BGRA, altered back to my own needs.
gluBuild2DMipmaps(GL_TEXTURE_2D,4,Surface->w,Surface->h,GL_RGBA,
GL_UNSIGNED_BYTE,Surface->pixels);
} else { // no alpha
gluBuild2DMipmaps(GL_TEXTURE_2D,3,Surface->w,Surface->h,GL_RGB,
GL_UNSIGNED_BYTE,Surface->pixels);
} // if

//make our new texture format
sTexture Tex;

Tex.Texture = texture;
Tex.Filename = Filename;

Tex.Width = Surface->w;
Tex.Height = Surface->h;

SDL_FreeSurface(Surface);

//lets find out the next number to use in the map
uint place;

if( m_Textures.empty() ) {
place = 1;
} else {
place = m_Textures.size() + 1;
} // if

//set the map accordingly and return its id/place
m_Textures[ place ] = Tex;

return place;
} // LoadTextureFromMemory()

This is how I draw it:

void cTextureManager::DrawTexture(uint TextureID, GLfloat X, GLfloat Y,
GLfloat Scale, GLfloat Rotation, GLfloat red,
GLfloat green, GLfloat blue, GLfloat alpha) {
//check if the right texture is bound
if( g_Graphics->CurrentTexture != TextureID ) {
//bind texture
glBindTexture(GL_TEXTURE_2D, m_Textures[TextureID].Texture );

//set graphics varible
g_Graphics->CurrentTexture = TextureID;
} // if

//scale the points if needed
GLfloat width = m_Textures[ TextureID ].Width * Scale;
GLfloat height = m_Textures[ TextureID ].Height * Scale;

glLoadIdentity();
glTranslatef(X - g_Camera->GetXposition(), Y - g_Camera->GetYposition(), 0.0);
glScaled(Scale, Scale, 0);
glRotatef(Rotation,0.0f,0.0f,1.0f);

//draw the quad
glBegin(GL_QUADS);
glColor4f(red, green, blue, alpha);

//Top-left vertex (corner)
glTexCoord2f(0, 1);
glVertex2f(0, 0);

//Bottom-left vertex (corner)
glTexCoord2f(0, 0);
glVertex2f(0, height);

//Bottom-right vertex (corner)
glTexCoord2f(1, 0);
glVertex2f(width, height);

//Top-right vertex (corner)
glTexCoord2f(1, 1);
glVertex2f(width, 0); // the zero here might be Y, seemed like a bug in the original.
glEnd();
} // DrawTexture()


Now, it doesn't seem to work if I do some colorkeying on the sdl surface before passing it to the load from memory function. In fact, even loading png's with an alpha channel doesn't work; the transparant background I see in my photo-editor is simply white in my application. I must be making a thinking mistake somewhere, does anyone have a clue what I'm doing wrong? Been trying to get this working for three days now. I also tinkered a bit with direct pixel calculations on the sdl layer, but to no avail.

My goal is to make a certain color (magic pink, or #FF00FF) to an alpha of 0, the rest to 255. How can I do this effectively?

Tony

dletozeun
05-12-2009, 12:52 PM
My goal is to make a certain color (magic pink, or #FF00FF) to an alpha of 0, the rest to 255. How can I do this effectively?


You can set the pink color as transparent using a shader, but the result will be bad with linear filtering enabled.

IMO, the best you can do is preprocess the opengl texture data and set 0 to every pink pixels alpha. Then create a RGBA texture with Opengl and enable alpha test.

ti83magic
05-13-2009, 04:28 AM
Hey again :)

After some more testing, it seems that the problem lies at SDL not reading the image well enough anymore. The Alpha mask is always zero, even when loading alpha masked png's. I'll take the question elsewhere mate, thanks for the help anyways :)

Tony

EDIT: Good god, when will the hurting stop. It's even worse; I have been trying to fix someone else's bug for three days now. Apparently, when creating an alpha layer PNG with the old version of Paint Shop Pro I have, if you use the 'quick fix' button, it creates a DIFFERENT PNG than when you save it as a PNG through the regular menu. SDL Image likes the latter, and despises the first. GRMBL...