Refactor renderer initialization and domElement handling in RuntimeHost

This commit is contained in:
2026-03-31 06:25:22 +02:00
parent 2667ae1349
commit 67706d4a7a

View File

@@ -29,7 +29,7 @@ const FALLBACK_FACE_COLOR = 0x747d89;
export class RuntimeHost { export class RuntimeHost {
private readonly scene = new Scene(); private readonly scene = new Scene();
private readonly camera = new PerspectiveCamera(70, 1, 0.05, 1000); private readonly camera = new PerspectiveCamera(70, 1, 0.05, 1000);
private readonly renderer = new WebGLRenderer({ antialias: true, alpha: true }); private readonly domElement: HTMLCanvasElement;
private readonly ambientLight = new AmbientLight(); private readonly ambientLight = new AmbientLight();
private readonly sunLight = new DirectionalLight(); private readonly sunLight = new DirectionalLight();
private readonly brushGroup = new Group(); private readonly brushGroup = new Group();
@@ -39,6 +39,7 @@ export class RuntimeHost {
private readonly brushMeshes = new Map<string, Mesh<BoxGeometry, MeshStandardMaterial[]>>(); private readonly brushMeshes = new Map<string, Mesh<BoxGeometry, MeshStandardMaterial[]>>();
private readonly materialTextureCache = new Map<string, CachedMaterialTexture>(); private readonly materialTextureCache = new Map<string, CachedMaterialTexture>();
private readonly controllerContext: RuntimeControllerContext; private readonly controllerContext: RuntimeControllerContext;
private readonly renderer: WebGLRenderer | null;
private resizeObserver: ResizeObserver | null = null; private resizeObserver: ResizeObserver | null = null;
private animationFrame = 0; private animationFrame = 0;
private previousFrameTime = 0; private previousFrameTime = 0;
@@ -50,16 +51,25 @@ export class RuntimeHost {
private currentRuntimeMessage: string | null = null; private currentRuntimeMessage: string | null = null;
private currentFirstPersonTelemetry: FirstPersonTelemetry | null = null; private currentFirstPersonTelemetry: FirstPersonTelemetry | null = null;
constructor() { constructor(options: { enableRendering?: boolean } = {}) {
const enableRendering = options.enableRendering ?? true;
this.scene.add(this.ambientLight); this.scene.add(this.ambientLight);
this.scene.add(this.sunLight); this.scene.add(this.sunLight);
this.scene.add(this.brushGroup); this.scene.add(this.brushGroup);
this.renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2)); this.renderer = enableRendering ? new WebGLRenderer({ antialias: true, alpha: true }) : null;
this.renderer.setClearAlpha(0); this.domElement = this.renderer?.domElement ?? document.createElement("canvas");
if (this.renderer !== null) {
this.renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
this.renderer.setClearAlpha(0);
} else {
this.domElement.className = "runner-canvas__surface";
}
this.controllerContext = { this.controllerContext = {
camera: this.camera, camera: this.camera,
domElement: this.renderer.domElement, domElement: this.domElement,
getRuntimeScene: () => { getRuntimeScene: () => {
if (this.runtimeScene === null) { if (this.runtimeScene === null) {
throw new Error("Runtime scene has not been loaded."); throw new Error("Runtime scene has not been loaded.");
@@ -84,7 +94,7 @@ export class RuntimeHost {
mount(container: HTMLElement) { mount(container: HTMLElement) {
this.container = container; this.container = container;
container.appendChild(this.renderer.domElement); container.appendChild(this.domElement);
this.resize(); this.resize();
this.resizeObserver = new ResizeObserver(() => { this.resizeObserver = new ResizeObserver(() => {
@@ -149,10 +159,10 @@ export class RuntimeHost {
} }
this.materialTextureCache.clear(); this.materialTextureCache.clear();
this.renderer.dispose(); this.renderer?.dispose();
if (this.container !== null && this.container.contains(this.renderer.domElement)) { if (this.container !== null && this.container.contains(this.domElement)) {
this.container.removeChild(this.renderer.domElement); this.container.removeChild(this.domElement);
} }
this.container = null; this.container = null;
@@ -260,7 +270,9 @@ export class RuntimeHost {
this.camera.aspect = width / height; this.camera.aspect = width / height;
this.camera.updateProjectionMatrix(); this.camera.updateProjectionMatrix();
this.renderer.setSize(width, height, false); this.domElement.width = width;
this.domElement.height = height;
this.renderer?.setSize(width, height, false);
} }
private render = () => { private render = () => {
@@ -283,7 +295,7 @@ export class RuntimeHost {
}); });
} }
this.renderer.render(this.scene, this.camera); this.renderer?.render(this.scene, this.camera);
}; };
private applyTeleportPlayerAction(target: RuntimeTeleportTarget) { private applyTeleportPlayerAction(target: RuntimeTeleportTarget) {