如何为抽象的2d自上而下的水纹理制作动画?


24

我目前正在实施一款具有自上而下的海洋景观的游戏。我使用以下抽象纹理:在此处输入图片说明

实际的纹理是透明的,为清晰起见,我添加了绿色。

我现在遇到的问题是,我不知道如何为该纹理设置动画,因此水看起来不错。我试图用正弦波移动纹理: texture.y += sin(angle)。当然,现在整个纹理正在移动,这看起来有点不现实。我尝试的下一件事是添加另一层并实现视差效果。这样,水面下的反射也会移动,但速度要慢得多。看起来好一点,但还不够好。

我认为,如果单个单元会膨胀和收缩,则外观最好的动画就像是一块网或一块布。想象一下,如果有人稍微拉动这些单元格的一个顶点,而相邻的单元格会扩张,而我拉向(或推向)的单元格就会收缩。有点像弹簧网(?)。但是我不知道如何实现这样的事情:

  • 什么是数学模型?带有弹簧的东西,力在哪里推/拉?
  • 如果是这样,如何将模型映射到给定的纹理?保持所有曲线,不保持曲线...

(我也对如何为给定的纹理设置动画有不同的想法/答案。现实主义并不是这里的重点,只是一些像运动一样漂亮的水...)

DMGregory的解决方案

我在这篇文章中发布了一个libgdx示例:2d水动画呈锯齿状且不平滑(请参阅有关纹理过滤的答案)

Answers:


41

这样做的一种常见方法是在着色器中使用间接纹理查找来扭曲显示纹理:

显示水动画的gif动画

在这里,我使用的是带有一些低频色彩噪声的纹理(平铺随机颜色的平滑斑点),并随着时间在整个显示几何体上滚动。

在此处输入图片说明

我没有从该纹理绘制颜色,而是取了红色和绿色通道,然后进行减去0.5f以将它们转换为伪随机2D向量,该向量随时间和空间而平滑变化。

然后,可以在从主要水纹理采样之前,将此向量的一小部分添加到我的UV坐标中。这会改变我们正在读取和显示的纹理的一部分,从而使其变形。

通过从该噪声中平均两个样本,并沿相反方向滚动,我们可以隐藏运动方向,因此看起来就像是无目标的晃动。

在Unity中,着色器看起来像这样-应该足够简单,以转换为您选择的着色器语言:

fixed4 frag (v2f i) : SV_Target
{               
    float2 waveUV = i.uv * _NoiseScale;
    float2 travel = _NoiseScrollVelocity * _Time.x;

    float2 uv = i.uv;
    uv += _Distortion * (tex2D(_Noise, waveUV + travel).rg - 0.5f);
    waveUV += 0.2f; // Force an offset between the two samples.
    uv += _Distortion * (tex2D(_Noise, waveUV - travel).rg - 0.5f);

    // Sample the main texture from the distorted UV coordinates.
    fixed4 col = tex2D(_MainTex, uv);

    return col;
}

1
这看起来真的很好。我不确定我是否了解所有属性:_NoseScale =用于缩放“噪声图”的标量。_NoiseScrollVelocity = Vector2,我们在噪声图上以该速度移动。_Noise =?。_Distortion =标量我选择作为失真因子?v2f =顶点,我们确定颜色。我=?
morpheus18年

_Noise是[纹理采样器,从上面的小块随机纹理读取。v2f i是来自顶点着色器的插值数据-我们主要使用它来获取要绘制的像素的纹理坐标i.uv。您对其他所有内容都完全正确。
DMGregory

我已经实现了着色器,但由于某种原因它无法正常工作(它无法移动或变形过大),我认为我没有正确设置值。时间=与上一帧的时间差(以毫秒为单位)。noise_scale = 1(我使用您的纹理,使用环绕模式重复)noise_scroll_velocity = [0.01,0.01]失真= 0.02
morpheus05

请注意,该变量称为时间,而不是DeltaTime。如果您使用时间上的差异,并且帧速率是一致的,那么您将始终获得相同的数字,并且将使用相同的输入重新运行着色器,获得相同的输出(不动)。更糟糕的是,如果帧速率不一致,则会来回振动。您要经过的总时间,而不是增量时间。
DMGregory

很快我就发送了,我意识到这一点,现在几乎可以了。动画似乎从右下角倾倒了波浪,大约10秒钟之后,它逐渐消失,就像波浪停止了一样。这可能是什么原因?
morpheus18年

6

这称为腐蚀效应,并且在运行时生成这些效应非常耗时,因此传统上是使用预渲染的逐帧动画来完成的。有些工具可以为您生成苛刻的动画帧,例如Caustics Generator,该工具具有非商业用途的免费版本。您还可以以比我提到的工具的专业版便宜得多的价格购买一些预制的产品。

注意,苛性效应通常也是在水下地形或水下表面上以光饼干形式施加的效果。就是说,向下注水时将其放在水面通常不是水的样子。


很有意思,我也将看看这个生成器(不过,如果我理解的话,我将尝试着色器变体...)
morpheus05 18/09/14

4

这看起来像可以从voronoi图生成的纹理,例如:

在此处输入图片说明

您可以通过移动点来对图形进行小而平滑的调整。每帧重新绘制图形会非常昂贵,因此您可能需要预渲染动画。


4
过去我实际上是在着色器中以这种方式渲染焦散的。它不一定像您想的那样昂贵(这是在WebGL着色器中实时渲染Voronoi边缘的示例),尽管要在边缘上获得正确的平滑形状-而不是尖锐的多边形-可能具有挑战性。
DMGregory

噢,那很好。我有一些地形生成器,对于它们来说非常方便。
FacticiusVir

0

有一种老式的方法,包括底部纹理层和两个半透明纹理,用于在顶部反射。

如果您想一直前进,并且不让水看上去充满克隆的波浪或蓝绿色的汤,那么就可以实现流程图。

https://steamcdn-a.akamaihd.net/apps/valve/2010/siggraph2010_vlachos_waterflow.pdf


3
尽管链接可能会有所帮助,但它们永远不会给出正确的答案。您能同时介绍这两种方法吗?如何实施呢?
Vaillancourt

第一种方法基本上是用于动画水的一种非常古老的方法-您获取基本层水纹理,该纹理的UVW坐标会移至您选择的方向。现在,您另外应用了一个法线贴图/凹凸贴图,您可以将其切换到另一个方向-如果操作得当,对于小河流来说,这看起来很有说服力。尽管对于大型水域来说,它非常有限-因为任何聚集波浪的物体都会产生波纹效应。链接比我可以更好地解释流程图的使用。
皮卡

请使用编辑功能通过此处添加的内容来改善问题:)人们习惯于在帖子中寻找答案,而不是在评论中寻找答案。
Vaillancourt
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.