Pmdnrs.docs
Quick search [⌘ + K]

Your first scene

This guide will help you setup your first React Three Fiber scene and introduce you to its core concepts.

This tutorial will assume some React knowledge, and will be based on this starter codesandbox, so just fork it and follow along!

Setting up the Canvas

We'll start by importing the <Canvas /> component from react-three-fiber and putting it in our React tree:

import { Canvas } from 'react-three-fiber'

function App() {
  return (
    <div id="canvas-container">
      <Canvas />
    </div>
  )
}

export default App

The Canvas component does some important setup work behind the scenes:

  • It sets up a Scene and a Camera, the basic building blocks necessary for rendering
  • It automatically handles window resizing
  • It renders our scene every frame

To actually render something in our scene, we'll add a mesh component. In Fiber, every THREE.js object has an equivalent component:

const myMesh = new THREE.Mesh()
// is equivalent to
<mesh />

Note that the Canvas will be resized to fit the parent div, so you can control how big it is by just changing the width and height of #canvas-container in your css.

Adding a Mesh

A Mesh is a basic object in THREE.js, and it's used to hold the polygons and the material that are needed to represent the object in 3D space. We'll create a new mesh using a BoxBufferGeometry as the geometry and a MeshPhongMaterial as the material.

To actually add these objects to our scene, we mount them inside the <Canvas /> component.

Note that we don't need to import anything, THREE objects will be treated as native JSX elements, just like you can just write <div> or <span /> in regular React. The general rule is that the Fiber components are available with the camel-case version of their name in THREE.js.

import { Canvas } from 'react-three-fiber'

function App() {
  return (
    <div id="canvas-container">
      <Canvas>
        <mesh>
          <boxBufferGeometry attach="geometry" />
          <meshPhongMaterial attach="material" />
        </mesh>
      </Canvas>
    </div>
  )
}

export default App

It's worth pausing a moment to understand exactly what is happening here. The code we just wrote, is the equivalent to this THREE.js code:

const myMesh = new THREE.Mesh()
const myGeometry = new THREE.BoxBufferGeometry()
const myMaterial = new THREE.MeshPhongMaterial()

myMesh.geometry = myGeometry
myMesh.material = myMaterial

scene.add(myMesh)

When you mount a mesh component, Fiber is creating a new THREE.Mesh object, and the same is done for geometry and material. Then, geometry and material are attached to their parent, by assigning its geometry and material properties to the newly created objects.

Changing the camera

Attach and Args

The attach prop is used to make this relationship explicit, effectively telling Fiber what property of the parent to attach the newly created object to.

The args prop is used to pass constructor arguments to THREE.js. To better understand this, we can take a look at the documentation for THREE's BoxBufferGeometry, that tells us how the geometry is constructed:

const geometry = new THREE.BoxBufferGeometry(2, 2, 2)

Looking at the docs, we understand that (2, 2, 2) are the width, height and depth of our box. These 3 values, make the arguments array of the BoxBufferGeoemtry constructor.

We can make use of this info in Fiber:

<boxBufferGeometry args={[2, 2, 2]} />

The value of args is always an array, and it's equivalent to the values we used in the THREE.js example to construct our geometry.

Adding lights

Next, we will add some lights to our scene, by putting these components as children of <Canvas />

<Canvas>
  ...
  <ambientLight args={[0xff0000]} intensity={0.4} />
  <directionalLight position={[0, 0, 5]} intensity={0.1} />
</Canvas>

This introduces us to the last fundamental concept of Fiber, how React props work on THREE objects. Let's focus on ambientLight:

<ambientLight // we are using a THREE.js AmbientLight
  args={[0xff0000]} // we are passing this color to the constructor
  intensity={0.1} // we are setting the light's intensity to 0.1
/>

From the AmbientLight documentation we learn that it is constructed with a color value (0xff0000 in our case) and has an intensity property, that defines how strong the light is. When you set any prop on a Fiber component, it will set the property of the same name on the THREE.js object, like you could do manually:

const myLight = new THREE.AmbientLight(0xff0000)

// when the `intensity` prop changes
myLight.intensity = 0.1

Our directionalLight doesn't have an args prop, meaning that the default arguments will be used when creating the object. It does have a position prop that, as you can imagine, will set the position property of the DirectionalLight object.

Here's our final result, a simple box with a Phong material:

Exercise: