

腾讯硬核干货!如何在页面极速渲染3D模型?
source link: https://www.uisdc.com/optimizing-3d-model
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

朋友们,还记得 QQ 20 周年 H5 中可可爱爱的太空鹅吗?
为了实现旋转和换肤功能,在 H5 中我们随机展示了5种类型的 3D 太空鹅模型,如下图所示:
但是在 H5 中引入 3D 模型往往存在资源太大、性能损耗严重、还原不真实的问题,这也让许多 3D 创意止步于开发阶段。
如何更好地在 H5 中还原模型呢?本文将从模型网格和贴图文件两方面分析,介绍几种通过技术角度优化加载速度和提高渲染性能的途径,在保证 3D 模型不减面,贴图不缩小的情况下,将模型精致地还原在 H5 或其他应用程序中。
模型网格压缩
首先是分析模型网格,对于大型 3D 资源,我们一般会通过在模型设计时进行「减面」来减少模型几何体的大小,但也会带来模型精致度的缺失。如下图所示:
而通过 glTF 配合 Draco 压缩的方式,可以在视觉效果近乎一致的情况下,让3D模型文件成倍缩小。下面具体介绍 glTF 格式及 Draco 压缩工具。
1. 将模型导出为 glTF 格式
glTF 介绍
glTF 称为「 3D 界的 JPEG」,使用了更优的数据结构,为应用程序实时渲染而生。glTF 有以下几大特点:
- 由现有 OpenGL 的维护组织 Khronos 推出,目的就是为了统一用于应用程序渲染的 3D 格式,更适用于基于 OpenGL 的引擎;
- 减少了 3D 格式中除了与渲染无关的冗余信息,最小化 3D 文件资源;
- 优化了应用程序读取效率和和减少渲染模型的运行时间;
- 支持 3D 模型几何体、材质、动画及场景、摄影机等信息。
glTF 导出格式有两种后缀格式可供选择:.gltf 和 .glb:
- .gltf 文件导出时一般会输出两种文件类型,一是 .bin 文件,以二进制流的方式存储顶点坐标、顶点法线坐标和贴图纹理坐标、贴图信息等模型基本数据信息;二是 .gltf 文件,本质是 json 文件,记录对bin文件中模型顶点基本数据的索引、材质索引等信息,方便编辑,可读性较好;
- .glb 文件格式只导出一个 .glb 文件,将所有数据都输出为二进制流,通常来说会更小一点,若不关心模型内的具体数据可直接选择此类型。
glTF 转换
目前有些建模工具还不具备导出 glTF 格式功能,可以输出 FBX / Collada 格式后通过以下工具进行转换:
FBX 转 glTF
- Facebook 推出的 FBX2glTF 命令行工具,可直接从 github 官网下载 release 版本;
- 通过 Paint 3D、Substance Painter 等可视化编辑工具进行转换。
Collada 转 glTF
COLLADA2GLTF 命令行工具,可转换 .dae 格式的文件,从 GitHub 官网直接下载 release 版本,解压后在命令行进入目录即可调用。
glTF 查看
转换后可通过以下查看工具查看 glTF 资源:
- Windows 10 及以上自带的 3D Paints;
- glTF 在线查看器:https://gltf-viewer.donmccurdy.com;
- 对于开发者,可直接使用 VSCode 插件—— glTF Tools。
2. 通过 Draco 进行压缩
Draco 及 gltf-pipeline 介绍
Draco 是 Google 推出的一个用于 3D 模型压缩和解压缩的工具库,上述介绍的 FBX2glTF 及 COLLADA2GLTF 工具也嵌入了 Draco 压缩功能,除此之外,glTF 资源可通过基于 Draco 开发的命令行工具 gltf-pipeline 进行编码压缩,gltf-pipeline 可通过 npm 的方式安装使用。使用方法如下:
#全局安装 npm install -g gltf-pipeline #压缩glb文件 -b表示输出glb格式,-d表示压缩 gltf-pipeline -i model.glb -b -d #压缩glb文件并将纹理图片分离出来 gltf-pipeline -i model.glb -b -d -t #更多参数查阅 gltf-pipeline -h
Draco 压缩分析
通过 Draco 进行压缩基本上是有损的,有两点表现:
- Draco 通过 Edge breaker 3D 压缩算法改变了模型的网格数据的索引方法,缺少了原来的网格顺序;
- Draco 通过减少顶点坐标、顶点纹理坐标等信息的位数,以减少数据的存储量。
但在 gltf-pipeline 或其他压缩工具中,压缩程度可通过设置参数进行调整,如下所示:
当 –draco.compressionLevel 为0时,将保留原来的网格顺序,网格数据索引的压缩力度最小,–draco.quantizeXXXBits 可控制坐标等基本数据值的位数,位数越少压缩力度越大。由于一个三角形网格对应多个顶点坐标、顶点法线坐标、颜色坐标等数据,一般来说 –draco.quantizeXXXBits 对文件的大小影响会更大。
若不设置参数,gltf-pipeline 会直接以默认值压缩。
虽说 Draco 是有损的,但相对于直接为模型减面来说,采用 Draco 压缩方法视觉偏差会小很多。
压缩后的 glTF 模型需要通过在应用中嵌入 Draco 解码工具包,主要是对 edge breaker 算法部分进行解码,解码时间一般比编码时间少,但必须考量模型与工具包的大小对比。例如 ThreeJS 提供了 draco_decoder 模块进行解码,draco_decoder 约600KB,若模型资源文件比工具包还小,就没有必要再引入 Draco 压缩了。
3. 效果测试
我们以太空鹅模型为例,只加载模型几何体,不带入材质属性,通过ThreeJS 分别加载 FBX / glTF / 压缩后的glTF 的格式,第三种格式以默认参数压缩。测试效果对比如下:
从图中可以看出,文件从 FBX 转换为 glTF 后大小差异不大,但是渲染速度有了明显提升。
另外经过压缩的 glTF 文件仅为正常 FBX 和 glTF 文件的1/10左右,而在视觉上三者几何体结构没有明显的差异,压缩后的 glTF 开启了 worker 线程做 Draco 解码,多了一小部分模型解码时间。
模型贴图优化
上述描述的模型压缩只针对模型网格数据,不会对 glTF 文件里的贴图进行处理。然而很多时候贴图文件往往大于模型。此时则需要将模型和贴图分开进行处理(建模时分开输出一个打好 UVtag 纹理坐标的「白模」和需要用到的纹理贴图)。下面介绍如何优化用于应用程序渲染的贴图文件。
1. 贴图加载过程分析
以一个基于物理引擎渲染的电视机 Demo 模型为例,一般会输出几种尺寸较大的贴图文件:颜色贴图,法线贴图,金属粗糙贴图,如下图例子所示:
输出贴图一般为 png 格式,许多同学会通过压缩 png 或者将 png 转成 jpg 格式减少纹理大小,其实这种处理方式只优化了图片加载速度,加载完毕后,png/jpg 仍需要全部转码为纹理(texture)才能开始渲染,而具有相同尺寸的贴图纹理 GPU 占用内存大小相同,故压缩后的 png/jpg 对于渲染过程并没有优化。
庆幸的是许多设备都有可直接用于渲染的 GPU 压缩纹理(compress texture)格式,压缩纹理可比由 png 直接转换的纹理减少5倍或以上的大小。如果直接提供压缩纹理格式,则不需要进行 png 的转码过程且可大大减少纹理内存。如下图方案2所示:
但由于 GPU 芯片提供商太多,设备的压缩纹理格式多种多样(例如安卓设备常用格式是 ETC1/ETC2,苹果设备是 PVRTC…),手动输出多种格式代价大,导致方案2较难落地。
2. Basis Universal 压缩
转折点在于今年五月份,Binomial 公司推出了 Basis Universal 压缩 GPU 纹理技术,Basis Universal 支持多种常用的压缩纹理格式,将 png 转换为 basis 文件后,大小与 jpg 格式差不多,但在 GPU 上比 png/jpg 小6-8倍。
应用程序加载 basis 文件后,可通过 basis 转码器快速转换成适用于设备的压缩纹理格式。如下图(图片来自Google Blog)所示:
Basis 用法也比较简单,可通过 basisu 命令行工具压缩 png,直接从 github 官网下载Release版本或者通过 CMake 编译源码,以 Mac 系统为例(Windows 系统将命令改为 basis.exe),列举几种常用用法:
# 进入执行目录 cd bin-osx # 将.png格式转为 .basis ./basisu xxx.png # 针对法线/金属/粗糙贴图等linear颜色空间的贴图 需加上-linear ./basisu xxx.png -linear # 最大限度保证图片质量的转换 ./basisu xxx.png -comp_level 5 -max_endpoints 16128 -max_selectors 16128 -no_selector_rdo # 最大限度压缩linear颜色空间的贴图 ./basisu xxx.png -linear -global_sel_pal -no_hybrid_sel_cb
生成的 .basis 文件需要在程序中通过转码器转成设备的压缩纹理格式,例如在ThreeJS 中可通过 basisTextureLoader 转换,具体用法可查阅 ThreeJS 官网 。
3. 效果测试
为了数据更加明显,我们在Mac Chrome 浏览器performance模式下,针对同一个电视机模型利用 ThreeJS 各自加载了 4096 x 4096 大小的颜色贴图、法线贴图、金属与粗糙贴图,对比如下:
由上图使用 basis 贴图资源文件大小比 png 减少了11倍以上,同时主线程的脚本时间和绘制时间花销也小于 png/jpg 贴图。
需要注意的是,同样由于不同的压缩纹理格式不同,在 basis 文件一致的情况下,不同设备的渲染表现可能会出现不一致,需要进行多端测试,且目前部分格式不支持 alpha 通道,带半透明的颜色贴图若不生效可考虑单独拆出 alpha 贴图。
展望
除了基于 webGL 的 H5,glTF 与 Basis 亦可用于其它基于 OpenGL 渲染的应用程序。值得期待的是,目前 Google 与 Binomial 公司正在推进 Basis Universal 与 glTF 3D 传输标准的合作,或许在不久的将来就可以迎来结合了 basis 贴图的 glTF 格式,不需要做另外的处理可以直接导入模型到应用程序中。
除了压缩3D 模型,平时设计师还可以利用这个网站压缩图片:
参考资料
- https://spin.atomicobject.com/2018/09/30/compress-3d-files-draco/
- https://neil3d.github.io/3dengine/gltf-mesh.html
- https://github.com/google/draco
- https://www.ece.uvic.ca/~frodo/publications/yuetang_meng_project_slides.pdf
- https://developers.facebook.com/docs/sharing/3d-posts/glb-tutorials
- https://github.com/AnalyticalGraphicsInc/gltf-pipeline
- https://www.khronos.org/gltf/
- https://news.ycombinator.com/item?id=19986749
- https://github.com/BinomialLLC/basis_universal
- https://www.khronos.org/blog/google-and-binomial-contribute-basis-universal-texture-format-to-khronos-gltf-3d-transmission-open-standard
欢迎关注「腾讯ISUX」的公众号:
Recommend
-
86
我们只能自造「 软硬核 」这个词汇来描述这篇文章的特点:首先,这是一篇实打实的关于 Cosmos 硬核技术的全面解读;但是,它...
-
46
硬核教学:如何在路边拍出大片?
-
58
技术派是如何利用逻辑回归模型实现用户增长的 黄天文将用户增长分为三大流派,分别是 市场营销派 、 实验增长派 和 技术派 ,下面简单...
-
20
前言 程序员对待IDE都是虔诚的,经常因为谁是最好的IDE而在江湖上掀起波澜,曾经我也是。
-
39
前言 程序员对待IDE都是虔诚的,经常因为谁是最好的IDE而在江湖上掀起波澜,曾经我也是。 后来我遇到了IDEA,从此是它,余生都是它。 IDEA 毫无疑问是目前最强大的Java开发工具了,但是大部分的人并没有将它用到极致,很多实用的配置,插件,小技巧被忽视
-
25
在一些网络服务的系统中,Redis 的性能,可能是比 MySQL 等硬盘数据库的性能更重要的课题。比如微博,把热点微博 [1] ,最新的用户关系,都存...
-
18
转载请注明出处: 葡萄城官网 ,葡萄城为开发者提供专业的开发工具、解决方案和服务,赋能开发者。 表格作为数据呈现的一种基本方式,在各类软件系统都发挥着重要的作用。在移动...
-
35
前提 之前已经花了大量时间分析同步器框架 AQS 的源码实现,这篇文章分析一下 CountDownLatch 的源码实现,本文参看的 JDK 源码为 JDK11 ,其他版本不一定适合。 ...
-
15
之前已经花了大量时间分析同步器框架AQS的源码实现,这篇文章分析一下CountDownLatch的源码实现,本文参看的JDK源码为JDK11,其他版本不一定适合。 CountDownLatch其实是复合名词,由...
-
4
《巅峰极速》负责人周潜:赛车游戏如何在移动端实现更逼真的光照效果? 2022-04-21 •...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK