Search code examples
c++opengltexturesblending

How to make white transparent


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.


Solution

  • 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);
        }
    }