openGL输出简单文字
- 格式:doc
- 大小:27.50 KB
- 文档页数:1
opengl学习(三)----绘制简单图形(⼀)今天说⼀说⼏种简单的图元。
所有的⼏何图元都是根据它们的顶点来描绘的。
⽽顶点就是它们在屏幕上的坐标位置。
我喜欢把这⼏个简单的图元称为点线⾯。
点,可以看到⼀个顶点;线,就是两个顶点指定的⼀条有限长度的线段;⾯,其实更准确讲是⼀个凸多边形。
opengl⾥所讲的多边形是内部⽤颜⾊填充的,视觉上称为⾯我个⼈认为是更贴近的。
当然,多边形也是由指定的顶点组成的。
需要注意的是,要想被opengl按照设计被绘制必须正确的认识到,所谓的多边形是顶点都处于⼀个平⾯上,凸多边形。
凸多边形不能理解的,请问度娘。
来看⼀个例⼦:C++代码1. glBegin(GL_POLYGON);2. glVertex2f(0.0, 0.0);3. glVertex2f(0.0, 3.0);4. glVertex2f(4.0, 3.0);5. glVertex2f(6.0, 1.5);6. glVertex2f(4.0, 0.0);7. glEnd();先不去关⼼代码本⾝,这段代码最终的结果是要指定5个顶点绘制⼀个凸五边形。
注意,不是5条线段⽽是⼀个凸五边形的平⾯。
不管是点线⾯的哪⼀种,都是需要指定⼀组顶点的。
如何判定顶点指定的开始和结束就是glBegin和glEnd的⼯作。
引⽤void glBegin(Glenum mode);标志着⼀个顶点数据列表的开始,它描述了⼀个⼏何图元。
mode参数指定了图元的类型。
void glEnd(void);标志着⼀个顶点数据列表的结束。
mode设置的不同,代表着将要绘制的图元也不同。
下⾯这个表就是图元的名称和含义:值含义GL_POINTS 单个的点GL_LINES ⼀对顶点被解释为⼀条直线GL_LINE_STRIP ⼀系列的连接直线GL_LINE_LOOP 和上⾯相同,但第⼀个顶点和最后⼀个顶点彼此相连GL_TRIANGLES 3个顶点被解释为⼀个三⾓形GL_TRIANGLES_STRIP 三⾓形的连接串GL_TRIANGLES_FAN 连接成扇形的三⾓形系列GL_QUADS 4个顶点被解释为⼀个四边形GL_QUADS_STRIP 四边形的连接串GL_POLYGON 简单的凸多边形的边界试想着,如果将glBegin(GL_POLYGON)修改为glBegin(GL_POINTS),绘制出来的将是什么图形呢? 哈哈,那就是5个点⽽已么。
SDL显⽰⽂字及中⽂#include <SDL_ttf.h>//Initialize SDL_ttfif( TTF_Init() == -1 )return -1;打开⼀个字体使⽤ TTF_Font *TTF_OpenFont(const char *file, int ptsize);其中file是指字体⽂件的路径,可以为相对路径或绝对路径, ptsize是指字号,即字体⼤⼩。
它是基于720DPI的,有⼀个简单办法来估算字体⼤⼩,在Word中选择相应的字号即可看出效果来。
中⽂字体的(五号字,⼩五,四号,⼩四)与数字字号有⼀个对应关系。
英⽂字体“磅”(Point)和中⽂字号的关系美国⼈习惯于⽤“磅”作为⽂字的计量单位,⽽中国⼈却习惯于字号作为⽂字的计量单位。
它们的对应关系是:初号=42磅=14.82毫⽶⼩初=36磅=12.70毫⽶⼀号=26磅=9.17毫⽶⼩⼀=24磅=8.47毫⽶⼆号=22磅=7.76毫⽶⼩⼆=18磅=6.35毫⽶三号=16磅=5.64毫⽶⼩三=15磅=5.29毫⽶四号=14磅=4.94毫⽶⼩四=12磅=4.23毫⽶五号=10.5磅=3.70毫⽶⼩五=9磅=3.18毫⽶六号=7.5磅=2.56毫⽶⼩六=6.5磅=2.29毫⽶七号=5.5磅=1.94毫⽶⼋号=5磅=1.76毫⽶其中的磅值就是你要设置的ptsize⼤致的值。
以下是打开⼀个仿宋字体的代码,字号为三号字,字体⽂件跟可执⾏⽂件在同⼀个⽬录下。
TTF_Font *font;font=TTF_OpenFont("simsun.ttf", 16);if(!font){printf("TTF_OpenFont: Open simsun.ttf %s\n", TTF_GetError());return -1;}输出英⽂/数字到⼀个SDL_Surface它使⽤ SDL_Surface *TTF_RenderText_Solid(TTF_Font *font, const char *text, SDL_Color fg);来输出⼀段英⽂其中font是某个打开的字体,text是输出的⽂本,fg是⽂字的颜⾊采⽤类型SDL_Color.采⽤RGB三⾊定义SDL_Color black = { 255, 255, 255 }; //⿊⾊SDL_Color red = { 255, 0, 0 }; //红⾊如果成功将⽂字输出⼀个SDL_Surface,如果失败将返回⼀个空值.其中Solid是单⾊的意思,类似输出有,空⼼字体:SDL_Surface *TTF_RenderText_Shaded(TTF_Font *font, const char *text, SDL_Color fg, SDL_Color bg) ;着⾊输出SDL_Surface *TTF_RenderText_Blended(TTF_Font *font, const char *text, SDL_Color fg) ;其中Solid输出,速度最快,但是字体不太美观。
OpenGL函数使用手册(一)OpenGL函数库格式:<库前缀><根命令><可选的参数个数><可选的参数类型> 库前缀有 gl、glu、aux、glut、wgl、glx、agl 等等,1,核心函数库主要可以分为以下几类函数:(1) 绘制基本的几何图元函数。
如:glBegain().(2) 矩阵操作、几何变换和投影变换的函数。
如:矩阵入栈glPushMatrix(),还有矩阵的出栈、转载、相乘,此外还有几何变换函数glTranslate*(),投影变换函数glOrtho()和视口变换函数glViewport()等等。
(3) 颜色、光照和材质函数。
(4) 显示列表函数,主要有创建、结束、生成、删除和调用显示列表的函数glNewList()、glEndList()、glGenLists()、glDeleteLists()和glCallList()。
(5) 纹理映射函数,主要有一维和二维纹理函数,设置纹理参数、纹理环境和纹理坐标的函数glTexParameter*()、glTexEnv*()和glTetCoord*()等。
(6) 特殊效果函数。
(7) 选着和反馈函数。
(8) 曲线与曲面的绘制函数。
(9) 状态设置与查询函数。
(10) 光栅化、像素函数。
2,OpenGL实用库(The OpenGL Utility Library)(GLU)包含有43个函数,函数名的前缀名为glu.(1) 辅助纹理贴图函数。
(2) 坐标转换和投影变换函数。
(3) 多边形镶嵌工具。
(4) 二次曲面绘制工具。
(5) 非均匀有理B样条绘制工具。
(6) 错误反馈工具,获取出错信息的字符串gluErrorString() 3,OpenGL辅助库包含有31个函数,函数名前缀名为aux这部分函数提供窗口管理、输入输出处理以及绘制一些简单的三维物体。
4,OpenGL工具库(OpenGL Utility Toolkit)包含大约30多个函数,函数前缀名为glut,此函数由glut.dll来负责解释执行。
O p e n G L进行文字显示的方法Company Document number:WTUT-WT88Y-W8BBGB-BWYTT-19998任何一个DEMO、仿真项目、游戏,都少不了文字这种媒体。
这不可不说是对图形视觉媒体的补充——我们还有一些无法超越文字来向观众表达的心事,或是补充说明,或是感悟,或是感激。
——一般的文字不属于图形渲染部分,而属于用户界面部分,这在游戏引擎中看或许一目了然,但是在底层的图形渲染API——OPENGL或D3D中,文字的显示“并不是必须”,但它是多么深深地被需要着口牙。
所以,把字体设置、文字显示作为一种图形学技术而非单纯的完全我属或他属,我是这么想的。
(同样,拾取也算是这样吧[])本文来源于ZwqXin(),转载请注明原文地址:怎么表达文字呢在OpenGL中,我们没有什么现成的东西可用,但确实有办法让我们“得到这种技术”。
让我最记忆深刻的是NEHE的两三篇教程(貌似都是十几课吧),讲述的就是今天的这个主题。
可以到或者在DANCINGWIND的中文翻译(见[])看看~。
而我所知道的这三种方法,前两种应该就是来自那里吧(记得~~),当时要努力完成课程DEMO,于是胡胡混混地就把相应的那两三课学了,而且把它的文字显示方法应用到自己的程序中(还经历了一段艰辛的探索史...连我当时的MyFont类也记录了这份小辛酸,现在看来,是因为当时的知识水平不够理解吧)。
然后后来又一个课程DEMO,老师后来觉得我应该“写中文”,于是我又去探索中文字体显示方法了,并在一个开源DEMO中找到,分析代码段后就拿来主义了,至昨不曾好好考究——这就是我所知的第三种方法。
三种方法都是三步曲:在初始化的时候“创建字体”[Build],在渲染阶段“应用字体”(显示文字)[Print],在程序结束或不再需要文字显示的时候“销毁字体”[kill]。
其中前两步比较重要,着重讨论讨论哈~1.常规的屏幕字体打印(NormalFont)应用得比较广,大名鼎鼎的AZURE以前的DEMO就是用这个的。
C++下的OpenGL文字显示的完美解决方案C++下的OpenGL文字显示的完美解决方案以前一直用Delphi+OpenGL搞图形开发。
最近改用VC++了。
比起Delphi而言,VC++最大的不同就在于没有统一的封装库(在Delphi中一律是VCL),如果仅为一点东西就使用某个库会使整个程序看起来极不协调。
这里的介绍的方法原理跟我以前在Delphi中使用的方法是一致的。
只不过没有使用任何封装库而已。
我曾在网上看过许多文字的解决方案,它们大多不能让人满意。
有一种方法采用wgl函数生成某个具体的文字的显示列表,并在渲染时调用显示列表。
这种方法必须为每个文字创建显示列表,文字一多就显得不够灵活。
因此我采用的方法是先用GDI把指定的文字绘制到内存中的Bitmap中去,在把Bitmap转换成纹理送给OpenGL。
这里也顺便小结一下Windows GDI,如果你对Windows GDI已十分熟悉可以跳过此节。
一提到GDI,很多人肯定会认为这个方法很慢。
其实不尽然。
GDI 的绘图函数比起OpenGL来确实慢了许多,但如果用的好,并不会影响程序的效率。
因为大多数情况下,你并不需要在每一帧都要重复使用GDI来绘制文字。
在实际应用中,大多数文字是静态的,少数文字在某些帧会发生改变。
因此我们需要这样的一种方法,它不仅能绘制出高质量的字体,而且在需要时可以不影响系统效率地灵活地改变。
单击这里下载本文的代码概念介绍首先要解决的问题是如何使用Windows GDI创建位图,然后在位图中绘制文字,并把绘制后的位图读取出来。
这一部分跟OpenGL 没有任何关系,并且这一操作也无需在每一帧都执行。
这一部分概括如下:1. 创建Windows GDI 设备环境2. 创建一个内存中的位图对象,并把它指定到设备环境中去3. 为设备环境指定绘图参数,如笔的颜色,背景颜色等等4. 调用Windows GDI绘图函数在设备环境中绘图5. 把位图对象中的信息抓取出来先解释一下Windows GDI的一些概念。
附录A OpenGL函数简介OpenGL是国际公认的在计算机中使用广泛、易学易用的三维图形标准,附录A给出了本教材所用OpenGL函数的简单说明(/documentation/manual/),供读者查询使用。
1.glAccumvoid glAccum ( GLenum op , GLfloat value );参数说明:op 取符号:GL_ACCUM,GL_LOAD,GL_ADD,GL_MULT,GL_RETURN。
value 取一个浮点数,op决定怎样使用value。
功能描述:按参数op指定的方式,在累积缓冲区中进行如下操作GL_ACCUM 从当前选定的缓冲区(缺省值为当前的颜色缓冲区)中逐点读取其R、G、B、A值,该RGBA乘以value加上累积缓冲区中的当前值后,再存入累积缓冲区中保存。
GL_LOAD 从当前选定的缓冲区中逐点读取其R、G、B、A值,该RGBA乘以value 后,再存入累积缓冲区中保存。
GL_ADD 将value直接加到累积缓冲区中每点的RGBA上。
GL_MULT 略。
GL_RETURN 将累积缓冲区中的RGBA乘以value后,送当前颜色缓冲区中显示。
2.glBegin, glEndvoid glBegin ( GLenum mode );参数说明:mode 取符号:GL_POINTS, GL_LINES, GL_LINE_STRIP, GL_LINE_LOOP, GL_TRIANGLES, GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN, GL_QUADS,GL_QUAD_STRIP和 GL_POLYGON。
void glEnd (void );功能描述:函数glBegin, glEnd成对出现,用来界定一个或一组类似图形元素顶点数据的开始与结束,图形元素的类型由mode确定。
GL_POINTS 每个顶点函数glVertex()描述了一个个孤立的顶点数据。
OpenGL函数使用手册(一)OpenGL函数库格式:<库前缀><根命令><可选的参数个数><可选的参数类型> 库前缀有gl、glu、aux、glut、wgl、glx、agl 等等,1,核心函数库主要可以分为以下几类函数:(1)绘制基本的几何图元函数。
如:glBegain().(2)矩阵操作、几何变换和投影变换的函数。
如:矩阵入栈glPushMatrix(),还有矩阵的出栈、转载、相乘,此外还有几何变换函数glTranslate*(),投影变换函数glOrtho()和视口变换函数glViewport()等等。
(3)颜色、光照和材质函数。
(4)显示列表函数,主要有创建、结束、生成、删除和调用显示列表的函数glNewList()、glEndList()、glGenLists()、glDeleteLists()和glCallList()。
(5)纹理映射函数,主要有一维和二维纹理函数,设置纹理参数、纹理环境和纹理坐标的函数glTexParameter*()、glTexEnv*()和glTetCoord*()等。
(6)特殊效果函数。
(7)选着和反馈函数。
(8)曲线与曲面的绘制函数。
(9)状态设置与查询函数。
(10)光栅化、像素函数。
2,OpenGL实用库(The OpenGL Utility Library)(GLU)包含有43个函数,函数名的前缀名为glu.(1)辅助纹理贴图函数。
(2)坐标转换和投影变换函数。
(3)多边形镶嵌工具。
(4)二次曲面绘制工具。
(5)非均匀有理B样条绘制工具。
(6)错误反馈工具,获取出错信息的字符串gluErrorString()3,OpenGL辅助库包含有31个函数,函数名前缀名为aux这部分函数提供窗口管理、输入输出处理以及绘制一些简单的三维物体。
4,OpenGL工具库(OpenGL Utility Toolkit)包含大约30多个函数,函数前缀名为glut,此函数由glut.dll来负责解释执行。
OpenGL11-绘制汉字最⾼效⽅法(使⽤Freetype)(代码已更新)OpenGL本⾝并没有绘制⽂字的功能,他只是⼀个三维绘图的API集和,很多东西都要⾃⼰动⼿才可以实现。
OpenGL绘制⽂字,⽹络上已经有很多成熟的⽅式⽅法,我这⾥给⼤家介绍的是我使⽤的⽅式,从绘制的效率上来说,速度上从已经达到我个⼈⽔平的最⼤值。
如果你有更好的⽅式,请联系我。
⾸先介绍下⽹络上的⼀些绘制⽅式。
⼀、将要绘制的⽂字按照每⼀个字⽣成⼀个⼩纹理的⽅式,然后再⽤将纹理贴到⽹格的表⾯,绘制出来,例如:“博客园-你好”,则会⽣成6个⼩纹理,然后⽣成⽹格,将纹理贴到⽹格的表⾯。
优点:每⼀个字的⼤⼩颜⾊都可选择。
缺点:⽂字多了以后,频繁的切换纹理造成效率低下。
OSG中使⽤了这种⽅式,效率极差,尤其是在⽂字更新的情况下。
⼆、直接将随绘制的⽂本字符串⽣成⼀个纹理数据(⽽不是⼀个⽂字⼀个纹理),这样做效率上⽐第⼀种要好很多,缺点就是更新的时候要重新构建⼀个新的纹理。
速度上有很⼤损失。
两种⽅式的原理图如下: 三、将所绘制的⽂字都放到⼀个较⼤的纹理上去,然后再纹理上做索引,当绘制的时候,去查表。
在将纹理贴到⽹格上绘制出来,这种⽅式,速度很快,很多游戏引擎都在使⽤这种⽅式,存在的问题绘制的⽂字多了以后速度会变慢,占⽤⼤量的cpu时间,当然对于⼩的应⽤已经⾜够了,今天我提出的⽅式也是基于这样⽅式的,只是我在索引上最了⼀些改进,改进之后的算法,将不再进⾏查表操作,⽽是直接索引,⼀定程度上降低了cpu消耗,提搞了效率。
纹理图⽚如下⽰意图:图⽚存的数据上也很重要,结合OpenGL,采⽤GL_ALPHA的上存储,这样可以⼤⼤降低图⽚所占⽤的显存空间,从⽽提⾼效率。
下⾯定义⼀个⽂字所存储的信息,如下所⽰:class Character{public:Character(){x0 = 0;y0 = 0;x1 = 0;y1 = 0;}/*** 存储当前字符在纹理上的坐标位置*/unsigned short x0;unsigned short y0;unsigned short x1;unsigned short y1;};为了快速索引,减少查找的过程,我么要结合字体本上来做⼀些处理,我们知道⼀个汉字要占⽤2个字节两个字节所能表⽰的范围是0-65535,就是6万多个汉字,那么我们就声明⼀个这么⼤的数组来存储字符的信息:代码如下:Character g_charMap[1<<16];当我们要绘制⼀个⽂字的时候,可以直接通过下标就可以直接定位到该字对应的信息了,例如我们绘制'中'就可以直接获取其在图⽚上的内容了:Character getCharacter(wchar_t ch){return g_charMap[ch];}然后这样也存在⼀个问题,即⼀张多⼤的纹理才可以容纳这么多的字符呢?如果是⼀般的应⽤,我们可以忽略这个问题,中国常⽤的汉字只有3000多个,假设是⼀个汉字占16*16的空间,那么⼀个1024*1024的纹理所能容纳的字符有 1024/16 * 1024/16 = 4096个,⾜够满⾜正常的需要,如果你是想做⼀个通⽤的,没有瑕疵的应⽤,我们就要修改我们的设计⽅式,我能⼀切从速度优先的⽅式考虑,我们在上⾯的Character类中增加⼀个字段描述字符所在的纹理句柄,如下:class Character{public:Character(){x0 = 0;y0 = 0;x1 = 0;y1 = 0;texId = 0;}unsigned short x0;unsigned short y0;unsigned short x1;unsigned short y1;//! 索引纹理,即当前字符所在的纹理unsigned texId;};这样,就可以拜托之前的限制,实现⼤规模的绘制⽂字了。
Qt OpenGL教程最近一段时间除了学习Qt,翻译Qt文档之外,由于工作和兴趣的原因,开始着手看Qt OpenGL编程。
在网上搜索了有关OpenGL的教程,发现NeHe的OpenGL 教程的还很不错,作者是NeHe。
上面有很多种语言的实现,但是没有Qt和Gtk 的,所以我就想着手写这个Qt OpenGL教程,每课的内容和NeHe是一样的。
另外,介绍NeHe的一个中文翻译站点CSDN-CKer翻译的NeHe的OpenGL教程,翻译人是CKer,在我学习这个教程的过程中,给了我很大的帮助。
下面就是Qt OpenGL教程的内容:Qt OpenGL的准备工作第一课:创建一个OpenGL窗口第二课:你的第一个多边形第三课:上色第四课:旋转第五课:向三维进军第六课:纹理映射第七课:纹理滤波、光源和键盘控制第八课:融合第九课:在三维空间中移动位图第十课:载入一个三维世界并在其中移动第十一课:旗的效果(波动纹理)第十二课:显示列表第十三课:位图字体第十四课:轮廓字体第十五课:使用纹理映射的轮廓字体第十六课:看起来很棒的雾因为本教程是从NeHe的OpenGL教程迁移过来的,代码变为Qt实现的。
所以有的课程一时还没有实现成功,所以可能有些教程是跳跃的。
因本人时间有限,所以难免有错误出现,如果您发现了这些错误,或者有什么建议,请来信指教,谢谢。
Qt OpenGL的准备工作因为Qt存在很多版本,另外它支持的平台也很多,到目前为止我只实验了几个组合,所以就先把这些列出来吧,欢迎大家补充。
Unix/X11LinuxQt:自由版或者企业版都支持OpenGL模块,而专业版则不能。
我现在使用的是3.1.0自由版和企业版。
gcc:编译器。
我现在使用的是3.2。
X:Linux下的图形环境。
我现在使用的是4.2.0。
Mesa:自由的OpenGL。
我现在使用的是5.0。
WindowsQt:企业版支持OpenGL模块,而专业版则不能。
我现在使用的是3.1.0企业版。
opengl中文字的几种常用绘制方法
在OpenGL中,文字的绘制主要有以下几种常用方法:
1. 使用专门的字体库:例如STB库或FreeType库,这些库提供了加载和渲染TrueType或OpenType字体文件的功能。
你可以使用这些库来加载字体文件,然后使用OpenGL的纹理映射技术将字体纹理映射到几何形状上。
2. 使用点阵字体:点阵字体是一种将文字表示为像素矩阵的字体。
你可以使用点阵字体的图像数据作为纹理,将其映射到几何形状上。
这种方法比较简单,但字体的大小和风格有限制。
3. 使用字符数组:你可以定义一个字符数组,每个字符都是一个OpenGL 的基本几何形状(例如三角形或四边形),然后使用OpenGL的顶点缓冲区来渲染这些字符。
这种方法可以让你自定义字体的样式和大小,但实现起来比较复杂。
4. 使用GLUT库:GLUT库提供了一些方便的函数来绘制文字,你可以使用这些函数来在窗口中输出文字。
这种方法比较简单,但字体的大小和风格有限制。
5. 使用OpenGL的字符生成函数:OpenGL提供了一些字符生成函数,例如glBitmap、glDrawPixels等,这些函数可以直接在屏幕上绘制文字。
这
种方法可以实现自定义的字体样式和大小,但实现起来比较复杂,需要有一定的OpenGL编程经验。
以上是OpenGL中文字的几种常用绘制方法,你可以根据具体的需求选择适合的方法来绘制文字。
OpenGL Step by Step 第一、准备好OpenGL。
第二、准备好开发环境。
1.OpenGL库和头文件2.GLUT库3.GLAUX库第三、准备好窗口。
第四、建立OpenGL应用程序框架。
第五、OpenGL原理与程序基本框架。
第六、坐标变换。
第八、法向与封闭实心物体第八、颜色与表面材质第九、颜色、颜色模型及表面材质第九、法向与面的朝向第十、光照效果第十、表面纹理细节第十一、表面纹理第十二、运动、相对运动、反向运动第十三、帧缓冲第十四、雾第十五、α融合OPENGL 基础教程 (4)1.前言 (4)1.1 OPENGL 简介及发展 (4)1.2 OPENGL与DIRECTX的关系 (6)1.3 OPENGL的准备工作 (6)2. 基本图元的绘制 (7)2.1 点、直线和多边形 (7)2.2 绘制三角形和四边形 (8)2.3 绘制三棱锥 (12)2.4 绘制圆 (13)2.5 绘制五角星............................................................................. 错误!未定义书签。
2.6 绘制正弦函数图形 (13)2.7 小结 (14)3. 基于VC的OPENGL建模程序 (15)3.1 openGL几何图元——点 (15)3.2 openGL几何图元——线 (21)3.3 绘制矩形 (25)3.4 绘制圆 (28)3.5 绘制五角星 (29)3.6 绘制正弦曲线 (30)3.7 清除屏幕颜色 (32)3.8 绘制多边形 (33)3.9 OPENGL中的颜色设置 (36)3.10 在3D空间中画直线 (42)OPENGL 基础教程1.前言1.1OPENGL 简介及发展OpenGL是OpenGraphicsLib的缩写,是一套三维图形处理库,也是该领域的工业标准。
计算机三维图形是指将用数据描述的三维空间通过计算转换成二维图像并显示或打印出来的技术。
【OpenGL】使⽤FreeType库加载字体并在GL中绘制⽂字FreeType⽤起来⽐较⿇烦,这⾥写了⼀份简单的⽰例代码,仅供参考。
实现了FT库⽣成字符位图,并上传到GL纹理。
实现了字符位图缓存功能,多个字符图像保存在同⼀个纹理中。
实现了简单的字体管理框架。
实现了简单的加粗和倾斜效果。
实现了反锯齿开关,并且兼容加粗倾斜效果。
代码如下:1// OpenGL library2 #include <gl/glut.h>34// Std misc5 #include <map>6 #include <vector>78// FreeType library9 #include <ft2build.h>10 #include FT_FREETYPE_H11 #include FT_BITMAP_H12 #include FT_OUTLINE_H131415 #ifdef CreateFont16#undef CreateFont17#endif1819 typedef unsigned char byte;2021class CFontManager22 {23public:24 CFontManager();25 ~CFontManager();2627bool initialize(void);28void release(void);29int createFont(const char *filename, int face, int tall, bool bold, bool italic, bool antialias);30bool getCharInfo(int font_index, int code, int *wide, int *tall, int *horiBearingX, int *horiBearingY, int *horiAdvance, GLuint *texture, float coords[]);31int getFontTall(int font_index);3233private:34struct glyphMetrics35 {36int width;37int height;38int horiBearingX;39int horiBearingY;40int horiAdvance;41//int vertBearingX;42//int vertBearingY;43//int vertAdvance;44 };4546class CFont47 {48public:49 CFont();50 ~CFont();5152bool create(FT_Library library, const char *filename, FT_Long face_index, int tall, bool bold, bool italic, bool antialias);53void release(void);54bool getCharInfo(int code, glyphMetrics *metrics, GLuint *texture, float coords[]);55int getFontTall(void);5657private:58bool loadChar(int code, glyphMetrics *metrics);5960class CChar61 {62public:63void setInfo(glyphMetrics *metrics);64void getInfo(glyphMetrics *metrics, GLuint *texture, float coords[]);66public:67int m_code;68 GLuint m_texture;69float m_coords[4]; // left top right bottom7071private:72 glyphMetrics m_metrics;73 };7475class CPage76 {77public:78 CPage();79 ~CPage();8081bool append(int wide, int tall, byte *rgba, float coords[]);82 GLuint getTexture(void);8384private:85 GLuint m_texture;86int m_wide;87int m_tall;88int m_posx;89int m_posy;90int m_maxCharTall;91 };9293 typedef std::map<int, CChar *> TCharMap;9495 FT_Library m_library;96 FT_Face m_face;97bool m_antialias;98bool m_bold;99int m_tall;100int m_rgbaSize;101 GLubyte *m_rgba;102 TCharMap m_chars;103 std::vector<CPage *> m_pages;104 };105106 FT_Library m_library;107 std::vector<CFont *> m_fonts;108 };109110111112//------------------------------------------------------------113// CFont114//------------------------------------------------------------115 CFontManager::CFont::CFont()116 {117 m_face = NULL;118 m_rgba = NULL;119 m_antialias = false;120 m_bold = false;121 m_tall = 0;122 }123124 CFontManager::CFont::~CFont()125 {126 release();127 }128129bool CFontManager::CFont::create(FT_Library library, const char *filename, FT_Long face_index, int tall, bool bold, bool italic, bool antialias) 130 {131 FT_Error err;132133if (tall > 256)134 {135// Bigger than a page size136return false;137 }138139if ((err = FT_New_Face(library, filename, face_index, &m_face)) != FT_Err_Ok)140 {141 printf("FT_New_Face() Error %d\n", err);142return false;143 }144145if ((err = FT_Set_Pixel_Sizes(m_face, 0, tall)) != FT_Err_Ok)146 {147 printf("FT_Set_Pixel_Sizes() Error %d\n", err);148return false;150151 m_rgbaSize = (tall * 2) * tall * 4;152153 m_rgba = new GLubyte[m_rgbaSize];154155if (m_rgba == NULL)156 {157return false;158 }159160 m_library = library;161 m_antialias = antialias;162 m_bold = bold;163 m_tall = tall;164165if (italic)166 {167 FT_Matrix m;168 m.xx = 0x10000L;169 m.xy = 0.5f * 0x10000L;170 m.yx = 0;171 m.yy = 0x10000L;172 FT_Set_Transform(m_face, &m, NULL);173 }174175return true;176 }177178void CFontManager::CFont::release(void)179 {180 FT_Error err;181182if (m_face)183 {184if ((err = FT_Done_Face(m_face)) != FT_Err_Ok)185 {186 printf("FT_Done_Face() Error %d\n", err);187 }188 m_face = NULL;189 }190191if (m_rgba)192 {193delete[] m_rgba;194 m_rgba = NULL;195 }196197for (TCharMap::iterator it = m_chars.begin(); it != m_chars.end(); it++)198 {199delete it->second;200 it->second = NULL;201 }202203 m_chars.clear();204205for (size_t i = 0; i < m_pages.size(); i++)206 {207delete m_pages[i];208 m_pages[i] = NULL;209 }210211 m_pages.clear();212 }213214bool CFontManager::CFont::getCharInfo(int code, glyphMetrics *metrics, GLuint *texture, float coords[]) 215 {216// fast find it217 TCharMap::iterator it = m_chars.find(code);218219if (it != m_chars.end())220 {221 it->second->getInfo(metrics, texture, coords);222return true;223 }224225 glyphMetrics gm;226227if (loadChar(code, &gm) == false)228 {229return false;230 }231232 CChar *ch = new CChar();234 ch->m_code = code;235 ch->setInfo(&gm);236237for (size_t i = 0; i < m_pages.size(); i++)238 {239 CPage *page = m_pages[i];240241if (page->append(gm.width, gm.height, m_rgba, ch->m_coords)) 242 {243 ch->m_texture = page->getTexture();244 ch->getInfo(metrics, texture, coords);245 m_chars.insert(TCharMap::value_type(code, ch));246return true;247 }248 }249250 CPage *page = new CPage();251252if (page->append(gm.width, gm.height, m_rgba, ch->m_coords)) 253 {254 ch->m_texture = page->getTexture();255 ch->getInfo(metrics, texture, coords);256 m_chars.insert(TCharMap::value_type(code, ch));257 m_pages.push_back(page);258return true;259 }260261delete ch;262delete page;263264return false;265 }266267int CFontManager::CFont::getFontTall(void)268 {269return m_tall;270 }271272// bitmap.width 位图宽度273// bitmap.rows 位图⾏数(⾼度)274// bitmap.pitch 位图⼀⾏占⽤的字节数275276//MONO模式每1个像素仅⽤1bit保存,只有⿊和⽩。
OpenGL显示字体OpenGL并没有直接提供显示文字的功能,并且,OpenGL也没有自带专门的字库。
因此,要显示文字,就必须依赖操作系统所提供的功能了。
各种流行的图形操作系统,例如Windows系统和Linux系统,都提供了一些功能,以便能够在OpenGL程序中方便的显示文字。
最常见的方法就是,我们给出一个字符,给出一个显示列表编号,然后操作系统由把绘制这个字符的OpenGL命令装到指定的显示列表中。
当需要绘制字符的时候,我们只需要调用这个显示列表即可。
不过,Windows系统和Linux系统,产生这个显示列表的方法是不同的(虽然大同小异)。
作为我个人,只在Windows系统中编程,没有使用Linux系统的相关经验,所以本课我们仅针对Windows系统。
OpenGL版的“Hello, World!”写完了本课,我的感受是:显示文字很简单,显示文字很复杂。
看似简单的功能,背后却隐藏了深不可测的玄机。
呵呵,别一开始就被吓住了,让我们先从“Hello, World!”开始。
前面已经说过了,要显示字符,就需要通过操作系统,把绘制字符的动作装到显示列表中,然后我们调用显示列表即可绘制字符。
假如我们要显示的文字全部是ASCII字符,则总共只有0到127这128种可能,因此可以预先把所有的字符分别装到对应的显示列表中,然后在需要时调用这些显示列表。
Windows系统中,可以使用wglUseFontBitmaps函数来批量的产生显示字符用的显示列表。
函数有四个参数:第一个参数是HDC,学过Windows GDI的朋友应该会熟悉这个。
如果没有学过,那也没关系,只要知道调用wglGetCurrentDC函数,就可以得到一个HDC了。
具体的情况可以看下面的代码。
第二个参数表示第一个要产生的字符,因为我们要产生0到127的字符的显示列表,所以这里填0。
第三个参数表示要产生字符的总个数,因为我们要产生0到127的字符的显示列表,总共有128个字符,所以这里填128。
作业1一:作业目的及要求:采用OpenGL程序,输出学号、姓名、照片等信息。
直线、线型、字体程序。
二:理论基础:1.使用GLUT进行窗口管理:(1)与大小有关的glutInitWindowSize(800,600); //用来定义显示窗口的初始化宽度和高度的像素数glutInitWindowPosition(200,200); //显示窗口左上角应该在屏幕左边界向右50个像素、屏幕上边界100像素的位置上。
gluOrth02D(0.0,200.0,0.0,150.0); //这表示使用正投影将世界坐标系二维矩形区域的内容映射到屏幕上。
以上三个概念需要弄清,其中gluOrtho2D是指屏幕区域对应的模型坐标范围,比如横向范围是0到200米,纵向是0到150米,而后面的glutInitWindowSize是指glut的窗口弹出来后相对于你电脑屏幕的位置和大小,单位是像素。
(2)窗口颜色设置glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); //指出显示窗口使用单个缓存且使用RGB (红绿蓝)颜色模型来设置颜色值glClearColor(1.0,1.0,1.0,0.0) //设置窗口背景颜色为白色,前三个变量为红绿蓝分量,最后一个为调和参数,相当于透明度。
glClear(GL_COLOR_BUFFER_BIT); //让赋予窗口的颜色在屏幕上显示。
Glcolor3f(1.0,0.0,0.0); //显示场景中各种对象的颜色,左边的简单的设置为红色(3)其他glutInit(&argc, argv); //GLUT初始化函数glutCreateWindow(" "); //显示窗口创建定一个标题glutDisplayFunc(Display); //将创建的图形的定义传递给GLUT函数glutMainLoop(); //创建的窗口及其中的图形内容激活2.输出图元(1)OpenGL画点函数OpenGL中定义的点放在函数glBegin()和glEnd()之间,有函数glBegin()的参数指定绘制图元的类型。
计算机图形学作业2姓名学号班级作业内容用OpenGL绘制直线,写一个自己名字中的汉字效果截图关键程序(<40行) #include <iostream>#include <windows.h>#include <GL/glut.h>using namespace std ;void init(void){glClearColor(0.0, 0.0, 0.0, 0.0) ;glOrtho(0, 1.0, 0, 1.0, -1.0, 1.0) ;}void display(void){glClear(GL_COLOR_BUFFER_BIT);// 将缓存清除为预先的设置值,即黑色glBegin(GL_LINE_STRIP);glVertex2f(0.5, 0.1);//设置第一个顶点的坐标glVertex2f(0.5, 0.9);//设置第二个顶点的坐标glEnd();glBegin(GL_LINE_STRIP);glVertex2f(0.2, 0.5);//设置第一个顶点的坐标glVertex2f(0.8, 0.5);//设置第二个顶点的坐标glEnd();glBegin(GL_LINE_STRIP);glVertex2f(0.3, 0.65);//设置第一个顶点的坐标glVertex2f(0.7, 0.65);//设置第二个顶点的坐标glEnd();glBegin(GL_LINE_STRIP);glVertex2f(0.3, 0.65);//设置第一个顶点的坐标glVertex2f(0.4, 0.8);//设置第二个顶点的坐标glEnd();glBegin(GL_LINE_STRIP);glVertex2f(0.3, 0.65);//设置第一个顶点的坐标glVertex2f(0.225, 0.528);//设置第二个顶点的坐标glEnd();glBegin(GL_LINE_STRIP);glVertex2f(0.5, 0.5);//设置第一个顶点的坐标glVertex2f(0.2, 0.25);//设置第二个顶点的坐标glEnd();glBegin(GL_LINE_STRIP);glVertex2f(0.5, 0.5);//设置第一个顶点的坐标glVertex2f(0.8, 0.2);//设置第二个顶点的坐标glEnd();glFlush();//强制OpenGL函数在有限时间内运行}int main(int argc, char **argv){glutInit(&argc, argv) ;glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB) ;glutInitWindowSize(400, 400) ;glutCreateWindow("朱") ;init() ;glutDisplayFunc(display) ;glutMainLoop() ;return 0 ;}小结通过这次实验,我对OpenGL这个专业又强大的3D图形接口有了一定的了解,它直观易用,并且跨平台性很强,几乎能在所有的主流平台和操作系统上运行;对OpenGL的基本命令语法和程序的基本结构也有了一定的认识,通过老师的讲解和上网查阅资料,终于把自己名字中的“朱”字画出来,基本上掌握了OpenGL中基本几何元素的绘制。