网页应用WebGL最佳实践
WebGL是一个图形库,利用GPU来提高性能,允许直接在浏览器中呈现高质量的视觉效果和复杂的动画。这个库为浏览器带来了OpenGL ES(一种低级别3D图形API)。它不需要任何额外的安装、扩展、插件或附加程序,并且遵循标准,因此各种库、常见着色器和图形引擎(例如游戏引擎)可以在支持的浏览器上支持它。
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会要求浏览器优先考虑性能而不是能效。抗锯齿等其他设置也会减少GPU的渲染处理,在某些应用上可能不那么明显。使用failIfMajorPerformanceCaveat: false在各种设备类型上重复使用WebGL上下文时,即使存在性能注意事项,浏览器创建WebGL上下文也会很有帮助。
// 优化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: 2025年10月7日

