3D
FrameScript には WebGL 用のヘルパーと、Three.js の描画を扱うキャンバスが用意されています。 context lost からの復旧も組み込まれており、レンダー時は復旧が完了するまで待機します。
WebGL ヘルパー
useWebGLContextが WebGL を初期化し、webglcontextlostからの復旧を行います。useWebGLFrameWaiterがヘッドレスレンダー時に GPU 完了待ちを入れます。
import { useRef } from "react"
import { useWebGLContext, useWebGLFrameWaiter } from "../src/lib/webgl"
const Canvas = () => {
const canvasRef = useRef<HTMLCanvasElement | null>(null)
const { glRef } = useWebGLContext(canvasRef, ({ gl }) => {
// シェーダやバッファを初期化
return () => {
// リソースの破棄
}
})
useWebGLFrameWaiter(glRef)
return <canvas ref={canvasRef} />
}
ThreeCanvas
<ThreeCanvas /> は useAnimation と組み合わせて使えます。
import { useAnimation, useVariable } from "../src/lib/animation"
import { BEZIER_SMOOTH } from "../src/lib/animation/functions"
import { seconds } from "../src/lib/frame"
import { ThreeCanvas, THREE, disposeThreeObject } from "../src/lib/webgl/three"
const Scene = () => {
const progress = useVariable(0)
useAnimation(async (ctx) => {
await ctx.move(progress).to(1, seconds(2), BEZIER_SMOOTH)
await ctx.move(progress).to(0, seconds(2), BEZIER_SMOOTH)
}, [])
return (
<ThreeCanvas
setup={({ renderer, size }) => {
renderer.outputColorSpace = THREE.SRGBColorSpace
const scene = new THREE.Scene()
const camera = new THREE.PerspectiveCamera(45, size.cssWidth / size.cssHeight, 0.1, 100)
camera.position.z = 6
const mesh = new THREE.Mesh(
new THREE.BoxGeometry(),
new THREE.MeshStandardMaterial({ color: 0x44aa88 })
)
scene.add(mesh)
const light = new THREE.DirectionalLight(0xffffff, 1)
light.position.set(2, 3, 4)
scene.add(light)
return {
scene,
camera,
update: ({ frame }) => {
const t = progress.get(frame)
mesh.position.x = (t - 0.5) * 3
mesh.rotation.y = t * Math.PI * 2
},
dispose: () => disposeThreeObject(mesh),
}
}}
/>
)
}