# 【Decentraland 浏览器选项卡中的 100 个虚拟化身】提高虚拟化身的渲染性能至关重要

By [Decentraland 中文社区](https://paragraph.com/@decentraland-2) · 2022-04-02

---

![](https://storage.googleapis.com/papyrus_images/8324619a40cb1ac02189afdfa40b8d6a0b403fd9b40fde8803ce32638418ea84.jpg)

_2022-1-14文章_

介绍
--

_Metaverse Festival （元宇宙节）被设想为平台历史上的一个里程碑，用户体验必须达到标准：提高虚拟化身的渲染性能至关重要。_

元宇宙节计划开始时，只能在玩家周围同时生成 20 个虚拟化身，如果它们都同时呈现在屏幕上，性能会显着下降。这个硬顶是由于 Web 浏览器渲染限制和旧的通信协议，后来通过新的 [Archipelago 解决方案](https://decentraland.org/blog/project-updates/communication-protocol-improvements/) 进行了改进。这不会为用户提供逼真的社交节日体验，因此 Decentraland 的贡献者得出结论，他们必须增加可以在屏幕上呈现的用户数量才能使节日成功。

Explorer 的贡献者首先测试了一个理论：渲染（连同 CPU 蒙皮）是屏幕上有多个虚拟化身导致性能问题的主要原因。在对受控环境中的 100-200 个虚拟化身机器人进行性能分析后，该理论得到了证实。

![](https://storage.googleapis.com/papyrus_images/6723904b1241c211ed3b8a145078137bdbbf4d55af0dff44aecc3b30e0e34fc2.png)

面对这些发现，我们的目标是将虚拟化身的最大显示数量从 20 个增加到 100 个。为此，我们做出了三项努力。

1 引入了新的**冒名顶替系统**。该系统通过在需要时将它们替换为单个相似的广告牌来避免渲染和动画化远处的虚拟化身。 2 **定制的 GPU 蒙皮**实施已到位，有效地大幅减少了 CPU 绑定的蒙皮瓶颈。 3 **虚拟化身渲染管道从头开始重新实现**，在最佳情况下将绘制调用从大约 10+ 减少到单个绘制调用。由于渲染状态切换，可穿戴设备的复杂组合可能会使绘制调用计数更高一些，但在最坏的情况下不会超过三到四次调用。

根据基准测试，这些联合努力将虚拟化身渲染性能提高了约 **180%**。这是为像元宇宙节这样的大型活动准备平台的众多努力中的第一个，超过 20,000 人参加了该活动。

虚拟化身冒名顶替者
---------

在实现了一个用于生成虚拟化身机器人的工具和另一个用于在 Web 浏览器中分析性能的工具之后，贡献者已准备好获取该分析数据并创建虚拟化身冒名顶替系统。

虽然在节日之前制作了令人敬畏的场景，但为了测试目的而构建了一个场景。它包含环境所需的某些因素：**类似体育场的结构**、**一些不断更新的对象**，以及至少两个不同的**视频流源**。所有这些都是使用 Decentraland SDK 完成的。

一切就绪后，虚拟化身冒名顶替者的概念验证就开始了。

[![]({{DOMAIN}}/editor/youtube/play.png)](https://www.youtube.com/watch?v=35m3_dT4Elc)

在核心逻辑运行后，贡献者开始研究该功能的“视觉部分”。

首先，使用带有**默认冒名顶替者的精灵图集**为每个虚拟化身随机分配冒名顶替者。

![](https://storage.googleapis.com/papyrus_images/8a2a645a367545b242408d5347f00e1a615cecd8bb6a20ffa760e39d598a0db1.jpg)

[![]({{DOMAIN}}/editor/youtube/play.png)](https://www.youtube.com/watch?v=vIdjn6nh-3Y)

[![]({{DOMAIN}}/editor/youtube/play.png)](https://www.youtube.com/watch?v=oxYh3mxbjAk)

然后，使用运行时捕获的快照完成了几个实验，每个虚拟化身的角度朝向相机。然而，事实证明，在浏览器中运行时的纹理操作对性能的影响非常大，因此该选项被丢弃。

[![]({{DOMAIN}}/editor/youtube/play.png)](https://www.youtube.com/watch?v=jpO9yVwApfQ)

最后，内容服务器中已经存在的用户身体快照被用作冒名顶替者，而默认的精灵图集则应用于机器人或没有个人资料的用户。

最后但同样重要的是，实施和调整了一些关于位置和距离的最终效果。

[![]({{DOMAIN}}/editor/youtube/play.png)](https://www.youtube.com/watch?v=D8Xt7RPDNJ0)

[![]({{DOMAIN}}/editor/youtube/play.png)](https://www.youtube.com/watch?v=-HmCVXTNaoA)

在与真实用户进行测试时，WonderMine 等频繁出现的场景被证明是无价的。

[![]({{DOMAIN}}/editor/youtube/play.png)](https://www.youtube.com/watch?v=AXfBTPfhbQw)

[![]({{DOMAIN}}/editor/youtube/play.png)](https://www.youtube.com/watch?v=7uxB0JorjUw)

> Impostor 系统贡献是公开的，可在以下 PR（[1](https://github.com/decentraland/unity-renderer/pull/677)、[2](https://github.com/decentraland/unity-renderer/pull/810)、[3](https://github.com/decentraland/unity-renderer/pull/957)、[4](https://github.com/decentraland/unity-renderer/pull/988)）上获得。

GPU蒙皮
-----

针对 WebGL/WASM 目标的换肤的 Unity 实现强制换肤计算在主线程上进行，此外，它错过了其它平台上存在的所有 SIMD 改进。当渲染大量虚拟化身时，这种开销会堆积起来并成为性能问题，在尝试渲染多个虚拟化身时会占用高达 15% 的帧时间（或更多！）。

![](https://storage.googleapis.com/papyrus_images/4874a974fc2b633b12776e55294fe10f28f87d1a960972678a720d77659745a2.png)

在互联网上描述的大多数 GPU 蒙皮实现中，动画数据被打包到纹理中，然后馈入蒙皮着色器。这对纸上的性能有好处，但它有其自身的局限性。例如，动画之间的混合很复杂，除了必须编写自己的自定义动画师来处理动画板。

  

由于 WASM 目标中的蒙皮优化非常差，贡献者发现即使没有将动画数据打包到纹理中，也可以观察到 200% 的性能提升。这意味着一个简单的实现，只需将骨骼矩阵上传到每帧的蒙皮着色器就足够了。由于最远的动画受到限制并且不会在每一帧上上传它们的骨骼矩阵，因此这种优化得到了进一步的增强。总而言之，这种方法提高了虚拟化身的性能，避免了重写 Unity 动画系统，并保持了动画状态混合支持。

在 Metaverse Festival （元宇宙节）的这些视频中，可以在最远的虚拟化身上看到**受限制的 GPU 蒙皮**：

[![]({{DOMAIN}}/editor/youtube/play.png)](https://www.youtube.com/watch?v=uYFe7SYo4dc)

[![]({{DOMAIN}}/editor/youtube/play.png)](https://www.youtube.com/watch?v=XrbChPcv8oA)

[![]({{DOMAIN}}/editor/youtube/play.png)](https://www.youtube.com/watch?v=-baHdW9B5e0)

[![]({{DOMAIN}}/editor/youtube/play.png)](https://www.youtube.com/watch?v=aSZZvPUGXkQ)

> GPU 蒙皮贡献是公开的，可在以下 PR ([1](https://github.com/decentraland/unity-renderer/pull/1041), [2](https://github.com/decentraland/unity-renderer/pull/1130), [3](https://github.com/decentraland/unity-renderer/pull/1140), [4](https://github.com/decentraland/unity-renderer/pull/1161)) 上获得。

虚拟化身渲染大修
--------

虚拟化身曾经被渲染为一系列不同的蒙皮网格渲染器，它们共享它们的骨骼数据。此外，一些可穿戴设备需要单独的材料来解释肤色和发射。这意味着一些可穿戴设备需要两个或三个绘图调用。在这种情况下，必须绘制整个虚拟化身可能涉及 10 次以上的绘制调用。 WebGL 中的绘图调用成本非常高，很容易与移动 GPU 绘图调用成本相媲美——甚至可能更糟。当在屏幕上使用 20 多个虚拟化身进行基准测试时，帧速率开始明显下降。

![](https://storage.googleapis.com/papyrus_images/c3b71aeedff6c38a8cddfd45be7e9d25d6c6dd492240f2cf25f0f0c4a263db76.png)

新的虚拟化身渲染管道通过将所有可穿戴基元合并到一个网格中，在顶点流中编码采样器和统一数据，从而允许将每个可穿戴材料打包成一个单一的材料。

![](https://storage.googleapis.com/papyrus_images/9dceb4c84c0807c7377cdcf9703c3e680d4b4a4d1d4b602e4ecdcd4edb57e3c0.png)

您可能想知道可穿戴设备的纹理是如何包装的。由于可穿戴设备具有动态特性，它们没有图谱的好处，而且它们之间的纹理共享很差——几乎不存在。最明显的优化是：

• 将所有纹理打包到运行时生成的图集中。

• 使用 2D 纹理数组并将所有可穿戴纹理放入运行时。

这些方法的问题在于，由于 CPU-GPU 内存瓶颈，在运行时生成和复制纹理像素非常昂贵。纹理数组方法还有另一个限制：它的纹理元素不能只引用其他纹理，它们必须被复制，并且数组的所有纹理必须具有相同的大小。

此外，为每个虚拟化身创建一个新纹理是内存密集型的，并且由于 emscripten 的限制，当前的客户端堆被限制为 2 GB——它可以扩展到 4 GB，但只能从 Unity 2021 开始，因为他们已经更新了 emscripten 版本。由于贡献者的目标是同时支持至少一百个分身，这不是合适的选择。 

为了完全避免纹理复制问题，采用了一种更简单但更有效的方法。

在虚拟化身着色器中，纹理采样器池使用 12 个允许的采样器插槽用于虚拟化身纹理。渲染时，使用自定义 UV 数据对所需的采样器进行索引。这些数据的布局方式是通过使用不同的 UV 通道来识别反照率和发射纹理。这种方法允许非常有效的包装。例如，相同的材质可以使用 6 个反照率和 6 个自发光纹理，或者 11 个反照率和一个自发光，等等。 Avatar combiner 利用了这一点，并尝试以最有效的方式打包所有使用的可穿戴设备——权衡是必须在着色器代码中使用分支，但片段性能不是问题，因此投资回报非常乐观。

![](https://storage.googleapis.com/papyrus_images/2eec0da552511794c9648dd4bd0ccf1ddf5e1c0d7215f48012cd17d5ba3184e5.png)

![](https://storage.googleapis.com/papyrus_images/73e5d36f85bb89fda81bdc5e71a2c6ce387807228789b2b5c9e5028059f7a64a.png)

上图，改进前（120ms / 8FPS）。下图，之后（50ms / 20FPS）。

> 虚拟化身渲染贡献是公开的，可在以下 PR ([1](https://github.com/decentraland/unity-renderer/pull/785), [2](https://github.com/decentraland/unity-renderer/pull/1230)) 查看。

结论
--

在这些改进之后，当屏幕上有 100 个虚拟化身时，性能提升了 180%（从平均 10FPS 到平均 28FPS）。

其中一些改进，例如节流的 GPU 蒙皮，将来可能会应用于 Decentraland 中的其它动画网格。

这些巨大的努力让电影节的屏幕上出现 5 倍以上的虚拟化身（从 20 到 100 个）现在已经成为 Decentraland explorer 的一部分，它们将继续为世界社交体验增加价值。

**选择您常用的频道加入与我们联系，关注Decentraland(MANA)的最新动态**

**DCL基金会全球社区： 【**[**Official Website**](https://decentraland.org)】 【[**Telegram**](https://t.me/decentralandTG)】 【[**Blog**](https://blog.decentraland.org)】 【[**Twitter**](https://twitter.com/decentraland)】 【[**Discord**](https://decentraland.org/discord/)】

**DCL中文社区： 【**[**电报群**](https://t.me/+BtB90_SKDeQ4OGQ1)**】 【**[**推特**](https://twitter.com/decentralandcn)】 【[**微博**](https://weibo.com/decentralandcn)】 【**微信群**】请加微信ID ChinWaan 【**微信公众号**】manalandcn

---

*Originally published on [Decentraland 中文社区](https://paragraph.com/@decentraland-2/decentraland-100)*
