#include <gl/glut.h>#include <iostream>#include <ft2build.h>#include FT_FREETYPE_Husing namespace std;#define PIXEL_SIZE 20 //字体的像素大小wchar_t ch = L'你';FT_Library ftLibrary;FT_Face ftFace;GLuint texture;void print(GLubyte *rgba);void ConvertMONOToRGBA(FT_Bitmap *source, GLubyte *rgba){ GLubyte *s = source->buffer; GLubyte *t = rgba; for(GLuint y = source->rows; y > 0; y--) { GLubyte *ss = s; GLubyte *tt = t; for(GLuint x = source->width >> 3; x > 0; x--) { GLuint val = *ss; for(GLuint i = 8; i > 0; i--) { tt[0] = tt[1] = tt[2] = tt[3] = (val & (1 << (i - 1))) ? 0xFF : 0x00; tt += 4; } ss += 1; } GLuint rem = source->width & 7; if(rem > 0) { GLuint val = *ss; for(GLuint x = rem; x > 0; x--) { tt[0] = tt[1] = tt[2] = tt[3] = (val & 0x80) ? 0xFF : 0x00; tt += 4; val <<= 1; } } s += source->pitch; t += source->width * 4; //pitch }}//FreeType的灰色模式:1个像素用1个字节保存。void ConvertGRAYToRGBA(FT_Bitmap *source, GLubyte *rgba) //灰度图转RGBA{ for(GLuint y = 0; y < source->rows; y++) { for(GLuint x = 0; x < source->width; x++) { GLubyte *s = &source->buffer[(y * source->pitch) + x]; GLubyte *t = &rgba[((y * source->pitch) + x) * 4]; t[0] = t[1] = t[2] = 0xFF; //RGB为255 t[3] = *s; //A通道存灰度图 } }}GLubyte* get_rgba(FT_Bitmap& bitmap){ int rgbaSize = bitmap.rows * bitmap.rows * 4; GLubyte *rgba = new GLubyte[rgbaSize]; switch(bitmap.pixel_mode) //像素模式 { case FT_PIXEL_MODE_MONO: //黑白 { // 将黑白转成RGBA ConvertMONOToRGBA(&bitmap, rgba); break; } case FT_PIXEL_MODE_GRAY: //灰度 { ConvertGRAYToRGBA(&bitmap, rgba); //灰度转RGBA break; } default: { memset(rgba, 0xFF, rgbaSize); break; } } return rgba;}GLubyte* get_rgba_2(FT_Bitmap& bitmap) //自己写的,对位图的理解有不足{ int rgbaSize = bitmap.rows * bitmap.rows * 4; GLubyte *rgba = new GLubyte[rgbaSize]; for(GLuint y = 0; y < bitmap.rows; y++) { for(GLuint x = 0; x < bitmap.width; x++) { GLubyte *s = &bitmap.buffer[y * bitmap.pitch + x / 8]; GLubyte *t = &rgba[((y * bitmap.width) + x) * 4]; if((*s & (0xC0 >> (x % 8))) == 0) //非字符像素 { t[0] = t[1] = t[2] = t[3] = 0x00; } else //字符像素 { t[0] = t[1] = t[2] = t[3] = 0xff; } } } return rgba;}void init(){ #pragma region FreeType的设置 // - 初始化FreeType对象 FT_Init_FreeType(&ftLibrary); FT_New_Face(ftLibrary, "C:\\WINDOWS\\Fonts\\simhei.ttf", //黑体中文字库 0, &ftFace); // - 设置 FT_Set_Pixel_Sizes(ftFace, PIXEL_SIZE, 0); //像素大小 // - 得到字符码的字形索引 FT_UInt uiGlyphIndex = FT_Get_Char_Index(ftFace, ch); if(uiGlyphIndex <= 0) { printf("未找到该字符的索引"); } FT_Load_Glyph(ftFace, uiGlyphIndex, FT_LOAD_DEFAULT); #pragma endregion #pragma region 生成位图 // - 生成位图:FreeType所得是8位的灰度图 if(ftFace->glyph->format != FT_GLYPH_FORMAT_BITMAP) { FT_Render_Glyph(ftFace->glyph, FT_RENDER_MODE_MONO); } // - 查看位图信息 printf("行:%d;列:%d\n", ftFace->glyph->bitmap.rows, ftFace->glyph->bitmap.width); printf("\n------ 位图信息 ------\n"); for(int iRow = 0; iRow < ftFace->glyph->bitmap.rows; iRow++) { for(int iCol = 0; iCol < ftFace->glyph->bitmap.width; iCol++) { printf("%d\t", ftFace->glyph->bitmap.buffer[iRow * ftFace->glyph->bitmap.pitch + iCol / 8]); } printf("\n"); } #pragma endregion #pragma region 打印成字体 printf("\n------ 查看字体信息 ------\n"); for(int iRow = 0; iRow < ftFace->glyph->bitmap.rows; iRow++) { for(int iCol = 0; iCol < ftFace->glyph->bitmap.width; iCol++) { auto index = iRow * ftFace->glyph->bitmap.pitch + iCol / 8; auto tmp = 0xC0 >> (iCol % 8); auto value = index & tmp; if((ftFace->glyph->bitmap.buffer[iRow * ftFace->glyph->bitmap.pitch + iCol / 8] & (0xC0 >> (iCol % 8))) == 0) { printf(" "); } else { printf("1"); } } printf("\n"); } #pragma endregion #pragma region 生成纹理 // 生成纹理 glEnable(GL_TEXTURE_2D); glGenTextures(1, &texture); glBindTexture(GL_TEXTURE_2D, texture); GLubyte* rgba = get_rgba(ftFace->glyph->bitmap); //GLubyte* rgba = get_rgba_2(ftFace->glyph->bitmap); print(rgba); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, ftFace->glyph->bitmap.width, ftFace->glyph->bitmap.rows, 0, GL_RGBA, GL_UNSIGNED_BYTE, rgba); delete rgba; glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glBindTexture(GL_TEXTURE_2D, 0); //解绑 #pragma endregion // 清空资源 FT_Done_Face(ftFace); FT_Done_FreeType(ftLibrary);}void myDisplay(void){ glClear(GL_COLOR_BUFFER_BIT); glClearColor(0, 0, 0, 0); // 画纹理 glBindTexture(GL_TEXTURE_2D, texture); glBegin(GL_QUADS); // 要注意字体纹理和OpenGL的绘制关系 glTexCoord2d(0, 0); //纹理 左下角 glVertex2f(-0.8f, 0.8f); //OpenGL 左上角 glTexCoord2d(0, 1); //左上角 glVertex2f(-0.8f, -0.8f); //左下角 glTexCoord2f(1.0f, 1.0f); //右上角 glVertex2f(0.8f, -0.8f); //右下角 glTexCoord2d(1, 0); //右下角 glVertex2f(0.8f, 0.8f); //右上角 glEnd(); glFlush();}int main(int argc, char *argv[]){ glutInit(&argc, argv); //初始化GLUT glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE); //初始化显示模式 glutInitWindowPosition(100, 100); //窗体位置 glutInitWindowSize(500, 500); //窗体大小 glutCreateWindow("OpenGL One Char"); //传入窗口名称,并开窗 init(); glutDisplayFunc(&myDisplay); //绘制的回调函数 glutMainLoop(); //循环绘制 return 0;}void print(GLubyte *rgba) //打印RGBA{ printf("\n----- R -----\n"); for(GLuint y = 0; y < ftFace->glyph->bitmap.rows; y++) { for(GLuint x = 0; x < ftFace->glyph->bitmap.width; x++) { GLubyte *s = &ftFace->glyph->bitmap.buffer[(y * ftFace->glyph->bitmap.pitch) + x]; GLubyte *t = &rgba[((y * ftFace->glyph->bitmap.pitch) + x) * 4]; printf("%d\t", t[0]); } printf("\n"); } printf("\n----- G -----\n"); for(GLuint y = 0; y < ftFace->glyph->bitmap.rows; y++) { for(GLuint x = 0; x < ftFace->glyph->bitmap.width; x++) { GLubyte *s = &ftFace->glyph->bitmap.buffer[(y * ftFace->glyph->bitmap.pitch) + x]; GLubyte *t = &rgba[((y * ftFace->glyph->bitmap.pitch) + x) * 4]; printf("%d\t", t[1]); } printf("\n"); } printf("\n----- B -----\n"); for(GLuint y = 0; y < ftFace->glyph->bitmap.rows; y++) { for(GLuint x = 0; x < ftFace->glyph->bitmap.width; x++) { GLubyte *s = &ftFace->glyph->bitmap.buffer[(y * ftFace->glyph->bitmap.pitch) + x]; GLubyte *t = &rgba[((y * ftFace->glyph->bitmap.pitch) + x) * 4]; printf("%d\t", t[2]); } printf("\n"); } printf("\n----- A -----\n"); for(GLuint y = 0; y < ftFace->glyph->bitmap.rows; y++) { for(GLuint x = 0; x < ftFace->glyph->bitmap.width; x++) { GLubyte *s = &ftFace->glyph->bitmap.buffer[(y * ftFace->glyph->bitmap.pitch) + x]; GLubyte *t = &rgba[((y * ftFace->glyph->bitmap.pitch) + x) * 4]; printf("%d\t", t[3]); } printf("\n"); }}