DEV Community

Trevor
Trevor

Posted on

Three.js & @React-Three/Fiber : Basics and Loading 3D Models (GLTF)

Three.js

There are no doubts about it, Three.js is complicated as hell. As it stands, I have but a tenuous grasp on this library and what it is capable of accomplishing -- know that going forward. That being said, my lack of knowledge is not a deterrent for attempting to implement it in various projects. The best way to learn is by doing, right?

Three.js is a cross-browser JavaScript library and application programming interface (API) used to create and display animated 3D computer graphics in a web browser using WebGL.

Essentially, Three.js allows us to make 3D objects and environments and implement them in various ways. Want to create a game? Three.js can handle it. Want to add an interesting project to your personal portfolio with more dimensions? Yeah, no problem.

So, how do we use it?

Basics of Three.js

You'll, of course, first need your HTML file.

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>My first three.js app</title>
        <style>
            body { margin: 0; }
        </style>
    </head>
    <body>
        <script src="js/three.js"></script>
        <script>
            // Our Javascript will go here.
        </script>
    </body>
</html>
Enter fullscreen mode Exit fullscreen mode

In order to get started, you're going to need a few things in your script file: a scene, a camera, and a renderer.

const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );

const renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
Enter fullscreen mode Exit fullscreen mode

You might be asking yourself, what the hell is going on here? Think of the scene as your environment. But, in order to actually display your scene you need a camera (which takes in arguments for FOV, aspect ratio, and near/far clipping planes), and a renderer. The renderer, described as "what makes the magic happen", can be thought of as your <Canvas /> -- which is typically set to the full-size of your window for obvious reasons (but, of course can be made smaller to fit your needs). Next we append the renderer to the body of our document.

Add a shape to the scene

We'll be rendering a simple cube -- which will require three things: a geometry, a material, and a mesh to fuse the geometry and material together.

const geometry = new THREE.BoxGeometry();
const material = new THREE.MeshBasicMaterial( { color: #000 } );
const cube = new THREE.Mesh( geometry, material );
scene.add( cube );

camera.position.z = 5;
Enter fullscreen mode Exit fullscreen mode

A few things to note here: a material takes an object of properties (not just limited to color), we need to add the cube to the scene by using the .add method and passing in the mesh we created, and we need to move the camera out a bit on the z-index to view the object (you could also change the default position of the cube object if you did not want to move the camera).

Render Loop

Here comes the last bit. If you used all the code above, you would not be seeing anything just yet. In order to actually view your cube on your canvas element, you'll need to use what is referred to as a render, game, or animate loop.

function animate() {
    requestAnimationFrame( animate );
    renderer.render( scene, camera );
}
animate();
Enter fullscreen mode Exit fullscreen mode

What this loop is doing is drawing your screen every time your screen refreshes (usually around 60 times per second, but can be more depending upon the quality of your monitor).

Your First Scene

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>My first three.js app</title>
        <style>
            body { margin: 0; }
        </style>
    </head>
    <body>
        <script src="js/three.js"></script>
        <script>
            const scene = new THREE.Scene();
            const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );

            const renderer = new THREE.WebGLRenderer();
            renderer.setSize( window.innerWidth, window.innerHeight );
            document.body.appendChild( renderer.domElement );

            const geometry = new THREE.BoxGeometry();
            const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
            const cube = new THREE.Mesh( geometry, material );
            scene.add( cube );

            camera.position.z = 5;

            const animate = function () {
                requestAnimationFrame( animate );


                renderer.render( scene, camera );
            };

            animate();
        </script>
    </body>
</html>
Enter fullscreen mode Exit fullscreen mode

React-Three/Fiber

You know all that complicated stuff creating a scene, camera, renderer, and animation loop we used earlier? Yeah, much easier using R3F. First off, install the following dependencies by running

npm i three @react-three/fiber @react-three/drei
Enter fullscreen mode Exit fullscreen mode

Next, prepare your App component with the following imports and stage your incoming 3d model with a Model component:

import { Canvas } from '@react-three/fiber'
import { useLoader } from '@react-three/fiber'
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'
import { Suspense } from "react";


const Model = () => {
    const gltf = useLoader(GLTFLoader, "./scene.gltf")
    return (
        <>
            <primitive  position={[0, 0, 0]} object={gltf.scene} scale={1} />
        </>
    );
};


function App = () => {
   return(
      <Canvas>
           <Suspense>
              <Model />
           </Suspense>
      </Canvas>
   )
}
Enter fullscreen mode Exit fullscreen mode

Now here's the great part, the <Canvas /> component imported from @react-three/fiber does all the work of creating the render loop, scene, renderer, and camera for you. If you want to reposition the camera (let's say pull it back a bit), you can pass camera as props to the canvas component like so:

  //specify the position of the camera with x, y, and z coordinates
   <Canvas camera={{ position: [0, -40, 20] }}>
   </Canvas>
Enter fullscreen mode Exit fullscreen mode

Add Your 3D Model

If you haven't already done so, head on over to SketchFab -- which is a great resource for acquiring 3D models. Find one that you like and download the .gltf version of the model and add it into the public folder of your React app (where your index.html file is stored). You'll need to add both the scene.bin and scene.gltf files in order for the model to appear.

Once this is done, run your React app and you should see your 3D model on the canvas!

Top comments (2)

Collapse
 
andriusmv profile image
Andres Moreno Vasquez

Can't load any 3d model (GLTF, OBJ or FBX) because "Error: ReactDOMServer does not yet support Suspense".

Look: github.com/pmndrs/react-three-fibe...

Has anyone encoutered the same issue? Thnkx

Collapse
 
zulkernien profile image
Zulker-Nien

You are using suspense around the wrong functions....use it in the parent component for instance, inside the canvas tag