Skip to content

Streaming Terrain Details

kring edited this page Sep 21, 2012 · 51 revisions

When you fire up Cesium for the first time, the first thing you probably notice is the high-resolution imagery data. As you zoom closer, however, you notice that the Earth is just a smooth spheroid. Where's the terrain?

High quality terrain visualization dramatically increases the realism of a virtual globe. For that reason, it is one of our highest priorities to bring high-resolution, streaming, world-wide terrain to Cesium.

Fortunately, large-scale terrain rendering is a well-researched problem. It still, however, presents a number of significant engineering challenges, some of which are described on this page.

This is an area that has plenty of opportunities for interested folks to get involved and contribute. If that's you, please introduce yourself on the development mailing list.

To Do List

Streaming terrain implementation is currently taking place in the imagery_layers branch. Here's our wildly-incomplete to-do list:

Before merging imagery_layers into master:

  • Check the list of requires in our changed files to see if we can eliminate some.
  • Look more closely at the API - what happens when "public" properties are changed after construction?
  • Improve tests and documentation.
  • Improve the replacement policy. Currently it simply keeps the tiles that were used last frame, mostly.
  • DONE Fix Mercator projection in Columbus View.
  • DONE Fix Mercator projection during morphing.
  • DONE Switch EllipsoidTerrainProvider to Geographic by default.
  • DONE Fix Mercator projection in 2D and Columbus View when using Geographic-projection terrain.
  • DONE Make the geometry render correctly with zero textures instead of just not showing it.
  • DONE Make sure Web Workers work in all environments: separate js files, combined Cesium.js, Dojo build, etc.
  • DONE Clean up map projections and tiling schemes. There's too much overlap.

Later:

  • Do we need to light the terrain/imagery? We can do that by including normals in terrain vertex arrays, using a normal map, or maybe by using a fancy technique like screen-space ambient occlusion.
  • Improve tile culling. Bounding spheres don't fit terrain tiles very tightly.
  • Add support for switching terrain providers after rendering has started.
  • Allow imagery detail to increase independent of increasing terrain detail.
  • Support more textures per tile than are directly supported by the GPU.
  • Set up a simple terrain server to host the default Cesium terrain.
  • Set up a more sophisticated terrain server with better data, meshes instead of heightmaps, geometric error information, etc.
  • Don't round-trip Mercator imagery to Geographic and back when using a Mercator projection in 2D or Columbus View.

Data sources

Cesium supports the following source of terrain data:

EllipsoidTerrainProvider

A very simple terrain provider that matches the WGS84 ellipsoid. In other words, the terrain height is 0.0 for the entire world.

ArcGisImageServerTerrainProvider

Provides elevation data downloaded as heightmaps from an Esri ArcGIS ImageServer.

This terrain provider can connect to any ArcGIS ImageServer. However, the connection to the ImageServer must be proxied through the /terrain/ service included with the Cesium Jetty-based web server, or an equivalent service. This is because the full-resolution heights are only offered in TIF format, and because most browsers can't read TIF files.

The /terrain/ proxy retrieves the TIF file from the ImageServer and then converts it to a specially-encoded, 24-bit PNG for transfer to the browser. To produce the PNG, the proxy first adds 1000.0 meters to the height and then multiplies it by one thousand. You can think of this as a height, in millimeters, above -1000.0 meters from the ellipsoid surface. Then, the transformed height is encoded as a 24-bit integer where the red channel has the highest-order byte, the green channel has the middle-order byte, and the blue channel has the lowest-order byte.

Esri hosts such an ImageServer loaded with high-quality terrain data, and details can be found here: http://www.arcgis.com/home/item.html?id=d3742572150f4fb5b22739fe94dea260

It is tempting to ship Cesium with this terrain source pointed at Esri's elevation service out-of-the-box, but we should avoid doing so for the following reasons:

  • The service is in beta.
  • We would have to pass on Esri's licensing requirements, which mandate that the service be used for non-commercial purposes or by Esri's existing customers.
  • The elevation heightmaps are not cached on the server, so the response time from the server is not as high as we'd like.
  • The proxy requirement, as described above, adds latency and complexity to the system.

TileMapServiceTerrainProvider

Provides elevation data downloaded as heightmaps from a TileMapService (TMS) server.

Currently, this terrain provider assumes that the tiles use a geographic projection, it has 12 levels of detail, and that the heights are encoded in PNG files as described for the /terrain/ service above. There's lots of opportunity for generalization.

WebMapServiceTerrainProvider

Provides elevation data downloaded as an array of heights from a Web Map Service (WMS) server via XMLHttpRequest.

Currently, this terrain provider assumes that the tiles use a geographic projection, it has 18 levels of detail, and that the heights are represented as a simple array of 16-bit integer heights, in meters. If serving WMS via GeoServer, you will need to use the DDS/BIL extension. We also recommend that you use the CORS Filter (or something similar) to allow your WMS server to be accessed from other domains.

This terrain provider needs a lot more work to be made applicable to a wider variety of WMS situations.

Future terrain providers

  • A terrain provider that downloads cached meshes, rather than heightmaps like the terrain providers above, using XMLHttpRequest. In the future, we may provide a server that can be loaded with terrain data which is then converted to simplified meshes for efficient streaming to the client.

Hosting our own terrain data

We want Cesium to have great terrain out of the box, and that means we need to host the terrain data ourselves.

Some potential sources of terrain data that we can use to populate our own terrain server:

Our server will likely serve terrain geometry as simplified meshes, rather than heightmaps, because these enable us to put the detail where it is needed. However, there are advantages to heightmaps as well. This paper describes a technique for minimizing error when generating simplified heightmaps.

Rendering ideas

  • Client-side (approximate) level-of-detail control.
  • Show terrain in Columbus view.
  • Interesting ways to morph terrain during transitions?
  • 2D - what happens to terrain? Bump mapping?
  • Rendering
    • Fill cracks between tiles. How can our screen-space work for ellipsoid tiles be adapted? Plan B - skirts.
    • Popping artifacts. Morph between LODs? Do nothing?

Longer term

  • Pick on terrain and get exact position - not dependent on terrain LOD.
  • Does laying down z first improve performance? Horizon views only? Is walking the tree in front-to-back order enough?
  • Procedural shading by height, slope, etc.
  • Efficiently encode terrain data for transmission:
    • Use the Google Body techniques, encoding the mesh as a UTF-8 string: http://code.google.com/p/webgl-loader/wiki/BenCompressionStats
    • Encode each tile as a delta from its parent:
      • Parent tile indicates which of its vertices are in which quadrant with index ranges.
      • Child has new vertices, index list linking parent and child vertices into triangles, and new index ranges describing the division of its vertices among its child quadrants.

Vector Data

  • Polygons on terrain - probably shadow volumes
  • Polylines on terrain - perhaps see if we can use our SIGGRAPH work without a geometry shader.
  • Billboards that do not partially sink under terrain.

Resources