19
\$\begingroup\$

I am looking for any input on simulating water in 2D, against a rather large (call it) blocked/not blocked array (viewed from the side). I have come up with the following ideas:

Cell Automata

Do a massively parralel simulation on the CPU, using cell automata. With rules as simple as:

  • If there is a cell open to the bottom move to it.
  • Check the left and right cells, choose a random one out of the two and move to it.

Pros

  • Simple to implement.
  • Meaningful/deterministic in a multiplayer system.

Cons

  • Probably really slow.
  • Not convincing.

Fluid Dynamics on the GPU

Perform a rough approximation of fluid dynamics on the GPU against a texture like the following:

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

Pros

  • Probably really fast.
  • Could be quite convincing.
  • A further pixel shader could render it directly.

Cons

  • Difficult to implement.
  • Difficult to tweak.
  • I can't allocate a single texture the size of my level.
    • I could overlap the grid areas, but this would add further complexity.

Particles

Use particles to simulate the water. During rendering using additive blending and then apply a multiplication function to the alpha channel to give the water crisp edges.

Pros

  • Will probably look nice.
  • Easy to implement.
  • Easy to render.
  • Meaningful in a multiplayer system, although would require quite a bit of bandwidth to transfer.

Cons

  • Inter-particle effects will probably be slow (neighborhood lookup).
  • Could lead to water 'leaking' through solid spaces (because the solid space is small, e.g. 1px).
  • Could lead to strange holes in the water depending on the particle size.
  • Both of the above could be mitigated by allowing particles to drift closer together than their real size, however would cause problems with the inter-particle and particle/landscape performance.

Any further ideas?

Note: This is an approximation, I am not looking for physically correct water here - just something that 'is good enough' (bonus points for quick and dirty). The game is multiplayer, so unfortunately the whole level needs to be simulated continuously.

\$\endgroup\$

1 Answer 1

12
\$\begingroup\$

every time I tried to simulate water I just ended up applying a lowpass filter on a texture representing water level. It's very simple to implement but it fails whenever you get massive changes in water level which may generate large waves. In this method there are some places where water always have some constant level, like river ends. in those cases you just over right color for that specific pixel.

Pros:

  • easy to implement
  • realistic results in case of calm waters
  • fast compute using GPU
  • easy to define static water levels or water sources

Cons:

  • unable to simulate waves

for wavy waters I use some way similar to your Cell Automata algorithm but with a small change that will let me use shaders to compute next step from current situation, here is a sudo code, again I've got a texture representing water level in each pixel color:

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;
}

this algorithm has features all similar to the previous one but it works better in wavy waters instead of calm ones. it your choice based on the sea you are simulating to use either one of them.

in the end you've got a texture which tells you water level for each position, in the next step you've got to draw results somehow, the easiest way is to generate a mesh based on water level data.

\$\endgroup\$
4
  • \$\begingroup\$ THanks, that's a brilliant answer. I'll leave the question open a while longer; but it seems like I have a knack for asking one answer questions around here :). \$\endgroup\$ Oct 10, 2011 at 22:09
  • \$\begingroup\$ you can also mix these algorithms to get a better results. \$\endgroup\$
    – Ali1S232
    Oct 11, 2011 at 8:06
  • \$\begingroup\$ How about a screenshot? \$\endgroup\$
    – ashes999
    May 15, 2014 at 22:02
  • \$\begingroup\$ @ashes999 I've got no screenshot, but here the same algorithm implemented! youtube.com/watch?v=avJPrL9UJ28 \$\endgroup\$
    – Ali1S232
    May 16, 2014 at 14:49

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .