Vega Web App Best Practices - WebGL
WebGL is a graphics library that leverages the GPU for accelerated performance, allowing for high-quality visuals and complex animations directly in the browser. This library brings OpenGL ES (a low-level 3D graphics API) to the browser. It doesn’t require any additional installation, extensions, plugins, or add-ons, and follows standards so that various libraries, common shaders, and graphics engines, such as gaming engines, support it across supported browsers.
How WebGL works on a Vega Web App
A Vega Web App is on v132 and supports WebGL 2.0. Vega uses Chromium’s WebGL layer without customization. It works very similar to Android’s WebView or Linux’s Chromium.
Additional details can be found by loading a WebView app on your device with the source uri https://webglreport.com/?v=2.
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
Supported extensions
Here is a list of extensions supported by 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
WebGL strategies for Vega
These apply to gaming, TV apps, and productivity applications that use WebGL libraries to improve performance. A browser manages rendering and memory management techniques for DOM/HTML whereas WebGL requires direct implementation. Follow these general guidelines:
- Simplify complex computations, efficiently manage memory, and make the conversion between JS and C/C++ as direct as possible.
- Reduce or limit the size of textures, assets, and objects.
- Reuse existing browser settings, GPU options and/or browser tools/libraries that have been optimized for the hardware or that are available for fine-tuning to your application.
Avoid canvas video
Avoid mixing up Video into WebGL like with the PixiJS api for Video. Instead, use the HTML video element or other web based video player libraries. Vega implements video playback directly into private GPU buffers which prevents taking frames out video as WebGL textures.
Reduce draw calls
Combine multiple objects into single draw calls (batching) using techniques like texture atlasing, instancing (rendering multiple instances of the same object), and using Vertex Buffer Objects (VBOs) and Index Buffer Objects (IBOs). Use fewer than 500 draw calls per frame in OpenGL ES.
Make sure to draw from requestAnimationFrame
instead of setTimeout
and useEffect
. When using useEffect
or useMemo
, update values that the requestAnimationFrame
uses to modify the objects drawn. When possible, cache drawn objects or equations used for drawing to reduce how long it takes.
Optimize textures
Resize textures to the minimum necessary resolution. Use compressed texture formats (like DXT or ETC) and employ mipmaps. Using texture atlases can also reduce draw calls and memory usage.
Simplify complex algorithms
- Use lower precision data types, such as
half
orfloat
, instead ofhighp float
where possible. - Minimize the complexity in shaders, and the number of calculations required.
- Use lookup textures as a replacement for resource-intensive functions like pow and sin.
- Too many lights and shadows can impact performance. Consider baked lighting (pre-rendered) or simplifying real-time lighting.
Implement Culling and LOD
Use algorithms like LOD, Frustum, or Occlusion Culling when possible. Reduce the level of detail, and avoid drawing objects invisible, to improve fluidity. Relative LOD can handle heavy loads by reducing the quality of polygons when more are in view.
Efficient Memory Management
- Properly dispose of WebGL objects, such as textures, buffers, and programs, when they are no longer needed.
- Carefully manage memory usage to avoid unnecessary allocations and deallocations.
- Use structs (TypeScript interfaces) instead of classes when possible.
- Avoid re-instantiating classes, string concatenation, or heavy equations in frequently used methods.
- Preallocate memory, use arrays instead of lists, and prefer shared resources like pointers and references.
- Implement object pooling to reduce memory fragmentation.
File management
- Reuse sprites and other image assets as much as possible to reduce file load times.
- Take advantage of existing asset bundle systems in various libraries or gaming systems that will compress, bundle, and help load assets when needed.
- Use asynchronous or parallel methods for loading files.
- Use compressed audio formats, such as MP3 or OGG, and avoid loading too many audio files if the same audio is played repeatedly.
- Concatenate audio files for sound effects (SFX) to optimize loading and memory usage.
- Consider playing audio with a duration-based approach instead of relying on separate audio files for each sound effect.
// Have one mp3 or ogg that plays at a time to a duration. Instead // of multiple audio files to optimize load time and memory use, // especially where the same audio is likely to be replayed often. // // Useful for sfx or background audio. this.playAudio(2.9088, 0.1437);
Hardware acceleration
Hardware acceleration is on by default. CSS that is used to trigger hardware acceleration on browsers is unlikely to provide any further performance boost.
// Force hardware acceleration - these are unlikely
document.body.style.transform = 'translateZ(0)';
document.body.style.backfaceVisibility = 'hidden';
There may be a small performance gain by using the following code on load. The setting powerPreference when set to “high-performance” tells the browser to prioritize performance over energy efficiency. Other settings such as antialiasing can also reduce the GPU processing for rendering and may not be as noticeable on certain apps. Telling the browser to create the WebGL context even if there are performance caveats is helpful when reusing a WebGL context across a variety of device types by using failIfMajorPerformanceCaveat: false
.
// Optimize WebGL contexts
const canvases = document.querySelectorAll('canvas');
canvases.forEach(canvas => {
const ctx = canvas.getContext('webgl', {
antialias: false,
powerPreference: 'high-performance',
failIfMajorPerformanceCaveat: false,
});
});
While hardware acceleration is enabled by default, additional settings can be fine-tuned for your app to take advantage of performance gains. This is useful for WebGL optimization on low-resource devices running a Vega Web App.
Minimize state changes and avoid blocking calls
- Minimize the number of state changes. Some ways to do this include switching between different shader programs, texture units, or render targets.
- Avoid blocking calls like
getError()
andgetParameter()
on the main thread, since they would impair performance. - Use
gl.flush()
when not usingrequestAnimationFrame
to ensure the browser executes WebGL commands more quickly.
Related topics
- Vega Web App Overview
- Vega Web App Performance Best Practices
- Vega Web App Development Best Practices for Vega TV
- Vega Web App Best Practices - Web Workers
Last updated: Sep 30, 2025