I understand that water ripples (e.g. stone thrown into a pond) are often handled with vertex shaders. My first question is: are the ripples nothing more than an algorithm that is the function of time?

If yes, it means that the size and diameter of ripples is not "additive." It means water vertices do not statefully "remember" their previous "disturbance" positions and accumulate more translation info. Rather it means that, as a function of time, the position of "disturbed" water vertices are freshly computed each frame per unit time.

If no, it means that indeed the vertices accumulate disturbance / translation information - the vertices are stateful.

I hope the answer is "yes," because that actually makes sense to me. If the answer is no, the I feel it creates tremendous burden on the CPU/GPU to keep track of all the state-per-vertice. If the answer is "neither," do tell. :)

My second question is, assuming a "yes" above, how does such a "water disturbance shader algorithm" account for continuous interaction with irregular shapes? For example, please look at the video 40 second mark showing a car crashing through water. It is not so clear how the vertex shader knows how to make a rectangular disturbance shape (the shape of the car). Perhaps, over-simplifying, the vertex shader takes both time and a vector to generate the ripples, where the vector is the speed/direction of a car (and the shader code always makes a car-shaped rectangle no matter what).

Is this the right high-level understanding of how this water trick works?

To answer your base question - a vertex shader does not modify the vertices of the mesh that it is acting on. A vertex shader is basically a transformation function that the vertices pass through when they are drawn. So vertices of the original model cannot accumulate movement.

So how is Dirt 2 doing its water effect? A bit of googling revealed this page that explains it:

An example of hardware tessellated dynamic water surfaces using DirectX 11 in DiRT 2. Many areas of the track are covered in water. The CPU generates the height field texture when cars drive through it. The tessellator using ATI Radeon hardware generates hundreds of triangles based on the camera position. The result: A beautiful, physically accurate, dynamic water surface. In the DirectX 9 version of the game, the surface is an illusion represented by just two triangles.

So to take a stab at decoding this to explain how it works on a technical level:

You have a texture (probably quite low resolution) that is generated each frame (or couple of frames) on the CPU that describes the waves that are moving through the water (probably height and velocity). Because it's on the CPU it can easily be accumulative.

On DirectX 9 you have the vertex shader reading that texture and displacing the vertices of the water mesh based on the values in that texture.

On DirectX 11, where, as well as vertex shaders, you have geometry shaders that can create vertices, it is also subdividing the water mesh to add additional detail. And it's probably generating that detail based off information originally coming from the texture describing the wave (adding small ripples and turbulence and so on).

(It wouldn't surprise me if the pixel shader is also using the same texture, generated by the CPU, to figure out where to draw foam on the water's surface.)

• This answer is out of date. Vertex shaders can output their data to buffers via "transform feedback" since 2012. So you can easily run a vertex shader that generates new vertices with ripples apply and next frame swap just like persistence with textures and swapping. – gman Nov 17 '20 at 19:29

Mystagogue: how does such a "water disturbance shader algorithm" account for continuous interaction with irregular shapes?

It is probably less irregular than you think. Wave propagation simply has a direction, time, a magnitude (amplitude), frequency, & some sort of dampening variable. In this case the direction is simply 90 degrees to the car's velocity.

Knowing the point of entry into the pond and the car's speed & direction (velocity), the propagation is simply calculated.

I am not entirely sure, but in the video you linked of Dirt 2, I believe the water is handled by a 2d height-map height map simulation of the water, and then that data is used by tessellation shaders to make a high resolution 3d displacement of the water without using too much GPU or CPU time.

Other games do something similar but use vertex shaders. I have seen some games that use pre-baked animations for the ripples and stuff so they are not additive, and some games use the 2d height map fluid simulation.

• If I understood, you are suggesting 3 common ways this is done? And one of those three is vertex shaders? If yes, then for a vertex-shader approach, is it indeed a time-based function (or time-based + impact vector)? – Mystagogue Sep 4 '10 at 19:46
• I am not entirely sure what you mean by "time-based function (or time-based + impact vector)" but here is a nice example and explanation of ripple simulation with a 2d java application. It is the pretty much the same kind of simulation that is used in 3d. neilwallis.com/java/water.html – AttackingHobo Sep 4 '10 at 20:31