Norad Tracks Santa Tech Preview


 

作为北美防空联合司令部追踪圣诞老人(NORAD Tracks Santa)团队的一员, Analytical Graphics, Inc. 正使用Cesium来构建一个3D网络地图以可视化Santa在12月24日的位置, 因为那一天他会在地球上游走。可以圣诞节前夕在www.noradsanta.org上看到他的轨迹。

在本文中, 我会分享3D网络地图背后的技术。屏幕截图使用的位置是基于测试数据的, 当然, 我们不知道Santa的路线, 仅当NORAD在圣诞节前夕开始追踪Santa。

Cesium and WebGL

我们借助Cesium开发了这个地图应用。Cesium, 是一个开源的虚拟地球和地图引擎(open-source virtual globe and map engine), 它本身基于WebGL——一个3D图形的开发标准——基本上是用于JavaScript的OpenGL ES 2.0. 在当前大多数的浏览器, 包括Chrome和Firefox, 以及所有主流的桌面操作系统: Windows, Linux 以及 Mac中, WebGL是可用的。

这就意味着, 用户可以在他们的浏览器中看到3D效果, 在不需要安装任何插件或获取管理员权限。作为一名长期的C++开发人员, 这也是我们开始使用WebGL的主要原因之一。

接下来, 让我们看看如何绘制这个应用的每一部分。

Land

我们使用WGS84 Ellipsoid而非一个Sphere来精确地建模地球。全球地形数据源于Shuttle Radar Topography Mission(SRTM) —— 南北纬60°之间有90m的间隔, 以及Global 30 Arc Second Elevation Data Set(GTOPO30)——整个球有着1km的间隔。因为这些原始数据集非常大, 我们使用了Tile Map Service(TMS)布局, 来预处理这些数据集为一个有层次的高度图瓦片。

Cesium基于当前的视域来异步地请求瓦片并绘制, 因此, 只有非常小的异步数据集需要发送到客户端。需要请求的瓦片是通过层级的精细级别(HLOD)确定的, 因此, 当离观察者很远时, 就请求低分辨率的瓦片, 视锥体剔除(view frustum culling)那些位于视域外的瓦片, 这些瓦片不会被请求; 地*线剔除(horizon culling)位于地*线之上的瓦片, 这些瓦片也不会被请求。为了最小化接收到新瓦片的停顿延迟, Cesium在网络工作者线程(web worker)中创建了一个源于高度图瓦片的网格, 这样, 主线程(main thread)可以继续发送WebGL调用命令。当然, 在瓦片渲染过程中使用了隐藏面(背面)剔除, 以使背离观察者的隐藏三角形不会被光栅化和着色。

 贴在地形上面的高分辨率影像流自于Bing Maps。影像也被分片, 请求方式与地形类似。然而, 地形和影像瓦片之间并不存在一对一的关系, 因此, Cesium生成多个片段着色器, 其中每个在一个地形瓦片上支持不同数量的影像瓦片。当然, 片段中真实的动态分支在这里会很有用, 但是按着色器排序和切换着色器仍然要比多路方式(the multi-pass alternative)要好。为了改善地*线视野(horizon views)的可视化品质, 使用了非均匀地纹理过滤(anisotropic texture filtering)。

高度图和影像瓦片都使用了缓存的方式, 最*最少使用的瓦片会被释放以为新的瓦片腾出空间。

Water

为了渲染全球范围内的水, 我们从渲染地形时使用的SRTM和GTOPO30数据中得到一个水面掩码(water mask)。为了最小化请求的数量(在追踪Santa时, 我们期待大量的请求), 我们在高域(heightfield)瓦片中包含了这个水面掩码作为一个字节数组, 其中1代表水, 0代表陆地。大多数瓦片要么全是水, 要么全是陆地, 当然, 便于压缩。我们预先压缩所有的瓦片以减少请求瓦片时, 服务器端(server-side)的处理。

给定的水面掩码, 用于绘制地球的片段着色器知道它是在对陆地还是水进行着色。对于动态的水,  椭球表面法线会受到几个与时间有关的读取到一个法线贴图以创建波浪效果。水的颜色会与高分辨率的影像混合, 隐约地显示出标签。

Sky and Space

大气圈提供了环绕地球的由白到蓝的光晕(光环), *似于大气散射(Accurate Atmosphere Scattering)

星星是通过在整个场景外围渲染一个天空盒来绘制的。为了最小化我们的数据需求, 在绘制天空盒的过程中, 我们使用了一个真实的赤道春分(True Equator Mean Equinox, TEME)到伪定点变换, 而非需要额外数据但更为精确的惯性变换。星星数据集源自于NASA。原始的图片被转换为6幅单独的图片, 每幅代表了天空盒的一个面, JPEG 压缩了80%的质量来降低带宽和启动事件。

Columbus View

除了3D地球, 用户可以改变到2.5D*坦的地球视图, 我们称之为哥伦布视图。使用了一个顶点着色器来做视图间的改变, 所以, 场景可以在视图改变过程中动画。

Rendering Pipeline

渲染一个全球范围的场景会导致精度问题。可能, 最常见的便是z-fighting, 即*处的物体或物体的一部分来回闪烁(flicker back and forth)。这是由于透视变换和全球范围场景所需要的大*到远比例(large near-to-far ratios)所致。

为了解决这个问题, Cesium渲染过程采用多重视锥(multiple frustums)。首先, 用来渲染天空盒、大气圈的大视锥采用最小的**面和最大的远*面。在渲染天空盒和大气圈时, 都禁用了深度写(是的, 这完全违背了最后渲染天空盒的咒语[mantra])。接下来, 我们迭代场景中所有可渲染的对象, 返回绘制命令, 包括对象的边界体积、着色器、顶点数组、渲染状态等等。在这个过程中, 我们剔除了位于视锥体之外和地*线之上的对象, 并确定剩余对象的最小*距离和最大远距离。然后, 我们确定我们需要多少个视锥来渲染这些对象才能确保每个视锥都维持一个合理的*到远*面, 同时, 将各个对象放置到每个视锥使用的桶中(一个对象可以处于多个视锥体中)。作为一项优化, 我们利用了局部相关性(temporal coherence)在计算新的视锥体之前尝试使用前一帧计算的视锥体以省去对这些对象再一遍计算。最终, 我们从后向前遍历这些视锥体, 在访问之前清空深度值, 然后为该视锥体中的每个对象发射绘制命令。

代表了Santa, 北极点以及礼物的广告牌, 会被批处理, 作为单个绘制命令发射。尽管仅有一些唯一的图标, 它们会被组合到单个纹理图集中以使用批处理。广告牌的大小是在顶点着色器中基于视觉距离设置的。

Flights

相机飞行(camera flights)在整个应用中可见。在应用首次启动时, 相机从一个全局视图飞行到Santa, 然后飞行到一个与被点击的图标相应的城市。使用了两种样条曲线: Hermite曲线确定了相机的位置, 球面线性插值确定了相机的方向。

Other Goodies

使用Fullscreen API, 我们的应用允许用户进入全屏模式。对于使用不支持WebGLobal的旧显卡或浏览器的用户, 我们回退到2D地图, 但仍然有大量的3D版本的特性, 如点击一个城市图标后查看Wikipedia弹窗。

在接*圣诞前夕的最后的几周, 我们仍然在调整我们的应用-添加优化, 健壮以及改善用户体验。

版权声明:本文为long3216原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/long3216/p/4853180.html