Finding Height In Gerstner Wave Function In World space.

1.4k Views Asked by At

Using the GPU Gems Article Effective Water Simulation From Physical Models I have implemented Gerstner Waves into UE4, I have built the function both on GPU for the tessellated mesh displacement and in code for the purpose of sampling height of the waves, but the issue I have run into is that the points by nature of the formula move away from their original points, so when using the gerstner function to get the height of a point, it is not necessarily at the point you are sampling so provides an incorrect height for that coordinate.

So somehow I need to solve for the point in the gerstner function that is actually lines up with the world position. I've taught myself enough to implement the waves, but i'm stuck on this solution, though I suspect there is some sort of matrix or way to take the inputs, apply the cos values and use it as a lookup for the actual point to sample. Any ideas and help is greatly appreciated.

For Reference the Gerstner Wave Formula

Formula Image

Q = Slope
L = WaveLength
A = Amplitude
D = Vector2 Direction
x = x world coordinate
y = y world coordinate
t = time
Where Qi = Q/wi * A * NumWaves
Where wi = 2pi/L
Where phase = Speed * 2/L

2

There are 2 best solutions below

0
On

Note I'm ignoring a lot of the variables for brevity Gerstner Waves vaguely simplify to y=sin(x) x = cos(x)

'Sample a vertical offset and send it somewhere that way horizontally' but we want the vertical offset of the point that landed here. We can guess where that point comes from by going backwards by the horizontal offset of our current position.

y = sin(x-cos(x))

This isn't perfectly accurate, but we can keep doing this to make it more accurate. But if we 'guess' again based on the position we've arrived at we can continue to get closer.

y = sin(x-cos(x-cos(x-cos(x)) or y = sin(x-cos(x-cos(x-cos(x-cos(x-cos(x)))) and so on

By the fifth time we've gotten a pretty accurate guess and I think five steps is about the right amount of times. This solution doesn't work if you step back an even number of times.

Obviously, this isn't very performant because it's about 5 times more complex than sampling a single point. But it's accurate enough for buoyancy.

Proof of concept: https://www.desmos.com/calculator/28taueduzs It didn't occur to me to step back multiple times until after I watched . this video at timestamp It's also a good idea to swap from Gerstner Waves to FFT as sampling a texture multiple times over is probably a lot cheaper than calculating the offsets multiple times over. Though FFTs are more complicated concepts to wrap your head around.

4
On

Solution that I use: $$ y=\frac{a}{2}\sin\left(\lambda x-a\cos\left(\lambda x-a\cos\left(...\right)\right)\right) $$ with:

  • $a$: wave effect strength
  • $p$: wavelength
  • $\lambda$: wave number, $\lambda=\frac{2\pi}{p}$

The post by Daniel Wells refers to a desmos graph using the formula $$ \begin{cases} y=ha\sin\left(w\left(x-a\frac{p}{\color{red}{8}}\cos\left(w\left(x-a\frac{p}{\color{red}{8}}\cos\left(...\right)\right)\right)\right)\right)\\ w=\frac{\color{red}{2\pi}}{p} \end{cases} $$

I don't get the use of the number 8 instead of 2π. It seems to lead to a beautiful curve in fewer steps but gives smooth results even for the maximum wave effect (a=1), when the wave is supposed to be spiky.