青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

  C++博客 :: 首頁 :: 聯系 ::  :: 管理
  163 Posts :: 4 Stories :: 350 Comments :: 0 Trackbacks

常用鏈接

留言簿(48)

我參與的團隊

搜索

  •  

積分與排名

  • 積分 - 401640
  • 排名 - 59

最新評論

閱讀排行榜

評論排行榜

在OpenGL中使用FreeType庫

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

動機

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



 

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


 

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



創建程序

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

接著在你使用它創建一個新的程序時,你需要鏈接libfreetype.lib庫,并包含FreeType的頭文件。

 
 
  
  
 現在我們已經能創建基于FreeType的程序了,但我們還不能運行它,因為我們需要freetype-6.dll文件。
好了,現在我們可以開始編寫我們的程序了,我們從13課的代碼開始,我們添加兩個新的文件"freetype.cpp"和"freetype.h"。我們把和FreeType相關的內容放在這兩個文件里。

好了,讓我們從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)


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

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

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

// 初始化結構
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的頭文件,下面我們看看怎樣實現它 
  

#include "freetype.h"
namespace freetype {


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

// 這個函數返回比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;}

  
 下面一個函數為make_dlist, 它是這個代碼的核心。它包含FT_Face對象,它是FreeType用來保存字體信息的類,接著創建一個顯示列表。 
  

// 為給定的字符創建一個顯示列表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");

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

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

}

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

// 轉化為OpenGl可以使用的大小    int width = next_p2( bitmap.width );    int height = next_p2( bitmap.rows );
// 保存位圖數據
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];
}
}

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

// 設置字體紋理的紋理過濾器    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 );

// 釋放分配的內存
delete [] expanded_data;


  
 接著創建一個顯示列表,它用來繪制一個字符 
  

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

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

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

// 計算位圖中字符圖像的寬度
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);

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


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

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

// 創建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);

// 創建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);
}


  
 下面的函數完成釋放資源的工作 
  

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

// 保存當前的矩陣,并設置視口與當前的窗口大小匹配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函數和13課的函數非常的像,但在實現上有一些不同。我們實際上是使用2通道的紋理而不是圖像。 
  

// 輸出文字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;                                       
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);

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

glPopMatrix();
}

glPopAttrib();

pop_projection_matrix();
}

}


}

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

#include "freetype.h"
  
 現在我們就可以調用freetype庫繪制字符串了 
  

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

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);                           
// 藍色文字
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; // 成功返回
}

  
 最后我們介紹一些實用的創建字體的相關站點

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

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

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

 
 
posted on 2008-01-04 21:31 sdfasdf 閱讀(5667) 評論(0)  編輯 收藏 引用 所屬分類: OPENGL
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            久久婷婷综合激情| 亚洲在线观看视频网站| 久久疯狂做爰流白浆xx| 亚洲欧美精品中文字幕在线| 国产精品视频xxx| 久久欧美肥婆一二区| 久久综合久色欧美综合狠狠| 1024成人网色www| 亚洲欧洲一区二区三区在线观看| 欧美精品少妇一区二区三区| 亚洲神马久久| 欧美亚洲日本网站| 亚洲精品久久久久久下一站| 亚洲美女尤物影院| 国产一本一道久久香蕉| 亚洲高清免费在线| 国产精品久久国产精品99gif| 久久午夜精品一区二区| 欧美顶级少妇做爰| 欧美在线视频导航| 欧美成人日本| 久久爱另类一区二区小说| 美国三级日本三级久久99| 亚洲免费人成在线视频观看| 久久国产日韩欧美| 亚洲午夜日本在线观看| 久久九九国产| 亚洲欧美日韩国产一区二区三区| 老司机凹凸av亚洲导航| 亚洲欧美日产图| 女女同性精品视频| 久久狠狠一本精品综合网| 欧美精品www在线观看| 久久久久www| 国产精品第2页| 亚洲国产精品国自产拍av秋霞| 国产精品永久入口久久久| 亚洲电影在线观看| 黑人巨大精品欧美黑白配亚洲| 日韩一级成人av| 亚洲黄色大片| 久久久五月婷婷| 欧美一级艳片视频免费观看| 欧美精品在线极品| 欧美国产成人精品| 黑丝一区二区| 欧美在线视频一区二区三区| 亚洲免费在线电影| 欧美另类高清视频在线| 亚洲电影免费在线| 亚洲高清免费视频| 久久久青草婷婷精品综合日韩| 欧美影视一区| 国产精品一区在线播放| 在线综合亚洲欧美在线视频| 99综合在线| 欧美激情中文字幕乱码免费| 欧美国产第一页| 亚洲国产日韩欧美一区二区三区| 久久久999精品免费| 久久久精品tv| 黄色日韩精品| 久久久噜噜噜久久久| 美国三级日本三级久久99| 今天的高清视频免费播放成人| 性18欧美另类| 麻豆91精品91久久久的内涵| 亚洲欧洲精品一区二区| 亚洲激情电影中文字幕| 欧美成人精品在线视频| 欧美激情按摩| 99日韩精品| 欧美午夜一区二区三区免费大片 | 国产日韩精品一区观看| 宅男66日本亚洲欧美视频| 午夜精品福利电影| 国产精品久久久久av免费| 亚洲一区二区欧美| 久久精品国产77777蜜臀| 黄色亚洲网站| 欧美r片在线| 亚洲毛片在线| 久久xxxx精品视频| 亚洲国产精品悠悠久久琪琪| 欧美韩日亚洲| 亚洲综合首页| 免费不卡在线观看av| 亚洲免费播放| 国产欧美一区二区三区国产幕精品 | 亚洲人成网站精品片在线观看| 欧美v亚洲v综合ⅴ国产v| 日韩一区二区久久| 久久久人成影片一区二区三区| 亚洲国产精品一区二区第四页av| 欧美激情中文不卡| 欧美在线播放一区| 亚洲国产精品久久精品怡红院| 亚洲视频高清| 在线观看日韩| 国产精品久久久久999| 久久视频在线看| 亚洲婷婷综合久久一本伊一区| 久久九九免费视频| 在线午夜精品| 狠狠狠色丁香婷婷综合激情| 欧美日韩在线观看视频| 久久久久国产精品麻豆ai换脸| 亚洲人体影院| 老司机精品视频网站| 亚洲女人天堂av| 91久久在线视频| 国产一区二区三区高清播放| 欧美区国产区| 蜜臀va亚洲va欧美va天堂| 亚洲在线视频观看| 亚洲精品小视频| 女人香蕉久久**毛片精品| 欧美一区二区三区四区在线观看地址 | 欧美国产一区二区| 欧美在线看片| 亚洲欧美日韩视频二区| 亚洲精品欧美激情| 尤物精品在线| 国产一区二区三区无遮挡| 国产精品影音先锋| 国产精品看片资源| 欧美三区在线视频| 欧美日韩精品免费观看视频完整| 狼狼综合久久久久综合网 | 欧美高清视频一区二区| 久久久夜精品| 久久久噜噜噜| 国产在线国偷精品产拍免费yy| 国产精品毛片大码女人| 欧美日韩午夜视频在线观看| 免费在线一区二区| 欧美二区不卡| 欧美本精品男人aⅴ天堂| 久久综合久久综合久久综合| 久久精品夜色噜噜亚洲a∨| 久久经典综合| 久久久久久一区| 老司机午夜精品视频在线观看| 久久久久青草大香线综合精品| 久久精品日产第一区二区三区| 欧美一区二区三区视频| 久久国产天堂福利天堂| 久久久久久午夜| 麻豆成人小视频| 欧美激情精品久久久久久免费印度 | 亚洲激情校园春色| 亚洲精品视频免费在线观看| 亚洲乱码一区二区| 亚洲一区二区高清| 午夜影院日韩| 久久免费精品视频| 欧美激情导航| 国产精品麻豆va在线播放| 国产日韩av高清| 激情欧美一区二区| 亚洲精品一线二线三线无人区| 一区二区三区视频在线播放| 亚洲欧美国产精品专区久久| 欧美专区在线观看一区| 老牛影视一区二区三区| 亚洲国产专区| 亚洲中字黄色| 老司机aⅴ在线精品导航| 欧美日韩国产不卡| 国产一区二区三区免费不卡| 亚洲人成网站色ww在线| 亚洲影视九九影院在线观看| 久久这里只精品最新地址| 亚洲国产一区二区三区青草影视| 亚洲视频综合| 久久深夜福利免费观看| 欧美日韩天堂| 有码中文亚洲精品| 久久久久中文| 国产精品男女猛烈高潮激情 | 欧美丝袜一区二区| 尤物精品在线| 亚洲欧美国产日韩天堂区| 麻豆成人av| 亚洲午夜久久久久久久久电影院| 久久久亚洲影院你懂的| 国产精品美女久久久久久免费| 在线观看日韩一区| 欧美在线视频二区| 亚洲免费大片| 免费观看一级特黄欧美大片| 国产精品免费一区豆花| 亚洲麻豆国产自偷在线| 免费av成人在线| 亚洲欧美日韩在线播放| 欧美日韩在线第一页| 91久久夜色精品国产网站| 久久久久久电影| 亚洲欧美日韩成人| 欧美日韩中文字幕精品|