WebGL Best Practices for Web Apps
WebGL is a graphics library that leverages the GPU for accelerated performance, enabling 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. Pluse WebGL follows standards, so that various libraries, common shaders, and graphics engines, like gaming engines, support it across most 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 like Android's WebView or Linux's Chromium.
See additional details when you load 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 strategies apply to gaming, TV apps, and productivity apps 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 or browser tools or libraries optimized for the hardware. Or only reuse browser settings you can fine-tune to your app.
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 plays video directly using private GPU buffers, which prevents extracting video frames as WebGL textures.
Reduce draw calls
Combine several objects into single draw calls (batching), using techniques like texture atlasing, Vertex Buffer Objects (VBOs) and Index Buffer Objects (IBOs), and instancing. Instancing means to render multiple instances of the same object. 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
halforfloat, instead ofhighp floatwhere 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 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 handles heavy loads by reducing polygon quality when you see more.
Efficient Memory Management
- Dispose of unneeded WebGL objects, such as textures, buffers, and programs.
- Carefully manage memory usage to avoid unnecessary allocations and deallocations.
- Use structs (TypeScript interfaces) instead of classes when possible.
- Avoid reinstantiating 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 libraries, or gaming systems that compress or bundle.
- 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 plays 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.
// Use one mp3 or ogg file to play for various durations rather than multiple files. // This optimizes load time and memory use, // especially if the same audio is replayed often. // // Useful for sfx or background audio. this.playAudio(2.9088, 0.1437);
Hardware acceleration
Hardware acceleration is on by default. CSS used to trigger hardware acceleration on browsers seldom provides a performance boost.
// Force hardware acceleration, which is 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 anti-aliasing reduce the GPU processing for rendering, and may not be as noticeable on certain apps. The option to use failIfMajorPerformanceCaveat: false even on slower devices may be useful if you want your code to run the same, even if the results are slower.
// 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, fine-tune additional settings for your app to take advantage of performance gains. Fine-tuning 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 minimize these include switching between 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 usingrequestAnimationFrameto make sure the browser runs WebGL commands more quickly.
Related topics
- Overview of Vega Web Apps
- Performance Best Practices for Web Apps
- Development Best Practices for Web Apps
- Web Worker Best Practices for Web Apps
Last updated: Feb 05, 2026

