劉賢梅,王 偉,薛繼偉 (東北石油大學(xué)計(jì)算機(jī)與信息技術(shù)學(xué)院,黑龍江大慶1 6331 8)
對火焰等景物進(jìn)行仿真模擬一直是計(jì)算機(jī)圖形學(xué)研究中的熱點(diǎn)課題[1]。由于這些形狀不規(guī)則物體都具有實(shí)時變化的特征,并且含有豐富的細(xì)節(jié),因此很難用傳統(tǒng)的造型方法來表現(xiàn)。
粒子系統(tǒng)是模擬復(fù)雜的、運(yùn)動的、不規(guī)則物體非常有效的一種圖形生成技術(shù)[2]。以往的粒子系統(tǒng)的計(jì)算完全是在CPU上完成的。由于CPU的任務(wù)繁多,因此在實(shí)際運(yùn)算的時候常常出現(xiàn)顯卡等待CPU數(shù)據(jù)的情況,影響了繪制速度[3]。針對以上問題,筆者在進(jìn)行油田井口事故火焰實(shí)時仿真時將粒子系統(tǒng)的所有計(jì)算完全放入GPU中,在GPU中完成粒子屬性的更新和繪制,不需要每次更新時從CPU中讀取粒子數(shù)據(jù)進(jìn)行繪制。因此,減少了粒子系統(tǒng)更新中GPU和CPU之間的頻繁通信、系統(tǒng)內(nèi)存和顯存間的頻繁數(shù)據(jù)傳送,降低CPU的負(fù)擔(dān),使粒子系統(tǒng)達(dá)到更高的實(shí)時性和高仿真性。
為每個粒子定義一個頂點(diǎn),目的是可以在屏幕上顯示粒子的屬性值,從而實(shí)現(xiàn)火焰的模擬。頂點(diǎn)結(jié)構(gòu)定義如下:
Postion是頂點(diǎn)最終繪制在屏幕上的位置,在Vertex Shader中對其進(jìn)行賦值。
Coords是頂點(diǎn)所對應(yīng)的屬性紋理的紋理坐標(biāo)。
在CPU上二維網(wǎng)格表現(xiàn)為一個數(shù)組,而在GPU中二維網(wǎng)格則表現(xiàn)為一張紋理,紋理具有GRBA 4個通道,提供了一個天然的數(shù)據(jù)結(jié)構(gòu)。最基本的運(yùn)算是二維網(wǎng)格上數(shù)據(jù)的讀取,在GPU中使用紋理查詢來完成。CPU中數(shù)組的偏移對應(yīng)GPU中紋理的紋理坐標(biāo)。
根據(jù)以上分析,把粒子屬性數(shù)據(jù)存儲到紋理中。油田井口事故火焰粒子中最重要的屬性是位置和速度。由于速度精度低,使用16位的浮點(diǎn)格式紋理存儲速度;位置的精度相對比較高,使用32位浮點(diǎn)格式紋理存儲位置數(shù)據(jù)?;鹧媪W拥钠渌麑傩匀缟?、顏色值、透明度都使用16位的浮點(diǎn)格式紋理存儲。
由于受當(dāng)前圖形硬件的限制,同一個紋理不能同時被寫入和讀出,因而更新后的屬性不能存儲到原有紋理中。要解決上述問題,需要引入雙緩存技術(shù)。每個屬性都需要2張具有相同大小和格式的紋理。首先將其中一塊作為輸入,另一塊作為輸出。在下一幀的計(jì)算中,輸入緩沖區(qū)變?yōu)檩敵?輸出緩沖區(qū)變?yōu)檩斎?。存儲方式如圖1所示。
圖1 粒子屬性存儲方式
為了計(jì)算火焰粒子運(yùn)動,對每個粒子定義如下屬性紋理:①2張16位的浮點(diǎn)格式速度紋理 VelTex:分別存儲前一幀和下一幀粒子的速度。②2張32位浮點(diǎn)格式位置紋理PosTex:分別存儲前一幀和下一幀粒子的位置。③2張 16位的浮點(diǎn)格式生命紋理AgeTex:分別存儲前一幀和下一幀粒子的生命值。④2張16位的浮點(diǎn)格式顏色紋理ColTex:分別存儲前一幀和下一幀粒子的顏色值。⑤2張16位的浮點(diǎn)格式透明度紋理tranTex:分別存儲前一幀和下一幀粒子的透明度。⑥1張初始位置紋理InitPosTex,存儲每個粒子的初始位置。⑦1張初始速度紋理InitVelTex,存儲每個粒子的初始速度。
著火極限、著火溫度和燃燒速度,常統(tǒng)稱為火焰3要素。油田井口發(fā)生火災(zāi)具有燃燒速度快、火焰溫度高、易發(fā)生爆炸和火勢極易蔓延的特點(diǎn)。因此,用粒子系統(tǒng)模擬油田井口事故火焰時應(yīng)突出上述特點(diǎn)。
1)火焰粒子的產(chǎn)生 油田井口事故火焰粒子系統(tǒng)產(chǎn)生粒子的過程即對新粒子的屬性進(jìn)行初始化。在該系統(tǒng)中,由于火焰是從井口中產(chǎn)生的。井口相當(dāng)是一個圓柱體,采用了一種新的方法實(shí)現(xiàn)粒子的發(fā)射源,即用Y值確定井口的高度,用θ和X軸之間的夾角確定井口表面的任何一點(diǎn)作為粒子的發(fā)射器。如圖2所示。
圖2 粒子發(fā)射器
Velocity為粒子的速度值,f為粒子速度的大小。火焰粒子發(fā)射速度的3個分量為:①粒子沿X軸、Y軸和Z軸方向的速度值分別為Velocity.x=f*cosθ、Velocity.y=f和Velocity.z=f*sinθ。
2)火焰粒子的初始位置及速度 火焰粒子的初始位置及速度是實(shí)現(xiàn)動態(tài)火焰必不可少的因素。Centerpos、VarPos、Velocity和VarSpeed是粒子系統(tǒng)中的4個系統(tǒng)參數(shù),分別表示粒子的火焰燃燒的中心位置、位置變化范圍、粒子的平均速度和速度變化范圍。初始位置和速度的設(shè)置分別如下:
3)火焰粒子的貼圖 粒子的貼圖對火焰的外觀極為重要。石油著火焰色反應(yīng)表現(xiàn)為火焰中外焰溫度最高顯紅火黃色,內(nèi)焰溫度稍低顯黃色并有一定的透明度。由于外焰和內(nèi)焰的顏色不一樣,因而通過著色語言對所屬范圍的粒子顏色屬性和透明度屬性做不同的賦值。著色語言如下:
為了盡量使模擬的火焰逼真,采用真實(shí)的油田井口事故火焰的照片并進(jìn)行處理,截取火焰的內(nèi)焰和外焰的貼圖,對火焰粒子的所屬內(nèi)焰和外焰分別進(jìn)行貼圖,以達(dá)到最佳火焰模擬效果。火焰粒子內(nèi)焰和外焰的貼圖分別如圖3和圖4所示。
圖3 內(nèi)焰貼圖
圖4 外焰貼圖
4)火焰粒子大小 粒子的大小決定了火焰模擬的精細(xì)程度。粒子過大,火焰失真;反之,系統(tǒng)的實(shí)時性較差。采用四邊形面片表示火焰粒子,當(dāng)繪制離井口中心較遠(yuǎn)的火焰時,使用較大的粒子;當(dāng)繪制離井口中心較近的火焰時,使用較小的粒子。粒子大小定義如下:
5)火焰粒子數(shù)量 粒子的數(shù)量決定了火焰的密度,由于油田井口事故火焰的火勢比較兇猛,因此模擬火焰需要大量的粒子才能達(dá)到更加逼真的效果。根據(jù)屏幕上每單位區(qū)域產(chǎn)生粒子數(shù)目的平均值(AveNumber)和顯示區(qū)域 (Area)粒子大小 (Size),確定初始時刻產(chǎn)生的粒子數(shù)量 (Number):
6)粒子屬性數(shù)據(jù)的更新 火焰粒子屬性的更新可以通過編寫像素著色器實(shí)現(xiàn)。根據(jù)分析油田井口事故火焰粒子的運(yùn)動模型,通過shader編程完成粒子速度、位置的更新計(jì)算,最后將計(jì)算的結(jié)果以輸出流的形式渲染到輸出紋理緩沖區(qū)中。用粒子的當(dāng)前速度v(t)和時間增量(Δt)來確定粒子一幀經(jīng)過的距離。該距離加上粒子的當(dāng)前位置p(t)可得出其下一個位置p(t+Δ t)。通過將當(dāng)前加速度值a(t)加上當(dāng)前速度v(t)可將粒子的速度更新?;鹧媪W拥奈恢谩⑺俣?、加速度的計(jì)算公式分別為:
7)粒子的消亡 油田井口事故火焰的高度由粒子的生命決定,因而賦給粒子生命值 (Li f e)一個初始值,把Li fe值存儲到紋理中的a通道中,隨著粒子的運(yùn)動,Lif e值不斷減小。當(dāng)減小到值等于零時,將該粒子設(shè)定為死亡。如果從a通道取出的生命值是負(fù)數(shù),可將生命值截取為0,如果生命值大于1,截取為1。用all函數(shù)判斷 li f e值是否為零,若li fe值為零,則粒子消亡:isdead=all(saturate(tex2D(SamPrePosition,t0).a))。
使用渲染到頂點(diǎn)緩沖區(qū)的方法實(shí)現(xiàn)粒子的繪制[6]。紋理中的像素和頂點(diǎn)數(shù)據(jù)都以數(shù)組的形式存儲在顯存中。紋理中的像素?cái)?shù)據(jù)是按照紋理的形式存儲的二維數(shù)組,而頂點(diǎn)數(shù)據(jù)是按照頂點(diǎn)的形式存儲的一維數(shù)據(jù)。Render to vertex buffer原理就是清除紋理中像素的固有解釋方式,以頂點(diǎn)的形式重新解釋這些數(shù)據(jù),使GPU可以直接從渲染目標(biāo) (紋理)中讀取頂點(diǎn)數(shù)據(jù),用于渲染[6]。
圖4 試驗(yàn)結(jié)果截圖
該試驗(yàn)使用的顯卡為NVIDIA GeForce GT 240M,顯卡顯存512MB,開發(fā)工具為Virtools,試驗(yàn)結(jié)果截圖如圖4所示,圖4顯示火焰效果逼真。
對基于CPU和基于GPU 2種算法的幀率進(jìn)行比較 (見表1)。從表1可以看出,當(dāng)粒子數(shù)比較少的時候,2種算法的幀率沒有太大區(qū)別;當(dāng)粒子數(shù)逐漸增多的時候,2種算法的幀率則產(chǎn)生明顯區(qū)別。如當(dāng)粒子數(shù)為160000時,基于CPU算法的幀率為4幀/s,而基于GPU算法的幀率為90幀/s,其模擬火焰的效果逼真,能滿足人們正常的視覺效果。
表1 基于CPU和基于GPU 2種算法的幀率的比較
筆者提出了一種基于GPU和粒子系統(tǒng)實(shí)現(xiàn)油田井口事故火焰的模擬方法。該方法具有較高的計(jì)算速度,能夠進(jìn)行大規(guī)?;鹧娴睦L制,且模擬火焰的效果逼真。但該方法也有需要完善之處,即進(jìn)一步優(yōu)化GPU算法和實(shí)現(xiàn)火焰粒子間碰撞檢測算法。
[1]金小進(jìn),馬堯海.基于粒子系統(tǒng)的火焰模擬與優(yōu)化 [J].計(jì)算機(jī)工程與設(shè)計(jì),2010,31(5):1118-1120.
[2]Akeninemoller T,Haines E,Hoffman N.Real-time Rendering[M].2thed.Wellesley.Massachusetts:A.KPETERSLtd,2002.
[3]許楠,郝愛民,王莉莉.一種基于GPU的粒子系統(tǒng) [J].計(jì)算機(jī)工程與應(yīng)用,2009,42(19):77-79.