网页应用WebGL最佳实践
WebGL是一个图形库,利用GPU来提高性能,可以直接在浏览器中呈现高质量的视觉效果和复杂的动画。这个库为浏览器带来了OpenGL ES(一种低级别3D图形API)。它不需要任何额外的安装、扩展、插件或附加程序。此外,WebGL遵循行业标准,因此大多数浏览器中的各种库、常用着色器和图形引擎(如游戏引擎)都支持它。
WebGL如何在Vega网页应用上运行
Vega网页应用在v132上运行,支持WebGL 2.0。Vega使用Chromium的WebGL层,无需自定义。它的工作原理很像Android的WebView或Linux的Chromium。
在设备上加载源URI为https://webglreport.com/?v=2的WebView应用时,可以查看其他详细信息。
Platform: Linux x86_64
Browser User Agent: Mozilla/5.0 (Linux; OS 1.1; AFTCA002 userdebug/1343; wv) AppleWebKit/537.36 (KHTML, like Gecko) Mobile Chrome/118.0.5993.159 Safari/537.36
Context Name: webgl2
GL Version: WebGL 2.0 (OpenGL ES 3.0 Chromium)
Shading Language Version: WebGL GLSL ES 3.00 (OpenGLES GLSL ES 3.0 Chromium)
Vendor: WebKit
Renderer: WebKit WebGL
Unmasked Vendor: Mesa
Unmasked Renderer: Mali-G310 (Panfrost)
Antialiasing: Available
ANGLE: No
Major Performance Caveat: No
支持的扩展
以下是WebGL支持的扩展的列表:
- EXT_color_buffer_float
- EXT_color_buffer_half_float
- EXT_disjoint_timer_query_webgl2
- EXT_float_blend
- EXT_texture_filter_anisotropic
- EXT_texture_norm16
- OES_texture_float_linear
- WEBGL_compressed_texture_astc
- WEBGL_compressed_texture_etc
- WEBGL_compressed_texture_etc1
- WEBGL_debug_renderer_info
- WEBGL_debug_shaders
- WEBGL_lose_context
- WEBGL_multi_draw
Vega的WebGL策略
这些策略适用于使用WebGL库来提高性能的游戏、电视应用和生产力应用。浏览器管理DOM/HTML的渲染和内存管理技术,而WebGL则需要直接实现。请遵循以下一般指导准则:
- 简化复杂计算,高效管理内存,并尽可能直接地在JS和C/C++之间进行转换。
- 减少或限制纹理、资源和对象的大小。
- 重复使用现有的浏览器设置、GPU选项,或是针对硬件进行了优化的浏览器工具或库。或者仅重复使用可对应用进行微调的浏览器设置。
避免使用画布视频
避免像适用于视频的PixiJS API那样将视频混合到WebGL中。改为使用HTML视频元素或其他基于网页的视频播放器库。Vega使用专用GPU缓冲区直接播放视频,这样可以防止将视频帧提取为WebGL纹理。
减少绘制调用
使用纹理图集、顶点缓冲区对象 (VBO) 和索引缓冲区对象 (IBO) 以及实例化等技术,将多个对象合并成单个绘制调用(批处理)。实例化意味着渲染同一对象的多个实例。在OpenGL ES中,每帧使用少于500次绘制调用。
确保从requestAnimationFrame而不是setTimeout和useEffect中绘制。使用useEffect或useMemo时,更新requestAnimationFrame用来修改所绘制对象的值。如果可能,缓存绘制的对象或用于绘制的方程式,以缩短所需时间。
优化纹理
将纹理调整到所需的最低分辨率。使用压缩纹理格式(如DXT或ETC)并使用mipmap。使用纹理图集还可以减少绘制调用和内存使用量。
简化复杂算法
- 尽可能使用较低精度的数据类型,例如
half或float,而不是highp float。 - 将着色器的复杂性和所需的计算数量降至最低。
- 使用查找纹理替换pow和sin等资源密集型函数。
- 过多的灯光和阴影会影响性能。考虑使用烘焙光照(预渲染)或简化实时光照。
实现剔除和LOD
尽可能使用LOD、Frustum或Occlusion Culling等算法。降低细节水平,避免绘制不可见的对象,以提高流畅度。当您看到更多对象,相对LOD可通过降低多边形质量来处理高计算量负载。
高效的内存管理
- 处置不需要的WebGL对象,例如纹理、缓冲区和程序。
- 谨慎管理内存使用情况,避免不必要的分配和解除分配。
- 尽可能使用结构(TypeScript接口)代替类。
- 避免在常用方法中重新实例化类、字符串连接或高计算量方程。
- 预分配内存,使用数组代替列表,并优先使用指针和引用等共享资源。
- 实现对象池化以减少内存碎片。
文件管理
- 尽可能重复使用sprite和其他图像资源,以减少文件加载时间。
- 充分利用库中现有的资产捆绑系统,或是可进行压缩或捆绑的游戏系统。
- 使用异步或并行方法加载文件。
- 使用压缩音频格式(例如MP3或OGG),如果重复播放同一音频,请避免加载过多的音频文件。
- 连接音频文件以获得音效 (SFX),以优化加载和内存使用。
- 考虑使用基于时长的方法播放音频,而不是依赖单独的音频文件来实现每种音效。
// 使用一个mp3或ogg文件(而不是多个文件)来播放不同的时长。 // 这样可以优化加载时间和内存使用, // 尤其是在经常重放同一音频时。 // // 对音效或背景音频很有用。 this.playAudio(2.9088, 0.1437);
硬件加速
默认情况下,硬件加速处于启用状态。CSS用于在浏览器上触发硬件加速,很少能提升性能。
// 强制硬件加速,这种情况不太可能发生
document.body.style.transform = 'translateZ(0)';
document.body.style.backfaceVisibility = 'hidden';
在加载时使用以下代码可能会带来很小的性能提升。如果powerPreference设置为“high-performance”(高性能),则该设置会要求浏览器优先考虑性能而不是能效。抗锯齿等其他设置会减少GPU的渲染处理,在某些应用上可能不那么明显。如果要让代码以相同方式运行,可以选择即使在速度较慢的设备上也使用failIfMajorPerformanceCaveat: false。尽管会导致运行速度变慢,但是该选项可能会很有用。
// 优化WebGL上下文
const canvases = document.querySelectorAll('canvas');
canvases.forEach(canvas => {
const ctx = canvas.getContext('webgl', {
antialias: false,
powerPreference: 'high-performance',
failIfMajorPerformanceCaveat: false,
});
});
虽然默认情况下硬件加速处于启用状态,但可以微调应用的其他设置,以充分利用性能增益。微调对于在运行Vega网页应用的低资源设备上进行WebGL优化很有用。
尽量减少状态变化并避免阻塞调用
- 尽量减少状态更改的次数。一些可以最大限度减少这些变化的方法需要在不同的着色器程序、纹理单元或渲染目标之间切换。
- 避免在主线程上阻塞诸如
getError()和getParameter()之类的调用,因为它们会影响性能。 - 不使用
requestAnimationFrame时使用gl.flush(),以确保浏览器更快地运行WebGL命令。
相关主题
Last updated: 2026年2月5日

