Skip to content

Loading Assets

Video Lecture

Loading Assets Loading Assets

Description

As our projects become more advanced, we will want to load extra assets into them, for example, images, models, sounds, animations, fonts, JSON data or more.

We have several ways of doing this.

Lesson Script

./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
77
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 hdr from './img/venice_sunset_1k.hdr'
// import image from './img/grid.png'
// import model from './models/suzanne_no_material.glb'

const scene = new THREE.Scene()

const hdr = 'https://sbcode.net/img/venice_sunset_1k.hdr'
const image = 'https://sbcode.net/img/grid.png'
const model = 'https://sbcode.net/models/suzanne_no_material.glb'

// const hdr = 'https://cdn.jsdelivr.net/gh/mrdoob/three.js@dev/examples/textures/equirectangular/venice_sunset_1k.hdr'
// const image = 'https://cdn.jsdelivr.net/gh/mrdoob/three.js@dev/examples/textures/uv_grid_opengl.jpg'
// const model = 'https://cdn.jsdelivr.net/gh/mrdoob/three.js@dev/examples/models/gltf/Xbot.glb'

// const hdr = 'img/venice_sunset_1k.hdr'
// const image = 'img/grid.png'
// const model = 'models/suzanne_no_material.glb'

new RGBELoader().load(hdr, (texture) => {
  texture.mapping = THREE.EquirectangularReflectionMapping
  scene.environment = texture
  scene.background = texture
})

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

const renderer = new THREE.WebGLRenderer({ antialias: true })
renderer.toneMapping = THREE.ACESFilmicToneMapping
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 material = new THREE.MeshStandardMaterial()
material.map = new THREE.TextureLoader().load(image)
//material.map.colorSpace = THREE.SRGBColorSpace

const plane = new THREE.Mesh(new THREE.PlaneGeometry(10, 10), material)
plane.rotation.x = -Math.PI / 2
plane.position.y = -1
scene.add(plane)

new GLTFLoader().load(model, (gltf) => {
  gltf.scene.traverse((child) => {
    ;(child as THREE.Mesh).material = material
  })
  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()

Load Assets from My Web Server

I don't recommend doing this long term. But, it is OK while learning.

E.g.,

const hdr = 'https://sbcode.net/img/venice_sunset_1k.hdr'
const image = 'https://sbcode.net/img/grid.png'
const model = 'https://sbcode.net/models/suzanne_no_material.glb'

Load Assets from a CDN

We could create CDN links pointing to assets you find on GitHub or elsewhere. I do this often when I experiment with, or share ideas in forums.

E.g., these links

const hdr = 'https://cdn.jsdelivr.net/gh/mrdoob/three.js@dev/examples/textures/equirectangular/venice_sunset_1k.hdr'
const image = 'https://cdn.jsdelivr.net/gh/mrdoob/three.js@dev/examples/textures/uv_grid_opengl.jpg'
const model = 'https://cdn.jsdelivr.net/gh/mrdoob/three.js@dev/examples/models/gltf/Xbot.glb'

Host Assets Locally

We could load assets locally from our projects ./public folder. This is the best approach. Host your own assets on your own servers.

E.g.,

const hdr = 'img/venice_sunset_1k.hdr'
const image = 'img/grid.png'
const model = 'models/suzanne_no_material.glb'

You can download the lesson assets from this link. Save both the img and models folders under your ./public folder.

loading-assets.zip

After extracting, your folder structure should resemble,

|-- Three.js-TypeScript-Boilerplate
    |-- node_modules
        |-- (Many files and folders. These are our projects dependencies)
    |-- public
        |-- img
            |-- grid.png
            |-- venice_sunset_1k.hdr
        |-- models
            |-- suzanne_no_material.glb
    |-- src
        |-- main.ts
        |-- style.css
    |-- .gitignore
    |-- index.html
    |-- package-lock.json
    |-- package.json
    |-- tsconfig.json

Use ES6 Import syntax

Or we could import assets using ES6 import syntax.

import hdr from 'img/venice_sunset_1k.hdr'
import grid from 'img/grid.png'
import model from 'models/suzanne_no_material.glb'

I don't recommend this approach, unless it actually benefits your application.

The simplest method, is too just to put your static assets in the ./public folder, and reference them correctly when needed. See Host Assets Locally.

Anyway, if you want to try using ES6 import syntax to load static assets, then you may get an error such as,

Cannot find module 'img/venice_sunset_1k.hdr' or its corresponding type declarations.ts

You will need to add a type declaration file so that TypeScript knows how to handle them.

./src/index.d.ts

declare module '*.png'

declare module '*.hdr'

declare module '*.glb'

The next error may be something like,

You may need to install appropriate plugins to handle the .hdr file format, or if it's an asset, add "**/*.hdr" to 'assetsInclude' in your configuration

To fix, add a vite.config.js to your projects root with the following.

./vite.config.js

import { defineConfig } from 'vite'

export default defineConfig({
  assetsInclude: ['**/*.hdr', '**/*.glb'],
})

Finally, move the img and models folders from ./public to ./src.

Note, only use this approach if it actually does add any benefit to your application. It most likely doesn't.

Prefer to just place your static assets in the ./public folder as outlined in the section Host Assets Locally

jsdelivr GitHub Tool