opengl文字显示

http://www.opengl.org/resources/features/fontsurvey/

http://blog.csdn.net/is01sjjj/archive/2006/12/07/1433103.aspx

 

字体简介:

点阵字库

包括现在,有很多游戏都还是使用的点阵字库。因为操作起来比较方便,加上这方面的经验已经积累了好几年了。通常如果只是一种字体就可以满足需要的话,它会是一个比较好、快的解决办法。但是它有3个缺点:

1. 如果放大显示,不做处理的话,显示出来的汉字,是很难看的。

2. 像是UCDOS所提供的点阵字库,只有24点阵的有几种字体,如:宋体、黑体、揩体…,而16点阵的好象就只有宋体一种。

3. 点阵字库,通常是有版权的,尤其是第三方制作的汉字库(如:方正)。

在这样的情况下,当我们写好这样的一个显示函数,就算是解决了如:放大、快速显示等问题的话,可供选择的字体还是太过于局限了。所以,在字体的要求比较强的情况下,点阵字库并不是一个好的解决方法,他不够灵活。尽管我们对于它的操作是如此得熟练,可以写出优美的代码来展示我们的编程技巧。

TTF

TTF是True Type Font的简称。在Windows/Fonts目录下面,我们可以看到许多后缀为ttf的文件,它就是接下来我们接下来所要谈到的。

TTF是一种矢量字库。我们经常可以听到矢量这个词,像是FLASH中的矢量图形,在100*100分辨率下制作的flash,就算它放大为全屏,显示出的画面也不会出现马赛克。所谓矢量,其实说白了就是用点和线来描述图形,这样,在图形需要放大的时候,只要把所有这个图形的点和线放大相应的倍数就可以了。而且,在网站上有很多的TTF字库可以下载,或者你可以去买一些专门的字库光盘。然后在你发行你精心制作的游戏时,可以顺便捎上这些后缀为.ttf的文件就行了。包括Quake这样的惊世之作,也都是用的TTF字库。

这样,我们就可以解决点阵汉字的一些问题。通过TTF,我们在字体的质量和字库的数量上获得了暂时性的胜利。


双字节字体:

       汉字是由2个字节保存,而英文只需要1个。而判断一个字是否是汉字,只需判断第1个byte是否>128(在原来的GB2312中,汉字的2个字节都是>128的。而新的GBK字库,汉字的第2个字节不一定>128,我想这是扩大了字库容量的原因。我的意思是说,如果给一个字符串你,随机给其中一个位置,然后我问你这个位置是什么?你的回答只能是:1 英文 2 汉字的首字节 3 汉字的尾字节。而这个问题的解法,为了稳妥起见,你必须从字符串的开始判断起)。也就是说在char[3]中,如果保存的是汉字,则char[0]保存汉字第1个字节,char[1]保存汉字第2个字节,第3个存放’/0’;如果是英文的话,则只用到char[0],其它的全部为’/0’。

    struct Char{

        WORD    hz;// 文字

        Char() : hz(0) {}

        // 用作查找文字

        inline bool operator == ( WORD h ) const

        {

            return hz==h ?true:false;

        }

    };

用VECTOR存储常用文字索引,绘制文字时先查找VECTOR,没有就新建,然后放入VECTOR。


OpenGL显示字体:

1.       位图Bitmap Fonts :适合单独缩放和旋转的标签,速度比较块,位置由glRasterPos决定,因此(-1,1)范围内的文字将会被显示,只要文字对象的位置超出屏幕范围之外,即便是有部分文字可以显示,仍然不会被绘制。


2.       轮廓线Outline Fonts:将字符转化为控制点和曲线,可以是线也可以是多边形,有opengl 3D几何体的所有特性:包括移动,旋转,缩放,材质贴图,灯光,反走样。


3.       贴图映射Texture Mapped Text:将文字制作成贴图的模式,对贴花字体很有效(如电线杆上的广告,街道指示牌等),拥有opengl贴图的特性。


不同平台的具体实现:

Glx:X系统

glXUseXFont(),创建一个显示列表集,然后调用显示列表。

优点:X系统下能很好的显示任何字体

缺点:只能是位图文字


GLC:只适用于Adobe公司的Type1字体,只能在SGI工作站上使用,提供位图,线条,三角面显示模式。(直接略过)


GLUT:

提供了两种方法:位图-glutBitmapCharacter() 笔画-glutStrokeCharacter()

优点:简单

缺点:字体太少,必须使用GLUT库


贴图映射:
将字符绘制成贴图

优点:高效(在支持硬件贴图的机器上很快),GLX上很容易使用

缺点:有限字符集很有效,字符太多的语言则不适用(需要好的管理策略),字体缩放或低采样时会降低质量,字体间距容易出错。


GLTT:
对FreeType库的进一步封装。支持位图,抗锯齿,轮廓线,多边形模式。可以直接修改字体,实现特殊效果。

优点:简单,灵活,跨平台,可使用TrueType字体。

缺点:速度比贴图映射要慢。


FTGL:

也是采用FreeType库。采用标准的字体文件格式,可以直接读取字体文件。支持位图,抗锯齿,贴图映射,轮廓线,多边形格网,突出(挤压)多边形格网。

优点:简单,灵活,跨平台,能使用任何TrueType字体。

缺点:字体载入时间长。


WGL:位图-wglUseFonBitmaps() 轮廓线-wglUseFontOutlines(), 微软平台

优点:简单,可以使用任何微软平台的字体

缺点:WINDOWS ONLY,不提供字体修改,速度慢。


GLF:罗马人创建的字体渲染库,支持大量的渲染模式:线框,位图,贴图映射,挤压线框和实心。

优点:简单,多平台

缺点:.glf格式字体文件没有文档化。


FreeType2的简单使用(zhuan)
FreeType2的简单使用:
FreeType2是一个简单的跨平台的字体绘制引擎.目前支持TrueType Type1 Type2等字体格式.不过目前好象还不支持OpenType.
使用FreeType的应用很多.著名的FTGL就是使用FreeType的.能在OpenGL高效率的绘制矢量字体.
FTGL我没用过.因为不想在没了解该怎么用FreeType的情况下就去用FTGL.

经过一个晚上的阅读代码(我的代码阅读能力是很差的).终于知道了如何使用FreeType2了。不过是简单的使用,还不知道如何设置Bold Itainly等属性.主要是简单的演示.以后准备做成一个完善的字体引擎.
下面简单的介绍一下.

首先当然是包含头文件了。头文件要这样包含:
#include [ft2build.h]
#include FT_FREETYPE_H
不知道为什么.反正就是要这么包含.
以下为FT2的初始化代码.和绘制以及释放的代码>
注意这里绘制代码接受的字符是Unicode.表示你这样就可以绘制了

//主要参考了Nehe的Lesson 43(这课的源码可以自己去下载,不过切分字符串那部分有问题,自己重新写个就OK了),经过本人修改后可以正常运算,代码如下:

头文件MyFont.h

//FreeType头文件
#include <ft2build.h>
#include <freetype/freetype.h>
#include <freetype/ftglyph.h>
#include <freetype/ftoutln.h>
#include <freetype/fttrigon.h>

//OpenGL头文件
#include <GL/gl.h>
#include <GL/glu.h>

#include <windows.h>

#pragma comment( lib, "libfreetype.lib")// FT连接库

//STL头文件
#include <vector>
#include <string>

struct WideChar
{
wchar_t data;//宽字符
GLuint texture;//该字符贴图
int left,top,width,height,bmp_width,bmp_rows;//贴图上的文字信息
};

//字体类,使用了FreeType字体引擎,可以读取TTF矢量字体库
class GFont
{
private:
int h; //字体高度
FT_Library library;
FT_Face face;
std::vector<WideChar> WideCharSet;//字符贴图集合

//保证贴图宽高为2的幂(opengl贴图大小限制,3.0除外)
int next_p2 (int a);
//绘制字体形成贴图并保存到vector容器
void CreateWideCharTexture(wchar_t ch,GLuint *texture,int *w,int *h,int *bmp_w,int *bmp_rows,int *left,int *top);
//从容器中获得宽字符的贴图信息
WideChar *GetFontTexture(wchar_t ch);


public:
//FREETYPE初始化
void Init(const char *fname, unsigned int h);
//释放
void Clean();
//绘制文字
void PrintText(const wchar_t *text,float x,float y,float z=0,float r=0,float g=0,float b=0,float a=0);
};

MyFont.cpp文件太大,贴不了,就贴部分重要的,其他的参看Lesson43代码即可

const wchar_t *start_line=text;//换行
vector<wstring> lines;
int length=wcslen(text);
int i=0;
while(i<length)
{
   wstring line;
   while (text[i]!=L'/n'&&text[i]!=L'/0')
   {
    line.append(1,text[i]);
    i++;
   }
   if (!line.empty())
   {
    lines.push_back(line);  
   }
   i++; 
}

int size=lines.size();
for(int row=0;row<size;row++)
{
   glPushMatrix();
   glLoadIdentity();
   glTranslatef(x,y-row*h,0);
   glMultMatrixf(modelview_matrix);
   int len=(lines.at(row)).size();
   WideChar *temp;
   for(int i=0;i<len;i++)
   {
    temp=GetFontTexture((lines.at(row)).at(i));

    glPushMatrix();
    glTranslatef(temp->left,0,0);
    glTranslatef(0,temp->top-temp->bmp_rows,0);

    float x=(float)temp->bmp_width/temp->width,
     y=(float)temp->bmp_rows/temp->height;
   //绘制文字
    glBindTexture(GL_TEXTURE_2D,temp->texture);
    glBegin(GL_QUADS);
    glTexCoord2d(0,0); glVertex2f(0,temp->bmp_rows);
    glTexCoord2d(0,y); glVertex2f(0,0);
    glTexCoord2d(x,y); glVertex2f(temp->bmp_width,0);
    glTexCoord2d(x,0); glVertex2f(temp->bmp_width,temp->bmp_rows);
    glEnd();
    glPopMatrix();
    glTranslatef(face->glyph->advance.x>> 6,0,0); 
   }
   glPopMatrix();
}
glPopAttrib(); 

五六百个中文字符的时候建议优化,以下为本人测试结果:字体库"SIMYOU.TTF",高16

长为724的双字节字符串,未使用优化FPS=6.53,使用算法优化:FPS=8.47,使用算法+显示列表优化:FPS=40.00(均采最高值)
 

 

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值