Let me begin with some catch up since last time. My team has met with our sponsor Dr. Patton multiple times. We’ve produced requirements documents and design documents, we’re finally at the point where we can move beyond “starting” the process, and into building. (Though I naturally started looking into tooling, APIs, and the requested algorithms for my portion of the project long ago.)
So what did we design? We’ve been working on snazzy Earth-like environments for our simulation! Other teams have been assigned to particle physics, the core dynamics engine, and space environments, but my team get to build bits of our little blue marble to pla—I mean, do serious engineering work in! In order to build these environments best, my team has further subdivided into prototyping different environmental segments. Personally, I will be working on porting gasgiant’s ocean simulation to our shiny Rust game engine (Bevy). While the repository for gasgiant’s work is MIT licensed [1], it lacks comments—comments of any kind. It has hundreds of lines of really intricate compute shaders. Therefore I decided to avoid parsing that right away, and instead have opted to use the repo’s linked video [2] to help me conceptualize the situation.
I wouldn’t say I really understand the entire video, but I would say I have caught brief glimpses of understanding like rays of sunshine pouring temporarily through the trees of insecurity and confusion. And I would say that at one point or another every bit of the process has made sense to me. I’ve also managed to understand enough of the techniques that I could identify the main tasks that must be completed to proceed, and I managed to come up with a reasonable first goal. In order to explain that I will briefly summarize the video.
Ocean surfaces have a lot of waves on them (you may have noticed this, if not I don’t know how I can help you, but keep reading anyway!) These waves can be approximated by a thing called “Gerstner” waves. In these waves, each point on the wave moves in a circle over time. This creates a sharp “crest” that moves through space at the phase velocity.
Unfortunately, to get a realistic looking ocean surface, you need to add up a ton of different Gerstner waves, thousands in fact. In order to do this we can use a Fast Fourier Transform (FFT) algorithm to find the inverse Discrete Fourier Transform of a lot of these waves, which speeds up adding these together. (It’s a math thing. If you find the Fourier Transform of a given wave you’ll get a “description” of the summands of that wave. That “description” is just another wave showing frequencies. If you take that “description” wave, you can use the Fourier Transform again to get the original wave, this is the “Inverse” Fourier Transform.) Thanks 3Blue1Brown, you’re awesome. But seriously, if you don’t know what a Fourier Transform is, watch [3]. And also watch everything else from 3Blue1Brown because his content is amazing and wonderful.
Still, there’s a lot of complexity in coming up with the all those little waves of the original ocean surface. We do that by sampling randomly from various distributions based on environmental parameters like depth and the wind vector. The distributions we use come from lots of fancy oceanographic research, but once you have all those numbers, you can generate the Discrete Fourier Transform and feed it to the FFT algorithm. This facilitates finding the displacements of your vertices every frame.
I’ve decided to forego all the FFT stuff for now. Implementing those compute shaders is the real challenge, but as a first step I’m building a 2D Gerstner wave in a custom vertex shader. It will serve as a proof of concept, lay the groundwork for vertex displacement, and solidify my understanding of Gerstner waves. Great right?
Well that brings my post to a close. Hopefully you learned something, or laughed, or somehow enjoyed my little ramble about the math I’m in the midst of learning. I know I’ve enjoyed learning about this technique, and implementing the beginning of it in the (again sparsely documented) Bevy. I leave you with this, the first fruits of my labors (the normals are fine).
[1] https://github.com/gasgiant/FFT-Ocean