管理您的 Cookie 设置。您可以在下方启用或禁用不同种类的 Cookie。详情请查看我们的隐私政策

WebGL性能

WebGL 的名声不佳:许多开发者认为 WebGL 很慢,无法渲染复杂的 3D 图形。许多示例证明这种看法是不对的,但开发者的体验却常常强化了这一观点。

运行 WebGL 代码的硬件并没有因为在浏览器里运行而被减速。那么,为什么开发者会认为在网页上无法快速渲染 3D 图形呢?

本文将引导您了解WebGL性能的最佳实践以及如何在网页上实现快速的3D渲染。

CPU 与 GPU 

在3D应用程序中,部分代码在CPU上运行,而部分代码在加速硬件(GPU)上运行。

WebGL 的设计是为了使用 GPU 来加速网页上的图形应用。因此,WebGL 可理解为一系列将工作发送到图形硬件并获取结果的函数。

创建 GPU 任务的代码在 CPU 上运行,而我们通过 JavaScript 来控制 WebGL。

浏览器开销 

由于浏览器的目标是保护用户免受潜在恶意网站的侵害,它会通过 JavaScript 检查网站每次 WebGL 调用的安全性。它还需要隔离运行网站代码的进程,任何对该进程的调用必须转换成一个可发送的格式,称为“编组”。

编组以及检查网站的 WebGL 调用带来了性能开销,与在本地环境的相同调用相比,这增加了更多的性能成本。

避免 WebGL 调用 

为了实现良好的 WebGL 性能,我们应避免使用那些具有高开销的调用。您可以通过分析您的 WebGL 应用程序轻松找出哪些调用特别昂贵。

以下是一些反直觉地昂贵的调用:

要避免这些调用的一个优秀方法是进行 WebGL 状态跟踪,并在生产版本的 WebGL 应用中减少错误检查。

避免绘制调用 

实现优良 WebGL 性能的秘诀在于尽可能减少绘制调用。绘制调用指任何使用以下 WebGL 函数的操作:

您可以通过多种方法实现这一点。例如,使用一个函数调用绘制多个对象,而不是多次调用函数来绘制相同的对象。您可以使用实例化来渲染大量相同的网格,或使用WEBGL_multi_draw 来使用相同的着色器渲染许多不同对象。

3D 引擎通常具备称为“批处理”的功能,可以将多个调用合并为一个 WebGL 调用。Wonderland Engine 将其推向了极致,场景中数万个动态对象可自动被渲染成不到十个绘制调用。

在移动设备上,WebGL 性能尤其容易受到绘制调用数量的影响。

避免绘制调用(移动设备) 

我们重复强调这一点:在移动设备上,即使没有浏览器的额外开销,绘制调用也是至关重要的。即使是使用 Unity 或直接与 GLES 进行原生构建,也需要保持较低的绘制调用次数。

如果您的目标是在移动设备上实现优良的 WebGL 性能,那么您需要对绘制调用格外关注。

Safari上的WebGL 

在 Safari(iOS 和 MacOS)上,某些 WebGL 调用具有意想不到的高开销,例如:

在为 Safari 执行优化时,请特别注意 Uniform Buffers 的使用。

JavaScript 

用于与浏览器 API(如 WebGL)交互的语言是 JavaScript。JavaScript 的主要性能问题来源于垃圾回收机制,它会自动找到并移除不再使用的内存。

垃圾回收过程可能会导致 WebGL 应用程序的性能变得不可预测和不可靠,因为您无法控制它何时发生。因此,它可能会在使渲染发生卡顿的时间扰乱性能表现,即使代码在其他方面已经被优化。

为了获得稳定的帧率,应严格采用无垃圾的 JavaScript 编写风格。

iOS Safari 和内存 

在 Safari 上能正常运行的 WebGL 应用较少。Safari 上的 WebGL 性能带来了一些额外的挑战。我们撰写了一整篇博客文章,介绍如何为 Safari 进行优化

内存限制 

在 iOS 上,您会遇到另一个挑战:浏览器标签页的内存非常有限,尤其是在较旧的 iPhone 硬件上。如果超出内存限制,标签页可能会重新加载或冻结。由于 iPhone 使用统一内存,CPU 和 GPU 共享 RAM,因此纹理和缓冲数据,以及 JavaScript 或 WebAssembly 内存都会计入内存限制。