Linux OpenGL 實踐篇 16 文字繪製

2022-08-24 10:09:15 字數 4317 閱讀 1177

本文主要射擊freetype的入門理解和在opengl中實現文字的渲染。

opengl本身並沒有提供文字繪製功能,通常有兩種方式來繪製文字,

使用freetype繪製文字屬於紋理字型的方式,這種繪製方式的好處就是靈活,擴充套件性強,比如你想把文字繪製在乙個飄動的紅旗上,用顯示列表的方式就很難實現;

demo**:

freetype的官網:

freetype中的library其型別是ft_library,定義如下:

typedef struct ft_libraryrec_  *ft_library;
所以可以簡單的理解為乙個ft_libraryrec_的物件,雖然freetype用c寫的,但這個地方不妨礙我們使用物件來理解它。因為_libraryrec_我並沒有看到源**,具體包含哪些內容我並不清楚。但根據其用法,可以推測其應該是一些字型上下文的內容,比如快取、記憶體管理等。

ft_error = ft_init_freetype(&library);
乙個face可以理解為字型的描述或者說字形的集合,比如「times new roman regular"表示正常的新羅馬字型,而"times new roman italic"表示新羅馬字型的斜體表示。乙個字型檔案中可以嵌入多個face,我們可以通過下面的api載入特定的face:

ft_error ft_new_face(ft_library library,const

char* filepathname,ft_long face_index,ft_face *aface);

其中face_index就表示要載入字型檔案中的哪個face,一般情況下,0總是可用的。如果face_index設定為-1,則可以通過face->num_faces獲取字型檔案中有多少個face。

error = ft_new_face(library,"

./arial.ttf

",0,&face);

error =ft_set_char_size(

face,

/*handle to face object

*/0, /*

char_width in 1/64th of points

*/16*64, /*

char_height in 1/64th of points

*/300, /*

horizontal device resolution

*/300 ); /*

vertical device resolution

*/

在這裡有兩個概念需要注意:pt和dpi。pt是point的縮寫,可以立即為乙個點,乙個點的大小使用物理距離來描述的,通常是1/72英吋。dpi的意思是dot per inch,表示每英吋有多少個點,這個點表示的是顯示裝置最小輸出單元,可以理解為我們常說的畫素,主流顯示裝置的標準值是72dpi和96dpi,這個可以在顯示器配置中查到。所以在這個方法中通過同時指定pt大小和裝置的dpi,根據換算關係可以計算字元的畫素大小。

下面的**直接設定字形的畫素大小。注意這兩個方法中,width的值設定為0,表示width與height一樣,height設定為0同理。

error =ft_set_pixel_sizes(

face,

/*handle to face object

*/0, /*

pixel_width

*/16 ); /*

pixel_height

*/

字形,其實就是某個字元具體的形狀描述。字形的描述有兩種,一種是點陣圖,一種是向量圖。點陣圖又叫點陣圖,簡單理解就是影象是由乙個乙個畫素點組成,每個畫素點可以有自己的顏色;向量圖則記錄的是乙個乙個的物件,這些物件是一種形狀,形狀由數學公式來描述的,簡單的理解就是向量圖記錄的是影象的畫法。這兩種描述最大的區別就是,縮放的時候向量圖不會失真。

使用freetype的時候,我們不需要關心這些底層的實現,直接使用ft_load_glyph即可載入。

ft_uint ft_get_char_index( ft_face   face,

ft_ulong charcode );

ft_error ft_load_glyph( ft_face face,

ft_uint glyph_index,

//the index of the glyph in the font file.

ft_int32 load_flags ); //

a flag indicating what to load for this glyph

ft_error ft_render_glyph( face->glyph,   /* glyph slot  */

render_mode ); /* render mode */

字形的資料結構:

typedef struct

ft_glyphslotrec_

ft_glyphslotrec;

在字形資料結構中,幾個比較重要的資料是bitmap,bitmap_left,bitmap_top。其中bitmap其實可以理解為字形的點陣圖資料,定義如下:

typedef struct

ft_bitmap_

ft_bitmap;

其中buffer畫素資料,rows,width表示影象的寬和高,我們在opengl中繪製時主要用到的三個資料。

除了bitmap,還有幾個重要的資料,這寫資料主要影響多個文字之間的布局,因為不是每個字形的大小都是一樣的,比如bitmap_left,bitmap_right等。讓我們以下圖為例說明一下freetype對於字形的描述:

每乙個字形都放在乙個水平的基準線(baseline)上(即上圖中水平箭頭指示的那條線)。一些字形恰好位於基準線上(如』x』),而另一些則會稍微越過基準線以下(如』g』或』p』)(譯註:即這些帶有下伸部的字母,可以見這裡)。這些度量值精確定義了擺放字形所需的每個字形距離基準線的偏移量,每個字形的大小,以及需要預留多少空間來渲染下乙個字形。下面這個表列出了我們需要的所有屬性。

freetype 官網有些例子給我們參考,點選這裡檢視。其中乙個簡單的例子是在終端中以字元的形式輸出字形,這個例子可以幫助我們理解bitmap中的資料形式。

獲取到字形的bitmap後,在opengl繪製文字的思路就很簡單了:根據字形資料生成二維紋理,然後把這個紋理繪製到乙個四方形中,以下是繪製的主要**,完整**見:

glpixelstorei(gl_unpack_alignment, 1); //禁用位元組對齊限制

unsigned int

textureid;

glgentextures(

1,&textureid);

glbindtexture(gl_texture_2d,textureid);

glteximage2d(gl_texture_2d,

0,format,width,height,0

,format,gl_unsigned_byte,data);

gltexparameteri(gl_texture_2d, gl_texture_wrap_s,gl_clamp_to_edge);

gltexparameteri(gl_texture_2d, gl_texture_wrap_t,gl_clamp_to_edge);

gltexparameteri(gl_texture_2d, gl_texture_min_filter,gl_linear);

gltexparameteri(gl_texture_2d, gl_texture_mag_filter,gl_linear);

在這裡需要注意位元組對齊的問題,opengl預設要求紋理4位元組對齊,即紋理的大小是4的倍數,這通常不會有什麼問題,因為絕大多數的紋理大小都是4的倍數並/或每個橡樹4位元組大小,但現在我們乙個畫素是乙個位元組(gl_red),它可以是任意的寬度,所以需要需求這個限制,將對齊引數設定為1,不然的話可能會造成段錯誤。

glpixelstorei(gl_unpack_alignment, 1);//禁用位元組對齊限制
效果:

Linux OpenGL 實踐篇 4 座標系統

opengl中頂點經過頂點著色器後會變為標準裝置座標系。標準裝置座標系的各座標的取值範圍是 1,1 超過這個範圍的點將會被剔除。而這個變換的過程可描述為頂點在幾個座標系統的變換,這幾個座標系統為 模型空間 local sapce 世界空間 world space 觀察空間 view space 裁切...

XP實踐 1 XP必讀篇

2008年9月26日 極限程式設計的一般思想 索引 1.應用領域 2.開發流程圖標 3.開發原則 4.設計原則 5.程式設計原則 6.團隊成員角色 宣告 ifanso gmail.com 正文 extreme programming xp,極限程式設計 是一種輕量級的軟體開發方法,它使用快速的反饋,...

演算法學習實踐篇 1 暴力求解(1)

有時候,問題的解決不需要特別高深的演算法。事實上,設計過於複雜的演算法可能離問題的解決更遠。演算法的初始結構要足夠魯棒,經得起你百般的蹂躪。問題描述1 有乙個n m 方格的棋盤,求其方格包含多少正方形 長方形 不包含正方形 問題分析 這個問題初看,覺得可以用列舉解決。那麼問題來了,我們怎樣列舉?這個...