Unity官方示例UnityWaterSurface分析
Unity为我们提供了一个使用CustomRenderTexture的简单示例,利用RenderTexture来存储上一此以及上上一次的水面像素点的波幅,来计算下一次该像素点的波幅,用来模拟雨滴掉落水面时的涟漪。示例程序公布在GitHub上:https://github.com/hecomi/UnityWaterSurface
场景总中包含了一个平面和一个Cube。平面用来模拟水面,Cube其实没什么用,仅仅是表现这个平面是半透明的(水面Shader并没有实现折射的效果,如果想实现也不难,使用一个GrabPass抓取平面后面的图像然后做一个偏移就可以模拟出折射的效果,感兴趣的话可以参考一些教程自己实现)
场景使用到的资源也很简单,包括一张用来初始化CustomRenderTexture的纹理(原始程序是中间有一个红圆点的,后面会分析为什么事红圈,我寄几手欠,改成全黑的了)。一张是我们用来保存水面波幅的CustomRenderTexture。两个材质,一个是WaterSurface的材质,应用在Plane上,用来模拟水面涟漪。一个是WaterSimulation材质,用在纹理WaterSimulation上,用来计算并更新水面像素点的波幅保存在一张名为WaterSimulation的CustomRenderTexture里面。名为WaterSurface的Shader正是使用这张CustomRenderTexture作为输入计算出睡眠的顶点偏移和表面法向量,以模拟出水面涟漪的效果。脚本WaterSimulation是用来控制CustomRenderTexture的更新的。
水面涟漪如何扩散
首先来讲一讲雨滴掉落水面产生涟漪的理论基础:雨滴坠落水面造成的涟漪是由于对水表面的某一点产生了压力,该店的位置由于力的作用产生了为孩子的偏移,由于水分子之间的张力,带动了其周围的水分子产生位移,四周的水分子的位移同时又会反过来作用于中心点本身,这样循环,产生视觉上的扩散波纹。如果从理论物理的角度进行模拟将会使用大量的流体力学公式,产生庞大的计算量和实现的复杂度,所以我们从数学的角度,参考理论,来使用一种近似的模拟方法,使视觉上达到较为逼真的效果,毕竟从游戏和特效的角度看,如果它看起来很像,那么它就是正确的,很多时候,真正能达到性能和效果双重目标的往往是一些简单的经验公式。
我们假设每一个像素下一次的震动波幅,是受到其自身本时刻的震动方向、以及周围上下左右四个像素的位置的影响:本时刻的运动方向可以用本时刻的位置减去上一时刻的震动位置来表示,上下左右的四个像素对中心像素的影响也可以用他们和中心像素的震动位置的差来表示,那么下一时刻的位置可表示为: