Shallow-water Wave Equation in 2D
CS 493
Lecture, Dr. Lawlor
I claim simple wave dynamics requires three variables:
- X velocity
- Y velocity
- Height
X variation in height drives X velocity: steep cliff facing right
will resolve itself by fluid flowing to the right.
Y variation in height drives Y velocity the same way.
Velocity "divergence" drives height: if all velocities are
converging on one point, that point gets higher.
These three things should make waves. Let's try this
shader:
float XvelChange=L.z-R.z;
float HtChange=L.x-R.x;
vec4 new=C;
new.x+=vel*XvelChange;
new.z+=ht*HtChange;
This is exactly the discrete form of the partial differential
equations at Wikipedia for the shallow
water wave equations.
Stability
Sadly, this is unstable--it explodes into weird zebra patterns.
There's a simple fix: blur things out, by averaging the neighbor
values.
vec4 blur=0.25*(L+R+T+B); /* neighborhood average */
new=(1.0-blurFrac)*new+blurFrac*blur;
Instead, Wikipedia recommends pushing back against velocities: big
velocities will tend to damp out this way, but you need to add so
much
viscosity, nothing interesting happens. Piles of tar are not
known for their cool ripples.
Curiously, the unstable zebra patterns are almost prettier than the
waves we're trying to simulate!
2D ripples
Here's the full 2D version, with X and Y change:
float XvelChange=L.z-R.z;
float YvelChange=B.z-T.z;
float HtChange=L.x-R.x+B.y-T.y; /* = divergence of velocity */
vec4 new=C;
new.x+=vel*XvelChange;
new.y+=vel*YvelChange;
new.z+=ht*HtChange;
Initial conditions make a big difference: if you have nonzero X and
Y
initial velocity, then your waves will move at that velocity.
The "ht" and "vel" constants are related: the ratio is the scale
factor between initial height and velocity.
Try the WebGL
waves demo.