Compute Water Surface Sample

Category:  Visuals
Min PC GPU: Fermi -based (GTX 4xx)
Min Tegra Device: Tegra K1


This sample demonstrates dynamic, interactive water surface animation using compute shaders

APIs Used

Shared User Interface

The OpenGL samples all share a common app framework and certain user interface elements, centered around the "Tweakbar" panel on the left side of the screen, which lets you interactively control certain variables in each sample.

To show and hide the Tweakbar, simply click or touch the triangular button positioned in the top-left of the view.

Other controls are listed below:

Device Input Result
touch 1-Finger Drag Orbit-rotate the camera
2-Finger Drag Move up/down/left/right
2-Finger Pinch Scale the view
mouse Left-Button Drag Orbit-rotate the camera
Right-Button Drag Move up/down/left/right
Middle-Click Drag Scale the view (up:out, down:in)
keyboard Escape Quit the application
  Tab Toggle Tweakbar visibility
gamepad Start Toggle Tweakbar visibility
  Right Thumbstick Orbit-rotate the camera
  Left Thumbstick Move forward/backward. Slide left/right
  Left/Right Triggers Move up/down

Technical Details


This sample shows how compute shaders can be used to implement height field-based water simulation techniques on the GPU, and use the results for rendering.

In this technique, the water surface is represented as regular grid with height and velocity values for each point.

Compute shader is used for surface transformation and computation of normals, which are required for realistic rendering.

Rendering Procedure:

  1. In the first pass, the compute shader calculates updated velocity vectors per water height map sample. New height values are computed for each point via integration, and the results written into a temporary buffer.

  2. In the second pass, the compute shader calculates water surface normals at each point via gradients, and updates the resulting data.

  3. The vertex shader accesses the resulting height and normal data to compute fresnel and reflection vectors.

  4. The fragment shader uses the fresnel and reflection vectors to draw, shade, and reflect the surface.

UI options:


Compute shader:

Height and velocity data is stored in regular buffers, which are used as input attributes to the vertex shader.

  1. Height Computation Pass

    1. Update the velocities using a nearest-neighbor distribution formula.

    2. Apply a damping factor to the current velocity.

    3. Update height value into temporary compute buffer.

    4. Apply a "disturbance" function to the temporary height value.

  2. Normal Computation Pass

    1. Compute surface normals and write into the gradients buffer.

    2. Copy temporary height data into output height field buffer.

Vertex shader:

The two result buffers from the compute shader stage (heights and normals) are bound as regular vertex attributes in the vertex shader stage.

The vertex shader does the following:

  1. Fetches gradients from the compute buffer and computes the normal for the vertex.

  2. Fetches the height value from the compute buffer and calculates the position of the vertex.

  3. Transforms and projects the vertex.

  4. Computes the fresnel term, reflection and refraction vectors and passes them to the fragment shader.

Fragment Shader:

The fragment shader fetches a texel from the environment map (a cube map texture) using the reflection and refraction vectors, and blends between them using a fresnel term.

See Also



NVIDIA® GameWorks™ Documentation Rev. 1.0.220830 ©2014-2022. NVIDIA Corporation and affiliates. All Rights Reserved.