JSFiddle - React, Tailwind, and code Playground

by Matt

HTML

<base href="https://rawcdn.githack.com/mrdoob/three.js/r154/examples/" />
<script async src="https://cdn.jsdelivr.net/npm/[email protected]/dist/es-module-shims.js"></script>
<script type="importmap">
	{
		"imports": {
			"three": "https://cdn.jsdelivr.net/npm/[email protected]/build/three.module.js",
			"three/addons/": "https://cdn.jsdelivr.net/npm/[email protected]/examples/jsm/",
			"@pixiv/three-vrm": "https://cdn.jsdelivr.net/npm/@pixiv/[email protected]/lib/three-vrm.module.min.js"
		}
	}
</script>

CSS

body {
	background-color: lightblue;
}

canvas {
	position: fixed;
	inset: 0;
}

JavaScript

import * as THREE from 'three'
import { OrbitControls } from 'three/addons/controls/OrbitControls.js'
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js'
import { VRMLoaderPlugin } from '@pixiv/three-vrm';

const VRM_URL = "https://nyc3.digitaloceanspaces.com/hallway-public/streamer/avatar/Hallway_Chan_V2.vrm"

let scene, camera, renderer
let orbitControls, clock
let currentVrm

init().then(animate)

async function init() {

	scene = new THREE.Scene()

	camera = new THREE.PerspectiveCamera(75, undefined, 0.1, 1000)
	camera.position.set(-0.5, 1.5, 1.5)
	
	clock = new THREE.Clock()

	renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true })
	renderer.outputEncoding = THREE.sRGBEncoding
	document.body.appendChild(renderer.domElement)

	orbitControls = new OrbitControls(camera, renderer.domElement)
	orbitControls.target.set(0, 1, 0)
	
	const directionalLight = new THREE.DirectionalLight()
	directionalLight.position.set(2,2,2)
	scene.add(directionalLight)
	
	const gltfLoader = new GLTFLoader()
	gltfLoader.register( ( parser ) => {
		return new VRMLoaderPlugin( parser );
	} );
	
	const gltf = await gltfLoader.loadAsync(VRM_URL)
	currentVrm = gltf.userData.vrm
	
	scene.add(gltf.scene)

	onWindowResize()
	
	window.addEventListener('resize', onWindowResize, false)
	
}

function animate() {

	const dt = clock.getDelta()

	orbitControls.update()
	
	if (currentVrm) {
		currentVrm.update(dt)
	}

	renderer.render(scene, camera)
	
	requestAnimationFrame(animate)

}


function onWindowResize() {

	camera.aspect = window.innerWidth / window.innerHeight
	camera.updateProjectionMatrix()
	renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))

	renderer.setSize(window.innerWidth, window.innerHeight)

}