[译]GLUT教程 - 位图和正交投影视图
Lighthouse3d.com >> GLUT Tutorial >> Fonts >> Bitmap Fonts and Orthogonal Projections
一般用法下,位图字体只能以二维的形式显示信息给用户.例如,一个简单的例子,我们想显示应用程序每秒的帧数.这些信息可以驻留在同一个位置,即使用户移动镜头.除此之外,用二维的正交投影比透视投影更容易计算这些位置,因为我们可以指定用像素表示该位置.
实现的基本模式是以之前的方式绘制世界,用透视投影,然后切换到正交投影来绘制文本.执行完最后一步之后我们要恢复到原来的视角,这样下一帧就会正确显示.
接下来我们演示一个渲染函数的模板来大道该效果:
void renderScene() { // do everything we need to render the world as usual
... setOrthographicProjection(); glPushMatrix();
glLoadIdentity();
renderBitmapString(,,GLUT_BITMAP_HELVETICA_18,"Lighthouse3D");
glPopMatrix(); restorePerspectiveProjection(); glutSwapBuffers();
}
上面有两个新函数: setOrthograpicProjection and restorePerspectiveProjection.第一个函数始于转换矩阵模式到GL_PROJECTION,意味着我们在镜头下工作.然后我们保存之前的设置,在这个例子中是引用自其它某处定义好的透视投影.然后我们用glLoadIdentity函数重置矩阵,并用gluOrtho函数定义一个正交投影.
该函数的参数是表示从x到y轴的范围.然后转换沿着y轴滑动,正值是向下,翻译成原型是到左上角.这样使输出文本到屏幕坐标更简单.
变量w和h在其它地方计算好(见之前changeSize函数).
void setOrthographicProjection() { // switch to projection mode
glMatrixMode(GL_PROJECTION); // save previous matrix which contains the
//settings for the perspective projection
glPushMatrix(); // reset matrix
glLoadIdentity(); // set a 2D orthographic projection
gluOrtho2D(, w, , h); // invert the y axis, down is positive
glScalef(, -, ); // mover the origin from the bottom left corner
// to the upper left corner
glTranslatef(, -h, ); // switch back to modelview mode
glMatrixMode(GL_MODELVIEW);
}
一个演示正交投影的快速方法如下.方法是设置投影而无需测量和翻译.
void setOrthographicProjection() { // switch to projection mode
glMatrixMode(GL_PROJECTION); // save previous matrix which contains the
//settings for the perspective projection
glPushMatrix(); // reset matrix
glLoadIdentity(); // set a 2D orthographic projection
gluOrtho2D(, w, h, ); // switch back to modelview mode
glMatrixMode(GL_MODELVIEW);
}
该函数非常简单.当我们在设置正交投影前保存透视投影的设置的时候,我们需要做的只是更改矩阵模式到GL_PROJECTION,然后弹出矩阵.然后恢复设置,最后更改矩阵模式回GL_MODELVIEW.
void restorePerspectiveProjection() { glMatrixMode(GL_PROJECTION);
// restore previous projection matrix
glPopMatrix(); // get back to modelview mode
glMatrixMode(GL_MODELVIEW);
}
上面这个renderBitmapString函数,上一节介绍过,会连续写入字符,不包含额外的空间,除了文本本身带有空格字符外.为了添加额外的空间,我们必须保持跟踪当然的栅格位置,这样才可以添加额外的空间到x坐标.至少有两种不同的方法来保持跟踪栅格位置.一种是在绘制完一张位图之后计算当前的栅格位置.另一种是专注于请求OpenGL的关于当前栅格位置的状态机器.
第一种方法需要我们知道字符的维度.最大的高度一直保持为一个特殊字体的常量,在多数字体中宽度是可以任意变更的.幸运的是GLUT提供了一个函数来返回字宽.glutBitmapWidth原型如下:
int glutBitmapWidth(void *font, int character);
font - GLUT中的预定义字体之一,见上一节中列出的可选值
character - 我们想要知道字宽的字符
所以,例如我们需要一个函数来写入一个固定每个字符所占像素量的字符串,我们可以如下实现:
void renderSpacedBitmapString( float x,
float y,
int spacing,
void *font,
char *string) { char *c;
int x1=x; for (c=string; *c != '\0'; c++) { glRasterPos2f(x1,y);
glutBitmapCharacter(font, *c);
x1 = x1 + glutBitmapWidth(font,*c) + spacing;
}
}
如果我们想要绘制垂直的文本,可以如下实现:
void renderVerticalBitmapString( float x,
float y,
int bitmapHeight,
void *font,
char *string) { char *c;
int i; for (c=string,i=; *c != '\0'; i++,c++) { glRasterPos2f(x, y+bitmapHeight*i);
glutBitmapCharacter(font, *c);
}
}
变量bitmapHeight可以很容易计算得出,因为我们知道每个字体的最大高度,就是字体名的最后那串数字.例如GLUT_BITMAP_TIMES_ROMAN_10是占10个像素的高度.
最后一件事是,GLUT提供了另外一个函数来处理位图字体,就是glutBitMapLength函数,它可以以像素为单位计算一个字符串的长度.函数的返回值是字符串中字符的宽度总和.原型如下:
int glutBitmapLength(void *font, char *string);
font - GLUT中的预定义字体之一,见上一节中列出的可选值
string - 我们想要知道字宽的字符串
[译]GLUT教程 - 位图和正交投影视图的更多相关文章
- [译]GLUT教程 - 位图字体
Lighthouse3d.com >> GLUT Tutorial >> Fonts >> Bitmap Fonts 位图字体一般是二维字体.虽然我们会把它放到三维 ...
- [译]GLUT教程(目录)
http://www.lighthouse3d.com/tutorials/glut-tutorial/ GLUT是OpenGL Utility Toolkit的意思.作者Mark J. Kilgar ...
- [译]GLUT教程 - 整合代码5
Lighthouse3d.com >> GLUT Tutorial >> Extras >> The Code So Far V 该代码与位图字体的代码类似.区别是 ...
- [译]GLUT教程 - 渲染到子窗体
Lighthouse3d.com >> GLUT Tutorial >> Subwindows >> Rendering to Subwindows 先回顾一下之前 ...
- [译]GLUT教程 - 整合代码6
Lighthouse3d.com >> GLUT Tutorial >> Extras >> The Code So Far VI 下面代码以窗体模式启动.你可以在 ...
- [译]GLUT教程 - 游戏模式
Lighthouse3d.com >> GLUT Tutorial >> Extras >> Game Mode 根据GLUT官网的说明,GLUT的游戏模式是为开启 ...
- [译]GLUT教程 - 笔划字体
Lighthouse3d.com >> GLUT Tutorial >> Fonts >> Stroke Fonts 笔划字体是用线条生成的.跟位图字体相反,笔划字 ...
- [译]GLUT教程 - 整合代码4
Lighthouse3d.com >> GLUT Tutorial >> Pop-up Menus >> The Code So Far IV 以下代码使用了位图字 ...
- [译]GLUT教程 - glutPostRedisplay函数
Lighthouse3d.com >> GLUT Tutorial >> Avoiding the Idle Func >> glutPostRedisplay 直 ...
随机推荐
- #422 Div2 D
#422 Div2 D 题意 假设有 n 个人比赛,每次比赛进行分组,每组人数必须相同,如果一组有 x 人,则那一组要比赛 $ \frac{x * (x - 1)}{2}$次,最终一人获胜,其它人淘汰 ...
- iOS 7.1 arm64 编辑报错 警告解决办法
昨天把我的4S更新到iOS7.1,今天发下需要更新Xcode到5.1,发现打包项目Archive的时候,多了一堆警告和错误,很是郁闷. 郁闷没有用,作为一个合格的程序员,要学会淡定!看看警告和错误的大 ...
- Working with the NSOperationQueue Class
Multi-tasking prevents apps from freezing. In most programming languages, achieving this is a bit tr ...
- Android ToolBar 使用完全解析
ToolBar简介 ToolBar是Android 5.0推出的一个新的导航控件用于取代之前的ActionBar,由于其高度的可定制性.灵活性.具有Material Design风格等优点,越来越多的 ...
- JAVA常见算法题(十六)
package com.xiaowu.demo; //猴子吃桃问题:猴子第一天摘下若干个桃子,当即吃了一半,还不过瘾,又多吃了一个: //第二天早上又将剩下的桃子吃掉一半,而且又多吃了一个. //以后 ...
- JavaScript的filter用法
Js的有些操作会改变原来的对象:有些操作则不会改变原来对象. 数组的filter方法就不会改变原来数组 利用filter,可以巧妙地去除Array的重复元素: 'use strict'; var r, ...
- flask调试代码更改、模板更改后立即生效
1.app.DEBUG=True时,代码更改后立即生效 2.APP.jinja_env.auto_reload = True时,模板修改后立即生效,无需重启 参考:https://stackoverf ...
- ylb:事务处理
ylbtech_sqlserver --1.定义三个变量分别保存你的姓名,年龄和身高,然后赋值并且输出 --DECLARE @name varchar(10) , @age int , @height ...
- wireshark问题现象分析
讲的非常透彻:建议学习 wireshark问题现象分析1:参考博客1 https://blog.csdn.net/u012398362/article/details/52276067 wiresha ...
- ElasticSearch _xpack角色管理
权限管理可以通过kibana的Management界面进行,本篇主要介绍的是通过命令进行,角色API使您能够在本机域中添加,删除和检索角色. 要使用此API,您必须至少具有manage_securit ...