@threlte/extras
<BakeShadows>
<BakeShadows>
instantly freezes all shadow maps upon mounting and unfreezes them upon unmounting. This improves performance by making all shadows static. Use <BakeShadows
if you have a complex but static scene as the shadows will only be calculated once.
<script lang="ts">
import Scene from './Scene.svelte'
import { Canvas } from '@threlte/core'
import { Checkbox, Pane } from 'svelte-tweakpane-ui'
let bake = $state(false)
</script>
<Pane
title="BakeShadows"
position="fixed"
>
<Checkbox
bind:value={bake}
label="bake shadows"
/>
</Pane>
<div>
<Canvas>
<Scene {bake} />
</Canvas>
</div>
<style>
div {
height: 100%;
}
</style>
<script lang="ts">
import { BakeShadows } from '@threlte/extras'
import { T, useTask } from '@threlte/core'
type Props = {
bake: boolean
}
let { bake }: Props = $props()
let rotation = $state(0)
useTask((delta) => {
rotation += delta
})
</script>
<T.PerspectiveCamera
makeDefault
position={[10, 10, 10]}
oncreate={(ref) => {
ref.lookAt(0, 1, 0)
}}
/>
<T.DirectionalLight
position={[0, 10, 10]}
castShadow
/>
<T.Mesh
castShadow
position.y={1}
rotation.y={rotation}
>
<T.BoxGeometry args={[1, 2, 1]} />
<T.MeshStandardMaterial color="hotpink" />
</T.Mesh>
<T.Mesh
receiveShadow
rotation.x={-1 * 0.5 * Math.PI}
>
<T.CircleGeometry args={[4, 40]} />
<T.MeshStandardMaterial color="white" />
</T.Mesh>
{#if bake}
<BakeShadows />
{/if}
When <BakeShadows>
is used within a <Suspense>
, shadows will be frozen after the boundary is no longer in a suspended state. It will unfreeze if the boundary is re-suspended.
<script lang="ts">
import Scene from './Scene.svelte'
import { Canvas } from '@threlte/core'
let bake = $state(false)
</script>
<div>
<Canvas>
<Scene {bake} />
</Canvas>
</div>
<style>
div {
height: 100%;
}
</style>
<script lang="ts">
import Spaceship from './Spaceship.svelte'
import type { SpaceshipProps } from './Spaceship.svelte'
import { BakeShadows, OrbitControls, Portal, Suspense } from '@threlte/extras'
import { Color } from 'three'
import { T, useThrelte } from '@threlte/core'
const { size, scene } = useThrelte()
scene.background = new Color('black')
let zoom = $derived($size.width / 50)
type Ship = Required<Pick<SpaceshipProps, 'name' | 'position'>>
const ships: Ship[] = [
{ name: 'Bob', position: [-12, 0, 3] },
{ name: 'Challenger', position: [10, 5, 6] },
{ name: 'Dispatcher', position: [8, 3, -23] },
{ name: 'Executioner', position: [12, -4, 6] },
{ name: 'Imperial', position: [-1, 0, -21] },
{ name: 'Insurgent', position: [-13, 1, -21] },
{ name: 'Omen', position: [-9, -5, 13] },
{ name: 'Pancake', position: [-9, -3, -9] },
{ name: 'Spitfire', position: [1, 0, 1] },
{ name: 'Striker', position: [8, -1, -10] },
{ name: 'Zenith', position: [-1, 0, 13] }
]
</script>
<T.OrthographicCamera
position={[-40, 25, 40]}
makeDefault
{zoom}
oncreate={(ref) => {
ref.lookAt(0, 0, -8)
}}
>
<OrbitControls />
</T.OrthographicCamera>
<T.SpotLight
position={[0, 25, 0]}
castShadow
intensity={1000}
angle={Math.PI / 3}
/>
<Suspense final>
{#each ships as { name, position }}
<Spaceship
{name}
{position}
/>
{/each}
<BakeShadows />
</Suspense>
<T.Mesh
receiveShadow
position.y={-10}
rotation.x={-1 * 0.5 * Math.PI}
>
<T.CircleGeometry args={[100]} />
<T.MeshStandardMaterial color="white" />
</T.Mesh>
<script lang="ts">
import type { SpaceshipProps } from './Spaceship.svelte'
import { T } from '@threlte/core'
import { useGltf, useSuspense } from '@threlte/extras'
let { name, ...props }: SpaceshipProps = $props()
const suspend = useSuspense()
let gltf = $derived(suspend(useGltf(`/models/spaceships/${name}.gltf`)))
</script>
{#await gltf then { scene }}
<T.Group {...props}>
<T
is={scene}
oncreate={(ref) => {
for (const child of ref.children) {
child.castShadow = true
child.receiveShadow = true
}
}}
/>
</T.Group>
{/await}
import type { Props } from '@threlte/core'
import type { SvelteComponent } from 'svelte'
import type { Group } from 'three'
export type SpaceshipProps = Props<Group> & {
name:
| 'Bob'
| 'Challenger'
| 'Dispatcher'
| 'Executioner'
| 'Imperial'
| 'Insurgent'
| 'Omen'
| 'Pancake'
| 'Spitfire'
| 'Striker'
| 'Zenith'
}
export default class Spaceship extends SvelteComponent<SpaceshipProps> {}
The example above is an ideal scene for <BakeShadows>
because all objects are stationary and the shadows will never change.