Winter 2019 | Geography 371 | Web Mapping
Instructor: Bo Zhao | Location: WLKN 210 | Time: MWF 0800 - 0850
Learning Objectives
- Get to know the basics of 3D visualization on web, including the history, browsers, libraries and applications;
- Get to know the virtual globe library Cesium.js;
- Make a virtual globe application using cesium.js; and
- overlay different map service providers.
WebGL (Web Graphics Library) is a JavaScript API for rendering 3D graphics within any compatible web browser without the use of plug-ins. WebGL is integrated completely into all the web standards of the browser allowing GPU accelerated usage of physics and image processing and effects as part of the web page canvas. WebGL elements can be mixed with other HTML elements and composited with other parts of the page or page background. WebGL programs consist of control code written in JavaScript and shader code that is written in GLSL, a language similar to C/C++, and is executed on a computer's Graphics Processing Unit (GPU). WebGL is designed and maintained by the non-profit Khronos Group.
WebGL evolved out of the Canvas 3D experiments started by Vladimir Vukićević at Mozilla. Vukićević first demonstrated a Canvas 3D prototype in 2006. By the end of 2007, both Mozilla
and Opera
had made their own separate implementations.
In early 2009, the non-profit technology consortium Khronos Group started the WebGL Working Group, with initial participation from Apple, Google, Mozilla, Opera, and others. Version 1.0 of the WebGL specification was released March 2011. As of March 2012, the chair of the working group is Ken Russell.
Early applications of WebGL include Zygote Body. In November 2012 Autodesk announced that they ported most of their applications to the cloud running on local WebGL clients. These applications included Fusion 360 and AutoCAD 360.
Development of the WebGL 2 specification started in 2013. This specification is based on OpenGL ES 3.0.
WebGL is widely supported in modern browsers. However its availability is dependent on other factors like the GPU supporting it. The official WebGL website offers a simple test page.
- Google Chrome – WebGL has been enabled on all platforms that have a capable graphics card with updated drivers since version 9, released in February 2011. By default on Windows, Chrome uses the ANGLE (Almost Native Graphics Layer Engine) renderer to translate OpenGL ES to Direct X 9.0c or 11.0, which have better driver support. On Linux and Mac OS X the default renderer is OpenGL however. It is also possible to force OpenGL as the renderer on Windows. Since September 2013, Chrome also has a newer Direct3D 11 renderer, which however requires a newer graphics card.
- Mozilla Firefox – WebGL has been enabled on all platforms that have a capable graphics card with updated drivers since version 4.0. Since 2013 Firefox also uses DirectX on the Windows platform via ANGLE.
- Safari – Safari 6.0 and newer versions installed on OS X Mountain Lion, Mac OS X Lion and Safari 5.1 on Mac OS X Snow Leopard implemented support for WebGL, which was disabled by default before Safari 8.0.
- Opera – WebGL has been implemented in Opera 11 and 12, although was disabled by default in 2014.
- Internet Explorer – WebGL is partially supported in Internet Explorer 11. It initially failed the majority of official WebGL conformance tests, but Microsoft later released several updates. The latest 0.94 WebGL engine currently passes ~97% of Khronos tests. WebGL support can also be manually added to earlier versions of Internet Explorer using third-party plugins such as IEWebGL.
- Microsoft Edge – The initial stable release supports WebGL version 0.95 (context name: "experimental-webgl") with an open source GLSL to HLSL transpiler.
The WebGL API may be too tedious to use directly without some utility libraries, which for example set up typical view transformation shaders (e.g. for view frustum). Loading scene graphs and 3D objects in the popular industry formats is also not directly provided for. JavaScript libraries have been built (or sometimes ported to WebGL) to provide the additional functionality. A non-exhaustive list of libraries that provide many high-level features includes A-Frame (VR)
, BabylonJS
, PlayCanvas
, three.js
, OSG.JS
and CopperLicht
. There also has been a rapid emergence of game engines for WebGL, including Unreal Engine 4
and Unity 5
. The Stage3D/Flash-based Away3D
high-level library also has a port to WebGL via TypeScript
. A more light-weight utility library that provides just the vector and matrix math utilities for shaders is sylvester.js
. It is sometimes used in conjunction with a WebGL specific extension called glUtils.js
. Although not very common, some 3D libraries, like the one used by LAI4D
, can work with HTML5 canvas when WebGL is not supported.
There are also some 2D libraries built on top of WebGL like Cocos2d-x
or Pixi.js
, which were implemented this way for performance reasons, in a move that parallels what happened with the Starling Framework
over Stage3D
in the Flash world. The WebGL-based 2D libraries fall back to HTML5 canvas when WebGL is not available.
X3D also made a project called X3DOM
to make X3D and VRML content running on WebGL. The 3D model will in XML tag <X3D>
in HTML5 and interactive script will use JavaScript and DOM. BS Content Studio and InstantReality X3D exporter can exported X3D in HTML and running by WebGL.
NASA developed an interactive web application called Experience Curiosity (https://eyes.nasa.gov/curiosity/)to celebrate the 3rd anniversary of the Curiosity rover landing on Mars. This Blend4Web-based app makes it possible to operate the rover, control its cameras and the robotic arm, and reproduces some of the prominent events of the Mars Science Laboratory mission.[The application was presented at the beginning of the WebGL section at SIGGRAPH 2015.
Experience Curiosity won the Webby Award as the best "Government & Civil Innovation" website of 2016. The 5-word speech at the award ceremony was Rockin' and Rovin' on Mars, voiced by NASA's representative Brian Kumanchik.
Cesium
is an open-source JavaScript library for world-class 3D globes and maps. It creates the leading 3D globe and map for static and time-dynamic content, with the best possible performance, precision, visual quality, platform support, community, and ease of use.
Cesium was founded by AGI (AGI) in 2011 as a cross-platform virtual globe for dynamic-data visualization in the space and defense industries. Since then, Cesium has grown into a 3D globe serving industries from geospatial and oil and gas to agriculture, real estate, entertainment, and sports. Currently, Cesium is lead by the Cesium Consortium, started by Analytical Graphics, Inc. and Bentley Systems. The consortium was started to accelerate open-source Cesium development and support long-term open-source Cesium sustainability.
AGI uses Cesium in many of its own applications, such as ComSpOC and NORAD Tracks Santa, and develops value-add products for Cesium including the STK Terrain Server.
A number of open 3D geospatial formats have grown out of Cesium. Open formats create interoperability for a full ecosystem of tools.
CZML, the Cesium Language, is a JSON schema for describing time-dynamic 3D scenes such as of satellites and aircraft. The quantized-meshformat enables efficient 3D terrain streaming and rendering. The Cesium team has worked closely with Khronos to create glTF, the GL Transmission Format, which is the open-standard runtime asset format for WebGL engines. 3D Tiles are a specification for streaming massive heterogeneous 3D geospatial datasets.
- Visualize high-resolution global terrain.
- Layer imagery from multiple sources, including WMS, TMS, WMTS, Bing Maps, Mapbox, Google Earth Enterprise, OpenStreetMap, ArcGIS MapServer, standard image files, and custom tiling schemes. Each layer can be alpha-blended with the layers below it, and its brightness, contrast, gamma, hue, and saturation can be dynamically changed.
- Industry standard vector formats, such as KML, GeoJSON, and TopoJSON, including terrain clamping.
- Draw 3D models using glTF with animations and skins. Clamp models to terrain. Convert COLLADA and OBJ to glTF using the online converter. Use KHR_binary_glTF and WEB3D_quantized_attributes extensions to reduce the file size.
- Create data-driven time-dynamic scenes using CZML.
- Draw and style a wide range of geometries:
- Shadows, including self-shadows and soft-shadows for terrain, 3D models, and geometries, based on the sun position.
- Draw the atmosphere, fog, sun, sun lighting, moon, stars, and water.
- Individual object picking.
- Camera navigation with mouse and touch handlers for rotate, zoom, pan with inertia, flights, free look, and terrain collision detection.
- Batching, culling, and JavaScript and GPU optimizations for performance.
- Precision handling for large view distances (avoiding z-fighting) and large world coordinates (avoiding jitter).
- A 3D globe, 2D map, and Columbus view (2.5D) with the same API.
- Display military symbology, such as MIL-STD-2525 and STANAG APP6, by integrating with milsymbol
- Cluster points, labels and billboards.
- Timeline and animation widgets for controlling simulation time.
- Base layer picker widget for selecting imagery and terrain.
- Selection and info box widgets for highlighting objects and displaying information.
- Geocoder widget for flying to addresses and landmarks.
- Home view widget to fly to the default camera view.
- Scene mode picker widget to morph between 3D, 2D, and Columbus view.
- Fullscreen widget for toggling fullscreen mode.
- Navigation help widget for providing mouse and touch instructions.
- Performance watch dog for monitoring the frame rate.
- Inspector widget for advanced graphics debugging.
- WebVR widget for viewing Cesium with VR devices like Google Cardboard.
- Reference frames such as World Geodetic System (WGS84), International Celestial Reference Frame (ICRF), and east-north-up.
- Equidistant Cylindrical and Mercator 2D map projections.
- Conversions such as longitude/latitude/height to Cartesian.
- Fast Cartesian, spherical, cartographic, matrix, and quaternion types.
- Julian dates, leap seconds, and UTC and TAI time standards.
The easiest way to verify that Cesium works in your web browser is to run the Hello World example by clicking here (opens a new window). If you see something like the below image, congratulations, your system can run Cesium and you can safely skip to the next section; otherwise, continue reading.
Cesium is built on several new HTML5 technologies, the most important of which is WebGL. Even though these new standards are quickly becoming widely adopted, some browsers and systems need to be updated to support them. If the example application doesn’t work for you, here are a few things to try.
-
Update your web browser. Most of the Cesium team uses Google Chrome, but Firefox, Internet Explorer 11, and Opera will also work. If you’re already using one of the above browsers, make sure it’s updated to the latest version.
-
Update your video card driver to better support 3D. If you know what type of video card you have, you can check the vendor web site for updates. The three most popular are: Nvidia, AMD, and Intel.
-
If you’re still having problems, try visiting http://get.webgl.org/, which offers additional trouble-shooting advice. You can also ask for help on the Cesium forum.
If you open up helloworld.html
in an editor, you’ll find the following simple application.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://cesiumjs.org/releases/1.54/Build/Cesium/Widgets/widgets.css">
<style>
html, body, #cesiumContainer { width: 100%; height: 100%; margin: 0; background: #fff;}
</style>
<script src="https://cesiumjs.org/releases/1.54/Build/Cesium/Cesium.js"></script>
<title>Hello world!</title>
</head>
<body>
<div id="cesiumContainer"></div>
<script>
//create a cesium view, and use the mapbox dark map as the base map.
var viewer = new Cesium.Viewer('cesiumContainer', {
terrainProvider : Cesium.createWorldTerrain(),
vrButton: true, // virtual reality support
sceneModePicker: true, // 2d, 2.5d and 3d
navigationHelpButton: true,
baseLayerPicker : true,
fullscreenButton: true,
geocoder: true,
homeButton: false,
animation: false,
timeline: false
});
</script>
</body>
</html>
These are the four lines needed to add Cesium to an application:
The first step is to include Cesium.js in a script tag. This defines the Cesium object, which contains everything we need.
<script src="https://cesiumjs.org/releases/1.54/Build/Cesium/Cesium.js"></script>
In order to use the Cesium Viewer widget, we need to include its CSS.
<link rel="stylesheet" href="https://cesiumjs.org/releases/1.54/Build/Cesium/Widgets/widgets.css">
In the HTML body, we create a div for the viewer to live.
<div id="cesiumContainer"></div>
Finally, we create an instance of viewer.
var viewer = new Cesium.Viewer('cesiumContainer');
Cesium supports drawing and layering high-resolution imagery (maps) from several standard services. Layers can be ordered, and blended together. Each layer’s brightness, contrast, gamma, hue, and saturation can be dynamically changed. This tutorial introduces imagery layer concepts and the related Cesium APIs.
Let’s ignore the details for the moment and just jump in by writing code to add a few imagery layers. Open the index.html in the root directory of this lecture. This example creates a Viewer
widget which, which, by default, has a single layer rendering Bing Maps imagery. We can specify a different base layer by providing an additional parameter to the Viewer
constructor. Let’s use a layer from an Esri ArcGIS MapServer:
var viewer = new Cesium.Viewer('cesiumContainer', {
imageryProvider : new Cesium.ArcGisMapServerImageryProvider({
url : 'http://server.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer'
})
});
High-resolution imagery like the first two layers used above is too large to fit into memory or often even a single disk, so imagery is divided into smaller images, called tiles, that can be streamed to a client as needed based on the view. Cesium supports several standards for requesting tiles using imagery providers. Most imagery providers use a REST interface over HTTP to request tiles. Imagery providers differ based on how requests are formatted and how tiles are organized. Cesium has the following imagery providers:
- Web Map Service (WMS) - An OGC standard for requesting map tiles for a geographic region from distributed geospatial databases. In Cesium, see WebMapServiceImageryProvider.
- Tile Map Service (TMS) - A REST interface for accessing map tiles. Tiles can be generated with MapTiler or GDAL2Tiles. In Cesium, see TileMapServiceImageryProvider.
- OpenGIS Web Map Tile Service (WMTS) - An OGC standard for serving pre-rendered georeferenced map tiles over the Internet. In Cesium, see WebMapServiceImageryProvider.
- OpenStreetMap - Access to OpenStreetMap tiles or any Slippy map tiles. There are several ways to host these tiles. In Cesium, see createOpenStreetMapImageryProvider.
- Bing Maps - Uses Bing Maps REST Services to access tiles. A Bing Maps key can be created at https://www.bingmapsportal.com/. In Cesium, see BingMapsImageryProvider.
- Esri ArcGIS MapServer - Uses the ArcGIS Server REST API to access tiles hosted by an ArcGIS MapServer. In Cesium, see ArcGisMapServerImageryProvider.
- Google Earth Enterprise - Provides access to the imagery stored in your organization’s Google Earth Enterprise server. In Cesium, see GoogleEarthImageryProvider.
- Mapbox - Uses the Mapbox API to access tiles. Create an account and supply your access token. In Cesium, see MapboxImageryProvider.
- Standard image files - Create a tile from a single image. In Cesium, see SingleTileImageryProvider.
- Custom tiling schemes - Using UrlTemplateImageryProvider, we can connect to a wide array of imagery sources by using a URL template. For example, a URL template for TMS is
//cesiumjs.org/tilesets/imagery/naturalearthii/{z}/{x}/{reverseY}.jpg
. - Tile coordinates - Shows how the globe is divided into tiles in a particular tiling scheme by drawing a border around each tile and labeling it with its level, X, and Y coordinates.
We can access other imagery services by implementing the ImageryProvider interface. If you do so, and think it is generally useful, please contribute it to Cesium for everyone’s benefit.
See the reference documentation for how to construct a particular imagery provider. We’ll look at the SingleTileImageryProvider here since many imagery providers share its construction properties:
url
- The url to the image. Like many imagery providers, this is the only required property. In other imagery providers this url points to the server or the root url of the service.extent
- An optional longitude-latitude rectangle that the image should cover. The default is to cover the entire globe.credit
- An optional string crediting the data source, which is displayed on the canvas. Some imagery providers, like BingMapsImageryProvider and ArcGIS Server REST API, get a credit logo or string directly from their service.proxy
- An optional proxy to use for requests to the service, which brings us to Cross-Origin Resource Sharing.
Imagery providers vs. layers
So far we haven’t clearly differentiated between imagery providers and layers. An imagery provider makes requests for tiles using a particular service, while a layer represents displayed tiles from an imagery provider. Code like
var layer = layers.addImageryProvider(imageryProvider);
is shorthand for
var layer = new ImageryLayer(imageryProvider);
layers.add(layer);
We usually construct an imagery provider just to create a layer, then we manipulate the layer to change its visual appearance using its properties like show
, alpha
, brightness
, and contrast
. See ImageryLayer. Decoupling imagery providers and layers makes it easier to write new imagery providers.
An imagery layer collection, like layers
in the above examples, determines the order in which layers are drawn. Layers are drawn bottom-to-top based on the order they are added. Imagery layer collections are manipulated like any other collection in Cesium using functions like add
, remove
, and get
. In addition, layers can be reordered using raise
, raiseToTop
, lower
, and lowerToBottom
. See ImageryLayerCollection.