From GLB to JSX: Integrating 3D Models into Your React App

In React, we can use tools like gltfjsx package to convert 3D models from GLB
or GLTF
formats into *.jsx
components for rendering within a React application.
GLTF (GL Transmission Format): A JSON-based format for 3D scenes and models, including meshes, textures, and animations, designed for efficient web transmission as seperate files.
GLB: A compact, binary version of GLTF that includes all resources in a single file, ideal for efficient 3D content transfer and use in web applications.
To make it easier to understand, I'm going to use both GLB
and GLTF
files of the same model and explain how we can convert 3D files into JSX components in both cases
npm install three @types/three @react-three/fiber @react-three/drei
glb
on the browser (glb to jsx)3d model
Merc Hovercar from Sketchfab and save the file inside the public > 3dModel
folder. CLI
to navigate to the 3dModel
folder. Ideally, the 3dModel
should be inside the public > 3dModel
folder.cd .\public\3dModel\
jsx
file and compressed version of the model (the textures will be converted to webp)npx gltfjsx free_merc_hovercar.glb --draco
This command installs the
gltfjsx
npm package and converts theGLTF
file to[fileName]-transformed.glb
The
[fileName].jsx
file will also be generated inside the folder.
or run the following command if you are insideIf you don’t need to compress the texture, then remove the
--draco
flag.
gltf
model foldernpx gltfjsx .\scene.gltf --draco
This will only generate a
jsx
file inside the folder
import React, { useRef } from "react";
import { useGLTF } from "@react-three/drei";
export function Model(props) {
const { nodes, materials } = useGLTF("/free_merc_hovercar.glb");
return (
<group {...props} dispose={null}>
<group
position={[0.019, -0.066, -0.047]}
rotation={[-Math.PI / 2, 0, 0]}
scale={0.496}
>
<mesh
geometry={nodes.Plane006_0.geometry}
material={materials["Material.001"]}
/>
<mesh
geometry={nodes.Plane006_1.geometry}
material={materials.Material_light}
/>
<mesh
geometry={nodes.Plane_0.geometry}
material={materials.Plane_0}
position={[0, 0, -0.582]}
scale={[1.187, 2, 1]}
/>
</group>
</group>
);
}
useGLTF.preload("/free_merc_hovercar.glb");
export function FlyingCar(props)
Then move the *.jsx
file to src>components>3dModel>FlyingCar.jsx
3dModel/free_merc_hovercar.glb
import React, { useRef } from "react";
import { useGLTF } from "@react-three/drei";
export function FlyingCar(props) {
const { nodes, materials } = useGLTF("3dModel/free_merc_hovercar.glb");
return (
<group {...props} dispose={null}>
<group
position={[0.019, -0.066, -0.047]}
rotation={[-Math.PI / 2, 0, 0]}
scale={0.496}
>
<mesh
geometry={nodes.Plane006_0.geometry}
material={materials["Material.001"]}
/>
<mesh
geometry={nodes.Plane006_1.geometry}
material={materials.Material_light}
/>
<mesh
geometry={nodes.Plane_0.geometry}
material={materials.Plane_0}
position={[0, 0, -0.582]}
scale={[1.187, 2, 1]}
/>
</group>
</group>
);
}
useGLTF.preload("3dModel/free_merc_hovercar.glb");
3d model
using react three fiber
. Create a new route
and page
to display the 3d model. Now open the page file. In my case my page file is GlbModel.jsx
import { Canvas } from "@react-three/fiber";
import { CameraControls, PerspectiveCamera } from "@react-three/drei";
function GlbModel() {
return (
<>
<title>GLB Model</title>
<main className="px-5">
<div className="border-2 h-[700px] my-5 rounded-lg">
<Canvas>
<PerspectiveCamera
makeDefault
fov={75}
position={[0, 0, 2]}
resolution={1024}
/>
<CameraControls />
<ambientLight intensity={0.5} />
</Canvas>
</div>
</main>
</>
);
}
export default GlbModel;
3D model
. Since the 3D model
may load more slowly and asynchronously compared to the page, we also need to import Suspense
from React.import { Canvas } from "@react-three/fiber";
import { Suspense } from "react";
import { CameraControls, PerspectiveCamera } from "@react-three/drei";
import { FlyingCar } from "../components/3dModels/FlyingCar.jsx";
function GlbModel() {
return (
<>
<title>GLB Model</title>
<main className="px-5">
<div className="border-2 h-[700px] my-5 rounded-lg">
<Canvas>
<PerspectiveCamera
makeDefault
fov={75}
position={[0, 0, 2]}
resolution={1024}
/>
<CameraControls />
<ambientLight intensity={5} />
<Suspense>
<FlyingCar></FlyingCar>
</Suspense>
</Canvas>
</div>
</main>
</>
);
}
export default GlbModel;
hdr
image to improve the look even furthur.import { Canvas } from "@react-three/fiber";
import { Suspense } from "react";
import {
CameraControls,
PerspectiveCamera,
Environment,
} from "@react-three/drei";
import { FlyingCar } from "../components/3dModels/FlyingCar.jsx";
function GlbModel() {
return (
<>
<title>GLB Model</title>
<main className="px-5">
<div className="border-2 h-[700px] my-5 rounded-lg">
<Canvas>
<PerspectiveCamera
makeDefault
fov={75}
position={[0, 0, 2]}
resolution={1024}
/>
<CameraControls />
<ambientLight intensity={1} />
<Suspense>
<FlyingCar></FlyingCar>
</Suspense>
<Environment background={false} preset={"apartment"} />
</Canvas>
</div>
</main>
</>
);
}
export default GlbModel;
If you are confuse about how the
hdr
image working, you can check the official documentation Basically somehdr
are already provided in the@react-three/drei
package and we can use those using the current preset likeapartment
,city
,forest
,studio
etc.
hdr
image then you can store the hdr
image on public > hdr > dry_field_01k.hdr
and use the image like the following codeimport { Canvas } from "@react-three/fiber";
import { Suspense } from "react";
import {
CameraControls,
PerspectiveCamera,
Environment,
} from "@react-three/drei";
import { FlyingCar } from "../components/3dModels/FlyingCar.jsx";
function GlbModel() {
return (
<>
<title>GLB Model</title>
<main className="px-5">
<div className="border-2 h-[700px] my-5 rounded-lg">
<Canvas>
<PerspectiveCamera
makeDefault
fov={75}
position={[0, 0, 2]}
resolution={1024}
/>
<CameraControls />
<ambientLight intensity={1} />
<Suspense>
<FlyingCar></FlyingCar>
</Suspense>
<Environment
background={true}
files={["/hdr/dry_field_01k.hdr"]}
/>
</Canvas>
</div>
</main>
</>
);
}
export default GlbModel;
Environment
tag.import { Canvas } from "@react-three/fiber";
import { Suspense } from "react";
import {
CameraControls,
PerspectiveCamera,
Environment,
} from "@react-three/drei";
import { FlyingCar } from "../components/3dModels/FlyingCar.jsx";
function GlbModel() {
return (
<>
<title>GLB Model</title>
<main className="px-5">
<div className="border-2 h-[700px] my-5 rounded-lg">
<Canvas>
<PerspectiveCamera
makeDefault
fov={75}
position={[0, 0, 2]}
resolution={1024}
/>
<CameraControls />
<ambientLight intensity={1} />
<Suspense>
<FlyingCar></FlyingCar>
</Suspense>
<Environment
background={true}
files={["/hdr/dry_field_01k.hdr"]}
ground={{
height: 5, // Height of the camera that was used to create the env map (Default: 15)
radius: 120, // Radius of the world. (Default 60)
scale: 10, // Scale of the backside projected sphere that holds the env texture (Default: 1000)
}}
/>
</Canvas>
</div>
</main>
</>
);
}
export default GlbModel;