From fea940ccef9e7806c18ed059af299d8422ed9511 Mon Sep 17 00:00:00 2001 From: "Alex C. Huber" <91097647+alexchuber@users.noreply.github.com> Date: Fri, 3 Oct 2025 18:23:40 -0400 Subject: [PATCH 1/4] Don't divide by 0 :) --- packages/dev/serializers/src/glTF/2.0/glTFMaterialExporter.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/dev/serializers/src/glTF/2.0/glTFMaterialExporter.ts b/packages/dev/serializers/src/glTF/2.0/glTFMaterialExporter.ts index d012cbc24cd..d6d33d6b88d 100644 --- a/packages/dev/serializers/src/glTF/2.0/glTFMaterialExporter.ts +++ b/packages/dev/serializers/src/glTF/2.0/glTFMaterialExporter.ts @@ -533,8 +533,8 @@ export class GLTFMaterialExporter { const specularPerceivedBrightness = this._getPerceivedBrightness(specularGlossiness.specularColor); const oneMinusSpecularStrength = 1 - this._getMaxComponent(specularGlossiness.specularColor); const metallic = _SolveMetallic(diffusePerceivedBrightness, specularPerceivedBrightness, oneMinusSpecularStrength); - const baseColorFromDiffuse = specularGlossiness.diffuseColor.scale(oneMinusSpecularStrength / (1.0 - DielectricSpecular.r) / Math.max(1 - metallic)); - const baseColorFromSpecular = specularGlossiness.specularColor.subtract(DielectricSpecular.scale(1 - metallic)).scale(1 / Math.max(metallic)); + const baseColorFromDiffuse = specularGlossiness.diffuseColor.scale(oneMinusSpecularStrength / (1.0 - DielectricSpecular.r) / Math.max(1 - metallic, Epsilon)); + const baseColorFromSpecular = specularGlossiness.specularColor.subtract(DielectricSpecular.scale(1 - metallic)).scale(1 / Math.max(metallic, Epsilon)); let baseColor = Color3.Lerp(baseColorFromDiffuse, baseColorFromSpecular, metallic * metallic); baseColor = baseColor.clampToRef(0, 1, baseColor); From 029ab90e75011c1e5b315ecc521be170c47520b1 Mon Sep 17 00:00:00 2001 From: "Alex C. Huber" <91097647+alexchuber@users.noreply.github.com> Date: Fri, 3 Oct 2025 18:24:16 -0400 Subject: [PATCH 2/4] Don't modify the "Black" const --- packages/dev/serializers/src/glTF/2.0/glTFMaterialExporter.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/dev/serializers/src/glTF/2.0/glTFMaterialExporter.ts b/packages/dev/serializers/src/glTF/2.0/glTFMaterialExporter.ts index d6d33d6b88d..7a51a904377 100644 --- a/packages/dev/serializers/src/glTF/2.0/glTFMaterialExporter.ts +++ b/packages/dev/serializers/src/glTF/2.0/glTFMaterialExporter.ts @@ -416,7 +416,7 @@ export class GLTFMaterialExporter { const baseColorBuffer = new Uint8Array(byteLength); const strideSize = 4; - const maxBaseColor = Black; + const maxBaseColor = new Color3(0, 0, 0); let maxMetallic = 0; let maxRoughness = 0; From a3593f811a332672e054554e651866970db0d8a4 Mon Sep 17 00:00:00 2001 From: "Alex C. Huber" <91097647+alexchuber@users.noreply.github.com> Date: Fri, 3 Oct 2025 18:24:57 -0400 Subject: [PATCH 3/4] Nits: dead code --- .../serializers/src/glTF/2.0/glTFMaterialExporter.ts | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/packages/dev/serializers/src/glTF/2.0/glTFMaterialExporter.ts b/packages/dev/serializers/src/glTF/2.0/glTFMaterialExporter.ts index 7a51a904377..f27a65b6bda 100644 --- a/packages/dev/serializers/src/glTF/2.0/glTFMaterialExporter.ts +++ b/packages/dev/serializers/src/glTF/2.0/glTFMaterialExporter.ts @@ -124,7 +124,6 @@ async function GetCachedImageAsync(babylonTexture: BaseTexture): Promise Date: Fri, 3 Oct 2025 18:33:15 -0400 Subject: [PATCH 4/4] Make reference values deeply immutable --- .../serializers/src/glTF/2.0/glTFMaterialExporter.ts | 8 ++++---- packages/dev/serializers/src/glTF/2.0/glTFUtilities.ts | 10 +++++----- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/dev/serializers/src/glTF/2.0/glTFMaterialExporter.ts b/packages/dev/serializers/src/glTF/2.0/glTFMaterialExporter.ts index f27a65b6bda..9180adc2bc4 100644 --- a/packages/dev/serializers/src/glTF/2.0/glTFMaterialExporter.ts +++ b/packages/dev/serializers/src/glTF/2.0/glTFMaterialExporter.ts @@ -5,7 +5,7 @@ import type { ITextureInfo, IMaterial, IMaterialPbrMetallicRoughness, IMaterialOcclusionTextureInfo, ISampler, IImage } from "babylonjs-gltf2interface"; import { ImageMimeType, MaterialAlphaMode, TextureMagFilter, TextureMinFilter, TextureWrapMode } from "babylonjs-gltf2interface"; -import type { Nullable } from "core/types"; +import type { DeepImmutable, Nullable } from "core/types"; import { Color3 } from "core/Maths/math.color"; import { Scalar } from "core/Maths/math.scalar"; import { Tools } from "core/Misc/tools"; @@ -29,10 +29,10 @@ import { GetMimeType } from "core/Misc/fileTools"; import type { OpenPBRMaterial } from "core/Materials/PBR/openPbrMaterial"; const Epsilon = 1e-6; -const DielectricSpecular = new Color3(0.04, 0.04, 0.04); +const DielectricSpecular = new Color3(0.04, 0.04, 0.04) as DeepImmutable; const MaxSpecularPower = 1024; -const White = Color3.White(); -const Black = Color3.Black(); +const White = Color3.White() as DeepImmutable; +const Black = Color3.BlackReadOnly; /** * Interface for storing specular glossiness factors diff --git a/packages/dev/serializers/src/glTF/2.0/glTFUtilities.ts b/packages/dev/serializers/src/glTF/2.0/glTFUtilities.ts index c2e1bb16fec..0928b4c8174 100644 --- a/packages/dev/serializers/src/glTF/2.0/glTFUtilities.ts +++ b/packages/dev/serializers/src/glTF/2.0/glTFUtilities.ts @@ -1,7 +1,7 @@ /* eslint-disable jsdoc/require-jsdoc */ import type { INode } from "babylonjs-gltf2interface"; import { AccessorType, MeshPrimitiveMode } from "babylonjs-gltf2interface"; -import type { FloatArray, DataArray, IndicesArray } from "core/types"; +import type { FloatArray, DataArray, IndicesArray, DeepImmutable } from "core/types"; import type { Vector4 } from "core/Maths/math.vector"; import { Quaternion, TmpVectors, Matrix, Vector3 } from "core/Maths/math.vector"; import { VertexBuffer } from "core/Buffers/buffer"; @@ -17,10 +17,10 @@ import { Epsilon } from "core/Maths/math.constants"; import { ConvertHandednessMatrix } from "../../exportUtils"; // Default values for comparison. -export const DefaultTranslation = Vector3.Zero(); -export const DefaultRotation = Quaternion.Identity(); -export const DefaultScale = Vector3.One(); -const DefaultLoaderCameraParentScaleLh = new Vector3(-1, 1, 1); +export const DefaultTranslation = Vector3.ZeroReadOnly; +export const DefaultRotation = Quaternion.Identity() as DeepImmutable; +export const DefaultScale = Vector3.OneReadOnly; +const DefaultLoaderCameraParentScaleLh = new Vector3(-1, 1, 1) as DeepImmutable; /** * Get the information necessary for enumerating a vertex buffer.