The following is a selected excerpt of Chapter 18 from GPU Gems 2: Programming Techniques for HighPerformance Graphics and GeneralPurpose Computation (ISBN 0321335597) published by AddisonWesley Professional.

Water surfaces are common in computer graphics, especially in games. They are a critical element that can significantly improve the level of realism in a scene. But depicting them realistically is a hard problem, because of the high visual complexity present in the motion of water surfaces, as well as in the way light interacts with water. This chapter describes techniques developed for rendering realistic depictions of the ocean for the game Pacific Fighters .
Modern graphics hardware provides a number of useful features with DirectX Shader Model 3.0 that can be used to aid the rendering of water surfaces. This chapter will discuss how one of these features, vertex texturing, can be used to increase the realism of rendered water surfaces. Figure 181 shows some sample results. In addition, we also use branching in order to improve the performance of our vertex programs.
18.1 Water Models
For water animation and rendering, a number of methods have been developed. The most remarkable and realisticlooking ones are those based on fluid dynamics and Fast Fourier Transforms (FFTs)(such as Tessendorf 2001). These methods provide very realistic results, but unfortunately they require substantial amounts of computation, making them inappropriate for interactive applications.


Figure 181. The Benefit of Displacement Mapping Water surface rendered (left) with displacement mapping and (right) without displacement mapping. 
At the other extreme, most games currently use very simple water models, most of which employ normal maps to create visual details. Unfortunately, these approaches cannot provide enough realism and do not faithfully reproduce waves on the surface.
We seek a technique that combines the speed of simple normalmapped waterrendering methods with the visual quality of FFTlike approaches.
18.2 Implementation
Our implementation builds upon rendering algorithms that employ normal maps for lighting calculations. Because normal maps faithfully reproduce fine detail in highfrequency waves, we use them for our lighting calculations. However, in addition, we perturb the water mesh geometrically with lowerfrequency waves with large amplitude.
18.2.1 Water Surface Model
Our model of a water surface is based on the superposition of several height maps, tiled in both space and time. Each texture represents one “harmonic” or “octave” of the spectrum, and the textures are added together as in Fourier synthesis. These textures are called height maps because each value represents the elevation of the corresponding point above the horizontal plane.
Height maps are great for artists: creating them is as simple as painting a grayscale image. See Figure 182. With height maps, artists can easily control the parameters of water animation down to individual waves by just painting their shapes. Height maps also work well as vertex textures: using them to displace vertex positions vertically is trivial.


Figure 182. A Height Map used for Water Displacement 
By combining several height maps with different spatial and time scales, we can achieve complex and visually intricate animations:
The coefficients A and B and the number of terms under the sum are chosen heuristically to achieve the most aesthetically pleasing results while minimizing repeatingpattern artifacts. In Pacific Fighters, we sum four height maps for lighting calculations, and two of them with the largest scale are used for displacement mapping. This is sufficient for simulating moving ocean surfaces at scales from 10 cm up to 40 km.
18.2.2 Implementation DetailsAll of the computations we need to perform can be classified into two groups: geometric displacement computations and lighting computations. Because our water surface is finely tessellated, it is reasonable to perform lighting calculations at the fragment program level, offloading the displacement mapping to the vertex stage. Also, performing lighting calculations at the vertex stage can create visual artifacts, especially in the distance.
At the time of writing, the only hardware capable of doing vertex texturing were GeForce 6 Series GPUs and the latest NVIDIA Quadro FX GPUs. The vertex texture implementation on this hardware has certain restrictions; in particular, vertex textures must be 32bitpercomponent textures, floating point, and they can't use any filtering mode except nearest filtering. Nevertheless, they proved to be very useful for the techniques described in this chapter.
18.2.3 Sampling Height MapsOur implementation samples the height maps per vertex and computes the resulting displacement value in the vertex program. For sampling, we use a radial grid, centered at the camera position. This grid is tessellated in such a way that it provides more detail closer to the viewer, as shown in Figure 183.
The following equations show how the vertex positions for the radial grid are computed.


Figure 183. Radial Grid for Sampling Vertex Textures 
With this approach, we naturally get distancebased tessellation, which provides a simple levelofdetail (LOD) scheme. Other approaches, such as the ROAM or SOAR terrainrendering algorithms, could be used here, but they require a significant amount of work on the CPU side, which would eliminate all the benefits of using vertex textures. See Chapter 2 of this book, “Terrain Rendering Using GPUBased Geometry Clipmaps,” for another approach to rendering height fields on the GPU with adaptive tessellation.
Listing 181 shows the simple vertex shader that implements sampling from a single height map with a radial grid.

float4 main( float4 position : POSITION,
// Transform to radial grid vertex
// Find displacement map texture coordinates
// Fetch displacement value from texture (lod 0)
// Scale fetched value from 0..1:
// Displace current position with water height 

Listing 181. Vertex Shader for Sampling from a Height Map Using the Radial Grid Geometry 