As I am currently working on a surfing game for the oculus rift, having a high-quality water shader is essential. The problems is that existing water shaders for unity are mostly designed to work with flat water planes and not with complex three dimensional bodies of water as seen in breaking waves. So I decided to write a new custom water CG shader from scratch:
Reflection and refraction color are both sampled from a skymap and an additional directional light. They are then blended according to the Fresnel Equation which depends on surface normal and viewing direction. The surface normals are modified by multiple combined uv map scales and offsets to simulate wave movement.
Absorption in the fluid is calculated according to the Beer–Lambert law, providing separate red, green and blue absorption coefficients. This determines the perceived color of the fluid and can be adjusted to simulate the dark blue of deep ocean water or the greenish tint of shallow coastal water. The amount of absorption requires the thickness of the object, which is calculated in screen coordinates in a separate pass by first adding up the distances of all the back-facing surfaces and then subtracting the distances of all the front-facing surfaces (Greg James, 2003). Finally, The Henyey-Greenstein phase function is used to approximate the Mie in- and out-scattering in the fluid, depending on viewing- and light angle.
Tough not yet optimized, the shader performs reasonably well on a integrated laptop graphics card. As it will be used for a surfing game were the water is not considered a "prop" but is actually the main point of focus, good looking water is a key factor and is certainly worth a big chunk of the time- and performance budget.