FFT鏡頭效果解析


轉載請注明出處為KlayGE游戲引擎,本文地址為http://www.klayge.org/2012/03/22/fft%e9%95%9c%e5%a4%b4%e6%95%88%e6%9e%9c%e8%a7%a3%e6%9e%90/

 

3DMark11的whitepaper里突出了用FFT實現鏡頭效果的方法。這里指的鏡頭效果包括bloom和泛光等,一般在HDR的tone mapping之前做。

傳統鏡頭效果

Bloom是最常見的效果。一般就用一個gaussian blur完成。但那樣的結果缺乏層次感,只是亮的一片。在Halo等游戲中,用了較為復雜的bloom方式。它先把HDR image做多次downsample,在每一次上都分別作gaussian blur,然后再以一定的權重混合起來,得到富有層次的bloom。

Bungie Bloom
Bungie的Bloom方法,來自 Lighting and Material of HALO 3

 

對於bloom本身這樣已經基本可以了,但如果要增加更多鏡頭眩光的效果,比如DX SDK里HDRLighting的Star Effect,就得再增加更多的pass。而且如果blur的kernel很大的話,速度也會有嚴重下降。比如在不少游戲里也開始使用類似Star Trek 11里面的橫向鏡頭眩光,幾乎需要一個全屏大小的kernel,對於實時應用來說是傷不起的。(J.J. Abrams在不少片子里都用了這種橫向的lens flare)

Lens flare

 

FFT方法

其實所有這些鏡頭效果都是blur,也就是用一個kernel去卷積每一個像素。數學上有個卷積定理:

其中表示卷積,表示傅里葉變換,表示傅里葉逆變換。也就是說,函數卷積的傅里葉變換是函數傅里葉變換的乘積。所以,所與那些鏡頭效果需要的卷積都可以在FFT之后的頻域上用一次乘法完成。不管你要多少層bloom、多少個star、多大的kernel,全都在1 pass內解決

整個算法的框架非常簡單:

  1. 對輸入圖像做FFT
  2. 把FFT過的kernel圖像和1的結果做逐像素復數乘法
  3. 逆FFT

這就完成了所有的鏡頭效果。舉個實際例子:

輸入圖像(來自前不久剛完成的Scene Player

Input image

 

在FFT之前需要downsample到512×512大小,並且只保留亮的部分(bright pass):

Bright pass

 

FFT的結果,分別是實數部分和虛數部分:

Real part

 

Imagin part

 

kernel圖像,在Paint.net里面隨便畫的

Kernel image

 

kernel也做FFT之后,把兩者進行復數相乘,

 

 

 

 

 

其中re和im分別表示實部和虛部。

逆FFT的結果

Restore image

 

疊加回原圖

Output

 

唯一剩下的問題就是如何得到kernel的圖像。目前我想到的方法是提供一個交互工具,由美術手工繪制,旁邊顯示最終結果。可以預定義一些pattern,在工具中迭加使用。

未來

FFT鏡頭效果的算法已經探索完成。目前的實驗里,FFT調用的是FFTW庫,下一步將會在GPU上實現FFT(有PS的版本和CS的版本),這樣就能把整條流水線在GPU上,替換掉現在HDR post process里的bloom部分。

FFT還可以用於其它跟卷積有關的操作中,以后我會探索用FFT完成DoF、Bokeh、Motion blur、SSAO等常用的效果。Again,仍是在一個pass內完成。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM