使用后期处理效果实现运动模糊
1.介紹
在電子游戲中模擬速度的一種最好的方法就是使用運(yùn)動模糊。運(yùn)動模糊是游戲中最重要的效果之一,尤其是在賽車游戲中,因?yàn)樗梢栽黾诱鎸?shí)感和速度感。運(yùn)動模糊還可以幫助游戲畫面的平滑,尤其是對于幀速小于等于30的游戲來說。但是,在已有的游戲引擎加入運(yùn)動模糊是具有挑戰(zhàn)性的,因?yàn)榇蠖鄶?shù)運(yùn)動模糊技術(shù)需要重新渲染場景,以產(chǎn)生基于每個像素的速度緩沖。這種多輪渲染的方法是具有限制性的:許多應(yīng)用程序在將場景多次送往圖形管線時,并不能保持原有的幀速。
其他生成基于每個像素的速度映射圖的方法包括使用多個渲染目標(biāo),然后將速度信息輸出到其中一個渲染目標(biāo)。這種方法的主要不足在于需要改變場景的著色器,增加相應(yīng)的代碼,以計(jì)算速度并將其輸出到第二個渲染目標(biāo)。這種方法的另一個不足在于渲染到多個目標(biāo)在一些平臺上可能降低性能。另外,一些平臺只有有限的渲染內(nèi)存,要求一種機(jī)制來在1280*720或者更大的幀緩存上使用多個渲染目標(biāo)。
在這章中,我們將介紹一項(xiàng)使用深度緩沖作為紋理輸入到片段著色器程序來生成場景速度映射圖的技術(shù)。片段著色器程序使用深度值和視圖投影矩陣,為每一個像素計(jì)算世界坐標(biāo)中的位置,而深度值保存在深度緩存中。一旦我們計(jì)算出該像素在世界坐標(biāo)中的位置,我們就可以使用前一幀的視圖投影矩陣對它進(jìn)行變換。然后我們可以計(jì)算當(dāng)前幀和前一幀中視口坐標(biāo)中該位置的差別,以生成每一個像素的速度值。運(yùn)動模糊的效果可以通過使用速度向量作為方向來組合幀緩存上的多重采樣,然后進(jìn)行歸一化最后產(chǎn)生模糊的效果。
這項(xiàng)技術(shù)的好處在于可以放在后期處理階段。這將使得這項(xiàng)技術(shù)可以很容易地集成到已有的圖形引擎中,這些引擎所運(yùn)行的硬件可能允許在深度緩存上采樣作為紋理。
圖1和圖2展示了使用運(yùn)動模糊前后的區(qū)別。
?
圖1?使用了運(yùn)動模糊的場景
?
圖2?沒有使用運(yùn)動模糊的場景
2.從深度緩存提取物體的位置
當(dāng)一個物體被渲染并且它的深度值被寫入深度緩存時,保存在深度緩存的值是三角面片的z值的插值,該z值是這樣計(jì)算出來的:首先三角形的三個頂點(diǎn)被世界視圖投影矩陣轉(zhuǎn)換,然后xyz坐標(biāo)被齊次坐標(biāo)中的w值所除。通過使用深度緩存作為紋理,我們可以提取出渲染到深度緩存的物體的世界坐標(biāo)中的位置。我們先將視口中的位置使用視圖投影矩陣的逆矩陣進(jìn)行轉(zhuǎn)化,然后用w值乘以結(jié)果,得出對應(yīng)的世界坐標(biāo)中的位置。令視口位置為像素在視口空間的位置,也就是說,x、y坐標(biāo)的值在-1到1的范圍內(nèi),而原點(diǎn)在屏幕的中心。那個像素在深度緩存中的深度值作為z值,而w值設(shè)為1。
我們可以將某一像素的視口位置定義為H:
?
令M為世界視圖投影矩陣,而W為該像素的世界坐標(biāo):
?
下面是HLSL/Cg代碼:
//?Get?the?depth?buffer?value?at?this?pixel.
float?zOverW?=?tex2D(depthTexture,?texCoord);
//?H?is?the?viewport?position?at?this?pixel?in?the?range?-1?to?1.
float4?H?=?float4(texCoord.x?*?2?-?1,?(1?-?texCoord.y)?*?2?-?1,
zOverW,?1);
//?Transform?by?the?view-projection?inverse.
float4?D?=?mul(H,?g_ViewProjectionInverseMatrix);
//?Divide?by?w?to?get?the?world?position.
float4?worldPos?=?D?/?D.w;
一旦我們計(jì)算出世界坐標(biāo),我們可以使用前一幀的視圖投影坐標(biāo)對其進(jìn)行變換,然后得到屏幕位置上的差別,以計(jì)算像素的速度,代碼如下:
//?Current?viewport?position
float4?currentPos?=?H;
//?Use?the?world?position,?and?transform?by?the?previous?view-
//?projection?matrix.
float4?previousPos?=?mul(worldPos,?g_previousViewProjectionMatrix);
//?Convert?to?nonhomogeneous?points?[-1,1]?by?dividing?by?w.
previousPos?/=?previousPos.w;
//?Use?this?frame's?position?and?last?frame's?to?compute?the?pixel
//?velocity.
float2?velocity?=?(currentPos?-?previousPos)/2.f;
請求深度緩存作為紋理使用的方法取決于使用的平臺,依賴于圖形API。訪問深度緩存作為紋理的細(xì)節(jié)在Gilham?2006中有詳細(xì)討論。如果硬件不支持從深度緩存中采樣作為紋理的話,就要使用多個渲染目標(biāo)然后將深度輸出到一個單獨(dú)的渲染目標(biāo),或者將深度值輸出到顏色緩存的alpha通道。
3.運(yùn)行運(yùn)動模糊
一旦我們有了像素的速度,我們可以在顏色緩存中沿著那個方向采樣,累計(jì)顏色值來得到運(yùn)動模糊的值,如下代碼:
//?Get?the?initial?color?at?this?pixel.
float4?color?=?tex2D(sceneSampler,?texCoord);
texCoord?+=?velocity;
for(int?i?=?1;?i?<?g_numSamples;?++i,?texCoord?+=?velocity)
{
??//?Sample?the?color?buffer?along?the?velocity?vector.
??float4?currentColor?=?tex2D(sceneSampler,?texCoord);
??//?Add?the?current?color?to?our?color?sum.
??color?+=?currentColor;
}
//?Average?all?of?the?samples?to?get?the?final?blur?color.
float4?finalColor?=?color?/?numSamples;
我們可以在圖3中看到運(yùn)行結(jié)果,注意到接近觀察者的地形比遠(yuǎn)處的地形更模糊。
?
圖3?運(yùn)動模糊的運(yùn)行結(jié)果
?
4.處理動態(tài)的物體
這項(xiàng)技術(shù)使用在靜止的物體上效果非常好,因?yàn)樗豢紤]到攝像機(jī)的運(yùn)動。但是,如果需要更加精確地記錄動態(tài)物體的速度,那么我們可以生成獨(dú)立的速度紋理。
為了生成缸體動態(tài)物體的速度紋理,首先要使用當(dāng)前幀的視圖投影矩陣以及前一幀的視圖投影矩陣對物體進(jìn)行變換,然后計(jì)算視口位置的差異。接著將兩個變換后的位置傳入片段著色器,并計(jì)算速度。這項(xiàng)技術(shù)在DirectX?9?SDK's?的運(yùn)動模糊示例中被描述。
5.屏蔽的物體
取決于應(yīng)用程序,你可能需要屏蔽場景的某個部分,不對此部分使用運(yùn)動模糊。比如,在賽車游戲中,你需要保持所有車輛的清晰度和細(xì)節(jié),而不對其進(jìn)行模糊。一種簡單的方法是渲染一個掩模到一個單獨(dú)的紋理或者到顏色緩存的alpha通道,然后使用這個掩模來決定什么像素應(yīng)該被模糊。
6.額外的工作
使用深度緩存計(jì)算物體的世界坐標(biāo)的技術(shù)是非常有用的。我們可以使用這項(xiàng)技術(shù)實(shí)現(xiàn)深度域的效果,正如Gilham?2006中所描述,還有場景霧也可以使用深度緩存作為后期處理來實(shí)現(xiàn)。
7.總結(jié)
在這章中,我們討論了一種使用深度緩存中的深度值來計(jì)算物體的世界坐標(biāo)的方法,并且介紹了那些信息如何用于在一個游戲引擎中實(shí)現(xiàn)運(yùn)動模糊的效果。將運(yùn)動模糊作為后期處理實(shí)現(xiàn)的技術(shù)可以很簡單地集成到一個已有的渲染引擎中,并能夠提供比傳統(tǒng)的多輪解決方法更好的性能。
8.參考文檔
[1]Gilham,?David.?2006.?"Real-Time?Depth-of-Field?Implemented?with?a?Post-Processing?Only?Technique."?In?Shader?X5,?edited?by?Wolfgang?Engel,?pp.?163–175.?Charles?River?Media.
[2]Microsoft?Corporation.?2006.?"DirectX?9.0?Programmer's?Reference."
轉(zhuǎn)載于:https://www.cnblogs.com/wangshaohao/archive/2012/11/14/2769663.html
總結(jié)
以上是生活随笔為你收集整理的使用后期处理效果实现运动模糊的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 20个 css3 html5 设计工具
- 下一篇: allegro约束设置