Basics
Loading Assets
Threlte works seamlessly with Three.js loaders, and provides a hook, useLoader, to help solve common loading issues. It caches results to prevent duplicate fetch/parse work and returns an async store, asyncWritable for convenient usage in Svelte.
Caching cuts network requests, bandwidth, and memory, improving app performance.
This section assumes you placed your assets in your public folder or in a place in your application where you can import them easily.
We recommend using SvelteKit’s asset function to help catch common loading problems. There are other equivalent vite plugins if your not using SvelteKit.
Models
Models come in many different formats, but .gltfs are usually the best fit
for the web. You can use Three.js’ GLTFLoader to load a .gltf model.
<script>
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'
import { useLoader } from '@threlte/core'
const gltf = useLoader(GLTFLoader).load('/assets/model.gltf')
</script>
{#if $gltf}
<T is={$gltf.scene} />
{/if}
The <GLTF/> component is roughly equivalent to
the example above.
useGltf hook
@threlte/extras provides a handy hook for loading .gltf models called
useGltf:
<script>
import { useGltf } from '@threlte/extras'
</script>
{#await useGltf('/assets/model.gltf') then gltf}
<T is={gltf.scene} />
{/await}
Adjusting and reusing models
You may run into the following challenges when working with models in Threlte:
- Your model may have multiple parts that you’d like to adjust individually but
there’s no easy way to declaritively achieve that with only one
<T/>component. - You can’t seem to place multiple copies in your scene.
To address both of these issues, you can use Threlte’s CLI tool
@threlte/gltf to generate a Svelte
component for your model. The generated component has <T/> components for all
of your models parts. Adjust the component to your liking, then
import and reuse it as much as you’d like.
Animations
Three.js uses AnimationMixer to drive animations. Threlte provides a convenient useGltfAnimations hook for gltfs. See the animation Three.js example for how to setup a model for your animation needs.
The Threlte docs also have an animation example to help you get started.
Common mistakes
Sometimes you’ll load a model and still just see a blank screen. Here are a few common mistakes that can cause this.
- Make sure your scene has lights.
- Make sure the model is not too small or not too big for your camera to see it.
- Make sure your camera is looking at the model
- Does the model render in a viewer like gltf-viewer?
Textures
The TextureLoader is another loader from Three.js that is used for textures.
<script>
import { TextureLoader } from 'three'
import { useLoader } from '@threlte/core'
const texture = useLoader(TextureLoader).load('/assets/texture.png')
</script>
{#if $texture}
<T.MeshStandardMaterial map={$texture} />
{/if}
useTexture hook
@threlte/extras provides a handy hook for loading textures called
useTexture:
<script>
import { useTexture } from '@threlte/extras'
</script>
{#await useTexture('/assets/texture.png') then texture}
<T.MeshStandardMaterial map={texture} />
{/await}
Multiple textures
Sometimes you’ll want your materials to be composed of multiple textures.
useLoader provides a way to load multiple textures at once and
spread the loaded textures on
a material.
Loading two textures for the map and normalMap channels can be done like
this:
const textures = useLoader(TextureLoader).load({
map: '/assets/texture.png',
normalMap: '/assets/normal.png'
})
or with the useTexture hook:
const textures = useTexture({
map: '/assets/texture.png',
normalMap: '/assets/normal.png'
})
Then spread on a material:
{#if $textures}
<T.MeshStandardMaterial {...$textures} />
{/if}
If multiple textures are given, the promise only resolves once all textures have loaded.
Applying multiple textures to different mesh faces
To declaratively apply different textures to multiple faces of a BoxGeometry,
set the attach prop to a function.
<T.Mesh>
<T.BoxGeometry />
<T.MeshStandardMaterial
map={texture1}
attach={({ parent, ref }) => {
if (Array.isArray(parent.material)) {
parent.material = [...parent.material, ref]
} else {
parent.material = [ref]
}
}}
/>
<T.MeshStandardMaterial
map={texture2}
attach={({ parent, ref }) => {
if (Array.isArray(parent.material)) {
parent.material = [...parent.material, ref]
} else {
parent.material = [ref]
}
}}
/>
</T.Mesh>
Other asset types
Threlte provides many components to help get started with many other asset types (like audio), but it doesn’t have components and hooks for all of them. Checkout Three.js examples to see what models, techniques and effects you can achieve, then use those examples as a guide for your own custom components.
Async loading
The return value from useLoader is an
AsyncWritable custom store. Its value will be undefined until the asset has
loaded.
Since the underlying store’s value is a promise, you can use it within a Svelte
#await block:
{#await $texture then value}
<T.MeshStandardMaterial map={value} />
{/await}
Assets can also be loaded after initialization by calling the loader.load
method:
<script>
import { AudioLoader } from 'three'
import { useLoader } from '@threlte/core'
// Instantiate the loader at component initialization
const loader = useLoader(AudioLoader)
const onSomeEvent = async () => {
// Load the asset when needed
const audioBuffer = await loader.load('/assets/sound.mp3')
}
</script>
The Suspense component can additionally help orchestrate loading multiple assets before displaying your scene.
Context Awareness
The useLoader hook, and other hooks like useTexture, use Svelte contexts.
The assets loaded with them are only available for child components of your
<Canvas> component.