# 渲染 - 水体模拟


## ***基础***

### ***波动方程***

$$
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} $*

#### ***方向***

![geogebra-export](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)
$$
*别忘记归一化，让法线变成单位向量哦~*


