海浪
海浪

海浪

弄完1.3版本的海浪之后,记录一下,虚幻里面具体的实现就不讲了,主要是记录一下原理相关的东西,在houdini里实现。

我们先创建一个地形和水面

image.png

计算海浪需要的三个必要的数据我们先计算出来,分别是SDF 与 海浪的方向。

image.png

我们先用intersection analysis节点求的水面与地形的相交线,知道了相交线我们就可以求得SDF数据。

那么我们的 海浪的方向 应该怎么计算,可以试着把离岸的距离dist转换成高度,这样水面就是一个凹凸起伏的面,这样就能直观的看出来海浪的方向就是对应转换后的梯度。

image.png

求梯度的话,我们可以使用uvsample采样当前点的高度,然后将UV往x偏移一点再采样一次,偏移点减去当前点就是梯度的x方向啦。y方向同理。

image.png

之后就可以将我们求得的数据pack到一个V4向量中输出到引擎中使用。

image.png

我这里一共输出 SDF 、海浪方向 、垂直水深度(可以做些颜色变化)。

这便是制作海浪需要离线烘焙的地形相关数据

这里先介绍一下海浪的核心,怎样计算海浪的UV。

海浪计算原理

我们给个简单例子,先给下预先需要的数据。

image.png

f@dist = [email protected];
v@dir = set(1,0,0);
@Cd = @dist;

计算海浪的UV

UVX分量计算

$UV_x = Time + \frac{Distance}{Width} – offset$

因为我们的UV是只有0到1的,所以公式改为:

$UV_x = \mathrm{frac}!\left(Time + \frac{Distance}{Width} – offset\right)$

这个公式对应的图像为 图一是x随着dist和time变化, 图二是dist固定,x随着time变化

image.png

dd8bf8f4-fd2e-47af-9e4d-31ef8710b86c.png

image.png

UVY分量计算

$UV_y=\operatorname{clamp}!\left((Distance-UV_x)\cdot AnimeSpeed,;0,;1\right)$

这里只需要近岸部分播放一次动画,所以Y轴就直接限制再0到1,也可以将贴图Y循环设置为clamp

这个公式对应的图像为 图一是y随着dist和time变化, 图二是dist固定,y随着time变化

366700c3-bd8e-45df-8f86-3a212cf5cc15.png

d97218bf-0db8-492f-89e9-92edfdf1da6e.png

20250920210821_rec_-convert.mp4

这里可以看到UVy并不是渐变的,而是在UVx的一个0到1周期是以一个常数存在,这个常数会跟随时间从0到1的增加。

为什么要是这样呢?

海浪动画原理

海浪的动画依赖于一张置换海浪的置换动画贴图(RG为置换方向的forward和height,B为海浪白沫mask),为什么叫置换动画贴图,因为它既是海浪的置换贴图也是海浪的动画贴图。海浪的动画就是这张贴图从左到右滚动一边。这样我们的UV采样只需要使用上述式子就能得到海浪动画

image.png

image.png

20250920213102_rec_.mp4

当使用上述计算的UV去采样置换动画贴图

%E6%B5%B7%E6%B5%AA2.mp4

%E6%B5%B7%E6%B5%AA1.mp4

这样我们就能初步的得到一个能看的海浪,但是它的波浪太过整齐统一,想要解决这步很简单也很神奇,我们只需要对这个整齐的条带做个噪声偏移就好。

f@width = chf("width");
f@offset = chf("offset");
f@time = chf("time");
f@animespeed = chf("animespeed");

float distance = @offset - (1/@width) * @dist;
f@x = frac(distance - @time);

f@y = clamp((distance - @x)*f@animespeed,0,1);

//v@Cd = set(0,@y,0);
//v@Cd = set(@x,0,0);
v@Cd = set(@x,@y,0);
f@width = chf("width");
f@offset = chf("offset");
f@time = chf("time");
f@animespeed = chf("animespeed");
f@x_noise = ((sin(@P.z*0.242)*-0.135) - (cos(@P.z*0.752)*-0.0375))*10;
f@y_noise =  ((sin(@P.z*0.242)*-0.135) - (cos(@P.z*0.752)*-0.0375))*5;

float distance = @offset - (1/@width) * @dist;
f@x = frac(distance - @time + f@x_noise);

f@y = clamp((distance + f@y_noise - @x)*f@animespeed,0,1);

//v@Cd = set(0,@y,0);
//v@Cd = set(@x,0,0);
v@Cd = set(@x,@y,0);

%E6%B5%B7%E6%B5%AA3.mp4

%E6%B5%B7%E6%B5%AA3.mp4

这里我只是随便给了uvx和uvy一个噪声,我们的海浪效果就大致就算完成了。

如果我们以上述海浪动画带UVx和UVy噪声的直接套用在地形上,可以看到右边的海浪是正常的,左边的海浪则错误,这是因为置换的错误。

image.png

原来我们这里只做了一个方向的海浪,如果是多方向该怎么做,这里就要用到上面提到的预烘焙海浪方向数据。

@P+=set(@Cd.x,[email protected],0)*chv("offset")*chf("v");
@Cd = @Cd.z+0.5;
vector offset=set(@Cd.x,[email protected],0)*chv("offset")*chf("v");
float forward = offset.x;
float height = offset.y;

v@pos = @P;
@pos += 1*forward*v@dir;
@pos.y += height;
@Cd = @Cd.z+0.5;

@P = lerp(v@pos,@P,clamp((@dist-3),0,1));

当我们使用预先计算的海浪方向数据作为海浪置换的forward向量,就能得到一个往各个方向海岸拍打的海浪效果。

%E6%B5%B7%E6%B5%AA5.mp4

houdini文件

file

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注