Skip to content

Instantly share code, notes, and snippets.

@dghez
Last active February 20, 2023 15:33
Show Gist options
  • Select an option

  • Save dghez/ca638ef04ad8216253e04ebd070bc9e4 to your computer and use it in GitHub Desktop.

Select an option

Save dghez/ca638ef04ad8216253e04ebd070bc9e4 to your computer and use it in GitHub Desktop.
Global loader manager for ThreeJs + react hook
/* eslint-disable no-multi-assign */
import { useMemo } from 'react'
import { TextureLoader, NearestFilter, FloatType, HalfFloatType, LinearEncoding } from 'three'
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'
import { EXRLoader } from 'three/examples/jsm/loaders/EXRLoader.js'
import staticData from './data.yml'
class Resources {
constructor() {
this._loaders = {
gltfLoader: new GLTFLoader(),
textureLoader: new TextureLoader(),
exrLoader: new EXRLoader(),
}
this._loaded = 0
this._resources = new Map()
this._onLoadCb = undefined
}
get(key) {
return this._resources.get(key)
}
startLoad(context, data = [], onLoadCb = () => {}) {
this._onLoadCb = onLoadCb
this._gl = context
// this._pmremGenerator = new PMREMGenerator(this._gl)
const promises = []
const all = [...data, ...staticData]
all.forEach((el) => {
if (this._resources.has(el.key)) { return } // SKIP IF ALREADY LOADED
const p = new Promise((res) => {
if (el.type === 'gltfModel') {
this._loaders.gltfLoader.load(el.path, (file) => {
this.onSingleLoad(el.key, file, res)
})
} else if (el.type === 'texture') {
this._loaders.textureLoader.load(el.path, (file) => {
file.encoding = 3001
file.needsUpdate = true
this.onSingleLoad(el.key, file, res, el)
})
} else if (el.type === 'fbo') {
this._loaders.exrLoader.load(el.path, (file) => {
file.minFilter = file.magFilter = NearestFilter
file.generateMipmaps = false
file.needsUpdate = true
this.onSingleLoad(el.key, file, res, el)
})
} else if (el.type === 'envtexture') {
this._pmremGenerator.compileEquirectangularShader()
this._loaders.textureLoader.load(el.path, (file) => {
file.encoding = 3001
file.needsUpdate = true
const envMap = this._pmremGenerator.fromEquirectangular(file).texture
this.onSingleLoad(el.key, envMap, res)
})
}
})
promises.push(p)
})
return Promise.all(promises).then(() => this.onLoadComplete())
}
onSingleLoad(key, file, resolve, el) {
console.log('--- LOADED:', key)
this._loaded += 1
this._resources.set(key, file)
resolve()
}
onLoadComplete() {
this._onLoadCb()
// this._pmremGenerator.dispose()
}
}
const resources = new Resources()
export const useResource = (key, deps = []) => {
return useMemo(() => resources.get(key), deps)
}
export default resources
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment