This commit is contained in:
syuilo 2026-06-13 20:34:04 +09:00
commit 37c3145859
7 changed files with 49 additions and 29 deletions

View file

@ -1134,6 +1134,8 @@ export class RoomEngine extends EngineBase<{
this.grabbingCtx.onDone?.();
}
this.grabbingCtx = null;
this.envManager.renderShadow();
}
public interact(oid: string, iid: string | null = null) {
@ -1369,6 +1371,8 @@ export class RoomEngine extends EngineBase<{
this.selectFuniture(null);
this.isEditMode = false;
await this.envManager.renderShadow();
await this.bake();
}
@ -1515,14 +1519,11 @@ export class RoomEngine extends EngineBase<{
// TODO: loadFunitureのものとある程度共通化
p.registerMeshes = (meshes) => {
for (const mesh of meshes) {
mesh.receiveShadows = false;
if (SYSTEM_MESH_NAMES.some(n => mesh.name.includes(n))) {
mesh.receiveShadows = false;
mesh.isVisible = false;
} else {
mesh.metadata = { isPlayer: true, playerId: k };
mesh.receiveShadows = true;
// TODO: メモリリークしそうだからいい感じにする
this.envManager.addShadowCaster(mesh);
//if (mesh.material) (mesh.material as BABYLON.PBRMaterial).ambientColor = new BABYLON.Color3(0.2, 0.2, 0.2);
if (mesh.material) {

View file

@ -14,7 +14,7 @@ export abstract class EnvManager<T = any> {
protected engine: RoomEngine;
public abstract envMapIndoor: BABYLON.CubeTexture | null;
public abstract maxCameraZ: number;
protected shadowGenerators: BABYLON.ShadowGenerator[] = [];
private shadowGenerators: BABYLON.ShadowGenerator[] = [];
protected isRoomLightOn = true;
constructor(engine: RoomEngine) {
@ -36,6 +36,24 @@ export abstract class EnvManager<T = any> {
this.applyRoomLight();
}
protected registerShadowGenerator(shadowGenerator: BABYLON.ShadowGenerator) {
this.shadowGenerators.push(shadowGenerator);
const shadowMap = shadowGenerator.getShadowMap()!;
shadowMap.refreshRate = BABYLON.RenderTargetTexture.REFRESHRATE_RENDER_ONCE;
// https://forum.babylonjs.com/t/is-it-intentional-that-the-shadow-map-refresh-rate-is-ignored-under-fast-snapshot-rendering/63523
const objectRenderer = shadowMap._objectRenderer;
const originalShouldRender = objectRenderer.shouldRender.bind(objectRenderer);
objectRenderer.shouldRender = function () {
if (this._engine.snapshotRendering) {
return this.refreshRate !== BABYLON.RenderTargetTexture.REFRESHRATE_RENDER_ONCE;
}
return originalShouldRender();
};
}
public addShadowCaster(mesh: BABYLON.AbstractMesh) {
for (const shadowGen of this.shadowGenerators) {
shadowGen.addShadowCaster(mesh);
@ -48,6 +66,24 @@ export abstract class EnvManager<T = any> {
}
}
public async renderShadow() {
this.engine.sr.disableSnapshotRendering();
for (const shadowGen of this.shadowGenerators) {
const shadowMap = shadowGen.getShadowMap()!;
shadowMap.refreshRate = 1;
}
await new Promise(resolve => setTimeout(resolve, 1));
for (const shadowGen of this.shadowGenerators) {
const shadowMap = shadowGen.getShadowMap()!;
shadowMap.refreshRate = BABYLON.RenderTargetTexture.REFRESHRATE_RENDER_ONCE;
}
this.engine.sr.enableSnapshotRendering();
}
protected registerMeshes(meshes: BABYLON.AbstractMesh[]) {
for (const mesh of meshes) {
if (!this.engine.scene.meshes.includes(mesh)) this.engine.scene.addMesh(mesh);

View file

@ -62,12 +62,9 @@ export class CustomMadoriEnvManager extends EnvManager<CustomMadoriEnvOptions> {
shadowGeneratorForRoomLight.bias = 0.0005;
shadowGeneratorForRoomLight.usePercentageCloserFiltering = true;
shadowGeneratorForRoomLight.filteringQuality = BABYLON.ShadowGenerator.QUALITY_HIGH;
if (this.engine.graphicsQuality <= GRAPHICS_QUALITY.MEDIUM) {
shadowGeneratorForRoomLight.getShadowMap().refreshRate = 60; // 効いてなさそう babylonのバグ
}
//shadowGeneratorForRoomLight.useContactHardeningShadow = true;
//shadowGeneratorForRoomLight.contactHardeningLightSizeUVRatio = 0.01;
this.shadowGenerators.push(shadowGeneratorForRoomLight);
this.registerShadowGenerator(shadowGeneratorForRoomLight);
}
for (const materialDef of options.flooringMaterials) {

View file

@ -46,12 +46,9 @@ export class JapaneseEnvManager extends EnvManager<JapaneseEnvOptions> {
shadowGeneratorForRoomLight.bias = 0.0005;
shadowGeneratorForRoomLight.usePercentageCloserFiltering = true;
shadowGeneratorForRoomLight.filteringQuality = BABYLON.ShadowGenerator.QUALITY_HIGH;
if (this.engine.graphicsQuality <= GRAPHICS_QUALITY.MEDIUM) {
shadowGeneratorForRoomLight.getShadowMap().refreshRate = 60;
}
//shadowGeneratorForRoomLight.useContactHardeningShadow = true;
//shadowGeneratorForRoomLight.contactHardeningLightSizeUVRatio = 0.01;
this.shadowGenerators.push(shadowGeneratorForRoomLight);
this.registerShadowGenerator(shadowGeneratorForRoomLight);
}
if (this.engine.graphicsQuality >= GRAPHICS_QUALITY.MEDIUM) {
@ -65,10 +62,7 @@ export class JapaneseEnvManager extends EnvManager<JapaneseEnvOptions> {
shadowGeneratorForSunLight.bias = 0.00001;
shadowGeneratorForSunLight.usePercentageCloserFiltering = true;
shadowGeneratorForSunLight.usePoissonSampling = true;
if (this.engine.graphicsQuality <= GRAPHICS_QUALITY.MEDIUM) {
shadowGeneratorForSunLight.getShadowMap().refreshRate = 60;
}
this.shadowGenerators.push(shadowGeneratorForSunLight);
this.registerShadowGenerator(shadowGeneratorForSunLight);
}
this.loaderResult = await BABYLON.ImportMeshAsync('/client-assets/room/envs/japanese/japanese.glb', this.engine.scene);

View file

@ -67,11 +67,8 @@ export class MuseumEnvManager extends EnvManager<MuseumEnvOptions> {
shadowGeneratorForRoomLight.normalBias = 0.005;
shadowGeneratorForRoomLight.usePercentageCloserFiltering = true;
shadowGeneratorForRoomLight.filteringQuality = BABYLON.ShadowGenerator.QUALITY_HIGH;
if (this.engine.graphicsQuality <= GRAPHICS_QUALITY.MEDIUM) {
shadowGeneratorForRoomLight.getShadowMap().refreshRate = 60;
}
//this.shadowGeneratorForRoomLight.useContactHardeningShadow = true;
this.shadowGenerators.push(shadowGeneratorForRoomLight);
this.registerShadowGenerator(shadowGeneratorForRoomLight);
}
for (const node of this.meshes.filter(mesh => mesh.name.includes('__LIGHT__'))) {

View file

@ -157,12 +157,9 @@ export class SimpleEnvManager extends EnvManager<SimpleEnvOptions> {
shadowGeneratorForRoomLight.bias = 0.0005;
shadowGeneratorForRoomLight.usePercentageCloserFiltering = true;
shadowGeneratorForRoomLight.filteringQuality = BABYLON.ShadowGenerator.QUALITY_HIGH;
if (this.engine.graphicsQuality <= GRAPHICS_QUALITY.MEDIUM) {
shadowGeneratorForRoomLight.getShadowMap().refreshRate = 60; // 効いてなさそう babylonのバグ
}
//shadowGeneratorForRoomLight.useContactHardeningShadow = true;
//shadowGeneratorForRoomLight.contactHardeningLightSizeUVRatio = 0.01;
this.shadowGenerators.push(shadowGeneratorForRoomLight);
this.registerShadowGenerator(shadowGeneratorForRoomLight);
}
if (this.engine.graphicsQuality >= GRAPHICS_QUALITY.MEDIUM) {
@ -176,10 +173,7 @@ export class SimpleEnvManager extends EnvManager<SimpleEnvOptions> {
shadowGeneratorForSunLight.bias = 0.00001;
shadowGeneratorForSunLight.usePercentageCloserFiltering = true;
shadowGeneratorForSunLight.usePoissonSampling = true;
if (this.engine.graphicsQuality <= GRAPHICS_QUALITY.MEDIUM) {
shadowGeneratorForSunLight.getShadowMap().refreshRate = 60; // 効いてなさそう babylonのバグ
}
this.shadowGenerators.push(shadowGeneratorForSunLight);
this.registerShadowGenerator(shadowGeneratorForSunLight);
}
this.envMapIndoor = BABYLON.CubeTexture.CreateFromPrefilteredData('/client-assets/room/indoor.env', this.engine.scene);

View file

@ -22,4 +22,5 @@ export const ceilingFan_schema = defineFurnitureSchema({
},
placement: 'ceiling',
hasCollisions: false,
castShadows: false,
});