From 5077011c261e4d88d11e90f5aa15c91d70d5aee1 Mon Sep 17 00:00:00 2001 From: Aymeric Rabot Date: Fri, 27 Feb 2026 14:28:31 -0500 Subject: [PATCH] Initialize WebGPU renderer before post-processing Make the gl prop synchronous and move/await renderer initialization inside the post-processing component. index.tsx: remove async gl factory and the await renderer.init() so renderer is created synchronously. post-processing.tsx: add isInitialized state, an async initRenderer that calls renderer.init(), and guard post-processing setup until init completes (with mounted cleanup and updated effect deps). This ensures the WebGPU renderer is fully initialized before building the render pipeline and avoids using an async gl factory. --- .../viewer/src/components/viewer/index.tsx | 3 +-- .../src/components/viewer/post-processing.tsx | 23 ++++++++++++++++--- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/packages/viewer/src/components/viewer/index.tsx b/packages/viewer/src/components/viewer/index.tsx index a59fd45e..7f23decc 100644 --- a/packages/viewer/src/components/viewer/index.tsx +++ b/packages/viewer/src/components/viewer/index.tsx @@ -41,9 +41,8 @@ const Viewer: React.FC = ({ children, selectionManager = 'default', { + gl={(props) => { const renderer = new THREE.WebGPURenderer(props as any) - await renderer.init() renderer.toneMapping = THREE.ACESFilmicToneMapping renderer.toneMappingExposure = 0.9 return renderer diff --git a/packages/viewer/src/components/viewer/post-processing.tsx b/packages/viewer/src/components/viewer/post-processing.tsx index 3577187e..a8a2cde1 100644 --- a/packages/viewer/src/components/viewer/post-processing.tsx +++ b/packages/viewer/src/components/viewer/post-processing.tsx @@ -1,5 +1,5 @@ import { useFrame, useThree } from '@react-three/fiber' -import { useEffect, useRef } from 'react' +import { useEffect, useRef, useState } from 'react' import { Color, UnsignedByteType } from 'three' import { outline } from 'three/addons/tsl/display/OutlineNode.js' import { ssgi } from 'three/addons/tsl/display/SSGINode.js' @@ -43,9 +43,26 @@ export const SSGI_PARAMS = { const PostProcessingPasses = () => { const { gl: renderer, scene, camera } = useThree() const renderPipelineRef = useRef(null) + const [isInitialized, setIsInitialized] = useState(false) useEffect(() => { - if (!renderer || !scene || !camera) { + let mounted = true + const initRenderer = async () => { + if (renderer && (renderer as any).init) { + await (renderer as any).init() + } + if (mounted) { + setIsInitialized(true) + } + } + initRenderer() + return () => { + mounted = false + } + }, [renderer]) + + useEffect(() => { + if (!renderer || !scene || !camera || !isInitialized) { return } @@ -173,7 +190,7 @@ const PostProcessingPasses = () => { } renderPipelineRef.current = null } - }, [renderer, scene, camera]) + }, [renderer, scene, camera, isInitialized]) useFrame(() => { if (renderPipelineRef.current) {