小型三维引擎设计实现-高程影像渲染总结

1:思路

       第0级瓦片渲染思路走通->多级瓦片渲染

2:主要技术点的实现: 

2.1:Screen-Space Error 的概念

         Screen-Space Error(屏幕空间误差),它就是类似于比例尺的概念, 就形象的叫比例尺好了, 由于地图分为好多层,当我们在渲染地图的时候,怎么确定当期细节程度不够了,还要继续请求细节程度更高的一层呢?就是由这个值决定的,它是怎么计算出来的呢,下面一步步说。

         首先,比如最开始,我们渲染整个地球时,比如第0层,我们用了1个瓦片,简单点说,我们把一张图片粘到地球上了,那么这张图片的每个像素点代表实地多长的距离呢, 这个其实就是第0层 Screen-Space Error, 比如拿赤道来说: 用赤道的长度除以图片的宽度,就是这个值;  另外每一层的瓦片在细分时又可以由四个子瓦片表示, 那么第1层, 第2层, 第N层的Screen-Space Error是不是就可以计算出来了,我们说这个是理论意义上的Screen-Space Error值。

         然后,当我们渲染第N层图片时,我们计算一个实际Screen-Space Error值,来和上面的理论值比较, 这样根据比较结果,我们就可以知道是否要渲染第N+1层了,那怎么办计算呢, 看图:  

         小型三维引擎设计实现-高程影像渲染总结

        在图中的摄像机的FOV角度是知道的,瓦片距离相机的距离 d 也是可以求出来的,然后根据图中的比例关系,我们可以推到出计算实际Screen-Space Error的公式:   

小型三维引擎设计实现-高程影像渲染总结

              

小型三维引擎设计实现-高程影像渲染总结

 

2.2:地形的生成:

         由高程图生成地形是最简便的,高程图一般是64*64的一块黑白图片或者RGB图片,高度就是像素值,或者是像素值得组合: height = R * 100 + G * 10 +  B。如图所示:

        小型三维引擎设计实现-高程影像渲染总结

         高程图代表地球上一块区域对吧,一般都是把地球投影后再切成一块块的高程图,这样呢高程图就有墨卡托投影和WGS84投影之分,但一般都是WGS的,所以如果是墨卡托投影的转换成WGS84。 然后遍历高程图的每个像素点,获取高度信息并将WGS84转换成笛卡尔坐标,步骤如图所示: 

          小型三维引擎设计实现-高程影像渲染总结

        高程图是引擎的热点函数,优化很重要,这里面涉及到投影转换,坐标转换,函数应该内联。

 

2.3:影像处理:

          首先看看影像切片的样子: 

          小型三维引擎设计实现-高程影像渲染总结    

         一个瓦片包含一块地形数据和一些影像数据, 首先得找到覆盖这块地形数据的影像, 怎么找呢,一块地形有经纬度范围和层级,那么就有Screen-Space Error值,那么根据这个值就能够找到影像对应的层级。

         另外有一种情况就是,墨卡托和WGS的切片方式是不一样的,比如第0级的时候,前者就是1张256*256的图片,后者呢是2张256*256的图片,如果地形是WGS的,影像是墨卡托的时候,就需要对影像进行重投影,让其拉伸成512*256的大小,逐像素做在CPU上做那是非常耗时的,这个过程可以放到GPU中做, 比如生成一个512*256个顶点数据, 在顶点着色器中计算每个点对于的纹理坐标,然后在片段着色器中呢对影像进行采样,这样就可以完成重投影的工作。

         小型三维引擎设计实现-高程影像渲染总结

            小型三维引擎设计实现-高程影像渲染总结

          除此之外还有一种情况要考虑, 就是一个地形跨两张影像, 或者一个影像跨两个地形或多个地形, 因为在生成地形数据的时候,我们已经生成纹理坐标了, 那只是针对地形和影像一对一的情况, 此时就不适合了,那怎么做呢, 我们需要对纹理坐标进行一个缩放平移操作,比如: 经度方向的缩放=瓦片的宽度/影像的宽度, 经度方向的偏移=(瓦片宽度与图片宽度的差值)/瓦片宽度,以纠正纹理坐标。  

 

2.5:瓦片加载与替换策略:

         这个策略是为了增强用户体验感,试着想想,用户移动浏览地球时,我们尽量避免频繁缓冲未命中,尽量用户呈现最想看到的瓦片,策略就是把一些瓦片放入一块缓冲区中,并每帧更新缓冲区中瓦片。尽量保证渲染画面连续不突兀。这块缓冲区称为优先级队列。 

         那这个队列中存哪些数据呢, 第一个策略是存上一帧渲染过得瓦片,因为有很大可能这一帧还要继续渲染这些瓦片。 第二个策略是采用广度优先遍历,避免不同LOD之间过渡太锐利,第三个策略是本帧请求的节点按照由近到远的顺序,或者由粗糙到精细的顺序存放。

         小型三维引擎设计实现-高程影像渲染总结

            第四个策略,由于这个队列的长度不是无限的,一般根据机器性能调整,长度100~200左右,为了保持恒定长度,这就需要有替换策略, 这里采用LRU策略,最近最少使用,优先级最低的,排到队尾的元素被替换掉。 

            小型三维引擎设计实现-高程影像渲染总结

          第五个策略,预取, 由于瓦片数据需要下载,我们可以预取当前节点的子节点数据,如图中红色节点。为用户可能的移动做准备。

           小型三维引擎设计实现-高程影像渲染总结

         如何判断用户行为呢,思路是记录用户移动轨迹,就是每帧的相机的位置,预计算出下一帧相机的位置和方向, 然后在这个预判的位置上做预取,即相机可见性判断, 从而达到预取功能。

         小型三维引擎设计实现-高程影像渲染总结  

          第六个策略,上采样,当用户想看更精细一级的瓦片,但数据还没有下载好,此时可以对上一级的瓦片数据做采用,生成一个粗略的数据,供用户浏览, 第一:地形数据取上一次地形的1/4块, 放大并对高度插值。 第二影像数据用上一级影像,纹理坐标缩放平移,这个在影像处理时已经做好了。