@threlte/extras
<Sky>
This component adds a Three.js Sky
object to the scene, renders that on-demand to a cubemap which is assigned to the default scene as the environment map.
<script lang="ts">
import Scene from './Scene.svelte'
import type { Preset } from './presets'
import { Canvas } from '@threlte/core'
import { Pane, Slider, Checkbox, Button, Folder } from 'svelte-tweakpane-ui'
import { Sky } from '@threlte/extras'
import { Spring } from 'svelte/motion'
import { presets } from './presets'
const entries = Object.entries(presets)
const presetSpring = new Spring(presets.sunset, {
damping: 0.95,
precision: 0.0001,
stiffness: 0.05
})
let setEnvironment = $state(true)
let azimuth = $state(0)
let elevation = $state(0)
let exposure = $state(0)
let mieCoefficient = $state(0)
let mieDirectionalG = $state(0)
let rayleigh = $state(0)
let turbidity = $state(0)
const applyPreset = (preset: Preset) => {
azimuth = preset.azimuth
elevation = preset.elevation
exposure = preset.exposure
mieCoefficient = preset.mieCoefficient
mieDirectionalG = preset.mieDirectionalG
rayleigh = preset.rayleigh
turbidity = preset.turbidity
}
applyPreset(presets.sunset)
$effect(() => {
presetSpring.set({
azimuth,
elevation,
exposure,
mieCoefficient,
mieDirectionalG,
rayleigh,
turbidity
})
})
</script>
<Pane
title="Sky"
position="fixed"
>
<Checkbox
bind:value={setEnvironment}
label="Set Environment"
/>
<Slider
label="Turbidity"
bind:value={turbidity}
min={0}
max={20}
/>
<Slider
label="Rayleigh"
bind:value={rayleigh}
min={0}
max={4}
/>
<Slider
label="Azimuth"
bind:value={azimuth}
min={-180}
max={180}
/>
<Slider
label="Elevation"
bind:value={elevation}
min={-5}
max={90}
/>
<Slider
label="Mie Coefficient"
bind:value={mieCoefficient}
min={0}
max={0.1}
/>
<Slider
label="Mie Directional G"
bind:value={mieDirectionalG}
min={0}
max={1}
/>
<Slider
label="Exposure"
bind:value={exposure}
min={0}
max={2}
/>
<Folder title="Presets">
{#each entries as [title, preset]}
<Button
{title}
on:click={() => {
applyPreset(preset)
}}
/>
{/each}
</Folder>
</Pane>
<Canvas>
<Sky
{setEnvironment}
{...presetSpring.current}
/>
<Scene exposure={presetSpring.current.exposure} />
</Canvas>
<script lang="ts">
import { DEG2RAD } from 'three/src/math/MathUtils.js'
import { Grid, OrbitControls } from '@threlte/extras'
import { SphereGeometry } from 'three'
import { T, useThrelte } from '@threlte/core'
let {
exposure = 1
}: {
exposure?: number
} = $props()
const { renderer, invalidate } = useThrelte()
$effect(() => {
renderer.toneMappingExposure = exposure
invalidate()
})
const sphereGeo = new SphereGeometry(2.5, 32, 32)
</script>
<T.PerspectiveCamera
position={[0, 7, 18]}
fov={60}
near={1}
far={20000}
makeDefault
>
<OrbitControls
maxPolarAngle={85 * DEG2RAD}
enableDamping
target={[0, 2.5, 0]}
/>
</T.PerspectiveCamera>
<T.Mesh
castShadow
position.x={3}
position.y={2.5}
>
<T is={sphereGeo} />
<T.MeshStandardMaterial
roughness={0.1}
metalness={1}
/>
</T.Mesh>
<T.Mesh
castShadow
position.x={-3}
position.y={2.5}
>
<T is={sphereGeo} />
<T.MeshStandardMaterial />
</T.Mesh>
<Grid
cellColor="white"
sectionColor="white"
/>
export type Preset = {
azimuth: number
elevation: number
exposure: number
mieCoefficient: number
mieDirectionalG: number
rayleigh: number
turbidity: number
}
export const presets: Record<'afternoon' | 'noon' | 'sunset' | 'night', Preset> = {
afternoon: {
azimuth: 180,
elevation: 30,
exposure: 0.65,
mieCoefficient: 0.002,
mieDirectionalG: 0.86,
rayleigh: 0.3,
turbidity: 4.78
},
night: {
azimuth: 180,
elevation: -5,
exposure: 0.26,
mieCoefficient: 0.038,
mieDirectionalG: 0,
rayleigh: 0.57,
turbidity: 20
},
noon: {
azimuth: 180,
elevation: 85,
exposure: 1,
mieCoefficient: 0.013,
mieDirectionalG: 0.7,
rayleigh: 0.17,
turbidity: 0.65
},
sunset: {
azimuth: 180,
elevation: 0.5,
exposure: 0.37,
mieCoefficient: 0.005,
mieDirectionalG: 0.7,
rayleigh: 3,
turbidity: 10
}
}
Usage
<script lang="ts">
import { T, Canvas } from '@threlte/core'
import { Sky } from '@threlte/extras'
</script>
<Canvas>
<Sky elevation={0.5} />
<T.PerspectiveCamera
makeDefault
position={[0, 3, 18]}
fov={60}
oncreate={(ref) => {
ref.lookAt(0, 0, 0)
}}
/>
</Canvas>
Environment
By default, this component will render the sky to the scene environment. This can be disabled by setting the setEnvironment
prop to false
.
<Sky setEnvironment={false} />
Performance
The <Sky>
component will only re-render the cubemap when the properties change.