2
votes

I load two textures using a function like below:

GLuint LoadImage(std::string ImageTitle, GLenum Target)
{
    Image Img(ImageTitle.c_str());
    std::vector<std::uint8_t> Buffer, Out(((Img.Width() * Img.GetBitsPerPixel() + 31) / 32) * 4 * Img.Height());
    ImageToBuffer(Buffer, Img);
    FlipImageBytes(Buffer.data(), Out.data(), Img.Width(), Img.Height(), Img.GetBitsPerPixel());

    GLuint ID;
    glGenTextures(1, &ID);
    glBindTexture(Target, ID);
    glTexParameteri(Target, GL_TEXTURE_WRAP_S, Target == GL_TEXTURE_2D ? GL_REPEAT : GL_CLAMP_TO_EDGE);
    glTexParameteri(Target, GL_TEXTURE_WRAP_T, Target == GL_TEXTURE_2D ? GL_REPEAT : GL_CLAMP_TO_EDGE);
    glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(Target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexImage2D(Target, 0, Img.GetBitsPerPixel() == 32 ? GL_RGBA : GL_RGB, Img.Width(), Img.Height(), 0, Img.GetBitsPerPixel() == 32 ? GL_BGRA : GL_BGR, GL_UNSIGNED_BYTE, Out.data());
    return ID;
}

The first texture is a Map and I draw it on screen normally. The second texture is Black with Red text on it and that's the one I want to draw on top of the Map texture. However, I want to ignore the black pixels so that it only draws the red text.

I draw using the following:

void DrawTexture(GLenum Target, GLuint ID, float X1, float Y1, float X2, float Y2, int Width = 1, int Height = 1)
{
    //glEnable(Target);
    //glBindTexture(Target, ID);
    glBegin(GL_QUADS);
        glTexCoord2f(0, 0);
        glVertex2f(X1, Y1);

        glTexCoord2f(0, Height);
        glVertex2f(X1, Y2);

        glTexCoord2f(Width, Height);
        glVertex2f(X2, Y2);

        glTexCoord2f(Width, 0);
        glVertex2f(X2, Y1);
    glEnd();
    glDisable(Target);
}


int X1 = 0, Y1 = 0, X2 = 512, Y2 = 512;
            glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
            glPushMatrix();


            //Draw MAP.
            glEnable(GL_TEXTURE_2D);
            glBindTexture(GL_TEXTURE_2D, ID);
            glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

            glEnable(GL_BLEND);
            glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
            DrawTexture(GL_TEXTURE_2D, MAPID, 0, 0, 512, 512);
            glFlush();


            //Draw TEXT..
            glBindTexture(GL_TEXTURE_2D, ID2);
            glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
            glBlendFunc(GL_ONE, GL_DST_ALPHA);
            DrawTexture(GL_TEXTURE_2D, TEXTID, 0, 0, 512, 512);

            glDisable(GL_BLEND);
            glDisable(GL_TEXTURE_2D);

            glPopMatrix();
            SwapBuffers(DC);
            Sleep(1);

What I'm trying to do:

std::vector<std::uint8_t> Buffer; 
    //Fill Buffer with Pixels. 

    glDrawPixels(Width, Height, .........);

enter image description here

However, it does not make the black pixels on the second image transparent. How can I make it draw every pixel except for Black only in the second texture? So draw the first texture normally and draw the second ignoring black.

I tried using glDrawPixels (I'd prefer to use this for drawing the black Text pixels if possible)

Any ideas?

2

2 Answers

2
votes

The proper way to do this is to use alpha blending, with an alpha channel. Your texture is probably 32bits anyway, with a fully opaque alpha channel at 255. Using your favorite picture editor, you can probably convert your picture to copy the red channel to your alpha channel, which will give you exactly what you need. It also will support semi-transparent textures as well.

Otherwise, what you're looking for is alpha test which would also require the usage of the alpha channel, unless you're using indexed colors.

1
votes
glBlendFunc(GL_ONE, GL_DST_ALPHA);

Why are you using the destination alpha? The source color is what tells whether the color should be written or not; the destination color's alpha has nothing to do with it.

You don't say whether your "black and red" texture has an alpha channel in it. So I will assume either that it does or that you know how to set one up properly.

For your needs, you need to linearly interpolate between the source and destination based on the alpha. And to do that, you use a blend function like this: glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA). That does linear interpolation between the two colors.