Cesium原理篇:3D Tiles(1)渲染调度

Cesium3DTiles

      Cesium在2016年3月份左右推出3D Tiles数据规范,在glTF基础上提供了LOD能力,定位就是Web环境下海量三维模型数据。虽然目前3D Tiles仍是Beta阶段,有很多硬伤,但3D Tiles数据规范于2016年9月30日开始了OGC标准化进程,积极成分仍是很大。 数组

      以前的glTF时分享了我的对二进制格式的一些想法和谨慎的态度。3D Tiles简单说就是具有LOD能力的glTF。有了数据首先是提供API能够渲染,保证用起来,下一步就要了解该数据规范的具体特色,好比倾斜,矢量,点云,OSM等支持状况,项目实施和风险评估等。最后,做为一个数据规范,从数据生产到深层次应用,须要时间沉淀出完善丰富的解决方案。 并发

      本文主要集中在渲染调度层面。看完本文可能会以为思路很简单。在实际应用中有不少细节,好比浏览时各类操做的差别,并发量,内存和显存管理,异步传输和Workers线程等等各类调优。思路简单,但要把这些小细节打磨好就不容易了。本文只讲诗和远方,鞋里的沙子本身来处理吧异步

1

 

      先看看如何加载3D Tiles数据,如上所示,Cesium提供了Cesium3DTileset类来管理,主要负责Tile的调度。在Cesium中,3DTiles就至关于一个Primitive的位置函数

3

3D Tile表述 工具

      当咱们建立一个Cesium3DTileset后,每个Tile对应一个Cesium3DTile。如上根节点是root,content是根节点对应的文件名,这里是parent.b3dm,四个子节点,子节点对应的文件名分别为ll.b3dm……。 性能

2

      如上,在获取JSON对象后,首先建立rootTile根节点,而后在while循环中,以广度优先的方式遍历这个树,每一个节点都有一个parentTile属性绑定父节点(根节点除外),同时有一个children数组,保存该节点对应的全部子节点。 学习

      这样,在初始化阶段,Cesium3DTileset中就保存了该3DTiles树上的全部节点及关联,固然此时只是属性信息,并无加载数据内容,因此内存上仍是能够接受。这就至关于咱们读书,都会先看这本书的目录,了解一个大概。但我的认为,第一,不必,实际上只须要找到根节点,下面按需顺藤摸瓜就能够(JSON在搜索节点上很麻烦);第二,若是数据量很大的状况下,初次加载所有节点是一个性能瓶颈。这是3D Tiles目前设计上的不足。 测试

4

       Cesium3DTile中经过一个简单的Cesium3DTileContentFactory工厂模式,目前主要提供四种类型。根据当前数据的具体类型(Type)来建立对应的内容(Content),本篇不涉及这块。初始化结束后,和以前glTF或primitive同样,基于状态的驱动流程: 大数据

5

      如上是调度管理的逻辑,四个函数的做用大概以下: 优化

  • processTiles

    • 处理Tile对应的DrawCommand状态,判断一些半透明等渲染顺序

  • selectTiles

    • 请求具体的b3dm数据,不一样Type根据对应的类来完成数据的下载,根据LOD策略决定哪些Tile进入渲染队列。

  • updateTiles

    • 当前帧状态下遍历这棵树,调用该Tile对应的Model::update,完成数据的解析最终构造出DrawCommand

  • unloadTiles

    • 判断当前Tiles数目是否超过上限,卸载多余的Tile

6

      在selectTiles函数中,首先是下载Tile对应的数据内容(b3dm后缀),经过contentUnloaded标识来判断,若是根节点的数据尚未下载,则request,而后返回。

7

      一个简单的request,里面的信息量其实也不小,调用对应Cesium3DTile和Content对应的request来下载数据,这这里Cesium专门封装了一个RequestScheduler类来管理并发,咱们最后在介绍这个。这里注意,当该数据下载完成后,则添加到两个队列:processQueue和removeQueue

      在Key2中,就是一个LOD策略的实现,上图给出了追加的逻辑注释。Cesium目前支持两种方式Add追加和Replace替换两种方式。Add方式较为简单,是Tiles求并的思路,而Replace是覆盖的思路,较为复杂,由于要控制父子节点直接的可见不可见,从代码来看,Cesium在这一块处理的比较简单,应该会出现闪烁的效果,不知道是否有人能够证明这个推测是否正确?

9

      UpdateTiles看上去就比较简单了,指定具体的Content..update,这个过程就是以前Pimitive和Model对应的update。

8

      对于能够卸载的Tile,则知足条件后调用unloadContent,但我的以为这块设计的仍是有些疑虑。首先,设计的很不错,从Content到BatchTable,到Model,以及Texture都提供了destory方法,但纹理仍是应该提供纹理管理器的概念,解决重用纹理的释放。

      让我学到的一点就是RequestScheduler类,大概思路是规定每次并发的最大请求数,每一帧收集下载请求但并不发送该请求,在下一帧对请求队列排序(相机远近),而后再发送。实现的很巧妙,方便管理。毕竟在海量数据下,有这样一个Manager来控制是颇有必要的。

      问题比较大的地方是删除上(由于没有大数据测试,仅从代码逻辑猜想)。第一,update和select两个都是异步或者workers线程机制,在数据量比较大的状况下会有内存泄漏。第二,Replace队列无脑删除,并非根据当前的范围和LOD,这个在设计上是一个很大的缺陷,只考虑了可见不可见,但没有优化删除策略。

      整体来讲,做为一个开源项目,3D Tiles迈出了很坚实的一步,数据规范设计的很优雅,基于glTF也下降了学习成本。同时Cesium提供了渲染3D Tiles的接口,稍显不足的就是尚未成熟的,免费的数据生成工具,能够从osg转为3d tiles,这是目前最大的瓶颈。简单说,Cesium目前提供了基本技术和规范,但并无提供完整的解决方案,同时还缺乏基于3D Tiles的丰富的扩展和应用。固然,咱们不能对一个开源项目要求苛刻,并且我相信,也但愿Cesium后续后慢慢完善,前面把路走踏实了,慢一点均可以接受,路遥知马力,踏踏实实作事情方能立本,本立而道生,在这个物欲横流的世界,这么简单的道理,其实并不简单。

相关文章
相关标签/搜索