4
votes

I am playing with OGL's blending. I have a white background. I draw quad on this background. The quad is binded with white and black texture. Colors array is filled with color and alpha values:

for (i = 0; i < IMAGE_WIDTH; i++) {
    for (j = 0; j < MAGE_HEIGHT; j++) {
        c = ((((i&0x8)==0)^((j&0x8))==0))*255;
        Image[i][j][0] = (GLubyte) c;
        Image[i][j][1] = (GLubyte) c;
        Image[i][j][2] = (GLubyte) c;
        Image[i][j][3] = (GLubyte) 255;
    };

Display textured quad:

glEnable(GL_BLEND);
glBlendFunc (GL_SRC_ALPHA, GL_ONE);    
glDisable (GL_DEPTH_TEST);                                              

glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texCheck);        

glLoadIdentity();                                                                      
glTranslatef (0.0f, 0.0f, -9.0f);

glBegin (GL_QUADS);    
    glColor3f (1.0f, 1.0f, 1.0f);
    glTexCoord2f(0.0, 0.0); glVertex3f(-5.0f, -5.0f, 0.0f);
    glTexCoord2f(0.0, 1.0); glVertex3f( 5.0f, -5.0f, 0.0f);
    glTexCoord2f(1.0, 1.0); glVertex3f( 5.0f, 5.0f, 0.0f);
    glTexCoord2f(1.0, 0.0); glVertex3f(-5.0f, 5.0f, 0.0f);
glEnd();

glDisable(GL_TEXTURE_2D);
glEnable (GL_DEPTH_TEST);                                              
glDisable (GL_BLEND);  

Black color of the binded texture on the quad is invisible and works fine. What should I do to make white color of binded texture transparent and black color of binded texure not transparent.

2

2 Answers

1
votes

You have to solve 2 issues:

  1. If different texels of a texture should be blended in different way, then you have to set different alpha channels. If, as in your case, black colored texels should be opaque and white colored texels should be invisible, then the alpha channel of the black texel has to be set to 255 and the alpha channel of the white texel has to be set to 0. Note, any alpha value between 0 and 255 causes a transparent effect, which is more or less strong.

  2. you have set the blending function to glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)


Blending calculates a new target color (the fragment color in the frame buffer), by a function of the original target color and the source color (in your case the color of the texel).

If you set the glBlendFunc with the functions (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) and you use glBlendEquation with the equation GL_FUNC_ADD (this is default) then the destination color is calculated as follows:

C_dest_new = C_src * A_src + C_dest * (1-A_src)

If the alpha channel is equal to 0.0:

C_dest_new = C_src * 0 + C_dest * (1-0) = C_dest

If the alpha channel is equal to 1.0 (255):

C_dest_new = C_src * 1 + C_dest * (1-1) = C_src    

Extension to the answer

To set the alpha channel of white texels to 0, the code, which generates the texture, has to be changed somehow like this:

for (i = 0; i < IMAGE_WIDTH; i++) {
    for (j = 0; j < MAGE_HEIGHT; j++) {
        c = ((((i&0x8)==0)^((j&0x8))==0))*255;
        Image[i][j][0] = (GLubyte) c;
        Image[i][j][1] = (GLubyte) c;
        Image[i][j][2] = (GLubyte) c;
        Image[i][j][3] = (GLubyte) (255 - c);
    }
}
2
votes

Your blend function should be

glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

Supplying GL_ONE as second parameter means that destination color value is taken without taking source alpha value into account so no proper blending occurs.