By tinkering over the course of a few nights, I wound up writing this little fluid simulation. As it turns out, most of the computation performed wound up on the CPU, so it was taxing little more than the transfer rate of my AGP 4x bus. However, it does shun vendor-specific extensions in favor of multipass rendering to layer the specular highlights onto the texture map.
The fluid patch is implemented using a height field; normals and other epiphenoma are derived from the vertex positions. Texture coordinates are calculated using Snell's law, by putting the texture on a virtual plane behind the fluid patch.
The simulation itself isn't really that interesting from a mathematical standpoint - I was just experimenting, so all the code is ad hoc. The positions are animated using different models. For liquids, linear combinations of many simple closed-form sinusoidal decay solutions are used. For the gooey-looking ones, a simple spring/damper model is used.
(Browsing this code ten years later, I can say that this being my second C++ program, the code stank a bit less than the cube solver. :P )
Be sure to pick HD if available over your connection... the low-resolution version looks like a tie-dye cow.
Lessons learned (or points confirmed):
- Programmer art sometimes far outlives its intended longevity... As of this writing, 10 years later, I still haven't replaced that Paint-produced bitmap.
- Stuff doesn't necessarily need to be complicated to look decent. In fact, the simpler it is, the easier it usually is to tweak the way you want it. (Recall that this was in year 2000; register combiner cards were still quite mainstream.)