第七章opengl文字显示
更新时间:2024-03-31 22:55:02 阅读量: 综合文库 文档下载
- OpenGL 文字推荐度:
- 相关推荐
OpenGL文字显示
(一)显示英文
OpenGL并没有直接提供显示文字的功能,并且,OpenGL也没有自带专门的字库。因此,要显示文字,就必须依赖操作系统所提供的功能了。
各种流行的图形操作系统,例如Windows系统和Linux系统,都提供了一些功能,以便能够在OpenGL程序中方便的显示文字。
最常见的方法就是,我们给出一个字符,给出一个显示列表编号,然后操作系统由把绘制这个字符的OpenGL命令装到指定的显示列表中。当需要绘制字符的时候,我们只需要调用这个显示列表即可。假如我们要显示的文字全部是ASCII字符,则总共只有0到127这128种可能,因此可以预先把所有的字符分别装到对应的显示列表中,然后在需要时调用这些显示列表。
Windows系统中,可以使用wglUseFontBitmaps函数来批量的产生显示字符用的显示列表。函数有四个参数:
第一个参数是HDC,这是Windows GDI的里的东西,调用wglGetCurrentDC函数,就可以得到一个HDC了。
第二个参数表示第一个要产生的字符,因为我们要产生0到127的字符的显示列表,所以这里填0。
第三个参数表示要产生字符的总个数,因为我们要产生0到127的字符的显示列表,总共有128个字符,所以这里填128。
第四个参数表示第一个字符所对应显示列表的编号。假如这里填1000,则第一个字符的绘制命令将被装到第1000号显示列表,第二个字符的绘制命令将被装到第1001号显示列表,依次类推。我们可以先用glGenLists申请128个连续的显示列表编号,然后把第一个显示列表编号填在这里。
我们为了简化view中的代码,特建立字符显示类COpenGLFont(后面给出): #define MAX_CHAR 128
wglUseFontBitmaps(wglGetCurrentDC(), 0, MAX_CHAR, lists); 在字符类中添加显示字符函数:
void COpenGLFont::drawString(const char* str) {
static int isFirstCall = 1; static GLuint lists;
if( isFirstCall ) { // 如果是第一次调用,执行初始化
// 为每一个ASCII字符产生一个显示列表 isFirstCall = 0;
// 申请MAX_CHAR个连续的显示列表编号
lists = glGenLists(MAX_CHAR); //编号分别是lists, lists + 1, lists + 2,
lists + MAX_CHAR -1
// 把每个字符的绘制命令都装到对应的显示列表中
wglUseFontBitmaps(wglGetCurrentDC(), 0, MAX_CHAR, lists); //从基数
lists开始依次显示各个字符
}
// 调用每个字符对应的显示列表,绘制每个字符 for(; *str!='\\0'; ++str) }
显示列表一旦产生就一直存在(除非调用glDeleteLists销毁),所以我们只需要在第一次调用的时候初始化,以后就可以很方便的调用这些显示列表来绘制字符了。
绘制字符的时候,可以先用glColor*等指定颜色,然后用glRasterPos*指定位置,最后调用显示列表来绘制。 #include\
void CMFCOpenGLView::OnDraw(CDC* /*pDC*/) {
CMFCOpenGLDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); if (!pDoc)
return;
glCallList(lists + *str);
// TODO: 在此处为本机数据添加绘制代码 glClearColor(0.0f,0.0f,0.7f,1.0f); //背景设置
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); glLoadIdentity();
gluLookAt(0,0,10,0,0, 0,0,1,0); glColor3f(1,0,0);
}
glRasterPos4s(-2,0,0,1); //指定位置 COpenGLFont font;
font.drawString(\glFinish();
SwapBuffers(wglGetCurrentDC());
指定字体:
在产生显示列表前,Windows允许选择字体。在COpenGLFont类中定义一个selectFont函数来实现它,大家可以看看代码。
void COpenGLFont::selectFont(int size, int charset, const char* face) { }
HFONT hFont =
CreateFontA(size, //指定字高 0, 0, 45,
//指定字宽 //指定角度(1/10度)
//指定字符的基线与x轴的角度(1/10度)
//指定字体的重量(FW_BOLD=700) //指定是否斜体 //指定是否有下划线 //指定是否是StrikeOut字体
FW_BOLD, 0, 0, 0, charset,
OUT_DEFAULT_PRECIS, //指定输出精度 CLIP_DEFAULT_PRECIS,//指定裁剪精度 DEFAULT_QUALITY, //指定输出质量
DEFAULT_PITCH | FF_SWISS, //指定字体的定位和外观 face);
HFONT hOldFont = (HFONT)SelectObject(wglGetCurrentDC(), hFont); DeleteObject(hOldFont);
在调用wglUseFontBitmaps之前使用selectFont函数即可指定字体。函数的三个参数分别表示了字体大小、字符集(英文字体ANSI_CHARSET,简体中文字体GB2312_CHARSET,繁体中文字体CHINESEBIG5_CHARSET ,对于中文的Windows系统,也可以直接用DEFAULT_CHARSET表示默认字符集)、字体名称。
(二)显示中文
原则上,显示中文和显示英文并无不同,同样是把要显示的字符做成显示列表,然后进行调用。但是有一个问题,英文字母很少,最多只有几百个,为每个字母创建一个显示列表,没有问题。但是汉字有非常多个,如果每个汉字都产生一个显示列表,这是不切实际的。我们不能在初始化时就为每个字符建立一个显示列表,那就只有在每次绘制字符时创建它了。当我们需要绘制一个字符时,创建对应的显示列表,等绘制完毕后,再将它销毁。
这里还经常涉及到中文乱码的问题,在网上流传的版本中,使用了MultiByteToWideChar这个函数的,基本上都没有出现乱码,所以我们也准备用这个函数。通常我们在C语言里面使用的字符串,如果中英文混合的话,例如“this is 中文字符.”,则英文字符只占用一个字节,而中文字符则占用两个字节。用MultiByteToWideChar函数,可以转化为所有的字符都占两个字节(同时解决了前面所说的乱码问题:))。 转化的代码如下: // 计算字符的个数
// 如果是双字节字符的(比如中文字符),两个字节才算一个字符 // 否则一个字节算一个字符 len = 0;
for(i=0; str[i]!='\\0'; ++i) {
if( IsDBCSLeadByte(str[i]) ) ++i; ++len; }
// 将混合字符转化为宽字符
wstring = (wchar_t*)malloc((len+1) * sizeof(wchar_t));
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, str, -1, wstring, len); wstring[len] = L'\\0';
// 用完后记得释放内存 free(wstring);
加上前面所讲到的wglUseFontBitmaps函数,即可显示中文字符了。在字体类中添加显示中文字符函数:
void COpenGLFont::drawCNString(const char* str) { int len, i;
wchar_t* wstring;
HDC hDC = wglGetCurrentDC(); GLuint list = glGenLists(1);
// 计算字符的个数
// 如果是双字节字符的(比如中文字符),两个字节才算一个字符 // 否则一个字节算一个字符 len = 0;
for(i=0; str[i]!='\\0'; ++i) { if( IsDBCSLeadByte(str[i]) ) ++i; ++len; }
// 将混合字符转化为宽字符
wstring = (wchar_t*)malloc((len+1) * sizeof(wchar_t));
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, str, -1, wstring, len); wstring[len] = L'\\0'; // 逐个输出字符 for(i=0; i // 回收所有临时资源 free(wstring); glDeleteLists(list, 1); } 注意我用了wglUseFontBitmapsW函数,而不是wglUseFontBitmaps。wglUseFontBitmapsW是wglUseFontBitmaps函数的宽字符版本,它认为字符都占两个字节。因为这里使用了MultiByteToWideChar,每个字符其实是占两个字节的,所以应该用wglUseFontBitmapsW。 void CMFCOpenGLView::OnDraw(CDC* /*pDC*/) { CMFCOpenGLDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); if (!pDoc) return; // TODO: 在此处为本机数据添加绘制代码 glClearColor(0.0f,0.0f,0.7f,1.0f); //背景设置 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(0,0,10,0,0, 0,0,1,0); glColor3f(1,0,0); glRasterPos4s(-5,0,0,1); //指定位置 COpenGLFont font; font.selectFont(48,DEFAULT_CHARSET, \黑体\ } font.drawCNString(\汉字显示测试!chinese character show test!12345\glFinish(); SwapBuffers(wglGetCurrentDC()); (三)三维汉字的显示 在OpenGL中输出文本有两个函数:wglUseFontBitmaps和wglUseFontOutlines,前者用来输出2维文字,后者用来输出3维文字, 项目需要采用unicode编码方式. void COpenGLFont::draw3DString(_TCHAR* str) { GLYPHMETRICSFLOAT pgmf[1]; DWORD dwChar; int list; HDC hDC=wglGetCurrentDC(); } for(size_t i=0;i<_tcslen(str);i++) { dwChar=str[i]; list=glGenLists(1); //取出一个字符的显示列表 wglUseFontOutlines(hDC,//设备环境句柄 dwChar,//要转换为显示列表的第一个字符 1, //要转换为显示列表的字符数 list,//显示列表的基数 0.0,//指定与实际轮廓的最大偏移量,显示精度 0.5,//在Z轴负方向的值,即厚度 0,//填充模式,为填充,为线框 NULL/*pgmf*/); //接受字符的地址 //绘制该字符的显示列表 glCallList(list); glDeleteLists(list, 1); } void CMFCOpenGLView::OnDraw(CDC* /*pDC*/) { CMFCOpenGLDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); if (!pDoc) return; // TODO: 在此处为本机数据添加绘制代码 glClearColor(0.0f,0.0f,0.7f,1.0f); //背景设置 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(0,0,10,0,0,0,0,1,0); mydraw();//完成图形绘制 glColor3f(1,0,0); glTranslatef(-3,2,-2); glScalef(1,2,1); COpenGLFont font; font.selectFont(10,DEFAULT_CHARSET, \宋体\ font.draw3DString(L\江西农业大学软件学院!\ glFinish(); SwapBuffers(wglGetCurrentDC()); }
正在阅读:
第七章opengl文字显示03-31
智能花盆自动浇水系统的设计06-25
苏教版四年级语文第一学期期末测试卷09-30
江苏重点项目-基本医疗卫生体系提升工程项目可行性研究报告03-14
江苏道明化学有限公司年年产24000吨过氧化二异丙苯(DCP)、副产800吨DCP-40、3600吨重芳烃、714.7吨粗苯酚 - 图文09-14
现代企业财务风险控制分析09-18
浅析CL建筑体系在多层建筑中的应用09-26
倪海厦人纪针灸脑瘤及肺癌处方04-05
影视剪辑 复习总结05-16
2020年拟提拔同志现实表现材料精选三篇09-10
- 小学生造句大全
- 增压泵投资项目可行性研究报告(模板)
- 高中语文人教版粤教版必修1-5全部文言文知识点归纳
- 两学一做专题民主生活会组织生活会批评与自我批评环节个人发言提
- 管理处环境保洁工作操作标准作业指导书
- 2012六一儿童节活动议程 - 图文
- 移树申请报告
- 《贵州省市政工程计价定额》2016定额说明及计算规则
- 计算机长期没有向WSUS报告状态
- 汉语拼音教学策略研究
- 发展西部领先的航空货运枢纽
- 司法所上半年工作总结4篇
- 如何提高银行服务水平
- 发电厂各级人员岗位职责
- 丰田汽车的外部环境分析
- 2017—2018年最新冀教版四年级数学下册《混合运算》教案精品优质
- 中建八局样板策划 - 图文
- 戚安邦《项目管理学》电子书
- 2015年高级项目经理笔记
- 弯桥的设计要点
- 第七章
- 文字
- 显示
- opengl
- 电工复习资料
- 中职语文试卷
- 2019年注册安全工程师安全生产法及相关法律知识重点难点考点总结
- 办实事 求实效 出实绩
- 河南省许昌市长葛市第三实验高中2013-2014学年高一(上)第三次
- 二年级下册比喻句专项训练
- 第一批全国建筑幕墙设计人员岗位能力评价通过人员继续教育复习题
- 关联企业避税
- 高分子物理典型计算题
- 八下语文借物抒情教学设计
- 2014-2015年人教新目标八年级上Unit4试题含答案(河南)
- 糠醛 理化性质
- 英语修辞学课程教学大纲2013版
- 浅谈小学阶段单位换算的教学
- Linux系统安全配置指南(基线)
- 关于应急管理工作存在的问题
- 出入境证件照片规范 - 图文
- 单中心网络版方案模板(简体版) - 图文
- 奇数和偶数奥数教案
- matlab复变函数画图形