threepipe
Version:
A 3D viewer framework built on top of three.js in TypeScript with a focus on quality rendering, modularity and extensibility.
87 lines (77 loc) • 2.73 kB
text/typescript
import {
_testFinish,
IObject3D,
LinearToneMapping,
LoadingScreenPlugin,
Mesh,
PerspectiveCamera2,
PlaneGeometry,
PopmotionPlugin,
ProgressivePlugin,
Texture,
ThreeViewer,
ToneMapping,
TonemapPlugin,
UnlitMaterial,
VirtualCamerasPlugin,
} from 'threepipe'
async function init() {
const viewer = new ThreeViewer({
canvas: document.getElementById('mcanvas') as HTMLCanvasElement,
debug: true,
plugins: [new ProgressivePlugin(16), LoadingScreenPlugin],
})
const virtualCameras = viewer.addPluginSync(VirtualCamerasPlugin)
const popmotion = viewer.addPluginSync(PopmotionPlugin)
await viewer.setEnvironmentMap('https://threejs.org/examples/textures/equirectangular/venice_sunset_1k.hdr')
await viewer.load<IObject3D>('https://threejs.org/examples/models/gltf/DamagedHelmet/glTF/DamagedHelmet.gltf', {
autoCenter: true,
autoScale: true,
})
const aspect = 2
const plane = new Mesh(
new PlaneGeometry(5 * aspect, 5)
.translate(0, 0, -3),
new UnlitMaterial({
color: '#ffffff',
})
)
plane.castShadow = false
plane.receiveShadow = true
viewer.scene.addObject(plane)
const camera = new PerspectiveCamera2('', viewer.canvas, false, 45, aspect)
camera.position.set(0, 0, 5)
camera.target.set(0, 0.25, 0)
camera.userData.autoLookAtTarget = true
camera.near = 1
camera.far = 10
camera.setDirty()
const vCam = virtualCameras.addCamera(camera)
plane.material.map = vCam.target.texture as Texture
popmotion.animate({
from: 0,
to: 1,
repeat: Infinity,
duration: 6000,
onUpdate: (v)=>{
// Set camera position xz in a circle around the target
const angle = v * Math.PI * 2 + Math.PI / 2
const radius = 5
camera.position.set(Math.cos(angle) * radius, 0, Math.sin(angle) * radius)
camera.setDirty()
viewer.setDirty() // since camera is not in the scene
},
})
// We need to disable tonemapping when rendering the virtual camera, otherwise the tonemapping will be applied multiple times.
let lastTonemapping: ToneMapping = LinearToneMapping
const tonemap = viewer.getPlugin(TonemapPlugin)!
virtualCameras.addEventListener('preRenderCamera', ()=>{
lastTonemapping = tonemap.toneMapping
// Comment this and see what happens to the color in the plane
tonemap.toneMapping = LinearToneMapping
})
virtualCameras.addEventListener('postRenderCamera', ()=>{
tonemap.toneMapping = lastTonemapping
})
}
init().finally(_testFinish)