AVIF Texture Loading in WebGL and WebGPU
AVIF offers superior compression efficiency and high dynamic range
support, making it an attractive asset format for real-time 3D web
applications. Integrating AVIF into WebGL and WebGPU pipelines involves
decoding the AV1-compressed bitstream into an uncompressed pixel
representation using browser APIs like createImageBitmap or
the WebCodecs API before uploading that data into GPU memory. This
article explains the technical mechanics, modern upload pathways, color
space management, and performance trade-offs when using AVIF for
graphics programming on the web.
The Role of AVIF in Graphics Pipelines
AVIF is an image delivery format rather than a GPU texture format. Unlike block-compressed formats designed for hardware (such as ASTC, BCn, or Basis Universal), AVIF cannot remain compressed inside GPU VRAM.
Instead, AVIF acts as an ultra-lightweight transmission format over the network. Once fetched by the client, the browser decodes the AV1 bitstream into raw, uncompressed RGBA pixel buffers in system memory. These raw pixels are subsequently copied into GPU texture memory for rendering.
Decoding AVIF Asynchronously
To prevent frame drops on the main thread, AVIF images must be
decoded asynchronously. Modern web architectures avoid using traditional
HTMLImageElement instances in favor of fetch
combined with createImageBitmap.
// Fetch the AVIF file as a Blob
const response = await fetch('texture.avif');
const blob = await response.blob();
// Decode off-thread into an ImageBitmap
const imageBitmap = await createImageBitmap(blob, {
colorSpaceConversion: 'none',
premultiplyAlpha: 'none'
});Using createImageBitmap allows the browser’s underlying
AV1 decoder to process the image on a worker thread. Specifying decoding
options ensures the raw data is not prematurely converted or blended
before reaching the shader.
WebGL Texture Upload Pipeline
In WebGL 1 and WebGL 2, the pipeline receives the decoded
ImageBitmap and uploads it via the CPU-to-GPU bridge.
- Configure Pixel Storage: Define alignment and
unpacking flags to match your asset’s layout:
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false); gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true); - Allocate and Upload: Bind a texture target and call
texImage2DortexSubImage2D:gl.bindTexture(gl.TEXTURE_2D, texture); gl.texImage2D( gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, imageBitmap ); gl.generateMipmap(gl.TEXTURE_2D);
Because AVIF does not store precomputed mipmaps, mip generation must
occur dynamically on the GPU using gl.generateMipmap(),
adding a small runtime overhead during scene initialization.
WebGPU Texture Upload Pipeline
WebGPU modernizes texture handling by introducing
copyExternalImageToTexture(), which coordinates the
transfer of image sources directly to GPU textures via the
GPUQueue.
// Create target texture
const texture = device.createTexture({
size: [imageBitmap.width, imageBitmap.height, 1],
format: 'rgba8unorm',
usage: GPUTextureUsage.TEXTURE_BINDING |
GPUTextureUsage.COPY_DST |
GPUTextureUsage.RENDER_ATTACHMENT,
});
// Direct transfer from decoded image source to GPU texture
device.queue.copyExternalImageToTexture(
{ source: imageBitmap, flipY: false },
{ texture: texture },
[imageBitmap.width, imageBitmap.height]
);This method is optimized inside browser engines to bypass unnecessary intermediate memory copies, achieving near-zero-copy transfers depending on the underlying OS compositor and hardware decoder capabilities.
High Dynamic Range (HDR) and Wide Color Gamut
One of AVIF's greatest advantages over older formats like WebP or JPEG is native support for 10-bit and 12-bit color depths, as well as wide color gamuts (BT.2020) and transfer functions like PQ and HLG.
- In WebGL 2: HDR AVIF data must be unpacked into
float or half-float textures (
gl.RGBA16Forgl.RGBA32F) to retain dynamic range without clamping values to 8-bit limits. - In WebGPU: Textures can be initialized with formats
like
rgba16float, and color spaces can be preserved explicitly through thecolorSpaceconfiguration incopyExternalImageToTexture().
Performance Trade-Offs
When designing a production pipeline, consider the following trade-offs between AVIF and GPU-native formats:
- Bandwidth vs. VRAM: AVIF dramatically reduces initial download times and storage requirements compared to raw or standard compressed files. However, once decoded, an AVIF image consumes full uncompressed VRAM (e.g., 4 bytes per pixel for standard RGBA8).
- Decoding Latency: AV1 decoding is computationally intensive. While hardware-accelerated AV1 decoding is increasingly common on modern chipsets, older mobile devices rely on software fallbacks that can spike CPU usage during bulk loads.
- Best Use Cases: AVIF excels for high-fidelity skyboxes, environmental lighting panoramas, user interface elements, and photorealistic overlays. For massive 3D asset libraries requiring hundreds of distinct surface maps, GPU-native formats like Basis Universal (transcoded directly to BCn/ASTC) remain preferable to keep runtime VRAM low.