LBS 开发微课堂|Polyline绘制优化:效果更丰富,性能更佳!

news2024/9/21 17:45:23

为了让广大的开发者

更深入地了解

百度地图开放平台的技术能力

轻松掌握满满的技术干货

更加简单地接入

开放平台的服务

我们特别推出了

“位置服务(LBS)开发微课堂”

系列技术案例

第一期的主题是

《Polyline 绘制优化升级》

你还想了解哪些技术内容?

快来评论区留言告诉我们吧!

cut-off

Polyline(线段)绘制,作为地图绘制的基础,凝聚着工程师们的巧思与智慧。百度地图开放平台持续对地图 SDK 的 Polyline 绘制技术进行优化,努力为开发者提供更好的开发体验。

百度地图最新版本的地图 SDK 在基础性能、渲染效果以及场景化应用等方面都有了明显的突破,让地图绘制更流畅,绘制效果更丰富。

(向上发光效果呈现出的围栏视觉效果)

(司乘同显:乘客端小车平滑移动效果)

今天,让我们一起来看看这些技术提升背后的秘密,体验一下百度地图在 Polyline 绘制方面的过人之处吧!


1 Polyline渲染优化

新版地图 SDK 的 Polyline 绘制功能采用了记录法向量的方式,有效解决了线宽变化导致的顶点数据重复计算的问题,使得开发者在调用相关功能进行开发时,能够显著降低CPU的占用率。

1.1 顶点数据优化方案

旧版 SDK:在线的每一段的顶点处,垂直当前线段做垂线,再沿垂线各取二分为一线宽长度计算出上下两个顶点的位置坐标。

新版 SDK:在线的每一段的顶点处,垂直当前线段做两个相反方向的射线,记录顶点位置点及射线的方向向量,绘制时传入线宽。

以两个点的线段为例:

旧版本(图 1)在 CPU 阶段根据线宽计算顶点位置 a1、a2、b1、b2 和纹理坐标 st 。

新版本(图 2)中直接记录原始 A、B 和 an1、an2、bn1、bn2 方向信息。

顶点偏移量计算 delta= an1*lineWidth*线宽缩放比例,等同于 shader 中的 vec4 delta= vec4(a_normal.xy * u_line_width * v_direction, 0, 0) 。

线宽缩放比例在正常直线时为 1,拐角连接处根据拐角类型(jointype)计算需要的缩放比例。比如:圆角为 1,尖角为向量 AB 的法向量与 AB、BC 法向量相加的向量的点乘结果(有最大值限制)。

1.2 顶点数据差异对比

图 3(旧版本)

图 4(新版本)

旧版中(图 3):a_position 中 xyz 代表位置,a_texCoord 中 st 代表纹理坐标。

新版中(图 4):a_position 中 xyz 代表位置,w 代表累计长度(纹理坐标及 Track 动画时使用);射线方向向量在 a_nomal 中,xy 代表法向量,z 的正负代表法向量的正逆,用于纹理计算;z 的绝对值代表线宽缩放比例,用于顶点偏移量计算。

1.3 Shader数据处理实现

图 5( 旧版本)

图 6( 新版本)

旧版中(图 5):gl_Position 数据由传入的顶点数据经过 MVP 矩阵转化后得到;纹理坐标直接传递给片段着色器。

新版中(图 6):gl_Position 数据由传入的顶点数据+线宽对应的顶点偏移量计算后再经过 MVP 矩阵转化后得到;纹理坐标也在顶点着色器 Shader 中计算后传递给片段着色器。

gl_Position 根据线宽在顶点着色器 Shader 中计算:

// 线宽缩放比例,直线时为1,拐角处根据拐角类型计算得出
float v_direction = abs(a_normal.z);
// 线宽对应的顶点偏移
vec4 delta= vec4(a_normal.xy * u_line_width * v_direction, 0, 0);
gl_Position = u_MVPMatrix * vec4(a_position.xyz, 1) + u_MVPMatrix * delta;

纹理坐标在顶点着色器 Shader 中计算(以repeat方式为例):

float s = 0.5 + a_normal.z * 0.5;
// u_gl_to_pixel不同地图缩放层级的坐标像素比例
// u_tex_height0为纹理高度
float t = a_position.w * u_gl_to_pixel / u_tex_height0;
v_tex_coord0 = vec2(s, t);
另外还内置其他纹理坐标计算方式:拉伸中间部分,纹理整数倍平铺、0~0.5 部分拉伸、单纹理拉伸、纹理等比缩放等。

路线走过擦除、置灰场景,走过和未走过路线样式的处理,是根据顶点着色器 Shader 中传递的累计长度(v_acculength)在片段着色器 Shader 中控制并渲染。

v_accuLength = a_position.w;
if (v_accuLength >= u_progressLength) { // progress forward
   gl_FragColor = u_color1;
} else { // progress backward
   gl_FragColor = u_color0;
}

1.4 性能对比

同等 26,050 个点数据路线绘制(乌鲁木齐-深圳),新旧版本性能对比,可以看到 CPU 占用率下降超 50%,GPU 性能没有明显改变。

图 7(旧版本)

图 8(新版本)

2 发光效果优化

2.1 性能优化

得益于顶点数据优化方案,新版的Polyline绘制实现了发光与非发光效果的顶点数据共享同一份数据Buffer,开发者在调用相关功能的过程中,可以显著降低内存的占用量。

2.2 模糊发光

旧版的发光效果逻辑中,需要用到离屏渲染,绘制比原polyline宽度更宽的线,然后进行多次模糊处理,生成一张模糊图片绘制到原来的Polyline下方,实现发光效果。所以旧版SDK的发光效果就需要两倍的时间、空间去计算和储存点信息,还要离屏渲染,不仅要申请额外的帧缓冲空间,多次模糊的处理还增加了GPU的耗时时间。

针对模糊效果的离屏渲染问题,我们在新版SDK的Shader中采用了模糊函数进行替代,避免了相关问题。模糊程度可通过系数灵活控制。

代码片段:

if (uniforms.u_bloom == 1) {
  // 透明度渐变发光
    // uniforms.u_speed衰减速度
    weight = pow(weight, uniforms.u_speed);
} else if (uniforms.u_bloom == 2) {
    // 模糊发光
    // uniforms.u_times代表模糊程度
    // r = 根号2 = 1.414,σ为 r/3 = 0.471
    // 2.0*σ方 = 2.0 * 0.471 * 0.471 =  0.443682
    weight = 1.0 - exp( - (weight * weight ) / float(uniforms.u_times) * 0.443682);
}

新、旧版模糊发光效果对比:

2.3 发光方向

通过记录方向向量的方案,发光效果拥有了更多的自由度:新版SDK的发光效果不仅可以实现正常的向两侧发光,还支持单侧发光和向上发光。Polygon边线、Circle的边线、弧线、大地曲线也采用了类似Polyline的处理技术。

多方向发光效果:

图 11 线段

图 12 圆边线

图 13 Polygon 边线

2.4 参数接口

Polyline的发光效果功能为开发者提供了高度灵活且可配置的参数接口,从而可以实现更加丰富和吸引人的用户体验,助力开发者打造出更具竞争力的应用。

渐变线多方向不同发光参数动态更新效果:

3 Track 动画

3.1 场景分析

在司乘同显场景中,旧版 SDK 在司乘同显组件中对路线和小车数据进行绑路计算,每次动画结束需要更新 Polyline 的点数据集,每次更新变化就会产生大量的计算。然而大部分的情况下整体路线信息是没有变化的,只是随着行程进度进行路线擦除或置灰。类似的还有轨迹回放,小车平滑移动等场景。为了解决以上问题,Polyline绘制引入了Track 动画。

3.2 Track 动画

在新版 SDK 中,Polyline 新增的 Track 动画能力,可以根据行程进度对路线进行动画处理;除了按进度进行动画,还内置了绑路逻辑,开发者可以直接传入小车行进的位置和方向信息,由 SDK 自动绑路后进行动画;另外除了正常(Nomal)样式,还新增了走过和未走过路线样式,实现 Polyline 走过和未走过路线的自定义绘制。对比旧版的 BMKTraceOverlay,在性能、效果、易用性和灵活性方面都有较大提升。

历史轨迹回放:

图 15

走过路线擦除:

图 16

新旧版本特性对照:

新版效果将于 9 月份在官网发布的 Android 地图 SDK V7.6.3 和 iOS 地图 SDK V6.6.3 版本中呈现,敬请期待!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1973245.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MySQL:Prepared Statement 预处理语句

预处理语句(Prepared Statement) 是一种在数据库管理系统中使用的编程概念,用于执行对数据库进行操作的 SQL 语句。 使用预处理语句的具体方式和语法依赖于所用的编程语言和数据库管理系统。常见的编程语言如 Java、PHP、Python 和 C# 都提供…

如何把视频语音转文字?交给这4款工具就完事

这两天巴黎奥运会的盛大开幕,世界各地的记者们纷纷涌入这个体育盛事的现场,带着他们的镜头和麦克风,捕捉每一个激动人心的瞬间。 然而,随着采访的深入,如何快速准确地将这些珍贵的视频内容转化为文字记录,…

代码随想录算法训练营第十七天 | 654.最大二叉树, 617.合并二叉树 ,700.二叉搜索树中的搜索 , 98.验证二叉搜索树

目录 654.最大二叉树 思路 方法一: 递归基础版 方法二:递归使用下标 方法三:递归使用切片 心得收获 617.合并二叉树 思路 递归法 迭代法 方法一: 递归 - 前序 - 修改root1 方法二:递归 - 前序 - 新建root…

敦煌文化主题页面 HTML,CSS,Javascript 源码分享

使用技术:HTML,CSS,JavaScript 项目亮点:加入了大量的CSS动画效果,以及JS交互效果,水平适合初学者以及大学生,包含登录注册页 需要的可以dd, 绿泡泡:ColdDayOne

AI入门指南:什么是人工智能、机器学习、神经网络、深度学习?

文章目录 一、前言二、人工智能(AI)是什么?起源概念人工智能分类人工智能应用 三、机器学习是什么?概念机器学习常见算法机器学习分类机器学习与人工智能的关系 四、神经网络是什么?概念神经网络组成部分神经网络模型神经网络和机器学习的关系…

【Hot100】LeetCode—76. 最小覆盖子串

题目 原题链接:76. 最小覆盖子串 1- 思路 利用两个哈希表解决分为 :① 初始化哈希表、②遍历 s,处理当前元素,判断当前字符是否有效、③收缩窗口、④更新最小覆盖子串 2- 实现 ⭐76. 最小覆盖子串——题解思路 class Solution …

Python | Leetcode Python题解之第316题去除重复字母

题目: 题解: class Solution:def removeDuplicateLetters(self, s: str) -> str:vis defaultdict(int)cnt defaultdict(int)for ch in s: cnt[ch] 1queue []for ch in s:if vis[ch] 0:while queue and queue[-1] > ch and cnt[queue[-1]]:vi…

VS Code设置C++编译器路径

C_Cpp.default.compilerPath是C/C编译器路径; python.condaPath是conda路径.

Could not connect to Redis at 127.0.0.1:6379: 由于目标计算机积极拒绝,无法连接

目录 报错 解决办法 报错 在redis文件夹的路径栏中输入 cmd 命令,打开控制栏窗口界面 报错说是 redis-cli.exe打开就显示Could not connect to Redis at 127.0.0.1:6379: 由于目标计算机积极拒绝,无法连接。 解决办法 (1)cmd…

【教学类-71-01】20240802蔬菜切切乐01

背景需求: ✂️自制教具分享✂️蔬菜切切乐(剪纸) - 小红书 (xiaohongshu.com)https://www.xiaohongshu.com/explore/65bf6809000000001100fa53?app_platformandroid&ignoreEngagetrue&app_version8.46.0&share_from_user_hidd…

mybatis保存postgresql数组格式数据

新建表的时候在int4后加上[]中括号就行 -- 创建数组 SELECT ARRAY[1, 2, 3, 4, 5];-- 访问数组元素(从1开始) SELECT ARRAY[1, 2, 3, 4, 5][1]; -- 返回 1-- 数组长度 SELECT array_length(ARRAY[1, 2, 3, 4, 5], 1); -- 返回 5-- 数组连接 SELECT ARRA…

C语言 | Leetcode C语言题解之第316题去除重复字母

题目&#xff1a; 题解&#xff1a; char* removeDuplicateLetters(char* s) {int vis[26], num[26];memset(vis, 0, sizeof(vis));memset(num, 0, sizeof(num));int n strlen(s);for (int i 0; i < n; i) {num[s[i] - a];}char* stk malloc(sizeof(char) * 27);int stk…

Linux软件编程

8月1日学习了最后的标准IO&#xff0c;流的偏移。然后进入了文件IO的学习&#xff0c;包括文件的打开、读写、关闭以及偏移。之后又学习了剩余的一些函数接口&#xff0c;可以对文件进行一些其余操作。 8月2日学习了目录文件和链接文件的操作。目录文件的操作包括目录的创建、…

8月17日|广州|Cocos开发者沙龙不见不散!

6月底举行的Cocos成都沙龙吸引了近200位开发者和10多家发行&#xff0c;得到了大家的一致好评。 Cocos广州沙龙即将到来&#xff0c;会邀请更多KOL和头部发行、渠道嘉宾分享行业经验&#xff0c;让大家实现技术干货、游戏合作、行业信息多丰收。 活动主题&#xff1a;小游戏与出…

二叉树构建(从3种遍历中构建)python刷题记录

R3-树与二叉树篇. 目录 从前序与中序遍历序列构造二叉树 算法思路&#xff1a; 灵神套路 从中序与后序遍历序列构造二叉树 算法思路&#xff1a; 灵神套路 从前序和后序遍历序列构造二叉树 算法思路&#xff1a; 灵神套路 从前序与中序遍历序列构造二叉树 算法…

请你学习:前端布局2 - 定位(Positioning)是一种重要的布局技术

在页面布局中&#xff0c;定位&#xff08;Positioning&#xff09;是一种重要的布局技术&#xff0c;它允许我们精确地控制元素在页面上的位置。定位模式、是否脱标以及移动位置是理解定位的三个关键方面。 1 定位模式 定位模式决定了元素在文档中的定位方式&#xff0c;通过…

一款完全免费的数据恢复软件

WinFR&#xff0c;Windows文件恢复&#xff08;微软命令行程序&#xff09;的免费图形界面&#xff0c;帮您轻松恢复文件。WinFR是免费的Windows数据恢复替代方案&#xff0c;支持U盘数据恢复、硬盘数据恢复、存储卡数据恢复、文件数据恢复等功能。WinFR完全调用Windows文件恢复…

简单的docker学习 第2章docker引擎

第2章docker引擎 2.1Docker 引擎发展历程 2.1.1 首发版本架构 Docker 在首次发布时&#xff0c;其引擎由两个核心组件构成&#xff1a;LXC&#xff08;Linux Container&#xff09;与 Docker Daemon。不过&#xff0c;该架构依赖于 LXC&#xff0c;使得 Docker 存在严重的问…

第一百八十六节 Java XML教程 - Java DOM编辑

Java XML教程 - Java DOM编辑 属性 以下代码显示如何向元素添加属性。 import java.io.StringWriter;import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.transform.OutputKeys; import javax.xml.transform.Tr…

【OS】AUTOSAR OS Spinlock实现原理(下篇)

目录 3.1 Spinlock配置代码 3.1.1 Os_SpinlockConfigType_Tag 3.1.2 Os_LockConfigType_Tag 3.1.3 不同配置参数对配置代码生成的影响 3.2 Os_GetSpinlock详解 3.2.1 Os_SpinlockIsNotLockedLocal 3.2.2 Os_SpinlockIsLockOrderValid 3.2.3 Os_SpinlockSuspendByMethod…