A common problem users of the Triton Ocean SDK encounter is blending the ocean with terrain at the coastline. The scenes in many simulators are expansive, stretching out for hundreds of miles from the viewpoint – and this can push the resolution of your depth buffer to the limit. Near the coastline, the surface of the water and the terrain below it may be very close to each other, and this can lead to “z-fighting” artifacts like this:

z-fighting artifacts resulting from coplanar water and terrain

Solving this problem can be challenging, but the very first thing to do is ensure your terrain contains accurate bathymetry data. If your terrain includes its own ocean surface geometry, drawing Triton’s ocean on top of it cannot work with normal depth sorting techniques. Bathymetry data means your terrain represents the ocean floor, and not just the ocean surface. With that information, we can compute the depth of the ocean as it nears the coastline, and smoothly blend it with the terrain at that boundary.

Just having a terrain database with bathymetry data isn’t enough, though – we need to provide that information to Triton somehow. We do this through height maps, a texture where each texel represents a floating-point height value the covers the area surrounding the camera. By providing this height map to Triton, its shaders can blend out the water as it becomes more shallow, leading to better transitions. If your simulation covers a fixed area, that height map might be pre-generated for the scene and remain static. But for most simulations, you’ll need to dynamically update this height map as the camera moves to cover the area around the camera. Usually this is done by rendering the scene in another pass top-down into the height map texture, with a shader that writes height values derived from each vertex, instead of color values.

An example of this is provided in the SDK’s osgDynamicHeightMapSample, seen here:

Blending of the Triton Ocean with coastal terrain in OpenSceneGraph

Compare that to the first image, from the same application but with height maps disabled!

Even with height maps however, sometimes that isn’t enough, and you need to take additional steps to squeeze whatever resolution you can in your depth buffer. If your coasts have really shallow, gently sloping water, the z-fighting may still be visible. Some more steps you can take:

  • Use a 32-bit depth buffer if possible
  • Maximize your depth buffer resolution by setting the near clip plane as far as possible, and the far clip plane as close as possible for the geometry in your scene
  • Use a logarithmic depth buffer
  • Adjust Triton’s simulated sea level to create more depth
  • Adjust the transparency of Triton’s water using Triton::Ocean::SetDepthOffset()
  • Edit your terrain to have better resolution near the coast, and ensure its bathymetry data is accurate
  • If you are using osgEarth, ensure you have properly integrated our user shaders with theirs

We’ve published several articles with more details; if you’re facing this problem, they are well worth reviewing:

Integrating Triton with terrain and shallow water
Using Height Maps with Triton: The Finer Points
Using an OpenGL Logarithmic Depth Buffer in SilverLining and Triton
A Logarithmic Depth Buffer Example.
Integrating osgEarth with SilverLining and Triton