目录

渲染 - 水体模拟

基础

波动方程

$$ F(x) = A \cdot \sin(\frac{2\pi}{T}x + p) $$

参数介绍:

参数 作用
T 波长。数值越大,波越平缓(宽);数值越小,波越密集(窄)。
A 振幅。数值越大,波浪起伏越高;设为 0 则变回平面。
p 相位。改变它会让波浪产生位移,通常用来做动画。

平移和方向

平移

如果让水波要看起来匀速水平无限的循环移动,只要让 p 相位的数据不断地取波浪一个周期的数值就好了

具体的做法就是要知道每移动一个波长需要的时间:

根据 时间 = 路程 / 速度 可以得到: $$ SpeedCycle = \frac{T}{Speed} $$

  • T 就是波长,Speed就是自定义的变量速度,SpeedCycle 其实就是周期

我们来看这个公式,这个公式告诉了我们:自 time = 0 开始,我们跑了多少周期 $$ \frac{Time}{SpeedCycle} $$ 我们可以直接取他们的小数点,因为我们不在乎他跑了多少周期,只在乎他在当前周期跑了多少,小数点就是当前周期跑了多少百分比 $$ frac(\frac{Time}{SpeedCycle}) $$ 最后我们映射到弧度,因为 $ \sin{x} = \sin{x + 2\pi} $

方向

C:\Users\25718\Downloads\geogebra-export.png

看图 我们目前 想要水波朝着U向量前进,就得首先将U进行归一化,使其变成单位向量。

随后我们必须将sin波垂直于U向量,也就是将屏幕上的像素点都要通过点积算出在U向量的投影长度(只要投影长度相同的点,它们都处于同一条垂直于U向量 的直线上),并将它作为sin波的输入,这样就可以了。

形象的比喻:一把梳子,U向量是梳子的梳柄,然后梳子的齿就是一排排的波浪,点积的作用就是确定每一个像素点落在了哪一根“梳子齿”上,因为梳子齿永远和手柄是垂直的,所以你通过点积算出来的波浪也永远是垂直于方向的

点积公式: $$ \mathbf{u} \cdot \mathbf{v} = \vert u \vert \vert v \vert \cos(\theta) $$ 由于U是一个单位向量,所以$ \vert v \vert \cos(\theta) $就是 v向量在u向量上的投影

随后我们将这个放入我们的sin波方程: $$ F(x) = A \cdot \sin(\frac{2\pi}{T}x + p) \\ \\ F(x) = A \cdot \sin(\frac{2\pi}{T} (\mathbf{u} \cdot \mathbf{v}) + p) $$

法线的矫正

法线

什么是法线:在曲面上某一点,垂直于该点切平面(Tangent Plane)的向量,就是该点的法线(Normal)。

  • 切平面:比如你有一个足球,随便找一个点,然后你有一个硬纸板,你贴在这个点上,那么这张硬纸板在数学上就叫 切平面
  • 法线:你往这个硬纸板上插一根直立的吸管,那么这个吸管就是法线

我们怎么计算出法线:那么就是微积分中的偏导数了

偏导数

简单介绍:导数是求曲线的某一点斜率,偏导数则求曲面上某一点在特定方向(如 x 或 y)上的斜率。这两个斜率都是一个数。 / 切平面则是由两个偏导数(x 方向斜率和 y方向斜率)共同确定的一个平面

偏导数符号:$ \partial{z} $

对 x 求偏导: $$ f_x(x, y) = \frac{\partial{z}}{\partial{x}} = \lim_{\Delta{x} \to 0} \frac{f(x + \Delta{x}, y) - f(x , y)}{\Delta{x}} $$ 对 y 求偏导: $$ f_y(x, y) = \frac{\partial{z}}{\partial{y}} = \lim_{\Delta{y} \to 0} \frac{f(x, y + \Delta{y}) - f(x , y)}{\Delta{y}} $$ 求出法线:两个方向的切向量叉乘就是垂直于他们的法线 $$ \vec{Normal} = \vec{T} \times \vec{B} $$ 简化后的终极公式:这里就不展示过程了,大家可以推导一下 $$ \vec{Normal} = (-\frac{\partial{z}}{\partial{x}}, -\frac{\partial{z}}{\partial{y}}, 1) $$ 别忘记归一化,让法线变成单位向量哦~