How do I render a GL_ALPHA texture?

5k Views Asked by At

I'm trying to work with the FTGL font library, to create a texture-mapped font and render it to the screen. The library creates a texture in the GL_ALPHA format to hold the font glyphs, and then when you tell it to render a string, it goes through and glBegin(GL_QUADS) and renders each glyph, exactly how you'd expect.

Only problem is, I'm not getting any text. In one scenario, I get solid black boxes instead of text, in another I get nothing. I've run the code under gDEBugger to ensure that the texture is getting uploaded and set up properly, and everything looks right, but I'm still not seeing any output.

I've tried the obvious stuff. Calling glColor beforehand to try to set a text color does nothing. Neither does attempting to ensure that alpha-blending will work properly, like so:

glEnable(GL_ALPHA_TEST);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

Does anyone have any idea what I'm missing, in order to make rendering from a GL_ALPHA texture to the screen show up properly?

1

There are 1 best solutions below

1
On

It's clear after an examination of FTGL's code that the API is designed to do the text rendering itself. You're expected to call its rendering functions, which will make the OpenGL calls internally.

To put it another way, FTGL is not designed to load a font into a texture, then give you that texture object and have you draw the glyphs yourself. That doesn't mean you can't, only that the API is not going to help you do it.

The reason you get black is because GL_ALPHA textures return zeros for the RGB component when accessed. Since you use GL_MODULATE in your texture environment, that's going to multiply zero by the RGB part of the color.

To do what you intend, you need to set the GL_TEXTURE_ENV_MODE to GL_COMBINE instead of GL_MODULATE. Which means you need to use the combine environment mode, which isn't simple. Having abandoned fixed-function for shaders pretty much as soon as they existed, I haven't touched combiners in a long time. So take what follows with a grain of salt. Here's a guess at what the environment code should look like:

glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);

glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PRIMARY_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);

glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);

What you want to do is generate a color where the RGB part comes from glColor and the Alpha part comes from the texture. This is how you do that.

In English, the first line says that the texture environment mode is "combine", which activates a more complicated operation mode. The next three lines specify how the RGB part of the color is generated. The GL_COMBINE_RGB set to GL_REPLACE means that the source RGB value 0 will be what the output RGB is. Setting GL_SRC0_RGB to GL_PRIMARY_COLOR means that source RGB value 0 is the primary color, which is the color generated by vertex processing (ie: unless you're using lighting, this is just what you passed with glColor). Setting GL_OPERAND0_RGB to GL_SRC_COLOR means to take the color as it is (there are special operations you can do, like take 1 - the color or whatever).

The next 3 lines set up where the alpha part of the output color comes from. The GL_COMBINE_ALPHA set to GL_REPLACE means that the source alpha value 0 (different from the source RGB value 0) will be what the output alpha is. Setting GL_SRC0_ALPHA to GL_TEXTURE means that the source alpha value 0 comes from the texture of the current texture unit. Setting GL_OPERAND0_ALPHA to GL_SRC_ALPHA means to take the alpha as it is (as before, you could apply some transform to the alpha here).

Alternatively, if your OpenGL implementation has ARB_texture_swizzle available, you can set up a swizzle mask to effectively transform the GL_ALPHA format into GL_INTENSITY. Then you can use GL_MODULATE as your GL_TEXTURE_ENV_MODE. However, you have to make sure that your blend mode is glBlendMode(GL_ONE, GL_ONE_MINUS_SRC_ALPHA). This is necessary because GL_MODULATE will multiply the color by the alpha. If you used GL_SRC_ALPHA instead of GL_ONE, you would be doing the multiply by alpha twice (once in the texture env stage, once in the blend stage).