Alpha-blending with OpenGL in SDL (multiple textures)

I’ve been trying for the past day or so to get alpha-blending working
with textures. The situation is as follows:

I have a main texture that is updated and sent to the SDL window each
frame. I’d like to use textured fonts, and as such, I’ve created a
font texture holding 256 glyphs. So when I draw fonts, I use
glTexSubImage2D to cut out the appropriate font, and draw it over the
texture shown onscreen.

My problem is with alpha-blending. I want the current glyph (8x8
pixels) to be drawn, but only the parts that make up the foreground of
the glyph. So I assumed that I’d set the foreground color to
0x808080FF (indicated a light grey with full opacity) and the
background to 0x0 (indicating full transparency).

It doesn’t seem to be working out. The following is part of the code:

glEnable(GL_BLEND);
glEnable(GL_TEXTURE_2D);
glBegin(GL_QUADS);
glTexCoord2f(0.0, 0.0); glVertex2i(xorig, yorig );
glTexCoord2f(1.0, 0.0); glVertex2i(xorig+8, yorig );
glTexCoord2f(0.0, 1.0); glVertex2i(xorig+8, yorig+8);
glTexCoord2f(1.0, 1.0); glVertex2i(xorig, yorig+8);
glEnd();

When I do this, it never seems to use the colors in the glyph texture,
but uses some other color. It seems that glEnable(GL_BLEND) turns on
alpha-blending for the whole texture, but it doesn’t use the alpha
setting of each pixel in the texture.

I’m pretty sure this has something to do with glBlendFunc(), but I’m not
having much success understanding that either.

Any help is greatly appreciated, because I’ve lost enough hair over
this.

Steve

First of all, comp.graphics.api.opengl is great for answering questions
like this.

Stephen Anthony wrote:

My problem is with alpha-blending. I want the current glyph (8x8
pixels) to be drawn, but only the parts that make up the foreground of
the glyph. So I assumed that I’d set the foreground color to
0x808080FF (indicated a light grey with full opacity) and the
background to 0x0 (indicating full transparency).

You need to set the alpha-channel of the image to values between 0 and

  1. If you do this, you should set the blendfunc to:

glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

  • which is a linear interpolation between the color of the texture you
    draw with, and the color that is already in the framebuffer.

If you don’t want to mess about with blendfuncs, you might use
glAlphaFunc(GL_GREATER, 0.5f);

  • but this requires actually setting an alpha-value for the texture.

You could blend according to the color of the texture though, using
glBlendFunc(GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR);

  • which would give the same result for monocrome textures.

It doesn’t seem to be working out. The following is part of the code:

glEnable(GL_BLEND);
glEnable(GL_TEXTURE_2D);
glBegin(GL_QUADS);
glTexCoord2f(0.0, 0.0); glVertex2i(xorig, yorig );
glTexCoord2f(1.0, 0.0); glVertex2i(xorig+8, yorig );
glTexCoord2f(0.0, 1.0); glVertex2i(xorig+8, yorig+8);
glTexCoord2f(1.0, 1.0); glVertex2i(xorig, yorig+8);
glEnd();

You forget to bind the texture.

glBindTexture(GL_TEXTURE_2D, texno);

  • where ‘texno’ is an integer returned from some code looking like (if
    you don’t have the following code somewhere, it should be placed before
    glBindTexture):
    GLuint texno;
    glGenTextures(1, &texno);

Another thing to remember is, that you always need to set wrap, min and
mag filters. The following piece of code should work:

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

I can’t tell if you need to draw several letters on top of each other,
but if you do, you should remember to draw them “back to front”, ie.
draw the letter you actually want to be shown on the screen, last.

Hope this helps,
\Mikkel Gjoel

First of all, comp.graphics.api.opengl is great for answering
questions like this.

Noted, and I will be following up on this message there.

You need to set the alpha-channel of the image to values between 0
and 1. If you do this, you should set the blendfunc to:

glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

  • which is a linear interpolation between the color of the texture
    you draw with, and the color that is already in the framebuffer.

If you don’t want to mess about with blendfuncs, you might use
glAlphaFunc(GL_GREATER, 0.5f);

  • but this requires actually setting an alpha-value for the texture.

You could blend according to the color of the texture though, using
glBlendFunc(GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR);

  • which would give the same result for monocrome textures.

OK, here is some sample code that was lifted from a few tutorials. It
doesn’t seem to work either.

GLubyte subimage[100][100][4];
for(int i=0;i<100;i++)
{
for(int j=0;j<50;j++)
{
subimage[i][j][0] = (GLubyte) 0xff;
subimage[i][j][1] = (GLubyte) 0;
subimage[i][j][2] = (GLubyte) 0;
subimage[i][j][3] = (GLubyte) 0xff;
}
for(int j=50;j<100;j++)
{
subimage[i][j][0] = (GLubyte) 0xff;
subimage[i][j][1] = (GLubyte) 0;
subimage[i][j][2] = (GLubyte) 0;
subimage[i][j][3] = (GLubyte) 0;
}
}

GLuint tex;
glEnable(GL_TEXTURE_2D);
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_2D, tex);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 100, 100,
GL_RGBA, GL_UNSIGNED_BYTE, subimage);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
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_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

glBegin(GL_QUADS);
glTexCoord2f(0.0, 0.0); glVertex2i(20, 60 );
glTexCoord2f(1.0, 0.0); glVertex2i(120, 60 );
glTexCoord2f(0.0, 1.0); glVertex2i(120, 160);
glTexCoord2f(1.0, 1.0); glVertex2i(20, 160);
glEnd();

Now from my (limited) understanding, this should create a texture that
is fully opaque and red in one half, and fully transparent in the other
half. That’s the type of code I need. But that’s not what’s
happening. Instead, the texture is drawn totally opaque in a color
that I set elsewhere previously (light grey). And if I change the
blending to ‘glBlendFunc(GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR)’, then
the texture is drawn somewhat transparently, but still in the light
grey color.

Obviously, it isn’t using the colors from the texture itself, and thats
what I need to know how to do.

I can’t tell if you need to draw several letters on top of each
other, but if you do, you should remember to draw them “back to
front”, ie. draw the letter you actually want to be shown on the
screen, last.

No, I wouldn’t need to draw over characters. But the character textures
are drawing over the main window texture.

Thanks for any help,
SteveOn Sunday 02 November 2003 06:20 pm, Mikkel Gj?l wrote: