Search code examples
three.jsreact-three-fiberreact-three-drei

How to set a plane to be the size of the camera React-Three-Fiber?


I'm trying to add a 3D effect on a plane in a React site. But I haven't been able to create a plane that fills the camera, like in all the Three.js shader or post-processing examples.

I have tried using an Orthographic Camera + plane, based on this answer, like so:

<Canvas>
  <OrthographicCamera left={-1} right={1} top={1} bottom={-1} near={0} far={1} />
    <planeGeometry args={[2, 2]} />
  </OrthographicCamera>
</Canvas>

But this results in a small square in the middle of the canvas. a small square in the middle of the canvas

I also tried using a ScreenQuad, like so:

<Canvas style={{width: '100vw', height: '100vh'}}>
  <ScreenQuad />
</Canvas>

But this results in a triangle in the middle of the canvas.

a triangle in the middle of the canvas

Here is a repo reproducing both examples: https://github.com/Cecile-Lebleu/gatsby-r3f-bug

I can only cover the Canvas by blowing up the size of the plane, but it's not a good solution: the effect looks giant on small screens and still cropped on larger screens.

What's going on? How can I make a simple plane that covers the camera regardless of Canvas size?


Solution

  • In case anyone ever runs into this, the solution thanks to @0xca0a:

    Set the camera to default: <OrthographicCamera makeDefault>

    And scale the mesh to fit the viewport.

    const viewport = useThree(state => state.viewport)
    return (
      <mesh scale={[viewport.width, viewport.height, 1]}>
        <planeGeometry />
      </mesh>
    

    Add in useAspect for responsive images:

    function Scene() {
      const size = useAspect(1800, 1000)
      return (
        <mesh scale={size}>
    )}
    

    The first two args are the width and height of the image, it then calculates a viewport big enough to cover, and it's responsive.

    Or just use drei/image.