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

OpenGL點陣字體繪制終極解決方案!

OpenGL點陣字體繪制終極解決方案!哈!

tsuui posted @ 7 years ago in Coding with tags OpenGL 中文顯示 freetype , 12160 readers

事情總在變化, opengl迎來了3.3以及4.1的進化, 相信今后的擴充也會朝著這個方向. 對于字體渲染方面, 也并不是什么壞事. 今后有時間再寫篇關(guān)于3.3和4.1的全屏字體渲染的新方案, 仍然是結(jié)合freetype2的, 相信隨著freetype2的進步, 和對它的逐步認識, 應(yīng)該會比現(xiàn)有方案更簡單高效... 現(xiàn)在最最最重要的事是...睡覺!!!

對于此文, 大家僅做參考吧.


經(jīng)過多次修改測試,字體問題終于有了個比較完美的解決方法了,貼出來亮亮~~

此法可以說完全是“紅寶書”(即《OpenGL編程指南》)所賜, 此篇也不過是一些實踐心得和我自己對字體顯示方法的一些體會罷了。

下面就來介紹這個所謂的“終極解決方案”,對于待解決的各種問題,都有著多種可供選擇的方案,就讓我來邊比較邊描述吧:

  1. 渲染方式和幀數(shù)

不管是不是OpenGL平臺, 在每個3D平臺中,  點陣字體無非兩個用處: 要么做效果,要么做提示。效果就是標題文字、按鈕之類的,我們一般稱之為banner,titile,caption的東西; 提示就是指一些有動態(tài)更新要求的文字,如控制信息提示,  調(diào)試模式下的對象名稱、坐標等, 還有就是交互場合,比如聊天。

兩種應(yīng)用需求有所不同,但不管是哪種,在OpenGL中我能找到的直接支持字體的,只有三種方法,選擇他們的標準只有一個——速度:

● glBindTexture, 紋理貼圖,連文字帶背景做好一張大圖,  按需地選取各個文字子圖像,再貼到相應(yīng)位置的矩形上。貼圖能夠?qū)崿F(xiàn)的文字效果最多,你可以把文字紋理映射到空間任意位置的巨型上,可以隨意的旋轉(zhuǎn)縮放和變形。在不要求大量動態(tài)更新文字內(nèi)容的地方,可以選用此方法。大部分的小型3D游戲,都采用了這樣的方式顯示文字,速度夠快,能實現(xiàn)所有的變換效果。

不足之處是:

很難實現(xiàn)多顏色混合顯示的文字,因為為紋理設(shè)置顏色需要的步驟十分繁瑣,需要反復(fù)切換和設(shè)置紋理函數(shù)和像素傳輸轉(zhuǎn)換函數(shù),難免影響性能;

文字內(nèi)容不能靈活的更換, 除非你打算用很多碎小的紋理來拼湊文章;但隨著碎小圖片的增多,頂點的和紋理對象也大量增加,需要大量額外的片段處理和過濾操作,會明顯拖慢處理流水線,在要求顯示大量動態(tài)文本的場合下力不從心。不過好在OpenGL在處理紋理對象時多數(shù)情況是使用硬件實現(xiàn)的,速度不會慢太多,但也絕對不夠塊(你可能玩過這樣的3D游戲:圖像效果場景規(guī)模都一般,可鼠標速度慢得難以忍受,出現(xiàn)這種情況,九成的原因是頂點片元過多造成的,單次場景同時顯示的紋理片段過碎過多,都會成倍地同時增加頂點和像素片元,拖慢速度,鼠標有時間響應(yīng),卻沒時間畫出來);

還有就是變換拉伸后,紋理字體會出現(xiàn)模糊的現(xiàn)象,有些人建議打開Anisotropic Filtering(各向異性過濾)開關(guān), 利用反走樣解決,但效果似乎也不穩(wěn)定,在轉(zhuǎn)角過大、近距離或光線角度太偏的情況下,效果就越來越差了,我想這是紋理映射的通病吧,不可能就一張圖你從哪里看都一樣的清晰啊,也有人用多等級的紋理和Mipmap解決,本人沒試驗過(比較麻煩)所以沒什么發(fā)現(xiàn)權(quán)。

● glDrawPixels,像素繪制,任何紋理能夠支持的圖像格式,它都能支持,縮放也很簡單,也可通過設(shè)置像素傳輸和像素封裝函數(shù)實現(xiàn)一些其他的效果。

缺點是:

他同紋理一樣,很難靈活設(shè)置顏色; 

只能在光柵上繪制,若需要各種變換效果,還要開辟額外的輔助緩沖和紋理對象;

而最大最大的問題就是速度! 像素在顯示之前的處理動作是沒有經(jīng)過加速的,也就是說不管你有沒有把他編譯到顯示列表,像素的轉(zhuǎn)換傳輸?shù)葎幼髅看味颊兆霾徽`,它不同于紋理對象中的像素,多數(shù)OpenGL實現(xiàn)沒有對它開辟專屬的顯存區(qū)域(這種說法有待考證,但實際測試中效率確實很差,編程指南中有特定篇幅介紹了如何提高像素繪制的效率,但即使犧牲一切資源來保證效率,實測效果仍然很難讓人滿意)。

所以,雖然 glDrawPixels似乎是三種方法中最簡單有效的, 可實際運行起來卻是三種方法中最慢的!所以如果你要繪制大量點陣字,又想保證幀數(shù)的話,寧愿去考慮紋理貼圖,也不要在這個函數(shù)上花太多心思。

● glBitmap,位圖,如果你想在你的3D引擎里添加一個控制臺,這個是唯一的選擇,96個可打印字符做成位圖映射到索引為0x20~0x7F的顯示列表,供隨時調(diào)用。就算直接用glBitmap也來的及,對幀數(shù)的影響也不算大,  三種方法中它的速度最能讓人滿意, 且能通過設(shè)置光柵顏色靈活改變位圖字體的顏色。想象一下,如果你的控制臺里的warning error 普通的log message和user command分別使用了不同的顏色顯示,而為實現(xiàn)這個既酷又實用的效果,所付出的代價僅僅是在設(shè)置光柵前加個glColor這么簡單而已。

缺點:

只能在光柵上繪制,若要縮放旋轉(zhuǎn)之類的變換,需要額外的處理工序,但由于其本身的速度優(yōu)勢,這些工序一般不會對幀數(shù)有太大的影響;

另外由于位圖只有黑白單色,無法表示灰度,鋸齒問題嚴重,如果只顯示英文字體還好,一旦要顯示中文,文字效果很差,實在是褻瀆中華文化!當然如果你知道怎么在OpenGL里實現(xiàn)一個和ClearType類似的技術(shù),那另當別論。

 

以往對于全屏字體渲染,glBitmap一直是我心中的痛,難以割舍它的高速,又無法忍受它的效果, 直到前一段在讀編程指南時,無意間發(fā)現(xiàn)了一種利用glBitmap顯示反鋸齒字體的技巧。當時反復(fù)讀了幾次,貌似明白了上面的意思,拿到機器上試了試, 果然天才, 很好地解決了鋸齒的問題,相見恨晚,感嘆讀書太不認真,怎么早沒發(fā)現(xiàn)!!  下面簡單描述一下這個方法:

對于一副256灰度圖像,每個像素使用了一個字節(jié)表示0~255個灰度,而位圖只有一位0或1,乍一看不太可能,但位圖可以靈活設(shè)置顏色的特點,成了突破口。既然位圖在設(shè)置光柵前可以使用glColor為光柵指定"當前光柵顏色",不僅如此,我們還可以指定顏色的alpha值,從而繪制明暗相間的彩色位圖,了解了?

把一個反鋸齒的灰度字體圖像分為多幅位圖,假設(shè)分為4張位圖,第一張:使灰度1~63的相應(yīng)點置1,其他點置0;第二張:64~127的置1,其他置0...以此類推, 灰階每上升64的點都集中到同一張位圖上。然后,打開混合,使用4次glBitmap調(diào)用繪制出來,每次繪制前將光柵顏色設(shè)置成與圖像對應(yīng)階段的灰度,像下面這樣: 

GLfloat curColor[4] = { r, g, b, a*0.25f}; //假設(shè)當前顏色為 (r,g,b,a) for (int i=0; i<4; ++i) { glColor4fv(curColor); glRasterPosiv(curPos); glBitmap(w,h, 0,0, 0,0, bitmap[i]); //當前alpha增幅0.25, 4次增至1.0 curColor[3] += a*0.25f; } 

就相當于讓一張256灰階的位圖降低到5灰階。這么做的效果如何呢?

下圖是我在glut這種超慢框架下的測試的:

中間的截圖是用glDrawPixels在打開freetype2的autohinting選項下渲染的256灰階字體, 上下兩張截圖都是使用glBitmap繪制的,沒有打開autohintng,上面的是3副位圖(4灰階)/字,下面的是4副位圖/字。glDrawPixels是使用了顯示列表繪制全屏1003個漢字的,已經(jīng)累成14FPS了,而glBitmap是沒用顯示列表的,同樣1003字一屏,在glut下也能達到50FPS以上! 近乎完美!

(窗口分辨率是960x600)

 同時,由于每個像素變成了4個bit表示(4張圖每張1bit),使存儲字模所需的空間降至原來的一半。

 

  1. 字庫和編碼映射

除了glDrawPixels,每一種方法都有應(yīng)用它的理由,但不管你用哪一種,要克服的最大困難除了渲染速度,就是字庫問題了! 讀取字庫建議使用FreeType2這個開源目, 它支持當今幾乎所有流行格式的字體文件,我們可以選擇它來作為字體導(dǎo)入的工具,當然也可以把它link到你的程序中,實時的載入ttf字體并按需生成字模圖像。解決字庫的讀取問題,F(xiàn)reeType2絕對是上上之選,就這么簡單~

當然, 如果你只想支持普通的96個可打印字符,除了glDrawPixels,其他兩種方式隨便用——想要效果就用glBindTexture、想要簡單方便就glBitmap,然后關(guān)掉瀏覽器、合上參考書,最多半個小時你的字體問題就有著落了! 可如果你想要支持中文??龐大的字庫體積是你不得不考慮的另一個問題, 何為龐大?讓我們簡單地算下:

GB2312編碼包含7445個字符,其中漢字6000多個,GBK編碼下僅漢字就有20902個,最新國家標準GB18030-2005,總共76546個字符, 而目前的Unicode字符集,已經(jīng)增至超過10萬個字符,雖然現(xiàn)在還沒有哪個unicode字庫能支持到這么多字符(難道真的有?),但至少20000個還是有的! 而這些字符都是分散在編碼空間中的,就是說編碼是不連續(xù)的,不能使用連續(xù)的顯示列表索引作簡單的映射(即使連續(xù),這么龐大的數(shù)目,就算顯示列表沒有上限,它所占據(jù)的顯存空間也相當可觀),因此不得不為‘字符編碼’到‘字模索引/列表索引’建立查找表。

最猛的做法是,在內(nèi)存平鋪整張表,字模全部存入內(nèi)存,一步索引到字模,生成顯示列表,下次再繪制字模時只需索引到顯示列表而不必去取字模。這樣做好像也沒什么問題,沒什么問題?如果真的沒問題就不會是最猛的了——對于GB2312和GBK這種"小型"多字節(jié)編碼就需要盡1MB的空間,對于unicode最少最少需要近4MB的空間,而在這個大表里,八成以上的內(nèi)容是普通人這輩子都用不上的,而每刷新一幀,你的每個要顯示的字符都要重復(fù)查表一次,在這樣大的空間中頻繁查表,產(chǎn)生頁交換的可能非常的大,速度不慢才怪,絕對不比你每次調(diào)用freetype實時轉(zhuǎn)換灰階來的快,而且還很浪費。

我建議的方法是利用std::map!當然如果你有自己的紅黑樹類和allocator也可以自己做一個map,效率上可能更勝一籌。map的作用是把字模信息映射到字符編碼,動態(tài)的載入我們僅有可能用到的那幾千個字模信息,這樣既節(jié)省了空間(省點是點),又比較高效。另外,這里不必專門為map設(shè)定空間限制,map在到達一定大小后(大約7000個節(jié)點)或每過一段時間后將查找表clear掉就可以了,除非你要在程序里顯示《說文解字》全篇,否則要讓map增大到5000節(jié)點都是個相當有難度的工作。

 

  1. 定制自己的字體文件

哎……這也是被逼無奈,如果你夢想著自己的圖行引擎能有全功能的中文支持(顯示、輸入),你必須一再考慮速度的問題!因為中文實在是太多了……而且萬把字符一會要查表一會要轉(zhuǎn)換圖像一會又要排布文字,各個環(huán)節(jié)都不像西文那樣方便直接, 都需要額外的繁瑣的計算!如果你還要些特效,你一定會比我更吝嗇速度。

實踐證明,使用了定制點陣字體文件的方式后,不使用顯示列表而是實時從內(nèi)存取得字模再逐個glBitmap,其效率幾乎可以和使用了顯示列表的內(nèi)嵌Freetype2的字體系統(tǒng)媲美。至于怎么建立自己的字體文件嘛,我的意見是:怎么方便怎么建,讀著方便,用這方便就OK了,因為像這樣的位圖數(shù)據(jù)生成文件后數(shù)據(jù)是很“稀疏”的,很容易壓縮和解壓,所以空間上不必太擔心(我自己做的24×24點陣字體文件,連帶額外數(shù)據(jù)只有4MB多一點)。

其他的就沒什么可說的了,要注意的只有三點:你需要一個有序的code-index表,為什么要有序?因為代碼域很長而實際的可顯示碼點很稀少,在一個有序的靜態(tài)表中二分查找是不二之選;你還需要為每個字模數(shù)據(jù)建立一個字模信息記錄,記錄啥?寬width、高height、列步進長度advance、行字節(jié)數(shù)pitch、字模數(shù)據(jù)指針等; 還有就是字模數(shù)據(jù),如果你想更塊一些,讓每行像素的字節(jié)數(shù)擴充到4的倍數(shù),浪費些空間可以再換些速度。

 

到目前為止我們基本完成了下面的要求:

1. 速度快,永遠不能放棄對它的追求!

2. 省內(nèi)存,CPU內(nèi)存要省,GPU內(nèi)存更要一省再省!

3. 美觀,字是拿來看的,辛勤勞動不能僅因一個難看而被淪為劣質(zhì)產(chǎn)品。

4. 簡單,方法要簡單通用!這個好像差點事.....

5. 支持海量中文,在新一輪的‘文字改革’到來之前,這永遠是個艱巨的任務(wù)!

http://tsuui.is-programmer.com/posts/4252.html

posted on 2015-11-07 08:05 zmj 閱讀(2190) 評論(0)  編輯 收藏 引用


只有注冊用戶登錄后才能發(fā)表評論。
網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            一区二区三区四区五区视频 | 中文亚洲欧美| 久久国产日韩| 牛人盗摄一区二区三区视频| 亚洲国产精品999| 欧美国产一区视频在线观看| 日韩视频一区二区三区在线播放免费观看 | 国产精品久久久久久亚洲毛片 | 亚洲三级电影全部在线观看高清| 亚洲欧洲在线一区| 亚洲精品综合| 国产精品一区二区三区观看| 久久人人精品| 一本色道久久综合亚洲精品婷婷| 宅男在线国产精品| 欧美中文字幕| 亚洲一区日本| 亚洲国产mv| 欧美自拍偷拍午夜视频| 亚洲日韩成人| 国产日韩欧美亚洲| 欧美激情中文不卡| 久久国产精品亚洲va麻豆| 亚洲专区国产精品| 好吊视频一区二区三区四区| 久久裸体视频| 夜夜嗨av色一区二区不卡| 一区二区在线视频播放| 国产精品美女久久久久久久 | 国产精品成人一区| 久久综合电影| 欧美在线一二三区| 欧美人与性禽动交情品| 久久综合九色| 国产欧美精品va在线观看| 国产精品久久久亚洲一区| 好吊色欧美一区二区三区四区| 亚洲精品一区二区在线观看| 久久久国产一区二区| 久久福利精品| 一区二区动漫| 欧美激情在线观看| 亚洲精品韩国| 美女视频网站黄色亚洲| 老司机凹凸av亚洲导航| 久久久精品tv| 亚洲深夜福利视频| 欧美另类变人与禽xxxxx| 伊人蜜桃色噜噜激情综合| 亚洲精品视频在线播放| 亚洲欧洲免费视频| 久久―日本道色综合久久| 国产精品美女主播| 一区二区三区不卡视频在线观看 | 国产精品综合视频| 亚洲手机成人高清视频| 久久蜜桃av一区精品变态类天堂| 国产美女扒开尿口久久久| 夜夜爽av福利精品导航| 亚洲大胆美女视频| 免费在线视频一区| 欧美伊久线香蕉线新在线| 国产精品成人v| 欧美区在线播放| 亚洲精品偷拍| 亚洲精品久久7777| 欧美激情一区在线观看| 一本一本久久| 亚洲精品久久嫩草网站秘色 | 日韩网站在线观看| 亚洲视频欧美视频| 国产综合色在线| 亚洲黑丝在线| 一本色道**综合亚洲精品蜜桃冫| 欧美激情综合色| 亚洲成人在线网| 久久人91精品久久久久久不卡| 亚洲成人在线视频播放| 亚洲精品日韩欧美| 亚洲啪啪91| 欧美午夜一区二区三区免费大片| 亚洲综合三区| 久久久夜精品| 国产日韩欧美一区二区三区在线观看| 午夜精品福利一区二区蜜股av| 久热爱精品视频线路一| 久久男人av资源网站| 99热免费精品| 亚洲欧美日韩爽爽影院| 欧美成人一区在线| 国产亚洲欧美激情| 一区二区三区视频在线观看| 99re6热在线精品视频播放速度 | 欧美日韩1080p| 国产亚洲欧美一区二区| 欧美超级免费视 在线| 欧美成人69| 亚洲一区自拍| 久久爱91午夜羞羞| 亚洲国产小视频| 亚洲欧美成人一区二区在线电影 | 亚洲精品中文字| 国产精品专区第二| 亚洲国产欧美另类丝袜| 亚洲欧美日韩区 | 羞羞色国产精品| 日韩亚洲欧美一区二区三区| 国产精品视频久久一区| 午夜精品福利一区二区蜜股av| 久久久精品国产免费观看同学| 国模 一区 二区 三区| 午夜激情一区| 一区二区三区四区精品| 亚洲电影免费在线观看| 亚洲日本成人女熟在线观看| 亚洲视频www| 国产免费观看久久黄| 亚洲精品欧美专区| 国产一区二区三区高清| 欧美影院精品一区| 久久乐国产精品| 欧美在线观看一二区| 国产一区二区三区的电影 | 久久国产一区| 欧美日本国产在线| 欧美一区二区视频在线观看2020| 欧美成人精品影院| 久久久福利视频| 国产视频观看一区| 中文精品视频| 亚洲视频香蕉人妖| 欧美精品1区2区3区| 欧美成人免费在线视频| 久久久久久久久久久久久久一区| 亚洲视频自拍偷拍| 欧美精品日日鲁夜夜添| 欧美超级免费视 在线| 在线观看亚洲专区| 麻豆国产精品一区二区三区| 亚洲九九精品| 欧美成人免费小视频| 美女免费视频一区| 在线观看亚洲一区| 蜜臀av在线播放一区二区三区| 美女黄毛**国产精品啪啪| 亚洲电影在线看| 欧美国产先锋| 99国产成+人+综合+亚洲欧美| 欧美日韩视频一区二区| 亚洲欧美bt| 久久一二三国产| 欧美国产第二页| 日韩视频一区二区在线观看 | 欧美夫妇交换俱乐部在线观看| 黄色成人av| 免费观看成人www动漫视频| 一区二区三区精品国产| 欧美精品一区三区| 亚洲人精品午夜| 亚洲影院免费| 国产一区二区三区网站| 久久综合网hezyo| 亚洲精品欧美在线| 午夜精品视频一区| 在线观看视频一区二区| 欧美另类极品videosbest最新版本| 艳女tv在线观看国产一区| 性感少妇一区| 亚洲高清在线| 国产精品欧美日韩久久| 久久久www免费人成黑人精品| 中文精品99久久国产香蕉| 欧美偷拍一区二区| 六月丁香综合| 一本一本久久a久久精品综合麻豆 一本一本久久a久久精品牛牛影视 | 欧美一区永久视频免费观看| 在线观看国产日韩| 欧美日韩精品一区二区天天拍小说| 亚洲一区二区少妇| 欧美国产亚洲另类动漫| 亚洲视频精选| 亚洲第一毛片| 国产精品毛片| 欧美不卡视频一区发布| 亚洲欧美国产制服动漫| 亚洲二区在线| 久久综合99re88久久爱| 国产一区成人| 欧美精品久久99| 久久九九国产精品| 亚洲性感美女99在线| 亚洲精品久久嫩草网站秘色| 国产欧美一区二区视频| 欧美色区777第一页| 欧美电影在线免费观看网站| 欧美一区二区三区男人的天堂| 欧美在线观看天堂一区二区三区| 亚洲精品久久嫩草网站秘色 | 欧美久久影院| 美女视频网站黄色亚洲|