(假如左边这幅图没有出现,请耐心的稍等片刻)
看到左边这幅动画,您也许不会相信他其实是用电脑做出来的,这就是“水波”特效的魅力所在。这个小动画是从程式的执行画面中抓出来的,假如您想亲自执行一下源程式,看看实际的效果,能够下载 RipSample.zip(92k)。(包含源程式和可执行文档。这个例子只是水波屏保的简化版本,省去了许多和水波原理无关的代码,这样做的目的是为了让水波特效的原理更容易理解)
在介绍编程之前,先让我们来回顾一下在高中的物理课上我们所学的关于水波的知识。
水波有如下几个特性:
- 扩散:当您投一块石头到水中,您会看到一个以石头入水点为圆心所形成的一圈圈的水波,这里,您可能会被这个现象所误导,以为水波上的每一点都是以石头入水点为中央向外扩散的,这是错误的。实际上,水波上的任何一点在任何时候都是以自己为圆心向四周扩散的,之所以会形成一个环状的水波,是因为水波的内部因为扩散的对称而相互抵消了。
- 衰减:因为水是有阻尼的,否则,当您在水池中投入石头,水波就会永不停止的震荡下去。
- 水的折射:因为水波上不同地点的倾斜角度不同,所以,因为水的折射,我们从观察点垂直往下看到的水底并不是在观察点的正下方,而有一定的偏移。假如不考虑水面上部的光线反射,这就是我们能感觉到水波形状的原因。
- 反射:水波碰到障碍物会反射。
- 衍射:突然又想到这一点,但是在程式里却看不到,假如能在水池中央放上一块礁石,或放一个中间有缝的隔板,那么就能看到水波的衍射现象了。
好了,有了这几个特性,再运用数学和几何知识,我们就能够模拟出真实的水波了。但是,假如您曾用3DMax做过水波的动画,您就会知道要渲染出一幅真实形状的水波画面少说也得好几十秒,而我们现在需要的是实时的渲染,每秒种至少也得渲染20帧才能使得水波得以平滑的显示。考虑到电脑运算的速度,我们不可能按照正弦函数或精确的公式来构造水波,不能用乘除法,更不能用sin、cos,只能用一种取近似值的快速算法,尽管这种算法存在一定误差,但是为了满足实时动画的需要,我们不得不这样做。
首先我们要建立两个和水池图象相同大小的数组buf1[PoolWidth*PoolHeight]和buf2[PoolWidth*PoolHeight](PoolWidth=水池图象的象素宽度、PoolHeight=水池图象的象素高度),用来保存水面上每一个点的前一时刻和后一时刻波幅数据,因为波幅也就代表了波的能量,所以以后我们称这两个数组为波能缓冲区。水面在初始状态时是个平面,各点的波幅都为0,所以,这两个数组的初始值都等于0。
下面来推导计算波幅的公式
我们假设存在这样一个一次公式,能够在任意时刻根据某一个点周围前、后、左、右四个点连同该点自身的振幅来推算出下一时刻该点的振幅,那么,我们就有可能用归纳法求出任意时刻这个水面上任意一点的振幅。如左图,您能够看到,某一时刻,X0点的振幅除了受X0点自身振幅的影响外,同时受来自他周围前、后、左、右四个点(X1、X2、X3、X4)的影响(为了简化,我们忽略了其他任何点),而且,这四个点对a0点的影响力能够说是机会均等的。那么我们能够假设这个一次公式为:
X0’=a(X1 X2 X3 X4) bX0
(公式1)
a、b为待定系数,X0’为0点下一时刻的振幅
X0、X1、X2、X3、X4为当前时刻的振幅
下面我们来求解a和b。
假设水的阻尼为0。在这种理想条件下,水的总势能将保持不变。也就是说在任何时刻,任何点的振幅的和保持不变。那么能够得到下面这个公式:
X0’ X1’ ... Xn’ = X0 X1 ... Xn
将每一个点都象公式1那样计算,然后代入上式,得到:
(4a b)X0 (4a b)X1 ...(4a b)Xn = X0 X1 ... Xn
=>4a b=1
找出一个最简解:a = 1/2、b = -1
因为1/2能够用移位运算符“>>”来进行,不用进行乘除法,所以,这组解是最适用的而且是最快的。那么最后得到的公式就是:
X0’=(X1 X2 X3 X4)/ 2- X0
好了,有了上面这个近似公式,您就能够推广到下面这个一般结论:已知某一时刻水面上任意一点的波幅,那么,在下一时刻,任意一点的波幅就等于和该点紧邻的前、后、左、右四点的波幅的和除以2、再减去该点的波幅。
应该注意到,水在实际中是存在阻尼的,否则,用上面这个公式,一旦您在水中增加一个波源,水面将永不停止的震荡下去。所以,还需要对波幅数据进行衰减处理,让每一个点在经过一次计算后,波幅都比理想值按一定的比例降低。这个衰减率经过测试,用1/32比较合适,也就是1/2^5。能够通过移位运算很快的获得。
到这里,水波特效制作中最艰难的部分已度过了,下面是源程式中计算波幅数据的代码。
//*******************************************************
//计算波能数据缓冲区
//*******************************************************文章整理:西部数码--专业提供域名注册、虚拟主机服务
http://www.west263.com
以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!




