import { Scene, PerspectiveCamera, WebGLRenderer, DirectionalLight, AmbientLight, Mesh, Clock, BoxGeometry, MeshToonMaterial, } from 'three'; export class Renderer { public scene!: Scene; public camera!: PerspectiveCamera; public renderer!: WebGLRenderer; public sun!: DirectionalLight; public ambient!: AmbientLight; public ground!: Mesh; private clock = new Clock(); private _updateFn?: (dt: number) => void; constructor() {} get canvas() { return this.renderer.domElement; } initialize() { this.scene = new Scene(); this.camera = new PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000, ); this.renderer = new WebGLRenderer(); this.renderer.setSize(window.innerWidth, window.innerHeight); document.body.appendChild(this.renderer.domElement); this.renderer.setClearColor(0x00ddff); this.sun = new DirectionalLight(0xffffff); this.sun.position.set(10, 10, 0); this.scene.add(this.sun); this.ambient = new AmbientLight(0xffffff, 0.5); this.scene.add(this.ambient); this.ground = new Mesh( new BoxGeometry(100, 1, 100, 10, 1, 10), new MeshToonMaterial({ color: 0x32a852 }), ); this.ground.position.set(0, -0.5, 0); this.scene.add(this.ground); this.camera.position.set(0, 4, 4); window.addEventListener('resize', () => { this.renderer.setSize(window.innerWidth, window.innerHeight); this.camera.aspect = window.innerWidth / window.innerHeight; this.camera.updateProjectionMatrix(); }); this.render(); } render() { requestAnimationFrame(() => this.render()); const delta = this.clock.getDelta(); if (this._updateFn) { this._updateFn(delta); } this.renderer.render(this.scene, this.camera); } public registerUpdateFunction(fn: (dt: number) => void) { this._updateFn = fn; } }