1
0
mirror of https://github.com/misskey-dev/misskey.git synced 2026-05-28 07:44:26 +02:00
This commit is contained in:
syuilo
2026-04-24 13:26:38 +09:00
parent 7ddcbf5e94
commit 35f6cac9f6
3 changed files with 43 additions and 13 deletions

View File

@@ -94,6 +94,16 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkButton danger @click="revert">戻す</MkButton> <MkButton danger @click="revert">戻す</MkButton>
<MkButton primary @click="save">保存</MkButton> <MkButton primary @click="save">保存</MkButton>
</div> </div>
<MkSelect
:modelValue="graphicsQuality" :items="[
{ label: 'High', value: 'high' },
{ label: 'Medium', value: 'medium' },
{ label: 'Low', value: 'low' },
]" @update:modelValue="v => graphicsQuality = v"
>
<template #label>Graphics quality</template>
</MkSelect>
<MkButton danger @click="reload">reload</MkButton>
</template> </template>
</div> </div>
</template> </template>
@@ -130,6 +140,7 @@ function resize() {
const isZenMode = ref(false); const isZenMode = ref(false);
const isRoomSettingsOpen = ref(false); const isRoomSettingsOpen = ref(false);
const isChanged = ref(false); const isChanged = ref(false);
const graphicsQuality = ref<'low' | 'medium' | 'high'>('medium');
const data = localStorage.getItem('roomData') != null ? JSON.parse(localStorage.getItem('roomData')!) : { const data = localStorage.getItem('roomData') != null ? JSON.parse(localStorage.getItem('roomData')!) : {
heya: { heya: {
@@ -166,14 +177,14 @@ const data = localStorage.getItem('roomData') != null ? JSON.parse(localStorage.
installedObjects: [], installedObjects: [],
}; };
console.log(data);
let latestData = deepClone(data); let latestData = deepClone(data);
const controller = new RoomController(data); const controller = new RoomController(data);
onMounted(async () => { onMounted(async () => {
controller.init(canvas.value!); controller.init(canvas.value!, {
graphicsQuality: graphicsQuality.value,
});
canvas.value!.focus(); canvas.value!.focus();
@@ -299,6 +310,12 @@ async function revert() {
isChanged.value = false; isChanged.value = false;
} }
async function reload() {
await controller.reset(null, null, {
graphicsQuality: graphicsQuality.value,
});
}
function expor() { function expor() {
const dataStr = 'data:text/json;charset=utf-8,' + encodeURIComponent(JSON.stringify(controller.roomState.value)); const dataStr = 'data:text/json;charset=utf-8,' + encodeURIComponent(JSON.stringify(controller.roomState.value));
const dlAnchorElem = window.document.createElement('a'); const dlAnchorElem = window.document.createElement('a');

View File

@@ -13,11 +13,17 @@ import type { RoomState } from './engine.js';
import type { ObjectDef, RoomStateObject } from './object.js'; import type { ObjectDef, RoomStateObject } from './object.js';
import * as sound from '@/utility/sound.js'; import * as sound from '@/utility/sound.js';
type Options = {
workerMode?: boolean;
graphicsQuality?: 'low' | 'medium' | 'high';
};
// 抽象化レイヤー // 抽象化レイヤー
export class RoomController { export class RoomController {
private worker: Worker | null = null; private worker: Worker | null = null;
private engine: RoomEngine | null = null; private engine: RoomEngine | null = null;
private canvas: HTMLCanvasElement | null = null; private canvas: HTMLCanvasElement | null = null;
private options: Options = {};
private isCanvasDragging = false; private isCanvasDragging = false;
public isReady = ref(false); public isReady = ref(false);
public isSitting = ref(false); public isSitting = ref(false);
@@ -44,21 +50,23 @@ export class RoomController {
this.onCanvasClick = this.onCanvasClick.bind(this); this.onCanvasClick = this.onCanvasClick.bind(this);
} }
public async init(canvas: HTMLCanvasElement, workerMode = false) { public async init(canvas: HTMLCanvasElement, options: Options = {}) {
this.canvas = canvas; this.canvas = canvas;
this.canvas.width = canvas.clientWidth; this.canvas.width = canvas.clientWidth;
this.canvas.height = canvas.clientHeight; this.canvas.height = canvas.clientHeight;
this.options = options;
if (workerMode) { if (options.workerMode) {
const offscreen = canvas.transferControlToOffscreen(); const offscreen = canvas.transferControlToOffscreen();
this.worker = new RoomWorker(); this.worker = new RoomWorker();
this.worker.postMessage({ type: 'init', canvas: offscreen, roomState: this.roomState.value }, [offscreen]); this.worker.postMessage({ type: 'init', canvas: offscreen, roomState: this.roomState.value, graphicsQuality: options.graphicsQuality }, [offscreen]);
this.isReady.value = true; this.isReady.value = true;
} else { } else {
const babylonEngine = new BABYLON.WebGPUEngine(canvas, { doNotHandleContextLost: true }); const babylonEngine = new BABYLON.WebGPUEngine(canvas, { doNotHandleContextLost: true });
babylonEngine.compatibilityMode = false; babylonEngine.compatibilityMode = false;
await babylonEngine.initAsync(); await babylonEngine.initAsync();
this.engine = new RoomEngine(this.roomState.value, { canvas, engine: babylonEngine });
this.engine = new RoomEngine(this.roomState.value, { canvas, engine: babylonEngine, graphicsQuality: options.graphicsQuality });
this.engine.on('loadingProgress', ({ progress }) => { this.engine.on('loadingProgress', ({ progress }) => {
this.initializeProgress.value = progress; this.initializeProgress.value = progress;
}); });
@@ -163,16 +171,16 @@ export class RoomController {
return false; return false;
} }
public async reset(roomState: RoomState, canvas?: HTMLCanvasElement, workerMode = false) { public async reset(roomState?: RoomState, canvas?: HTMLCanvasElement, options: Options = {}) {
this.destroy(); this.destroy();
this.roomState.value = roomState; if (roomState != null) this.roomState.value = roomState;
this.isReady.value = false; this.isReady.value = false;
this.isSitting.value = false; this.isSitting.value = false;
this.isEditMode.value = false; this.isEditMode.value = false;
this.grabbing.value = null; this.grabbing.value = null;
this.selected.value = null; this.selected.value = null;
this.initializeProgress.value = 0; this.initializeProgress.value = 0;
await this.init(canvas ?? this.canvas!, workerMode); await this.init(canvas ?? this.canvas!, options ?? this.options);
} }
public pauseRender() { public pauseRender() {

View File

@@ -26,7 +26,6 @@ import { deepClone } from '@/utility/clone.js';
const BAKE_TRANSFORM = false; // 実験的 const BAKE_TRANSFORM = false; // 実験的
const SNAPSHOT_RENDERING = true; // 実験的 const SNAPSHOT_RENDERING = true; // 実験的
const IGNORE_OBJECTS: string[] = []; // for debug const IGNORE_OBJECTS: string[] = []; // for debug
const USE_GLOW = true; // ドローコールが増えて重い
const RENDER_OUTDOOR_ENV = false; const RENDER_OUTDOOR_ENV = false;
const IN_WEB_WORKER = typeof window === 'undefined'; const IN_WEB_WORKER = typeof window === 'undefined';
@@ -117,6 +116,7 @@ export type RoomEngineEvents = {
}; };
export class RoomEngine extends EventEmitter<RoomEngineEvents> { export class RoomEngine extends EventEmitter<RoomEngineEvents> {
private useGlow: boolean;
private canvas: HTMLCanvasElement; private canvas: HTMLCanvasElement;
private engine: BABYLON.WebGPUEngine; private engine: BABYLON.WebGPUEngine;
public scene: BABYLON.Scene; public scene: BABYLON.Scene;
@@ -218,6 +218,7 @@ export class RoomEngine extends EventEmitter<RoomEngineEvents> {
constructor(roomState: RoomState, options: { constructor(roomState: RoomState, options: {
canvas: HTMLCanvasElement; canvas: HTMLCanvasElement;
engine: BABYLON.WebGPUEngine; engine: BABYLON.WebGPUEngine;
graphicsQuality?: 'low' | 'medium' | 'high';
}) { }) {
super(); super();
@@ -230,9 +231,13 @@ export class RoomEngine extends EventEmitter<RoomEngineEvents> {
}; };
this.canvas = options.canvas; this.canvas = options.canvas;
this.fps = options.graphicsQuality === 'low' || options.graphicsQuality === 'medium' ? 30 : null;
this.useGlow = options.graphicsQuality !== 'low';
registerBuiltInLoaders(); registerBuiltInLoaders();
this.engine = options.engine; this.engine = options.engine;
if (options.graphicsQuality === 'low') this.engine.setHardwareScalingLevel(2);
this.scene = new BABYLON.Scene(this.engine); this.scene = new BABYLON.Scene(this.engine);
// なんかレンダリングがおかしくなるときがあるのでコメントアウト // なんかレンダリングがおかしくなるときがあるのでコメントアウト
// オブジェクトを選択し、後ろを向いて別のオブジェクトを選択した後、最初のオブジェクトに振り返ると消えているなど // オブジェクトを選択し、後ろを向いて別のオブジェクトを選択した後、最初のオブジェクトに振り返ると消えているなど
@@ -350,7 +355,7 @@ export class RoomEngine extends EventEmitter<RoomEngineEvents> {
this.turnOnRoomLight(true); this.turnOnRoomLight(true);
if (USE_GLOW) { if (this.useGlow) {
this.gl = new BABYLON.GlowLayer('glow', this.scene, { this.gl = new BABYLON.GlowLayer('glow', this.scene, {
//mainTextureFixedSize: 512, //mainTextureFixedSize: 512,
blurKernelSize: 64, blurKernelSize: 64,
@@ -407,7 +412,7 @@ export class RoomEngine extends EventEmitter<RoomEngineEvents> {
if (_DEV_) { if (_DEV_) {
// snapshot renderingかつglow layerが有効だとなんかクラッシュする // snapshot renderingかつglow layerが有効だとなんかクラッシュする
if (!(SNAPSHOT_RENDERING && USE_GLOW)) { if (!(SNAPSHOT_RENDERING && this.useGlow)) {
const axes = new AxesViewer(this.scene, 30); const axes = new AxesViewer(this.scene, 30);
axes.xAxis.position = new BABYLON.Vector3(0, 30, 0); axes.xAxis.position = new BABYLON.Vector3(0, 30, 0);
axes.yAxis.position = new BABYLON.Vector3(0, 30, 0); axes.yAxis.position = new BABYLON.Vector3(0, 30, 0);