Simulating Ocean Waves Using iFFT

I am trying to create an ocean wave generator which uses the iFFT (inverse fast fourier transformation) method, as shown in ths video. That program was created for Unity, but I assume the same is possible in three.js.

One of the best three.js versions I found was the is FFT_Ocean by Jeremy Bouny which is posted on GitHub. However, that program was written 6 years ago and is three.js r72. I have been attempting to create an upgraded variation of the program. Here is a modular version of the program, upgraded to r101. My latest variation is shown here on CodePen. To simplify, I have removed the portion of the code which creates a mirror surface.

The original version of this question asked using about how to use cascading (described in the video) to eliminate the tiling on iFFT wave generators - which is what the first two responses discuss. I am still interested in implementing cascading. But in order to do so, I need to have a working example of an iFFT wave generator, which is what I am trying to do now.

If I can upgrade the Bouny program to r150, I can try to add cascading to that program. Or I could use the program as a prototype for creating an iFFT wave generator using the “modern” method described in the video (and elsewhere). The Bouny program contains an excellent example of how to create a “buffer pipeline” which allows you to use shaders to make intermediate computations. So, even if I do not use the Bouny program, it will provide a useful template.

I have updated the Bouny program to r150 and have posted the result to a showcase. I plan to use what I have learned from studying that program to create a iFFT wave generator using the method described in the video. Once I have completed that, I will renew my request for guidance on cascading.

I have finally been able to convert the Bouny iFFT wave generator to work with my program. It creates both a displacement map and a corresponding normal map. I use a scrolling map with an inner 16x16 grid of square planes with 256x256 segments each. On outer grids, I use only the normal map with a flat plane (no segments.)

However, I now have to address the original problem - how to avoid tiling. This is especially a problem in a flight simulation where there are large changes in altitude.

The following three programs illustrate my problem nicely:

  • 800m squares (1/2 mile) - sharp close to surface, tiling apparent above 500 ft.
  • 1600m squares (1 mile) - a bit fuzzy close to surface, tiling apparent above 2.5k ft.
  • 3200m squares (1.5 mile) - fuzzy close to surface, tiling apparent above 10k ft.

So I am searching for a way to accomplish both objectives - sharp close to surface and no tiling until at least 10k.

In connection with the iFFT method, some have mentioned using “cascading” textures, which involves splitting the frequencies, to that low frequency waves are drawn farther away and high frequency wave are drawn closer. (The iFFT uses a fixed frequency spectrum.) However, I am not sure how to implement that here.

Another alternative that I am considering are somehow overlaying a random perlin-type noise over, say, 4 adjacent grids. Perhaps I could pre-define the 4 squares as planes with vertices that are already displaced and the displacement map would merely displace them further so that the edges would still match. But would having 4 different types of squares slow things down too much?

Any other ideas?

1 Like

Although the image below is not about FFT (it is about Perlin noise), I think the concept is similar.

Different frequencies provide different scales of variation. One of the maps is about the big waves, and another map is responsible for normal waves and a third map is for the tiny ripples. For waves that are far away, the ripples are not visible, so there is no sense to spend computational efforts for their calculation.

This illustration shows three maps separately and then combined. The goal is to have high resolution details near you, but low resolution far away from you.

So, the area near the view point should combine all waves – the big ones, the normal ones and the ripples.

1 Like

Yes, I think that is what is going on.

On my program, I used scrolling nested 9x9 grids which all shared the same geometry. So I could simply make changes to one geometry and it would affect all. This was fast, but there would be visible tiling.

In contrast, many other ocean simulations, including the Bouny FFT simulation, appear to use a non-scrolling single grid. On the Bouny similation, the tiling appears to result from allowing tiling within the grid. I expect that a simple cascading version would have non-scrolling nested grids.

But I have seen even more complex grid systems, including circular ones. I am hoping there is a cascading FFT out there that is not too complex…

1 Like