Skip to content

GLTF Loader

Video Lecture

Section Video Links
GLTFloader : Part 1 GLTF Loader : Part 1 GLTF Loader : Part 1
GLTFloader : Part 1 GLTF Loader : Part 2 GLTF Loader : Part 2

Description

A loader for loading glTF models into the Threejs scene.

glTF is a specification for the efficient transmission and loading of 3D scenes and models.

glTF minimizes both the size of 3D assets, and the runtime processing needed to unpack and use those assets.

A glTF file may contain one or more scenes, meshes, materials, textures, skins, skeletons, morph targets, animations, lights and cameras.

Assets can be provided in either JSON (.gltf) or binary (.glb) format.

Part 1

The 3D models used in this lesson can easily be created using Blender. If you don't want to use blender to create the model, then you can download the finished model using the link below. Extract the included suzanne_scene.glb file into the ./public/models/ folder.

gltf-loader.zip

./src/main.ts

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
import './style.css'
import * as THREE from 'three'
import { OrbitControls } from 'three/addons/controls/OrbitControls.js'
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js'
//import { RGBELoader } from 'three/addons/loaders/RGBELoader.js'
import Stats from 'three/addons/libs/stats.module.js'
//import { Lensflare, LensflareElement } from 'three/addons/objects/Lensflare.js'

const scene = new THREE.Scene()

// const light = new THREE.SpotLight(undefined, Math.PI * 1000)
// light.position.set(5, 5, 5)
// light.angle = Math.PI / 16
// light.castShadow = true
// scene.add(light)

// const helper = new THREE.SpotLightHelper(light)
// scene.add(helper)

// new RGBELoader().load('img/venice_sunset_1k.hdr', (texture) => {
//   texture.mapping = THREE.EquirectangularReflectionMapping
//   scene.environment = texture
// })

const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 100)
camera.position.set(1.5, 0.75, 2)

const renderer = new THREE.WebGLRenderer({ antialias: true })
//renderer.toneMapping = THREE.ACESFilmicToneMapping
//renderer.toneMappingExposure = 0.1
renderer.shadowMap.enabled = true
renderer.setSize(window.innerWidth, window.innerHeight)
document.body.appendChild(renderer.domElement)

window.addEventListener('resize', () => {
  camera.aspect = window.innerWidth / window.innerHeight
  camera.updateProjectionMatrix()
  renderer.setSize(window.innerWidth, window.innerHeight)
})

const controls = new OrbitControls(camera, renderer.domElement)
controls.enableDamping = true

// const textureLoader = new THREE.TextureLoader()
// const textureFlare0 = textureLoader.load('https://cdn.jsdelivr.net/gh/Sean-Bradley/First-Car-Shooter@main/dist/client/img/lensflare0.png')

// const lensflare = new Lensflare()
// lensflare.addElement(new LensflareElement(textureFlare0, 1000, 0))
// light.add(lensflare)

new GLTFLoader().load('models/suzanne_scene.glb', (gltf) => {
  console.log(gltf)

  // const suzanne = gltf.scene.getObjectByName('Suzanne') as THREE.Mesh
  // suzanne.castShadow = true

  // const plane = gltf.scene.getObjectByName('Plane') as THREE.Mesh
  // plane.receiveShadow = true

  scene.add(gltf.scene)
})

const stats = new Stats()
document.body.appendChild(stats.dom)

function animate() {
  requestAnimationFrame(animate)

  controls.update()

  renderer.render(scene, camera)

  stats.update()
}

animate()

Working Example

<>

Part 2

We will experiment with materials, textures and lighting.

The final 3D model used in this lesson was created using Blender.

Instructions on how to make the model, are shown in the videos.

If you don't want to create the model, then you can download the finished version using the link below. Extract the suzanne_scene.glb file into the ./public/models/ folder.

gltf-loader-p2.zip

./src/main.ts

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
import './style.css'
import * as THREE from 'three'
import { OrbitControls } from 'three/addons/controls/OrbitControls.js'
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js'
import { RGBELoader } from 'three/addons/loaders/RGBELoader.js'
import Stats from 'three/addons/libs/stats.module.js'
import { Lensflare, LensflareElement } from 'three/addons/objects/Lensflare.js'

const scene = new THREE.Scene()

const light = new THREE.SpotLight(undefined, Math.PI * 1000)
light.position.set(5, 5, 5)
light.angle = Math.PI / 16
light.castShadow = true
scene.add(light)

new RGBELoader().load('img/venice_sunset_1k.hdr', (texture) => {
  texture.mapping = THREE.EquirectangularReflectionMapping
  scene.environment = texture
})

const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 100)
camera.position.set(1.5, 0.75, 2)

const renderer = new THREE.WebGLRenderer({ antialias: true })
renderer.toneMapping = THREE.ACESFilmicToneMapping
renderer.toneMappingExposure = 0.1
renderer.shadowMap.enabled = true
renderer.setSize(window.innerWidth, window.innerHeight)
document.body.appendChild(renderer.domElement)

window.addEventListener('resize', () => {
  camera.aspect = window.innerWidth / window.innerHeight
  camera.updateProjectionMatrix()
  renderer.setSize(window.innerWidth, window.innerHeight)
})

const controls = new OrbitControls(camera, renderer.domElement)
controls.enableDamping = true

const textureLoader = new THREE.TextureLoader()
const textureFlare0 = textureLoader.load('https://cdn.jsdelivr.net/gh/Sean-Bradley/First-Car-Shooter@main/dist/client/img/lensflare0.png')

const lensflare = new Lensflare()
lensflare.addElement(new LensflareElement(textureFlare0, 1000, 0))
light.add(lensflare)

new GLTFLoader().load('models/suzanne_scene.glb', (gltf) => {
  const suzanne = gltf.scene.getObjectByName('Suzanne') as THREE.Mesh
  suzanne.castShadow = true

  const plane = gltf.scene.getObjectByName('Plane') as THREE.Mesh
  plane.receiveShadow = true

  scene.add(gltf.scene)
})

const stats = new Stats()
document.body.appendChild(stats.dom)

function animate() {
  requestAnimationFrame(animate)

  controls.update()

  renderer.render(scene, camera)

  stats.update()
}

animate()

Working Example

<>

Group (threejs.org)

Download Blender

glTF Overview (khronos.org)

GLTFLoader (threejs.org)

Lensflare (threejs.org)

Troubleshooting

SyntaxError: JSON.parse: unexpected character at line 1 column 1 of the JSON data

This usually means that you have the path wrong in your glTF loaders URL parameter, or the model doesn't exist. Many development servers, including Vite, will return the default document (index.html) as an HTTP 200 success instead, rather than indicating an HTTP 404 file not found error. This can be misleading. Check that the path correctly points to the glb model you are trying to load into your scene.

If your model is located at ./public/models/my_model.glb, then the URL used in the glTF loader should be /models/my_model.glb.

new GLTFLoader().load('models/my_model.glb', (gltf) => {
  scene.add(gltf.scene)
})

Comments