involved technology: C#、Unity shader、compute shader
This project adopts the offline FFT method, uses compute shader to calculate FFT waveform, and pre-computes and renders a series of displacement, Normal, bubble map, load resources dynamically at runtime. For water coloring, the unity shader under the default pipeline is used to realize the water effect of gradation, refraction, reflection, wave tip foam, and shore waves.
It is implemented during my internship at Kingsoft. I was responsible for building the main algorithm of the FFT ocean, which is using compute shader. and also the offline implementation of baking the texture into keyframes. and the rendering of the water body, including reflection, refraction, the Fresnel term of water, foam, and also the Highlight.
For the ocean shape simulation, I read the paper 'Water Flow in Protal2' by Alex Vlachos, Valve (SIGGRAPH 2010) https://docplayer.net/235493-Water-flow-in-alex-vlachos-valve-july-28-2010.html, Water Technology of Uncharted (GDC2005)https://ubm-twvideo01.s3.amazonaws.com/o1/vault/gdc2012/slides/Programming%20Track/Gonzalez-Ochoa_Carlos_Water_Technology_Uncharted.pdf , Simulating ocean water[J] by Tessendorf J. (SIGGRAPH 2001) , GPU Gems1 and also Ocean Surface Simulation by NVIDIA 2004.
They both discuss how to use mathematical expressions for waveform simulations, including simple sine wave, Gerstner wave, and Gerstner wave superposition methods. As well as there is the use of Fast Fourier Transforms for ocean simulations, along with the need to use the empirical ocean model from the paper. And how to perform the acceleration algorithm for FFT. And how to generate the formulas of ocean height map, normal map, displacement map, and white foam map correspondingly after performing FFT calculation. The mathematical formulas and theories discussed in their paper are applied in my project for waveform simulation and height map calculation.
A fast Fourier transform is an algorithm that computes the discrete Fourier transform of a sequence, or its inverse. Fourier analysis converts a signal from its original domain to a representation in the frequency domain and vice versa. -Wiki
For the Offline baking options, I read the article FX Guide 2012, Assassins Creed III The tech behind or beneath the action,https://link.zhihu.com/?target=https%3A//www.fxguide.com/fxfeatured/assassins-creed-iii-the-tech-behind-or-beneath-the-action/ . the team talk about their experience of water shape simulations and also how they deal with the offline baking method.
What's more, as for the water rendering/shading part, I read the paper GPU Gems2, Using Vertex Texture Displacement for Realistic Water Rendering , Ocean Surface Simulation by NVIDIA 2004 ,and also the article Vector Displacement Mapping in Real-Time https://80.lv/articles/case-study-vector-displacement-mapping-in-real-time/. They discussed what to include in the shading part of the realistic water rendering, such as diffuse reflections, highlights, reflections, refractions, how to show translucency (usually using subsurface scattering), scatter, white foam, flow performance, and underwater fog effects.
The main Wave simulation of FFT ocean
Offline Texture was set up into running, and also the reflection, refraction and foam in the offshore was applied.
FFT Ocean Shape and Wave Simulation
The Offline FFT method was first used by the Assassin’s Creed 3 team.
The FFT ocean structure uses the Tessendorf Spectrum+Donelan-Banner+stockham FFT algorithm architecture and is Implemented on the compute shader.
The shape of the water body, the lighting effect, and the foam on the top of the wave are realized through the pre-calculated displacement, normal, and bubble map.
there are many fasten algorithms for FFT ocean such as the Stockham algorithms :
Here I am using the Stockham algorithms as fasten algorithms for FFT ocean which will be process in compute shader.
Pseudocode for parallel computing on GPU:
FFT(x,N, m, input) {
Ns = pow(2,m-1);//Ns is the size of the current iteration of the sub-transformation,m is the number of stages
//compute the input index
index = floor(x / (Ns * 2)) * Ns + x % Ns;//x is the location of the pixel point (pixel point horizontal x vertical y)
// calculate the weight W
angle = 2 * PI * (x / (Ns * 2)); w = (cos(angle),sin(angle));
// Multiply the complex numbers and add the output
x0 = input[index];
x1 = input[index + N / 2];//N is the entire fft texture size, representing several points of the FFT
return x0 + compldexMultiply(x1,w);
}
Offline Render - Save the height map, normal map, and displacement map As Keyframe
After we have built the algorithm for FFT Ocean,rather than calculate the maps each frame,we Save the calculated Render Texture as png for each frame; use Resources.load() to load the texture into the array for dynamic loading, Then change the corresponding texture in the material according to the time.
Here we baked a 32*32 resolution displacement map and a 128*128 normal map, baking a total of 128 frames. In the actual project, we found that a lower resolution of the displacement map would not have much impact. Here I use the compute shader to pre-calculate the texture data of the displacement map, normal map, and bubble map of 128 frames per frame, bake and save the data, and then load it into the shader for rendering when it runs. For the convenience of testing, I set the resolution to 512*512 first, but I can actually adjust it later.
This method requires a certain amount of memory to make the sequence frame, but it does not take up a lot of memory (it can be adjusted by setting the baked texture size and the sequence frame rate).
The realization of reflection and refraction obtains the corresponding reflection and refraction RenderTexture through the newly added camera in the screen space and transmits it to the water surface material.
The gradient of the ocean obtains the water depth by sampling the camera depth and the depth of the water surface, and then sampling the ramp map to construct the basic watercolor; the shore waves are constructed by obtaining the water depth. and use this way to achieve UV animation.
Comments