实时水面波动模拟的两种方式

Crest

图片来自大名鼎鼎的Crest Ocean项目截图,其波动算法为Gerstner Waves
因为HDRP项目需要一套水,现有的水都比较简陋,所以又双叒叕在做玩具
主要是 Gerstner Waves 和 Statistical Wave Models

Gerstner Waves

1. Gerstner函数

在GPU Gems 第一部分 第一章 用物理模型进行高效水模拟 中提供了Gerstner函数:
Gerstner函数
其中 Q i Q_i Qi是控制波坡度的参数。对于单个波 i i i Q i = 0 Q_i = 0 Qi=0 会得到正常的正弦波,而 Q i = 1 / ( w i A i ) Q_i =1/ (w _i A_i) Qi=1/(wiAi) 可以给出尖峰的波形。我们可以提供可调参数到面板,使用 Q i = 1 / ( w i A i × N u m W a v e s ) Q_i =1/ (w _i A_i \times NumWaves) Qi=1/(wiAi×NumWaves) 控制波的平滑程度。
然后,我们可以通过分别对 x , y x,y x,y偏导,求出切线和副切线向量:
切线
副切线
然后 B × T B \times T B×T 得到法线方向
法线方向
其中
WA, S, C
可见,计算复杂度随着波形的数量变化;文章开头是启用了8八种波形的效果,但我们往往只需要计算坐标和法线。
实现的话只需要把公式算出来罢了

float3 GerstnerWave(float2 pos, float A, float Q, float T, float Phi, float D, out float3 normal)
{
   
    float3 outPutPos = float3(0.0f, 0.0f, 0.0f);

    float2 Dir = normalize(float2(cos(D), sin(D)));
    float Omega = (2.0f * 3.14159265f) / T;
    float WA = Omega * A;
    float Qi = Q / WA;
    float TSP = _Time.y * Phi;
    float fun1 = TSP + Omega * dot(Dir, pos);
    float cosFun1 = Qi * A * cos(fun1);
    float sinFun1 = sin(fun1);

    //P(x,y,t)
    outPutPos.x = Dir.x * cosFun1;
    outPutPos.y = A * sinFun1;
    outPutPos.z = Dir.y * cosFun1;

    //法线计算
    float2 P = float2(outPutPos.x, outPutPos.z);
    float tempValue = Omega * dot(Dir, P) + TSP;
    float cosFun2 = cos(tempValue);
    float sinFun2 = sin(tempValue);

    normal.xz = Dir * WA * cosFun2;
    normal.y = Qi * WA * sinFun1;

    return outPutPos;
}

叠加的部分,需要几次层得加几层

offsetVertex += GerstnerWave(v.vertex.xz, _A.x, _Q.x, _T.x, _Phi.x, _D.x, tempNormal);
finalNormal += tempNormal;
2. 效果

感觉很容易控制和调节,而且比较节省
在这里插入图片描述

Statistical Wave Models

1. 实用的海浪算法

基于FFT的高度场表达式
在这里插入图片描述
其中 t t t 是时间, k k k 是二维坐标,即水平坐标
在这里插入图片描述
n n n m m m 是整数,N、M是傅里叶变换的规模,必须是2的幂次方; L是网格的大小
在这里插入图片描述 在这里插入图片描述
x x x 为水平离散点坐标
在这里插入图片描述
现在,我们只剩 h ( k , t ) − \stackrel{-}{h(k,t)} h(k,t)未知了。

2. 建立随机的高度场

水波高度场的实现是由迄今为止详细阐述的原则:具有规定形式的空间谱的高斯随机数来实现的。这是直接在傅里叶域中实现的最有效的方法。波高场的傅里叶振幅可表示为
在这里插入图片描述在这里插入图片描述
其中, ξ r \xi_r ξr ξ i \xi_i ξi 是均值为0,标准差为1的高斯分布的随机数,分布形式的不同,会导致不同的效果。
原文中提到,对大量的海洋表面波浪浮标、照片和雷达测量数据的统计分析表明,波浪高度振幅几乎是统计上显著的、独立的、高斯波动,频谱统计均值可表示为:
在这里插入图片描述
有很多经验模型模拟 P h ( k ) P_h(k) Ph(k),其中 Phillips 比较常用
在这里插入图片描述
其中 L = V 2 / g L = V^2 / g L=V2/g ,V是风速,g是重力加速度, w ^ \hat w w^是风的方向。

现在,我们有了计算 h ( x , t ) h(x,t) h(x,t)所需的所有信息。

3. 优化计算

这个计算量明显要比上面的方法大太多了,为了把计算的复杂度降下来,除了尽量分离可预计算的参数之外,FFT必须得掌握
看了几篇文章,总结就是利用单位根的性质,计算基于点值表示的多项式,然后转换回去。

1. 基于点值的多项式计算

对于多项式
A ( x ) = ∑ l = 0 n − 1 a i ⋅ x i A(x) = \sum ^{n - 1}_{l = 0} a_i \cdot x^i A(x)=l=0n1aixi
把不重合的差值节点 ( x 0 , x 1 , x 2 , . . . , x n ) (x_0,x_1,x_2,...,x_n) (x0,x1,x2,...,xn) 分别代入 A ( x ) A(x) A(x),得到 ( y 0 , y 1 , y 2 , . . . , y n ) (y_0,y_1,y_2,...,y_n) (y0,y1,y2,...,yn),这就是多项式的点值表示法
仅仅是表示方法并没有降低计算复杂度,复杂度的降低主要依赖于单位根的性质。
在单位圆中,单位根 w n k w^k_n wnk可表示为:
w n k = c o s ( 2 π ⋅ k n ) + i ⋅ s i n ( 2 π ⋅ k n ) w^k_n = cos(2\pi \cdot \cfrac{k}{n}) + i \cdot sin(2 \pi \cdot \cfrac{k}{n}) wnk=cos(2πnk)+isin(2πnk)

  • 5
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
### 回答1: Mathematica是一种强大的数学计算软件,可以用来进行水面波动模拟。以下是一些可能有用的代码和步骤: 1. 定义水面高度的初始条件。可以使用正弦波或其他函数模拟波浪。 ``` height[x_, y_] := Sin[x + y] ``` 2. 计算水面的法向量。这可以通过计算高度函数的梯度来完成。 ``` normal[x_, y_] := {D[height[x, y], x], D[height[x, y], y], 1} ``` 3. 计算水面上的流体速度。这可以通过求解Navier-Stokes方程来完成。在这里,我们使用了一个简化版本的方程。 ``` velocity[x_, y_] := {D[height[x, y], y], -D[height[x, y], x]} ``` 4. 计算水面上的压力。这可以通过求解泊松方程来完成。 ``` pressure[x_, y_] := Laplacian[height[x, y], {x, y}] ``` 5. 使用以上定义的函数模拟水面波动。可以使用演化方程或其他方法进行时间积分。 ``` evolve[height_, dt_] := height + dt*velocity[x, y] + (dt^2/2)*pressure[x, y] ``` 这些代码可以用来进行基本的水面波动模拟。但是,要创建逼真的模拟,需要更多的复杂性和细节。 ### 回答2: Mathematica是一种用于数学建模和仿真的软件工具,它提供了丰富的函数和算法来处理各种数学问题。对于水面波动模拟,Mathematica可以使用其图形和物理引擎来实现。 首先,我们需要定义水面的初始状态。可以通过数学方程或离散点来描述初始水面的形状。然后,使用Mathematica的画图函数,可以将这个形状可视化出来。 接下来,我们需要建立数学模型来描述水面上的波动。根据物理原理,可以使用波动方程来描述水面上的波动。Mathematica提供了求解偏微分方程的功能,可以使用它来求解波动方程并得到波动的解析解。 如果要进行仿真,我们还可以使用Mathematica的数值解算功能。通过将偏微分方程转化为差分方程,并利用数值方法进行离散化和迭代计算,可以得到水面波动的数值解。 在仿真过程中,可以设置波动的参数,例如频率、振幅、波长等,以及水面的初始条件和边界条件。通过改变这些参数,可以模拟不同类型和形状的水面波动。 最后,可以使用Mathematica的图形功能将水面波动的结果可视化出来,例如绘制水面随时间的变化、水面上各点的位移等。 总之,通过使用Mathematica的数学建模和仿真功能,我们可以对水面波动进行模拟和分析,从而更好地理解水面波动的特性和行为。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值