掌握腾讯地图基于WebGL实现自定义栅格图层踩坑经验
2023-12-17 03:17:14
自定义栅格图层入门
自定义栅格图层是指地图开发者使用专用软件将图片切割为瓦片,再按照相应方式生成图形文件,最终利用瓦片坐标拼接出地图图层。常见的用途包括手绘地图、卫星图、地形图等。瓦片按加载顺序排列绘制到纹理,占位宽度一致,竖向排列。
以瓦片大小为256px为例,若瓦片1到瓦片4依次加载到同一纹理上,那么这四个瓦片则会按照从左到右、从上到下的顺序排列。如果瓦片16、17、18、19、20加载到同一纹理上,则依次排列的起始位置便在瓦片1到4的下边。每个纹理中瓦片起始位置对应的列号和行号保存在瓦片队列中。
制作纹理和瓦片
瓦片队列从左到右记录每个纹理对应的列号和行号,从上到下记录每个纹理对应的起始行号,即在瓦片队列的右侧可看出总共加载的纹理数。若瓦片12加载到纹理5,则从瓦片队列右侧能看出总计加载了6个纹理。
整个渲染过程依赖瓦片队列,队列的长度决定了可以同时加载的瓦片数量,与地图性能密切相关。若瓦片队列过长,每个瓦片都对应纹理,会占用更多内存资源,降低渲染速度,所以一般来说,瓦片队列的长度会控制在10到15个之内。若瓦片队列过短,可同时加载的瓦片数量会受限,影响地图渲染的连续性,导致地图在快速移动或缩放时变得断断续续。
注意,瓦片加载算法并不复杂,算法关键点在于内存管理,因为内存是稀缺资源,必须合理使用。若瓦片队列过长,既消耗大量内存,又对实际渲染无益,还会对内存管理产生一定压力。若瓦片队列过短,加载新瓦片时,为了腾出足够空间,需要先卸载旧瓦片,过程中会浪费内存空间,还会影响渲染连续性,容易导致地图断断续续。
纹理加载和卸载
在程序中,瓦片按瓦片序号从左到右依次加载到纹理上,同时将每个瓦片的纹理坐标存入瓦片队列,并存储纹理起始行号。需要注意的是,必须在瓦片数据加载完成后才能加载对应的纹理。否则,很可能会因为数据加载失败导致程序运行出错。
为确保加载完成后才继续加载纹理,通常做法是加载瓦片数据的同时,为每个瓦片创建一个定时器,若定时器触发,则表示数据加载失败。相反,数据加载成功后,定时器会取消。此方案优点在于逻辑简单,缺点在于当多个瓦片同时加载时,容易出错。
另一种方法是将瓦片数据加载与纹理加载解耦,解耦的方法很多,比如借助消息队列或事件监听。当瓦片数据加载完成,程序会发出加载成功的信号,纹理加载程序接收到信号后,再加载相应的纹理。这种解耦方式相比前一种更健壮,处理多个瓦片数据时出错几率更低。
合理安排地图瓦片的切分
地图瓦片切分时,如何合理组织纹理是程序性能优化的关键。影响纹理加载性能的因素主要有三个:① 将若干瓦片组合成纹理时,纹理边缘可能存在边缝,若所有瓦片都这么做,最终整张纹理会覆盖很多细小的边缝,导致纹理尺寸增加。纹理尺寸越大,载入纹理需要花费的时间越长,显示纹理时也会占用更多显存。因此,减少纹理边缘的边缝很重要。② 若纹理本身尺寸太大,则必须将其切割成多个小块加载,以防止内存溢出。但这样一来,瓦片加载过程会很繁琐。③ 若加载纹理时,纹理的一部分数据已经加载进显存,而另一部分数据还未加载进显存,这时若需要渲染使用未加载进显存的纹理数据,就会出现渲染中断问题,影响渲染速度。纹理尺寸越大,出现渲染中断的几率越高。
为解决这些问题,有以下优化方案:① 切割纹理时,为了尽可能减少边缝,应该将瓦片规则排列在纹理上,避免将其打散。这样一来,瓦片的边缘就只能出现在纹理的边缘上,而不会出现在纹理的内部,渲染时无需使用边框进行处理,可以大幅提升效率。② 控制纹理大小,以减少纹理数量。③ 合理安排地图瓦片的切分,尽量确保同一纹理中的所有瓦片都一次性加载进显存,避免纹理数据加载不均匀时出现渲染中断。
后记
本文介绍了基于WebGL实现的腾讯地图自定义栅格图层的关键点,并结合技术指南与范例,分享了相应的踩坑经验,助力地图开发者轻松上手,提升开发效率,避免踩坑风险。希望对大家有所帮助。