What is GLB?

  • .gltf → JSON + separate textures/files
  • .glb → Everything packed into one file

Most websites use GLB because it's easier and loads faster.


 Load GLB Model

Import Loader

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


Load Model

const loader = new GLTFLoader();

loader.load(
  '/models/shoe.glb',

  function(gltf) {

    const model = gltf.scene;

    model.scale.set(1,1,1);

    model.position.set(0,0,0);

    scene.add(model);

  },

  function(xhr) {

    console.log(
      (xhr.loaded / xhr.total * 100)
      + '% loaded'
    );

  },

  function(error) {

    console.log(error);

  }
);


 DRACO Loader

Without Draco:

shoe.glb = 20 MB

With Draco:

shoe.glb = 2-5 MB

Huge performance improvement.


Import

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


KTX2 Texture Compression

Professional websites use:

GLB + Draco + KTX2

Benefits:

  • Faster loading
  • Less GPU memory
  • Mobile optimization

Import:

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

Used for compressed textures.


Step 1: Create the Sandal in Blender

You make 3 separate objects:

Sandal
├── Sole
├── Top
├── Buckle

In Blender Outliner:

Collection
 ├── Sole
 ├── Top
 ├── Buckle

⚠️ Don't join them (Ctrl + J).

Keep them as separate meshes.


Step 2: Export as GLB

File
→ Export
→ glTF 2.0
→ Format: GLB

Export:

sandal.glb

Inside that single GLB:

Sole Mesh
Top Mesh
Buckle Mesh

are all stored separately.


Step 3: Load in Three.js

const loader = new GLTFLoader();

loader.load('/models/sandal.glb', (gltf) => {

    const sandal = gltf.scene;

    scene.add(sandal);

});

At this point:

Sole
Top
Buckle

appear together as one sandal.


Step 4: Access Individual Parts

Because they are separate objects in Blender:

loader.load('/models/sandal.glb', (gltf) => {

    const sandal = gltf.scene;

    const sole =
    sandal.getObjectByName("Sole");

    const top =
    sandal.getObjectByName("Top");

    const buckle =
    sandal.getObjectByName("Buckle");

    scene.add(sandal);

});

Now Three.js can control each part independently.


let sole;
let top;
let buckle;

loader.load('/models/sandal.glb', (gltf) => {

  const sandal = gltf.scene;

  sole = sandal.getObjectByName("Sole");
  top = sandal.getObjectByName("Top");
  buckle = sandal.getObjectByName("Buckle");

  scene.add(sandal);

});

Animate in the Render Loop

Rotate Only the Buckle

function animate() {

    requestAnimationFrame(animate);

    if(buckle){
        buckle.rotation.y += 0.02;
    }

    renderer.render(scene, camera);

}

animate();

Only the buckle rotates.


Using GSAP

Most product websites use GSAP.

<script src="https://cdn.jsdelivr.net/npm/gsap@3"></script>

Animate Buckle

gsap.to(buckle.rotation,{
    y:Math.PI * 2,
    duration:2,
    repeat:-1,
    ease:"none"
});


In this section