• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

              C++博客 :: 首頁 :: 聯(lián)系 ::  :: 管理
              163 Posts :: 4 Stories :: 350 Comments :: 0 Trackbacks

            常用鏈接

            留言簿(48)

            我參與的團(tuán)隊(duì)

            搜索

            •  

            積分與排名

            • 積分 - 399102
            • 排名 - 59

            最新評論

            閱讀排行榜

            評論排行榜

            在OpenGL中使用FreeType庫

            這里是一個快速的介紹,它告訴你如何在OpenGL中使用FreeType渲染TrueType字體。使用這個庫我們可以渲染反走樣的文本,它看起來更加的漂亮。

            動機(jī)

            這里我將給你兩個例子,一個是用WGL的bitmap字體渲染得文字,另一個是用FreeType渲染得文字。



             

            使用WGl渲染得文字是一些圖像,當(dāng)你放大它們時看起來如下:


             

            如果你使用GNU的FreeType庫(暴雪公司也在它們的游戲中使用這個庫),它將看起來更漂亮,如下所示,它具有了反走樣:



            創(chuàng)建程序

            第一步你需要從下面的網(wǎng)站上下載FreeType庫:http://gnuwin32.sourceforge.net/packages/freetype.htm

            接著在你使用它創(chuàng)建一個新的程序時,你需要鏈接libfreetype.lib庫,并包含F(xiàn)reeType的頭文件。

             
             
              
              
             現(xiàn)在我們已經(jīng)能創(chuàng)建基于FreeType的程序了,但我們還不能運(yùn)行它,因?yàn)槲覀冃枰猣reetype-6.dll文件。
            好了,現(xiàn)在我們可以開始編寫我們的程序了,我們從13課的代碼開始,我們添加兩個新的文件"freetype.cpp"和"freetype.h"。我們把和FreeType相關(guān)的內(nèi)容放在這兩個文件里。

            好了,讓我們從freetype.h開始吧。

            按慣例我們包含一些需要的頭文件
             
              

            #ifndef FREE_NEHE_H#define FREE_NEHE_H
            //FreeType 頭文件
            #include <ft2build.h>
            #include <freetype/freetype.h>
            #include <freetype/ftglyph.h>
            #include <freetype/ftoutln.h>
            #include <freetype/fttrigon.h>

            //OpenGL 頭文件
            #include <windows.h>
            #include <GL/gl.h>
            #include <GL/glu.h>

            //STL 頭文件
            #include <vector>
            #include <string>

            //STL異常類
            #include <stdexcept>
            #pragma warning(disable: 4786)


              
             我們將把每個字符需要的信息封裝在一個結(jié)構(gòu)中,這樣就像使用WGL字體一樣,我們可以分別控制每個字符的顯示狀態(tài)。 
              

            // 把所有的操作放在名字空間freetype中,這樣可以避免與其他函數(shù)的沖突namespace freetype
            {
            // 使用vector和string名字空間
            using std::vector;
            using std::string;

            // 這個結(jié)構(gòu)保存字體信息
            struct font_data
            {
            float h; // 字體的高度
            GLuint * textures; // 使用的紋理
            GLuint list_base; // 顯示列表的值

            // 初始化結(jié)構(gòu)
            void init(const char * fname, unsigned int h);

            // 清楚所有的資源
            void clean();
            };


              
             最后一件事是定義我們輸出字符串的原形: 
              

            // 把字符輸出到屏幕void print(const font_data &ft_font, float x, float y, const char *fmt, ...);
            }

            #endif


              
             上面就是FreeType的頭文件,下面我們看看怎樣實(shí)現(xiàn)它 
              

            #include "freetype.h"
            namespace freetype {


              
             我們使用紋理去顯示字符,在OpenGL中紋理大小必須為2的次方,這個函數(shù)用來字符的大小近似到這個值。所以我們有了如下的方程: 
              

            // 這個函數(shù)返回比a大的,并且是最接近a的2的次方的數(shù)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;}

              
             下面一個函數(shù)為make_dlist, 它是這個代碼的核心。它包含F(xiàn)T_Face對象,它是FreeType用來保存字體信息的類,接著創(chuàng)建一個顯示列表。 
              

            // 為給定的字符創(chuàng)建一個顯示列表void make_dlist ( FT_Face face, char ch, GLuint list_base, GLuint * tex_base ) {
            // 載入給定字符的輪廓
            if(FT_Load_Glyph( face, FT_Get_Char_Index( face, ch ), FT_LOAD_DEFAULT ))
            throw std::runtime_error("FT_Load_Glyph failed");

            // 保存輪廓對象
            FT_Glyph glyph;
            if(FT_Get_Glyph( face->glyph, &glyph ))
            throw std::runtime_error("FT_Get_Glyph failed");

            // 把輪廓轉(zhuǎn)化為位圖
            FT_Glyph_To_Bitmap( &glyph, ft_render_mode_normal, 0, 1 );
            FT_BitmapGlyph bitmap_glyph = (FT_BitmapGlyph)glyph;

            // 保存位圖
            FT_Bitmap& bitmap=bitmap_glyph->bitmap;

            }

              
             現(xiàn)在我們已經(jīng)從FreeType中獲得了位圖,我們需要把它轉(zhuǎn)化為一個滿足OpenGL紋理要求的位圖。你必須知道,在OpenGL中位圖表示黑白的數(shù)據(jù),而在FreeType中我們使用8位的顏色表示位圖,所以FreeType的位圖可以保存亮度信息。 
              

            // 轉(zhuǎn)化為OpenGl可以使用的大小    int width = next_p2( bitmap.width );    int height = next_p2( bitmap.rows );
            // 保存位圖數(shù)據(jù)
            GLubyte* expanded_data = new GLubyte[ 2 * width * height];

            // 這里我們使用8位表示亮度8位表示alpha值
            for(int j=0; j <height;j++) {
            for(int i=0; i < width; i++){
            expanded_data[2*(i+j*width)]= expanded_data[2*(i+j*width)+1] =
            (i>=bitmap.width || j>=bitmap.rows) ?
            0 : bitmap.buffer[i + bitmap.width*j];
            }
            }

              
             接下來我們選則字體紋理,并生成字體的貼圖紋理 
              

            // 設(shè)置字體紋理的紋理過濾器    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);
            // 邦定紋理
            glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0,
            GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, expanded_data );

            // 釋放分配的內(nèi)存
            delete [] expanded_data;


              
             接著創(chuàng)建一個顯示列表,它用來繪制一個字符 
              

            // 創(chuàng)建顯示列表    glNewList(list_base+ch,GL_COMPILE);
            glBindTexture(GL_TEXTURE_2D,tex_base[ch]);

            //首先我們向左移動一點(diǎn)
            glTranslatef(bitmap_glyph->left,0,0);

            //接著我們向下移動一點(diǎn),這只隊(duì)'g','y'之類的字符有用
            //它使得所有的字符都有一個基線
            glPushMatrix();
            glTranslatef(0,bitmap_glyph->top-bitmap.rows,0);

            // 計(jì)算位圖中字符圖像的寬度
            float x=(float)bitmap.width / (float)width,
            y=(float)bitmap.rows / (float)height;

            //繪制一個正方形,顯示字符
            glBegin(GL_QUADS);
            glTexCoord2d(0,0); glVertex2f(0,bitmap.rows);
            glTexCoord2d(0,y); glVertex2f(0,0);
            glTexCoord2d(x,y); glVertex2f(bitmap.width,0);
            glTexCoord2d(x,0); glVertex2f(bitmap.width,bitmap.rows);
            glEnd();
            glPopMatrix();
            glTranslatef(face->glyph->advance.x >> 6 ,0,0);

            //結(jié)束顯示列表的繪制
            glEndList();
            }


              
             下面的函數(shù)將使用make_dlist創(chuàng)建一個字符集的顯示列表,fname為你要使用的FreeType字符文件。 
              

            void font_data::init(const char * fname, unsigned int h) {        // 保存紋理ID.    textures = new GLuint[128];
            this->h=h;

            // 創(chuàng)建FreeType庫
            FT_Library library;
            if (FT_Init_FreeType( &library ))
            throw std::runtime_error("FT_Init_FreeType failed");

            // 在FreeType庫中保存字體信息的類叫做face
            FT_Face face;

            // 使用你輸入的Freetype字符文件初始化face類
            if (FT_New_Face( library, fname, 0, &face ))
            throw std::runtime_error("FT_New_Face failed (there is probably a problem with your font file)");

            // 在FreeType中使用1/64作為一個像素的高度所以我們需要縮放h來滿足這個要求
            FT_Set_Char_Size( face, h << 6, h << 6, 96, 96);

            // 創(chuàng)建128個顯示列表
            list_base=glGenLists(128);
            glGenTextures( 128, textures );
            make_dlist(face,i,list_base,textures);

            // 釋放face類
            FT_Done_Face(face);

            // 釋放FreeType庫
            FT_Done_FreeType(library);
            }


              
             下面的函數(shù)完成釋放資源的工作 
              

            void font_data::clean() {    glDeleteLists(list_base,128);    glDeleteTextures(128,textures);    delete [] textures;}
              
             在print函數(shù)中要用到下面的兩個方程,pushScreenCoordinateMatrix函數(shù)用來保存當(dāng)前的矩陣,并設(shè)置視口與當(dāng)前的窗口大小匹配。pop_projection_matrix函數(shù)用來返回pushScreenCoordinateMatrix保存的矩陣。reference manual.  
              

            // 保存當(dāng)前的矩陣,并設(shè)置視口與當(dāng)前的窗口大小匹配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();}
            //返回pushScreenCoordinateMatrix保存的矩陣
            inline void pop_projection_matrix() {
            glPushAttrib(GL_TRANSFORM_BIT);
            glMatrixMode(GL_PROJECTION);
            glPopMatrix();
            glPopAttrib();


              
             我們的print函數(shù)和13課的函數(shù)非常的像,但在實(shí)現(xiàn)上有一些不同。我們實(shí)際上是使用2通道的紋理而不是圖像。 
              

            // 輸出文字void print(const font_data &ft_font, float x, float y, const char *fmt, ...)  {                // 保存當(dāng)前矩陣    pushScreenCoordinateMatrix();                                               GLuint font=ft_font.list_base;    float h=ft_font.h/.63f;                                                     char    text[256];                                        va_list    ap;                                       
            if (fmt == NULL)
            *text=0;
            else {
            va_start(ap, fmt);
            vsprintf(text, fmt, ap);
            va_end(ap);
            }

            // 把輸入的字符串按回車分割
            const char *start_line=text;
            vector<string> lines;
            for(const char *c=text;*c;c++) {
            if(*c=='\n') {
            string line;
            for(const char *n=start_line;n<c;n++) line.append(1,*n);
            lines.push_back(line);
            start_line=c+1;
            }
            }
            if(start_line) {
            string line;
            for(const char *n=start_line;n<c;n++) line.append(1,*n);
            lines.push_back(line);
            }

            glPushAttrib(GL_LIST_BIT | GL_CURRENT_BIT | GL_ENABLE_BIT | GL_TRANSFORM_BIT);
            glMatrixMode(GL_MODELVIEW);
            glDisable(GL_LIGHTING);
            glEnable(GL_TEXTURE_2D);
            glDisable(GL_DEPTH_TEST);
            glEnable(GL_BLEND);
            glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

            glListBase(font);

                float modelview_matrix[16];         glGetFloatv(GL_MODELVIEW_MATRIX, modelview_matrix);
            // 下面的代碼完成具體的繪制過程
            for(int i=0;i<lines.size();i++) {
            glPushMatrix();
            glLoadIdentity();
            glTranslatef(x,y-h*i,0);
            glMultMatrixf(modelview_matrix);

            //調(diào)用顯示列表繪制
            glCallLists(lines[i].length(), GL_UNSIGNED_BYTE, lines[i].c_str());

            glPopMatrix();
            }

            glPopAttrib();

            pop_projection_matrix();
            }

            }


            }

              
             FreeType庫我們就寫好了,現(xiàn)我們在13課的代碼上來做一些修改,當(dāng)然首先我們需要包含freetype.h的頭文件 
              

            #include "freetype.h"
              
             現(xiàn)在我們就可以調(diào)用freetype庫繪制字符串了 
              

            // 保存我們創(chuàng)建的字體的信息freetype::font_data our_font;
              
             接下來使用test.ttf文件初始化字體 
              

            our_font.init("Test.ttf", 16);
              
             在程序結(jié)束時記得釋放內(nèi)存資源 
              

            our_font.clean();
              
             下面是我們具體的繪制函數(shù) 
              

            int DrawGLScene(GLvoid)                                        {    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);                        glLoadIdentity();                                        glTranslatef(0.0f,0.0f,-1.0f);                           
            // 藍(lán)色文字
            glColor3ub(0,0,0xff);

            // 繪制WGL文字
            glRasterPos2f(-0.40f, 0.35f);
            glPrint("Active WGL Bitmap Text With NeHe - %7.2f", cnt1);

            // 紅色文字
            glColor3ub(0xff,0,0);

            glPushMatrix();
            glLoadIdentity();
            glRotatef(cnt1,0,0,1);
            glScalef(1,.8+.3*cos(cnt1/5),1);
            glTranslatef(-180,0,0);
            //繪制freetype文字
            freetype::print(our_font, 320, 200, "Active FreeType Text - %7.2f", cnt1);
            glPopMatrix();

            cnt1+=0.051f;
            cnt2+=0.005f;
            return TRUE; // 成功返回
            }

              
             最后我們介紹一些實(shí)用的創(chuàng)建字體的相關(guān)站點(diǎn)

            OGLFT 非常漂亮的基于FreeType2的字體庫,下面是它的站點(diǎn)http://oglft.sourceforge.net/.

            FTGL 是為OS X設(shè)計(jì)的第三方字體庫. http://homepages.paradise.net.nz/henryj/code/#FTGL

            FNT 一個非FreeType庫,它使用自己定義的字體格式,但它具有非常好的界面http://plib.sourceforge.net/fnt.

             
             
            posted on 2008-01-04 21:31 sdfasdf 閱讀(5639) 評論(0)  編輯 收藏 引用 所屬分類: OPENGL
            国产精品免费久久久久影院 | 国产精品欧美久久久久天天影视 | a高清免费毛片久久| 少妇内射兰兰久久| 色欲久久久天天天综合网| 午夜精品久久久久9999高清| 久久久久亚洲AV综合波多野结衣| 99久久国产综合精品五月天喷水| 久久夜色精品国产亚洲| 久久精品草草草| 国内精品久久久久久不卡影院| 狠狠综合久久综合中文88| 久久久久亚洲?V成人无码| 日产久久强奸免费的看| 伊色综合久久之综合久久| 亚洲精品午夜国产VA久久成人| 亚洲第一极品精品无码久久| 国产精品久久久久久福利69堂| 日韩一区二区久久久久久| 婷婷久久综合九色综合绿巨人| 麻豆国内精品久久久久久| 久久婷婷五月综合97色直播 | 久久久午夜精品| 久久99国产精品久久久| 久久久久免费视频| 久久久久亚洲AV无码网站| 国产精久久一区二区三区| 亚洲精品乱码久久久久久| 日韩精品国产自在久久现线拍| 亚洲精品无码久久久| 久久久久久免费一区二区三区| 热久久视久久精品18| 国产精品久久久久久一区二区三区 | 久久人人爽爽爽人久久久| 99精品久久久久久久婷婷| 久久精品国产免费观看三人同眠| 99国产精品久久久久久久成人热| 久久国产成人午夜aⅴ影院| 久久亚洲精品成人AV| 要久久爱在线免费观看| 久久精品中文字幕久久|