您的位置:首页 > 运维架构 > Linux

Linux下Modern OpenGL显示汉字

2017-08-24 14:48 671 查看

Linux下Modern OpenGL显示汉字

前一篇中解码出来的图像已经能够正常颜色格式转换和显示了,现在遇到了新的问题:显示文字

本以为这是一个很简单的东西,因为之前使用SDL时直接应用sdl_ttf库很简单的就实现了文字渲染工作,结果万万没想到OpenGL中实现这个小功能竟然没有现成API,这对于CV码农来说简直是灾难。没办法,看了这么久的GL硬着头皮也要走下去,经过两天不断的查资料和编码调试终于大功告成!老版本的OpenGL直接使用glut加载字符就能完成显示,modern OpenGL则需要使用shader结合vaovbo完成渲染,下面介绍如何实现

FreeType2

freetype2是一个字体库,能够完成加载字体文件,提取字符,生成bitmap等工作

FreeType is a software development library that is able to load fonts, render them to bitmaps and provide support for several font-related operations. It is a popular library used by Mac OS X, Java, PlayStation Consoles, Linux and Android to name a few. What makes FreeType particularly attractive is that it is able to load TrueType fonts.


关键代码

FT_Library ft;

if (FT_Init_FreeType(&ft))

std::cout << "ERROR::FREETYPE: Could not init FreeType Library" << std::endl;

FT_Face face;

if (FT_New_Face(ft, "fonts/arial.ttf", 0, &face))

std::cout << "ERROR::FREETYPE: Failed to load font" << std::endl;


这部分代码完成初始化工作

if (FT_Load_Char(face, 'X', FT_LOAD_RENDER))

std::cout << "ERROR::FREETYTPE: Failed to load Glyph" << std::endl;


完成加载字符工作

glTexImage2D(

GL_TEXTURE_2D,

0,

GL_RED,

face->glyph->bitmap.width,

face->glyph->bitmap.rows,

0,

GL_RED,

GL_UNSIGNED_BYTE,

face->glyph->bitmap.buffer

);


完成字符到GL纹理的存储

struct Character

{

GLuint TextureID;   // ID handle of the glyph texture

glm::ivec2 Size;    // Size of glyph

glm::ivec2 Bearing;  // Offset from baseline to left/top of glyph

GLuint Advance;    // Horizontal offset to advance to next glyph

};


这是存储字符纹理和大小、偏移等参数的结构体

要显示中文的话需要加载中文字体,可以去网上下载自己喜欢的或者去win里面拷

我使用的是谷歌出品的思源宋体,挺好看的

String转WString

英文字符占一字节,中文字符占两个,所以需要把String转成Wstring

这里我使用C++11的codecvt类完成,话说C++做文字处理真是蛋疼,这活在Python里根本不算事

include <locale>

include <codecvt>

using convert_typeX = std::codecvt_utf8<wchar_t>;

std::wstring_convert<convert_typeX, wchar_t> converterX;

std::wstring wide = converterX.from_bytes(text);


还算简单,五行代码完活

纹理存储

每一个字符都是一张纹理,如果需要显示很多文字的话,那么每次刷新都为文字创建纹理会很耗费资源,所以使用map存储显示过的文字,就第一次使用这个字符时需要创建纹理分配存储,后面可以直接去map中找,节省计算资源。

std::map<wchar_t, Character> Characters;

if(Characters.find(c)==Characters.end())

{

//生成纹理,绑定,存储等等

Characters.insert(std::pair<wchar_t, Character>(c, character));

}

else

{}


效果



代码

将文字显示功能整合了一下,实际使用只需要两步

textRender tr(800,600,"/home/wnl/workspace/textRender/SourceHanSerifCN-Bold.otf");


参数是窗口大小和字体路径

渲染循环中

std::string s("WuNL的OpenGL文字显示测试");

tr.RenderText(s,(GLfloat)35.0f,(GLfloat)35.0f,1.0f, glm::vec3(0.5, 0.8f, 0.2f));


rendertext参数为需要渲染的文字,显示位置,大小比例,颜色

实现代码在我的github上,网址为https://github.com/WuNL/textRender

觉得我的代码有些帮助请打颗星,谢谢
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  opengl linux freetype2