基于 Three.js 的 3D 模型加载优化

作者:来自 vivo 互联网前端团队- Su Ning

作为一个3D的项目,从用户打开页面到最终模型的渲染需要经过多个流程,加载的时间也会比普通的H5项目要更长一些,从而造成大量的用户流失。为了提升首屏加载的转化率,需要尽可能的降低loading的时间。这里就分享一些我们在模型加载优化方面的心得。

一、前言

近段时间,我们使用three.js完成了vivo拟我形象的开发工作,大家可以在vivo账号中拟制属于自己的3D形象,也可以保存作为自己的头像名片。

作为一个3D的项目,从用户打开页面到最终模型的渲染需要经过多个流程,加载的时间也会比普通的H5项目要更长一些。然而过长的等待时间会造成大量的用户流失,这部分用户没有体验到具体的功能就退出了页面非常的遗憾,为了提升首屏加载的转化率,需要尽可能的降低loading的时间。这里就分享一些我们在模型加载优化方面的心得。

二、模型加载的优化思路

想对加载进行优化,首先需要了解Three.js加载模型时的工作流程,并分析出其中耗时的部分进行针对性的处理。

在Three.js中,模型从加载到渲染需要经过模型下载、序列化模型、网格解析、写入缓存和渲染模型几个步骤,经过分析发现主要的瓶颈在网络请求和网格解析两个部分,所以整体的优化思路就是减少网络请求资源的体积和提升网格的解析速度。

图片

三、缩小模型的体积

3.1 常见的解决方案

目前主流的压缩方案是使用google的draco库对模型进行压缩。draco的原理类似降低图片的分辨率,通过减少模型的顶点数起到压缩体积的效果。

也就是说draco是一种有损的压缩方式,这样就会带来诸多的问题

  • 可能在网格连接处存在画面模型撕裂。

  • 仅仅压缩顶点只能将50.7mb的人物模型压缩到49.5,压缩效果有限。

  • draco前台decoder在h5中的解算效率不理想,可能节省下来的网络请求时间还没有增加的数据解算的时间长。

基于以上几点,最终我们放弃了draco的压缩方案。

图片

使用draco压缩之后导致的模型撕裂

3.2 进阶方案

高端的食材,往往只需要采用最朴素的烹饪方式。经过一些尝试,我们发现将glb模型直接打成zip包可以明显的提升模型的压缩效率。50.7mb的人物模型可以压缩到11.6mb。

图片

图片

但是Three.js提供的gltfloader是不能直接加载zip文件的,于是我们需要对其进行功能扩展。

Three.js加载gltf模型是首先通过fetch请求获取到模型的arraybuffer,再对arraybuffer进行格式化。所以我们只需要在模型格式化之前拦截zip文件进行解压缩即可。

图片

于是我们使用jszip,资源加载完成后判断资源的后缀,如果是zip文件就使用jszip进行解压缩。

图片

看起来还不错,在保证视觉效果的同时又可以大幅压缩模型的体积,那么有没有可能做的再极致一些呢?

既然是针对性的场景,我们就可以从解压缩的解算开始入手,于是我们使用rust写了一个解压工具,将其转换成wasm包代替jszip,可以发现wasm的冷启动性能确实要比js好很多,可以将解压的时长从几十到100毫秒降低到1毫秒左右,适合体积比较小的解压缩场景。

图片

图片

四、文件的加解密

作为一个h5项目,获取到静态资源的链接并不困难,所以需要对模型文件进行一点点加密,让破解起来没有那么容易。同时解密的过程不能显著延长资源加载的时间,影响用户体验。

基于数据解密的效率,我们可以截取文件buffer的一部分进行加密,而不对全文进行加密,同时将数据解密的过程也放到wasm中,提升解算效率的同时也增强了安全性。采用对称加密的算法,同一个方法既可以用于加密,也可以用于解密。

按照模型加载的流程,解密的操作应该放在解压缩之后,序列化之前,那么如何判断数据是否进行了加密呢,可以通过判断解压数据decode以后是否有glTF的标记来确定。

图片

如下图,数据解密的耗时几乎可以忽略不计,可以放心使用。

图片

五、如何优化首帧的渲染体验

优化完模型的加载,继续来优化模型的渲染,在加载一个体积比较大的模型的时候经常会有页面的卡死的情况出现,需要从两方面治标也治本的进行优化:

  1. 通过减少页面的卡停来优化用户的感官体验。

  2. 通过缩短首屏渲染的时长来解决根本问题。

5.1 减少页面的卡停

在模型加载的时候通常会设置一个loading页面来展示当前的加载进度,同时loading页也可以播放一些动效或者互动来让用户等待的过程中不那么无聊。但是由于js单线程的特性,在进行首帧渲染的时候任何事件都不无法响应,会让用户误以为页面卡死,造成流失。

为了解决这个问题我们可以使用分步加载的方案,在模型加载的时候先遍历第一层网格,将所有的网格隐藏起来,然后循环这些网格,每展示一个就执行一次render方法,这样就可以把一个大的卡顿分散成多个小的,不至于影响前台的体验。

图片

但是这样的方法只能让用户感受起来没那么卡顿,该等的时间一点没少,过长的等待时间还是会让用户等的不耐烦,有没有其他解决卡顿的方式呢?这就要从Three.js的渲染逻辑来进行分析了。

5.2 缩短首帧渲染的时间

由于我们做的是一个捏脸的项目,通过形态键来实现不同的脸型,表情等表现。在Three.js中存储形态键信息的属性在geometry.morphAttributes中,形态键存放的顶点信息总数与网格的顶点数相同,这就意味着同一个模型有多少个形态键,就额外需要加载多少套网格的顶点信息。在首次渲染的时候Three.js会遍历每一个形态键的顶点信息,生成一个float32array,而这个巨量的遍历操作就是造成卡顿的根本原因。

图片

如何解决这个循环黑洞呢,我想到了steamdeck上的着色器预缓存,通过将着色器编译的结果进行持久化,缩短页面加载的时间。那么我们只要将每一个网格的形态键编译的结果储存起来就行了。

  • /three/src/renderers/webgl/WebGLMorphtargets.js

图片

通过这种方式成功的将首帧渲染的时间从7秒缩短到0.6秒,大幅的提升了用户的体验。

讲到这里,大家可能发现了,虽然首帧渲染的时长缩短了,但是形态键缓存的资源有80mb,压缩后也有15mb,这块的时长可不可以继续压榨呢,先看一下资源的处理流程,处理解压后的文件需要将文件解析成JSON字符串,然后在转换成float32array,这里耗时最大的点就是JSON.parse的操作,有没有更好的方式处理呢,可以将这部分内容丢到rust里面,平均可以减少0.5s的时间。

图片

图片

六、总结与规划

以上就是我们的优化流程,将glb模型文件压缩成zip包,配合前台wasm解压工具降低模型的加载时间。通过增加形态键缓存的方式来降低首帧渲染的时长。

图片

经过这一系列的操作,成功的将模型的体积从50mb压缩到11mb,增加了额外80mb的形态键缓存也可以使用zip压缩到15mb,处理后页面的首次加载时长从15秒缩短到5秒,算是一个不小的提升。

然而,我们也意识到还有进一步的优化空间,譬如目前虽然有了形态键缓存,但是原模型中的形态键信息还存储在模型中,这一部分的信息不需要被threejs读取,却很大的占用了模型的体积,后续可以开发一个gltf-pipeline类似的处理工具,将形态键缓存直接整合进gltf模型中,同时把整个模型的序列化工作放到wasm中处理,降低模型的尺寸的同时也可以减少模型解析的时长。期待为大家带来更好的使用体验。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

ELK企业级日志分析

目 录 一、ELK简介 1.1 elasticsearch简介 1.2 logstash简介 1.3 kibana简介 1.4 ELK的好处 1.5 ELK的工作原理 二、部署ELK 2.1 部署elasticsearch(集群) 2.1.1 修改配置文件 2.1.2 修改系统参数 2.1.2.1 修改systemmd服务管理器 2.1.2.2 性能调优参数 2.1.2.3 …

9.11和9.9哪个大?

没问题 文心一言 通义千问

信创数据库沙龙(南京站 | 开启报名)

信创数据库沙龙: 是一个致力于推动数据库技术创新和发展的高端交流平台,旨在增强国内数据库产业的自主可控性和高质量发展。这个平台汇集了学术界和产业界的顶尖专家、学者以及技术爱好者,通过专题演讲、案例分享和技术研讨等丰富多样的活动形式&#x…

(ISPRS,2021)具有遥感知识图谱的鲁棒深度对齐网络用于零样本和广义零样本遥感图像场景分类

文章目录 Robust deep alignment network with remote sensing knowledge graph for zero-shot and generalized zero-shot remote sensing image scene classification相关资料摘要引言遥感知识图谱的表示学习遥感知识图谱的构建实体和关系的语义表示学习创建遥感场景类别的语…

【C#】计算两条直线的交点坐标

问题描述 计算两条直线的交点坐标,可以理解为给定坐标P1、P2、P3、P4,形成两条线,返回这两条直线的交点坐标? 注意区分:这两条线是否垂直、是否平行。 代码实现 斜率解释 斜率是数学中的一个概念,特别是…

TiDB实践—索引加速+分布式执行框架创建索引提升70+倍

作者: 数据源的TiDB学习之路 原文来源: https://tidb.net/blog/92d348c2 背景介绍 TiDB 采用在线异步变更的方式执行 DDL 语句,从而实现 DDL 语句的执行不会阻塞其他会话中的 DML 语句。按照是否需要操作 DDL 目标对象所包括的数据来划分…

QT样式美化 之 qss入门

样例一 *{font-size:13px;color:white;font-family:"宋体"; }CallWidget QLineEdit#telEdt {font-size:24px;}QMainWindow,QDialog{background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,stop: 0 #1B2534, stop: 0.4 #010101,stop: 0.5 #000101, stop: 1.0 #1F2B…

springboot项目中,yml文件乱码

项目场景: 在springboot项目的resource目录,新建yml文件,并且输入了中文,但是关闭idea,再打开,里面的中文乱码了 问题描述 原因分析: 编码设置相关 解决方案: 方案1&#xff0…

使用 XPath 定位 HTML 中的 img 标签

引言 随着互联网内容的日益丰富,网页数据的自动化处理变得愈发重要。图片作为网页中的重要组成部分,其获取和处理在许多应用场景中都显得至关重要。例如,在社交媒体分析、内容聚合平台、数据抓取工具等领域,图片的自动下载和处理…

Linux源码安装的Redis如何配置systemd管理并设置开机启动

文章目录 实验前提实验 实验前提 已完成源码安装并能正常启动redis /usr/local/bin/redis-server能正常启动redis 实验 vim /etc/systemd/system/redis.service内容如下: [unit] Descriptionredis-server Afternetwork.target[Service] Typeforking ExecStart/…

k8s集群 安装配置 Prometheus+grafana

k8s集群 安装配置 Prometheusgrafana k8s环境如下:机器规划: node-exporter组件安装和配置安装node-exporter通过node-exporter采集数据显示192.168.40.180主机cpu的使用情况显示192.168.40.180主机负载使用情况 Prometheus server安装和配置创建sa账号&…

[论文笔记] CT数据配比方法论——1、Motivation

我正在写这方面的论文,感兴趣的可以和我一起讨论!!!!!! Motivation 1、探测原有模型的配比: 配比 与 ppl, loss, bpw, benchmark等指标 之间的关系。 2、效果稳定的配比:配比 与 模型效果 之间的规律。 Experiments 1、主语言(什么语言作为主语言,几种主语言?…

Linux----Mplayer音视频库的移植

想要播放视频音乐就得移植相关库到板子上 Mplayer移植需要依赖以下源文件:(从官网获取或者网上) 1、zlib-1.2.3.tar.gz :通用的内存空间的压缩库。 2、libpng-1.2.57.tar.gz :png格式图片的压缩或解压库 3、Jpegsrc.v9b.tar.gz : jpeg格式图片的压…

docker应用:搭建云手机

简介:近来慵懒,身体懈怠良多,思来想去随手看点小攻略以宽慰不懈怠的心。云手机Cloudphone,就是将云计算技术运用于网络终端服务,通过云服务器实现云服务的手机。其实就是深度结合了网络服务的智能手机,这类…

初谈Linux信号-=-信号的产生

文章目录 概述从生活角度理解信号Linux中信号信号常见的处理方式理解信号的发送与保存 信号的产生core、term区别 概述 从生活角度理解信号 你在网上买了很多件商品,再等待不同商品快递的到来。但即便快递没有到来,你也知道快递来临时, 你该…

【IntelliJ IDEA】一篇文章集合所有IDEA的所有设置

IntelliJ IDEA 是一款功能强大的集成开发环境(IDE),其设置涵盖了多个方面,以满足不同开发者的需求和偏好。由于 IDEA 的设置相当复杂和详尽,这里无法在一篇简短的文章中详细介绍所有设置。然而,我可以提供一…

义务外贸wordpress独立站主题

健身器材wordpress网站模板 跑步机、椭圆机、划船机、动感单车、健身车、深蹲架、龙门架、健身器材wordpress网站模板。 https://www.jianzhanpress.com/?p4251 农业机械wordpress网站模板 植保机械、畜牧养殖机械、农机配件、土壤耕整机械、农业机械wordpress网站模板。 …

戴着苹果Vision Pro,如何吃花生米

6月底苹果Vision Pro国内开售,我早早到官网预订了一台。选择必要的配件,输入视力信息,定制符合自己视力的蔡司镜片。确实贵。把主要配件和镜片配齐,要3万6,比Pico、META的眼镜贵一个数量级。 Vision Pro出来后&#x…

复合翼无人机搭载自组网模块集群组网技术实现详解

复合翼无人机作为一种具备高效飞行和长航时特点的飞行器,在多个领域如军事侦察、环境监测、灾害救援等都有着广泛的应用。而为了实现复合翼无人机之间的高效通信,搭载自组网模块实现集群组网技术显得尤为重要。本文将详细介绍复合翼无人机搭载自组网模块…

Java实现随机题库-全站最呆瓜思想,保证你能学会

目录 Blue留言 : 学本篇文章之前所需掌握技能 推荐视频: 代码逻辑思想 步骤: 1、引入依赖 2、做一个excel表格 3、java实现从excel表中取数据 第一步:根据excel上面的字段名(如下图)&#xff0…