WebGPURenderer
This example shows how to run the experimental Three.js WebGPURenderer renderer with Threlte’s <Canvas>
.
<script lang="ts">
import { Canvas } from '@threlte/core'
import WebGPURenderer from 'three/addons/renderers/webgpu/WebGPURenderer.js'
import Scene from './Scene.svelte'
</script>
<div>
<Canvas
createRenderer={(canvas) => {
return new WebGPURenderer({
canvas,
antialias: true,
forceWebGL: false
})
}}
>
<Scene />
</Canvas>
</div>
<style>
div {
height: 100%;
}
</style>
<script lang="ts">
import { T, useTask, useThrelte, watch } from '@threlte/core'
import { OrbitControls } from '@threlte/extras'
import * as THREE from 'three'
import Stats from 'three/addons/libs/stats.module.js'
import { MeshToonNodeMaterial } from 'three/nodes'
const { scene, size, renderer, invalidate } = useThrelte()
scene.background = new THREE.Color(0xc1c1c1)
let geometries: THREE.BufferGeometry[] = [
new THREE.ConeGeometry(1.0, 2.0, 3, 1),
new THREE.BoxGeometry(2.0, 2.0, 2.0),
new THREE.PlaneGeometry(2.0, 2, 1, 1),
new THREE.CapsuleGeometry(),
new THREE.CircleGeometry(1.0, 3),
new THREE.CylinderGeometry(1.0, 1.0, 2.0, 3, 1),
new THREE.DodecahedronGeometry(1.0, 0),
new THREE.IcosahedronGeometry(1.0, 0),
new THREE.OctahedronGeometry(1.0, 0),
new THREE.PolyhedronGeometry([0, 0, 0], [0, 0, 0], 1, 0),
new THREE.RingGeometry(1.0, 1.5, 3),
new THREE.SphereGeometry(1.0, 3, 2),
new THREE.TetrahedronGeometry(1.0, 0),
new THREE.TorusGeometry(1.0, 0.5, 3, 3),
new THREE.TorusKnotGeometry(1.0, 0.5, 20, 3, 1, 1)
]
const group = new THREE.Group()
group.static = true
const position = new THREE.Vector3()
const rotation = new THREE.Euler()
const quaternion = new THREE.Quaternion()
const scale = new THREE.Vector3()
const count = 3000
function randomizeMatrix(matrix: THREE.Matrix4) {
position.x = Math.random() * 80 - 40
position.y = Math.random() * 80 - 40
position.z = Math.random() * 80 - 40
rotation.x = Math.random() * 2 * Math.PI
rotation.y = Math.random() * 2 * Math.PI
rotation.z = Math.random() * 2 * Math.PI
quaternion.setFromEuler(rotation)
const factorScale = 1
scale.x = scale.y = scale.z = 0.35 * factorScale + Math.random() * 0.5 * factorScale
return matrix.compose(position, quaternion, scale)
}
const randomizeRotationSpeed = (rotation: THREE.Euler) => {
rotation.x = Math.random() * 0.05
rotation.y = Math.random() * 0.05
rotation.z = Math.random() * 0.05
return rotation
}
for (let i = 0; i < count; i++) {
const material = new MeshToonNodeMaterial({
color: new THREE.Color(Math.random() * 0xffffff),
side: THREE.DoubleSide
})
const child = new THREE.Mesh(geometries[i % geometries.length], material)
randomizeMatrix(child.matrix)
child.matrix.decompose(child.position, child.quaternion, child.scale)
child.userData.rotationSpeed = randomizeRotationSpeed(new THREE.Euler())
child.frustumCulled = false
group.add(child)
}
watch(size, () => {
group.needsUpdate = true
})
const stats = new Stats()
renderer.domElement.parentNode?.appendChild(stats.dom)
stats.begin()
useTask(() => {
stats.end()
for (const child of group.children) {
if (!child) return
const { rotationSpeed } = child.userData
child.rotation.set(
child.rotation.x + rotationSpeed.x,
child.rotation.y + rotationSpeed.y,
child.rotation.z + rotationSpeed.z
)
}
stats.begin()
})
</script>
<T is={group} />
<T.PerspectiveCamera
position.z={50}
makeDefault
>
<OrbitControls
autoRotate
enableZoom={false}
autoRotateSpeed={1}
onchange={invalidate}
/>
</T.PerspectiveCamera>
<T.DirectionalLight
color="0xffffff"
intensity={3.4}
/>
Adapted from this Three.js example.
In a browser that supports WebGPU, such as Chrome, this example will default to the new WebGPURenderer. In other browsers, it will fallback to a WebGL Renderer.
Vite
The WebGPURenderer uses top-level async to determine WebGPU compatibility. Vite will often throw an error when it detects top level await.
To circumvent this issue, the following can be added to your Vite config.
// vite.config.js
optimizeDeps: {
esbuildOptions: {
target: 'esnext'
}
},
build: {
target: 'esnext'
}
Alternatively, vite-plugin-top-level-await
can be used, although less success has been reported with this method.