??? 摘 要: 針對低端嵌入式設(shè)備運(yùn)算速度較低,,存儲(chǔ)空間較小且不支持通用3D圖形庫的局限性,,通過分析常規(guī)3D渲染管線和算法,,對次要功能實(shí)施裁減,設(shè)計(jì)出一個(gè)簡化的3D圖形庫,。經(jīng)在低性能手機(jī)上測試,,此方案渲染效果良好,切實(shí)可行,。
??? 關(guān)鍵詞: 3D圖形庫,;渲染管線;嵌入式設(shè)備
?
?? 隨著計(jì)算機(jī)硬件技術(shù)的迅速發(fā)展與圖形渲染技術(shù)的不斷革新,,工業(yè)控制與消費(fèi)電子領(lǐng)域的嵌入式設(shè)備都已經(jīng)引入了3D顯示的功能,。嵌入式設(shè)備在具有體積小、功耗低,、適應(yīng)性強(qiáng)的優(yōu)勢的同時(shí),,也存在處理器運(yùn)算速度低,存儲(chǔ)空間小等諸多局限性,,而且部分低端設(shè)備并不支持通用的嵌入式3D圖形庫(如通用的OpenGL ES與手機(jī)平臺(tái)的Mobile 3D Graphics),。為了在此類設(shè)備上實(shí)現(xiàn)3D渲染與顯示,,需要深入分析常規(guī)3D渲染管線的實(shí)現(xiàn)過程,在此基礎(chǔ)上去掉一些次要的效果或功能,,最后設(shè)計(jì)簡化后的3D圖形庫,。
??? 與2D圖形顯示相比,3D渲染更為形象更接近現(xiàn)實(shí),,因?yàn)楹笳呒尤肓送敢曅Чc光影效果,。在有限的條件下,設(shè)備用戶往往對透視效果(如物體的縱深與遮擋)的需求遠(yuǎn)遠(yuǎn)大于光影效果(如光照與霧化處理),。因此,,簡化后的3D圖形庫需要保留最基本的透視效果,而去除表現(xiàn)光影效果的相關(guān)功能,。
1 3D渲染管線的裁減
??? 盡管3D渲染的具體流程隨圖形處理器與用戶需求的不同存在相當(dāng)?shù)牟町?,但大體上都要經(jīng)過坐標(biāo)變換、頂點(diǎn)與片段著色,、光照計(jì)算,、Alpha混合以及相關(guān)的剔除裁剪處理。OpenGL是目前應(yīng)用最為廣泛的底層3D圖形庫,,并已經(jīng)作為一個(gè)工業(yè)級(jí)的標(biāo)準(zhǔn),,它采用的渲染管線如圖1所示[1]。
?
1.1 頂點(diǎn)變換
??? 頂點(diǎn)變換的功能有:(1)頂點(diǎn)位置的坐標(biāo)變換,;(2)頂點(diǎn)光照的計(jì)算,;(3)頂點(diǎn)紋理坐標(biāo)的生成與變換。
??? OpenGL有2種坐標(biāo)變換矩陣:透視變換矩陣與模型視圖變換矩陣,,分別由2個(gè)獨(dú)立的堆棧維護(hù)[2],。由于3D坐標(biāo)變換是用矩陣相乘完成的,其時(shí)間復(fù)雜度為O(n3)且參與運(yùn)算的為浮點(diǎn)數(shù),,開銷較大,,所以將透視變換矩陣去掉,保留模型視圖變換矩陣,。在模型視圖變換以后,對每個(gè)頂點(diǎn)P(x,,y,,z)進(jìn)行以下處理,以模擬透視變換的縱深效果(距離越遠(yuǎn)的物體顯示越小):
??? x=Kx×y/z? y=Ky×y/z
??? 式中,,Kx,、Ky是可調(diào)整的縮放參數(shù),可以根據(jù)顯示屏幕的長寬進(jìn)行調(diào)整,。
??? 根據(jù)前面的分析,,直接去掉光照計(jì)算;保留紋理坐標(biāo)的生成,去掉紋理坐標(biāo)的變換(因?yàn)楹笳咧饕糜诩y理動(dòng)畫),。
1.2 圖元裝配
??? 這個(gè)階段需要計(jì)算片段在幀緩沖區(qū)的坐標(biāo)以及對片段各點(diǎn)進(jìn)行屬性插值,。片段各頂點(diǎn)的原始坐標(biāo)一般是浮點(diǎn)數(shù)表示的,而在幀緩沖區(qū)內(nèi),,像素坐標(biāo)是離散的整數(shù),,這是由顯示設(shè)備光柵的物理構(gòu)造決定的。對此可以簡單地通過將浮點(diǎn)坐標(biāo)取整的方式獲得幀緩沖區(qū)坐標(biāo),,下面主要討論插值算法,。
??? 插值算法有很多種,常用的有線性插值,、Hermite插值,、最小曲率插值等,其中線性插值執(zhí)行效率最高,,在精度要求較低的場合使用較為廣泛,。
??? 在較高性能的系統(tǒng)中(如PC機(jī)),插值運(yùn)算是由硬件(GPU)完成的,,插值運(yùn)算后還要經(jīng)過各種平滑濾波處理,,速度快且效果好。而對于嵌入式設(shè)備,,可以采用2次線性插值的方法來達(dá)到較為理想的效果:先由構(gòu)成片段的頂點(diǎn)屬性(位置坐標(biāo),、紋理坐標(biāo)、顏色等)計(jì)算片段邊界線上各點(diǎn)的屬性值,,同時(shí)用行掃描線算法得到片段覆蓋的有效區(qū)域內(nèi)每條掃描線的起止點(diǎn)坐標(biāo),;再對每條掃描線起止點(diǎn)之間的各點(diǎn)進(jìn)行屬性插值,最終計(jì)算出片段內(nèi)部所有點(diǎn)的屬性值,。
??? 例如,,由頂點(diǎn)P1(1,2,,3),、P2(6,3,,2),、P3(3,8,,1)構(gòu)成的片段,,先計(jì)算片段邊界線上各點(diǎn)的坐標(biāo)。以P1,,P2為例,,由于|x1-x2|>|y1-y2|,,所以利用x坐標(biāo)作參考量對y坐標(biāo)與z坐標(biāo)(即深度緩沖)進(jìn)行插值,即:
??? y=y1+(x-x1)×(y2-y1)/(x2-x1)
??? z=z1+(x-x1)×(z2-z1)/(x2-x1),,其中y1
??? 然后對每條掃描線2個(gè)邊界點(diǎn)之間的各點(diǎn)即片段內(nèi)部各點(diǎn)進(jìn)行屬性插值,,以第3條掃描線為例,它的起止點(diǎn)坐標(biāo)為(2,,4,2.333)與(5,,4,,1.8),,計(jì)算得到其間2點(diǎn)坐標(biāo)為(3,4,,1.977),、(4,4,,2.155),。整個(gè)運(yùn)算過程如圖2所示。
??? 對片段內(nèi)部各像素點(diǎn)的紋理坐標(biāo)和顏色進(jìn)行插值的算法與此類似,,其中顏色的插值又可以分為R,、G、B 3個(gè)通道進(jìn)行,。
1.3 片段紋理映射與著色
??? 如果紋理映射未開啟或當(dāng)前片段未綁定有效的紋理,,那么上階段插值得到的片段各點(diǎn)顏色值就是片段著色的結(jié)果;否則還需要利用上階段插值得到的各點(diǎn)紋理坐標(biāo)(通常稱為UV坐標(biāo))計(jì)算其顏色值,,其計(jì)算公式可以簡單表示如下:
??? Color=tex[int(u×texWidth)][int(v×texHeight)]
??? 式中,,tex是存儲(chǔ)紋理各像素顏色值的二維數(shù)組,因?yàn)???? 這樣簡單處理可能會(huì)帶來一些問題,例如一個(gè)面積很大的片段在映射一片面積較小的紋理區(qū)域時(shí),,會(huì)造成紋理貼圖因放大明顯分辨率不足而出現(xiàn)格狀,,而面積很小的片段在映射一片面積較大的紋理區(qū)域時(shí),又會(huì)造成片段內(nèi)頂點(diǎn)紋理坐標(biāo)不穩(wěn)定而出現(xiàn)畫面躁動(dòng),。這些現(xiàn)象都會(huì)影響視覺效果,。為此,OpenGL與Direct3D等通用3D圖形庫會(huì)根據(jù)實(shí)際情況采取一些修正措施,。
1.4 光柵操作
??? 以上步驟已經(jīng)完成了像素的定位,、頂點(diǎn)與片段的著色。在將這些信息發(fā)送到顯示屏幕之前,,還要進(jìn)行必要的測試,,以剔除不需要渲染的像素,這些測試主要包含[3]:(1)坐標(biāo)測試,;(2)Alpha測試,;(3)模板測試;(4)深度測試,。
??? 坐標(biāo)測試是將定位在顯示屏幕之外的點(diǎn)去掉,,這一步驟是必須保留的,;Alpha測試主要用于混色(blending)以達(dá)到一些特殊的半透明效果(如火焰),所以這一步驟應(yīng)該去掉,;模板測試主要用于制作鏤空,、鏡面、陰影等效果,,也應(yīng)該去掉,;深度測試用于決定各個(gè)頂點(diǎn)或物體之間的遮擋關(guān)系(x、y坐標(biāo)相同的條件下,,z坐標(biāo)即深度值較小的頂點(diǎn)覆蓋z坐標(biāo)較大的頂點(diǎn)),,予以保留[4]。
??? 經(jīng)過裁減后的3D渲染流程如圖3所示,。
1.5 硬件配置需求
??? 以顯示屏幕分辨率為200×200,、像素顏色深度與深度緩存深度均為16位(2字節(jié))的手持設(shè)備為例,根據(jù)裁減以后的渲染管線,,幀緩沖區(qū)由像素顏色緩存與深度緩存組成,,需求為200×200×2×2=160 KB,加上正弦,、余弦等函數(shù)表以及各類常數(shù)的存儲(chǔ),,設(shè)備的存儲(chǔ)空間至少要在200 KB以上。如果要渲染較為復(fù)雜的模型,,由于紋理貼圖與骨骼動(dòng)畫關(guān)鍵幀信息還需要更多的空間,,則存儲(chǔ)空間須在1 MB以上,處理器頻率至少要在50 MHz以上,。
2 軟件解決方案
2.1 3D模型數(shù)據(jù)結(jié)構(gòu)的簡化
??? 當(dāng)前3D模型在計(jì)算機(jī)中大多是用網(wǎng)格(mesh)表示與存儲(chǔ)的,,而每個(gè)網(wǎng)格又由若干個(gè)三角形組成,同時(shí)每個(gè)三角形又由3個(gè)頂點(diǎn)(vertex)組成,,頂點(diǎn)數(shù)據(jù)包含位置坐標(biāo),、紋理坐標(biāo)、頂點(diǎn)顏色等信息,,這樣就構(gòu)成了網(wǎng)格-三角形-頂點(diǎn)的三級(jí)結(jié)構(gòu),。由于1個(gè)頂點(diǎn)會(huì)同時(shí)被幾個(gè)三角形包含,為了避免重復(fù)存儲(chǔ),,三角形并不存儲(chǔ)所含3個(gè)頂點(diǎn)的詳細(xì)信息,,而僅僅存儲(chǔ)3個(gè)頂點(diǎn)的索引;而每個(gè)網(wǎng)格除了它所包含的三角形信息外還要存儲(chǔ)紋理貼圖,,材質(zhì)等多種信息,,為了防止結(jié)構(gòu)體過于龐大,一般不直接存放每個(gè)三角形的詳細(xì)信息而只存放三角形的索引[5]。
使用這樣的結(jié)構(gòu),,每渲染1個(gè)頂點(diǎn)實(shí)際上只要經(jīng)過2層索引查找操作,,因?yàn)榫W(wǎng)格含有的材質(zhì)信息與三角形含有的法線向量數(shù)據(jù)(均用于光照計(jì)算)并不需要,所以將上述三級(jí)結(jié)構(gòu)簡化為網(wǎng)格-頂點(diǎn)二級(jí)結(jié)構(gòu),,如圖4所示。這樣既簡化了數(shù)據(jù)結(jié)構(gòu)節(jié)省了存儲(chǔ)空間,,又提高了編程效率,。
2.2 浮點(diǎn)運(yùn)算的模擬
??? 一些低端嵌入式設(shè)備(如基于ARM7的微控制器系統(tǒng)與CLDC1.0版本的手機(jī))不支持浮點(diǎn)數(shù),而浮點(diǎn)運(yùn)算貫穿于整個(gè)3D渲染過程,,所以必須用定點(diǎn)數(shù)表示浮點(diǎn)數(shù)并模擬浮點(diǎn)運(yùn)算,。
??? 以long型(4個(gè)字節(jié))為例,可以劃分8位表示指數(shù),,其余24位表示尾數(shù),,每次運(yùn)算以后都要進(jìn)行規(guī)格化以便保存。這是IEEE的float型運(yùn)算的軟件實(shí)現(xiàn),,精度較高但需要耗費(fèi)較多的時(shí)間,。
??? 對此可采用另一種精度較低但更為快速的方法——小數(shù)掩碼法,即將定點(diǎn)數(shù)的最后若干位劃為小數(shù)位,,每次乘法運(yùn)算后將結(jié)果右移相應(yīng)位數(shù),,每次除法運(yùn)算前將被除數(shù)左移相應(yīng)位數(shù),而加減運(yùn)算規(guī)則不變,。小數(shù)位劃分越多運(yùn)算結(jié)果越精確,,反之可表示數(shù)的范圍越大。本文取8位作小數(shù)位,,運(yùn)算精度為1/28,,可以滿足一般的要求,同時(shí)可以保證整數(shù)部分在進(jìn)行乘法時(shí)不會(huì)越界,,這是因?yàn)榍度胧皆O(shè)備顯示屏幕一般分辨率較小(長寬均小于28=256),,而相乘后整數(shù)部分有效位不會(huì)超過16位,小數(shù)部分有效位也不會(huì)超過16位,,運(yùn)算結(jié)果用4字節(jié)32位的long型即可存儲(chǔ),。此外,小數(shù)掩碼法附加的運(yùn)算都是移位運(yùn)算,,硬件執(zhí)行效率較高,。
2.3 幀緩沖區(qū)的設(shè)計(jì)
??? 幀緩沖區(qū)是3D渲染過程的終點(diǎn),由于不需要模板緩存與像素的Alpha值,,這段區(qū)域僅由像素顏色緩存與深度緩存組成,。
??? 像素的顏色格式有很多種,如RGB、ARGB,、YUV等,,PC機(jī)平臺(tái)常用的32位ARGB真彩色可以充分滿足人眼的視覺需求。但考慮到嵌入式設(shè)備存儲(chǔ)空間有限,,故采用16位ARGB 1555加強(qiáng)色格式,,每個(gè)像素占用16位2個(gè)字節(jié)的空間,RGB每個(gè)顏色通道各占用5位,,另留1位作為Alpha標(biāo)記,,用于表示該像素是否透明,進(jìn)而可以表現(xiàn)紋理貼圖邊緣的不規(guī)則形狀,。
??? 深度緩存根據(jù)需要可以設(shè)置為16位,、24位、32位等,,在嵌入式設(shè)備上采用16位便可以滿足需求,。如果設(shè)備不支持浮點(diǎn)數(shù),可以用小數(shù)掩碼法用短整數(shù)來表示,,劃分低8位作小數(shù)位,。
??? 本文從分析常規(guī)3D渲染管線出發(fā),結(jié)合低端嵌入式設(shè)備處理器運(yùn)算速度較低,,存儲(chǔ)器空間較小且不支持現(xiàn)有通用3D圖形庫的局限性,,提出了一種經(jīng)過功能裁減后的渲染方案并計(jì)算所需的硬件最低配置需求,最終完成簡化3D圖形庫的設(shè)計(jì),。這種圖形庫去除的是一些需要耗費(fèi)大量運(yùn)算時(shí)間與存儲(chǔ)空間的光照,、霧化、半透明,、陰影,、粒子等光影效果,而保存了3D圖形基本特征與透視效果,,所以仍然能夠滿足設(shè)備用戶的一般視覺需求,。此外,本文針對軟件設(shè)計(jì)中的幾個(gè)問題進(jìn)行了討論,,并給出了解決的方案,。
參考文獻(xiàn)
[1] OpenGL Pipeline Overview[DB/OL]. http://www.lighthouse3d.com.
[2] Nehe, OpenGL Tutorials[DB/OL]. http://nehe.gamedev.net.
[3] OpenGL編程指南(第四版)[M].鄧鄭祥,,譯.北京:人民郵電出版社,,2005.
[4] 唐澤圣,周嘉玉,,李新友.計(jì)算機(jī)圖形學(xué)基礎(chǔ)[M].北京: 清華大學(xué)出版社,,1995.
[5] MILLER J R. Vector geometry for computer graphics[J]. Computer Graphics, 1999,19(3):66-73.