Implemented progressive JPEG streaming for WebGL using Emscripten-compiled libjpeg. The goal was enabling real-time texture loading with visual preview, addressing a performance bottleneck in web-based 3D applications.
3D models can be efficiently compressed, but textures often exceed model size and must load completely before display. Progressive JPEG supports incremental rendering, but browsers’ Image element doesn’t expose intermediate stages. I developed multiple approaches to enable progressive texture streaming in WebGL.
The first approach used XMLHttpRequest to stream binary data with base64 encoding. It worked in Firefox 12 but failed in Chrome 19 due to libjpeg-turbo integration differences.
The second approach rendered progressive images to 2D Canvas, extracted typed arrays, and copied to WebGL textures. Cross-browser compatible but introduced stuttering from decode overhead - about 50ms per 2K texture on the main thread, too slow for 60 FPS.
The recommended approach compiled libjpeg using Emscripten (C to JavaScript via LLVM) to decode JPEGs in Web Workers, eliminating main thread blocking. Trade-offs: 85KB GZIP overhead for the library, 4 seconds to decode a 2K texture (80x slower than native), but zero main thread impact. Only viable for applications with many large textures.
The key finding: progressive streaming makes sense when connection speed is slower than decoding speed and you have multiple large textures to justify the overhead. For fast connections (>10 Mbps), native loading is faster. This was one of the early demonstrations of using Emscripten to bring C libraries to the browser for performance-critical tasks, and the pattern of offloading intensive computation to Web Workers became common.