From 341725b37aa01d514da57c0a9d69093ca1dcc9c4 Mon Sep 17 00:00:00 2001 From: billy <61808505+b9llach@users.noreply.github.com> Date: Wed, 15 Apr 2026 17:23:27 -0400 Subject: [PATCH] fix(viewer): await renderer.init() in Canvas gl factory (#233) The WebGPURenderer needs its backend initialized before any direct `.render(scene, camera)` call. The commented-out `// renderer.init()` said "Only use when using ", but the non-debug path also calls direct render from the post-processing fallback (post-processing.tsx:318), which throws "Renderer: .render() called before the backend is initialized" on any browser that falls back to the WebGL2 backend. Switching the gl factory to an async function and awaiting init() before returning is safe in both backends (init() is idempotent and the async factory is a supported @react-three/fiber v9+ pattern), and prevents the error in WebGL2 fallback. --- packages/viewer/src/components/viewer/index.tsx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/viewer/src/components/viewer/index.tsx b/packages/viewer/src/components/viewer/index.tsx index cf00dd5e..bfbfdc96 100644 --- a/packages/viewer/src/components/viewer/index.tsx +++ b/packages/viewer/src/components/viewer/index.tsx @@ -110,6 +110,12 @@ const Viewer: React.FC = ({ const renderer = new THREE.WebGPURenderer(props as any) renderer.toneMapping = THREE.ACESFilmicToneMapping renderer.toneMappingExposure = 0.9 + // Awaiting init() is required when the browser falls back to the + // WebGL2 backend (Safari without the WebGPU flag, older Chrome on + // machines without a WebGPU device). In native WebGPU mode the + // init resolves almost instantly. Without this await, the first + // render throws "Renderer: .render() called before the backend is + // initialized" from the post-processing fallback path. await renderer.init() return renderer }}