From 78de73236ed5c63feae6361c888d31c3a9261289 Mon Sep 17 00:00:00 2001 From: Ryan Tremblay Date: Mon, 2 Jun 2025 15:58:00 -0700 Subject: [PATCH 1/4] Replace ShadowOnlyMaterial with BackgroundMaterial --- packages/public/@babylonjs/viewer/package.json | 3 +-- packages/tools/viewer/src/viewer.ts | 17 ++++++++--------- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/packages/public/@babylonjs/viewer/package.json b/packages/public/@babylonjs/viewer/package.json index 5747bd9920a..9ec80967ee5 100644 --- a/packages/public/@babylonjs/viewer/package.json +++ b/packages/public/@babylonjs/viewer/package.json @@ -32,8 +32,7 @@ }, "peerDependencies": { "@babylonjs/core": "^8.0.0", - "@babylonjs/loaders": "^8.0.0", - "@babylonjs/materials": "^8.0.0" + "@babylonjs/loaders": "^8.0.0" }, "devDependencies": { "@babylonjs/core": "^8.10.0", diff --git a/packages/tools/viewer/src/viewer.ts b/packages/tools/viewer/src/viewer.ts index 3d75eb07e8e..cb4a2c1395c 100644 --- a/packages/tools/viewer/src/viewer.ts +++ b/packages/tools/viewer/src/viewer.ts @@ -19,6 +19,7 @@ import type { Nullable, Observer, PickingInfo, + ShadowLight, ShaderMaterial, ShadowGenerator, // eslint-disable-next-line import/no-internal-modules @@ -32,10 +33,11 @@ import { PointerEventTypes } from "core/Events/pointerEvents"; import { SpotLight } from "core/Lights/spotLight"; import { HemisphericLight } from "core/Lights/hemisphericLight"; import { LoadAssetContainerAsync } from "core/Loading/sceneLoader"; +import { BackgroundMaterial } from "core/Materials/Background/backgroundMaterial"; import { ImageProcessingConfiguration } from "core/Materials/imageProcessingConfiguration"; import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; import { Texture } from "core/Materials/Textures/texture"; -import { Color4 } from "core/Maths/math.color"; +import { Color3, Color4 } from "core/Maths/math.color"; import { Clamp } from "core/Maths/math.scalar.functions"; import { Matrix, Vector2, Vector3 } from "core/Maths/math.vector"; import { Viewport } from "core/Maths/math.viewport"; @@ -136,7 +138,7 @@ type ShadowState = { normal?: { generator: ShadowGenerator; ground: Mesh; - light: SpotLight; + light: ShadowLight; shouldRender: boolean; }; high?: { @@ -1751,16 +1753,11 @@ export class Viewer implements IDisposable { private async _updateShadowMap(abortSignal?: AbortSignal) { // eslint-disable-next-line @typescript-eslint/naming-convention - const [{ CreateDisc }, { ShadowOnlyMaterial }, { RenderTargetTexture }, { ShadowGenerator }] = await Promise.all([ + const [{ CreateDisc }, { RenderTargetTexture }, { ShadowGenerator }] = await Promise.all([ import("core/Meshes/Builders/discBuilder"), - import("materials/shadowOnly/shadowOnlyMaterial"), import("core/Materials/Textures/renderTargetTexture"), import("core/Lights/Shadows/shadowGenerator"), import("core/Lights/Shadows/shadowGeneratorSceneComponent"), - // TODO: Why are these explicit imports needed, even though they are imported directly in shadowOnlyMaterial? - // Without these explicit imports, the shaders do not end up in the esm dist and we get a runtime error. - import("materials/shadowOnly/shadowOnly.vertex"), - import("materials/shadowOnly/shadowOnly.fragment"), ]); // cancel if the model is unloaded before the shadows are created @@ -1805,7 +1802,9 @@ export class Viewer implements IDisposable { shadowMap.refreshRate = RenderTargetTexture.REFRESHRATE_RENDER_ONEVERYFRAME; } - const shadowMaterial = new ShadowOnlyMaterial("shadowMapGroundMaterial", this._scene); + const shadowMaterial = new BackgroundMaterial("shadowMapGroundMaterial", this._scene); + shadowMaterial.shadowOnly = true; + shadowMaterial.primaryColor = new Color3(0, 0, 0); const ground = CreateDisc("shadowMapGround", { radius: groundSize, tessellation: 64 }, this._scene); ground.rotation.x = Math.PI / 2; From b5a9678bb74893255de746bc9c7749edb1d69b1b Mon Sep 17 00:00:00 2001 From: Ryan Tremblay Date: Mon, 2 Jun 2025 16:00:53 -0700 Subject: [PATCH 2/4] Replace PBRMaterial with BackgroundMaterial for skybox --- .../src/ShadersWGSL/background.fragment.fx | 2 +- packages/tools/viewer/src/viewer.ts | 19 +++++++------------ 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/packages/dev/core/src/ShadersWGSL/background.fragment.fx b/packages/dev/core/src/ShadersWGSL/background.fragment.fx index 78426512b98..9b2af611004 100644 --- a/packages/dev/core/src/ShadersWGSL/background.fragment.fx +++ b/packages/dev/core/src/ShadersWGSL/background.fragment.fx @@ -203,7 +203,7 @@ fn main(input: FragmentInputs) -> FragmentOutputs { #ifdef TEXTURELODSUPPORT // Apply environment convolution scale/offset filter tuning parameters to the mipmap LOD selection - reflectionLOD = reflectionLOD * log2(vReflectionMicrosurfaceInfos.x) * vReflectionMicrosurfaceInfos.y + vReflectionMicrosurfaceInfos.z; + reflectionLOD = reflectionLOD * log2(uniforms.vReflectionMicrosurfaceInfos.x) * uniforms.vReflectionMicrosurfaceInfos.y + uniforms.vReflectionMicrosurfaceInfos.z; reflectionColor = textureSampleLevel(reflectionSampler, reflectionSamplerSampler, reflectionCoords, reflectionLOD); #else var lodReflectionNormalized: f32 = saturate(reflectionLOD); diff --git a/packages/tools/viewer/src/viewer.ts b/packages/tools/viewer/src/viewer.ts index cb4a2c1395c..f97b1bae9ca 100644 --- a/packages/tools/viewer/src/viewer.ts +++ b/packages/tools/viewer/src/viewer.ts @@ -202,18 +202,13 @@ function createSkybox(scene: Scene, camera: Camera, reflectionTexture: BaseTextu const originalBlockMaterialDirtyMechanism = scene.blockMaterialDirtyMechanism; scene.blockMaterialDirtyMechanism = true; try { - const hdrSkybox = CreateBox("hdrSkyBox", undefined, scene); - const hdrSkyboxMaterial = new PBRMaterial("skyBox", scene); + const hdrSkybox = CreateBox("hdrSkyBox", { sideOrientation: Mesh.BACKSIDE }, scene); + const hdrSkyboxMaterial = new BackgroundMaterial("skyBox", scene); // Use the default image processing configuration on the skybox (e.g. don't apply tone mapping, contrast, or exposure). hdrSkyboxMaterial.imageProcessingConfiguration = new ImageProcessingConfiguration(); - hdrSkyboxMaterial.backFaceCulling = false; hdrSkyboxMaterial.reflectionTexture = reflectionTexture; - if (hdrSkyboxMaterial.reflectionTexture) { - hdrSkyboxMaterial.reflectionTexture.coordinatesMode = Texture.SKYBOX_MODE; - } - hdrSkyboxMaterial.microSurface = 1.0 - blur; - hdrSkyboxMaterial.disableLighting = true; - hdrSkyboxMaterial.twoSidedLighting = true; + reflectionTexture.coordinatesMode = Texture.SKYBOX_MODE; + hdrSkyboxMaterial.reflectionBlur = blur; hdrSkybox.material = hdrSkyboxMaterial; hdrSkybox.isPickable = false; hdrSkybox.infiniteDistance = true; @@ -1010,9 +1005,9 @@ export class Viewer implements IDisposable { this._skyboxBlur = value; if (this._skybox) { const material = this._skybox.material; - if (material instanceof PBRMaterial) { + if (material instanceof BackgroundMaterial) { this._snapshotHelper.disableSnapshotRendering(); - material.microSurface = 1.0 - this._skyboxBlur; + material.reflectionBlur = this._skyboxBlur; this._snapshotHelper.enableSnapshotRendering(); this._markSceneMutated(); } @@ -1787,7 +1782,7 @@ export class Viewer implements IDisposable { const position = new Vector3(x * (radius * positionFactor), radius * positionFactor, z * (radius * positionFactor)); let normal = this._shadowState.normal; if (!normal) { - const light = new SpotLight("spotLight", position, new Vector3(-x, -1, -z), Math.PI / 3, 30, this._scene); + const light = new SpotLight("shadowLight", position, new Vector3(-x, -1, -z), Math.PI / 3, 30, this._scene); const generator = new ShadowGenerator(size, light); generator.setDarkness(0.8); From dbb90df894f25d9446c017a2b8ff8a60a9ad078e Mon Sep 17 00:00:00 2001 From: Ryan Tremblay Date: Mon, 2 Jun 2025 16:07:12 -0700 Subject: [PATCH 3/4] enableSoftTransparentShadows and bias --- packages/tools/viewer/src/viewer.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/tools/viewer/src/viewer.ts b/packages/tools/viewer/src/viewer.ts index f97b1bae9ca..66a2b91945f 100644 --- a/packages/tools/viewer/src/viewer.ts +++ b/packages/tools/viewer/src/viewer.ts @@ -1789,6 +1789,8 @@ export class Viewer implements IDisposable { generator.setTransparencyShadow(true); generator.filteringQuality = ShadowGenerator.QUALITY_HIGH; generator.useBlurExponentialShadowMap = true; + generator.enableSoftTransparentShadow = true; + generator.bias = radius / 1000; generator.useKernelBlur = true; generator.blurKernel = 32; From 6529dbe182b21eb33da9f3cf4a5480184115dbf1 Mon Sep 17 00:00:00 2001 From: Ryan Tremblay Date: Mon, 2 Jun 2025 16:19:36 -0700 Subject: [PATCH 4/4] Use Black() helper function for shadow color --- packages/tools/viewer/src/viewer.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/tools/viewer/src/viewer.ts b/packages/tools/viewer/src/viewer.ts index 66a2b91945f..e14981341e6 100644 --- a/packages/tools/viewer/src/viewer.ts +++ b/packages/tools/viewer/src/viewer.ts @@ -1801,7 +1801,7 @@ export class Viewer implements IDisposable { const shadowMaterial = new BackgroundMaterial("shadowMapGroundMaterial", this._scene); shadowMaterial.shadowOnly = true; - shadowMaterial.primaryColor = new Color3(0, 0, 0); + shadowMaterial.primaryColor = Color3.Black(); const ground = CreateDisc("shadowMapGround", { radius: groundSize, tessellation: 64 }, this._scene); ground.rotation.x = Math.PI / 2;