Loading GLTF Models with Textures in React Three Fiber

08/25/2023

Contents

In this article, you will learn how to load GLTF models with textures in react three fiber.

Demo

Loading GLTF Models

First, let’s load the GLTF model.
Import useGLTF from @react-three/drei in Model.jsx:

import { useGLTF } from '@react-three/drei'

Load the glb file (model.glb) with useGLTF in the Model function:

export default function Model() {
    const { nodes } = useGLTF('./model.glb')

    // ...
}

The model was created in Blender and named baked, so it can be accessed with nodes.baked.
Create a <mesh> in the Model function and set its geometry to nodes.baked.geometry.

export default function Model() {
    const { nodes } = useGLTF('./model.glb')

    return (
        <>
            <color args={ [ '#0c0b00' ] } attach="background" />

            <mesh geometry={ nodes.baked.geometry } />
        </>
    )
}

The model was drawn on the screen:

Applying textures to models

Let’s apply textures to the loaded model.
Import useTexture from @react-three/drei in Model.jsx:

import { useTexture, useGLTF } from '@react-three/drei'

Load the texture image (texture.jpg) with useTexture in the Model function:

export default function Model() {

    // ...

    const texture = useTexture('./texture.jpg')

    // ...
}

Create a <meshBasicMaterial> in the <mesh> we just created, and set texture to its map.

export default function Model() {

    // ...

    return (
        <>
            // ...

            <mesh geometry={ nodes.baked.geometry } >
                <meshBasicMaterial map={ texture } />
            </mesh>
        </>
    )
}

The texture is applied to the model as shown in the image below:

It’s kind of weird. . .
Let’s flip the Y coordinate of the texture.

export default function Model() {

    // ...

    const texture = useTexture('./texture.jpg')
    texture.flipY = false

    // ...
}

Then the texture was successfully applied to the model:

But, the color is darker than the one made with Blender.
This happens because React Three Fiber and Blender have overlapping toneMapping settings.
To solve this, add flat to <Canvas> in index.jsx:

createRoot(document.getElementById('root')).render(
    <Canvas
        flat
        camera={ {
            fov: 45,
            near: 0.1,
            far: 50,
            position: [ 0, 4, 20 ]
        } }
    >

    // ...

)

Now the color is normal:

Head lights and fog lights

Finally, let’s add the car’s headlights and fog lights.
The light meshes are separate from the base model we just loaded and are named headLightA, headLightB, fogLightA and fogLightB respectively.

Create as many <mesh> as the number of lights to be added, and set the geometry, position and rotation. Also create a <meshBasicMaterial> inside each <mesh> and set the color:

export default function Model() {

    // ...

    return (
        <>
            // ...

            <mesh geometry={ nodes.headLightA.geometry } position={ nodes.headLightA.position } rotation={ nodes.headLightA.rotation }>
                <meshBasicMaterial color="#ffffff" />
            </mesh>
            <mesh geometry={ nodes.headLightB.geometry } position={ nodes.headLightB.position } rotation={ nodes.headLightB.rotation }>
                <meshBasicMaterial color="#ffffff" />
            </mesh>
            <mesh geometry={ nodes.fogLightA.geometry } position={ nodes.fogLightA.position } rotation={ nodes.fogLightA.rotation }>
                <meshBasicMaterial color="#ffffff" />
            </mesh>
            <mesh geometry={ nodes.fogLightB.geometry } position={ nodes.fogLightB.position } rotation={ nodes.fogLightB.rotation }>
                <meshBasicMaterial color="#ffffff" />
            </mesh>
        </>
    )
}

Then the lights were added: