LOD
This is a practical example showing a best-practice method of implementing LOD in Threlte. The example is a great demonstration of the power of ref bindings.
This is an adaption of Three.js own documentation, and therefore it’s also a great way to learn how to translate what you already know how to do with imperative three.js, into declerative Threlte code.
<script lang="ts">
import { Canvas } from '@threlte/core'
import Scene from './Scene.svelte'
import { Pane, Button } from 'svelte-tweakpane-ui'
let reset: () => any | undefined
</script>
<Pane
title="LOD"
position="fixed"
>
<Button
title="Reset Camera"
on:click={reset}
/>
</Pane>
<div>
<Canvas>
<Scene bind:reset />
</Canvas>
</div>
<style>
div {
position: relative;
height: 100%;
width: 100%;
}
</style>
<script>
import { T, useThrelte } from '@threlte/core'
import { OrbitControls } from '@threlte/extras'
let controls
export const reset = () => controls.reset()
</script>
<T.PerspectiveCamera
makeDefault
position={[0, 0, 25]}
lookAt.y={0}
>
<OrbitControls
enableZoom={true}
bind:ref={controls}
/>
</T.PerspectiveCamera>
<T.DirectionalLight position={[3, 10, 10]} />
<T.HemisphereLight intensity={0.2} />
<T.LOD let:ref={lod}>
{#each ['red', 'green', 'blue'] as color, i}
<T.Group
on:create={({ ref }) => {
lod.addLevel(ref, i * 75)
}}
>
<T.Mesh>
<T.IcosahedronGeometry args={[10, 3 - i]} />
<T.MeshStandardMaterial
{color}
wireframe
/>
</T.Mesh>
<T.Mesh>
<T.IcosahedronGeometry args={[10, 3 - i]} />
<T.MeshStandardMaterial
{color}
transparent
opacity={0.3}
/>
</T.Mesh>
</T.Group>
{/each}
</T.LOD>
How does it work
- First
<T>
creates the geometry and material - Then it attaches those to the mesh
on:create
will run later, but we remember to use a reference to the mesh itselfref
and a referencelod
to the parent LOD object.
… which happens 3 times due to the #each
block
<T.LOD let:ref={lod}>
{#each ['red', 'green', 'blue'] as color, i}
<T.Mesh
on:create={({ ref }) => {
lod.addLevel(ref, i * 75) // i * 75 = distance
}}
>
<T.IcosahedronGeometry args={[10, 3 - i]} />
<T.MeshStandardMaterial
{color}
wireframe
/>
</T.Mesh>
{/each}
</T.LOD>
<T>
now creates the LOD parent and internally calls the three.js functionlod.add(child)
on each mesh, since they are defined inside the<T.LOD>
object.- However, in three.js we need the
lod.addLevel(child, distance)
as well to register the children as LOD levels and not just attached children. - This is where our
on:create
function comes in - upon creation of each mesh, we are able to calllod.addLevel(child, distance)