diff --git a/packages/frontend/src/pages/room.vue b/packages/frontend/src/pages/room.vue index dcf6be4859..97ac733dd7 100644 --- a/packages/frontend/src/pages/room.vue +++ b/packages/frontend/src/pages/room.vue @@ -96,13 +96,13 @@ import * as os from '@/os.js'; import { RoomController } from '@/world/room/controller.js'; import { cm, getHex, getRgb, WORLD_SCALE } from '@/world/utility.js'; import { deepClone } from '@/utility/clone.js'; -import { GRAPHICS_QUALITY_HIGH, GRAPHICS_QUALITY_LOW, GRAPHICS_QUALITY_MEDIUM } from '@/world/room/engine.js'; import { deviceKind } from '@/utility/device-kind.js'; import MkProgressBar from '@/components/MkProgressBar.vue'; import { Joystick } from '@/world/joystick.js'; import { isTouchUsing } from '@/utility/touch.js'; import { prefer } from '@/preferences.js'; import { getObjectDef } from '@/world/room/object-defs.js'; +import { GRAPHICS_QUALITY } from '@/world/room/utility.js'; const canvas = useTemplateRef('canvas'); @@ -121,7 +121,7 @@ const isRoomSettingsOpen = ref(false); const isModified = ref(false); const graphicsQualityRaw = prefer.model('world.graphicsQuality'); -const graphicsQualityAutoValue = computed(() => deviceKind !== 'desktop' ? GRAPHICS_QUALITY_LOW : GRAPHICS_QUALITY_MEDIUM); +const graphicsQualityAutoValue = computed(() => deviceKind !== 'desktop' ? GRAPHICS_QUALITY.LOW : GRAPHICS_QUALITY.MEDIUM); const graphicsQuality = computed(() => graphicsQualityRaw.value ?? graphicsQualityAutoValue.value); const fpsRaw = prefer.model('world.fps'); @@ -531,17 +531,17 @@ function showOtherMenu(ev: PointerEvent) { text: i18n.ts._room.graphicsQuality, caption: graphicsQualityRaw.value == null ? i18n.ts.auto : graphicsQualityRaw.value === GRAPHICS_QUALITY_HIGH ? 'High' : graphicsQualityRaw.value === GRAPHICS_QUALITY_MEDIUM ? 'Medium' : 'Low', options: [{ - label: `${i18n.ts.auto} (${graphicsQualityAutoValue.value === GRAPHICS_QUALITY_HIGH ? 'High' : graphicsQualityAutoValue.value === GRAPHICS_QUALITY_MEDIUM ? 'Medium' : 'Low'})`, + label: `${i18n.ts.auto} (${graphicsQualityAutoValue.value === GRAPHICS_QUALITY.HIGH ? 'High' : graphicsQualityAutoValue.value === GRAPHICS_QUALITY.MEDIUM ? 'Medium' : 'Low'})`, value: null, }, { type: 'divider' }, { label: 'High', - value: GRAPHICS_QUALITY_HIGH, + value: GRAPHICS_QUALITY.HIGH, }, { label: 'Medium', - value: GRAPHICS_QUALITY_MEDIUM, + value: GRAPHICS_QUALITY.MEDIUM, }, { label: 'Low', - value: GRAPHICS_QUALITY_LOW, + value: GRAPHICS_QUALITY.LOW, }], ref: graphicsQualityRaw, }, { diff --git a/packages/frontend/src/world/room/controller.ts b/packages/frontend/src/world/room/controller.ts index e5c7ff50f4..5982acb64e 100644 --- a/packages/frontend/src/world/room/controller.ts +++ b/packages/frontend/src/world/room/controller.ts @@ -8,7 +8,7 @@ import * as BABYLON from '@babylonjs/core'; import { EventEmitter } from 'eventemitter3'; import { cm } from '../utility.js'; import RoomWorker from './worker?worker'; -import { GRAPHICS_QUALITY_MEDIUM, RoomEngine } from './engine.js'; +import { RoomEngine } from './engine.js'; import type { ShallowRef } from 'vue'; import type { RoomEngineEvents, RoomState } from './engine.js'; import type { ObjectDef, RoomStateObject } from './object.js'; diff --git a/packages/frontend/src/world/room/engine.ts b/packages/frontend/src/world/room/engine.ts index d34c67baf4..be4d3a9b4c 100644 --- a/packages/frontend/src/world/room/engine.ts +++ b/packages/frontend/src/world/room/engine.ts @@ -17,7 +17,7 @@ import { registerBuiltInLoaders } from '@babylonjs/loaders/dynamic'; import { EventEmitter } from 'eventemitter3'; import { TIME_MAP, scaleMorph, camelToKebab, cm, WORLD_SCALE, getMeshesBoundingBox, Timer, getYRotationDirection, FreeCameraManualInput, remap } from '../utility.js'; import { getObjectDef } from './object-defs.js'; -import { findMaterial, ModelManager, SYSTEM_HEYA_MESH_NAMES, SYSTEM_MESH_NAMES } from './utility.js'; +import { findMaterial, GRAPHICS_QUALITY, ModelManager, SYSTEM_HEYA_MESH_NAMES, SYSTEM_MESH_NAMES } from './utility.js'; import { MuseumEnvManager, SimpleEnvManager } from './env.js'; import type { GridMaterial } from '@babylonjs/materials'; import type { EnvManager, JapaneseEnvOptions, SimpleEnvOptions } from './env.js'; @@ -95,10 +95,6 @@ function enableObjectCollision(meshes: BABYLON.Mesh[]) { } } -export const GRAPHICS_QUALITY_HIGH = 1; -export const GRAPHICS_QUALITY_MEDIUM = 0; -export const GRAPHICS_QUALITY_LOW = -1; - export type RoomEngineEvents = { 'changeSelectedState': (ctx: { selected: { @@ -233,7 +229,7 @@ export class RoomEngine extends EventEmitter { }; this.graphicsQuality = options.graphicsQuality; this.fps = options.fps; - this.useGlow = this.graphicsQuality >= GRAPHICS_QUALITY_MEDIUM; + this.useGlow = this.graphicsQuality >= GRAPHICS_QUALITY.MEDIUM; this.time = TIME_MAP[new Date().getHours() as keyof typeof TIME_MAP]; registerBuiltInLoaders(); @@ -278,7 +274,7 @@ export class RoomEngine extends EventEmitter { //this.scene.activeCamera = this.camera; this.lightContainer = new BABYLON.ClusteredLightContainer('clustered', [], this.scene); - this.lightContainer.maxRange = this.graphicsQuality >= GRAPHICS_QUALITY_HIGH ? cm(200) : this.graphicsQuality >= GRAPHICS_QUALITY_MEDIUM ? cm(90) : cm(30); + this.lightContainer.maxRange = this.graphicsQuality >= GRAPHICS_QUALITY.HIGH ? cm(200) : this.graphicsQuality >= GRAPHICS_QUALITY.MEDIUM ? cm(90) : cm(30); this.lightContainer.verticalTiles = 32; this.lightContainer.horizontalTiles = 32; this.lightContainer.depthSlices = 32; @@ -322,13 +318,13 @@ export class RoomEngine extends EventEmitter { this.gridPlane.isVisible = false; this.gridPlane.setEnabled(false); - if (this.graphicsQuality >= GRAPHICS_QUALITY_MEDIUM) { + if (this.graphicsQuality >= GRAPHICS_QUALITY.MEDIUM) { this.selectionOutlineLayer = new BABYLON.SelectionOutlineLayer('outliner', this.scene); this.scene.setRenderingAutoClearDepthStencil(this.selectionOutlineLayer.renderingGroupId, false); this.sr.updateMeshesForEffectLayer(this.selectionOutlineLayer); } - if (this.graphicsQuality >= GRAPHICS_QUALITY_HIGH) { + if (this.graphicsQuality >= GRAPHICS_QUALITY.HIGH) { const pipeline = new BABYLON.DefaultRenderingPipeline('default', true, this.scene); if (options.antialias) { pipeline.samples = 4; diff --git a/packages/frontend/src/world/room/env.ts b/packages/frontend/src/world/room/env.ts index a86e2b7db5..9bab8bf0d4 100644 --- a/packages/frontend/src/world/room/env.ts +++ b/packages/frontend/src/world/room/env.ts @@ -6,8 +6,7 @@ import * as BABYLON from '@babylonjs/core'; import { cm, WORLD_SCALE } from '../utility.js'; -import { findMaterial, SYSTEM_HEYA_MESH_NAMES } from './utility.js'; -import { GRAPHICS_QUALITY_MEDIUM } from './engine.js'; +import { findMaterial, GRAPHICS_QUALITY, SYSTEM_HEYA_MESH_NAMES } from './utility.js'; import type { RoomEngine } from './engine.js'; //export interface EnvManager { @@ -122,32 +121,32 @@ export class SimpleEnvManager extends EnvManager { this.roomLight.shadowMaxZ = cm(300); this.roomLight.radius = cm(30); - if (this.engine.graphicsQuality >= GRAPHICS_QUALITY_MEDIUM) { - const shadowGeneratorForRoomLight = new BABYLON.ShadowGenerator(this.engine.graphicsQuality <= GRAPHICS_QUALITY_MEDIUM ? 1024 : 2048, this.roomLight); + if (this.engine.graphicsQuality >= GRAPHICS_QUALITY.MEDIUM) { + const shadowGeneratorForRoomLight = new BABYLON.ShadowGenerator(this.engine.graphicsQuality <= GRAPHICS_QUALITY.MEDIUM ? 1024 : 2048, this.roomLight); shadowGeneratorForRoomLight.forceBackFacesOnly = true; shadowGeneratorForRoomLight.bias = 0.00001; shadowGeneratorForRoomLight.normalBias = 0.005; shadowGeneratorForRoomLight.usePercentageCloserFiltering = true; shadowGeneratorForRoomLight.filteringQuality = BABYLON.ShadowGenerator.QUALITY_HIGH; - if (this.engine.graphicsQuality <= GRAPHICS_QUALITY_MEDIUM) { + if (this.engine.graphicsQuality <= GRAPHICS_QUALITY.MEDIUM) { shadowGeneratorForRoomLight.getShadowMap().refreshRate = 60; } //this.shadowGeneratorForRoomLight.useContactHardeningShadow = true; this.shadowGenerators.push(shadowGeneratorForRoomLight); } - if (this.engine.graphicsQuality >= GRAPHICS_QUALITY_MEDIUM) { + if (this.engine.graphicsQuality >= GRAPHICS_QUALITY.MEDIUM) { this.sunLight = new BABYLON.DirectionalLight('simpleEnv:SunLight', new BABYLON.Vector3(0.2, -1, -1), this.engine.scene); this.sunLight.position = new BABYLON.Vector3(cm(-20), cm(1000), cm(1000)); this.sunLight.shadowMinZ = cm(1000); this.sunLight.shadowMaxZ = cm(2000); - const shadowGeneratorForSunLight = new BABYLON.ShadowGenerator(this.engine.graphicsQuality <= GRAPHICS_QUALITY_MEDIUM ? 1024 : 2048, this.sunLight); + const shadowGeneratorForSunLight = new BABYLON.ShadowGenerator(this.engine.graphicsQuality <= GRAPHICS_QUALITY.MEDIUM ? 1024 : 2048, this.sunLight); shadowGeneratorForSunLight.forceBackFacesOnly = true; shadowGeneratorForSunLight.bias = 0.00001; shadowGeneratorForSunLight.usePercentageCloserFiltering = true; shadowGeneratorForSunLight.usePoissonSampling = true; - if (this.engine.graphicsQuality <= GRAPHICS_QUALITY_MEDIUM) { + if (this.engine.graphicsQuality <= GRAPHICS_QUALITY.MEDIUM) { shadowGeneratorForSunLight.getShadowMap().refreshRate = 60; } this.shadowGenerators.push(shadowGeneratorForSunLight); @@ -536,14 +535,14 @@ export class MuseumEnvManager extends EnvManager { this.roomLight.shadowMaxZ = cm(500); this.roomLight.radius = cm(30); - if (this.engine.graphicsQuality >= GRAPHICS_QUALITY_MEDIUM) { - const shadowGeneratorForRoomLight = new BABYLON.ShadowGenerator(this.engine.graphicsQuality <= GRAPHICS_QUALITY_MEDIUM ? 1024 : 2048, this.roomLight); + if (this.engine.graphicsQuality >= GRAPHICS_QUALITY.MEDIUM) { + const shadowGeneratorForRoomLight = new BABYLON.ShadowGenerator(this.engine.graphicsQuality <= GRAPHICS_QUALITY.MEDIUM ? 1024 : 2048, this.roomLight); shadowGeneratorForRoomLight.forceBackFacesOnly = true; shadowGeneratorForRoomLight.bias = 0.00001; shadowGeneratorForRoomLight.normalBias = 0.005; shadowGeneratorForRoomLight.usePercentageCloserFiltering = true; shadowGeneratorForRoomLight.filteringQuality = BABYLON.ShadowGenerator.QUALITY_HIGH; - if (this.engine.graphicsQuality <= GRAPHICS_QUALITY_MEDIUM) { + if (this.engine.graphicsQuality <= GRAPHICS_QUALITY.MEDIUM) { shadowGeneratorForRoomLight.getShadowMap().refreshRate = 60; } //this.shadowGeneratorForRoomLight.useContactHardeningShadow = true; diff --git a/packages/frontend/src/world/room/objects/woodRingFloorLamp.ts b/packages/frontend/src/world/room/objects/woodRingFloorLamp.ts index dfe2e83a4e..807a972b4e 100644 --- a/packages/frontend/src/world/room/objects/woodRingFloorLamp.ts +++ b/packages/frontend/src/world/room/objects/woodRingFloorLamp.ts @@ -86,7 +86,7 @@ export const woodRingFloorLamp = defineObject({ const applyLightBrightness = () => { for (const light of lights) { light.intensity = 1 * options.lightBrightness * WORLD_SCALE * WORLD_SCALE; - light.range = cm(200) * options.lightBrightness; + light.range = cm(200); } for (const lamp of lamps) { const emissive = lamp.material as BABYLON.PBRMaterial; diff --git a/packages/frontend/src/world/room/utility.ts b/packages/frontend/src/world/room/utility.ts index ee41b3cf27..2f1e41be09 100644 --- a/packages/frontend/src/world/room/utility.ts +++ b/packages/frontend/src/world/room/utility.ts @@ -6,6 +6,12 @@ import * as BABYLON from '@babylonjs/core'; import { applyMorphTargetsToMesh, cm, getPlaneUvIndexes, Timer } from '../utility.js'; +export const GRAPHICS_QUALITY = { + HIGH: 1, + MEDIUM: 0, + LOW: -1, +} as const; + export const SYSTEM_MESH_NAMES = ['__TOP__', '__SIDE__', '__PICK__', '__COLLISION__']; export const SYSTEM_HEYA_MESH_NAMES = ['__ROOM_WALL__', '__ROOM_SIDE__', '__ROOM_FLOOR__', '__ROOM_CEILING__', '__ROOM_TOP__', '__ROOM_BOTTOM__', '__COLLISION__']; diff --git a/packages/frontend/src/world/room/worker.ts b/packages/frontend/src/world/room/worker.ts index 3f20edc6fa..7fcaad4155 100644 --- a/packages/frontend/src/world/room/worker.ts +++ b/packages/frontend/src/world/room/worker.ts @@ -4,7 +4,7 @@ */ import * as BABYLON from '@babylonjs/core'; -import { GRAPHICS_QUALITY_MEDIUM, RoomEngine } from './engine.js'; +import { RoomEngine } from './engine.js'; import type { RoomState } from './engine.js'; let engine: RoomEngine | null = null;