Wave Mechanics

CS 482 Lecture, Dr. Lawlor

I claim simple wave dynamics requires only three variables:
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 N=C;
N.x+=vel*XvelChange;
N.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 vel=0.2, ht=0.2; // constants

vec4 N=C;

N.x+=vel*(L.z-R.z); // height gradient
N.y+=vel*(B.z-T.z);

N.z+=ht*(L.x-R.x+B.y-T.y); // velocity divergence
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.

Examples: