It’s me once again, with a question resulted from my attempts to get texture mapped fonts to work on various platforms and configurations.
Inspite of all my efforts, at least on some notebooks (like DELL PRECISION) with mobile nVIDIA graphic cards under Windows XP and RedHat Linux 8 I get rectangles filled with the current color instead of character glyphs, or rectangles filled with “current-colored” and white horizontal stripes (assuming that the background color is white).
One more example of problematic configuration: graphic card S3 SAVAGE/IX (driver version 5.12.1.7062 of 20/03/2001) under MS Windows 2000 Pro.
I failed to resolve the problem by updating the graphic driver: in my cases, it is almost impossible to find an updated version of graphic driver.
I can make the text visible (for testing purpose) by specifying “internal_format” and “format” arguments for glTexImage2D() function different from GL_INTENSITY and GL_LUMINANCE_ALPHA - for instance, GL_RGBA. However, I cannot change text color in this case.
Probably, there is an alternative and more reliable combination of texture parameters that would allow to draw texture-mapped fonts (with transparent empty pixels between glyphs and a possibility to change font color without re-building the texture) - I would be extremely thankful for any suggestions.
Some code excerpts (nothing particular in fact - it works well on most Win2k/WinXP/RedHat 8 stations):
// 1. Computing necessary geometrical font parameters,
// preparing a font image in “pixels” variable
// For each pixel, two bytes - luminance and alpha - are stored:
// both zero for empty pixels and 0xff for image pixels
char* pixels = new char[myTexFontWidth * myTexFontHeight * 2];
// …
// 2. Creating a texture with character glyphs
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glGenTextures(1, &myTexFont);
glBindTexture(GL_TEXTURE_2D, myTexFont);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, myMinMagFilter);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, myMinMagFilter);
glTexImage2D(GL_TEXTURE_2D,
0,
GL_INTENSITY,
myTexFontWidth,
myTexFontHeight,
0,
GL_LUMINANCE_ALPHA,
GL_UNSIGNED_BYTE,
pixels);
// …
// 3. Using the texture to display text from
// “theStr” variable
double aXScale = 1., aYScale = 1.;
// store attributes
glPushAttrib( GL_ENABLE_BIT | GL_TEXTURE_BIT );
if ( !myIsResizeable )
{
glGetDoublev (GL_MODELVIEW_MATRIX, modelMatrix);
aXScale = modelMatrix[0];
aYScale = modelMatrix[5];
}
glEnable(GL_TEXTURE_2D);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, myMinMagFilter);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, myMinMagFilter);
glPixelTransferi(GL_MAP_COLOR, 0);
glAlphaFunc(GL_GEQUAL, 0.05F);
glEnable(GL_ALPHA_TEST);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
glBindTexture(GL_TEXTURE_2D, myTexFont);
glBegin(GL_QUADS);
if ( myIsResizeable && theScale > 0. )
{
aXScale = aXScale / theScale;
aYScale = aYScale / theScale;
}
// aFontHeight contains the font height in pixels
// coming from font metrics
theY = theY - ( myTexFontHeight - aFontHeight ) / aYScale;
double aLettBegin, aLettEnd, aDY = ( myTexFontHeight - 1 ) / aYScale, aDX;
char aLetter;
int aLettIndex;
for( int i = 0, l = strlen( theStr ); l > i; i++ )
{
aLetter = theStr[i];
aLettIndex = (int)aLetter - FirstSymbolNumber;
aLettBegin = (double)myPositions[aLettIndex] / ( (double)myTexFontWidth - 1. );
aLettEnd = aLettBegin + ( (double)myWidths[aLettIndex] - 1. ) / ( (double)myTexFontWidth - 1. );
aDX = ( (double)myWidths[aLettIndex] - 1. ) / aXScale;
glTexCoord2d( aLettBegin, 0.0 );
glVertex3d( theX, theY, 1.0 );
glTexCoord2d( aLettBegin, 1.0 );
glVertex3d( theX, theY + aDY, 1.0 );
glTexCoord2d( aLettEnd, 1.0 );
glVertex3d( theX + aDX, theY + aDY, 1.0 );
glTexCoord2d( aLettEnd, 0.0 );
glVertex3d( theX + aDX, theY, 1.0 );
theX += aDX + mySeparator / aXScale;
}
glEnd();
// restore attributes
glPopAttrib();
Best regards,
Sergey