以文本方式查看主题 - 计算机科学论坛 (http://bbs.xml.org.cn/index.asp) -- 『 C/C++编程思想 』 (http://bbs.xml.org.cn/list.asp?boardid=61) ---- [推荐]NeHe OpenGL教程(中英文版附带VC++源码)Lesson 43-lesson 44 (http://bbs.xml.org.cn/dispbbs.asp?boardid=61&rootid=&id=54710) |
-- 作者:一分之千 -- 发布时间:10/31/2007 9:01:00 PM -- [推荐]NeHe OpenGL教程(中英文版附带VC++源码)Lesson 43-lesson 44 第四十三四十四课 ![]() ![]() 第四十三课
使用FreeType库可以创建非常好看的反走样的字体,记住暴雪公司就是使用这个库的,就是那个做魔兽世界的。尝试一下吧,我只告诉你了基本的使用方式,你可以走的更远。 这里是一个快速的介绍,它告诉你如何在OpenGL中使用FreeType渲染TrueType字体。使用这个库我们可以渲染反走样的文本,它看起来更加的漂亮。 动机 这里我将给你两个例子,一个是用WGL的bitmap字体渲染得文字,另一个是用FreeType渲染得文字。
使用WGl渲染得文字是一些图像,当你放大它们时看起来如下: 如果你使用GNU的FreeType库(暴雪公司也在它们的游戏中使用这个库),它将看起来更漂亮,如下所示,它具有了反走样:
创建程序 第一步你需要从下面的网站上下载FreeType库:http://gnuwin32.sourceforge.net/packages/freetype.htm 接着在你使用它创建一个新的程序时,你需要链接libfreetype.lib库,并包含FreeType的头文件。 好了,让我们从freetype.h开始吧。 按惯例我们包含一些需要的头文件 #ifndef FREE_NEHE_H#define FREE_NEHE_H //OpenGL 头文件 //STL 头文件 //STL异常类 // 把所有的操作放在名字空间freetype中,这样可以避免与其他函数的冲突namespace freetype // 这个结构保存字体信息 // 初始化结构 // 清楚所有的资源 // 把字符输出到屏幕void print(const font_data &ft_font, float x, float y, const char *fmt, ...); #endif #include "freetype.h" // 这个函数返回比a大的,并且是最接近a的2的次方的数inline int next_p2 (int a ){ int rval=1; // rval<<=1 Is A Prettier Way Of Writing rval*=2; while(rval<a) rval<<=1; return rval;} // 为给定的字符创建一个显示列表void make_dlist ( FT_Face face, char ch, GLuint list_base, GLuint * tex_base ) { // 保存轮廓对象 // 把轮廓转化为位图 // 保存位图 } // 转化为OpenGl可以使用的大小 int width = next_p2( bitmap.width ); int height = next_p2( bitmap.rows ); // 这里我们使用8位表示亮度8位表示alpha值 // 设置字体纹理的纹理过滤器 glBindTexture( GL_TEXTURE_2D, tex_base[ch]); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); // 释放分配的内存 // 创建显示列表 glNewList(list_base+ch,GL_COMPILE); //首先我们向左移动一点 //接着我们向下移动一点,这只队'g','y'之类的字符有用 // 计算位图中字符图像的宽度 //绘制一个正方形,显示字符 //结束显示列表的绘制 void font_data::init(const char * fname, unsigned int h) { // 保存纹理ID. textures = new GLuint[128]; // 创建FreeType库 // 在FreeType库中保存字体信息的类叫做face // 使用你输入的Freetype字符文件初始化face类 // 在FreeType中使用1/64作为一个像素的高度所以我们需要缩放h来满足这个要求 // 创建128个显示列表 // 释放face类 // 释放FreeType库 void font_data::clean() { glDeleteLists(list_base,128); glDeleteTextures(128,textures); delete [] textures;} // 保存当前的矩阵,并设置视口与当前的窗口大小匹配inline void pushScreenCoordinateMatrix() { glPushAttrib(GL_TRANSFORM_BIT); GLint viewport[4]; glGetIntegerv(GL_VIEWPORT, viewport); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); gluOrtho2D(viewport[0],viewport[2],viewport[1],viewport[3]); glPopAttrib();} // 输出文字void print(const font_data &ft_font, float x, float y, const char *fmt, ...) { // 保存当前矩阵 pushScreenCoordinateMatrix(); GLuint font=ft_font.list_base; float h=ft_font.h/.63f; char text[256]; va_list ap; // 把输入的字符串按回车分割 glPushAttrib(GL_LIST_BIT | GL_CURRENT_BIT | GL_ENABLE_BIT | GL_TRANSFORM_BIT); glListBase(font); float modelview_matrix[16]; glGetFloatv(GL_MODELVIEW_MATRIX, modelview_matrix); //调用显示列表绘制 glPopMatrix(); glPopAttrib(); pop_projection_matrix(); } #include "freetype.h" // 保存我们创建的字体的信息freetype::font_data our_font; our_font.init("Test.ttf", 16); our_font.clean(); int DrawGLScene(GLvoid) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); glTranslatef(0.0f,0.0f,-1.0f); // 绘制WGL文字 // 红色文字 glPushMatrix(); cnt1+=0.051f; OGLFT 非常漂亮的基于FreeType2的字体库,下面是它的站点http://oglft.sourceforge.net. FTGL 是为OS X设计的第三方字体库. http://homepages.paradise.net.nz/henryj/code/#FTGL. FNT 一个非FreeType库,它使用自己定义的字体格式,但它具有非常好的界面http://plib.sourceforge.net/fnt.
|
-- 作者:一分之千 -- 发布时间:10/31/2007 9:15:00 PM -- Lesson: 43 Tutorial on using FreeType Fonts in OpenGL So here's a quick tutorial to show you how to use the FreeType font rendering library in OpenGL. By using the FreeType library we can create anti-aliased text that looks better than text made using bitmap fonts (as in Lesson 13). Our text will also have some other advantages over bitmap fonts - it will be easy to rotate and works well with OpenGL's picking functions. Here I've printed out the same text using both WGL bitmap fonts and fonts rendered with FreeType as per this tutorial (both are Arial Black Italic).
The basic problem with using bitmaps fonts is that in OpenGL bitmaps are by definition binary images. This means that an OpenGL bitmap stores only one bit of information per-pixel. If you zoom in on the text created using WGL bitmaps, the result looks like this: Because bitmaps are binary images, there are no gray pixels in the image above, and it means that the text looks. Luckily it is fairly easy to make better looking fonts using the GNU FreeType library. FreeType is the same library that Blizzard uses to render the fonts in their games, so you know it has to be good! Here's a close up of the text that I've created with the help of the FreeType library:
You can see that there are a fair number of gray pixels around the edges of the text; this is typical of an anti-aliased font, the gray pixels make the font look smoother from a distance. Creating the Program The first step is to get yourself a copy of the GNU FreeType library. Go to http://gnuwin32.sourceforge.net/packages/freetype.htm and download the binaries and developer files. When you install it make sure to notice the licensing terms, which basically say that if you are going to use FreeType in your own programs, you need to give them credit somewhere in your documentation. Now we need to setup MSVC to use FreeType. So create new project as in Lesson 1, but when you go to Project->Settings->Link make sure you add libfreetype.lib to Object Modules / libraries along with opengl32.lib, glu32.lib and glaux.lib (if required). Next we need to go to Tools->Options->Directories and add the FreeType library directories. Under "Show Directories For" select "Include Files", then double click on the empty line at the bottom of the directory list, after you double click a "..." button will appear that you can use to browse for a directory. In this way add C:\PROGRAM FILES\GNUWIN32\INCLUDE\FREETYPE2 C:\PROGRAM FILES\GNUWIN32\INCLUDE C:\PROGRAM FILES\GNUWIN32\LIB Now add and create two new files called "freetype.cpp" and "freetype.h". We will put all our FreeType specific code into these files, and then modify lesson13 a little to show off the functions that we've written. When we are done, we will have created a very simple OpenGL FreeType library that could theoretically be used in any OpenGL project. We will start with freetype.h. Naturally, we need include the FreeType and OpenGL headers. We will also include some handy parts of the Standard Template Library, including STL's exception classes, which will make it easier for us create nice debugging messages. #ifndef FREE_NEHE_H#define FREE_NEHE_H // OpenGL Headers // Some STL Headers // Using The STL Exception Library Increases The // MSVC Will Spit Out All Sorts Of Useless Warnings If // Wrap Everything In A Namespace, That Way We Can Use A Common// Function Name Like "print" Without Worrying About// Overlapping With Anyone Else's Code.namespace freetype { // Ditto For String. // This Holds All Of The Information Related To Any // The Init Function Will Create A Font With // Free All The Resources Associated With The Font. // The Flagship Function Of The Library - This Thing Will Print// Out Text At Window Coordinates X, Y, Using The Font ft_font.// The Current Modelview Matrix Will Also Be Applied To The Text. void print(const font_data &ft_font, float x, float y, const char *fmt, ...); #endif // Include Our Header File.#include "freetype.h" // This Function Gets The First Power Of 2 >= The// Int That We Pass It.inline int next_p2 (int a ){ int rval=1; // rval<<=1 Is A Prettier Way Of Writing rval*=2; while(rval<a) rval<<=1; return rval;} // Create A Display List Corresponding To The Given Character.void make_dlist ( FT_Face face, char ch, GLuint list_base, GLuint * tex_base ) { // Load The Glyph For Our Character. // Move The Face's Glyph Into A Glyph Object. // Convert The Glyph To A Bitmap. // This Reference Will Make Accessing The Bitmap Easier. // Use Our Helper Function To Get The Widths Of // The Bitmap Data That We Will Need In Order To Create // Our Texture. int width = next_p2( bitmap.width ); int height = next_p2( bitmap.rows ); // Here We Fill In The Data For The Expanded Bitmap. // Now We Just Setup Some Texture Parameters. glBindTexture( GL_TEXTURE_2D, tex_base[ch]); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); // With The Texture Created, We Don't Need The Expanded Data Anymore. // Now We Create The Display List glNewList(list_base+ch,GL_COMPILE); // First We Need To Move Over A Little So That // Now We Move Down A Little In The Case That The // Now We Need To Account For The Fact That Many Of // Here We Draw The Texturemapped Quads. // Increment The Raster Position As If We Were A Bitmap Font. // Finish The Display List void font_data::init(const char * fname, unsigned int h) { // Allocate Some Memory To Store The Texture Ids. textures = new GLuint[128]; // Create And Initilize A FreeType Font Library. // The Object In Which FreeType Holds Information On A Given // This Is Where We Load In The Font Information From The File. // For Some Twisted Reason, FreeType Measures Font Size // Here We Ask OpenGL To Allocate Resources For // This Is Where We Actually Create Each Of The Fonts Display Lists. // We Don't Need The Face Information Now That The Display // Ditto For The Font Library. void font_data::clean() { glDeleteLists(list_base,128); glDeleteTextures(128,textures); delete [] textures; // A Fairly Straightforward Function That Pushes// A Projection Matrix That Will Make Object World // Coordinates Identical To Window Coordinates.inline void pushScreenCoordinateMatrix() { glPushAttrib(GL_TRANSFORM_BIT); GLint viewport[4]; glGetIntegerv(GL_VIEWPORT, viewport); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); gluOrtho2D(viewport[0],viewport[2],viewport[1],viewport[3]); glPopAttrib();} // Much Like NeHe's glPrint Function, But Modified To Work// With FreeType Fonts.void print(const font_data &ft_font, float x, float y, const char *fmt, ...) { // We Want A Coordinate System Where Distance Is Measured In Window Pixels. pushScreenCoordinateMatrix(); GLuint font=ft_font.list_base; // We Make The Height A Little Bigger. There Will Be Some Space Between Lines. float h=ft_font.h/.63f; char text[256]; // Holds Our String va_list ap; // Pointer To List Of Arguments // Here Is Some Code To Split The Text That We Have Been glPushAttrib(GL_LIST_BIT | GL_CURRENT_BIT | GL_ENABLE_BIT | GL_TRANSFORM_BIT); glListBase(font); float modelview_matrix[16]; glGetFloatv(GL_MODELVIEW_MATRIX, modelview_matrix); // The Commented Out Raster Position Stuff Can Be Useful If You Need To glPopMatrix(); glPopAttrib(); pop_projection_matrix(); } // Close The Namespace #include "freetype.h" // This Holds All The Information For The Font That We Are Going To Create.freetype::font_data our_font; our_font.init("Test.ttf", 16); our_font.clean(); int DrawGLScene(GLvoid) // Here's Where We Do All The Drawing{ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear Screen And Depth Buffer glLoadIdentity(); // Reset The Current Modelview Matrix glTranslatef(0.0f,0.0f,-1.0f); // Move One Unit Into The Screen // Position the WGL Text On The Screen // Here We Print Some Text Using Our Freetype Font // Red Text glPushMatrix(); // Uncomment This To Test Out Print's Ability To Handle Newlines. cnt1+=0.051f; // Increase The First Counter MSG msg; // Windows Message Structure BOOL done=FALSE; // Bool Variable To Exit Loop // Shutdown KillGLWindow(); // Kill The Window return (msg.wParam); There are a number of improvements that you might want to make to this library. For one thing using the font data objects directly tends to be a little awkward, so you might want to create a standard cache of fonts to hide font resource management from users. You might also want to take a tip from the OpenGL library itself and create a font stack, which would let you avoid passing in references to font objects each time you called the print function. (These are all things that I currently do things in my own code, but decided to leave out of the tutorial for the sake of simplicity.) You might also want to make a version of print that centers the text- to do that you will probably need to use the techniques discussed below. Right now I have the text spinning around it's center. However, to get an effect like this to work for arbitrary text, you would need to have some way of knowing exactly how long the line of text was - this can be a little tricky. One way to get the length of the text is to put glBitmap commands into the font's display lists in order modify the raster position as well as the modelview matrix (I've left the necessary line in the code, but it is commented out). Then you can set the raster position to x,y before using glCallLists, and use glGet to find the raster position after the text is drawn - the difference in raster positions will give you the length of the text in pixels. You should be aware that FreeType fonts take up much more memory than WGL's bitmap fonts (that's one the advantages of binary images, they use very little space). If for some reason you really need to conserve your texture memory, you might want to stick with the code from lesson 13. Another interesting advantage of using texture mapped quads to represent fonts is that quads, unlike bitmaps, work well with the OpenGL picking functions (see Lesson 32 ). This makes life much easier if you want to create text that responds when someone holds the mouse over it or clicks on it. (Making WGL fonts work well with picking functions is possible, again the key trick is to use raster coordinates to figure out the length of the text in pixels). And finally, here are some links to OpenGL font libraries. Depending on your goals and compiler you may want to use one of them instead of this code (there are many more of them out there, I've generally only included things that I have some amount of experience with myself). GLTT This library is an old library that doesn't seem to still be maintained, but it has gotten some very positive reviews. Based on FreeType1. I think you will need to find a copy of the old FreeType1 source distribution to compile it in MSVC6. Download available from http://www.opengl.org/developers/faqs/technical/fonts.htm. OGLFT A nice FreeType2 based font library, it takes a bit of work to compile under MSVC though (mostly just typical for-loop scope problems). Seems to be targeted at linux machines... http://oglft.sourceforge.net. FTGL Yet a third FreeType based font library, this one was clearly developed for OS X. http://homepages.paradise.net.nz/henryj/code/#FTGL. FNT A non-FreeType library that is part of PLIB. Seems to have a nice interface, uses its own font format, compiles under MSVC6 with a minimum amount of fuss... http://plib.sourceforge.net/fnt. Sven Olsen |
-- 作者:一分之千 -- 发布时间:10/31/2007 9:29:00 PM -- 3D 光晕 当镜头对准太阳的时候就会出现这种效果,模拟它非常的简单,一点数学和纹理贴图就够了。好好看看吧。 void glCamera::SetPrespective(){ GLfloat Matrix[16]; glVector v; // 返回模型变换矩阵 // 获得视线的方向 // 重置矩阵 // 旋转场景 // 设置当前摄像机的位置 // 变换到新的位置 Big Glow Glow Halo
现在你在头脑里应该有了一个大慨地图像了吧。我们来说说何时我们应该绘制光晕,一般来说平时我们是看不见这些光晕的,只有当我们对准光源的时候才能看见这些。所以我们首先要获得视景体的数据,下面的函数可以帮我们完成这个功能。 // 获得当前视景体的6个平面方程的参数void glCamera::UpdateFrustum(){ GLfloat clip[16]; GLfloat proj[16]; GLfloat modl[16]; GLfloat t; //返回模型变换矩阵 //计算剪切矩阵,即上面两个矩阵的乘积 clip[ 4] = modl[ 4] * proj[ 0] + modl[ 5] * proj[ 4] + modl[ 6] * proj[ 8] + modl[ 7] * proj[12]; clip[ 8] = modl[ 8] * proj[ 0] + modl[ 9] * proj[ 4] + modl[10] * proj[ 8] + modl[11] * proj[12]; clip[12] = modl[12] * proj[ 0] + modl[13] * proj[ 4] + modl[14] * proj[ 8] + modl[15] * proj[12]; //提取右面的平面方程系数 //提取左面的平面方程系数 //提取下面的平面方程系数 //提取上面的平面方程系数 //提取远面的平面方程系数 //提取近面的平面方程系数 BOOL glCamera::PointInFrustum(glPoint p){ int i; for(i = 0; i < 6; i++) { if(m_Frustum[i][0] * p.x + m_Frustum[i][1] * p.y + m_Frustum[i][2] * p.z + m_Frustum[i][3] <= 0) { return(FALSE); } } return(TRUE);} bool glCamera::IsOccluded(glPoint p){ GLint viewport[4]; GLdouble mvmatrix[16], projmatrix[16]; GLdouble winx, winy, winz; GLdouble flareZ; GLfloat bufferZ; // 返回顶点p在单位立方体中的位置 // 读取点(winx,winy)的深度坐标 // 如果深度坐标小于点的坐标,则返回true //下面的函数完成具体的渲染光晕的任务void glCamera::RenderLensFlare(){ GLfloat Length = 0.0f; //下面三个函数计算光源位置到光晕结束位置之间的向量 glEnable(GL_BLEND);
if (!IsOccluded(m_LightSourcePos)) //如果光晕可见 { // 渲染中间的光晕 RenderBigGlow(0.60f, 0.60f, 0.8f, 1.0f, m_LightSourcePos, 16.0f); RenderStreaks(0.60f, 0.60f, 0.8f, 1.0f, m_LightSourcePos, 16.0f); RenderGlow(0.8f, 0.8f, 1.0f, 0.5f, m_LightSourcePos, 3.5f); //绘制到光晕结束位置的0.15处的光晕 //绘制到光晕结束位置的0.175处的光晕 //绘制到光晕结束位置的0.285处的光晕 //绘制到光晕结束位置的0.2755处的光晕 //绘制到光晕结束位置的0.4755处的光晕 //绘制到光晕结束位置的0.49处的光晕 //绘制到光晕结束位置的0.65处的光晕 //绘制到光晕结束位置的0.63处的光晕 //绘制到光晕结束位置的0.8处的光晕 //绘制到光晕结束位置的0.7825处的光晕 //绘制到光晕结束位置的1.0处的光晕 //绘制到光晕结束位置的0.975处的光晕 } //绘制Halo形的光晕void glCamera::RenderHalo(GLfloat r, GLfloat g, GLfloat b, GLfloat a, glPoint p, GLfloat scale){ glPoint q[4]; q[0].x = (p.x - scale); q[0].y = (p.y - scale); q[1].x = (p.x - scale); q[1].y = (p.y + scale); q[2].x = (p.x + scale); q[2].y = (p.y - scale); q[3].x = (p.x + scale); q[3].y = (p.y + scale); glPushMatrix(); glTranslatef(p.x, p.y, p.z); glRotatef(-m_HeadingDegrees, 0.0f, 1.0f, 0.0f); glRotatef(-m_PitchDegrees, 1.0f, 0.0f, 0.0f); glBindTexture(GL_TEXTURE_2D, m_HaloTexture); glColor4f(r, g, b, a); glBegin(GL_TRIANGLE_STRIP); glTexCoord2f(0.0f, 0.0f); glVertex2f(q[0].x, q[0].y); glTexCoord2f(0.0f, 1.0f); glVertex2f(q[1].x, q[1].y); glTexCoord2f(1.0f, 0.0f); glVertex2f(q[2].x, q[2].y); glTexCoord2f(1.0f, 1.0f); glVertex2f(q[3].x, q[3].y); glEnd(); glPopMatrix(); } q[0].x = (p.x - scale); q[1].x = (p.x - scale); q[2].x = (p.x + scale); q[3].x = (p.x + scale); glPushMatrix(); glBegin(GL_TRIANGLE_STRIP); //绘制BigGlow形的光晕 q[0].x = (p.x - scale); q[1].x = (p.x - scale); q[2].x = (p.x + scale); q[3].x = (p.x + scale); glPushMatrix(); glBegin(GL_TRIANGLE_STRIP); //绘制Streaks形的光晕 q[0].x = (p.x - scale); q[1].x = (p.x - scale); q[2].x = (p.x + scale); q[3].x = (p.x + scale); glPushMatrix(); glBegin(GL_TRIANGLE_STRIP);
上面就是这个教程的全部了,所有的问题,评论和抱怨都欢迎。当然我不是第一个作这个效果的人,下面是其他方面相关的文章: |
-- 作者:长风万里 -- 发布时间:11/1/2007 12:42:00 AM -- 非常感谢~~~ |
-- 作者:lanway -- 发布时间:12/9/2007 4:11:00 PM -- 3Q 辛苦了 |
W 3 C h i n a ( since 2003 ) 旗 下 站 点 苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》 |
328.125ms |