OpenGL採用顯示列表顯示文字完整範例

2021-06-20 13:21:25 字數 4872 閱讀 4905

2011-05-23 16:01:07|  分類: 預設分類

|  標籤:

opengl

|舉報 |字型大小大中小訂閱

(一)顯示英文

opengl並沒有直接提供顯示文字的功能,並且,

opengl也沒有自帶專門的字型檔。因此,要顯示文字,就必須依賴作業系統所提供的功能了。

各種流行的圖形作業系統,例如

windows系統和

linux系統,都提供了一些功能,以便能夠在

opengl程式中方便的顯示文字。

最常見的方法就是,我們給出乙個字元,給出乙個顯示列表編號,然後作業系統由把繪製這個字元的

opengl命令裝到指定的顯示列表中。當需要繪製字元的時候,我們只需要呼叫這個顯示列表即可。假如我們要顯示的文字全部是

ascii字元,則總共只有

0到 127這

128種可能,因此可以預先把所有的字元分別裝到對應的顯示列表中,然後在需要時呼叫這些顯示列表。

windows系統中,可以使用wglusefontbitmaps函式來批量的產生顯示字元用的顯示列表。函式有四個引數:

第乙個引數是hdc,學過windows gdi的朋友應該會熟悉這個。如果沒有學過,那也沒關係,只要知道呼叫wglgetcurrentdc函式,就可以得到乙個hdc了。具體的情況可以看下面的**。

第二個引數表示第乙個要產生的字元,因為我們要產生0到127的字元的顯示列表,所以這裡填0。

第三個引數表示要產生字元的總個數,因為我們要產生0到127的字元的顯示列表,總共有128個字元,所以這裡填128。

第四個引數表示第乙個字元所對應顯示列表的編號。假如這裡填1000,則第乙個字元的繪製命令將被裝到第1000號顯示列表,第二個字元的繪製命令將被裝到第1001號顯示列表,依次類推。我們可以先用glgenlists申請128個連續的顯示列表編號,然後把第乙個顯示列表編號填在這裡。

還要說明一下,因為wglusefontbitmaps是windows系統特有的函式,所以在使用前需要加入標頭檔案:#include 。

現在讓我們來看具體的**:

#include

// ascii字元總共只有0到127,一共128種字元

#define max_char       128

void drawstring(const

char* str) 

// 呼叫每個字元對應的顯示列表,繪製每個字元

for(; *str!='\0'; ++str)

glcalllist(lists + *str);}

顯示列表一旦產生就一直存在(除非呼叫gldeletelists銷毀),所以我們只需要在第一次呼叫的時候初始化,以後就可以很方便的呼叫這些顯示列表來繪製字元了。

繪製字元的時候,可以先用glcolor*等指定顏色,然後用glrasterpos*指定位置,最後呼叫顯示列表來繪製。

void

display(void) 

指定字型

在產生顯示列表前,windows允許選擇字型。

我做了乙個selectfont函式來實現它,大家可以看看**。

void

selectfont(int size, int charset, const

char* face) 

void display(void) 

完整的原始碼:

#include

#include

#define max_char       128

void drawstring(const char* str)

// 呼叫每個字元對應的顯示列表,繪製每個字元

for(; *str!='\0'; ++str)

glcalllist(lists + *str);

}void selectfont(int size, int charset, const char* face)

void display(void)

void init (void) 

int main(int argc, char** argv)

最主要的部分就在於那個引數超多的

createfont函式,學過

windows gdi的朋友應該不會陌生。沒有學過

gdi的朋友,有興趣的話可以自己翻翻

msdn文件。這裡我並不準備仔細講這些引數了,下面的內容還多著呢

:(如果需要在自己的程式中選擇字型的話,把

selectfont函式抄下來,在呼叫

glutcreatewindow之後、在呼叫

wglusefontbitmaps之前使用

selectfont函式即可指定字型。函式的三個引數分別表示了字型大小、字符集(英文本型可以用

ansi_charset,簡體中文本型可以用

gb2312_charset,正體中文本型可以用

chinesebig5_charset,對於中文的

windows系統,也可以直接用

default_charset表示預設字符集)、字型名稱。

(二)顯示中文

原則上,顯示中文和顯示英文並無不同,同樣是把要顯示的字元做成顯示列表,然後進行呼叫。

但是有乙個問題,英文本母很少,最多只有幾百個,為每個字母建立乙個顯示列表,沒有問題。但是漢字有非常多個,如果每個漢字都產生乙個顯示列表,這是不切實際的。

我們不能在初始化時就為每個字元建立乙個顯示列表,那就只有在每次繪製字元時建立它了。當我們需要繪製乙個字元時,建立對應的顯示列表,等繪製完畢後,再將它銷毀。

這裡還經常涉及到中文亂碼的問題,我對這個問題也不甚了解,但是網上流傳的版本中,使用了multibytetowidechar這個函式的,基本上都沒有出現亂碼,所以我也準備用這個函式:)

通常我們在c語言裡面使用的字串,如果中英文混合的話,例如「this is 中文字元.」,則英文本元只占用乙個位元組,而中文字元則占用兩個位元組。用multibytetowidechar函式,可以轉化為所有的字元都佔兩個位元組(同時解決了前面所說的亂碼問題:))。

轉化的**如下:

// 計算字元的個數

// 如果是雙位元組字元的(比如中文字元),兩個位元組才算乙個字元

// 否則乙個位元組算乙個字元

len = 0;

for(i=0; str[i]!='\0'; ++i)

// 將混合字元轉化為寬字元

wstring = (wchar_t*)malloc((len+1) * sizeof(wchar_t));

multibytetowidechar(cp_acp, mb_precomposed, str, -1, wstring, len);

wstring[len] = l'\0';

// 用完後記得釋放記憶體

free(wstring);

加上前面所講到的wglusefontbitmaps函式,即可顯示中文字元了。

void

drawcnstring(const

char* str) 

// 將混合字元轉化為寬字元

wstring = (wchar_t*)malloc((len+1) * sizeof(wchar_t));

multibytetowidechar(cp_acp, mb_precomposed, str, -1, wstring, len);

wstring[len] = l'\0';

// 逐個輸出字元

for(i=0; iwstring[i], 1, list);

glcalllist(list);

}// **所有臨時資源

free(wstring);

gldeletelists(list, 1);}

注意我用了wglusefontbitmapsw函式,而不是wglusefontbitmaps。wglusefontbitmapsw是wglusefontbitmaps函式的寬字元版本,它認為字元都佔兩個位元組。因為這裡使用了multibytetowidechar,每個字元其實是佔兩個位元組的,所以應該用wglusefontbitmapsw。

void

display(void) 

完整原始碼:

#include

#include

#define max_char       128

void drawstring(const char* str)

// 呼叫每個字元對應的顯示列表,繪製每個字元

for(; *str!='\0'; ++str)

glcalllist(lists + *str);

}void drawcnstring(const char* str)

// 將混合字元轉化為寬字元

wstring = (wchar_t*)malloc((len+1) * sizeof(wchar_t));

multibytetowidechar(cp_acp, mb_precomposed, str, -1, wstring, len);

wstring[len] = l'\0';

// 逐個輸出字元

for(i=0; i

// **所有臨時資源

free(wstring);

gldeletelists(list, 1);

}void selectfont(int size, int charset, const char* face)

void display(void)

void init (void) 

int main(int argc, char** argv)

列表顯示格式

list2 1,2,3,4,5,6,7,8,9 range start,end,step list2 start,end,step print list2 1 2 1 print list2 1 print list2 2 2 import random 取乙個60 100的隨機整數 print r...

OpenGL 顯示列表

原 文 lesson 12 display lists 譯 者 marhoo 這次我將教你如何使用顯示列表,顯示列表將加快程式的速度,而且可以減少 的長度。當你在製作遊戲裡的小行星場景時,每一層上至少需要兩個行星,你可以用opengl中的多邊形來構造每乙個行星。聰明點的做法是做乙個迴圈,每個迴圈畫出...

OpenGL 顯示列表

相關主題 頂點緩衝區物件 vbo 顯示列表是一組被儲存或編譯的用來以後執行的opengl命令的集合。當乙個顯示列表被建立以後,所有的頂點資料和畫素資料被複製到位於伺服器端的顯示列表記憶體中。這個過程只進行一次。當顯示列表準備好 被編譯完成 後,你可以重複使用它而不需要在每幀中重複地傳輸這些資料。顯示...