大型 3D 互动项目开发和优化实践

点击上方 前端Q,关注公众号

回复加群,加入前端Q技术交流群

开发背景

得益于“元宇宙”概念在前段时间的爆火,各家公司都推出了使用 3D 场景的活动或频道。

ff2c3199d238e563bb8fe668ad560976.gif
https://img13.360buyimg.com/imagetools/jfs/t1/220303/24/28446/2896414/6476b7f1F5f42bd3a/029b1f997b40151e.gif
427c9562e5d9f5c578d68c3d34fc492b.gif
https://img11.360buyimg.com/imagetools/jfs/t1/125059/29/37448/3233054/6476baa8Fbc2d03d0/33818977a21a42f1.gif

3D 场景相比传统的 2D 页面优点是多一个维度,同屏展示的内容可以更多,能完整的展示物体、商品的信息。

相应带来的缺点是用户使用方式改变,用户需要额外的学习成本。另外初期需要的开发量、美术资源和生成3D模型的设备也是增加的成本。

在这样的背景下,我们团队接到了食品频道的一个互动项目的开发需求,希望通过 3D 场景的展示和互动方式,作为对未来购物的一种尝试与探索,满足用户对未来美好新奇的一个需求。将购物场景化、娱乐化,给用户带来美好的购物感受。

b60dee11298a8b497198a5bc7987c78e.jpeg
https://img12.360buyimg.com/imagetools/jfs/t1/97211/35/26397/124352/6476bbbcFa5164793/f7f9a586e6ea7620.jpg

前端框架选择

3D项目相比之前的2D项目改变的主要是客户端的表现。在希望不依赖app客户端支持和在尽量多的环境下能运行,我们首先采用的方案是在 Web 端实现 3D 项目。

开发套件—

首先我们考虑的是成熟的开发套件,如unity/egret等,但这些开发套件都有一些我们不能绕过的问题,例如:

  • 商业化使用需要收费

  • 需要使用其他语言开发(如 C# ),对团队学习成本较大

  • 打包输出的文件大小过大

  • 官方文档不够详细,学习曲线较抖

引擎名称/对比维度使用价格(权重50%)脚本上手(权重30%)场景搭建(权重20%)支持模型格式(权重10%)社区资料丰富程度(权重30%)支持web端发布(一票否决)
Unity 3d3710810Y
Laya49777Y
Egret108776Y
Cocos2d-js




N
Godot107787Y

由于以上的原因,开发套件里没有令团队很满意的选择,我们从其他方向寻找开发工具。

开源渲染库—

另外也比较了 Web 前端使用量较多的两个 3D 渲染库:

  • three.js 提供的组件粒度较小,较基础,能做很高程度的定制化二次开发,但如果需要开发一个互动项目,需要开发的组件比较多

  • babylon.js 既提供了粒度小的基础组件,也封装了接近开箱即用的组件。并自带了性能测量工具,提供了方便的debug方法和优化策略

经过团队内对各个开发套件/渲染库的试用,最后选择了 babylon.js 作为项目的渲染层库,在其提供的组件上二次开发业务逻辑。

项目场景搭建

渲染分层结构—

项目渲染层级总体分为两层:3D 场景层和 HUD 层

3D 场景层顾名思义渲染 3D 场景,由人物模型、建筑模型和宝箱这些互动模型组成

HUD 层渲染互动按钮、弹窗、业务需要的商品列表等2D UI 内容

本来 babylonjs 是支持 3D 和 2D 内容混合渲染的,但是如果都使用 babylonjs 渲染,在设置两种内容需要使用统一的分辨率,而在现在的移动端设备上,能支持像素分辨率(如iPhone 14的像素分辨率为1170x2532)渲染不卡顿的只占一小部分。在大部分的设备上,最多只能支持在逻辑分辨率(如iPhone 14逻辑分辨率为390x844)下流畅运行,但设置这样的分辨率会使 2D 层渲染模糊,所以使用分层的方法渲染。

由 babylonjs 渲染 3D 场景层,而 HUD 层则通过 react 框架使用传统 DOM 方式渲染。

第二个 3D 渲染层—

渲染层分为 3D 场景层和 HUD 层带来了一个问题,需要在 HUD 层上再渲染 3D 内容时,例如展示 3D 模型,则不得不再增加一层 3D渲染层。而 3D 渲染层不停地在调用渲染方法,以响应用户操作和播放动画,这耗费了大量 CPU 和 GPU 的计算资源,还占用了存储模型顶点信息和贴图纹理的内存空间,因此在多个 3D 渲染层共存的情况下,需进行一定的管理以优化性能。我们采用以下策略管理多个 3D 渲染层:

  • 在展示另外的 3D 渲染层时再实例化,并暂停原来 3D 渲染层的渲染

  • 在不需要展示的时候销毁,恢复原 3D 渲染层的渲染方法调用

以尽量减少资源的占用,提高项目的渲染性能。

b7991cd28f72d8f78ac9d34d5f9a7c91.jpeg
https://img12.360buyimg.com/imagetools/jfs/t1/47088/13/21231/152433/6476bac2Fa76a9fb4/46144ec5dd733e60.jpg

交互组件开发

碰撞检测—

babylonjs 自带检测模型间是否碰撞的方法,但使用设计师提供的高精度模型直接去调用碰撞检测方法的话,计算量会很大,虽然未在测试设备上出现较严重的卡顿现象,但是已经使设备发热。

因此需要使用一个包围模型的不可见的、精简面的“空气墙”模型来做碰撞检测。在项目初期,这个“空气墙”模型需要设计师提供,在建模软件里根据原模型制作低精度包围模型。在后续迭代开发中,我们团队开发了“一键生成空气墙”的工具,自动生成低精度模型,减少设计师交付的资源数量,也减少更新模型时出错的机会。

130f2a00cc4b67e6c0ca6bc22eeac611.jpeg
https://img12.360buyimg.com/imagetools/jfs/t1/137287/2/36821/164863/64770da9F8623ceac/bae5848981ee5de7.jpg

镜头避障—

因为项目用的是第三人称的镜头,镜头离开人物模型有一定的距离,在人物走动或用户控制角度的时候,镜头有可能和建筑模型或场景模型碰撞,造成“镜头穿模”的现象。

babylonjs 自带的镜头没有避开模型的功能,在产品也没有处理经验的时候,我们做了如下两个方案:

  1. 镜头外围用一个不可见模型包围,跟人物一样与建筑、场景模型做碰撞检测,使镜头不会进入到模型中去。

这种方法的优点是可以使用内置的碰撞检测方法,不需要额外的开发量。但是缺点也很明显,用户对镜头和模型的碰撞导致停止没有预期,总会觉得镜头不自然的不受控制。

  1. 镜头和人物之间用棒状的模型连接,同样在棒状模型上调用与建筑、场景模型的碰撞检测,当棒状模型的某个位置发生碰撞时,镜头将移动到人物与碰撞点之间的位置,避免镜头进入模型的同时,也避免模型穿插在人物与镜头中间,造成导致用户找不到人物的问题。

这种方法实现的效果符合一些同样是第三人称视角的 3D 游戏的镜头运动逻辑,用户感受更自然,不会出现失控的现象。而引入的额外开发量也在可控的范围内。

481916379d6a09689e3d77978b1be1c1.gif
https://img10.360buyimg.com/imagetools/jfs/t1/136696/40/30256/3148299/6476ba96F2b4fd474/da06304d717e74ba.gif

与设计团队的资源交接

模型格式—

在众多的 3D 模型格式中,我们选择了 .gltf 格式。相对于其他模型格式,.gltf 可以减少 3D 格式中与渲染无关的的冗余数据,从而确保文件体积更小。

目前 3D 素材相对来说都比较大,这对于移动端加载体验来说,无疑是致命的。因此拥有更小体积的格式,也拥有了更高的优先选择权重。

除此之外,.gltf 是对近二十年来各种 3D 格式的总结,使用最优的数据结构,从而保证最大的兼容性以及可伸缩性,在拥有大容量的同时,支持更多的拓展,比如支持多贴图、多动画等。

所以 .gltf 成为了我们与视觉约定好的唯一素材格式。

模型输出流程—

本来设计师工作流使用的建模软件是 C4D ,但是在资源交接的过程中,我们发现了几个问题:

  1. 缺少导出 gltf 文件功能。在某些版本的 C4D 不能导出 gltf 格式的模型;某些版本能导出,但是导出有问题。而又因为设计师使用的一些渲染器支持问题,不能轻易更新 C4D 版本。

  2. 导出模型大小不统一。可能因为某些版本的 C4D 导出的问题,或是 C4D 里的一些设置没能导出到 gltf 文件,设计师几次导出的模型大小并不统一,例如人物模型比建筑模型还要大上好几倍。

  3. 导出材质信息丢失。设计师在建模时,因为模型可能会在多个渠道使用,例如渲染宣传图片,大部分情况会使用第三方的渲染器做渲染,这时候可能模型里会使用这些渲染器独有的材质。而这些材质导出到 gltf 文件时,会丢失这些独有材质的信息。再导入到页面的场景中时,设计师会发现展示的效果跟他们在建模软件里看到的相差甚远。

在和设计师多次沟通后,我们之间定立了一个导出模型的工作流:

在 C4D 建模完成后,导出 FBX 格式的文件,再导入到对 gltf 支持较好的 blender 软件中,设计师可以预览他们的材质在中转过程中有没有丢失效果,blender 导出的 gltf 文件中的模型也能保持一致的大小。

预设光影—

在默认的渲染设置中,我们把设计侧输出的模型放进场景中,加上光源,也只有明暗的变化,没有影子,缺少了一些立体感。

在我们尝试加入影子的过程中,发现性能受到严重影响。在查阅了渲染原理后,发现当每在一个平面上增加影子,相当于多渲染一次场景,渲染的压力成倍增加。

在跟设计侧交流后,决定在地板的贴图纹理上预先加上建筑的投影。这种方法对大部分是固定模型的场景能有较好的效果,而人物的阴影可以用静态图片跟随模型移动模拟。

de4b5b43710b2f52718f937eaf9e9200.jpeg

https://img14.360buyimg.com/imagetools/jfs/t1/138642/30/37525/34423/6476e644Fcaa0cfa1/b9f39d0c1e006780.jpg

渲染优化

压缩纹理—

在开发期间发现在型号旧一点的iPhone设备上很容易出现闪退的现象,应该是页面使用的内存超过了上限。

在项目中使用的资源体积最大的是模型 gltf 文件,检查文件的内容,占体积很大一部分的是纹理贴图,解析资源发现很多贴图的大小是3K(3072x3072的图片),根据 WebGL 渲染原理,无论贴图的资源原来是什么格式,最后在渲染前需要解压,相当于一张贴图需要在内存中占 3072 x 3072 x 3Byte = 27MB,解压后还需要传到 GPU,在多张贴图同时渲染时很可能占用大量的内存。

经过和设计侧的沟通,同意在一些展示距离不可能很近的模型上替换较低分辨率的贴图。

另外通常 2D 项目中使用的 png/jpg 格式图片,并不适合 3D 渲染,他们需要经过上述的解压过程,才能被 GPU 读取。

在 3D 渲染领域,有其他适合 GPU 读取的格式,如安卓支持的 ETC ,iOS 支持的 PVRTC,新一代的标准压缩纹理格式 ASTC ,他们都不需要解压就可以被 GPU 读取,可以大大减少中间解压占用的内存容量。

在项目中,我们使用 gltf-transform 工具做缩小贴图分辨率,和转换格式的工作。

模型减面—

模型在 WebGL 中渲染的流程是先用模型的顶点信息确定三角面,再在每个三角面上计算需要展示的颜色。

所以如果能减少模型面的数量,能减少每次渲染的计算量,减少每帧需要的渲染时间。

而如上面所说的,设计师建模的时候,可能面对的需求是输出渲染图,而不会对实时渲染做优化,所以在某些地方可能使用了过多的面。

参考团队内其他同学的优化经验(说一说 glTF 文件压缩),使用 gltf-transform 工具对模型进行自动化减面。在和设计测反复沟通后,我们确定了减面的参数 ratio = 0, error = 0.0001 。

合批渲染—

在 3D 渲染中有一个 draw call 的概念,一次 draw call 就是 CPU 向 GPU 下的一次画图指令。在一次指令中,CPU 会向 GPU 传递需要画的三角形信息,和三角形上颜色怎么计算的方法,这个方法用人类明白的语言称作材质。所以一次 draw call 只能画相同材质的面。

f36fa9c1bf6d0683b83a5f6cd3bf4425.png
https://img12.360buyimg.com/imagetools/jfs/t1/164489/23/33383/492796/6476e758F51c088c7/31fe4f1af20fa73d.png

因为每次 draw call 有这些准备的动作,所以通常两次 draw call 会比一次花的时间多。

在模型文件中,相同材质的面,可能不是定义在同一个模型中,这样 CPU 会把这些面拆分成不同的画图指令,令 draw call 数量增加。

有一种对这种情况的优化方法叫合批,可以对这些相同材质的面合并,使他们可以在一次 draw call 中完成绘制。

这工作没有工具帮助我们处理模型文件,但是在前端加载模型文件时,可以遍历模型中的网格 mesh ,把使用相同材质的做合并。

需要注意的是带动画的网格不能这样处理,因为合并后的物体中心会变化,例如两个自转的球合并之后会围绕两个球的中点公转。

后续迭代

模型懒加载和分级加载—

虽然暂时的项目展示的场景还不是很大,同时加载和渲染对设备的压力不算很大,但在场景增长到一定程度的时候,需要引入模型的懒加载和分级加载。

  • 懒加载策略:在镜头移动到足够靠近时再加载并插入模型到场景,销毁离镜头足够远的模型。

  • 分级加载策略:在镜头较远时,加载较低精度的模型,较近时再切换成精度高的模型。

以上两个策略都是现在较大型的 3D 游戏会使用的加载策略,能减少同一屏幕中绘制的面数量,减轻渲染压力。

分级渲染—

现时访问 3D 项目的设备性能差距非常大,有加上特效也能流畅运行的,也有只能在设备分辨率下基本运行的。

babylonjs 自带一个分级渲染的功能,能实时检测运行帧率决定是否降级,在之后的迭代中,可以增加从像素分辨率加上特效到设备分辨率基本渲染的分级渲染策略。

实时光影—

在使用以上的分级渲染策略后,可以在性能较好的设备上加上实时光影的特效,动态替换预烘焙贴图。

场景搭建工具—

在之前的项目开发过程中,设计师和产品、运营都需要通过前端输出demo才能大概体验到 3D 场景的效果,决定下一步如何调整。为解决这个痛点,我们团队开发了一个 3D 场景的搭建工具,用户可通过上传 gltf 文件搭建 3D 场景,实时预览渲染效果。

并加入了在项目中沉淀的互动组件,快速生成 3D 场景项目。

总结

以上内容基本覆盖了团队内开发 3D web 项目的整个流程,在从 0 到 1 的过程中积累了对 3D 模型的控制方法和 3D 渲染原理的理解,并用工程化手段简化中间的一些渲染优化流程。

在对独立的模型文件作优化后,对搭建完成的场景还可以作进一步优化,如模型间共用材质的合并,重复模型的实例化。并在与设计侧的沟通中,除了用规范控制输出模型的规格外,还需要能即时地告知渲染效果作出反馈,由此引发出开发场景搭建工具的想法。

3D 互动项目的开发经验还在不断累积的阶段,在往后的项目开发中将不断迭代开发工作流及沉淀开发工具,希望能和有相关开发经验和兴趣的同学更多交流。

8ae47f995c8446b6498a8ca63286f0ab.png

往期推荐

闲来无事,摸鱼时让 chatgpt 帮忙,写了一个 console 样式增强库并发布 npm

0021e0e8033fdd91b2ad5cc3f6d5cc9e.png

目前工资最高的几家外包公司汇总!(2023最新版)

5240aa0054ce5799fe5ce8725b2bfaeb.png

放心,前端死不了

5214eb50453a4fa42016305175752496.png


最后

  • 欢迎加我微信,拉你进技术群,长期交流学习...

  • 欢迎关注「前端Q」,认真学前端,做个专业的技术人...

b0bc9b657b8ab1dd7fbef7c5426b43a9.jpeg

bc02adbbd09a9bb7f17b1825b6a4c701.png

点个在看支持我吧

32eacb2d7def685350efbb6c6d4fc2f9.gif

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

建立数字化、学习型人事平台,HR 与业务终于不再「隔空对话」

本篇文章暨 CSDN《中国 101 计划》系列数字化转型场景之一。 《中国 101 计划——探索企业数字化发展新生态》为 CSDN 联合《新程序员》、GitCode.net 开源代码仓共同策划推出的系列活动,寻访一百零一个数字化转型场景,聚合呈现并开通评选通道&#xff…

程序员因薪资低拒绝offer,HR恼羞成怒,网友瞬间炸翻了..

一名程序员员在求职过程中,碰到一位薪资谈不拢就恼羞成怒的HR,并说出“估计你一辈子就是个程序员”这样的话。 从这位测试员和HR的聊天内容中,我们可以看到二者的谈薪过程。 首先,HR开出15k的薪资,测试员表示太低了&a…

模拟书本世界-Ai外语训练平台-文字冒险游戏-程序介绍

首先给出这个平台的进入链接:模拟书本世界 www.chatlangue.com 然后我会简要介绍一下这个平台。最后我会分享一下这个程序是如何实现的。 简要介绍:这个平台既是一款游戏又是一款外语学习软件。你通过这个平台可以进入一本书的模拟世界,这个世…

chatgpt赋能python:Python如何将英文转化为中文的最佳方法

Python如何将英文转化为中文的最佳方法 介绍 在现代全球化社会中,国与国之间的交流越来越频繁,相应的语言翻译工具的需求也愈发迫切。Python是一种易于学习、快速上手的编程语言,适合初学者和经验丰富的程序员使用,在语言翻译方…

chatgpt赋能python:Python做出来的图:探究数据可视化的魅力

Python做出来的图:探究数据可视化的魅力 在当今数字化时代,数据可视化是一种越来越重要的手段。随着数据分析和处理技术的飞速发展,现在可以轻松地使用Python编写代码来实现复杂而美丽的图形化呈现。 Python:强大的工具 Python…

chatgpt赋能python:Python图表:可视化数据的艺术

Python图表:可视化数据的艺术 作为一种易于学习和使用的编程语言,Python在数据科学和数据分析领域中的应用越来越普遍。Python的一个强大的功能是其图表功能,可以帮助我们将数据转化为可视化图表,从而更好地理解数据、提供洞察和…

chatgpt赋能python:Python面积图:简单易学、功能强大的数据可视化工具

Python 面积图:简单易学、功能强大的数据可视化工具 Python 是一种目前非常流行的编程语言,拥有强大的数据处理和可视化功能。其中,Python 的面积图是一种非常实用的数据可视化工具,能够直观地展现数据的变化趋势和占比关系。 什…

如何自己制作简历模板?简历在线制作的方法介绍

找工作时好看并有意义的简历是十分重要的事儿,如何制作一份出色的简历,在漫天的简历中脱颖而出呢?如何自己制作简历模板?今天七分简历--简历在线制作就来给大家介绍方法吧。 1.选用正确的简历模板 所谓正确的简历模板,…

用HTML做一份个人简历

学习了基本的HTML知识后&#xff0c;今天尝试用Html做一份个人简历。需要用到的基础知识是&#xff1a; Html表格&#xff1a;以<table></table>标签作为开始&#xff0c;<tr></tr>作为行&#xff0c;<td></td>作为列。 <th></…

手把手教你打造自己的简历编辑网站-编辑完后可以一键导出为PDF

如何打造自己的简历编辑网站 目录 如何打造自己的简历编辑网站一.相关环境配置A.服务器环境B.服务器面板 二.相关软件安装A.安装Node.jsB.安装yarn 三.部署简历网站A.开始安装 先看下效果&#xff0c;然后下面开始教大家搭建操作了 一.相关环境配置 A.服务器环境 系统&#x…

简历上的照片怎么制作?这两种方法真的很简单

怎么制作简历上的照片呢&#xff1f;简历是每个人在找工作的时候必须要用到的&#xff0c;在简历中&#xff0c;除了填写我们出众的履历和工作技能之外&#xff0c;还有一个很重要的影响因素&#xff0c;那就是我们放在简历中的证件照&#xff0c;一个好的照片可以让面试官一眼…

手机怎么做个人简历?多行业简历模板自由选择

如何利用手机来制作简历呢&#xff1f;现在找工作的时候&#xff0c;大多会使用手机来查看各种招聘app软件的信息来选择自己喜欢的工作。那么为了能够更好的获取面试的机会&#xff0c;那么准备一份优质的个人简历是必不可少的&#xff0c;那么从手机上如何下载一个精美简历模板…

html制作个人简历

前几天我为大家介绍了些html的标签&#xff0c;利用这些标签咱们可以简单制作个简历&#xff0c;来巩固知识。 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>个人简历</title> </head>…

简历生成工具(类似wps简历助手)

目前支持简历的编辑&#xff0c;导出&#xff0c;模块化&#xff0c;顺序调整&#xff0c;导出样式选择&#xff0c;完成进度等功能&#xff0c;已经完全可以满足简历编辑的基本需求 github地址&#xff1a;GitHub - bllon/jianli-tools: 简历助手前端项目 &#xff08;求给st…

BEVFusion(mit)最强环境安装,部署复现

0.前言 最近在做BEV视图下融合感知的项目&#xff0c;需要对相关工作进行学习。BEVFusion作为一项经典的工作&#xff0c;值得深入探索&#xff0c;论文地址&#xff0c;代码地址。然而由于配置环境比较麻烦&#xff0c;耽误了一些时间。经过几次成功配置之后&#xff0c;有了一…

去了一家不到 20 人的 IT 公司后,真的是大开眼界。。。

转自&#xff1a;知乎 来源&#xff1a; zhihu.com/question/421150601/answer/1475676199 前几天在知乎看到一个挺有意思的话题&#xff1a;不到 20 人的 IT 公司该去吗&#xff1f; 回答区有一位老哥分享了自己在一个20 来人的小公司的奇葩工作经历&#xff0c;分享一下。 下…

去了一家不到 20 人的 IT 公司后,真的是大开眼界。。。。

图片来源&#xff1a;AIGC 文章来源&#xff1a;知乎 前几天在知乎看到一个挺有意思的话题&#xff1a;不到 20 人的 IT 公司该去吗&#xff1f; 回答区有一位老哥分享了自己在一个20 来人的小公司的奇葩工作经历&#xff0c;分享一下。 原回答地址&#xff1a; zhihu.com/ques…

Android面试你简历准备好了吗?以及3-5年的Android工程师的瓶颈怎么突破

前言 以前都说&#xff1a; 不论是什么样的大小面试&#xff0c;要想不被面试官虐的不要不要的&#xff0c;只有刷爆面试题题做好全面的准备&#xff0c;当然除了这个还需要在平时把自己的基础打扎实&#xff0c;这样不论面试官怎么样一个知识点里往死里凿&#xff0c;你也能应…

一键通(手机实现对讲机功能)

所谓“一键通”&#xff08;英文缩写PTT&#xff0c;即Push-To-Talk&#xff09;&#xff0c;实际上就是集成了对讲机功能的手机&#xff0c;用户按下手机上的对讲键&#xff0c;就可以与任何地方的群组或个人直接进行通话。 一键通就是“即按即说”(PTT)的手机&#xff0c;融合…

Android SIP软电话,通话录音,VoIP电话,linphone电话

各位大佬好&#xff0c;我又来记笔记了~~ 公司又提新需求了&#xff0c;需要开发一个能通话&#xff08;呼叫客户的手机号码&#xff09;自动录音的模块。刚接触这个是蒙的&#xff0c;经过一番研究&#xff0c;可实现通话录音的方式大致有下面几种&#xff1a; 方案一&#xf…