mirror of
https://github.com/misskey-dev/misskey.git
synced 2026-06-25 17:10:43 +00:00
room light
This commit is contained in:
parent
79541bcbe3
commit
39c6baf6f2
11 changed files with 70 additions and 108 deletions
|
|
@ -1179,12 +1179,12 @@ export class RoomEngine extends EngineBase<{
|
|||
this.fixedCamera.parent = null;
|
||||
}
|
||||
|
||||
public updateRoomLightColor(color: [number, number, number]) {
|
||||
this.sr.disableSnapshotRendering();
|
||||
this.envManager.updateRoomLightColor(new BABYLON.Color3(...color));
|
||||
this.sr.enableSnapshotRendering();
|
||||
this.roomState.roomLightColor = color;
|
||||
public updateLightSettings(light: RoomState['light']) {
|
||||
this.roomState.light = light;
|
||||
this.ev('changeRoomState', { roomState: this.roomState });
|
||||
this.sr.disableSnapshotRendering();
|
||||
this.envManager.applyRoomLight();
|
||||
this.sr.enableSnapshotRendering();
|
||||
}
|
||||
|
||||
public turnOnRoomLight(forInit = false) {
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ export abstract class EnvManager<T = any> {
|
|||
public abstract envMapIndoor: BABYLON.CubeTexture | null;
|
||||
public abstract maxCameraZ: number;
|
||||
protected shadowGenerators: BABYLON.ShadowGenerator[] = [];
|
||||
protected isRoomLightOn = true;
|
||||
|
||||
constructor(engine: RoomEngine) {
|
||||
this.engine = engine;
|
||||
|
|
@ -24,9 +25,17 @@ export abstract class EnvManager<T = any> {
|
|||
abstract load(options: T, scene: BABYLON.Scene, engine: RoomEngine): Promise<void>;
|
||||
abstract applyOptions(options: T): void;
|
||||
abstract setTime(time: number): void;
|
||||
abstract updateRoomLightColor(color: BABYLON.Color3): void;
|
||||
abstract turnOnRoomLight(): void;
|
||||
abstract turnOffRoomLight(): void;
|
||||
abstract applyRoomLight(): void;
|
||||
|
||||
public turnOnRoomLight() {
|
||||
this.isRoomLightOn = true;
|
||||
this.applyRoomLight();
|
||||
}
|
||||
|
||||
public turnOffRoomLight() {
|
||||
this.isRoomLightOn = false;
|
||||
this.applyRoomLight();
|
||||
}
|
||||
|
||||
public addShadowCaster(mesh: BABYLON.AbstractMesh) {
|
||||
for (const shadowGen of this.shadowGenerators) {
|
||||
|
|
|
|||
|
|
@ -50,11 +50,12 @@ export class CustomMadoriEnvManager extends EnvManager<CustomMadoriEnvOptions> {
|
|||
|
||||
this.roomLight = new BABYLON.DirectionalLight('env:RoomLight', new BABYLON.Vector3(0, -1, 0), this.engine.scene);
|
||||
this.roomLight.position = new BABYLON.Vector3(0, cm(300), 0);
|
||||
this.roomLight.diffuse = new BABYLON.Color3(...this.engine.roomState.roomLightColor);
|
||||
this.roomLight.shadowMinZ = cm(10);
|
||||
this.roomLight.shadowMaxZ = cm(500);
|
||||
this.roomLight.radius = cm(30);
|
||||
|
||||
this.applyRoomLight();
|
||||
|
||||
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;
|
||||
|
|
@ -295,29 +296,14 @@ export class CustomMadoriEnvManager extends EnvManager<CustomMadoriEnvOptions> {
|
|||
}
|
||||
}
|
||||
|
||||
public updateRoomLightColor(color: BABYLON.Color3): void {
|
||||
public applyRoomLight(): void {
|
||||
if (this.roomLight == null) return;
|
||||
this.roomLight.diffuse = color;
|
||||
}
|
||||
|
||||
public turnOnRoomLight(): void {
|
||||
if (this.roomLight == null) return;
|
||||
this.roomLight.intensity = 0.0005 * WORLD_SCALE * WORLD_SCALE;
|
||||
if (this.envMapIndoor != null) this.envMapIndoor.level = 0.2;
|
||||
this.roomLight.diffuse = new BABYLON.Color3(...this.engine.roomState.light.color);
|
||||
this.roomLight.intensity = 0.0005 * WORLD_SCALE * WORLD_SCALE * this.engine.roomState.light.brightness * (this.isRoomLightOn ? 1 : 0);
|
||||
if (this.envMapIndoor != null) this.envMapIndoor.level = 0.025 + (0.575 * this.engine.roomState.light.brightness * (this.isRoomLightOn ? 1 : 0));
|
||||
for (const m of this.engine.scene.materials) {
|
||||
if (m.metadata?.disableEnvMap) {
|
||||
m.ambientColor = new BABYLON.Color3(0.5, 0.5, 0.5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public turnOffRoomLight(): void {
|
||||
if (this.roomLight == null) return;
|
||||
this.roomLight.intensity = 0;
|
||||
if (this.envMapIndoor != null) this.envMapIndoor.level = 0.025;
|
||||
for (const m of this.engine.scene.materials) {
|
||||
if (m.metadata?.disableEnvMap) {
|
||||
m.ambientColor = new BABYLON.Color3(0.025, 0.025, 0.025);
|
||||
m.ambientColor = this.isRoomLightOn ? new BABYLON.Color3(0.5, 0.5, 0.5) : new BABYLON.Color3(0.025, 0.025, 0.025);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import { findMaterial, GRAPHICS_QUALITY } from '../../utility.js';
|
|||
import { SYSTEM_HEYA_MESH_NAMES } from '../utility.js';
|
||||
import { EnvManager } from '../env.js';
|
||||
import type { RoomEngine } from '../engine.js';
|
||||
import type { SimpleEnvOptions, JapaneseEnvOptions } from 'misskey-world/src/room/env.js';
|
||||
import type { JapaneseEnvOptions } from 'misskey-world/src/room/env.js';
|
||||
|
||||
export class JapaneseEnvManager extends EnvManager<JapaneseEnvOptions> {
|
||||
private loaderResult: BABYLON.ISceneLoaderAsyncResult | null = null;
|
||||
|
|
@ -34,11 +34,12 @@ export class JapaneseEnvManager extends EnvManager<JapaneseEnvOptions> {
|
|||
this.skybox.infiniteDistance = true;
|
||||
|
||||
this.roomLight = new BABYLON.SpotLight('env:RoomLight', new BABYLON.Vector3(0, cm(249), 0), new BABYLON.Vector3(0, -1, 0), 16, 8, this.engine.scene);
|
||||
this.roomLight.diffuse = new BABYLON.Color3(...this.engine.roomState.roomLightColor);
|
||||
this.roomLight.shadowMinZ = cm(10);
|
||||
this.roomLight.shadowMaxZ = cm(300);
|
||||
this.roomLight.radius = cm(30);
|
||||
|
||||
this.applyRoomLight();
|
||||
|
||||
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;
|
||||
|
|
@ -127,34 +128,19 @@ export class JapaneseEnvManager extends EnvManager<JapaneseEnvOptions> {
|
|||
}
|
||||
}
|
||||
|
||||
public updateRoomLightColor(color: BABYLON.Color3): void {
|
||||
public applyRoomLight(): void {
|
||||
if (this.roomLight == null) return;
|
||||
this.roomLight.diffuse = color;
|
||||
}
|
||||
|
||||
public turnOnRoomLight(): void {
|
||||
if (this.roomLight == null) return;
|
||||
this.roomLight.intensity = 18 * WORLD_SCALE * WORLD_SCALE;
|
||||
if (this.envMapIndoor != null) this.envMapIndoor.level = 0.6;
|
||||
this.roomLight.diffuse = new BABYLON.Color3(...this.engine.roomState.light.color);
|
||||
this.roomLight.intensity = 18 * WORLD_SCALE * WORLD_SCALE * this.engine.roomState.light.brightness * (this.isRoomLightOn ? 1 : 0);
|
||||
if (this.envMapIndoor != null) this.envMapIndoor.level = 0.025 + (0.575 * this.engine.roomState.light.brightness * (this.isRoomLightOn ? 1 : 0));
|
||||
for (const m of this.engine.scene.materials) {
|
||||
if (m.metadata?.disableEnvMap) {
|
||||
m.ambientColor = new BABYLON.Color3(0.5, 0.5, 0.5);
|
||||
m.ambientColor = this.isRoomLightOn ? new BABYLON.Color3(0.5, 0.5, 0.5) : new BABYLON.Color3(0.025, 0.025, 0.025);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public turnOffRoomLight(): void {
|
||||
if (this.roomLight == null) return;
|
||||
this.roomLight.intensity = 0;
|
||||
if (this.envMapIndoor != null) this.envMapIndoor.level = 0.025;
|
||||
for (const m of this.engine.scene.materials) {
|
||||
if (m.metadata?.disableEnvMap) {
|
||||
m.ambientColor = new BABYLON.Color3(0.025, 0.025, 0.025);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public applyOptions(options: SimpleEnvOptions) {
|
||||
public applyOptions(options: JapaneseEnvOptions) {
|
||||
this.registerMeshes(this.meshes);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -56,7 +56,6 @@ export class MuseumEnvManager extends EnvManager<MuseumEnvOptions> {
|
|||
|
||||
this.roomLight = new BABYLON.DirectionalLight('env:RoomLight', new BABYLON.Vector3(0, -1, 0), this.engine.scene);
|
||||
this.roomLight.position = new BABYLON.Vector3(0, cm(300), 0);
|
||||
this.roomLight.diffuse = new BABYLON.Color3(...this.engine.roomState.roomLightColor);
|
||||
this.roomLight.shadowMinZ = cm(10);
|
||||
this.roomLight.shadowMaxZ = cm(500);
|
||||
this.roomLight.radius = cm(30);
|
||||
|
|
@ -77,7 +76,6 @@ export class MuseumEnvManager extends EnvManager<MuseumEnvOptions> {
|
|||
|
||||
for (const node of this.meshes.filter(mesh => mesh.name.includes('__LIGHT__'))) {
|
||||
const light = new BABYLON.SpotLight('env:SubRoomLight', node.position, new BABYLON.Vector3(0, -1, 0), 16, 8, this.engine.scene, true);
|
||||
light.diffuse = new BABYLON.Color3(...this.engine.roomState.roomLightColor);
|
||||
light.range = cm(500);
|
||||
light.radius = cm(15);
|
||||
light.parent = this.meshes[0];
|
||||
|
|
@ -85,6 +83,8 @@ export class MuseumEnvManager extends EnvManager<MuseumEnvOptions> {
|
|||
this.subRoomLights.push(light);
|
||||
}
|
||||
|
||||
this.applyRoomLight();
|
||||
|
||||
for (const mesh of this.meshes) {
|
||||
if (SYSTEM_HEYA_MESH_NAMES.some(name => mesh.name.includes(name))) continue;
|
||||
mesh.receiveShadows = true;
|
||||
|
|
@ -97,38 +97,18 @@ export class MuseumEnvManager extends EnvManager<MuseumEnvOptions> {
|
|||
public setTime(time: number) {
|
||||
}
|
||||
|
||||
public updateRoomLightColor(color: BABYLON.Color3): void {
|
||||
public applyRoomLight(): void {
|
||||
if (this.roomLight == null) return;
|
||||
this.roomLight.diffuse = color;
|
||||
this.roomLight.diffuse = new BABYLON.Color3(...this.engine.roomState.light.color);
|
||||
this.roomLight.intensity = 0.00005 * WORLD_SCALE * WORLD_SCALE * this.engine.roomState.light.brightness * (this.isRoomLightOn ? 1 : 0);
|
||||
for (const subLight of this.subRoomLights) {
|
||||
subLight.diffuse = color;
|
||||
subLight.diffuse = new BABYLON.Color3(...this.engine.roomState.light.color);
|
||||
subLight.intensity = 20 * WORLD_SCALE * WORLD_SCALE * this.engine.roomState.light.brightness * (this.isRoomLightOn ? 1 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
public turnOnRoomLight(): void {
|
||||
if (this.roomLight == null) return;
|
||||
this.roomLight.intensity = 0.00005 * WORLD_SCALE * WORLD_SCALE;
|
||||
for (const subLight of this.subRoomLights) {
|
||||
subLight.intensity = 20 * WORLD_SCALE * WORLD_SCALE;
|
||||
}
|
||||
if (this.envMapIndoor != null) this.envMapIndoor.level = 0.2;
|
||||
if (this.envMapIndoor != null) this.envMapIndoor.level = 0.025 + (0.175 * this.engine.roomState.light.brightness * (this.isRoomLightOn ? 1 : 0));
|
||||
for (const m of this.engine.scene.materials) {
|
||||
if (m.metadata?.disableEnvMap) {
|
||||
m.ambientColor = new BABYLON.Color3(0.5, 0.5, 0.5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public turnOffRoomLight(): void {
|
||||
if (this.roomLight == null) return;
|
||||
this.roomLight.intensity = 0;
|
||||
for (const subLight of this.subRoomLights) {
|
||||
subLight.intensity = 0;
|
||||
}
|
||||
if (this.envMapIndoor != null) this.envMapIndoor.level = 0.025;
|
||||
for (const m of this.engine.scene.materials) {
|
||||
if (m.metadata?.disableEnvMap) {
|
||||
m.ambientColor = new BABYLON.Color3(0.025, 0.025, 0.025);
|
||||
m.ambientColor = this.isRoomLightOn ? new BABYLON.Color3(0.5, 0.5, 0.5) : new BABYLON.Color3(0.025, 0.025, 0.025);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -145,11 +145,12 @@ export class SimpleEnvManager extends EnvManager<SimpleEnvOptions> {
|
|||
this.skybox.infiniteDistance = true;
|
||||
|
||||
this.roomLight = new BABYLON.SpotLight('env:RoomLight', new BABYLON.Vector3(0, cm(249), 0), new BABYLON.Vector3(0, -1, 0), 16, 8, this.engine.scene);
|
||||
this.roomLight.diffuse = new BABYLON.Color3(...this.engine.roomState.roomLightColor);
|
||||
this.roomLight.shadowMinZ = cm(10);
|
||||
this.roomLight.shadowMaxZ = cm(300);
|
||||
this.roomLight.radius = cm(30);
|
||||
|
||||
this.applyRoomLight();
|
||||
|
||||
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;
|
||||
|
|
@ -435,29 +436,14 @@ export class SimpleEnvManager extends EnvManager<SimpleEnvOptions> {
|
|||
}
|
||||
}
|
||||
|
||||
public updateRoomLightColor(color: BABYLON.Color3): void {
|
||||
public applyRoomLight(): void {
|
||||
if (this.roomLight == null) return;
|
||||
this.roomLight.diffuse = color;
|
||||
}
|
||||
|
||||
public turnOnRoomLight(): void {
|
||||
if (this.roomLight == null) return;
|
||||
this.roomLight.intensity = 18 * WORLD_SCALE * WORLD_SCALE;
|
||||
if (this.envMapIndoor != null) this.envMapIndoor.level = 0.6;
|
||||
this.roomLight.diffuse = new BABYLON.Color3(...this.engine.roomState.light.color);
|
||||
this.roomLight.intensity = 18 * WORLD_SCALE * WORLD_SCALE * this.engine.roomState.light.brightness * (this.isRoomLightOn ? 1 : 0);
|
||||
if (this.envMapIndoor != null) this.envMapIndoor.level = 0.025 + (0.575 * this.engine.roomState.light.brightness * (this.isRoomLightOn ? 1 : 0));
|
||||
for (const m of this.engine.scene.materials) {
|
||||
if (m.metadata?.disableEnvMap) {
|
||||
m.ambientColor = new BABYLON.Color3(0.5, 0.5, 0.5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public turnOffRoomLight(): void {
|
||||
if (this.roomLight == null) return;
|
||||
this.roomLight.intensity = 0;
|
||||
if (this.envMapIndoor != null) this.envMapIndoor.level = 0.025;
|
||||
for (const m of this.engine.scene.materials) {
|
||||
if (m.metadata?.disableEnvMap) {
|
||||
m.ambientColor = new BABYLON.Color3(0.025, 0.025, 0.025);
|
||||
m.ambientColor = this.isRoomLightOn ? new BABYLON.Color3(0.5, 0.5, 0.5) : new BABYLON.Color3(0.025, 0.025, 0.025);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,7 +54,10 @@ const initialRoomDef = {
|
|||
type: 'simple',
|
||||
options: getDefaultSimpleEnvOptions(),
|
||||
},
|
||||
roomLightColor: [1.0, 0.9, 0.8],
|
||||
light: {
|
||||
color: [1.0, 0.9, 0.8],
|
||||
brightness: 1,
|
||||
},
|
||||
installedFurnitures: [],
|
||||
worldScale: WORLD_SCALE,
|
||||
} satisfies RoomState;
|
||||
|
|
|
|||
|
|
@ -252,6 +252,13 @@ if (initialRoomState.installedObjects != null) {
|
|||
initialRoomState.installedFurnitures = initialRoomState.installedObjects;
|
||||
delete initialRoomState.installedObjects;
|
||||
}
|
||||
if (initialRoomState.roomLightColor != null) {
|
||||
initialRoomState.light = {
|
||||
color: initialRoomState.roomLightColor,
|
||||
brightness: 1,
|
||||
};
|
||||
delete initialRoomState.roomLightColor;
|
||||
}
|
||||
for (const obj of initialRoomState.installedFurnitures) {
|
||||
if (obj.options.customPicture != null) {
|
||||
obj.options.image = {
|
||||
|
|
|
|||
|
|
@ -18,10 +18,14 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</MkSelect>
|
||||
|
||||
<!-- debounce or throttleしないとカラーピッカー上で高速でなぞったときになぜか無限ループになる。ワーカーとの間でラグがあるため、少し前の値がまたmodelValueとしてフィードバックされてしまうためだと思われる -->
|
||||
<MkInput :modelValue="getHex(controller.roomState.value.roomLightColor)" type="color" :throttle="300" @update:modelValue="v => { const c = getRgb(v); if (c != null) controller.updateRoomLightColor(c); }">
|
||||
<MkInput :modelValue="getHex(controller.roomState.value.light.color)" type="color" :throttle="300" @update:modelValue="v => { const c = getRgb(v); if (c != null) controller.updateLightSettings({ ...controller.roomState.value.light, color: c }); }">
|
||||
<template #label>light color</template>
|
||||
</MkInput>
|
||||
|
||||
<MkRange :modelValue="controller.roomState.value.light.brightness" :min="0" :max="1" :step="0.1" continuousUpdate @update:modelValue="v => controller.updateLightSettings({ ...controller.roomState.value.light, brightness: v })">
|
||||
<template #label>light brightness</template>
|
||||
</MkRange>
|
||||
|
||||
<template v-if="controller.roomState.value.env.type === 'simple'">
|
||||
<XDefaultEnvOptions :options="controller.roomState.value.env.options" @update="v => updateEnvOptions(v)"></XDefaultEnvOptions>
|
||||
</template>
|
||||
|
|
@ -36,8 +40,6 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
import { computed, defineAsyncComponent, nextTick, onMounted, onUnmounted, ref, shallowRef, useTemplateRef, watch } from 'vue';
|
||||
import { getHex, getRgb } from 'misskey-world/src/utility.js';
|
||||
import { throttle } from 'throttle-debounce';
|
||||
import XWallOption from './room.simple-env-wall-options.vue';
|
||||
import XPillarOption from './room.simple-env-pillar-options.vue';
|
||||
import XDefaultEnvOptions from './room.simple-env-options.vue';
|
||||
import XCustomMadoriEnvOptions from './room.custom-madori-env-options.vue';
|
||||
import type { RoomController } from '@/world/room/controller.js';
|
||||
|
|
|
|||
|
|
@ -173,8 +173,8 @@ export class RoomController extends EngineControllerBase<RoomEngine, {
|
|||
this.call('updateEnvOptions', [options]);
|
||||
}
|
||||
|
||||
public updateRoomLightColor(color: [number, number, number]) {
|
||||
this.call('updateRoomLightColor', [color]);
|
||||
public updateLightSettings(light: RoomState['light']) {
|
||||
this.call('updateLightSettings', [light]);
|
||||
}
|
||||
|
||||
public beginSelectedInstalledFunitureGrabbing() {
|
||||
|
|
|
|||
|
|
@ -21,7 +21,10 @@ export type RoomState = {
|
|||
type: 'customMadori';
|
||||
options: CustomMadoriEnvOptions;
|
||||
};
|
||||
roomLightColor: [number, number, number];
|
||||
light: {
|
||||
color: [number, number, number];
|
||||
brightness: number;
|
||||
};
|
||||
installedFurnitures: RoomState_InstalledFurniture[];
|
||||
worldScale: number;
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue