OMG~~图片贴不进来....不管了- -迟点换个博客吧
已经搬家到新博客 jjyy.guru
分享跟游戏相关的技术、编程心得、unity3d、cocos2d、emacs、操作系统
第一章.高效水体模拟的物理模型
Mark Finch
Cyan Worlds
这一章讲一个模拟和在GPU中渲染大体积水体的系统。
这个系统产生基础网(base mesh)的物理起伏通过动态的法线贴图生成。这个系统证明适合实时游戏场景,已经非常广泛地用于Cyan World,如下图:
1.1目标和范围
在过去几年里,实时游戏渲染技术已经移植应用到了离线渲染的世界里。快速傅里叶变换(FFT)技术,就像在Tessendorf 2001概述的一样,足够大的抽样网格产生让人难以置信的真实感,中等规模网格在平民级PC上运行也成了可能。基于像素解决方案的简化形式Navier-Stokes方程也是切实可行的。虽然我们还没掌握背面消影的要领,离线水体模拟等等。到了2002年,差距正在缩小。在这章出版的时候,FFT文库可能会可供定点和像素着色器只用的,但由于写这本书,这些技术的实时版本还受着在CPU上运行的限制。
同时,水体模拟模型在GPU上运行已经变得足够容易。Isidoro et al 2002上讲了利用4正弦波的相加在定点着色器里计算表面高度和方向。Leauchli 2002 展示了用着色器计算表面高度通过使用郭士纳波(Gerstner waves)。
我们通过计算简单的正弦函数开始,然后再进入更复杂的函数,视情况而定。我们也把技术融入像素着色器里面,通过一个周期波函数的和(periodic wave function)去创建动态的凹凸贴图来表达水面的细节。
这一章重点放在系统参数的物理意义,显示出近似的正弦波总和的水面是作为临时作用,而不是实时显示。我们特别把注意力放在让我们理清底层模型的实际执行情况的数学。数学的关键是扩展方法。
该系统是专为从一个小池塘作为海洋水体范围看,就像看待海湾到岛屿一样。虽然不是一个严谨的物理模拟,但它确实是有效,灵活的渲染动态水体的方案。因为这些模拟完全运行在GPU上,所以他们更加容易去编写,如果反复编译。使整个动力系统--除了其中的波浪--增加了额外级别的生活(extra level of life)。
1.2 The Sum of Sines
粗略估计
我们运行两个表面模拟:一个用于几何起伏的表面网格,另一个用于网格表面涟漪的法线贴图。两个模拟本质上是一样的。水面高度可以使用简单的周期波的总和来实现。我们由相加正弦函数开始接着我们会进入更加有趣的波形方面的学习。
正弦函数的相加得到了一个连续函数去描述在所有点上水的高度和表面方向。在顶点处理方面,我们尝试基于每个顶点的水平位置的函数,遵从连续水面网格布线的极限。后面的几何决议,我们继续从技术角度探讨纹理空间。我们产生一张法线贴图用在表面上,这张法线贴图是通过上面讲到的正弦函数的相加,通过简单的像素着色操作,在呈现近似的渲染目标纹理。为每一帧渲染我们的法线贴图,可以使得我们的正弦波有限的独立移动,有力的加强了渲染的真实感。
事实上,波纹的纹理支配了我们的真实模拟的很大部分。
目前的纹理,我们波浪起伏的表面几何体提供了一个微妙的架构。如此,我们有不同的选择几何与纹理波的尺度。
1.2.1 波纹的选择
我们需要一系列的参数去定义每一个波纹。如图
图中单个波纹函数的参数
波长L:世界空间(world space)中波峰到波峰的距离。波长L与频率W的关系为W=2pi/L.(pi为圆周率).
振幅A:波峰到会平面的距离。
速度S:波峰每秒移动的距离。速度的表达式非常容易表示。 =S*2pi/L.
方向D:.....不解释
每个波纹的水平位置(X,Y)和时间(t)被定义为:
等式一:
而整个表面为
等式二:
对于每个波纹i
为了实现动态场景我们随机产生这些系统规定的波纹参数。随着时间,我们将会连续地让一个波纹褪去,让后再不同的参数让它回来。事实证明,这些参数是相互关系的。完全为每个可靠地合并过的波纹产生一系列的参数是必须小心的。
1.2.2
因为我们有了一个可用的函数用于表面,所以我们可以直接地计算表面方向的任何点,而不是依赖于有限分差技术。我们的副法线B和切线T向量分别是x,y方向的偏导数。任何在2D水平位置的(X,Y),可得3D位置P在表面上:
等式3
X方向的偏导数是:
等式4a
等式4b
相似的,切线向量是:
等式5a
等式5b
法线是由副法线以及切线共同生成的,如:
等式6a
等式6b
在推导函数H之前,记下等式3-6中实用的公式是怎么一回事。这两个偏导数的值给了我们九个构成切线空间的基础。这是一个我们用高度场去逼近我们表面的直接结果。就是P(x,y).x=x 、P(x,y).y=y,这两个偏导数生成零和一。这是只适合于这样的高度场,但对于一般的函数,我们会选择H(X,Y,T)。对于1.21中的高度函数,偏导数是特别方便用于计算。因为导数的结果是结果的导数:
等式7
对于所有波i。
对于通过正弦函数产生波纹的方法的一个弊端是,它产生了太多圆的波,而真实的波纹是更有尖锐的波峰的,更有平滑的波谷。事实上,那种效果是可以通过正弦函数的变形得到。
我们偏移我们的正弦函数而成为一个非负的而且上升到一个指数K。函数以及它的偏导数的方向到X是:
等式8a
等式8b
下图展示了带指数K的函数所产生的波形。这就是我们事实上用在我们的波纹的纹理,但不完全是,我们继续
来用正弦函数的简单相加去得到我们要表达的波形,我们还要记下我们必须为了我们在基本波形上面的改变而计算的地方。
1.2.3 几何波形
我们限制了四个波形,因为增加波形不以为着会有什么新发现,只是会产生更多的相似顶点着色指令和常量。
定向和圆形波纹
我们选择了定向的和圆形的波纹,就像下面显示的那样。定向的波纹需要稍微少的着色指令,但其他的选择由场景的模拟程度决定。
对于定向的波纹,对于每一个D,等式1是波纹的常数。对于圆形的波纹,方向必须要为每一个定点计算和从中央C的波纹定点得到相应的法线向量。
对于大型水体,定向的波纹是更好用的,因为他们是由风驱动的更好的波纹模型。对于小型的水体,它们更多是使用圆形波纹。圆形波纹也是一个不错的模型,由于他们干涉条纹不会重复。这两种波纹的实现是非常相似的。对于定向的波纹来说,波纹的方向是随机的,有风向决定。而对于圆形波纹来说,波纹的中心是随机的有限范围。因为他们的实现差不多,所以剩下的讨论就集中在其中一个,定向的波纹。
郭士纳(Gerstner)波
为了有效的模拟,我们需要去控制我们一些不合理的波纹。就像之前讲到的,正弦波纹看起来太圆了,当我们需要一个平静的小池塘的时候就满足不了我们的要求了。而对于汹涌的大海,我们更需要的是构造出尖锐的浪花以及更宽广的波谷。我们可以使用等式8a以及等式8b,因为他们可以产生我们想要的形状,但是我们现在选择的郭士纳(Gerstner)波可以替代它们。郭士纳波函数是起源于长久以来的计算机图形学对于海洋模型的模拟而发展起来的,它是基于物理的。因此,郭士纳增加了波浪表面(surface)运动的一些令人信服的微妙之处,但没有被公开。(详情可以参看Tessendorf 2001)我们选择用郭士纳波是因为它有一些经常被忽视的重要性:他们构造浪花的形状是同移动定点到相应的波峰。因为浪花是在表面上充满形状的(尖尖的,而且频率高),而郭士纳波则可以非常准确的我们想要的地方产生波浪,如图:
郭士纳波的函数是:
等式9:
这里的Q是一个参数用来控制波浪的尖锐程度。对于每一个波浪i来说,Q为零则是一个常见的滚动的正弦波,Q=(W*A)则是一个有形状的波峰。Q的最大值应该避免出现,因为它会导致循环,以至于波峰上空产生。事实上,我们可以为艺术家(美工)留下一个波峰险峻程度的参数Q,允许的范围为0到1,而且用Qi= Q/(wi Aix numWaves) 来控制平滑到险峻的波浪的产生。
留意等式3与等式9的区别,只不过是侧向移动的顶点。高度则是一样的。这意味着我们不用严格使用高度的方程。这就是但是,函数依旧很容易微分而且有一些方便的取消条件。就像词根之于读者,向量则是我们目标空间的基础:
等式10
等式11
等式12
其中:
这些等式不像等式4b,5b还有6b那样清晰,但是他们是相当有效的计算。仔细看看正常证明那些有趣的由上下文构循环而造出的波峰的Z轴。当Tessendorf (2001)来自于他的震荡效果从Navier-Stokes描述的流体动态和流动变换技术,结果是郭士纳波的变种频域。在频域中,波纹的顶端循环可以躲避以及删除,