Ocean Baker - GhislainGir/BlenderGameToolsDoc GitHub Wiki

Blender includes an Ocean Modifier that generates a realistic-looking ocean using the inverse Fast Fourier Transform, or iFFT. While this process is quite complex and often computationally intensive, it can be implemented in real-time applications. Sea of Thieves is probably the most famous example, using an iFFT implemented on the GPU via compute shaders.

Generating an ocean surface using the iFFT starts with creating a wave spectrum based on wind and other data. The most commonly used model is the Phillips Spectrum, which correlates wind velocity and direction with wave intensity across all frequencies, using analytical data derived from real-world observations.

This mathematical model produces a large set of wave amplitudes, frequencies, and offsets that simulate how real ocean surfaces behave under specific wind conditions. The frequency spectrum is then converted into the spatial domain using the iFFT, which results in XYZ displacement data applied to a tessellated water plane every frame.

If you're familiar with Gerstner waves, this process is similar to summing thousands of them—each with precisely tuned intensity, direction, amplitude, and offset to replicate realistic ocean movement. Calculating that many Gerstner waves individually isn’t practical, which is where the iFFT becomes essential. It leverages the GPU’s massive parallel processing power and shares results from redundant calculations, computing the entire domain in n log(n) time instead of n².

That said, it’s possible to get FFT-style ocean visuals without implementing the full algorithm or paying its performance cost—at the expense of interactivity, fidelity, and memory usage. Blender’s Ocean Modifier can be baked into a set of textures, typically including displacement (offset), normal maps, and optionally foam or crest data.

These textures can be sampled in various ways: stacked into a texture array on the GPU, stored as a 3D volume texture with each Z slice representing a frame, or packed into a flipbook texture.

Since this is a baked workflow, it comes with familiar limitations: what's baked is baked. Texture resolution must be managed to fit memory constraints. The ocean animation can't be changed at runtime, and you're limited to a fixed number of frames. This means the ocean must loop within a short timeframe so that the texture sequence can play in a continuous cycle.

Blender’s Ocean Modifier does support basic baking, but it doesn’t account for many limitations we need to handle ourselves—such as looping the animation seamlessly. The process can be a bit more involved, and making the ocean loop properly isn’t intuitive at first. Furthermore, depending on how you package the textures (array, volume, flipbook, etc.), certain precautions are necessary. For example, when using a flipbook texture, each frame tiles correctly on its own, but placing all frames side by side in a single texture can cause sampling issues at the borders. This is usually solved through padding or oversampling—a detail that’s not obvious initially and will be covered in more depth later.

This tool helps streamline the process of baking ocean data from Blender.

[!IMPORTANT] It is considered experimental because the bake process is extremely slow at the moment. Improvements have to be made in that area.

Even though this technique is quite old and comes with artistic constraints—like fixed resolution and looping—it’s extremely cheap to render. In fact, it’s been used successfully in high-profile games. Assassin’s Creed: Black Flag, for example, used FFT simulations baked into textures.

Additionally, the baked workflow offers some advantages. The buoyancy system can be greatly simplified. Since waves are precomputed, wave height at any given point can also be precomputed and stored in a CPU-friendly format, allowing for fast, low-cost sampling at runtime. This can be faster and easier to implement compared to traditional methods like asynchronous GPU reads or reimplementing FFT calculations on the CPU for buoyancy.