真实感海洋的绘制(二):使用快速傅里叶变换加速波形计算

真实感海洋的绘制(二):使用快速傅里叶变换加速波形计算

其实上一篇博文所写的\(H(\vec{x},t)?\),就是二维傅里叶变换的求和式,之前的暴力计算法属于二维的离散傅里叶变换(Discrete Fourier Transform, DFT),利用二维的快速傅里叶变换(Fast Fourier Transform, FFT)可以将复杂度从\(O(n^4)?\)降低到\(O(n^2\log{n})?\)。

如果读者不熟悉FFT,强烈建议阅读《算法导论》相关章节,个人感觉没有什么资料讲得比《算法导论》更清楚了。书后习题还有关于二维FFT的思考,是本文算法正确性的理论基础。

数学推导

高度场

出于数学上推导的简单和实现上的简单,我们约定\(L_x=L_y=N=M=2^k\),把方程重写为如下形式

\[
H(\vec x,t) = \sum_{\vec{k}}h(\vec k, t)e^{i\vec{k}\cdot \vec{x}} \mbox{, where }
\vec{k}=(2\pi n/L,2\pi m/L), \ \vec{x}=(x, z)\-N/2\le n, m < N/2
\]

将\(\vec{k}\)与\(\vec{x}\)带入整理得

\[
\begin{align}
H(\vec{x},t)&=\sum_{n=-N/2}^{N/2 - 1}\sum_{m=-N/2}^{N/2-1}h(\vec{k},t)e^{2\pi nxi/N+2\pi mz/N} \&=\sum_{n=-N/2}^{N/2-1}e^{2\pi nxi/N}\sum_{m=-N/2}^{N/2-1}h(\vec{k},t)e^{2\pi mzi/N}
\end{align}
\]

为了化成便于使用FFT的形式,令\(n‘=n+N/2\), \(m‘=m+N/2\)

\[
H(\vec{x},t)=\sum_{n‘=0}^{N-1}e^{2\pi(n‘-N/2)xi/N}\sum_{m‘=0}^{N-1}h(\vec{k},t)e^{2\pi(m‘-N/2)zi/N}
\]

其中

\[
\begin{align}
e^{2\pi(n‘-N/2)xi/N}&=e^{2\pi n‘xi/N}e^{-\pi xi}\&=(-1)^x e^{2\pi n‘xi/N} (\mbox{ note that }e^{\pi i}=-1, N\ge 2)
\end{align}
\]

所以

\[
H(\vec{x},t)=(-1)^{x+z}\sum_{n‘=0}^{N-1}e^{2\pi n‘xi/N}\sum_{m‘=0}^{N-1}h(\vec{k},t)e^{2\pi m‘zi/N}
\]

这样已经成为了可以进行FFT的形式。这儿出现了一个\((-1)^{x+z}\),不用担心,在全部计算完之后带入即可。

法线

关于法线的计算有一些tricky。我们先写出之前给出的法线公式

\[
\epsilon(\vec{x},t)=\nabla H(\vec{x},t)=\sum_{\vec{k}}i\vec{k}h(\vec{k},t)e^{i\vec{k}\cdot \vec{x}}\\begin{align}
\vec{N}(\vec{x},t)&=(0,1,0)-(\epsilon_x(\vec{x},t),0,\epsilon_z(\vec{x},t))\&=(-\epsilon_x(\vec{x},t),1,-\epsilon_z(\vec{x},t))
\end{align}
\]

问题在于计算\(\epsilon(\vec{x},t) = (\epsilon_x, \epsilon_z)\)。我们首先类似\(H\)的推导得到

\[
\epsilon(\vec{x},t)=(-1)^{x+z}\sum_{n‘=0}^{N-1}e^{2\pi n‘xi/N}\sum_{m‘=0}^{N-1}i\vec{k}h(\vec{k},t)e^{2\pi m‘zi/N}
\]

经过观察我们发现\(\epsilon(\vec{x},t)\)的两个方向分别只与\(\vec{k}\)的两个方向有关,那么可以写成如下形式

\[
\epsilon_x(\vec{x},t)=(-1)^{x+z}\sum_{n‘=0}^{N-1}e^{2\pi n‘xi/N}\sum_{m‘=0}^{N-1}ik_xh(\vec{k},t)e^{2\pi m‘zi/N}\\epsilon_z(\vec{x},t)=(-1)^{x+z}\sum_{n‘=0}^{N-1}e^{2\pi n‘xi/N}\sum_{m‘=0}^{N-1}ik_zh(\vec{k},t)e^{2\pi m‘zi/N}\\]

然后分别计算即可。

偏置量

类似地,我们写出偏置量的公式

\[
\vec{D}(\vec{x},t)=\sum_{\vec{k}}-i\frac{\vec{k}}{|\vec{k}|}
h(\vec{k},t)e^{i\vec{k}\cdot \vec{x}}
\]

和法线计算的方式完全一样得到

\[
\vec{D}(\vec{x},t)=(-1)^{x+z}\sum_{n‘=0}^{N-1}e^{2\pi n‘xi/N}\sum_{m‘=0}^{N-1}-i\frac{\vec{k}}{|\vec{k}|}h(\vec{k},t)e^{2\pi m‘zi/N}
\]

分成两个方向

\[
D_x(\vec{x},t)=(-1)^{x+z}\sum_{n‘=0}^{N-1}e^{2\pi n‘xi/N}\sum_{m‘=0}^{N-1}-i\frac{k_x}{|\vec{k}|}h(\vec{k},t)e^{2\pi m‘zi/N} \D_z(\vec{x},t)=(-1)^{x+z}\sum_{n‘=0}^{N-1}e^{2\pi n‘xi/N}\sum_{m‘=0}^{N-1}-i\frac{k_z}{|\vec{k}|}h(\vec{k},t)e^{2\pi m‘zi/N}
\]

这就完成了推导的工作。相信熟悉FFT的读者可以对上边的公式很容易给出一个自己的FFT计算实现。

实现结果

之后的博客将会研究如何对这样的海面进行真实感渲染和光照计算。如果有时间的话,可能会探索如何把这个FFT模型移植到GPU上并行计算以实现更好的性能。

参考文献

  1. Tessendorf, Jerry. Simulating Ocean Water. In SIGGRAPH 2002 Course Notes #9 (Simulating Nature: Realistic and Interactive Techniques), ACM Press.
  2. Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest and Clifford Stein. Introduction to Algorithms, 3rd Edition, MIT Press.

原文地址:https://www.cnblogs.com/hehao98/p/8604163.html

时间: 2024-08-12 00:32:20

真实感海洋的绘制(二):使用快速傅里叶变换加速波形计算的相关文章

准零基础搞懂FFT快速傅里叶变换及其实现程序(二)

上一篇文章我们了解了DFT的原理,FFT是基于DFT的更适合计算机运算的算法,本文我们就正式开始学习FFT的原理. 首先我么先来宏观的看一下FFT.如果我们把整个FFT的算法看成一个黑盒子的话,那么它的输入就是时间波形信号,比如声音波形(横轴为时间,纵轴为振幅).外什么FFT要比DFT速度更快呢?下面(图1)解释了FFT和DFT的(对于计算机的)算法复杂度 图1 从上面的数学表达式可以看出,一个1024采样点的FFT比DFT块了102.4倍.如果傅里叶变换的数量级更大,FFT的速度优势会更明显.

研究傅里叶变换的一本好书&lt;&lt;快速傅里叶变换及其C程序&gt;&gt;

快速傅里叶变换及其C程序 <快速傅里叶变换及其C程序>是中国科学技术大学出版社出版的.本书系统地介绍了傅里叶变换的理论和技术,内容包括傅里叶变换(FT)的定义.存在条件及其性质,离散傅里叶变换(DFT)的定义.性质及由离散引起的频谱混叠和渗漏,快速傅里叶变换(FFT)算法的基本原理和复序列基2算法及其实用程序,并以此为基础,给出了实序列DFT.正弦变换.余弦变换.傅里叶级数.谱函数近似.功率谱估计.卷积和相关等的快速算法和实用程序,给出了 2D—DFT的行列算法.二维实序列2D—DFT的行列算

[学习笔记] 多项式与快速傅里叶变换(FFT)基础

引入 可能有不少OIer都知道FFT这个神奇的算法, 通过一系列玄学的变化就可以在 $O(nlog(n))$ 的总时间复杂度内计算出两个向量的卷积(或者多项式乘法/高精度乘法), 而代码量却非常小. 博主一年半前曾经因COGS的一道叫做"神秘的常数 $\pi$"的题目而去学习过FFT, 但是基本就是照着板子打打完并不知道自己在写些什么鬼畜的东西OwO 不过...博主这几天突然照着算法导论自己看了一遍发现自己似乎突然意识到了什么OwO然后就打了一道板子题还1A了OwO再加上午考试差点AK

灰度图像--频域滤波 傅里叶变换之二维离散傅里叶变换

学习DIP第24天 转载请标明本文出处:http://blog.csdn.net/tonyshengtan,欢迎大家转载,发现博客被某些论坛转载后,图像无法正常显示,无法正常表达本人观点,对此表示很不满意.有些网站转载了我的博文,很开心的是自己写的东西被更多人看到了,但不开心的是这段话被去掉了,也没标明转载来源,虽然这并没有版权保护,但感觉还是不太好,出于尊重文章作者的劳动,转载请标明出处!!!! 开篇废话 今天要记录的是二维离散傅里叶变换的一些性质,也是傅里叶在图像处理中要用到的一些性质,所以

Matlab之快速傅里叶变换

一.快速傅里叶介绍 傅立叶原理表明:任何连续测量的时序或信号,都可以表示为不同频率的余弦(或正弦)波信号的无限叠加.FFT是离散傅立叶变换的快速算法,可以将一个信号变换到频域.那其在实际应用中,有哪些用途呢? 1.有些信号在时域上是很难看出什么特征的,但是如果变换到频域之后,就很容易看出特征(频率,幅值,初相位): 2.FFT可以将一个信号的频谱提取出来,进行频谱分析,为后续滤波准备: 3.通过对一个系统的输入信号和输出信号进行快速傅里叶变换后,两者进行对比,对系统可以有一个初步认识. 假设采样

FFT算法实现——基于GPU的基2快速傅里叶变换

最近做一个东西,要用到快速傅里叶变换,抱着蛋疼的心态,自己尝试写了一下,遇到一些问题. 首先看一下什么叫做快速傅里叶变换(FFT)(来自Wiki): 快速傅里叶变换(英语:Fast Fourier Transform, FFT),是离散傅里叶变换的快速算法,也可用于计算离散傅里叶变换的逆变换.快速傅里叶变换有广泛的应用,如数字信号处理.计算大整数乘法.求解偏微分方程等等. 对于复数串行,离散傅里叶变换公式为: 直接变换的计算复杂度是O(n^2).快速傅里叶变换可以计算出与直接计算相同的结果,但只

【知识总结】快速傅里叶变换(FFT)

这可能是我第五次学FFT了--菜哭qwq 先给出一些个人认为非常优秀的参考资料: 一小时学会快速傅里叶变换(Fast Fourier Transform) - 知乎 小学生都能看懂的FFT!!! - 胡小兔 - 博客园 快速傅里叶变换(FFT)用于计算两个\(n\)次多项式相乘,能把复杂度从朴素的\(O(n^2)\)优化到\(O(nlog_2n)\).一个常见的应用是计算大整数相乘. 本文中所有多项式默认\(x\)为变量,其他字母均为常数.所有角均为弧度制. 一.多项式的两种表示方法 我们平时常

傅里叶变换通俗解释及快速傅里叶变换的python实现

通俗理解傅里叶变换,先看这篇文章傅里叶变换的通俗理解! 接下来便是使用python进行傅里叶FFT-频谱分析: 一.一些关键概念的引入 1.离散傅里叶变换(DFT) 离散傅里叶变换(discrete Fourier transform) 傅里叶分析方法是信号分析的最基本方法,傅里叶变换是傅里叶分析的核心,通过它把信号从时间域变换到频率域,进而研究信号的频谱结构和变化规律.但是它的致命缺点是:计算量太大,时间复杂度太高,当采样点数太高的时候,计算缓慢,由此出现了DFT的快速实现,即下面的快速傅里叶

实序列快速傅里叶变换(一)

一.功能 计算实序列的快速傅里叶变换. 二.方法简介 实序列\(x(n)\)的离散傅立叶变换为 \[ X(k)=\sum_{n=0}^{N-1}x(n)W_{N}^{nk} \ , \ k=0,1,...,N-1 \] 上式可用复序列FFT算法进行计算.但考虑到\(x(n)\)是实数,为进一步提高计算效率,需要对按时间抽取的基2复序列FFT算法进行一定的修改. 如果序列\(x(n)\)是实数,那么其傅立叶变换\(X(k)\)一般是复数,但其实部是偶对称,虚部是奇对称,即\(X(k)\)具有如下共