前言

学习源码的时候有一个好的学习方案往往能事半功倍。 在跟读源码时定下一个学习目标,记录学习过程。 比如需要了解那个API的初始化过程来作为学习导向。

这篇已cesium如何渲染地形和影像为学习导向来研究cesium的数据调度机制

数据调度

之前讲过cesiumWidget如何初始化的,里边说到场景内的数据会自动做每一帧的循环渲染。

startRenderLoop 开始渲染三维窗口内的对象

通过requestAnimationFrame函数循环渲染,每一帧的结束,就是下一帧的开始

使用requestAnimationFrame创建一个draw循环 每个动画帧都调用tick回调函数 最终都会都用scene.render()函数

其中 地形和影像 都是在globe.beginframe 和 globe.endframe之间完成渲染的

调度说明

updateAndExecuteCommands 负责数据的调度,比如哪些Tile需要创建,这些Tile相关的地形数据,以及涉及到的影像数据之间的调度,都是在该函数中维护。但是updateAndExecuteCommands函数只负责管理,也就是他所创建的Tile类只是一个个的Tasks,自己并不负责Tasks内容的实现(数据的加载和维护)。这样,导致架构会有些复杂,因为不是一个流水线的作业方式,所以就需要有状态的维护。但这也是必然的,不仅保证该函数高效,不拖累每一帧的时间消耗,同时因为实时性满足人的要求(帧数能够达到或接近60),每一帧需要的Tile队列可以实时计算,不用考虑时间和状态之间的关系。

可以这样理解,updateAndExecuteCommands是一个管理者,只说不做,与之相反,scene.globe.endFrame中,会对该帧所涉及的GlobeTile的下载,解析等进行处理

简单而言,updateAndExecuteCommands负责上面看得见的事情,根据当前这一帧相机的状态,先打一个黄色的网格,然后检查当前状态下,这些网格里面的地形和影像数据是否都已经准备好了,如果准备好,每一个Tile就创建一个DrawCommand来渲染,把这个球画出来。如果没准备好也不管,反正有endFrame函数负责,各司其职

scene.globe.endFrame就按照吩咐来准备每一个Tile的数据,全是看不见的工作,默默的奉献自己的青春。这里,Promise,Worker等技术都会使用,通过异步和多线程的方式,来缓解每一帧的负担,而在主线程下,主要是数据状态的维护。如果一个Tile的数据解析完成,则该GlobeTile的状态更新为renderable(可渲染),done(已完成)。

类关系图

在这个过程中,类的关系大致如下:

网格按照经纬度来划分的,每一个网格对应一个QuadtreeTile四叉树类,其中有一个GlobeSurfaceTile,里面保存地形数据TileTerrain和影像数据TileImagery。当前相机下需要多个网格,就需要多个QuadtreeTile,该队列保存在QuadtreePrimitiveQuadtreePrimitive统一维护所有Tile的管理,具体是通过GlobeSurfaceTileProvider来实现逻辑操作,而QuadtreePrimitive上面包了一个GlobeScene

初始化globe 创建QuadtreePrimitive数据队列对象, 该对象会实例化 一个GlobeSurfaceTileProvider将地形和影像数据分别存储进去

渲染过程

地形和影像的渲染是通过updateAndExecuteCommands完成数据调度

关系图

源码跟读

scene.updateAndExecuteCommands 开始执行 
scene.executeCommandsInViewport 方法
执行 updateAndRenderPrimitives
调用globe的update函数

globe.update调用数据队列的update

最终调用GlobeSurfaceTileProvider 实现逻辑
渲染说明

在QuadtreePrimitive的update中,调用selectTilesForRendering来或许当前需要创建的网格,其中,在第一帧会把全球分为两块Tile:

而在queueChildrenLoadAndDetermineIfChildrenAreAllRenderable函数中,基于这两个Tile来做四叉树剖分,也就是所有的后来的QuadtreeTile都能够上溯到这两个Tile之一:

创建的GlobeSurfaceTile都会存储到更新队列中,等待数据下载和解析的过程,而如果当前帧中,存在准备好的,已经可以渲染的GlobeSurfaceTile,则调用addDrawCommandsForTile,构造成VBO,最终通过WebGL实现渲染。

更新过程

用大佬的原文解释:

参考博文 : https://www.cnblogs.com/fuckgiser/p/5744509.html