二维水模拟的想法


18

我正在寻找相对于一个较大的(称为)阻塞/非阻塞数组(从侧面观察)在2D中模拟水的任何输入。我提出了以下想法:

细胞自动机

使用单元自动机在CPU上进行大规模并行仿真。使用简单的规则:

  • 如果底部有一个开放的单元,则移至该单元。
  • 检查左侧和右侧的单元格,从两个单元格中随机选择一个并移至该单元格。

优点

  • 易于实现。
  • 在多人游戏系统中有意义/确定性。

缺点

  • 可能真的很慢。
  • 不令人信服。

GPU上的流体动力学

针对如下所示的纹理在GPU上执行流体动力学的粗略近似:

+------+-----+-----+-------+
|R     |G    |B    |A      |
+------+-----+-----+-------+
|vX    |vY   |NULL |Density|
+------+-----+-----+-------+

优点

  • 可能真的很快。
  • 可能非常令人信服。
  • 另一个像素着色器可以直接渲染它。

缺点

  • 难以实施。
  • 难以调整。
  • 我无法为我的水平分配单个纹理。
    • 我可以重叠网格区域,但这会增加进一步的复杂性。

粒子

使用粒子模拟水。在使用添加混合进行渲染的过程中,然后将乘法函数应用于Alpha通道以赋予水脆边缘。

优点

  • 可能看起来不错。
  • 易于实现。
  • 易于渲染。
  • 尽管在多人游戏系统中需要大量的带宽才能传输,但这仍然有意义。

缺点

  • 粒子间的影响可能会很慢(邻居查找)。
  • 可能导致水通过实心空间“漏出”(因为实心空间很小,例如1px)。
  • 根据颗粒大小,可能导致水中出现奇怪的孔。
  • 可以通过允许粒子比实际大小更靠近一起漂移来缓解上述两种情况,但是这会导致粒子间和粒子/横向性能出现问题。

还有其他想法吗?

注意:这是一个近似值,我在这里不是在寻找物理上正确的水-只是“足够好”的东西(快速和肮脏的加分点)。该游戏是多人游戏,因此不幸的是,整个关卡需要不断进行模拟。

Answers:


12

每次尝试模拟水时,我最终都会在代表水位的纹理上应用低通滤镜。它的实施非常简单,但是只要您的水位发生巨大变化(可能会产生大波浪),它就会失败。在这种方法中,有些地方的水总是保持一定的水位,例如河边。在这些情况下,您只需为该特定像素设置正确的颜色。

优点:

  • 易于实施
  • 在平静的水域下可获得真实的结果
  • 使用GPU进行快速计算
  • 易于定义静态水位或水源

缺点:

  • 无法模拟波浪

对于波浪状的水,我使用与“细胞自动机”算法相似的方法,但有一点小的变化,这将使我可以使用着色器从当前情况计算下一步,这是一个sudo代码,再次,我有一个表示水位的纹理像素颜色:

foreach (pixel p) in oldTexture
{
    newtexture.pixels[p.x,p.y]    += p.color / 5;
    newtexture.pixels[p.x+1,p.y]  += p.color / 5;
    newtexture.pixels[p.x-1,p.y]  += p.color / 5;
    newtexture.pixels[p.x,p.y+1]  += p.color / 5;
    newtexture.pixels[p.x,p.y-1]  += p.color / 5;
}

该算法具有与上一个算法相似的所有功能,但是在波浪水域而不是平静水域中效果更好。它是根据您正在模拟使用其中任意一种海洋而选择的。

最后,您将获得一个纹理,该纹理可以告诉您每个位置的水位,在下一步中,您将以某种方式绘制结果,最简单的方法是根据水位数据生成网格。


谢谢,这是一个绝妙的答案。我让问题待一会儿再说。但似乎我很想在这里问一个答案:)。
乔纳森·迪金森

您还可以混合使用这些算法以获得更好的结果。
Ali1S232

屏幕截图如何?
ashes999 2014年

@ ashes999我没有屏幕截图,但是这里实现了相同的算法!youtube.com/watch?v=avJPrL9UJ28
Ali1S232 2014年
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.