NeHe OpenGL教程 第十五课:纹理图形字
转自【翻译】NeHe OpenGL 教程
前言
声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改。对NeHe的OpenGL管线教程的编写,以及yarn的翻译整理表示感谢。
NeHe OpenGL第十五课:纹理图形字
图形字体的纹理映射:
这一课,我们将在上一课的基础上创建带有纹理的字体,它真的很简单。
在发布了前两篇关于位图字体和轮廓字体的教程以后,我收到很多邮件,很多读者都想知道如何才能给字体赋予纹理贴图。你可以使用自动纹理坐标生成器。它会为字体上的每一个多边形生成纹理坐标。
一个小注释,这段代码是专门针对Windows写的,它使用了Windows的wgl函数来创建字体,显然,Apple机系统有agl,X系统有glx来支持做同样事情的,不幸的是,我不能保证这些代码也是容易使用的。如果哪位
有能在屏幕上显示文字且独立于平台的代码,请告诉我,我将重写一个有关字体的教程。
我们将使用第14课的代码来创作纹理字体的演示。如果程序中哪部分的代码有变化,我会重写那部分的所有代码以便看出我做的改动。
我们还要添加一个叫做texture[]的整型变量。它用于保存纹理。后面3行是第14课中的代码,本课不做改动。
下面的部分做了一些小改动。我打算在这课使用wingdings字体来显示一个海盗旗(骷髅头和十字骨头)的标志。如果你想显示文字的话,就不用改动第14课中的代码了,也可以选择另一种字体。
有些人想知道如何使用wingdings字体,这也是我不用标准字体的一个原因。wingdings是一种符号字体,使用它时需要做一些改动。告诉Windows使用wingdings字体并不太简单。如果你把字体的名字改为
wingdings,你会注意到字体其实并没有选到。你必须告诉Windows这种字体是一种符号字体而不是一种标准字符字体。后面会继续解释。
GLvoid BuildFont(GLvoid) // 创建位图字体
{
GLYPHMETRICSFLOAT gmf[256]; // 记录256个字符的信息
HFONT font; // 字体句柄
base = glGenLists(256); // 创建256个显示列表
font = CreateFont( -12, // 字体高度
0, // 字体宽度
0, // 字体的旋转角度 Angle Of Escapement
0, // 字体底线的旋转角度Orientation Angle
FW_BOLD, // 字体的重量
FALSE, // 是否使用斜体
FALSE, // 是否使用下划线
FALSE, // 是否使用删除线
这就是有魔力的那一行!不使用第14课中的ANSI_CHARSET,我们将使用SYMBOL_CHARSET。这会告诉Windows我们创建的字体并不是由标准字符组成的典型字体。所谓符号字体通常是由一些小图片(符号)组成的
。如果你忘了改变这行,wingdings,webdings以及你想用的其它符号字体就不会工作。
SYMBOL_CHARSET, // 设置字符集
下面几行没有变化。
OUT_TT_PRECIS, // 输出精度
CLIP_DEFAULT_PRECIS, // 裁剪精度
ANTIALIASED_QUALITY, // 输出质量
FF_DONTCARE|DEFAULT_PITCH, // Family And Pitch
既然我们已经选择了符号字符集标识符,我们就可以选择wingdings字体了
"Wingdings"); // 字体名称
剩下几行代码没有变化
SelectObject(hDC, font); // 选择创建的字体
wglUseFontOutlines( hDC, // 设置当前窗口设备描述表的句柄
0, // 用于创建显示列表字体的第一个字符的ASCII值
255, // 字符数
base, // 第一个显示列表的名称
我们允许有更多的误差,这意味着GL不会严格的遵守字体的轮廓线。如果你把误差设置为0.0f,你就会发现严格地在曲面上贴图存在一些问题。但是如果你允许一定的误差,很多问题都可以避免。
0.1f, // 字体的光滑度,越小越光滑,0.0为最光滑的状态
下面三行代码还是相同的
0.2f, // 在z方向突出的距离
WGL_FONT_POLYGONS, // 使用多边形来生成字符,每个顶点具有独立的法线
gmf); // 一个接收字形度量数据的数组的地址,每个数组元素用它对应的显示列表字符的数据填充
}
在ReSizeGLScene()函数之前,我们要加上下面一段代码来读取纹理。你可能会认得这些前几课中的代码。我们创建一个保存位图的地方,读取位图,告诉Windows生成一个纹理,并把它保存在texture[0]中。
我们创建一种细化纹理(mipmapped texture),这样会看起来好些。纹理的名字叫做lights.bmp。
if (TextureImage[0]=LoadBMP("Data/Lights.bmp")) // 载入位图
下面四行代码将为我们绘制在屏幕上的任何物体自动生成纹理坐标。函数glTexGen非常强大,而且复杂,如果要完全讲清楚它的数学原理需要再写一篇教程。不过,你只要知道GL_S和GL_T是纹理坐标就可以了。默认
状态下,它被设置为提取物体此刻在屏幕上的x坐标和y坐标,并把它们转换为顶点坐标。你会发现到物体在z平面没有纹理,只显示一些斑纹。正面和反面都被赋予了纹理,这些都是由glTexGen函数产生的。(X
(GL_S)用于从左到右映射纹理,Y(GL_T)用于从上到下映射纹理。
GL_TEXTURE_GEN_MODE允许我们选择我们想在S和T纹理坐标上使用的纹理映射模式。你有3种选择:
GL_EYE_LINEAR - 纹理会固定在屏幕上。它永远不会移动。物体将被赋予处于它通过的地区的那一块纹理。
GL_OBJECT_LINEAR - 这种就是我们使用的模式。纹理被固定于在屏幕上运动的物体上。
GL_SPHERE_MAP - 每个人都喜欢。创建一种有金属质感的物体。
// 设置纹理映射模式
glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
glEnable(GL_TEXTURE_GEN_S); // 使用自动生成纹理
glEnable(GL_TEXTURE_GEN_T);
在InitGL()的最后有几行新代码。BuildFont()被放到了读取纹理的代码之后。glEnable(GL_COLOR_MATERIAL) 这行被删掉了,如果你想使用glColor3f(r,g,b)来改变纹理的颜色,那么就把glEnable
(GL_COLOR_MATERIAL)这行重新加到这部分代码中。
int InitGL(GLvoid) // 此处开始对OpenGL进行所有设置
{
if (!LoadGLTextures()) // 载入纹理
{
return FALSE; // 失败则返回
}
BuildFont(); // 创建字体显示列表
glShadeModel(GL_SMOOTH); // 启用阴影平滑
glClearColor(0.0f, 0.0f, 0.0f, 0.5f); // 黑色背景
glClearDepth(1.0f); // 设置深度缓存
glEnable(GL_DEPTH_TEST); // 启用深度测试
glDepthFunc(GL_LEQUAL); // 所作深度测试的类型
glEnable(GL_LIGHT0); // 使用第0号灯
glEnable(GL_LIGHTING); // 使用光照
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // 告诉系统对透视进行修正
启动2D纹理映射,并选择第一个纹理。这样就把第一个纹理映射到我们绘制在屏幕上的3D物体上了。如果你想加入更多的操作,可以按自己的意愿启动或禁用纹理映射。
glEnable(GL_TEXTURE_2D); // 使用二维纹理
glBindTexture(GL_TEXTURE_2D, texture[0]); // 选择使用的纹理
return TRUE; // 初始化成功
}
重置大小的代码没有变化,但DrawGLScene这部分代码有变化。
这里是第一处变动。我们打算使用COS和SIN让物体绕着屏幕旋转而不是把它固定在屏幕中间。我们将把物体向屏幕里移动3个单位。在x轴,我们将移动范围限制在-1.1到+1.1之间。我们使用rot变量来控制左右移动
。我们把上下移动的范围限制在+0.8到-0.8之间。同样使用rot变量来控制上下移动(最好充分利用你的变量)。
// 设置字体的位置
glTranslatef(1.1f*float(cos(rot/16.0f)),0.8f*float(sin(rot/20.0f)),-3.0f);
下面做常规的旋转。这会使符号在X,Y和Z轴旋转。
glRotatef(rot,1.0f,0.0f,0.0f); // 沿X轴旋转
glRotatef(rot*1.2f,0.0f,1.0f,0.0f); // 沿Y轴旋转
glRotatef(rot*1.4f,0.0f,0.0f,1.0f); // 沿Z轴旋转
我们将物体相对观察点向左向下移动一点,以便于把符号定位于每个轴的中心。否则,当我们旋转它的时候,看起来就不像是在围绕它自己的中心在旋转。-0.35只是一个能让符号正确显示的数。我也试过一些其它数,
因为我不知道这种字体的宽度是多少,可以适情况作出调整。我不知道为什么这种字体没有一个中心。
glTranslatef(-0.35f,-0.35f,0.1f); // 移动到可以显示的位置
最后,我们绘制海盗旗的符号,然后增加rot变量,从而使这个符号在屏幕中旋转和移动。如果你不知道我是如何从字母‘N’中得到海盗旗符号的,那就打开Microsoft Word或是写字板。在字体下拉菜单中选择
Wingdings字体。输入大写字母‘N’,就会显示出海盗旗符号了。
glPrint("N"); // 绘制海盗旗符号
rot+=0.1f; // 增加旋转变量
最后要做的事就是在KillGLWindow()的最后添加KillFont()函数,如下所示。添加这行代码很重要。它将在我们退出程序之前做清理工作。
原文及其个版本源代码下载:
http://nehe.gamedev.net/data/lessons/lesson.asp?lesson=15
NeHe OpenGL教程 第十五课:纹理图形字相关推荐
- NeHe OpenGL第三十五课:播放AVI
NeHe OpenGL第三十五课:播放AVI 在OpenGL中播放AVI: 在OpenGL中如何播放AVI呢?利用Windows的API把每一帧作为纹理绑定到OpenGL中,虽然很慢,但它的效果不错. ...
- NeHe OpenGL教程 第二十九课:Blt函数
转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...
- NeHe OpenGL教程 第二十六课:反射
转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...
- NeHe OpenGL第三十二课:拾取游戏
NeHe OpenGL第三十二课:拾取游戏 拾取, Alpha混合, Alpha测试, 排序: 这又是一个小游戏,交给的东西会很多,慢慢体会吧 欢迎来到32课. 这课大概是在我所写作已来最大的一课 ...
- NeHe OpenGL第三十九课:物理模拟
NeHe OpenGL第三十九课:物理模拟 物理模拟简介: 还记得高中的物理吧,直线运动,自由落体运动,弹簧.在这一课里,我们将创造这一切. 物理模拟介绍 如果你很熟悉物理规律,并且想实现它,这篇 ...
- NeHe OpenGL第四十四课:3D光晕
NeHe OpenGL第四十四课:3D光晕 3D 光晕 当镜头对准太阳的时候就会出现这种效果,模拟它非常的简单,一点数学和纹理贴图就够了.好好看看吧. 大家好,欢迎来到新的一课,在这一课中我们将扩 ...
- NeHe OpenGL第四十六课:全屏反走样
NeHe OpenGL第四十六课:全屏反走样 全屏反走样 当今显卡的强大功能,你几乎什么都不用做,只需要在创建窗口的时候该一个数据.看看吧,驱动程序为你做完了一切. 在图形的绘制中,直线的走样是非 ...
- NeHe OpenGL教程 第十课:3D世界
转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...
- NeHe OpenGL教程 第三十七课:卡通映射
转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...
最新文章
- :link,:visited,:focus,:hover,:active详解
- MySQL5.7号称永久解决了复制延迟问题的并行复制
- linux df -h卡成狗
- android 360加固 例子,[原创]利用VirtualApp实现360加固的soHook简单例子
- Hibernate读书笔记
- 7、JPA-映射-双向一对多
- linux+读取初始化文件,Linux 初始化系统 SystemV Upstart
- CISCO路由器的备份与还原(2)
- 周立功arm linux教程,极速搭建周立功IMX287A ARM Linux开发环境
- 曲线运动与万有引力公式_【知识总结】物理必修二曲线运动与万有引力相关公式和规律...
- 陈景润定理对筛法理论的重要贡献
- SD卡CF卡U盘硬盘等磁盘属性显示为0字节怎么恢复数据
- PCB设计——使用Altium Designer做PCB拼版文件技巧总结
- 小游戏类项目 —— 五子棋游戏
- 嘉士达擦玻璃机器人_擦窗机器人哪个牌子好?最好用的三个擦玻璃机器人品牌推荐...
- RabbitMQ重试机制+死信队列
- CNNIC第43次调查报告:微信政务服务
- 【Unity】动作游戏开发实战详细分析-25-角色残影效果的实现
- 赞奇超高清云工作站新功能更新,总有一个功能适合你
- 电商企业微博营销:挖掘粉丝深层价值
热门文章
- 大数据运维--Linux安装java
- 自定义一个求平均值函数
- 路由器的信号无法连接到服务器,华为路由器可以搜到 Wi-Fi 信号 但无法连接 解决办法...
- notepad++ 使用
- 中国现在哪里有什么世界一流大学?
- Android获取系统字体的大小,Android中设置字体不随系统字体大小而变化
- 限制儿童使用计算机,大神应对win7系统开启家长控制限制儿童使用计算机的操作的办法介绍...
- mysql 复合索引_mysql联合索引(复合索引)详解
- 2015年计算机网络原理真题,2015年4月04741计算机网络原理试题及答案-20210413074741.docx-原创力文档...
- 最全面的SpringMVC教程(一)——SpringMVC简介