摘 要:陰影分為硬陰影和軟陰影。在3D計(jì)算機(jī)圖形系統(tǒng)中,陰影體算法曾一度用來生成硬陰影,然而需要耗費(fèi)大量的渲染時(shí)間才可以使軟陰影變?yōu)楝F(xiàn)實(shí)。采用沿著硬陰影的輪廓邊渲染半影楔子來生成軟陰影的方法實(shí)現(xiàn)實(shí)時(shí)動(dòng)態(tài)陰影,利用了當(dāng)前圖形硬件的支持來完成算法優(yōu)化,其中深度限制和Shader Model 3.0 像素著色器優(yōu)化可以增加陰影算法的性能。最后把陰影算法應(yīng)用到Torque游戲引擎中。
關(guān)鍵詞:陰影算法; 軟陰影; 硬陰影; 游戲引擎; TGE
中圖分類號(hào):TP391.9 文獻(xiàn)標(biāo)識(shí)碼:B
文章編號(hào):1004-373X(2010)12-0107-04
Realization of Real-time Dynamic Shadow Algorithm and Its Application in TGE
GAO Li-na,HAN Li-yan
(Department of Public Compute, Bohai University, Jinzhou 121000,China)
Abstract:There are two types of shadow: hard shadow and soft shadow. In the 3D computer graphics system, the shadow volumes algorithm was used to generate hard shadows at some time in the past, and soft shadows were generated by time-consuming rendering. The real-time dynamic shadow is generated by the way of the penumbra wedge rendering along outline rendering of the shadow with hard edges. The method is optimized by using the current graphics hardware, and the shadow performance is increased by the depth bound and Shader Model 3.0 pixel shader optimization. Finally the shadow algorithm is applied to the Torque game engine.
Keywords:shadow algorithm; soft shadow; hard shadow; game engine; TGE
3D游戲引擎的功能[1]可分以下幾個(gè)部分:光影效果;動(dòng)畫;提供物理系統(tǒng);碰撞檢測(cè);渲染;負(fù)責(zé)玩家與電腦之間的溝通。
陰影在3D游戲中起著至關(guān)重要的作用,加入陰影效果后,增加了圖像的立體感和層次感,提高虛擬環(huán)境的真實(shí)感程度,對(duì)于理解三維物體的幾何信息有著重要的作用;有助于理解物體間的相互位置關(guān)系和大小;有助于理解復(fù)雜遮擋物的幾何形狀;有助于理解復(fù)雜接收體的幾何信息。
1 硬陰影和軟陰影
陰影可分為硬陰影和軟陰影。對(duì)陰影來說一種最簡(jiǎn)單的情況就是硬陰影,也就是說場(chǎng)景中的點(diǎn)只有在陰影中或在陰影之外兩種狀態(tài)。這種陰影只有在一個(gè)點(diǎn)光源的照射下才可能存在,然而在現(xiàn)實(shí)中并不多見,這使得硬陰影降低了圖像的真實(shí)感。
軟陰影比硬陰影有多得多的真實(shí)感。特別是軟陰影的半影區(qū)域(如圖1所示,3種顏色的亮源被遮擋后,形成3個(gè)相交的陰影體)可以根據(jù)光源,遮擋物,接收者之間相互的位置關(guān)系進(jìn)行變化。在計(jì)算機(jī)圖形中,當(dāng)光源和遮擋物的距離遠(yuǎn)遠(yuǎn)大于遮擋物和接收者之間的距離的時(shí)候,我們可以用點(diǎn)光源來近似一些較小的光源。對(duì)于其他情況,使用軟陰影可以帶來更為真實(shí)的效果。
圖1 軟陰影和硬陰影
2 實(shí)時(shí)動(dòng)態(tài)軟陰影算法的實(shí)現(xiàn)
2.1 算法概述
實(shí)時(shí)動(dòng)態(tài)軟陰影算法結(jié)合使用了Assarsson的軟陰影算法[2-3]和Everitt、Kilgard的硬陰影算法[4],采用沿著硬陰影的輪廓邊渲染半影楔子來生成軟陰影的方法實(shí)現(xiàn)實(shí)時(shí)動(dòng)態(tài)陰影。
輸入:表現(xiàn)3D場(chǎng)景的多邊形模型和光源列表。
輸出:在幀緩沖區(qū)中輸出正確的陰影貼圖。
首先在幀緩沖區(qū)中渲染環(huán)境貼圖(場(chǎng)景中沒有投射光源),對(duì)于當(dāng)前每個(gè)光源計(jì)算其陰影貼圖,然后計(jì)算帶有光照信息的陰影貼圖。
具體實(shí)現(xiàn)過程如圖2所示,在實(shí)現(xiàn)過程中采用screen-to-texture 傳遞,而原始軟陰影算法采用單獨(dú)的v-buffer進(jìn)行交換,且在offscreen中存在拷貝紋理。雖然這樣速度很快,但是需要昂貴的交換。清除了所有交換需求而且很容易的在屏幕上完成實(shí)時(shí)繪制,這種方法可以與Everitt和Kilgard的硬陰影算法更好的兼容。
圖2 實(shí)現(xiàn)過程
在實(shí)現(xiàn)陰影時(shí),可以簡(jiǎn)單地累加投射的光源,形成臨時(shí)的屏幕紋理,不管場(chǎng)景中有多少光源都可以。
2.2 生成硬陰影體
硬陰影體算法能夠在當(dāng)前場(chǎng)景中生成由遮擋而產(chǎn)生的陰影,用一個(gè)完全閉合的多邊形模型來表示遮擋物,如圖3所示。
圖3 確定輪廓線
每個(gè)輪廓線從光源向無窮遠(yuǎn)處延伸,生成一個(gè)四邊形(見圖4)。其中頂點(diǎn)被指定為無窮遠(yuǎn)是通過應(yīng)用OpenGL中的4D相似變換,它是由相應(yīng)的w值區(qū)分x,y,z值的3D變換(一個(gè)矩形的頂點(diǎn) w=1,無窮遠(yuǎn)處w=0和x,y,z指向無窮遠(yuǎn)處頂點(diǎn)的位置)。在這種情況下,如果輪廓線由頂點(diǎn)e和f表示,光源的位置由l表示,那么無窮遠(yuǎn)處的2個(gè)頂點(diǎn)由e′= (ex-lx, ey-ly,ez-lz, 0)和f′= (fx-lx,fy-ly,fz-lz, 0)表示。當(dāng)繪制這個(gè)四邊形時(shí),必須按照順時(shí)針方向e,e′,f′,f。這樣就構(gòu)成了一個(gè)陰影體[5]。它由面向光源的物體多邊形,輪廓邊四邊形和背向光源的物體多邊形投射到無窮遠(yuǎn)處的多邊形組成的。
圖4 硬陰影體
2.3 構(gòu)造半影楔子
半影楔子定義為一個(gè)由輪廓線圍成的半影區(qū)[6]。在構(gòu)造半影楔子時(shí)采用線性代數(shù)的方法處理球形光源產(chǎn)生陰影(如圖5所示):給定邊e和f的兩個(gè)頂點(diǎn)和光源位置l形成一個(gè)順時(shí)針方向三角形。三角形的法線向量 n 通過(e-l)×(f-l)計(jì)算得到,標(biāo)準(zhǔn)化向量為已得到向量的單位長(zhǎng)度。附加向量 m 通過從e到f標(biāo)準(zhǔn)化向量得到。最后,m 和 n 叉乘的結(jié)果作為向量 o ,向量 o 平行于這兩個(gè)向量并向下指向輪廓邊的位置。向量 n ,m和o 通過光源半徑進(jìn)行縮放。圖5中,向量 n ,m和o 是由光源中心產(chǎn)生的;且這三個(gè)向量與球體是無關(guān)的。
圖5 計(jì)算內(nèi)部一半的半影楔子
如果增加向量 n ,m和o 到l,那么就會(huì)產(chǎn)生一個(gè)新的頂點(diǎn)p形成和e形成一條直線。這條直線與三角形的一邊封閉了左邊硬陰影內(nèi)的半影楔子。由于楔子延伸到無窮遠(yuǎn)處,在這條直線上無窮遠(yuǎn)處的頂點(diǎn)通過相似變換(ex-px,ey-py,ez-pz,0)將被指定為e′ ′ ′。然后增加向量 m和o 到l得到頂點(diǎn)跟e形成另外一條直線,表示左邊封閉三角形另外的處于硬陰影內(nèi)的半影楔子,在這條直線無窮遠(yuǎn)處的頂點(diǎn)被指定為e″。處于硬硬陰影內(nèi)的半影楔子的左邊封閉的三角形指定為e,e′ ′ ′和e″。
右邊處于硬陰影內(nèi)的半影楔子的三角形可以通過f和- m 分別代替上述的e和 m ,新產(chǎn)生的向量指定為f′ ′ ′和f″。最后,封閉的e,e″,f″和f組成前面四邊形;f,f′ ′ ′,e′ ′ ′和e組成背面多邊形;f″,e″,e′ ′ ′和f′ ′ ′作為底部多邊形。
以上就是計(jì)算硬陰影內(nèi)半影楔子的過程。硬陰影外半影楔子的計(jì)算可以通過交換e和f完成。需要注意的是硬陰影內(nèi)的半影楔子的e″和f″與硬陰影外的半影楔子的f″和e″是一樣的。
2.4 渲染半影楔子
渲染半影楔子實(shí)際上就是計(jì)算在楔子里的每個(gè)像素的可見值。這個(gè)算法的基本原理是渲染每個(gè)半影楔子到屏幕上,并應(yīng)用基于硬件的像素著色器在v-buffer中轉(zhuǎn)化成可見值[7]。
渲染時(shí),半影楔子覆蓋了投射到場(chǎng)景中的2-D區(qū)域。這樣并不能覆蓋3-D半影楔子的全部像素。為了避免像素著色器渲染這些頂點(diǎn),應(yīng)用了模板緩沖器來遮罩那些不在半影楔子的頂點(diǎn)。以下是渲染半影楔子的算法描述:
輸入:z-buffer,frame buffer,預(yù)計(jì)算的深度紋理,遮擋物,光源位置和半徑;
輸出:在給定的遮擋物和光源的情況下,構(gòu)造軟陰影到frame buffer中。
對(duì)于每個(gè)半影楔子:
(1) 構(gòu)造半影楔子應(yīng)用2.3節(jié)給出的方法。
(2) 渲染面向觀察者的半影楔子多邊形到模板緩沖器中(初始值為0)。因此,如果半影楔子中的像素相對(duì)于屏幕遠(yuǎn)離觀察者范圍,則設(shè)置模板緩沖器的值為1。
(3) 設(shè)置渲染半影楔子的像素著色器可用,輸入當(dāng)前輪廓邊的頂點(diǎn)、光源的位置和半徑及預(yù)計(jì)算的深度紋理。
(4) 每個(gè)半影楔子內(nèi)既遠(yuǎn)離觀察者相對(duì)于屏幕,又在模板緩沖器中的值為0的像素,在frame buffer中渲染這些背向觀察者的半影楔子多邊形。當(dāng)繪制背向三角形時(shí),模板緩沖器中像素的值要清零,為了繪制下一個(gè)半影楔子,模板緩沖器也要清零。
為了取得更好的效率和簡(jiǎn)化運(yùn)算,采用RGBA buffer 來代替構(gòu)造加減運(yùn)算器的v-buffer。每個(gè)像素的紅色、綠色信息存儲(chǔ)的加法運(yùn)算器,藍(lán)色和alpha信息存儲(chǔ)到減法運(yùn)算器中。浮點(diǎn)數(shù)用以下公式分成2個(gè)8位值,通過編碼找到紋理信息。
upperValue=(floor(8)×coverage)/256
lowerValue=(fract(8)×coverage)/256
式中:floor() 表示輸入值的整數(shù)部分;fract()表示輸入值的小數(shù)部分;平均值定義在[0.0,1.0]范圍內(nèi)。這個(gè)公式確保8位小數(shù)值和4位整數(shù)值(原來的公式是12位小數(shù)值和5位整數(shù)值)。
3 實(shí)時(shí)動(dòng)態(tài)陰影在TGE引擎中的應(yīng)用
TGE(torque game engine)是Garage Games公司的游戲引擎,該引擎功能強(qiáng)大,能實(shí)現(xiàn)火、霧、水等虛擬三維效果,提供強(qiáng)大的交互功能,支持各類三維游戲的開發(fā)。
3.1 在TGE中實(shí)現(xiàn)實(shí)時(shí)動(dòng)態(tài)陰影
算法實(shí)現(xiàn)步驟:
(1) 在幀緩沖區(qū)中渲染環(huán)境貼圖。
首先設(shè)置深度函數(shù)以渲染在深度緩沖區(qū)中比當(dāng)前像素更近的像素;清空幀緩沖區(qū)和深度緩沖區(qū),在幀緩沖中渲染場(chǎng)景周圍的所有模型。
(2) 對(duì)當(dāng)前每個(gè)光源計(jì)算其陰影貼圖。
如果軟陰影不可用,就清空模版緩沖區(qū),陰影繪制將從幀緩沖區(qū)交換到模版緩沖區(qū);否則,在保存好幀緩沖區(qū)的內(nèi)容后,清空它。
允許深度函數(shù)渲染在深度緩沖區(qū)中比自己當(dāng)前像素遠(yuǎn)的像素;渲染硬陰影體的遮擋物;如果軟陰影可用,渲染遮擋物的半影楔子。
(3) 計(jì)算帶有光照信息的陰影貼圖。
如果軟陰影不可用,陰影繪制將從模版緩沖區(qū)交換到幀緩沖區(qū)中,附加的混合是可用的,模版測(cè)試不允許配置像素是非零的。否則,保存陰影紋理清空幀緩沖區(qū);設(shè)置深度函數(shù)允許渲染與當(dāng)前像素同深度的像素;在幀緩沖區(qū)中渲染所有受當(dāng)前光源影響到的模型。如果用戶只渲染硬陰影,模版測(cè)試將有效的遮擋陰影區(qū)域;如果軟陰影可用,在幀緩沖區(qū)中應(yīng)用陰影紋理,這樣可以調(diào)節(jié)當(dāng)前屏幕上的圖像與陰影紋理的內(nèi)容。然后,場(chǎng)景紋理也加到當(dāng)前屏幕上了,如此完成了環(huán)境貼圖在當(dāng)前與先前光源的混合。
在頂點(diǎn)著色器中,為了實(shí)現(xiàn)深度判斷,必須將當(dāng)前頂點(diǎn)位置經(jīng)過坐標(biāo)變換到以光源為視點(diǎn)的投影坐標(biāo)系下,坐標(biāo)變換矩陣如下:
M = M world M LighfView M LighfProj
式中: M world是變換世界坐標(biāo)系的變換矩陣; M LighfView為以光源為視點(diǎn)的視域坐標(biāo)變換矩陣; M LighfProj為以光源為視點(diǎn)的投影坐標(biāo)變換矩陣。
將變換后的坐標(biāo)以紋理坐標(biāo)的形式輸出給pixel shader,由于后面還需要實(shí)現(xiàn)基于像素的光照計(jì)算(per-pixel lighting)。每個(gè)頂點(diǎn)的法向,紋理坐標(biāo)等信息也需要以紋理坐標(biāo)的方式輸出,所以使光柵化后的每個(gè)像素都包含這些數(shù)據(jù)。
在像素著色器中,把每個(gè)像素上的可見點(diǎn)在光源坐標(biāo)系下的坐標(biāo)值的x和y變換至紋理坐標(biāo)空間中生成深度表紋理的坐標(biāo)tex:
tex.x = 0.5x/w+0.5
tex.y =0.5-0.5y/w
式中:w為坐標(biāo)的齊次項(xiàng)。上式可以將在[-1,l]范圍的投影坐標(biāo)變換到[0,l]的紋理坐標(biāo)空間內(nèi)。之后使用tex采樣深度表紋理,用當(dāng)前像素上可見點(diǎn)在光源坐標(biāo)系下的坐標(biāo)的z/w和深度表_h記錄的深度值進(jìn)行比較,如果z/w的值大于記錄的深度值,則當(dāng)前像素可見點(diǎn)處于陰影中,反之當(dāng)前像素可見點(diǎn)不被陰影遮蔽。在正確判斷出陰影后,將其效果作為乘積因子帶入光照計(jì)算公式中即可。
3.2 實(shí)驗(yàn)結(jié)果
圖6為在TGE中實(shí)現(xiàn)的軟陰影效果圖片。
圖6 TGE中實(shí)現(xiàn)的軟陰影
利用深度限制[8]和Shader Model 3.0 像素著色器對(duì)游戲引擎中的陰影進(jìn)行優(yōu)化[9-10],測(cè)試結(jié)果(如圖7所示)進(jìn)一步驗(yàn)證了在典型的復(fù)雜游戲場(chǎng)景中(TGE),著色器的開啟可以增加算法的性能。
圖7 對(duì)TGE中陰影優(yōu)化
4 結(jié) 語
Shadows Volume技術(shù)是實(shí)現(xiàn)統(tǒng)一光照模型比較好的一種技術(shù),但是這種方法是基于CPU,對(duì)處理器依賴比較重,在AI/物理運(yùn)算較多的場(chǎng)景中CPU運(yùn)算能力可能不足。隨著可編程技術(shù)的發(fā)展,圖形處理單元的 渲染速度遠(yuǎn)遠(yuǎn)大于CPU,為提高三維場(chǎng)景的渲染效率提供了更大的空間。利用圖形硬件的圖形處理單元(GPU)的運(yùn)算能力和可編程性,將生成陰影體的大量計(jì)算從CPU轉(zhuǎn)移到GPU,可以有效地提高實(shí)時(shí)陰影的繪制效率。
參考文獻(xiàn)
[1]劉祎瑋,張引,葉修梓.3D游戲引擎渲染內(nèi)核架構(gòu)及其技術(shù)[J].計(jì)算機(jī)應(yīng)用研究,2006(8):45-48.
[2]ASSARSSON Ulf, AKENINE- MOELLER Tomas. A geometry-based soft shadow volume algorithm using graphics hardware[J]. ACM Transactions on Graphics, 2003, 22(3): 511-520.
[3]ASSARSSON Ulf, DOUGHERTY Michael,MOUNIER Michael, et al. An optimized soft shadow volume algorithm with real-time performance[C]//2003 Graphics Hardware Workshop. Diego: California Graphics Hardware, 2003:1727-3471.
[4]ONOUEK, NISHITA T. Practical and robust stenciled shadow volumes for hardware-accelerated rendering[J]. Computer Graphics Forum, 2005,24(1): 51-60.
[5]ANEREW Woo, PIERRE Poulin, ALAIN Fournier. A survey of shadow algorithms[J]. IEEE Computer Graphics and Applications, 1990,10(6):13-32.
[6]周國(guó)民,盧滌非,張其前.一種梯形結(jié)構(gòu)的軟陰影錐生成方法[J].浙江大學(xué)學(xué)報(bào):理學(xué)版,2007,34(6):628-632.
[7]季國(guó)紅.3D游戲引擎中實(shí)時(shí)動(dòng)態(tài)陰影的研究[D].南京:南京工業(yè)大學(xué),2007.
[8]KURT P, PIRANHA B. Combined depth and ID-based shadow buffers[J].Game Programming Gens,2004.4:341-354.
[9]GABOR Nagy. Real-time shadows on complex objects[J]. Game Programming Gem, 2000: 567-580.
[10]繆小亮,周政春,萬旺根. 三維場(chǎng)景動(dòng)態(tài)模糊陰影算實(shí)現(xiàn)[J].上海大學(xué)學(xué)報(bào):自然科學(xué)版,2007,13(2):138-142.