OpenGL進行文字顯示的方法_第1頁
OpenGL進行文字顯示的方法_第2頁
OpenGL進行文字顯示的方法_第3頁
OpenGL進行文字顯示的方法_第4頁
OpenGL進行文字顯示的方法_第5頁
已閱讀5頁,還剩7頁未讀 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

1、任何一個DEMO、仿真項目、游戲,都少不了文字這種媒體。這不可不說是對圖形視覺媒體的補充我們還有一些無法超越文字來向觀眾表達的心事,或是補充說明,或是感悟,或是感激。 ZwqX一般的文字不屬于圖形渲染部分,而屬于用戶界面部分,這在游戲引擎中看或許一目了然,但是在底層的圖形渲染APIOPENGL或D3D中,文字的顯示“并不是必須”,但它是多么深深地被需要著口牙。所以,把字體設置、文字顯示作為一種圖形學技術而非單純的完全我屬或他屬,我是這么想的。(同樣,拾取也算是這樣吧?亂彈OpenGL選擇-拾取機制)本文來源于 ZwqXin ( 轉載請注明  &

2、#160;   原文地址:怎么表達文字呢?在OpenGL中,我們沒有什么現成的東西可用,但確實有辦法讓我們“得到這種技術”。讓我最記憶深刻的是NEHE的兩三篇教程(貌似都是十幾課吧),講述的就是今天的這個主題??梢缘絅EHE網站或者在DANCINGWIND的中文翻譯(見搜集的優(yōu)良OpenGL教程 )看看。而我所知道的這三種方法,前兩種應該就是來自那里吧(記得),當時要努力完成課程DEMO,于是胡胡混混地就把相應的那兩三課學了,而且把它的文字顯示方法應用到自己的程序中(還經歷了一段艱辛的探索史.連我當時的MyFont類也記錄了這份小辛酸,現在看來,是因為當時的知識水

3、平不夠理解吧)。然后后來又一個課程DEMO,老師后來覺得我應該“寫中文”,于是我又去探索中文字體顯示方法了,并在一個開源DEMO中找到,分析代碼段后就拿來主義了,至昨不曾好好考究這就是我所知的第三種方法。三種方法都是三步曲:在初始化的時候“創(chuàng)建字體”Build,在渲染階段“應用字體”(顯示文字)Print,在程序結束或不再需要文字顯示的時候“銷毀字體”kill。其中前兩步比較重要,著重討論討論哈1. 常規(guī)的屏幕字體打?。∟ormalFont)應用得比較廣,大名鼎鼎的AZURE以前的DEMO就是用這個的。NEHE教程中作為首次出現的字體顯示方法,介紹應該比較全面,大家想仔細了解的話請務必從上面網

4、址進入學習(當然還有因為我理解不透不敢亂講的緣由)。1.  /一般的英語字體打印2. void MyFont:BuildGLFont(int fontHeight)3. 4.    HDC   hDC =:GetDC(HWND_DESKTOP);    /就是這里搞暈了半晚5.    6.    int tFontHeight = -1 * fon

5、tHeight;7.  8.    NormalFontBase = glGenLists(96);                         / Storage For 96 Characters9.    HF

6、ONT font = CreateFont( -tFontHeight,                   / Height Of Font10.                 

7、;              0,                            / Width Of Font11.   

8、;                            0,                     

9、60;      / Angle Of Escapement12.                               0,      

10、60;                     / Orientation Angle13.                        

11、       FW_BOLD,                      / Font Weight14.                &

12、#160;              TRUE,                         / Italic15.       

13、60;                       FALSE,                        / Un

14、derline16.                               FALSE,                 &

15、#160;      / Strikeout17.                               ANSI_CHARSET,       

16、0;         / Character Set Identifier18.                               OUT_TT_PRECIS, 

17、;               / Output Precision19.                              

18、60;CLIP_DEFAULT_PRECIS,          / Clipping Precision20.                               ANT

19、IALIASED_QUALITY,          / Output Quality21.                               FF_DONTCARE|D

20、EFAULT_PITCH,    / Family And Pitch22.                               "Georgia");    &

21、#160;              / Font Name23.  24.     HFONT oldfont = (HFONT)SelectObject(hDC, font);         / Selects The Fo

22、nt We Want25.     26.     wglUseFontBitmaps(hDC, 32, 96, NormalFontBase);         / Builds 96 Characters Starting At Character 3227.    

23、0;28.     SelectObject(hDC, oldfont);                         / Selects The Font We Want to return to29.  

24、;   DeleteObject(font);                                 / Delete The Font30.     31.

25、    SetBkMode(hDC,TRANSPARENT);   32.  33.     NormalFont = true; 34. 其中bUild的時候首先用到的是GDI的CreateFont函數創(chuàng)建字體這應該是比較常用的方法,設置了關于字體的一切并選入字體后,有一步重要的操作:wglUseFontBitmaps。1.  2. wglUseFontBitmap3. 為當前選中的GDI字體創(chuàng)建一組OpenGL顯示列表位圖字體

26、60;4. BOOL wglUseFontBitmap(HDC hDC, DWORD dwFirst, DWORD dwCount, DWORD dwListBase); 5.  6. 參數7. hDC8. 設備環(huán)境句柄9.  10. dwFirst11. 用于創(chuàng)建顯示列表字體的第一個字符的ASCII值12.  13. dwCount14. 字符數15.  16. dwListBase17. 第一個顯示列表的名稱18.  19. 返回值20. 成功返回TR

27、UE,否則返回FALSE 21.  輸入為DC,32,96以及創(chuàng)建的96個新顯示列表的base列表。函數繪制從ASCII碼為32-128的字符進入顯示列表,依賴OPENGL顯示列表的高速顯示能力(直接從硬件拿存儲區(qū)),可以方便進行字符的切換。在Print過程中,調用glCallLists就能調動起這些列表了,但是怎么決定具體要“調動”哪些字母呢(96個之中)?1. void MyFont:PrintGLText(GLint x, GLint y, const char *string, .)&#

28、160;2.     char  text256;3.     va_list pArguments;4.  5.     if (string = NULL)6.         return;7.  8.     va_start(pArguments, strin

29、g);9.     vsprintf(text, string, pArguments);10.     va_end(pArguments);11.  12.  13.     glPushAttrib(GL_LIST_BIT | GL_CURRENT_BIT |  GL_ENABLE_BIT | GL_LIGHTING_BIT);14.   &

30、#160; glDisable(GL_DEPTH_TEST);15.     glDisable(GL_LIGHTING);16.     glDisable(GL_TEXTURE_2D);17.     glColor4f(mColor0, mColor1, mColor2, mColor3);18.  19.     glWindowPos2i(x, y);20. 

31、0;21.     glListBase(NormalFontBase - 32);22.     glCallLists(strlen(text), GL_UNSIGNED_BYTE, text);23.     glPopAttrib();24. 首先看函數形式printf形式,若想有個詳細了解,可到這里看看。簡單來說,就是C時代的可變參數列。va_start - vsprintf - (va_arg)- va_end這套機制就是為

32、了把可變參數列的內容,通過va_list (char*指針)一個一個從棧中取出來賦予他者我們的glCallLists所要接受的所有“具體字符”,通過base為基礎的索引快速尋覓而取得對應ASCII字符的字體信息(實際是位圖字體),并依照期望使其形成為“具體字符串”印入屏幕。另外著重介紹的是我所添加的兩個優(yōu)化它們貫穿三種文字顯示方法之中。其一是glPushAttrib,它與glPopAttrib配合,保證了其之間的OPENGL狀態(tài)設置的獨立性,使其不影響該代碼邏輯的前后的具體渲染狀態(tài)。當然參數取GL_ALL_ATTRIB_BITS是保險點,但只要你弄清楚自己的需要,像上面這樣給予特定的

33、狀態(tài)作為參數效率會更高。恩,顏色,光照,深度測試,混合選擇與當前方法最匹配的狀態(tài)而沒有對狀態(tài)機的后顧之憂,如同文字本身一樣作為對象完全獨立于圖形渲染“模塊”。另一是glWindowPos2i(x, y),按OpenGL編程指南第8章所說,它取代我們以前用的glRasterPos2i,不再讓作為描繪對象的物體承受模型-視圖-投影變換之苦亂彈OpenGL中的矩陣變換(上) ,而是直接獨立到OPENGL世界的出口屏幕坐標系,如GDI般用窗口坐標(根據屏幕像素數)來描述文字的起點位置。這同樣是賦予文字的獨立性,而且意義重大可知道,當時我用glRasterPos2i多么狼狽,好難才讓文字不在場

34、景“里面”亂竄。在具體應用中,在初始化調用BuildGLFont.,在渲染階段調用PrintGLText。譬如:1. /CMAINFRAME2. MyFont mFont;3.  4. /初始化:5. mFont.BuildGLFont(25);/25是字體字高,控制字體大小6.  7. /渲染階段(RenderGLScene)8.  9. mFont.PrintGLText(530, 710, "http:/www.Z - My 3D Graphics");10. 

35、0;11. /將在坐標X = 530, Y =710位置開始繪制文字。對1024*768大小的渲染窗口中,即在右上角注意,OpenGL窗口坐標系的原點在窗口的左下角,橫坐標為X,豎坐標為Y,最大值在右上角。(同見亂彈OpenGL選擇-拾取機制 )瀏覽一下效果,第一行就是了,因為我默認用的是Georgia字體(應該一般人電腦都有),所以很漂亮接下來會談及其余兩種方法,并比較之。真正的紋理文字是怎樣弄的呢?怎樣讓中文字體乖乖顯示?什么時候用哪種方法?我集成的MyFont類是怎樣個怪樣?聽下回分解:在OpenGL上設置字體和顯示文字(下)本文來源于 

36、ZwqXin ( 轉載請注明      原文地址:Tags: OpenGL  代碼  工具類  C  分類:OpenGL技術 | 評論:1 | 引用:0 | 瀏覽:7399« 水效果 - 水池在OpenGL上設置字體和顯示文字(下) »分享到新浪微博QQ空間騰訊微博人人網豆瓣0· 點擊這里獲取該日志的TrackBack引用地址· 相關文章:· 亂彈OpenGL選擇-拾取機制(下

37、)  (2009-6-14 23:3:8)亂彈OpenGL選擇-拾取機制(上)  (2009-6-13 16:54:2)子類調用父類的純虛函數之問題  (2009-6-8 23:18:32)視錐類CFrustum .zwqxin ver  (2009-6-2 22:39:52)標準MFC在OpenGL  (2009-5-31 17:46:47)QuickSort 快速排序的實現  (2009-5-6 1:21:55)全屏反鋸齒 - 多重采樣  (2009-

38、5-3 19:50:7)全屏反鋸齒 - 多重采樣  (2009-5-2 16:21:56)圖像處理里的空間域濾波  (2009-4-27 23:53:18)一年前,首次獻給OpenGL之夜.雷達追蹤  (2009-4-5 22:18:52)在OpenGL上設置字體和顯示文字(下)2009-8-6 10:22:27 | 發(fā)布:zwqxin本篇緊隨上篇,繼續(xù)說一下鄙人所了解的在OpenGL進行文字顯示的方法,也方便不知從哪個次元來到這里的學習者提供一點這方面的信息。上一篇見:在OpenGL上設置字體和顯示文字(上) ZwqX本文來源于&#

39、160;ZwqXin ( 轉載請注明      原文地址:2. 紋理字體最近接觸Irrlicht引擎,里面的GUI模塊涉及的字體設置就是用了這種紋理字體的方法。事實上,上篇的方法最后多少了涉及到了位圖字體,但是這里所說的,是直接從一張“寫著各個英文字符和其他常用字符”的紋理上,按對此紋理上的圖案“結構”的先驗知識而獲取字符對應的“紋理部分”,顯示到屏幕上。換句話來說,這就是真正的紋理貼圖了,因此必須結合一張?zhí)囟ㄔO計的“字體紋理”。要顯示一個字符,需要你繪制一個一定大小的矩形(這個長度值相當于之前的字體高度它控制最后出來的文字

40、的大?。缓笳业侥闼枳址谠摷y理上的紋理坐標,作為索引檢索出紋理上的對應字符部分的小紋理,貼到該矩形上。1.  2. /從字體集紋理中取出的字符3. void MyFont:BuildTextureFont(GLuint fonttex, int fontHeight, int screenWidth, int screenHeight)4. 5.     TextureFontFont = fonttex;6.  7.  

41、;   float   cx;                                         / Ho

42、lds Our X Character Coord8.     float   cy;                                 

43、0;       / Holds Our Y Character Coord9.  10.     glEnable(GL_TEXTURE_2D);11.  12.     TextureFontBase = glGenLists(256);          

44、;        / Creating 256 Display Lists13.  14.     glBindTexture(GL_TEXTURE_2D, TextureFontFont);      / Select Our Font Texture15.  16.    &

45、#160;for(int loop=0; loop<256; loop+)                    / Loop Through All 256 Lists17.     18.       

46、0; cx=float(loop%16)/16.0f;                        / X Position Of Current Character19.         cy=float(loop/

47、16)/16.0f;                        / Y Position Of Current Character20.  21.         glNewList(TextureFontBase&

48、#160;+ loop, GL_COMPILE);  / Start Building A List22.             glBegin(GL_QUADS);                   &#

49、160;      / Use A Quad For Each Character23.                 glTexCoord2f(cx,1-cy-0.0625f);          / Te

50、xture Coord (Bottom Left)24.                 glVertex2i(0,0);                        

51、/ Vertex Coord (Bottom Left)25.                 glTexCoord2f(cx+0.0625f,1-cy-0.0625f);  / Texture Coord (Bottom Right)26.         

52、        glVertex2i(fontHeight, 0);              / Vertex Coord (Bottom Right)27.               

53、  glTexCoord2f(cx+0.0625f,1-cy);          / Texture Coord (Top Right)28.                 glVertex2i(fontHeight,fontHeight);   

54、;   / Vertex Coord (Top Right)29.                 glTexCoord2f(cx,1-cy);                  /

55、0;Texture Coord (Top Left)30.                 glVertex2i(0, fontHeight);              / Vertex Coord (Top Left

56、)31.             glEnd();                                    

57、;/ Done Building Our Quad (Character)32.             glTranslated(fontHeight,0,0);               / Move To The Right

58、0;Of The Character33.         glEndList();                                  

59、0; / Done Building The Display List34.                                       

60、60;                / Loop Until All 256 Are Built35.  36.     glDisable(GL_TEXTURE_2D);37.  38.     ScreenWidth = screenWidth;39.

61、    ScreenHeight = screenHeight;40.  41.     TextureFont = true;42. 這在BUILD階段就做的必要是沒有的,但是一次過導入紋理中256個字符,生成256個小紋理,并在每幀都選擇對應的紋理索引檢索紋理,且每個字符如此這樣的重復不變而低效的事情,還是由OpenGL的顯示列表技術來做比較好一次過在初始化時做好,放入顯示列表。在 PRINT階段只要調用顯示列表就好。關于顯示列表,eastcowboy在他的OP

62、ENGL入門學習中詳細提及過,有興趣的朋友可看看他的文章:OpenGL入門學習第八課-使用顯示列表 。比起最時興的VBO,顯示列表在重復勞動上還是有一定優(yōu)勢的額最后的結果是按glTranslated進行排列的256個具有紋理字符的矩形。為什么要得到渲染窗口的大小呢?因為這些矩形要保證在屏幕最前方,就應該讓它突破矩陣變換啊。在上篇在OpenGL上設置字體和顯示文字(上) 也提過glWindowPos2i(x, y),但這里對實際的矩形它不是很適用。因此我還是選擇原來的路子,來給予文字以獨立于圖形的屬性在屏幕最前而位置只由屏幕坐標XY決定。方法就是,或許很多人也熟悉的,glOrtho正交

63、投影變換。因此,屏幕大小(這里指渲染窗口的大?。┦切枰?。1.  2. void MyFont:PrintTextureText(GLint x, GLint y, char *string, int TextureSet)3. 4.     if (TextureSet > 1)TextureSet = 1;5.     if (TextureSet 

64、;< 0)TextureSet = 0;6.  7.     glPushAttrib(GL_CURRENT_BIT | GL_LIGHTING_BIT | GL_ENABLE_BIT|  GL_LIST_BIT);8.     glDisable(GL_LIGHTING); 9.  10.     glEnable(GL_TEXTURE_2D);11

65、.     glBindTexture(GL_TEXTURE_2D, TextureFontFont);      / Select Our Font Texture12.  13.     glDisable(GL_DEPTH_TEST);             &

66、#160;             / Disables Depth Testing14.     glEnable(GL_BLEND);15.     glBlendFunc(GL_SRC_ALPHA,GL_ONE);16.  17.     glColor4f(mColor0, mColor1,

67、 mColor2, mColor3);  18.  19.     glMatrixMode(GL_PROJECTION);                        / Select The Projection Matri

68、x20.     glPushMatrix();                                     / Store The Project

69、ion Matrix21.     22.     glLoadIdentity();                                   /&

70、#160;Reset The Projection Matrix23.     glOrtho(0,ScreenWidth,0,ScreenHeight,-1,1);         / Set Up An Ortho Screen24.  25.     glMatrixMode(GL_MODELVIEW);  &#

71、160;                      / Select The Modelview Matrix26.     glPushMatrix();            

72、                         / Store The Modelview Matrix27.     28.     glLoadIdentity();     

73、;                              / Reset The Modelview Matrix29.     glTranslated(x,y,0);    

74、;                            / Position The Text (0,0 - Bottom Left)30.     31.     g

75、lListBase(TextureFontBase-32 + (128 * TextureSet);/ Choose The Font Set (0 or 1)32.     glCallLists(strlen(string),GL_UNSIGNED_BYTE,string);/ Write The Text To The Screen33.    

76、60;34.     glMatrixMode(GL_PROJECTION);                        / Select The Projection Matrix35.     glPopMatrix(); 

77、;                                     / Restore The Old Projection Matrix36.   &

78、#160; glMatrixMode(GL_MODELVIEW);                         / Select The Modelview Matrix37.     glPopMatrix();   

79、60;                                  / Restore The Old Projection Matrix38.     39. &

80、#160;   glDisable(GL_BLEND);40.     glEnable(GL_DEPTH_TEST);                            / Enables Depth Testin

81、g41.     glDisable(GL_TEXTURE_2D);42.  43.     glPopAttrib();44. TextureSet選擇字符集,因為字符紋理里面每個字符對應兩種字體,用0/1選擇。glPushAttrib的作用前面說過了。之后我們用glPushMatrix保存當前的投影/模型視圖矩陣,在弄好一切好就馬上切換回去。弄什么呢?新的坐標變換。文字(glCallLists繪制)是脫離我們OPENGL圖形世界的,因此單獨給予它一套變換在屏幕最前方且不受視覺透視影響。glOrtho(

82、0,ScreenWidth,0,ScreenHeight,-1,1)這樣的投影變換設置配合glTranslated這樣的模型變換就能滿足我的要求了。因為創(chuàng)建的正交投影是與渲染窗口大小一致的,所以glTranslated的X,Y的單位與像素pixel對應這不也就是GDI那種設置方式了么哈。具體應用:1. /CMAINFRAME 2. MyFont mFont; 3.   4. /初始化: 5. mFont.BuildTextureFont(FontTextureID, 25, VB_WIDTH, VB_HE

83、IGHT);6. /25是字體字高,控制字體大小 ,FontTextureID字體紋理的紋理ID7.   8. /渲染階段(RenderGLScene) 9.   10. mFont.PrintTextureText(790,645,"Font Test",1);11.   12. /將在坐標X = 790, Y =645位置開始繪制文字。對1024*768大小的渲染窗口中,13. /即在右上角偏下3.GDI字體事實上第一種方法也可以說是GDI的

84、方法,但是這里更明顯,結合GDI字體創(chuàng)建和位圖創(chuàng)建。而且它不涉及顯示列表。它是在渲染時動態(tài)創(chuàng)建包容文字的設備相關位圖(具體可參考我的一篇舊文認識HBITMAP與Bmp操作(整內存拷貝版) ),再把此位圖定位而成的。因此,它是很慢的(抽)。但是為了中文字體,一點點的性能損失算得了什么呢。1. /GDI, 位圖字體 可設中文字體2. void MyFont:BuildGDIFont(LPCTSTR lpszFacename, int fontWeights, int fontHeight)3. 4.  

85、60;int tfontHeight = -1 * fontHeight;5.       hGDIFont = CreateFont(tfontHeight, 0, 0, 0, fontWeights, 0, 0, 0, GB2312_CHARSET,6.            

86、;             0, 0, 0, FF_MODERN, lpszFacename);7.       GDIFont = true;8. BUILD部分就不多說了,就是CreateFontfontWeights表示字體的重量,在0900內可選,直接設置FW_BOLD之類的也行,這里給出這個參數不過是多給它一些可控性而已。首參數是字體,譬

87、如可以是"黑體","宋體"等等,也可以是英文字體。當然這里應該是取你電腦的字庫里的字體,所以考慮程序的通用性,別搞些另類的字體或只有自己有的字體GB2312_CHARSET你該知道啦哈。1. void MyFont:PrintfChtext(int x, int y, LPCTSTR lpszText)2. 3.       CBitmap bitmap;4.      

88、60;BITMAP bm;5.       SIZE size;6.       7.       HDC MDC = :CreateCompatibleDC(NULL);8.       SelectObject(MDC, hGDIFont);9.     

89、  10.       :GetTextExtentPoint32(MDC,lpszText,strlen(lpszText),&size);11.  12.       bitmap.CreateBitmap(size.cx, size.cy, 1, 1, NULL);13.  14.       HBITMAP ol

90、dBmp=(HBITMAP)SelectObject(MDC,bitmap);15.  16.       SetBkColor  (MDC, RGB(0,     0,   0);17.       SetTextColor(MDC, RGB(255, 255, 255);18.  19.   &

91、#160;   TextOut(MDC, 0, 0, lpszText, strlen(lpszText);20.  21.       bitmap.GetBitmap(&bm);22.       size.cx = (bm.bmWidth + 31) & (31);23.  24.   

92、    int bufsize = size.cy * size.cx;25.  26.       struct   27.               BITMAPINFOHEADER bih;28.     

93、60;         RGBQUAD col2;29.              bic; 30.  31.       BITMAPINFO *binf = (BITMAPINFO *)&bic; 32.   

94、;    binf->bmiHeader.biSize     = sizeof(binf->bmiHeader);33.       binf->bmiHeader.biWidth    = bm.bmWidth;34.       binf->bmiHeader.biHeight  

95、; = bm.bmHeight;35.       binf->bmiHeader.biPlanes   = 1;   36.       binf->bmiHeader.biBitCount = 1;37.       binf->bmiHeader.biCompression 

96、= BI_RGB;38.       binf->bmiHeader.biSizeImage   = bufsize; 39.  40.       UCHAR* Bits = new UCHARbufsize; 41.       :GetDIBits(MDC,bitmap, 0, bm.bmHeight, Bits, binf, DIB_RGB_COLORS); 42.                           

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論