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教程 - 位图和正交投影视图的更多相关文章

  1. [译]GLUT教程 - 位图字体

    Lighthouse3d.com >> GLUT Tutorial >> Fonts >> Bitmap Fonts 位图字体一般是二维字体.虽然我们会把它放到三维 ...

  2. [译]GLUT教程(目录)

    http://www.lighthouse3d.com/tutorials/glut-tutorial/ GLUT是OpenGL Utility Toolkit的意思.作者Mark J. Kilgar ...

  3. [译]GLUT教程 - 整合代码5

    Lighthouse3d.com >> GLUT Tutorial >> Extras >> The Code So Far V 该代码与位图字体的代码类似.区别是 ...

  4. [译]GLUT教程 - 渲染到子窗体

    Lighthouse3d.com >> GLUT Tutorial >> Subwindows >> Rendering to Subwindows 先回顾一下之前 ...

  5. [译]GLUT教程 - 整合代码6

    Lighthouse3d.com >> GLUT Tutorial >> Extras >> The Code So Far VI 下面代码以窗体模式启动.你可以在 ...

  6. [译]GLUT教程 - 游戏模式

    Lighthouse3d.com >> GLUT Tutorial >> Extras >> Game Mode 根据GLUT官网的说明,GLUT的游戏模式是为开启 ...

  7. [译]GLUT教程 - 笔划字体

    Lighthouse3d.com >> GLUT Tutorial >> Fonts >> Stroke Fonts 笔划字体是用线条生成的.跟位图字体相反,笔划字 ...

  8. [译]GLUT教程 - 整合代码4

    Lighthouse3d.com >> GLUT Tutorial >> Pop-up Menus >> The Code So Far IV 以下代码使用了位图字 ...

  9. [译]GLUT教程 - glutPostRedisplay函数

    Lighthouse3d.com >> GLUT Tutorial >> Avoiding the Idle Func >> glutPostRedisplay 直 ...

随机推荐

  1. Python的功能模块[0] -> wmi -> 获取 Windows 内部信息

    wmi模块 / wmi Module WMI (Windows Management Instrumentation) 模块可用于获取 Windows 内部信息.该模块需要 win32com 的支持, ...

  2. java.sql.SQLException: Access denied for user 'roo'@'localhost' (using password: YES)

    初学mysql,安装了mysql8.0.11,激动的用jdbc连接数据库,出现error,折腾了三天依旧无解,最后无奈装了比较稳定的mysql5.5,问题得以解决,很迷,但只要error没了就开心. ...

  3. Spring Cloud 微服务架构解决方案

    1 理解微服务 1.1 软件架构演进 软件架构的发展经历了从单体结构.垂直架构.SOA架构到微服务架构的过程. 1.1.1 单体架构 特点: 1.所有的功能集成在一个项目工程中. 2.所有的功能打一个 ...

  4. nginx+tomcat负载使用

    Nginx+Tomcat搭建 版本 操作系统版本 Centos 6.4 Nginx版本 nginx-1.3.15.tar.gz JDK版本 jdk-7u71-linux-i586   //jdk1.7 ...

  5. Flatten 2D Vector -- LeetCode

    Implement an iterator to flatten a 2d vector. For example,Given 2d vector = [ [,], [], [,,] ] By cal ...

  6. luogu P1164 小A点菜

    题目背景 uim神犇拿到了uoi的ra(镭牌)后,立刻拉着基友小A到了一家……餐馆,很低端的那种. uim指着墙上的价目表(太低级了没有菜单),说:“随便点”. 题目描述 不过uim由于买了一些辅(e ...

  7. SQL的连接(外连接、内连接、交叉连接和自连接)

    在查询多个表时,我们经常会用到连接查询,连接是关系型数据库的主要特点,也是它区别于其他类型的数据库管理系统的一个标志. 一.什么是连接查询 连接查询:根据两个表或者多个表的列之间的关系,来从这些表中查 ...

  8. 彻底解决DZ大附件上传问题

    个. 注意:很多人遇到修改php.ini后重应WEB服务后仍然不能生效.这种情况应该先确认一下所改的php.ini是不是当前PHP所使用的.您可以在WEB目录下建立一个php文件,内容很简单就一句话& ...

  9. ES6中的迭代器(Iterator)和生成器(Generator)(二)

    一.内建迭代器 迭代器是ES6的一个重要组成部分,在ES6中,已经默认为许多内建类型提供了内建迭代器,只有当这些内建迭代器无法实现目标时才需要自己创建.通常来说当定义自己的对象和类时才会遇到这种情况, ...

  10. bind域名dns解析及主从服务的配置

    bind域名dns解析及主从服务的配置 1.dns解析介绍     人们习惯记忆域名,但机器间互相只认IP地址,域名与IP地址之间是多对一的关系,一个ip地址不一定只对应一个域名,且一个域名只可以对应 ...