随笔 - 129  文章 - 0  评论 - 123  阅读 - 33万

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内完成。

posted on   龚敏敏  阅读(2915)  评论(5编辑  收藏  举报
编辑推荐:
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
阅读排行:
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
< 2012年3月 >
26 27 28 29 1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
1 2 3 4 5 6 7

点击右上角即可分享
微信分享提示