Textures displaying solid backgrounds instead of transparent pixels

Started by
4 comments, last by FXACE 11 years, 11 months ago
Hello, all. I am getting red backgrounds on my textures which should be transparent...

Here are my source image files:

http://dl.dropbox.co.../slider_bar.tga
http://dl.dropbox.co...ider_slider.tga

Here are all my OpenGL options:

glEnable( GL_TEXTURE_2D );
glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glBlendFunc(GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA);
glEnable(GL_BLEND);
glAlphaFunc(GL_NOTEQUAL, 1);
glEnable(GL_ALPHA_TEST);
glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f);
glViewport( 0, 0, 900, 600 );
glClear( GL_COLOR_BUFFER_BIT );
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
glOrtho(0.0f, 900, 600, 0.0f, -1.0f, 1.0f);
glMatrixMode( GL_MODELVIEW );
glScalef(1, -1, 1);
glDisable(GL_DEPTH_TEST);
glLoadIdentity();


Here is my texture loading/initialization code:

texture::texture(SDL_Surface *rawSurface)
{
if(listInitialized == false)
{
initList();

}

for(int a = 0; a < 256; a++)
{
if(textureFree[a] == true)
{

glTexture = a;
numTextures++;
textureFree[a] = false;
break;
}
}

SDL_PixelFormat pixF = *rawSurface->format;
std::cout << "BPP : " << (int) pixF.BytesPerPixel;

SDL_Surface *surface;

textureRect.w = nextPowerOfTwo(rawSurface->w);
textureRect.h = nextPowerOfTwo(rawSurface->h);
textureRect.x = 0;
textureRect.y = 0;

imageRect.w = rawSurface->w;
imageRect.h = rawSurface->h;
imageRect.x = 0;
imageRect.y = 0;

paddingW = textureRect.w - imageRect.w;
paddingH = textureRect.h - imageRect.h;

//where within the texture surface is the actual image?
SDL_Rect rectDestination;
rectDestination.w = imageRect.w;
rectDestination.h = imageRect.h;
rectDestination.x = paddingW;
rectDestination.y = paddingH;

GLint nOfColors = rawSurface->format->BytesPerPixel;
GLenum texture_format;

if (nOfColors == 4) // contains an alpha channel
{
if (rawSurface->format->Rmask == 0x000000ff)
{
std::cout << "format RGBA\n";
texture_format = GL_RGBA;
}
else
{
std::cout << "format BGRA\n";
texture_format = GL_BGRA;
}

} else if (nOfColors == 3) // no alpha channel
{
if (rawSurface->format->Rmask == 0x000000ff)
{
std::cout << "format RGB\n";
texture_format = GL_RGB;

}
else
{
std::cout << "format BGR\n";
texture_format = GL_BGR;
}

}

surface = SDL_CreateRGBSurface(SDL_SWSURFACE, textureRect.w , textureRect.h , 32, rawSurface->format->Rmask, rawSurface->format->Gmask, rawSurface->format->Bmask, rawSurface->format->Amask);
SDL_FillRect(surface, &textureRect, SDL_MapRGBA(surface->format, 255, 0, 0, 9));
SDL_SetAlpha(rawSurface, 0, SDL_ALPHA_OPAQUE);
SDL_SetAlpha(surface, 0, SDL_ALPHA_OPAQUE);
SDL_BlitSurface(rawSurface, &imageRect, surface, &rectDestination);
SDL_SetAlpha(rawSurface, SDL_SRCALPHA, 0);
SDL_SetAlpha(surface, SDL_SRCALPHA, SDL_ALPHA_OPAQUE);

glBindTexture(GL_TEXTURE_2D, textureBank[glTexture]);
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, 4, surface->w, surface->h, 0, texture_format, GL_UNSIGNED_BYTE, surface->pixels);

if(surface)
{SDL_FreeSurface( surface );}
}


and finally, rendering...

void texture::drawTexture(int x, int y)
{
x = x - paddingW;
// Bind the texture to which subsequent calls refer to
glBindTexture( GL_TEXTURE_2D, textureBank[glTexture] );
glColor4f(1,1,1,1);
glBegin( GL_QUADS );
//Bottom-left vertex (corner)
glTexCoord2i( 0, 0 );
glVertex3f( x, (y + textureRect.h), 0.0f );

//Bottom-right vertex (corner)
glTexCoord2i( 1, 0 );
glVertex3f( (x + textureRect.w), (y + textureRect.h), 0.f );

//Top-right vertex (corner)
glTexCoord2i( 1, 1 );
glVertex3f( (x + textureRect.w), y, 0.f );

//Top-left vertex (corner)
glTexCoord2i( 0, 1 );
glVertex3f( x, y, 0.f );
glEnd();
}


And my output...

AS6RM.png

Halp smile.png Thanks
Advertisement

glAlphaFunc(GL_NOTEQUAL, 1);
glEnable(GL_ALPHA_TEST);

by this code, pixels which have alpha:255 they will be invisible (ignored from drawing)... So, drop them...

glBlendFunc(GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA);

this function will not give you "transparent" effect as you expecting.
use this:

glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

Now, looking at images I see, they are 32-bit but their alpha channel filled with zero values (invisible)...
Best wishes, FXACE.
All right, here goes.

First, I tried just changing that line.



glEnable( GL_TEXTURE_2D );
glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
glAlphaFunc(GL_NOTEQUAL, 1);
glEnable(GL_ALPHA_TEST);


I got this output (there are barely-visible blue pixels where there should be transparency).

QVBMj.png

So then, I changed the alpha func around...:

glAlphaFunc(GL_GREATER, 0);

But I got this output:

http://i.imgur.com/QVBMj.png

totally black!
All right... now that I have seen your edit, I have removed the alpha testing stuff altogether. Here is what I get now:

2zYZ6.png
Okay, I see that the red pixels were actually ENTIRELY by my own hand... however, I cannot get blending to actually work. When I swap thevalues in glBlendFunc call, I get a black screen BTW.

vblF2.png
Nothing changed...
Again, let's check your "http://dl.dropbox.co...ider_slider.tga" (for example):
h6s08.jpg
Here, we see your image in photoshop and how much each channel (red,green,blue,alpha) filled. Now, are you not see that alpha channel is filled by black color (not visible)?
Now, let's imagine this image in your code:

glBlendFunc(/* src factor */GL_ONE_MINUS_SRC_ALPHA, /* dst factor */GL_SRC_ALPHA);

And put the values together:
dst.rgb = src.rgb * (1-src.a) + dst.rgb * src.a; : where "src" - "texel of your image" * "glColor", "dst" - OpenGL's color buffer.
Now, each pixel (of your image) in alpha channel has 0.0 (black). If to put this value into this formula it would be:
dst.rgb = src.rgb; which looks like "blend is disabled".
Now, useless code:

glAlphaFunc(GL_NOTEQUAL, 1);
glEnable(GL_ALPHA_TEST);

In fact, this will never fail with your image. Alpha test is used for to draw the pixels into buffer if their alpha channel passes "glAlphaFunc" condition.

Now, how to solve this:
First of all, you need to do something with you images (to paint into their alpha channel):
3SkoV.jpg
"I have just copied values from blue channel to alpha channel"...
Next, it's would be enough to do:

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

When you done everything with blending mode do this:

glDisable(GL_BLEND);

Usually this is need, because when you would draw some objects without blend, you would get some "unexpected blended pixels", and the reason would be "you forgot to disable blending mode".
Also, you don't need there GL_ALPHA_TEST.

Another thing:
It would be much better if you put "GL_RGBA" instead of "4" in "internalFormat" parameter of "glTexImage2D", not only for my eyes but for OpenGL too.

Best wishes, FXACE.

This topic is closed to new replies.

Advertisement