Shortcuts ⌨️

  • SPACE to play / pause
  • ARROW RIGHT or L to go forward
  • ARROW LEFT or J to go backward
  • ARROW UP to increase volume
  • ARROW DOWN to decrease volume
  • F to toggle fullscreen
  • M to toggle mute
  • 0 to 9 to go to the corresponding part of the video
  • SHIFT + , to decrease playback speed
  • SHIFT + . or ; to increase playback speed

Unlock content 🔓

To get access to 93 hours of video, a members-only Discord server, subtitles, lesson resources, future updates and much more join us for only $95!

Want to learn more? 🤘


That's the end of the free part 😔

To get access to 93 hours of video, a members-only Discord server and future updates, join us for only $95!

Next lesson

Load models

Difficulty Medium

Introduction 00:00

In one of the previous lessons, we created a hamburger (although I realised it should have been named “cheeseburger”) and learned how to implement it in Three.js.

We are going to do the same with R3F and discover some tips and tricks along the way.

Setup 00:33

The starter is similar to the previous lesson with a sphere, a cube and a green floor.

We’ve also added <Perf /> from r3f-perf in order to keep an eye on performance.

We activated the shadows on the <Canvas> and added castShadow and receiveShadow on the corresponding <mesh> and <directionalLight>.

The @react-three/drei dependency is already installed within the project and we are using the OrbitControls helper to be able to move the camera around.

Clean up

In Experience.jsx, we can start by removing the sphere <mesh> and the cube <mesh> that were there just to make sure that the shadows function:

export default function Experience()
    return <>

        <Perf position="top-left" />

        <OrbitControls makeDefault />

        <directionalLight castShadow position={ [ 1, 2, 3 ] } intensity={ 4.5 } />
        <ambientLight intensity={ 1.5 } />

        <mesh receiveShadow position-y={ - 1 } rotation-x={ - Math.PI * 0.5 } scale={ 10 }>
            <planeGeometry />
            <meshStandardMaterial color="greenyellow" />


Loading a model 01:37

We have a bunch of models available in the /public/ folder and we are going to focus on the two hamburger files for now.

One is DRACO compressed (hamburger-draco.glb) and the other is not (hamburger.glb).

In the following part, we are only going to discuss GLTF loading since it’s the standard and the most frequently used format, but the solutions we are going to see can be used with other formats.

R3F provides a hook named useLoader that abstract loading.

In Experience.jsx, import useLoader from @react-three/fiber:

import { useLoader } from '@react-three/fiber'

To use it, we need to send it the Three.js loader class we want to use and the path to the file.

Because it’s a GLTF, we need to import GLTFLoader from three:

import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'

In Experience, we can now call useLoader:

export default function Experience()
    const model = useLoader(GLTFLoader, './hamburger.glb')

    // ...

Note that we started the path to the file with ./ which should work in most cases. './hamburger.glb' will look for the file named hamburger.glb in the same folder and since the files located in the /public/ folder are made available like if they are at the root of the website, the model will load. Still, when putting your experience online, you might have to do some tweaks according to your website, the path to access it, specific folders structure and rewriting rules.

Back to our project, you should see an object containing our model in the console.

To display it in our scene, we need to add model.scene somewhere in the JSX. Unfortunately, we can’t just write it like this:

{ model.scene }

Or like this:

<model.scene />

These commands are not supported by R3F and they don’t really make sense.

Want to learn more?

That's the end of the free part 😔

To get access to 93 hours of video, a members-only Discord server and future updates, join us for only $95!

How to use it 🤔

  • Download the Starter pack or Final project
  • Unzip it
  • Open your terminal and go to the unzip folder
  • Run npm install to install dependencies
    (if your terminal warns you about vulnerabilities, ignore it)
  • Run npm run dev to launch the local server
    (project should open on your default browser automatically)
  • Start coding
  • The JS is located in src/script.js
  • The HTML is located in src/index.html
  • The CSS is located in src/style.css

If you get stuck and need help, join the members-only Discord server: