top of page

Realtime Ocean Rendering

This is a project aimed at creating beautiful ocean surface inside unity

Using simple texture mapping

The most cost-effective method to render a patch of ocean is to use multiple noise texture to displace the water surface and use normal map texture. The displacement texture could be sampled with another position based distortion to enhance the randomness. Before displacing the vertices of the water plane, I've used the built-in tesselataion function in unity's surface shader to make the mesh denser to displace. Here I have used four noise texture for displacement and two texture for normal mapping. I've also added some form to areas with large wave displacement and near shore area. And added a fading to near shore area to get a smooth looking.

Displacement of original mesh

Close range result

Mid-range result

The limitation of this method is that we couldn't get a realistic look unless we spend a lot of time tuning those parameters. And if we are not very patient of the parameter tweaking work, we can easily get a result with artifacts of tiling. Texture scaling and distorted sampling can mitigate the problem, but to me, it is just too painful to be faced with a plethora of parameters.

Viewing from a far point causes tiling

Using fast fourier transform

The more accurate way to express ocean is by using oceanographic spectrum. But using this method we need a fast way to compute the added value of thousands of sin function with different wave number and frequency. Here FFT(fast fourier transform), a elegant and useful algorithm comes into play. It's an effective algorithm that can utilize the parallelism of hardware. Here I would like to use hlsl's compute shader to do the heavy lifting.

The most famous implementation of FFT is Cookey Tolley algorithm, but this algorithm needs a process of bit-reversal array reorder, which is expensive on GPU. However, another implementation of FFT is called Stockham algorithm. This algorithm avoids the bit-reversal reorder in Cookey Tolley algorithm, and thus could achieve better performence. In compute shader, we can set each kernel function of the shader to be a butterfly operator.

After implementing the FFT algorithm, I've used lenna's image to test its correctness.

(The color difference is due to unity's texture sampling)

Comparison of two FFT implementation

Left: Original picture      Middle: FFT Result      Right: IFFT Result

​Using oceanographic spectrum in Jerry Tessendorf's famous article "Simulating Ocean Water". Now we need a normal distribution to get the randomness in spectrum. Here I simply use numpy and matplotlib to generate a gaussian noise texture.

Another two compute shader were used to compute the time invariant and time dependent part of the spectrum, time invariant compute is only dispatched in the beginning, while time dependent compute needed to be dispatched per frame.

Unscaled displacement map and normal map

Displaced geometry

Rendered with normal

Rendered with scene

By using gpu based FFT, we can get an implementation of realtime rendering ocean. In my work, a ocean texture of 512*512 only takes about 0.2ms gpu latency(on RTX2070 super) to compute.

bdwhst's portfolio

©2022 bdwhst 版權所有。透過 Wix.com 製作的理想網站

bottom of page