HOME

How To Load a GLTF or GLB

Load a GLTF or GLB
An Example of a GLTF Header

In this tutorial, I will show you how to load a GLTF or GLB.

As an example, I create a website header that is a GLB file using React, Three.js, and @react-three/fiber. You can try the demo here.

WebGL allows us to create interactive browser-based animations inside an HTML canvas element. It takes about a hundred lines of code just to draw a triangle on the screen using WebGL.

Luckily there is a library called Three.js that is a more user-friendly library built on top of WebGL, as well as React Three Fiber and Drei, which give us some great tools to bring Three.js to React. 

What is a GLTF/GLB?

In this simple tutorial, I hope to show you how to incorporate a Graphics Language Transmission Format (GLTF) or its cousin the Graphic Language Binary (GLB) into an interactive header. This project is a collaboration with 3D artist Stacie Ant.

These two formats convert a 3D model into JSON format, which is easy for the browser to work with. The only difference between GLTF and GLB is the number of files needed to render a 3D model in the browser.

A GLTF is commonly 3 or more separate files, a .gltf file, a .bin file, and texture files, that can be .jpg, .png, or .ktx2.

A GLB is all of these files combined into one file. I personally prefer working with GLB, as there is less clutter in my working directory, and it is easier to send one file to a Content Delivery Network (CDN) than it is to send 3 or more.

Getting Started

I would recommend that you clone the repo that I created for this tutorial. I am assuming you have some familiarity with React and JavaScript and you want to learn how to load a GLTF or GLB.

It’s not mandatory that you have experience with 3D modeling and rendering software but it would help.

If you are completely new to the topic I would recommend downloading a free program like Blender and working on some simple scenes.

Essentially, all 3D scenes need 3 things, a model, some lighting, and a camera.

All of these objects exist inside an X, Y, and Z coordinate grid.

When using software it is easy to visualize lighting and camera placement, however, with Three.js you will have to experiment a bit to get used to giving these 3 elements their coordinates in an array.

how to load a GLTF or GLB

The first thing you need to do is import the model. The code below loads the model and returns it to be used inside the Canvas element, which is provided by react-three/fiber.

WebGL is rendered inside a <canvas> element inside the DOM.

To load the model I created a function named Model.

This function uses useLoader from react-three/fiber, as well as GLTFLoader from Three. The second argument inside useLoader is the model you will be loading. I chose to render this model from Imagekit, however, feel free to use your own model. Which can be placed inside your source folder and linked directly.

A great place to find your own models is Sketchfab.

Another point to mention is that the GLTFLoader can be replaced with other loaders which can render different 3D model formats, such as .obj, .fbx, etc. However, GLTF/GLB are most commonly used because they are optimized for WebGL.

There is also a useGLTF() function inside the “@react-three/drei” library.

const Model = () => {

  const gltf = useLoader(

    GLTFLoader,

    "https://ik.imagekit.io/fx30u3wgcqib/logo_10_ZkMj5uZks.glb?updatedAt=1629708924337"

  );

  return (

    <>

      <primitive object={gltf.scene} scale={1} />

    </>

  );

};

Rendering The Model On The Screen

The first thing to note is that there is some CSS going on here, that essentially makes the canvas fullscreen. I do not want to delve into the CSS in this article, so please take a look at the code on GitHub.

The first thing we need is a Canvas to load the model into, this is provided to us by the react-three/fiber library.

We pass into this element, a camera prop with an object inside it, that contains a position. This position will not work for every model, I just found that these settings gave me the look I was going for. Please read the documentation to see what other props can be passed to Canvas and the other elements below.

For now, I will skip the Suspense element and come back to that in a moment.

Next, we render the Model element inside the Canvas. The OrbitalControls that I use are provided by @react-three/drei. They are not mandatory to render the model, however, they make the model interactive.

I passed props of autoRotate and autoRotateSpeed to the OrbitalControls. These props, as you may have guessed, cause the model to automatically rotate!

If you recall in the beginning I mentioned that every 3D scene needs 3 elements, a model, a camera, and lighting. Well so far we have a model and a camera, but no lighting.

For this project, I chose to use a High Dynamic Range Image (HDRI) map for the lighting. Essentially an HDRI map is a 3D photo, the information in the HDRI map, allows the 3D program or web application to approximate the lighting conditions of the photo, without manually needing to place lights in the scene.

This suited the aesthetic of Stacie Ant’s art. To do this I used the Environment element provided by Drei. To The Environment element, I provide two props, a preset of ‘dawn’ and background, which looks like a sunrise over a desert, and using the image of the HDR for the background. 

You can use background={false} to remove the image.

const Head = () => {

  return (

    <div id="header_container">

      <Canvas camera={{ position: [0, -2, 15] }}>

        <Suspense fallback={<Loader />}>

          <Model />

          <OrbitControls autoRotate autoRotateSpeed={0.5} />

          <Environment preset="dawn" background />

        </Suspense>

      </Canvas>

      <div id="header_content">

        <a id="header_button" href="http://www.aaronjcunningham.com">

          ENTER

        </a>

      </div>

    </div>

  );

};

Wrapping things up

I am passing a Drei element called HTML to that React Suspense element. Simply put this is a loader that shows the viewer the percentage of the model that has been downloaded. Again this is not needed but I find it helpful.

One word of warning is that 3D models can be quite large, and will take a long time to download unless optimized correctly.

Initially, Stacie Ant gave me a model that was over 15 MB.

I was able to work with her and get that down to 1.3MB, she did this by reducing the triangle count.

function Loader() {

  const { progress } = useProgress();

  return (

    <Html center>

      <h2 id="loading">{progress} % loaded</h2>

    </Html>

  );

}

So that’s it, that’s how to load a GLTF or GLB. I hope this helps. My biggest tip would be to get your hand dirty and experiment with what is possible.