|
|

楼主 |
发表于 2004-10-7 01:58:00
|
显示全部楼层
Re:NeHe OpenGL Tutorial lesson 13[原创]
NeHe
OpenGL
Tutorial
by NeHe
原著 Jeff Molofee (NeHe) http://nehe.gamedev.net/
nehe@connect.ab.ca
译著 戴瑞 DaiRui (Terry) QQ: 21240154
my blog: http://the_eternal_god.blogone.net
e-mail addr: terryd1983@yahoo.com.cn
the_eternal_god@163.com
the_eternal_god @hotmail.com
Version 1.0.0
Preface
这是我第一次进行翻译,呵呵,在这里首先感谢原著作者Jeff Molofee (NeHe),为我们提供了很好的学习材料,其次我要感谢江超宇 (Aman JIANG),是他给了我想要进行翻译的冲动。恩,还要感谢我的一位网友七七(PP)她在我翻译过程中很热心的听我解释并提出自己的看法,Terry特地向她表示感谢。
下面是原文的保留字。
Originally compiled by LOneWoolf
Recompiled by M0RPhEuS
The lessons on this page may contain mistakes, poor commenting, and should not be considered the best resource to learn OpenGL from. What you do with the code is up to you. I am merely trying to make the learning process a little easier for those people new to OpenGL. If you are serious about learning OpenGL, you should spend the money and invest in the OpenGL Red Book (ISBN 0-201-46138-2) and OpenGL Blue Book (ISBN 0-201-46140-4). I have the second edition of each book, and although they can be difficult for the new OpenGL programmer to understand, they are by far the best books written on the subject of OpenGL. Another book I would recommend is the OpenGL Superbible, although opinions vary. It is also important that you have a solid understanding of the language you plan to use. Although I do comment the non-GL lines, I am self-taught, and may not always write proper or even good code. It's up to you to take what you have learned from this site and apply it to projects of your own. Play around with the code, read books, ask me questions if need be. Once you have surpassed the code on this site or even before, check out some of the more professional sites such as OpenGL.org. Also be sure to visit the many OpenGL links on my page. Each site I link to is an incredible asset the OpenGL community. Most of these sites are run by talented individuals that not only know their GL, they also program alot better than I do. Please keep all of this in mind while browsing my site. I hope you enjoy what I have to offer, and hope to see projects created by yourself in the near future!
One final note, if you see code that you feel is to similar to someone else's code, please contact me. I assure you, any code I borrow from or learn from either comes from the MSDN or from sites created to help teach people in a similar way that my site teaches GL. I never intentionally take code, and never would without giving the proper person credit. There may be instances where I get code from a free site not knowing that site took it from someone else, so if that happens, please contact me. I will either rewrite the code, or remove it from my program. Most the code should be original however, I only borrow when I absolutely have no idea how to accomplish something, and even then I make sure I understand the code before I decide to include it in my program. If you spot mistakes in any of the lessons, no matter how tiny the mistake may be, please let me know.
One important thing to note about my base code is that it was written in 1997. It has undergone many changes, and it is definitely not borrowed from any other sites. It will more than likely be altered in the future. If I am not the one that modifies it, the person responsible for the changes will be credited.
Lesson 13
Bitmap Fonts:
原文Index中的前言:
I think the question I get asked most often in email is "how can I display text on the screen using OpenGL?". You could always texture map text onto your screen. Of course you have very little control over the text, and unless you're good at blending, the text usually ends up mixing with the images on the screen. If you'd like an easy way to write the text you want anywhere you want on the screen in any color you want, using any of your computers built in fonts, then this tutorial is definitely for you. Bitmaps font's are 2D scalable fonts, they can not be rotated. They always face forward.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
正文:
Welcome to yet another Tutorial. This time on I'll be teaching you how to use Bitmap Fonts. You may be saying to yourself "what's so hard about putting text onto the screen". If you've ever tried it, it's not that easy!
欢迎进入教程新的一课。这次我将告诉你如何使用位图字体(原文Bitmap Fonts)。你或许会自言自语道:“在屏幕上绘制字符(原文:text文本)有什么困难的。”但是,如果你尝试过的话,你会发现,它的确不是那么容易的呢!
Sure you can load up an art program, write text onto an image, load the image into your OpenGL program, turn on blending then map the text onto the screen. But this is time consuming, the final result usually looks blurry or blocky depending on the type of filtering you use, and unless your image has an alpha channel your text will end up transparent (blended with the objects on the screen) once it's mapped to the screen.
当然,你可以使用一个图像处理程序(原文: an art program),把文字(text)写在一幅图(原文: an image)上,然后把这幅图像载入到你的OpenGL程序[Terry:就是你正在写的,使用到OpenGL程序]里面。
If you've ever used Wordpad, Microsoft Word or some other Word Processor, you may have noticed all the different types of Font's available. This tutorial will teach you how to use the exact same fonts in your own OpenGL programs. As a matter of fact... Any font you install on your computer can be used in your demos.
如果你曾用过“写字板”(Wordpad,Windows的写字板程序),Microsoft Word(Terry:微软Word)或者别的什么字处理软件的话,你或许已经注意到了他们都支持很多不同的可选字体。这一课将教你怎样在你的程序里使用那些特定字体。 实际上,你可以在你的程序中使用在你机器上安装的任何字体。
Not only do Bitmap Fonts looks 100 times better than graphical fonts (textures). You can change the text on the fly. No need to make textures for each word or letter you want to write to the screen. Just position the text, and use my handy new gl command to display the text on the screen.
“位图字体(原文Bitmap Fonts)”可不仅仅是比“图形字体”[原文:graphical font (textures)]看起来好一百倍。[Terry:其实就是前面所述的那种使用image的方法]
你还可以频繁地改变文字(原文:the text) [Terry:原文说是:“You can change the text on the fly.”,字典中,把on the fly解释为“匆忙的”,呵呵我还是觉得写成“频繁”的好] 。
你没有必要再为每个你想要的单词或是字母创建纹理了,你要做得仅仅只是确定显示得位置,然后使用我现成的gl命令(原文: gl command)来在屏幕上显示那些文字。
I tried to make the command as simple as possible. All you do is type glPrint("Hello"). It's that easy. Anyways. You can tell by the long intro that I'm pretty happy with this tutorial. It took me roughly 1 1/2 hours to create the program. Why so long? Because there is literally no information available on using Bitmap Fonts, unless of course you enjoy MFC code. In order to keep the code simple I decided it would be nice if I wrote it all in simple to understand C code
我尽力使得命令能够简单。你所需要做的只是敲入glPrint("Hello"),这是多么简单啊。恩,通过这么长的介绍,你可以发现我因为写了这一课而感到非常的高兴呢。[Terry: 原文为“Anyways. You can tell by the long intro that I'm pretty happy with this tutorial.”,但是我觉得自己译得还不够“信达雅”]。恩,写这个程序花了我大概一个半小时。为什么会花这么长时间呢?因为,关于使用“位图字体(原文Bitmap Fonts)”,没有现成可用的文字信息,当然除非你喜欢MFC的代码[Terry:“当然除非你喜欢MFC的代码”, 我还没搞明白呢]。为了保持代码简单,我觉得自己使用简单易懂的C代码来写程序会比较好,于是我使用了C代码。
A small note, this code is Windows specific. It uses the wgl functions of Windows to build the font. Apparently Apple has agl support that should do the same thing, and X has glx. Unfortunately I can't guarantee this code is portable. If anyone has platform independant code to draw fonts to the screen, send it my way and I'll write another font tutorial.
这里小小的提示一下,这个代码是针对Windows的。它使用了Windows wgl函数建立字体。当然[Terry:原文:“Apparently”,“显然”,我觉得还是用“当然”好],苹果有agl支持,X有glx,它们都完成和wgl同样的事情。[Terry: 我不知道X是什么是X window,是不是用于Unix的窗口阿?]但不幸的是,我不能保证这个代码的可移植性[Terry: 就是不一定可以用在别的平台上],如果谁写出了绘制字体的与平台无关的代码,请把它发给我,我将再写一篇关于字体的教程。
We start off with the typical code from lesson 1. We'll be adding the stdio.h header file for standard input/output operations; the stdarg.h header file to parse the text and convert variables to text, and finally the math.h header file so we can move the text around the screen using SIN and COS.
还是从第一课的代码开始吧。 我们将包含stdio.h头文件以使用标准的 输入/输出 操作(stdio.h头文件分析文本并把变量转换为文本)然后包含math.h头文件,这样我们就可以使用SIN 和 COS把文字在屏幕上移来移去了[Terry: SIN,COS应该是正弦函数和余弦函数]。
#include <windows.h> // Header File For Windows
#include <math.h> // Header File For Windows Math Library
#include <stdio.h> // Header File For Standard Input/Output
#include <stdarg.h> // Header File For Variable Argument Routines
#include <gl\gl.h> // Header File For The OpenGL32 Library
#include <gl\glu.h> // Header File For The GLu32 Library
#include <gl\glaux.h> // Header File For The Glaux Library
HDC hDC=NULL; // Private GDI Device Context
HGLRC hRC=NULL; // Permanent Rendering Context
HWND hWnd=NULL; // Holds Our Window Handle
HINSTANCE hInstance; // Holds The Instance Of The Application
We're going to add 3 new variables as well. base will hold the number of the first display list we create. Each character requires it's own display list. The character 'A' is 65 in the display list, 'B' is 66, 'C' is 67, etc. So 'A' would be stored in display list base+65.
我们还将添加3个新的变量。Base将用来存储我们创建的第一个显示列表的数字[Terry:应该相当于基地址]。每个字符需要她自己的显示列表。字符’A’在显示列表里是65,’B’是66,’C’是67,等等。所以’A’将存储在显示列表 base+65。
Next we add two counters (cnt1 & cnt2). These counters will count up at different rates, and are used to move the text around the screen using SIN and COS. This creates a semi-random looking movement on the screen. We'll also use the counters to control the color of the letters (more on this later).
接下来,我们添加两个计数器(cnt1 & cnt2)。这些计数器将按不同的变化率计数,我们将使用它们并使用SIN和COS来在屏幕上移动文字。这样就我们就创建了文字在屏幕上半随机的运动[Terry: 原文:“semi-random”,应该就是一种伪随机]。我们还是用这两个计数器来控制字母的颜色(后文将详述)。
GLuint base; // Base Display List For The Font Set
GLfloat cnt1; // 1st Counter Used To Move Text & For Coloring
GLfloat cnt2; // 2nd Counter Used To Move Text & For Coloring
bool keys[256]; // Array Used For The Keyboard Routine
bool active=TRUE; // Window Active Flag Set To TRUE By Default
bool fullscreen=TRUE; // Fullscreen Flag Set To Fullscreen Mode By Default
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); // Declaration For WndProc
The following section of code builds the actual font. This was the most difficult part of the code to write. 'HFONT font' in simple english tells Windows we are going to be manipulating a Windows font. oldfont is used for good house keeping.
下面的代码建立了字体。这是我写的代码里面最困难的部分了。’HFONT font’告诉Windows我们将要操作一个Windows字体。HFONT oldfont是用较好的完成内务处理(内部的字体处理)[Terry:原文:” oldfont is used for good house keeping.”,这个第一次没看懂啊~,现在明白了呢。就是用来保存字体的,号称为old实际上就是当时用的,因为后面的代码中直接把 font给Delete掉了阿。参见下面代码]
oldfont = (HFONT)SelectObject(hDC, font); // Selects The Font We Want
wglUseFontBitmaps(hDC, 32, 96, base); // Builds 96 Characters Starting At Character 32
SelectObject(hDC, oldfont); // Selects The Font We Want
DeleteObject(font); // Delete The Font
}
[/Terry:上面这些都是后话]
Next we define base. We do this by creating a group of 96 display lists using glGenLists(96). After the display lists are created, the variable base will hold the number of the first list.
接下来我们定义base。我们使用glGenLists(96)建立了一组有96个显示列表 (display list) 的列表组(display lists)。创建显示列表组织后,变量base将会保存第一个显示列表的数字[Terry: 编号]。
GLvoid BuildFont(GLvoid) // Build Our Bitmap Font
{
HFONT font; // Windows Font ID
HFONT oldfont; // Used For Good House Keeping
base = glGenLists(96); // Storage For 96 Characters
Now for the fun stuff. We're going to create our font. We start off by specifying the size of the font. You'll notice it's a negative number. By putting a minus, we're telling windows to find us a font based on the CHARACTER height. If we use a positive number we match the font based on the CELL height.
下面的是很有趣的哦。我们将要创建我们的字体。首先,要确定字体的大小(原文:size of the font)。你会注意到那是一个负数。通过使用负号‘-’,我们告诉Windows来为我们找到一个基于字符(原文:CHARACTER)高度的字体。如果我们使用一个正数,Windows会找到一个基于CELL高度的字体。[Terry:这个CHARACTER和 这个CELL到底是什么东东,还有待我的理解。不过我尝试过修改源码的-24,换为+/- 240 觉得没什么差别。]
font = CreateFont( -24, // Height Of Font
Then we specify the cell width. You'll notice I have it set to 0. By setting values to 0, windows will use the default value. You can play around with this value if you want. Make the font wide, etc.
然后我们确定了cell的宽度[Terry: cell不是显示的字符的笔画的宽度,而是单个字符的宽度,或者说应该是一个字符显示区域cell的宽度,这个区域有看不到的边界]。你注意到了我把它设为0了。通过把它设为0,windows将会是用默认值。如果你想要修改它的值的话,你可以试着改改看。可以把字体改宽,等等。
0, // Width Of Font
Angle of Escapement will rotate the font. Unfortunately this isn't a very useful feature. Unless your at 0, 90, 180, and 270 degrees, the font usually gets cropped to fit inside it's invisible square border. Orientation Angle quoted from MSDN help Specifies the angle, in tenths of degrees, between each character's base line and the x-axis of the device. Unfortunately I have no idea what that means 
Angle of Escapement 将会旋转字体,但是这并不是非常有用的参数。除非你的角度是0°,90°,180°
和270°,通常字体为了适应它们不可见的方形边界,从而不会被正确地裁剪。引自MSDN的Orientation Angle可以帮助解释这个角度,”in tenths of degrees, between each character's base line and the x-axis of the device.”很可惜我还不理解那究竟是什么意思。[Terry: 作者也不知道那究竟是什么,崩溃~~~]
0, // Angle Of Escapement
0, // Orientation Angle
Font weight is a great parameter. You can put a number from 0 - 1000 or you can use one of the predefined values. FW_DONTCARE is 0, FW_NORMAL is 400, FW_BOLD is 700 and FW_BLACK is 900. There are alot more predefined values, but those 4 give some good variety. The higher the value, the thicker the font (more bold).
字体的笔画宽度(原文:Font weight)是一个很重要的参数。你可以给它一个介于0和1000之间的数,或者给它一些预定义的取值。FW_DONTCARE值为0,FW_NORMAL值为400,FW_BOLD值为700,FW_BLACK值为900。当然还有很多预定义值,这4个预定义值已经够用了(原文: but those 4 give some good variety.)。[Terry:Font weight是字体的字形笔画宽度(可以理解为笔画格式,比如 FW_BOLD粗体,FW_BLACK在VC6的WINGDI.h头文件中被定义为FW_HEAVY值为900,等等)]
取值越大,字体笔画越宽(越粗) (原文:The higher the value, the thicker the font (more bold).)。
FW_BOLD, // Font Weight
Italic, Underline and Strikeout can be either TRUE or FALSE. Basically if underline is TRUE, the font will be underlined. If it's FALSE it wont be. Pretty simple :)
斜体,下划线,删除线的取值可以为TRUE 或者 FALSE。基本上,如果下划线(underline)取值为TRUE,则字体将会带有下划线。如果下划线(underline)为FALSE,则字体不会带有下划线。很简单是吧:)
FALSE, // Italic
FALSE, // Underline
FALSE, // Strikeout
Character set Identifier describes the type of Character set you wish to use. There are too many types to explain. CHINESEBIG5_CHARSET, GREEK_CHARSET, RUSSIAN_CHARSET, DEFAULT_CHARSET, etc. ANSI is the one I use, although DEFAULT would probably work just as well.
字符集描述符(原文:Character set Identifier)描述了你想要使用的字符集的类型。字符集有好多类型的。CHINESEBIG5_CHARSET, GREEK_CHARSET, RUSSIAN_CHARSET, DEFAULT_CHARSET,等等[Terry: 大家从定义的这些名字就可以看出来了吧,我就不再解释了。]。 尽管DEFAULT (默认)或许也可以正常使用,但我用的字符集是ANSI。
If you're interested in using a font such as Webdings or Wingdings, you need to use SYMBOL_CHARSET instead of ANSI_CHARSET.
如果你想使用Webdings字体 或者 Wingdings字体[Terry:是两种西文字体,看起来都是符号,恩,你可以在Word里面试试看,呵呵],你就需要使用SYMBOL_CHARSET来换掉ANSI_CHARSET。
ANSI_CHARSET, // Character Set Identifier
Output Precision is very important. It tells Windows what type of character set to use if there is more than one type available. OUT_TT_PRECIS tells Windows that if there is more than one type of font to choose from with the same name, select the TRUETYPE version of the font. Truetype fonts always look better, especially when you make them large. You can also use OUT_TT_ONLY_PRECIS, which ALWAYS trys to use a TRUETYPE Font.
输出精度非常的重要。如果有多于一个的字符集类型可用的情况下,它会告知Windows要使用什么类型的字符集。OUT_TT_PRECIS告知Windows,如果由同一个名字可以选择不只一个字体类型的话,则选择字体的TRUETYPE版本(原文:OUT_TT_PRECIS tells Windows that if there is more than one type of font to choose from with the same name, select the TRUETYPE version of the font.)特别是当你把文字变得很大时,Truetype字体会看起来跟好的。你还可以使用OUT_TT_ONLY_PRECIS,它总是尝试使用一个TRUETYPE字体。
OUT_TT_PRECIS, // Output Precision。
Clipping Precision is the type of clipping to do on the font if it goes outside the clipping region. Not much to say about this, just leave it set to default.
裁剪精度描述的是 如果字体超出了裁剪区域(原文:the clipping region)时所使用的裁剪类型[Terry: the clipping region可能就是前面说的那个cell的东东。]。我不想过多地解释它,这里把它设成默认值。
CLIP_DEFAULT_PRECIS, // Clipping Precision
Output Quality is very important. You can have PROOF, DRAFT, NONANTIALIASED, DEFAULT or ANTIALIASED. We all know that ANTIALIASED fonts look good :) Antialiasing a font is the same effect you get when you turn on font smoothing in Windows. It makes everything look less jagged.
输出品质也非常重要。你可以使用DEFAULT 默认,DRAFT草稿,PROOF印刷,NONANTIALIASED无抗锯齿 或者 ANTIALIASED抗锯齿[Terry:这里我改变了这些值的顺序,我的顺序是参照WINGDI.h中的定义顺序由小到大的排列的。恩“ANTIALIASED抗锯齿”,也可以译作“反走样”,意思一样,但是从字面上看还是“抗锯齿”比较形象贴切,因为图形光栅化之后呢的确会呈现锯齿状的呢。]。我们都知道ANTIALIASED抗锯齿的字体看起来会很棒:) ,消除一个字体的锯齿走样同样可以在Windows中打开字体平滑时实现(原文 :Antialiasing a font is the same effect you get when you turn on font smoothing in Windows.)它会使所有字体看起来比较平滑(原文:It makes everything look less jagged. Jagged,锯齿状的)
ANTIALIASED_QUALITY, // Output Quality
Next we have the Family and Pitch settings. For pitch you can have DEFAULT_PITCH, FIXED_PITCH and VARIABLE_PITCH, and for family you can have FF_DECORATIVE, FF_MODERN, FF_ROMAN, FF_SCRIPT, FF_SWISS, FF_DONTCARE. Play around with them to find out what they do. I just set them both to default.
下来我们来设置Family 和 Pitch[Terry:the Family and Pitch settings,我不知道Family是个什么东东,我只能查到说Pitch setting是“节距置位”根据理解应该是指“间距方式的设置”吧]。关于节距(原文:pitch)你可以取用DEFAULT_PITCH 默认节距, FIXED_PITCH 固定节距 和 VARIABLE_PITCH可变节距,而;关于family你可以用FF_DECORATIVE可装饰的, FF_MODERN现代, FF_ROMAN 罗马字,FF_SCRIPT手写,FF_SWISS瑞士字,FF_DONTCARE随便。你可以尝试在例子中改变他们取值,看看他们究竟起到什么作用。我在这里仅是把它们都设成默认值。
[Terry:我还没发现上面那些有什么用处,呵呵。这些是在 WINGDI.h中定义的 Families]
/* Font Families */
#define FF_DONTCARE (0<<4) /* Don't care or don't know. */
#define FF_ROMAN (1<<4) /* Variable stroke width, serifed. */
/* Times Roman, Century Schoolbook, etc. */
#define FF_SWISS (2<<4) /* Variable stroke width, sans-serifed. */
/* Helvetica, Swiss, etc. */
#define FF_MODERN (3<<4) /* Constant stroke width, serifed or sans-serifed. */
/* Pica, Elite, Courier, etc. */
#define FF_SCRIPT (4<<4) /* Cursive, etc. */
#define FF_DECORATIVE (5<<4) /* Old English, etc. */
[/Terry:上面的这些仅供参考,如果想要详细了解还是去看看MSDN吧,或许那个有些帮助的。]
FF_DONTCARE|DEFAULT_PITCH, // Family And Pitch
Finally... We have the actual name of the font. Boot up Microsoft Word or some other text editor. Click on the font drop down menu, and find a font you like. To use the font, replace 'Courier New' with the name of the font you'd rather use.
最后,我们设置字体的名字。运行Microsoft Word或者其他的文本编辑器,单击字体的下拉菜单,然后找一个你喜欢的字体。要使用你想要的字体,只需要把代码中的'Courier New'用你找到的字体的名字替换掉就好了。
"Courier New"); // Font Name
|
|