[ SOLVED ] Raycast issue with nested scene

Hi !

I have created a mainScene that contains a plane Mesh which has an FBO texture map of an offscreen scene (Scene2). This offscreen scene has 2 boxes with an onPointerOver event, and each scene has its own perspective camera. The issue is that when I move the offscreen scene with the Orbitcontrols, the raycaster seems to be tied to the main camera instead of the offscreen scene’s camera, causing the ray to no longer sync with the cubes but still sync with their initial position.

You can see the issue here: https://cp5dlm.csb.app.
Just move the scene with the boxes to the bottom (with a right-click) and then mouse over near the center of the screen. You will see the boxes change color anyway. How can I properly re-sync the raycaster with the offscreen scene?

Thank you for your help.

each portal is a state enclave. in that enclave you can have your own cameras, but if you don’t make one the default it must use the system default. so the camera it’s using here to raycast is the main camera.

function MainScene() {
  const fboTexture = useFBO();
  const size = useThree((state) => state.size);
  const scale = useAspect(size.width, size.height, 1);
  const [offScreenScene] = useState(() => new Scene());
  const cameraRef = useRef(null);

  useFrame((state) => {
    state.gl.setRenderTarget(fboTexture);
    state.gl.render(offScreenScene, cameraRef.current);
    state.gl.setRenderTarget(null);
  });

  return (
    <>
      <mesh scale={scale} raycast={() => null}>
        <planeGeometry />
        <meshBasicMaterial map={fboTexture.texture} />
      </mesh>

      {createPortal(
        <>
          <Scene2 />
          <OrbitControls />
          <PerspectiveCamera
            makeDefault
            position={[0, 0, 5]}
            aspect={size.width / size.height}
            ref={cameraRef}
          />
        </>,
        offScreenScene
      )}
    </>

btw, now that you’ve made a camera the new default inside the portal everything reacts to it. so instead of messing with orbitcontrols like that you simply drop it into the same portal and et voila, it uses that camera.

you also don’t have to inject the camera into other components like Scene2, everything that executes const camera = useThree(state => state.camera) (like orbitcontrols for instance) will end up with the portal cam.

ps. createPortal is a very powerful low-level feature. you would normally use higher up abstractions. all this could be way easier, for instance using drei/RenderTexture:

this demo demonstrates how far you can go with events on non-planar surfaces

and this one is probably the craziest

You are the boss, thanks a lot, it works like a charm :slight_smile:
I already tried to add 2nd Camera into the Createpoprtal function but I had forgotten to add the makeDefault property…

Regarding the RenderTexture comp, I wanted to use shader material with FBO texture. But maybe I could use a Ref on RenderTexture and pass this Ref (map texture) within a uniform… I will try :slight_smile:

Thank you again for your precisous help!