矢量在全球规则格网地形上的叠加绘制方法

13 篇文章 2 订阅

矢量在全球规则格网地形上的叠加绘制方法

        为了精确、高效地将传统的且对地形有约束作用的二维矢量数据叠加绘制到多分辨率全球地形上,提出了一种基于矢量高程纹理矢量叠加绘制方法。首先将矢量高程渲染到矢量高程纹理金字塔中,然后在GPU中采用膨胀方法对高程纹理进行处理,在绘制地形网格时根据从矢量高程纹理中的采样值调整顶点高度,最后叠加绘制矢量网格。实验表明,该方法可与Clipmap等主流多分辨率规则格网地形模型结合,在地形上精确绘制矢量,并有效解决由于地形网格精度导致的矢量边缘被地形遮挡问题。
    一个三维场景通常由地形和地形表面上的矢量共同构成。由此产生一个问题,如何在三维地形上叠加绘制矢量。特别是当前多数三维场景均采用了多分辨率地形模型,使得地形几何表面随视点变化[1],这增加了问题的难度。已有的研究集中于如何将矢量数据紧贴着地形绘制到场景中[2-4],这种绘制方法对于抽象化的矢量符号是足够的,但在具有真实感的场景中,矢量数据的存在往往会对地形产生约束作用5,对于这种情况下矢量在地形上的叠加绘制研究较少。文献[5]提出采用足迹纹理和高程纹理合成绘制矢量地形的方法,但其论述是基于平面场景的,而对于如何将足迹纹理应用到规则球面地形网格及如何解决地形网格精度不够时的矢量压盖等关键问题并未深入探讨。
    受文献[5]启发,本文以面状矢量要素为例,提出了GPU友好的在规则球面地形网格上叠加绘制矢量数据的方法,并对其中出现的矢量边缘被地形压盖的问题进行了分析和改进。本文采用的矢量绘制方法主要分为4个步骤:1)将要绘制的矢量数据预先正射的绘制到一张32位浮点型矢量高程纹理上,这张纹理称为矢量高程纹理;2)对矢量高程纹理进行膨胀修正,以避免矢量边缘被地形压盖的问题;3)在绘制地形网格的顶点着色器中,从矢量高程纹理中采样出高程值,据此修改顶点高程;4)将要绘制的矢量构建成三角网,然后进行绘制。

  • 1地形数据的组织
        为平衡全球海量地形的渲染质量和速度,一般采用面向全球的多分辨率金字塔模型组织地形[6]。这种技术把全球地形按经纬度分成不同的层和块,所有地形块的地形网格连在一起,构成全球地形网格。当视点移动时,需将已不在视锥体内的地形块从内存中卸载,并用新的地形块替换。当视点向地球靠近时,使用精细的地形块替换粗糙的地形块。相反,当视点离开地球时,使用粗糙的地形块替换精细的地形块。参考文献[1]中的方法组织并绘制地形,建立一个以视点为中心的L层,每一层由M*M个四边形组成地形网格金字塔,每一层网格的边长是相邻粗糙层的1/2。不同地形层间的关系和每个地形块内的网格结构如图1所示。
    在这里插入图片描述
  • 2矢量高程纹理的绘制
      2.1矢量高程纹理的组织
      通过把同一层地形块范围内的矢量数据正射的绘制到与地形范围重合的浮点纹理上来获得矢量高程纹理,其与传统基于纹理的矢量绘制方法不同的是,写入纹理的数据是矢量高程。
      为了减少纹理分辨率引起的变形,并控制纹理开销,本文采用实时纹理金字塔技术[3]管理矢量高程纹理,将矢量高程动态绘制到数量和范围与地形层次相同的L张纹理上。由于精细层范围是粗糙层范围的1/4,但用的纹理分辨率相同,这就保证了越靠近视点使用的高程纹理越精细。
      2.2纹理坐标和纹理矩阵的计算
      为把球面上地形网格的顶点映射到矢量高程纹理上,采用切圆柱墨卡托投影将球面投影到平面矩形上,并以矩形的左上角点为原点,纬线方向为u轴,经线方向为v轴,建立图2所示纹理坐标系。
      在这里插入图片描述
      采用下式计算每个地形顶点的纹理坐标(u,v):
      在这里插入图片描述
      式中:x为顶点经度,西经为负,东经为正;y为顶点纬度,北纬为正,南纬为负。计算出的坐标称为全局纹理坐标,为将其映射为每个矢量纹理的坐标,需对其进行矩阵变换:
      在这里插入图片描述
      其中:ω、φ分别为矢量纹理左、右上角经度,width为矢量高程纹理u方向跨过的经度,height为v方向跨过的纬度。因为GPU所能接受的纹理坐标精度为32位浮点型,为了减小舍入误差,提高纹理坐标精度,为每个顶点纹理坐标扩大了2L倍,L为顶点所在层号,所以实际采用的纹理矩阵是:
      在这里插入图片描述
      通过把每一层纹理的全局纹理坐标范围传给GPU,可以在绘制地形的顶点着色器中计算出当前顶点所位于的最精细层是哪一层,然后把其全局纹理坐标乘以相应层的纹理矩阵,从而获得用来在矢量高程纹理中采样的纹理坐标。
      2.3动态生成矢量高程纹理
      文献[2]为了解决矢量覆盖区地形和周边地形间的平滑过渡问题,引入了Z曲线,但采用此方法需要把矢量在构建三角网时划分为边界和内部两部分,使得问题复杂化。本文只考虑强制地形位于矢量下方的情况,因此只需把矢量的高程保存到矢量三角剖分后的顶点属性中,就可以在片元着色器中将矢量高程写入纹理中。
      根据当前绘制的最粗糙层的范围,从矢量图层中查询出范围内的矢量纹理,将矢量三角剖分为三角链后,采用正射投影的方式绘制矢量。以32位浮点纹理作为矢量纹理,将纹理默认值设置为一个极大值作为非法值,将矢量高程写入纹理中,这一过程在片元着色器中完成。
  • 3.矢量高程纹理的膨胀修正及对地形高程的修改
      3.1矢量边缘压盖问题
      在使用矢量高程纹理修改地形的过程中,由于矢量覆盖区域与高程纹理栅格并不重合,会引起矢量边缘的精度损失。如图3所示,虚线网格为矢量高程纹理的栅格结构,实线区域为原始的矢量范围,黑色区域为写入矢量高程纹理的矢量范围,灰色区域为矢量边缘精度损失部分。这会导致当矢量叠加绘制到地形后,其边缘被地形压盖、闪烁等现象(图4)。
      在这里插入图片描述
      在这里插入图片描述
      可以通过提高矢量高程纹理分辨率和地形网格密度来减少边缘精度损失。对于平面场景,可通过将一小块规则网格不断地平移和缩放联结成整个场景的地形,因此对这一小块地形提高精度对其渲染性能影响不大。但是对于球面场景,由于不同纬度的四边形网格形状不同,需要把整套网格顶点放在顶点缓冲区并进行渲染,所以提高地形格网密度对性能影响很大。
      3.2膨胀修正方法
      对矢量纹理进行“膨胀”操作,使得到的矢量高程纹理比原来大一圈,以保证修改后的矢量在高程纹理上的对应像素区域能够完全包含矢量本身的范围。需要确定这个膨胀范围多大合适,膨胀范围应该恰好能够比膨胀前多压盖一个地形网格。由于每一层地形都对应一张矢量纹理,纹理的大小pp和每层的地形网格数n都是固定的,所以每个地形网格的一条边占用了纹理上的p/n个像素。所以为了使得在纹理上膨胀的部分能够压盖一个完整网格,需要膨胀√2p/n个像素。
      图像膨胀操作的基本原理是:用一个(2k+1)
    (2k+1)大小的结构元素扫描原图像的每个元素,用结构元素与其覆盖的二值图像做“与”操作,如果都为0,则结果图像的该元素为0,否则为1,其结果图像将比原图像扩大k个像素大小的一圈。根据上述计算结果,结构元素k=√2p/n。
      为了提高膨胀操作的速度,把它放在GPU中处理。方法是绘制一个大小与矢量纹理相同的与屏幕对齐的矩形到一个32位浮点纹理中,在片元着色器中以原始图像作为纹理输入,进行膨胀操作。其glsl语言的片元着色器代码如下:
    const int KernelSize=170;
    uniform sample2D baseImage
    uniform vec2 offset[KernelSize];
    uniform float MAXVALUE;
    void main(){
      float heightValue=0.0;
      float resultHeightValue=0.0;
      resultHeightValue=texture2D(baseImage,gl_TexCoord[0].st);
      for(int i=0;i<kernelsize;i++){
      heightValue=texture2D(baseImage,gl_TexCoord[0].st+offset[i]);
      if(heightValue!=MAXVALUE){
       resultHeightValue=heightValue;
       break;
      }

      gl_FragColor=vec4(resultHeightValue);

      其中:KernelSize为(2k+1)
    (2k+1),baseImage为原始的矢量纹理,offset数组保存的是结构元素矩阵中每个元素相对于矩阵中心的偏移量。MAX-VALUE是矢量纹理中没有被矢量覆盖区域存储的标识值。
      3.3使用矢量高程纹理修改地形高程
      绘制地形时,在顶点着色器中根据顶点纹理坐标分别从矢量纹理和高程纹理中采样出纹理值,以矢量纹理中的非极大值的采样值修改地形顶点高度。在以球心为原点的世界坐标系中,球面网格顶点可由下式计算:
    在这里插入图片描述
     在地形顶点着色器中,可按下式调整顶点位置:
     在这里插入图片描述
     pos.xyz=pos.xyz*(Radius+h)/Radius
      其中:Radius为地球半径,latitude和longitude为顶点经纬度,h为从矢量高程纹理中获得的采样值。
  • 4.矢量的叠加绘制
      采用墨卡托切圆柱投影将面状矢量的顶点投影到一个横轴为经度、纵轴为纬度的矩形平面上,在此平面坐标系下进行三角剖分,将面状矢量转化为一个相互连接的三角网结构,由式(1)得到矢量顶点在三维空间中的位置。这样一个二维面状矢量就转化为了三维空间中一个随地球弯曲的三角形构成的折面,将此折面叠加绘制到修改过高程的地形上即可。
      当面状矢量范围很大,此时矢量折面与球面地形贴合不好,可用模板阴影体法代替上述方法。
  • 5.实验结果
      在Win32平台下,基于C++和OGRE渲染引擎构建了一个验证系统。动态绘制6层地形网格,每一层包含6464个四边形地形网格,每一个网格剖分为2个三角片。默认视场角为90°,屏幕分辨率为1440900,由此计算出最精细层地形三角面占大约30.625个像素。使用6张1024*1024分辨率的纹理作为矢量高程纹理,此时纹理资源大小为24M。纹理覆盖范围与地形网格相应层对应。
      实验中采用上文提出的方法以解决在地形上叠加绘制水体的问题,通过“展平”水体矢量所覆盖地形,使得水体不被地形所遮挡。实验地形数据采用京津地区分辨率为30m的地形数据,矢量数据采用京津地区湖泊数据。图5a为没有采用本文方法时水体矢量被地形遮挡的情况,图5b为采用本文方法后矢量与地形的叠合情况,图6a为使用矢量高程纹理修改地形前后的地形网格情况。可见通过矢量高程修改纹理,可以有效解决矢量数据被地形遮挡的问题。
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述
  • 6结语
      本文提出了基于矢量高程纹理在球面规则地形网格上叠加绘制矢量的方法。理论和实验证明,通过把矢量动态绘制到6张矢量高程纹理上,再在GPU顶点着色器中动态修改地形高程,可以有效地解决由于地形数据和矢量数据精度不同导致的地形遮挡矢量问题。通过对矢量高程纹理进行膨胀操作,使矢量的边界部分不会被地形网格遮挡。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

梅里雪山GIS

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值