📄 tutorial_17.htm
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"><html><head><!-- 这篇文章由Dancingwind翻译,作者的联系方式zhouwei02@mails.tsinghua.edu.cn --><title>NeHe OpenGL教程第十七课,DancingWind翻译</title>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<style type="text/css">
A:link {COLOR: #ccaaff; TEXT-DECORATION: none}
A:visited {COLOR: #ccaaff; TEXT-DECORATION: none}
A:active {COLOR: #ccaaff; TEXT-DECORATION: none}
A:hover {COLOR: #ffccaa; TEXT-DECORATION: none}
</style></head><body bgcolor="#000000" text="#ffffff"><br><br>
<table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td height="130" width="326"><img src="Tutorial_17_files/logo.png" height="130" width="326"></td>
<td align="center" valign="middle" width="75%"><font color="#ffccaa" size="+3"><b><i>第17课</i></b></font></td>
</tr></tbody></table>
<!-- 上边框-->
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody>
<tr>
<td><img src="Tutorial_17_files/tl.jpg" height="28" width="28"></td>
<td width="100%"><img src="Tutorial_17_files/tc.gif" height="28" width="100%"></td>
<td><img src="Tutorial_17_files/tr.gif" height="28" width="28"></td>
</tr>
</tbody>
</table>
<!-- 中部-->
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody>
<tr>
<!-- 中部左边框-->
<td background="Tutorial_17_files/l.gif"><img src="Tutorial_17_files/l.gif" height="28" width="28"></td>
<!-- 中部文字部分-->
<td valign="top" width="100%">
<table border="0" width="100%">
<tbody><tr>
<td width="30%"><img src="Tutorial_17_files/lesson17.jpg" height="180" width="240"></td>
<td width="70%"><p><font class="head">2D 图像文字:</font></p>
<p><font size="3">在这一课中,你将学会如何使用四边形纹理贴图把文字显示在屏幕上。你将学会如何把256个不同的文字从一个256x256的纹理图像中分别提取出来,并为每一个文字创建一个显示列表,接着创建一个输出函数来创建任意你希望的文字。</font></p></td>
</tr>
</tbody></table>
</td>
<!-- 中部右边框-->
<td background="Tutorial_17_files/r.gif"><img src="Tutorial_17_files/r.gif" height="28" width="28"></td>
</tr>
</tbody>
</table>
<!-- 下边框-->
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody>
<tr>
<td><img src="Tutorial_17_files/bl.gif" height="28" width="28"></td>
<td width="100%"><img src="Tutorial_17_files/bc.gif" height="28" width="100%"></td>
<td><img src="Tutorial_17_files/br.gif" height="28" width="28"></td>
</tr>
</tbody>
</table>
<table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td><img src="Tutorial_17_files/tl.png" height="28" width="28"></td><td width="100%"><img src="Tutorial_17_files/tc.png" height="28" width="100%"></td><td><img src="Tutorial_17_files/tr.png" height="28" width="28"></td></tr></tbody></table><table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td background="Tutorial_17_files/l.png"><img src="Tutorial_17_files/l.png"></td>
<td valign="top" width="100%">本教程由NeHe和Giuseppe D'Agata提供。
<p>我知道每个人都或许厌恶字体。目前为止我写的文字教程不仅能显示文字,还能显示3D文字,有纹理贴图的文字,以及处理变量。但是当你将你的作品移植到不支持位图或是轮廓字体的机器上会发生什么事呢?</p>
<p>由
于Giuseppe
D'Agata我们有了另一篇字体教程。你还会问什么?如果你记得在第一篇字体教程中我提到使用纹理在屏幕上绘制文字。通常当你使用纹理绘制文字时你会调
用你最喜欢的图像处理程序,选择一种字体,然后输入你想显示的文字或段落。然后你保存位图并把它作为纹理读入到你的程序里。对一个需要很多文字或是文字在
不停变化的程序来说这么做效率并不高。 </p>
<p>本教程只使用有一个纹理来显示任意256个不同的字符。记住平均一个字符只有16个像素宽,大概16个像
素高。如果你使用标准的256x256的纹理那么很明显你可以放入交叉的16个文字(即一个X),且最多16行16列。如果你需要一个更详细的解释:纹理
是256个像素宽,一个字符是16个像素宽,256除以16得16:)</p>
<p>现在让我们来创建一个2D纹理字体demo!这课的
程序基于第一课的代码。在程序的第一段,我们包括数学(math)和标准输入输出库(stdio)。我们需要数学库来使用正弦和余弦函数在屏幕上移动我们
的文字,我们需要标准输入输出库来保证在我们制作纹理前要使用的位图实际存在。<br>
</p></td>
<td background="Tutorial_17_files/r.gif"><img src="Tutorial_17_files/r.gif" height="28" width="28"></td>
</tr>
</tbody></table>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody><tr>
<td><img src="Tutorial_17_files/bl.gif" height="28" width="28"></td>
<td width="100%"><img src="Tutorial_17_files/bc.gif" height="28" width="100%"></td>
<td><img src="Tutorial_17_files/br.gif" height="28" width="28"></td>
</tr>
</tbody></table>
<font color="#aaffaa" size="3"> </font>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody><tr>
<td><img src="Tutorial_17_files/tl.jpg" height="28" width="28"></td>
<td width="100%"><img src="Tutorial_17_files/tc.gif" height="28" width="100%"></td>
<td><img src="Tutorial_17_files/tr.gif" height="28" width="28"></td>
</tr>
</tbody></table>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody><tr>
<td background="Tutorial_17_files/l.gif"><img src="Tutorial_17_files/l.gif" height="28" width="28"></td>
<td valign="top" width="100%">我们将要加入一个变量base来指向我们的显示列表。我们还加入texture[2]来保存我们将要创建的两个纹理。Texture
1将是字体纹理,texture 2将是用来创建简单3D物体的凹凸纹理。
<p>我们加入用来执行循环的变量loop。最后我们加入用来绕屏幕移动文字和旋转3D物体的cnt1和cnt2。<br>
</p></td>
<td background="Tutorial_17_files/r.gif"><img src="Tutorial_17_files/r.gif" height="28" width="28"></td>
</tr>
</tbody></table>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody><tr>
<td><img src="Tutorial_17_files/bl.gif" height="28" width="28"></td>
<td width="100%"><img src="Tutorial_17_files/bc.gif" height="28" width="100%"></td>
<td><img src="Tutorial_17_files/br.gif" height="28" width="28"></td>
</tr>
</tbody></table>
<font color="#aaffaa" size="3">
<pre>GLuint base; <font color="#ffffaa">// 绘制字体的显示列表的开始位置</font>
GLuint texture[2]; <font color="#ffffaa">// 保存字体纹理</font>
GLuint loop; <font color="#ffffaa">// 通用循环变量</font>
GLfloat cnt1; <font color="#ffffaa">// 字体移动计数器1</font>
GLfloat cnt2; <font color="#ffffaa">// 字体移动计数器2</font>
</pre>
</font>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody><tr>
<td><img src="Tutorial_17_files/tl.jpg" height="28" width="28"></td>
<td width="100%"><img src="Tutorial_17_files/tc.gif" height="28" width="100%"></td>
<td><img src="Tutorial_17_files/tr.gif" height="28" width="28"></td>
</tr>
</tbody></table>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody><tr>
<td background="Tutorial_17_files/l.gif"><img src="Tutorial_17_files/l.gif" height="28" width="28"></td>
<td valign="top" width="100%">接下来是读取纹理代码。这跟前面纹理影射教程中的一模一样。</td>
<td background="Tutorial_17_files/r.gif"><img src="Tutorial_17_files/r.gif" height="28" width="28"></td>
</tr>
</tbody></table>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody><tr>
<td><img src="Tutorial_17_files/bl.gif" height="28" width="28"></td>
<td width="100%"><img src="Tutorial_17_files/bc.gif" height="28" width="100%"></td>
<td><img src="Tutorial_17_files/br.gif" height="28" width="28"></td>
</tr>
</tbody></table>
<font color="#aaffaa" size="3"> </font>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody><tr>
<td><img src="Tutorial_17_files/tl.jpg" height="28" width="28"></td>
<td width="100%"><img src="Tutorial_17_files/tc.gif" height="28" width="100%"></td>
<td><img src="Tutorial_17_files/tr.gif" height="28" width="28"></td>
</tr>
</tbody></table>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody><tr>
<td background="Tutorial_17_files/l.gif"><img src="Tutorial_17_files/l.gif" height="28" width="28"></td>
<td valign="top" width="100%">下面的代码同样对之前教程的代码改动很小。如果你不清楚下面每行的用途,回头复习一下。<br>
注意TextureImage[ ]将保存2个rgb图像记录。复查处理读取或存储纹理的纹理很重要。一个错误的数字可能导致内存溢出或崩溃!</td>
<td background="Tutorial_17_files/r.gif"><img src="Tutorial_17_files/r.gif" height="28" width="28"></td>
</tr>
</tbody></table>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody><tr>
<td><img src="Tutorial_17_files/bl.gif" height="28" width="28"></td>
<td width="100%"><img src="Tutorial_17_files/bc.gif" height="28" width="100%"></td>
<td><img src="Tutorial_17_files/br.gif" height="28" width="28"></td>
</tr>
</tbody></table>
<font color="#aaffaa" size="3">
<pre>int LoadGLTextures() <font color="#ffffaa">// 载入位图(调用上面的代码)并转换成纹理</font>
{
int Status=FALSE; <font color="#ffffaa">// 状态指示器</font>
AUX_RGBImageRec *TextureImage[2]; <font color="#ffffaa">// 创建纹理的存储空间</font>
</pre>
</font>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody><tr>
<td><img src="Tutorial_17_files/tl.jpg" height="28" width="28"></td>
<td width="100%"><img src="Tutorial_17_files/tc.gif" height="28" width="100%"></td>
<td><img src="Tutorial_17_files/tr.gif" height="28" width="28"></td>
</tr>
</tbody></table>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody><tr>
<td background="Tutorial_17_files/l.gif"><img src="Tutorial_17_files/l.gif" height="28" width="28"></td>
<td valign="top" width="100%">下一行十分重要。如果你用别的数字替换2将发生严重问题。再查一次!这个数字应该与你在设置TextureImages[
]时的数字相匹配。
<p>我们将读取的纹理是font.bmp 和bumps.bmp。第二个纹理可用任何你想用的纹理替换。我不是特别有创造性,所以我使的纹理可能有些单调。<br>
</p></td>
<td background="Tutorial_17_files/r.gif"><img src="Tutorial_17_files/r.gif" height="28" width="28"></td>
</tr>
</tbody></table>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody><tr>
<td><img src="Tutorial_17_files/bl.gif" height="28" width="28"></td>
<td width="100%"><img src="Tutorial_17_files/bc.gif" height="28" width="100%"></td>
<td><img src="Tutorial_17_files/br.gif" height="28" width="28"></td>
</tr>
</tbody></table>
<font color="#aaffaa" size="3">
<pre>memset(TextureImage,0,sizeof(void *)*2); <font color="#ffffaa"> // 将指针设为 NULL</font>
if ((TextureImage[0]=LoadBMP("Data/Font.bmp")) && <font color="#ffffaa">// 载入字体图像</font>
(TextureImage[1]=LoadBMP("Data/Bumps.bmp"))) <font color="#ffffaa">// 载入纹理图像</font>
{
Status=TRUE; <font color="#ffffaa">// 将 Status 设为 TRUE</font>
</pre>
</font>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody><tr>
<td><img src="Tutorial_17_files/tl.jpg" height="28" width="28"></td>
<td width="100%"><img src="Tutorial_17_files/tc.gif" height="28" width="100%"></td>
<td><img src="Tutorial_17_files/tr.gif" height="28" width="28"></td>
</tr>
</tbody></table>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody><tr>
<td background="Tutorial_17_files/l.gif"><img src="Tutorial_17_files/l.gif" height="28" width="28"></td>
<td valign="top" width="100%">另一十分重要,要检查两遍的行。我无法开始告诉你我收到多少email问“为什么我只看到一个纹理,或为什么我的纹理是全白的!?!”通常问题都出在这行。如果你用1替换2,那么将只创建一个纹理,第二个纹理将显示为全白。如果你用3替换2,你的程序可能崩溃!
<p>你
应该只调用glGenTextures()一次。调用glGenTextures()后你应该创建你的所有纹理。我曾见过有人在每创建一个纹理前都加上一
行glGenTextures()。这通常导致新建的纹理覆盖了你之前创建的。决定你需要创建多少个纹理是个好主意,调用glGenTextures()
一次,然后创建所有的纹理。把glGenTextures()放进循环是不明智的,除非你有自己的理由。<br>
</p></td>
<td background="Tutorial_17_files/r.gif"><img src="Tutorial_17_files/r.gif" height="28" width="28"></td>
</tr>
</tbody></table>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody><tr>
<td><img src="Tutorial_17_files/bl.gif" height="28" width="28"></td>
<td width="100%"><img src="Tutorial_17_files/bc.gif" height="28" width="100%"></td>
<td><img src="Tutorial_17_files/br.gif" height="28" width="28"></td>
</tr>
</tbody></table>
<font color="#aaffaa" size="3">
</font><pre><font color="#aaffaa" size="3">glGenTextures(2, &texture[0]); <font color="#ffffaa">// 创建纹理</font>
for (loop=0; loop<2; loop++) <font color="#ffffaa">// 循环设置所有的纹理</font>
{
<font color="#ffffaa">// 生成所有纹理</font>
glBindTexture(GL_TEXTURE_2D, texture[loop]);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[loop]->sizeX, TextureImage[loop]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[loop]->data);
}
}
</font></pre>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -