Quick answer: Listen for webglcontextlost and preventDefault() it (this allows restoration). On webglcontextrestored, recreate every GPU resource — textures, buffers, shaders.

A browser game running for a while goes blank. The GPU process crashed or the OS reclaimed the context. Without handling, WebGL never comes back.

Listen and Prevent Default

canvas.addEventListener("webglcontextlost", (e) => {
    e.preventDefault();   // REQUIRED for restoration to be possible
    cancelAnimationFrame(rafId);
    gpuResourcesValid = false;
}, false);

Without preventDefault, the browser won’t fire the restored event — the context is gone permanently.

Recreate on Restore

canvas.addEventListener("webglcontextrestored", () => {
    initGLState();        // blend modes, etc.
    recreateShaders();
    reuploadTextures();   // from CPU-side copies
    recreateBuffers();
    gpuResourcesValid = true;
    rafId = requestAnimationFrame(loop);
}, false);

All GPU objects are invalid after loss. Recreate from CPU-side source data — which means you must keep that source data around.

Keep CPU-Side Copies

Texture pixels, vertex data, shader source — retain them (or be able to re-fetch). If you discarded them after upload, you can’t restore.

Engine Note

Unity WebGL, Godot Web, and Construct 3 handle context loss internally to varying degrees. For hand-rolled WebGL or three.js, you own this.

Verifying

Simulate loss via the WEBGL_lose_context extension in dev. The game pauses, then restores and resumes rendering. No permanent blank canvas.

“Context loss is normal on the web. preventDefault, keep CPU copies, recreate on restore.”

Test context loss explicitly — it’s rare in dev but common on real devices under memory pressure, especially mobile browsers.