原文鏈接 : http://www.cnblogs.com/effulgent/archive/2008/10/06/1305029.html
原文:
Realistic and Fast Cloud Rendering
NinianeWang
MicrosoftCorporation(nowatGoogleInc.)
niniane@ofb.net
November11,2003
最近在網上看到很多雲渲染的效果圖,但很多人吝於向人分享經驗知識,我不是很贊同這種想法,本來就是屬於別人的知識,自己有幸學習得到就應該拿出來分享。 廢話不多說了,這篇文章中所述的方法正是微軟飛行模擬2004采用的方法,也是CRYSIS中雲的實現方法,當然CRYSIS中有更多改進。感謝我前同事 提供原論文。
傍晚的雲彩
雲是構成室外場景的重要元素,這篇文章將講述利用在粒子上賦予紋理的方式來近視各種形態的雲彩,而且即使在漫天烏雲的情況下也能得到非常理想的運行效率,在光照着色方面我們給予美工最大的控制權,利用美術資源來獲取理想的光照效果,而不是傳統的利用簡單光照模型計算得到,這樣對於最終效果可控性會更強.同時我們還將講述模擬雲彩群聚和分散的效果。
真實的雲彩能讓室外場景精彩萬分,特別是在交互寫實的應用中尤為重要,好的雲彩系統必須能呈現各種形態各種密度,並且各方向都真實的雲,我們的系統必須滿足以下幾個要求: 1.必須高效,平台應用廣泛 2.要能很好的模擬雲彩的光照效果 3.雲彩需要運動起來才行。
傳統雲彩技術
很多技術用來對雲彩進行建模、動畫和渲染。比如最傳統的體渲染,利用程序生成的噪聲對一個橢球體紋理進行干擾,而着色計算也是基於真實的大氣條件,最大的缺點就是不可控,無論是噪聲生成的形態還是着色效果,然后就體渲染本身與多邊形3D還是有些差別,2者聚合在一起比較麻煩。
如果對體渲染雲彩感興趣的請參考:http://www.vrvis.at/via/resources/course-volgraphics-2004/
Course notes "Real-Time Volume Graphics", Course #28, Siggraph 2004
如果對純物理模擬感興趣的請參考:《Real-Time Cloud Simulation and Rendering》By Mark Jason Harris
我們雲彩如何建模?
我們利用5-400個精靈的ALPHA混合來渲染單朵雲彩,渲染時所有精靈都面對相機,聚合在一起形成一個具有3D分布的體積。然后我們需要依照相機距離來從后向前渲染他們,然而如何來建立這些精靈呢?我們選擇了一個能給與最終效果更好可控性的方式,傳統的程序生成方式,特別是來暴露了許多方程參數的調控讓美工痛苦萬分,而且並不能所見既所得。我們寫了個3DS-MAX插件,它能讓美工通過一系列的方盒來近似一個雲彩整體形狀,美工還能指定之后生成的精靈數量,這樣能控制雲的濃淡,還能設置生成精靈尺寸范圍,生成的精靈大部分是正方形的,當然也會用一些狹長的矩形來模擬雲際見最縹緲的部分,通常一個16平方公里的天空會用20-200個盒子來描述雲彩外行,而每個盒子根據雲彩濃淡又會最終生成1-100個精靈。導出時,插件會首先根據盒子范圍、雲彩密度等參數,生成一系列的精靈中心點,然后插件會遍歷精靈,將距離太近的精力合並消除,這樣能很好的提高效率,我們發現這個閥值指定在1/3精靈尺寸時在普通雲彩中能得到滿意效果,而稠密得雲彩則使用1/5~1/6尺寸。導出時,我們需要包含如下信息:精靈位置、尺寸(長寬)、旋轉(增加隨機性)、紋理以及着色信息(稍后詳述)。
我們使用什么樣得紋理呢?
我們綜合使用(不同數量比例,不同渲染參數,旋轉扭曲,拉伸)以上16種雲彩紋理來模擬各種截然不同得雲彩,這個圖時32位帶ALPHA通道得.比如使用較多得第4種紋理來模擬底部平坦得積雨雲,而第一排得其他3種霧一樣得紋理多用來模擬藍灰色調的稀薄層雲,最下兩排中飽滿膨脹的紋理則多用來模擬堆積雲,剩下的紋理則在所有類型的雲中都又應用.為了使用有限的16種紋理模擬盡可能多的雲彩,我們需要做更多的變換,比如隨即旋轉,一般的雲彩我們讓它在0~360范圍內隨機,而雨雲平坦的底部一般使用-5~5度.
在雲中飛翔我們需要做些什么?
我們的系統將為相機穿梭在雲層中提供真實的體驗,當相機穿過精靈后,精靈馬上從視野中消失,通常這能達到一個完美的效果,但如果相機穿過雲層的時候正在做變形動畫,可能就會在視覺上有一些不協調的突變。當我們首次實現這個解決方案的時候,我們讓精靈作為公告板始終面對相機平面,這樣就不會在相機運動過程中明顯感覺到精靈的邊界,當這樣有個很大的缺點,就時當相機離精靈很近的時候,精靈的旋轉會非常明顯,為了解決這個問題,我們決定當相機距離精靈距離小於精靈半徑的一半時,就不再旋轉精靈了,這樣能很好解決前面提到的精靈旋轉問題,但又引進了一個新問題,就是如果精靈旋轉被鎖定后,如果此時相機旋轉觀察精靈,此時精靈的邊界又會比較明顯了,最終我們決定根據相機觀察方向與精靈鎖定時的方向之間的夾角,來調節精靈的透明度。
雲彩如何生成為消亡?
雲能自然的生成和消亡將會極大的增加真實性,這里我們通過控制精靈ALPHA程度來完成雲彩的演化過程,我們通過精靈在雲中的位置來來決定頂點的透明程度,當雲形成時,我們首先只渲染位於雲中半徑一半范圍內的精靈,隨着時間流逝,慢慢減少他們的透明度,當透明度達到一個閥值時,我們才開始渲染半徑一半外的精靈。雲彩的消亡過程與此相反,當半徑一半之外的精靈基本全部透明后,開始增加半徑一半內精靈的透明度,需要注意的是,記得對更外面的精靈使用大一些的透明變化。
雲彩如何進行光照着色?
我們的着色模型中主要又兩個控制因子,天光和陽光。
天光的模擬
現實中,當光線穿過雲層時會被雲層的粒子散射和吸收,通常在均勻天光條件下,雲彩會呈現上白下暗的外觀,為模擬這個效果,美工首先定義5個顏色等級,每個顏色等級由一個RGBA顏色和高度組成。
美工可以使用不同的亮度等級來模擬不同類型的雲彩。使用方法見原文。美工還需要定義一個百分比等級來模擬一天不同時段的天光強度,比如中午的天光最強,晚上基本沒光了。最后計算流程如下:首先必須完成公告板的旋轉,讓他們面對相機,還有根據精靈與相機的遠近程度將精靈鎖定到相關角度,對於每個精靈的頂點,我們取它的高度分量,利用它在高度等級中對天光顏色進行插值,再利用當前游戲時間,插值得到當前天光百分比等級,將兩者相乘就得到了頂點得當前時間得天光顏色。
陽光的模擬
太陽會向天空中的雲彩投射方向光,特別是再黎明和黃昏,變化的陽光能讓雲彩更加生動,我們現在將模擬雲彩面向太陽光的部分與被向陽光部分的明暗。但我們不模擬雲彩之間,雲彩自身以及雲彩與場景中其他物體之間的遮擋與投影效果。美工再3DSMAX中會指定着色組,通常1~30個精靈為一組,每個BOX都有一個用戶屬性來指定這個BOX產生精靈所屬的着色組,每個組用來模擬現實雲彩中的緊密聚在一起的一簇,當我們為一個頂點着色時,首先計算其所屬着色組中心到這個頂點的向量,然后再計算所屬着色組中心到太陽的向量,將他們正規化后,進行點積,得到一個位於[-1, 1]之間得值,現在我們要將這個值映射到[Cmin, Cmax]之間,[-1, 0]映射到[Cmin, Cmed], [0, 1]映射到[Cmed, Cmax]。這樣單位雲簇從明到暗就有一個光滑得過渡,而Cmin Cmed Cmax均為亮度百分比,由美工指定,美工還會指定一天中太陽光變化T0->C0 T1->C1,給定一個時間,則頂點得顏色計算為:
C_sun = Func_map(v0*v1) * ( A * C0 + ( 1 – A ) * C1 ) A = (T1 – T) / (T1 – T0)
最終顏色為:
C_vertex = ( C_sky + C_sun ) * C_tex * Alpha_morph
如何優化性能?
主要再兩個方面,一個時頂點的位置計算和着色計算,第二個時GPU象素填充率 。文中提到使用了頂點信息預計算和八角形環代理紋理方式,這里不再詳述,請參看原文。
限制
我們的雲彩系統因為是體積分布的精靈,所以非常不適合做平面雲,如果要做高積雲等非常扁平的雲,可以直接使用紋理平面.因為所有的粒子再渲染前都做了從后向前的排序,這樣才可以得到正確的渲染效果,但當相機移動的時候,很可能導致渲染順序的改變,這樣再視覺上可能會由一些可以察覺的變化,特別是在太陽光分量比較重的黎明和黃昏,但這個問題還沒有嚴重到一定需要解決的地步。還有一些情況與現實不符,比如相機在雲彩中間時看到的雲比在外面看要更透明,因為有一半的精靈位於相機后面了,而現實並非如此。當相機靠近雲層后向下看,因為精靈都被垂直的鎖定了,所以我們將會看到大片無雲空白,一個建議的解決方案是當相機進入到雲彩中心的時候,給世界加上一個額外的霧化來增強雲的濃度。到此為止我們的雲沒有任何的動畫,現實中的雲一般都會隨氣流運動變形,我們可以通過旋轉和移動雲中的精靈來模仿被風擾動的效果,同樣我們可以通過透明掉其中部分精靈來改變雲的形狀等等,因為我們的雲沒有模擬對光的散射,雲彩自身不會投影也不會對其他物體產生投影,還有利用相對與太陽的夾角來評估光照是錯誤的,應該是根據陽光穿過雲層的距離和密度來估算,這樣我們就不能得到一些現實中得效果,比如在雲層后面觀察太陽能看到雲得光邊。