(1.中国科学院地理科学与资源研究所,北京100101;2.中国科学院大学,北京100039;3.北京超图软件股份有限公司,北京100015)
论文来源:《地理与地理信息科学》 2013年11月 第29卷第6期
摘要:为了精确、高效地将传统的且对地形有约束作用的二维矢量数据叠加绘制到多分辨率全球地形上,提出了一种基于矢量高程纹理矢量叠加绘制方法。首先将矢量高程渲染到矢量高程纹理金字塔中,然后在GPU中采用膨胀方法对高程纹理进行处理,在绘制地形网格时根据从矢量高程纹理中的采样值调整顶点高度,最后叠加绘制矢量网格。实验表明,该方法可与Clipmap等主流多分辨率规则格网地形模型结合,在地形上精确绘制矢量,并有效解决由于地形网格精度导致的矢量边缘被地形遮挡问题。
关键词: 矢量数据,三维地形,绘制,高程纹理
A Method for Rendering Vector Data over Global 3D Regular Terrain Grid
SUN Yinle,SONG Guanfu,FENG Zhenhua
(1.Institute of Geographic Sciences and Natural Resources Research,Chinese Academy of Sciences,Beijing100101;2.University of Chinese Academy of Sciences,Beijing100039;3.SuperMap Software Co.Ltd.,Beijing100015,China)
Abstract:To display traditional 2D vector data which constraints the terrain,on a 3D multi-resolution terrain model,a method based on elevation textures of vector data has been proposed in this paper. The elevation of vectors was saved in a dynamic pyramid of textures and the footprint of vectors in elevation texture was expanded in GPU. When rendering the terrain,the height of the vertex was modified according to the value read from vector elevation texture. Then meshes of vector data were constructed and rendered.The result of an experiment indicates that vector data and its edges could be rendered accurately and correctly. In addition,this method is suited to work with most of major terrain LOD algorithms.
Keywords:vector data; 3D terrain; rendering; elevation texture
一个三维场景通常由地形和地形表面上的矢量共同构成。由此产生一个问题,如何在三维地形上叠加绘制矢量。特别是当前多数三维场景均采用了多分辨率地形模型,使得地形几何表面随视点变化[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膨胀修正方法
对矢量纹理进行“膨胀”操作,使得到的矢量高程纹理比原来大一圈,以保证修改后的矢量在高程纹理上的对应像素区域能够完全包含矢量本身的范围。需要确定这个膨胀范围多大合适,膨胀范围应该恰好能够比膨胀前多压盖一个地形网格。由于每一层地形都对应一张矢量纹理,纹理的大小p*p和每层的地形网格数n都是固定的,所以每个地形网格的一条边占用了纹理上的p/n个像素。所以为了使得在纹理上膨胀的部分能够压盖一个完整网格,需要膨胀√2p/n个像素。
图像膨胀操作的基本原理是:用一个(2k+1)*(2k+1)大小的结构元素扫描原图像的每个元素,用结构元素与其覆盖的二值图像做“与”操作,如果都为0,则结果图像的该元素为0,否则为1,其结果图像将比原图像扩大k个像素大小的一圈。根据上述计算结果,结构元素k=√2*p/n。
为了提高膨胀操作的速度,把它放在GPU中处理。方法是绘制一个大小与矢量纹理相同的与屏幕对齐的矩形到一个32位浮点纹理中,在片元着色器中以原始图像作为纹理输入,进行膨胀操作。其glsl语言的片元着色器代码如下:
const int KernelSize=170;其中: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层地形网格,每一层包含64*64个四边形地形网格,每一个网格剖分为2个三角片。默认视场角为90°,屏幕分辨率为1440*900,由此计算出最精细层地形三角面占大约30.625个像素。使用6张1024*1024分辨率的纹理作为矢量高程纹理,此时纹理资源大小为24M。纹理覆盖范围与地形网格相应层对应。
实验中采用上文提出的方法以解决在地形上叠加绘制水体的问题,通过“展平”水体矢量所覆盖地形,使得水体不被地形所遮挡。实验地形数据采用京津地区分辨率为30m的地形数据,矢量数据采用京津地区湖泊数据。图5a为没有采用本文方法时水体矢量被地形遮挡的情况,图5b为采用本文方法后矢量与地形的叠合情况,图6a为使用矢量高程纹理修改地形前后的地形网格情况。可见通过矢量高程修改纹理,可以有效解决矢量数据被地形遮挡的问题。
6结语
本文提出了基于矢量高程纹理在球面规则地形网格上叠加绘制矢量的方法。理论和实验证明,通过把矢量动态绘制到6张矢量高程纹理上,再在GPU顶点着色器中动态修改地形高程,可以有效地解决由于地形数据和矢量数据精度不同导致的地形遮挡矢量问题。通过对矢量高程纹理进行膨胀操作,使矢量的边界部分不会被地形网格遮挡。
参考文献:
[1]ARSIRVATHAM A,HOPPE H.GPU Gems2[M]. New Jersey:Addison Wesley,2005.27-44.
[2]WEBER A,BENNER J. Interactive generation of digital terrain models using multiple data sources[A]. First International Symposium on Digital Earth Moving[C]. Switzerland:Manno(Lugano),2001.60-64.
[3]KERSTING O,DOLLNER J. Interactive 3D visualization of vector data in GIS [A]. Proceedings of the 10th ACM International Symposium on Advances in Geographic Information Systems[C]. VA,USA:McLean,2002.107-112.
[4]SCHNEIDER M,KLEIN R.Efficient and accurate rendering of vector data on virtual landscapes [J] . WSCG,2007,15(3):59-65.
[5]BRUNETON E,NEYRET F.Real-time rendering and editing of vector-based terrains[J].Euro.graphics Proceedings,2008,27:311-320.
[6]杜莹,武玉国,王晓明,等.全球多分辨率虚拟地形环境的金字塔模型研究[J].系统仿真学报,2006,18(4):955-958.
作者简介:孙寅乐(1986-),男,硕士研究生,主要研究方向为三维地理信息系统。