WebGL和WebGPU区别详解

AI 知识库2个月前发布
992 0 0
熊猫办公
这篇文章详细解释了目前很火的WebGPU跟旧的WebGL的区别。是时候启用WebGPU了。

WebGL和WebGPU区别详解


自 2011 年以来,WebGL 一直是基于 Web 的 3D 图形技术的基础。如今,WebGPU 作为其继任者正在兴起,它带来了重大的架构变革,影响着我们在 Web 上构建 3D 体验的方式。本指南将解释 WebGL 和 WebGPU 之间的关键区别,探讨 WebGPU 在哪些方面带来了有意义的改进,介绍 Three.js 着色器语言 (TSL),并就何时采用该技术提供实用指导。什么是 WebGL?WebGL (Web Graphics Library) 是一个图形 API,十多年来一直为 Web 上的 3D 渲染提供动力。它基于 OpenGL ES 2.0 构建,将 JavaScript 代码转换为 GPU 指令。当你在 Three.js 中调用renderer.render(scene, camera)时,WebGL 会处理着色器编译、几何体上传、GPU 状态管理和像素渲染。它稳定、得到普遍支持,并在数百万个网站中经过了实战检验。问题在于,它的架构反映了 2011 年代的 GPU 设计,现代硬件的能力与 WebGL 所能提供的功能之间的差距逐年扩大。什么是 WebGPU?WebGPU 是一个从头开始为现代 GPU 设计的下一代图形 API。它没有基于老化的 OpenGL 标准构建,而是借鉴了 Vulkan、Metal 和 Direct3D 12 等当代 API 的思想。其改进主要集中在四个方面:通过更高效地与 GPU 通信来降低 CPU 开销,支持计算着色器以进行通用 GPU 计算,通过显式资源控制实现细粒度的内存和管线管理,以及一个能够随着硬件发展暴露新 GPU 功能的可扩展架构。WebGPU 不仅仅是 “WebGL 3.0″,它代表了一次根本性的架构升级,改变了浏览器与图形硬件的对话方式。WebGL 的架构局限性WebGL 的制约源于其对 GPU 架构的设计假设,而这些假设如今已经发生了显著演变。理解这些局限性有助于阐明 WebGPU 为何存在以及它解决了什么问题。单线程执行模型WebGL 在单线程上运行。每一次绘制调用、状态变更和资源上传都按顺序执行,这会产生 CPU 开销,从而阻止 GPU 发挥其全部性能。这种瓶颈以一种令人沮丧的方式表现出来:你的场景几何体数量适中,纹理也经过了优化,GPU 使用率停在 40%——但帧率仍然受限,因为 CPU 无法足够快地输送指令。现代 GPU 可以毫不费力地每帧处理数百万个三角形,但 WebGL 的单线程命令提交意味着 GPU 常常在空闲地等待下一条指令。不支持计算着色器WebGL 将 GPU 的使用限制在图形渲染上。物理模拟、粒子系统和计算任务必须在 CPU 上运行——而 CPU 这个硬件已经因渲染开销而成为瓶颈。这一点尤其具有限制性,因为现代 GPU 非常擅长并行计算。你的显卡拥有数千个处理核心,非常适合运行物理计算或程序化生成,但 WebGL 没有提供任何访问这种能力的方法。你被迫在可能只有 8-16 个核心的 CPU 上运行这些工作负载,从而造成巨大的性能差距。着色器语言演进受限自 WebGL 推出以来,GLSL (OpenGL Shading Language) 基本上没有变化。该语言缺乏现代开发者工具,在不同设备上会产生不一致的编译结果,并且提供的调试能力有限。着色器调试问题当一个 GLSL 着色器失败时,你通常只会得到一条晦涩的错误信息,没有堆栈跟踪,没有代码行高亮,而且常常表现出设备特定的行为。一个在你开发机器上编译通过的着色器,可能会在用户的硬件上失败,并显示完全不同的错误信息。这使得着色器开发过程缓慢得令人沮丧且容易出错。固化的特性集WebGL 无法访问现代 GPU 的功能,如高级纹理压缩格式、光线追踪加速结构或当代的渲染技术。它的特性集被锁定在 2011 年的规范上。即使 GPU 增加了新功能——更好的纹理格式、改进的混合模式、硬件加速特性——WebGL 仍然停滞不前。这不是一个在 WebGL 架构内部可以修复的问题;这是基于 OpenGL ES 2.0 构建所带来的根本限制。WebGPU 的技术优势WebGPU 的改进解决了 WebGL 的每一个核心局限性,同时为未来的 GPU 功能提供了基础。多线程命令生成WebGPU 支持在多个线程上同时准备渲染命令。这大大减少了 CPU 开销,并让 GPU 持续有工作可做,而不是在指令之间空闲等待。在具有数百个绘制调用的复杂场景中,性能影响最为明显。在这些场景中,WebGL 会在单个线程上顺序处理每个命令,而 WebGPU 可以将命令准备工作分配到所有可用的 CPU 核心上。结果是更高的帧率和更稳定的性能,尤其是在多核处理器上。计算着色器能力计算着色器使得在 GPU 上运行任意计算成为可能,将你的显卡变成一个通用的并行处理器。这使得以前不切实际的技术得以大规模应用。考虑一个拥有 100,000 个粒子的粒子系统。在 WebGL 中,你需要在 CPU 上更新粒子位置,然后每帧将更新后的数据上传到 GPU——这是一个缓慢且低效的过程。使用 WebGPU 计算着色器,整个模拟都在 GPU 上运行。粒子位置永远不会离开 GPU 内存,更新成本仅为原来的一小部分。同样的原理也适用于流体模拟、程序化生成、布料物理和 GPU 加速的 AI 推理。计算着色器实践一个真实世界的例子:一个包含 10,000 个粒子的 WebGL 粒子系统,在 CPU 上每帧更新可能需要 30 毫秒。同样一个系统使用 WebGPU 计算着色器,可以在不到 2 毫秒的时间内更新 100,000 个粒子——在性能和规模上都实现了 150 倍的提升。GPU 在数学运算上并非更快;它只是在正确的硬件上做了正确的工作。显式资源管理WebGPU 提供了对 GPU 内存分配、资源绑定和管线状态的精细控制。这比 WebGL 的自动资源管理需要更多的前期工作,但为那些了解其性能瓶颈的开发者提供了巨大的优化机会。你可以精确控制资源何时分配、内存如何布局,以及数据在 CPU 和 GPU 之间何时传输。对于性能关键的应用来说,这种控制水平是达到 60 FPS 和达到 120 FPS 之间的区别。提升移动设备效率WebGPU 的架构效率直接转化为更低的功耗。同样一个渲染工作负载,在 WebGL 上可能会在 2 小时内耗尽手机电池,但在 WebGPU 上可能可以运行 3 小时,原因仅仅是更少的 CPU 开销意味着更少的能源浪费。这不仅仅关乎电池续航。移动设备在过热时会进行热降频,削减性能以防止损坏。WebGPU 的高效率意味着更少的热量产生,从而带来更持久的稳定性能。一个在 WebGL 上开始时 60 FPS,五分钟后降至 30 FPS 的手机游戏,在 WebGPU 上可能能够始终保持 60 FPS。可扩展设计WebGPU 的架构能够适应未来 GPU 随着硬件演进带来的新功能。当新的纹理格式、混合模式或渲染技术出现时,WebGPU 可以通过扩展来暴露它们,而无需完全重新设计 API。这意味着 WebGPU 将随着 GPU 技术的发展而保持其 relevance,而不是在几年内就过时。TSL: Three.js 着色器语言Three.js r166 版本引入了 TSL (Three.js Shading Language),这是一个为 WebGPU 设计并兼容 WebGL 的基于节点的材质系统。TSL 代表了为 Three.js 编写着色器方式的根本性转变。TSL 让你通过组合 JavaScript 节点来构建材质,而不是将着色器编写为 GLSL 字符串。为了展示区别,这里有一个使用传统 GLSL 方法和新的 TSL 方法编写的边缘光(rim-lighting)着色器的例子。// 传统 GLSL 方法
constmaterial =newTHREE.ShaderMaterial({
vertexShader:`
varying vec3 vNormal;
varying vec3 vViewPosition;

void main() {
vNormal = normalize(normalMatrix * normal);
vec4 mvPosition = modelViewMatrix * vec4(position, 1.0);
vViewPosition = -mvPosition.xyz;
gl_Position = projectionMatrix * mvPosition;
}
`,
fragmentShader:`
varying vec3 vNormal;
varying vec3 vViewPosition;
uniform vec3 rimColor;
uniform float rimPower;

void main() {
vec3 viewDir = normalize(vViewPosition);
float rimFactor = 1.0 - max(0.0, dot(viewDir, vNormal));
rimFactor = pow(rimFactor, rimPower);

vec3 finalColor = rimColor * rimFactor;
gl_FragColor = vec4(finalColor, 1.0);
}
`,
uniforms: {
rimColor: {value:newTHREE.Color(0x00ffff) },
rimPower: {value:3.0}
}
});

// TSL 方法
import{MeshBasicNodeMaterial, normalView, positionView,
vec3, pow, max, dot, normalize, uniform }from'three/nodes';

constmaterial =newMeshBasicNodeMaterial();

constrimColor =uniform(vec3(0,1,1));
constrimPower =uniform(3.0);

constviewDir =normalize(positionView.negate());
constrimFactor =pow(max(0,dot(viewDir, normalView)).oneMinus(), rimPower);

material.colorNode= rimColor.mul(rimFactor);

其好处不仅仅是更简洁的语法。TSL 提供了类型安全,在开发时而不是运行时捕获错误。你可以获得完整的 IDE 支持,包括自动补全、重构和内联文档。着色器组件变得模块化和可复用,而不是复制粘贴的字符串片段。最重要的是,TSL 代码在 WebGL 和 WebGPU 渲染器上表现完全一致,让你只需编写一次着色器,就能在两个后端上运行。TSL 的调试体验比传统 GLSL 好得多。当出现问题时,你会得到指向失败代码确切位置的 JavaScript 堆栈跟踪,而不是因 GPU 供应商而异的晦涩的着色器编译错误。为什么 TSL 现在很重要即使你还没有使用 WebGPU,学习 TSL 也能让你为 Three.js 的未来方向做好准备。Three.js 团队正积极将 TSL 作为未来的主要着色器编写方法。现在开始用 TSL 进行新的着色器工作,意味着你的代码将随着生态系统的发展而保持最新。WebGPU 的采用考量WebGPU 的技术优势是明确的,但采用时机取决于你具体的项目需求和限制。何时现在使用 WebGPU 是合理的性能关键型应用,特别是那些有大量绘制调用的应用,能立即从 WebGPU 降低的开销中受益。如果你正在构建包含成百上千个对象的场景,并且尽管进行了 GPU 优化,仍然遇到 CPU 瓶颈,那么 WebGPU 的多线程命令生成将带来可观的帧率提升。计算密集型工作负载将看到最显著的收益。涉及大规模粒子系统(10万+粒子)、实时物理模拟、程序化生成或 GPU 加速处理的应用,通过计算着色器支持可以获得数量级的性能提升。如果你的应用每帧都在 CPU 上运行昂贵的计算,将这些计算转移到 GPU 计算着色器上,可以从根本上改变可能性。开发周期在 6-12 个月后部署的项目应认真评估将 WebGPU 作为主要目标。浏览器支持在不断改善,到你的项目发布时,WebGPU 的兼容性将比现在广泛得多。何时继续使用 WebGL 是合适的需要普遍浏览器支持的生产应用应继续使用 WebGL,直到 WebGPU 的支持成熟。如果你的应用需要在所有浏览器上都能工作,且没有回退方案或降级体验,WebGL 仍然是安全的选择。现有代码库很少有理由进行迁移,除非特定的性能瓶颈正好与 WebGPU 的优势相吻合。如果你的应用在 WebGL 上运行良好,迁移所需的工程投入通常超过了收益。只有当你遇到了 WebGPU 明确能解决的具体性能壁垒时,迁移才有意义——而不是作为一项常规的现代化工作。性能要求不高的项目从 WebGPU 增加的复杂性中获益甚少。如果你的场景在 WebGL 上能以 60 FPS 稳定渲染且仍有余量,切换到 WebGPU 只会增加复杂性,而没有实质性的好处。浏览器支持状态截至 2024 年底,WebGPU 已在 Chrome 和 Edge 中作为稳定功能提供,在 Safari 和 Firefox 中则需要通过实验性标志启用。最新的采用统计数据可在caniuse.com/webgpu上查看。发展趋势是明确的:WebGPU 的支持正在扩大,但尚未普及。今天发布项目需要考虑其目标受众是否支持 WebGPU,或者是否需要一个 WebGL 的回退方案。Three.js 迁移路径Three.js 提供了渲染器无关的场景图,这意味着在 WebGL 和 WebGPU 之间切换通常很简单:// WebGL
constrenderer =newTHREE.WebGLRenderer();

// WebGPU
constrenderer =newTHREE.WebGPURenderer();

对于使用标准材质的基本场景,这种切换可能立即生效。复杂性在于当你想要利用 WebGPU 特有功能(如计算着色器或高级 TSL 功能)时。这些需要额外的代码和架构变更,但基本的兼容性意味着你可以从简单的渲染器切换开始,然后逐步进行功能增强。总结与建议WebGPU 代表了对 WebGL 的一次重大架构进步,提供了更低的开销、计算着色器支持以及对现代 GPU 功能的访问。然而,由于浏览器支持的成熟度,WebGL 对于大多数生产应用来说仍然是务实的选择。从 WebGL 到 WebGPU 的过渡是一个长达数年的演进,而非一蹴而就的替代。开发者有足够的时间来学习 WebGPU 的功能,试验计算着色器和 TSL,并根据项目需求和浏览器支持的时间线来规划迁移策略。关键在于理解 WebGPU 在你的特定用例中能提供真正的优势,而不是仅仅因为新技术存在就进行迁移。

https://threejsroadmap.com/blog/webgl-vs-webgpu-explained

© 版权声明

相关文章