wcandillon / wcandillon/react-native-webgpu

THREE.Renderer: .render() called before the backend is initialized. Try using .renderAsync() instead.

Open
#214 2 comments 3 reactions 1 assignee View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
1.2k
Forks
70
Avg merge
1d 6h
Merged PRs (30d)
23

Description

Hi, really appreciate the project, I'm trying to get this to work with an expo project and react-three-fiber
for web I got an error that I could get around by just creating a FiberCanvas.web.tsx and just use the regular Canvas from fiber.
but on ios when I try following the guide in the readme, I get this error

(NOBRIDGE) WARN  THREE.Renderer: .render() called before the backend is initialized. Try using .renderAsync() instead

I dug into the threejs code and changed the state.gl.render to renderAsync, which did remove the warning but rendered nothing.

so I found this https://github.com/pmndrs/react-three-fiber/issues/3403 issue, and the suggested fix does not work because I never get past

await state.gl.init();

when modifying a bit to try to do the fix like this

import type { ReconcilerRoot, RootState } from "@react-three/fiber";
import {
  createRoot,
  events,
  extend,
  unmountComponentAtNode,
} from "@react-three/fiber";
import React, { useRef, useState } from "react";
import type { ViewProps } from "react-native";
import { PixelRatio } from "react-native";
import { useCanvasEffect, Canvas as WCanvas } from "react-native-wgpu";
import * as THREE from "three";

import {
  makeWebGPURenderer,
  ReactNativeCanvas,
} from "@/utils/makeWebGPURenderer";

//global.THREE = global.THREE || THREE;

interface FiberCanvasProps {
  children: React.ReactNode;
  style?: ViewProps["style"];
  camera?: THREE.PerspectiveCamera;
  scene?: THREE.Scene;
}

export const Canvas = ({
  children,
  style,
  scene,
  camera,
}: FiberCanvasProps) => {
  const root = useRef<ReconcilerRoot<OffscreenCanvas>>(null!);

  React.useMemo(() => extend(THREE), []);
  const [frameloop, setFrameloop] = useState<"always" | "never">("never");
  const canvasRef = useCanvasEffect(async () => {
    const context = canvasRef.current!.getContext("webgpu")!;
    const renderer = makeWebGPURenderer(context);

    // eslint-disable-next-line @typescript-eslint/ban-ts-comment
    // @ts-expect-error
    const canvas = new ReactNativeCanvas(context.canvas) as HTMLCanvasElement;
    canvas.width = canvas.clientWidth * PixelRatio.get();
    canvas.height = canvas.clientHeight * PixelRatio.get();
    const size = {
      top: 0,
      left: 0,
      width: canvas.clientWidth,
      height: canvas.clientHeight,
    };

    if (!root.current) {
      root.current = createRoot(canvas);
    }
    root.current.configure({
      size,
      events,
      scene,
      camera,
      gl: (context) => {
        const renderer = new THREE.WebGPURenderer({
          antialias: true,
          canvas,
          context,
        });
        renderer.init().then(() => setFrameloop("always"));
        renderer.xr = { addEventListener: () => {} };
        return renderer;
      },
      frameloop,
      dpr: 1, //PixelRatio.get(),
      onCreated: async (state: RootState) => {
        //@ts-ignore
        await state.gl.init();
        const renderFrame = state.gl.render.bind(state.gl);
        state.gl.render = (s: THREE.Scene, c: THREE.Camera) => {
          renderFrame(s, c);
          context?.present();
        };
      },
    });
    root.current.render(children);
    return () => {
      if (canvas != null) {
        unmountComponentAtNode(canvas!);
      }
    };
  });

  return <WCanvas ref={canvasRef} style={style} />;
};

I get this

(NOBRIDGE) WARN THREE.WebGPURenderer: WebGPU is not available, running under WebGL2 backend.

And also, I don't think the useCanvasEffect will rerun if I change the component state.
Any help would be appreciated

PS. sometimes it does render but it is not consistent

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.