problem with texture and alpha blending

Hello,

I want to texture an image with a color key : I want to draw the texels of my texture that are not of a specified color.
So I have an array of RGBA pixels ; some of them (those whose color is the color key, let’s say green) have their alpha component set to 0, others are opaque. Then I do the following :

void *texels =...
GLuint textureID;

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

glGenTextures( 1, &textureID );
glBindTexture( GL_TEXTURE_2D, textureID );
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

glTexImage2D(
   GL_TEXTURE_2D,
   0,
   4,
   width, height,
   0,
   GL_RGBA,
   GL_UNSIGNED_BYTE,
   texels
);

glBegin(GL_TRIANGLE_STRIP);
   glTexCoord2f(0., 0.); glVertex2i( ...
glEnd();

What happens is that my transparent pixels appear with a white color.
Moreover, if I disable the alpa blending, my transparent pixels are still white (they should be green)!

(The depth of my display is 32 bpp.)

Has anybody an idea?
In my case, what is the most optimized blend function? I just want to use alpha blending in a “binary mode” (1->draw the pixel, 0-> don’t draw).

Thanks in advance.

Several things.

Look at you blending function : there is no mention of DST, so only SRc alphas are important. No need for a RGBA framebuffer. It doesn’t hurt, but good to know.

If by disabling blending you end up with white ‘green pixels’ then you messed up something around the glTexture2D call (check order of components, etc).

The perfect tool to do binary alpha transparency is not alpha blending but alpha testing :
glEnable(GL_ALPHA_TEST);
glAlphaFunc(GL_GREATER,0.5f); // read the doc and tweak to eliminate thin green borders

The code is correct AFAICS and should do what you want. The problem must lie elsewhere.

Originally posted by jean-bobby:
What happens is that my transparent pixels appear with a white color.
Moreover, if I disable the alpa blending, my transparent pixels are still white (they should be green)!

Three possible explanations:
1)the part of the code that’s supposed to replace the green texel’s alpha with 0 isn’t working correctly.

2)your clear color is white :stuck_out_tongue: (okay, this is obvious, I mentioned it just for completeness …)

3)you have some “combiner” state set up that does unexpected things. Look around your code for glTexEnvi calls and comment them all out. You can put them back in later if you found the problem.
If you’re using fragment programs or the like, disable them as well.

Thank you ZbuffeR and zeckensack! You were both right.
The problem was that I had to use the alpha test and not alpha blending. Also, I called glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); and that was why my “green pixels” were white (I’ve replaced GL_DECAL by GL_REPLACE).
For those who could be interested in texturing with a color key, the code is above (it works with SDL ; errors aren’t managed).
In fact, I have already a problem : after the drawing of my texture, I want to disable the alpha test. If I do that, the alpha test isn’t done for my texture. I call glFinish after the texture’s drawing (with no double buffering) and then glDisable( ALPHA_TEST ).
Must I keep the alpha test or is there a mean to disable it?

Thanks.

#include <GL/gl.h>
#include "SDL.h"

// Returns the next nearest power of two from n
int power_of_two( int n );

glEnable(GL_TEXTURE_2D);
glAlphaFunc(GL_GREATER,0.f);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,  GL_REPLACE);


SDL_Surface *image = IMG_Load(imageFileName);
Uint32 colorKey = ...

SDL_SetColorKey( image, SDL_SRCCOLORKEY, colorKey );

textureImage= SDL_CreateRGBSurface(
   SDL_SWSURFACE,
   image->w,
   image->h,
   32,
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
   0x000000FF,
   0x0000FF00,
   0x00FF0000,
   0xFF000000
#else
   0xFF000000,
   0x00FF0000,
   0x0000FF00,
   0x000000FF
#endif
);

SDL_FillRect( textureImage, NULL, colorKey );
SDL_BlitSurface( image, NULL, textureImage, NULL );
SDL_FreeSurface( image );

GLuint textureID;

glGenTextures( 1, &textureID );
glBindTexture( GL_TEXTURE_2D, textureID );
   glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
   glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );


int width = power_of_two( textureImage->w );
int height = power_of_two( textureImage->h );


glTexImage2D(GL_TEXTURE_2D,
   0,
   4,
   width, height,
   0,
   RGBA,
   UNSIGNED_BYTE,
   NULL
);


glTexSubImage2D( GL_TEXTURE_2D,
                 0,
                 0,
                 0,
                 textureImage->w,
                 textureImage->h,
                 RGBA,
                 UNSIGNED_BYTE,
                 textureImage->pixels );

GLfloat widthRate = ((GLfloat) textureImage->w) / ((GLfloat) width);
GLfloat heightRate = ((GLfloat) textureImage->h) / ((GLfloat) height);

glEnable( GL_ALPHA_TEST );
glBindTexture(GL_TEXTURE_2D, textureID);

GLfloat x = ...,
        y = ...;

glBegin(GL_TRIANGLE_STRIP);
   glTexCoord2f(0.,        0.);          glVertex2i(x,                   y  );
   glTexCoord2f(widthRate, 0.);          glVertex2i(x + textureImage->w, y  );
   glTexCoord2f(0.,        heightRate);  glVertex2i(x,                   y + height);
   glTexCoord2f(widthRate, heightRate);  glVertex2i(x + textureImage->w, y + textureImage->h);
glEnd();

//glDisable( GL_ALPHA_TEST );   => Doesn't work!!

Hope it can be useful.

The way you made it should work according to the specs. See the red book http://fly.cc.fer.hr/~unreal/theredbook/chapter10.html , the part about alpha test.

You may want to put some glIsEnabled(GL_ALPHA_TEST) around to see the actual value, and at which point it is enabled/disabled.

If really you can’t disable it correctly, you can instead set the glAlphaFunc(GL_ALWAYS,0.0). Do not forget to change it back.

A night has passed and now it works… I don’t know why it didn’t work before and it works now but that’s cool.
Thanks all