Real-time water rendering is required in many applications especially games. We not only want the water to be realistic in dynamics and appearance, but also want it to be rendered in realtime. In this work, we use GPU shading language NVIDIA Cg to render water in real-time. We simulate the water motion from physical model and render the effects such as reflection, refraction and caustics, etc.
A triangle mesh is used to represent the water surface. To simulate the motion of water surface, we dynamically undulate the water mesh and set the normal of the surface accordingly. We design the water surface model as a sum of modified sine waves. Since the parameters of the wave function have physical basis, it is easy to script the parameters. And even if it is not a physical simulation, the dynamic rendering of water can be still convincing. Moreover, the simulation runs entirely on GPU, so it is very efficient to calculate the water surface configuration.
We simulate the water surface by summing up sine wave functions.We sample the height and surface orientation of water at each vertex of the triangle mesh. If (x,z) is the horizontal coordinates of a sample vertex, then the height of the surface can be represented using the following equation,
where i is the index of wave, A is the amplitude, D is the horizontal crest traveling direction, w is the frequency, t is the time, and phi is the phase constant. The normal of the surface is calculated by the cross product of the binormal and tangent and can be represented by equation as,
The problem with the sine function when simulating the water is that there are too many rolls but not enough sharper peaks. The modified version of it is to offset the sine function to be nonnegative and raise it to an exponent k. The comparison between different wave functions with different k is shown by the figure 1. [Finch et al.] below. The larger k is, the sharper the peak we can achieve.
So we use the modified sine function as each individual wave function. In our implementation, we have four modified sine wave functions combined to generate the water surface and surface normal. The figure 2. shows the water mesh we generated.
To render the water suface, we need to capture the effect of interaction between light and water surface. Our lighting model for water can be represented as below,
surface_color = ambient + diffuse + specular_reflection + refraction.
We implement the lighting model using vertex shader and fragment shader. Next, we will discuss each component in detail.
The ambient term accounts for light coming from all directions, and the out going light is equal in every direction. We can write the ambient term as follows,
ambient = K_a x global_ambient.
The ambient term is illustrated as in figure 3.
The diffuse term accounts for directed light reflected off a surface equally in all directions. It can be written as,
diffuse = K_d x light_color x max(dot(N,L),0).
The diffuse term is illustrated as in figure 4.
The rendered water with ambient and diffuse light is shown in figure 5.
We consider mirror reflection when rendering the water. The environment mapping is used to simulate the water reflecting its surroundings. Figure 6. illustrated how to render reflection. The incident light (red arrow) direction is based on the eye ray (green arrow) according to mirror reflection. Then the incident light intersects with the cube map (purple square) and use the color of the cube map as the color of this fragment. And the figure 7. is an example environment map that we used.
The following video shows the result of water reflection.
The refraction is caused by light passing through the boundary of two material with different density. As illustrated by figure 8., when we look at the object under the water, the eye ray and light ray will saitisfy Snell's law. We also use cube map to get the color of the fragment by intersect the incident ray with cube map.
The following video shows the result of the refraction.
The caustics is a very important effect of light being focused due to reflection and refraction of water. When we look at the floor underneath the water, we can see moving bright area which shows the caustics effect. To accuratly simulate the caustics requires calculating the path of photons and is very time consuming in rendering. The goal here is to render caustics effect which looks realistic. Jos Stam proposed using animated caustics texture based on wave theory [Stam et al.].
Here we make the assumption about where the caustics can happen and use only a subset of the arriving light rays. And thus we can achieve visually realistic caustics in real-time. The transparency of water is between 77 and 80 percent per linear meter, thus between 20 and 23 percent of incident light per meter is absorbed by the medium. So the caustics will be formed easily when light travels the shortest distance from the moment they enter the water to the moment they hit the floor. It can be illustrated by figure 9. So for each point on the floor, we assume that it is lighted by the vertical light ray through the water. The light direction coming from outside the water is calculated by using Snells law. We can use a light map to get the incoming light, but here we approximate the light intensity based on where the sun is. And if the intensity of this light is strong, then we blend a bright color with the color of the floor at this point. Figure 10. illustrates how to calculate caustics.
Here is the video to show the result of the caustics effect.
Both water simulation and rendering are programmed in GPU using Cg shading language. Cg is a shading language designed by NVIDIA. The graphics hardware has come to the fourth generation. The GPUs provide both vertex-level and pixel-level programmability. Cg heritage comes from three sources, as shown in Figure . Cg bases its syntax and semantics on the general-purpose programming language. And it incorporates many concepts from offline shading languages such as the RenderMan Shading Language. Moreover, Cg bases its graphics functionality on OpenGL and Direct3D programming interfaces for real-time 3D.
The lighting calculation and reflection and rafraction are mainly written in framgment shader. And thus we can use Phong shading instead of Gouraud shading. Basically, Phong shading is interpolating normal while Gouraud shading is interpolating color. The problem with Gourand shading is the under mesh is obvious when the tessilation is not good enough. The comparison between Gouraud shading and Phong shading is illustrated by the following Figure 11.
1. "Effective Water Simulation from Physical Models", Mark Finch, Cyan Worlds
2. "Random Caustics: Wave Theory and Natural Textures Revisited", Jos Stam
3. "Rendering Water Caustics", Juan Guardado
4. "Cg tutorial"