@onerjs/serializers 9.0.1 → 9.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/glTF/2.0/Extensions/KHR_materials_anisotropy.pure.js +12 -10
  2. package/glTF/2.0/Extensions/KHR_materials_anisotropy.pure.js.map +1 -1
  3. package/glTF/2.0/Extensions/KHR_materials_coat.pure.js +11 -9
  4. package/glTF/2.0/Extensions/KHR_materials_coat.pure.js.map +1 -1
  5. package/glTF/2.0/Extensions/KHR_materials_scatter.d.ts +5 -0
  6. package/glTF/2.0/Extensions/KHR_materials_scatter.js +8 -0
  7. package/glTF/2.0/Extensions/KHR_materials_scatter.js.map +1 -0
  8. package/glTF/2.0/Extensions/KHR_materials_scatter.pure.d.ts +120 -0
  9. package/glTF/2.0/Extensions/KHR_materials_scatter.pure.js +396 -0
  10. package/glTF/2.0/Extensions/KHR_materials_scatter.pure.js.map +1 -0
  11. package/glTF/2.0/Extensions/KHR_materials_transmission.pure.d.ts +2 -0
  12. package/glTF/2.0/Extensions/KHR_materials_transmission.pure.js +141 -39
  13. package/glTF/2.0/Extensions/KHR_materials_transmission.pure.js.map +1 -1
  14. package/glTF/2.0/Extensions/KHR_materials_volume.pure.js +2 -48
  15. package/glTF/2.0/Extensions/KHR_materials_volume.pure.js.map +1 -1
  16. package/glTF/2.0/Extensions/index.d.ts +1 -1
  17. package/glTF/2.0/Extensions/index.js +1 -1
  18. package/glTF/2.0/Extensions/index.js.map +1 -1
  19. package/glTF/2.0/Extensions/pure.d.ts +1 -1
  20. package/glTF/2.0/Extensions/pure.js +1 -1
  21. package/glTF/2.0/Extensions/pure.js.map +1 -1
  22. package/glTF/2.0/glTFExporter.d.ts +6 -0
  23. package/glTF/2.0/glTFExporter.js +9 -0
  24. package/glTF/2.0/glTFExporter.js.map +1 -1
  25. package/glTF/2.0/glTFMaterialExporter.d.ts +2 -1
  26. package/glTF/2.0/glTFMaterialExporter.js +68 -31
  27. package/glTF/2.0/glTFMaterialExporter.js.map +1 -1
  28. package/glTF/2.0/glTFSerializer.d.ts +1 -2
  29. package/glTF/2.0/glTFSerializer.js.map +1 -1
  30. package/glTF/2.0/glTFUtilities.d.ts +37 -1
  31. package/glTF/2.0/glTFUtilities.js +99 -0
  32. package/glTF/2.0/glTFUtilities.js.map +1 -1
  33. package/package.json +2 -2
  34. package/glTF/2.0/Extensions/KHR_materials_volume_scatter.d.ts +0 -5
  35. package/glTF/2.0/Extensions/KHR_materials_volume_scatter.js +0 -8
  36. package/glTF/2.0/Extensions/KHR_materials_volume_scatter.js.map +0 -1
  37. package/glTF/2.0/Extensions/KHR_materials_volume_scatter.pure.d.ts +0 -45
  38. package/glTF/2.0/Extensions/KHR_materials_volume_scatter.pure.js +0 -145
  39. package/glTF/2.0/Extensions/KHR_materials_volume_scatter.pure.js.map +0 -1
@@ -78,6 +78,7 @@ export declare class GLTFMaterialExporter {
78
78
  * @param babylonPBRMaterial BJS PBR Metallic Roughness Material
79
79
  * @param glTFPbrMetallicRoughness glTF PBR Metallic Roughness interface
80
80
  * @param hasUVs specifies if texture coordinates are present on the submesh to determine if textures should be applied
81
+ * @param skipBaseColorTexture when true, do not generate/assign the base color texture (an extension will own it)
81
82
  * @returns glTF PBR Metallic Roughness factors
82
83
  */
83
84
  private _convertMetalRoughFactorsToMetallicRoughnessAsync;
@@ -94,7 +95,7 @@ export declare class GLTFMaterialExporter {
94
95
  exportPBRMaterialAsync(babylonPBRMaterial: PBRBaseMaterial, hasUVs: boolean): Promise<number>;
95
96
  private _setMetallicRoughnessPbrMaterialAsync;
96
97
  exportOpenPBRMaterialAsync(babylonOpenPBRMaterial: OpenPBRMaterial, hasUVs: boolean): Promise<number>;
97
- exportTextureAsync(babylonTexture: BaseTexture, overrideId?: Nullable<number>): Promise<Nullable<ITextureInfo>>;
98
+ exportTextureAsync(babylonTexture: BaseTexture, overrideId?: Nullable<number | string>): Promise<Nullable<ITextureInfo>>;
98
99
  private _exportTextureImageAsync;
99
100
  private _exportImageAsync;
100
101
  private _exportTextureInfo;
@@ -14,6 +14,7 @@ import { SpecularPowerToRoughness } from "@onerjs/core/Helpers/materialConversio
14
14
  import { OpenPBRMaterial } from "@onerjs/core/Materials/PBR/openpbrMaterial.js";
15
15
  import { MergeTexturesAsync, CreateRGBAConfiguration, CreateTextureInput, CreateConstantInput } from "@onerjs/core/Materials/Textures/textureMerger.js";
16
16
  import { GetCachedImageAsync, GetFileExtensionFromMimeType } from "../../exportImageUtils.js";
17
+ import { CopyTextureSampling, GetSampledTextureKey } from "./glTFUtilities.js";
17
18
  const Epsilon = 1e-6;
18
19
  const DielectricSpecular = new Color3(0.04, 0.04, 0.04);
19
20
  const MaxSpecularPower = 1024;
@@ -107,6 +108,30 @@ function ConvertPixelArrayToFloat32(pixels) {
107
108
  throw new Error("Unsupported pixel format!");
108
109
  }
109
110
  }
111
+ /**
112
+ * Packs occlusion (R), roughness (G) and metallic (B) into one texture.
113
+ * glTF requires metallic and roughness to share sampling, but occlusion is referenced separately with its own
114
+ * UV set and transform, so occlusion is packed raw in a second, independent merge.
115
+ * The returned texture carries the metallic-roughness sampling parameters.
116
+ * @param occlusionTexture The ambient occlusion texture (red channel), if any
117
+ * @param roughnessTexture The roughness texture (channel 0), if any
118
+ * @param metallicTexture The metallic texture (channel 0), if any
119
+ * @param scene The scene used to create the merged textures
120
+ * @returns The packed texture
121
+ */
122
+ async function CreateOcclusionMetallicRoughnessTextureAsync(occlusionTexture, roughnessTexture, metallicTexture, scene) {
123
+ const metallicRoughness = await MergeTexturesAsync("MetalRoughTexture", {
124
+ ...CreateRGBAConfiguration(CreateConstantInput(1.0), roughnessTexture ? CreateTextureInput(roughnessTexture, 0) : CreateConstantInput(1.0), metallicTexture ? CreateTextureInput(metallicTexture, 0) : CreateConstantInput(1.0)),
125
+ sharedSampling: true,
126
+ }, scene);
127
+ if (!occlusionTexture) {
128
+ return metallicRoughness;
129
+ }
130
+ const packed = await MergeTexturesAsync("OcclusionMetalRoughTexture", CreateRGBAConfiguration(CreateTextureInput(occlusionTexture, 0), CreateTextureInput(metallicRoughness, 1), CreateTextureInput(metallicRoughness, 2)), scene);
131
+ CopyTextureSampling(metallicRoughness, packed);
132
+ metallicRoughness.dispose();
133
+ return packed;
134
+ }
110
135
  /**
111
136
  * Utility methods for working with glTF material conversion properties.
112
137
  * @internal
@@ -115,6 +140,7 @@ export class GLTFMaterialExporter {
115
140
  constructor(_exporter) {
116
141
  this._exporter = _exporter;
117
142
  // Mapping to store textures
143
+ // Keyed by texture uniqueId, or by a string key describing the inputs (and their sampling) of a merged texture
118
144
  this._textureMap = new Map();
119
145
  // Mapping of internal textures to images to avoid exporting duplicate images
120
146
  this._internalTextureToImage = {};
@@ -413,9 +439,10 @@ export class GLTFMaterialExporter {
413
439
  * @param babylonPBRMaterial BJS PBR Metallic Roughness Material
414
440
  * @param glTFPbrMetallicRoughness glTF PBR Metallic Roughness interface
415
441
  * @param hasUVs specifies if texture coordinates are present on the submesh to determine if textures should be applied
442
+ * @param skipBaseColorTexture when true, do not generate/assign the base color texture (an extension will own it)
416
443
  * @returns glTF PBR Metallic Roughness factors
417
444
  */
418
- async _convertMetalRoughFactorsToMetallicRoughnessAsync(baseColor, metallic, roughness, albedoTexture, metallicTexture, roughnessTexture, babylonPBRMaterial, glTFPbrMetallicRoughness, hasUVs) {
445
+ async _convertMetalRoughFactorsToMetallicRoughnessAsync(baseColor, metallic, roughness, albedoTexture, metallicTexture, roughnessTexture, babylonPBRMaterial, glTFPbrMetallicRoughness, hasUVs, skipBaseColorTexture = false) {
419
446
  const promises = [];
420
447
  const metallicRoughness = {
421
448
  baseColor: baseColor,
@@ -424,33 +451,38 @@ export class GLTFMaterialExporter {
424
451
  };
425
452
  if (hasUVs) {
426
453
  if (babylonPBRMaterial instanceof OpenPBRMaterial) {
427
- if (babylonPBRMaterial.geometryOpacityTexture) {
428
- // Merge baseColor and opacity
429
- const albedoId = albedoTexture && albedoTexture.getInternalTexture() ? albedoTexture.getInternalTexture().uniqueId : 0;
430
- const opacityId = babylonPBRMaterial.geometryOpacityTexture && babylonPBRMaterial.geometryOpacityTexture.getInternalTexture()
431
- ? babylonPBRMaterial.geometryOpacityTexture.getInternalTexture().uniqueId
432
- : 0;
433
- const mergedId = Number(`${albedoId}${opacityId}`);
434
- const glTFTexture = this._textureMap.get(mergedId);
435
- if (glTFTexture) {
436
- glTFPbrMetallicRoughness.baseColorTexture = glTFTexture;
454
+ // Skip base color texture generation when an extension (e.g. KHR_materials_transmission)
455
+ // will overwrite the base color anyway; otherwise the texture/image baked here would be
456
+ // orphaned in the output. The extension re-bakes base color (including opacity) itself.
457
+ if (!skipBaseColorTexture) {
458
+ if (babylonPBRMaterial.geometryOpacityTexture) {
459
+ // Merge baseColor and opacity
460
+ // The merge bakes input transforms, so the cache key must include each input's sampling state
461
+ const mergedId = `baseColorOpacity|${GetSampledTextureKey(albedoTexture, "none")}|${GetSampledTextureKey(babylonPBRMaterial.geometryOpacityTexture, "none")}`;
462
+ const glTFTexture = this._textureMap.get(mergedId);
463
+ if (glTFTexture) {
464
+ glTFPbrMetallicRoughness.baseColorTexture = glTFTexture;
465
+ }
466
+ else {
467
+ promises.push(MergeTexturesAsync("baseColorOpacityTexture", {
468
+ ...CreateRGBAConfiguration(albedoTexture ? CreateTextureInput(albedoTexture, 0) : CreateConstantInput(1.0), albedoTexture ? CreateTextureInput(albedoTexture, 1) : CreateConstantInput(1.0), albedoTexture ? CreateTextureInput(albedoTexture, 2) : CreateConstantInput(1.0), CreateTextureInput(babylonPBRMaterial.geometryOpacityTexture, 0)),
469
+ sharedSampling: true,
470
+ }, babylonPBRMaterial.getScene()).then(async (mergedTexture) => {
471
+ const glTFTexture = await this.exportTextureAsync(mergedTexture, mergedId);
472
+ if (glTFTexture) {
473
+ glTFPbrMetallicRoughness.baseColorTexture = glTFTexture;
474
+ }
475
+ }));
476
+ }
437
477
  }
438
478
  else {
439
- promises.push(MergeTexturesAsync("baseColorOpacityTexture", CreateRGBAConfiguration(albedoTexture ? CreateTextureInput(albedoTexture, 0) : CreateConstantInput(1.0), albedoTexture ? CreateTextureInput(albedoTexture, 1) : CreateConstantInput(1.0), albedoTexture ? CreateTextureInput(albedoTexture, 2) : CreateConstantInput(1.0), CreateTextureInput(babylonPBRMaterial.geometryOpacityTexture, 0)), babylonPBRMaterial.getScene()).then(async (mergedTexture) => {
440
- const glTFTexture = await this.exportTextureAsync(mergedTexture, mergedId);
441
- if (glTFTexture) {
442
- glTFPbrMetallicRoughness.baseColorTexture = glTFTexture;
443
- }
444
- }));
445
- }
446
- }
447
- else {
448
- if (albedoTexture) {
449
- promises.push(this.exportTextureAsync(albedoTexture).then((glTFTexture) => {
450
- if (glTFTexture) {
451
- glTFPbrMetallicRoughness.baseColorTexture = glTFTexture;
452
- }
453
- }));
479
+ if (albedoTexture) {
480
+ promises.push(this.exportTextureAsync(albedoTexture).then((glTFTexture) => {
481
+ if (glTFTexture) {
482
+ glTFPbrMetallicRoughness.baseColorTexture = glTFTexture;
483
+ }
484
+ }));
485
+ }
454
486
  }
455
487
  }
456
488
  if (babylonPBRMaterial._useMetallicFromMetallicTextureBlue && metallicTexture) {
@@ -461,15 +493,14 @@ export class GLTFMaterialExporter {
461
493
  }));
462
494
  }
463
495
  else if (roughnessTexture || metallicTexture) {
464
- const metallicId = metallicTexture && metallicTexture.getInternalTexture() ? metallicTexture.getInternalTexture().uniqueId : 0;
465
- const roughnessId = roughnessTexture && roughnessTexture.getInternalTexture() ? roughnessTexture.getInternalTexture().uniqueId : 0;
466
- const mergedId = Number(`${metallicId}${roughnessId}`);
496
+ // The merge bakes input transforms (and packs occlusion), so the cache key must include every input's sampling state
497
+ const mergedId = `occlusionMetallicRoughness|${GetSampledTextureKey(babylonPBRMaterial.ambientOcclusionTexture, "none")}|${GetSampledTextureKey(metallicTexture, "none")}|${GetSampledTextureKey(roughnessTexture, "none")}`;
467
498
  const glTFTexture = this._textureMap.get(mergedId);
468
499
  if (glTFTexture) {
469
500
  glTFPbrMetallicRoughness.metallicRoughnessTexture = glTFTexture;
470
501
  }
471
502
  else {
472
- promises.push(MergeTexturesAsync("MetalRoughTexture", CreateRGBAConfiguration(babylonPBRMaterial.ambientOcclusionTexture ? CreateTextureInput(babylonPBRMaterial.ambientOcclusionTexture, 0) : CreateConstantInput(1.0), roughnessTexture ? CreateTextureInput(roughnessTexture, 0) : CreateConstantInput(1.0), metallicTexture ? CreateTextureInput(metallicTexture, 0) : CreateConstantInput(1.0)), babylonPBRMaterial.getScene()).then(async (mergedTexture) => {
503
+ promises.push(CreateOcclusionMetallicRoughnessTextureAsync(babylonPBRMaterial.ambientOcclusionTexture, roughnessTexture, metallicTexture, babylonPBRMaterial.getScene()).then(async (mergedTexture) => {
473
504
  const glTFTexture = await this.exportTextureAsync(mergedTexture, mergedId);
474
505
  if (glTFTexture) {
475
506
  glTFPbrMetallicRoughness.metallicRoughnessTexture = glTFTexture;
@@ -749,7 +780,13 @@ export class GLTFMaterialExporter {
749
780
  if (albedoColor) {
750
781
  glTFPbrMetallicRoughness.baseColorFactor = [albedoColor.r, albedoColor.g, albedoColor.b, alpha];
751
782
  }
752
- const metallicRoughness = await this._convertMetalRoughFactorsToMetallicRoughnessAsync(babylonOpenPBRMaterial.baseColor, babylonOpenPBRMaterial.baseMetalness, babylonOpenPBRMaterial.specularRoughness, babylonOpenPBRMaterial.baseColorTexture, babylonOpenPBRMaterial.baseMetalnessTexture, babylonOpenPBRMaterial.specularRoughnessTexture, babylonOpenPBRMaterial, glTFPbrMetallicRoughness, hasUVs);
783
+ // KHR_materials_transmission overwrites the base color for OpenPBR materials with surface
784
+ // transmission/subsurface (glTF tints transmission by base color, OpenPBR does not). When that
785
+ // extension is active, let it own the base color texture so we don't bake an orphaned one here.
786
+ const skipBaseColorTexture = this._exporter.isExtensionEnabled("KHR_materials_transmission") &&
787
+ !babylonOpenPBRMaterial.unlit &&
788
+ (babylonOpenPBRMaterial.transmissionWeight > 0 || babylonOpenPBRMaterial.subsurfaceWeight > 0);
789
+ const metallicRoughness = await this._convertMetalRoughFactorsToMetallicRoughnessAsync(babylonOpenPBRMaterial.baseColor, babylonOpenPBRMaterial.baseMetalness, babylonOpenPBRMaterial.specularRoughness, babylonOpenPBRMaterial.baseColorTexture, babylonOpenPBRMaterial.baseMetalnessTexture, babylonOpenPBRMaterial.specularRoughnessTexture, babylonOpenPBRMaterial, glTFPbrMetallicRoughness, hasUVs, skipBaseColorTexture);
753
790
  await this._setMetallicRoughnessPbrMaterialAsync(metallicRoughness, babylonOpenPBRMaterial, glTFMaterial, glTFPbrMetallicRoughness, hasUVs);
754
791
  await this._finishMaterialAsync(glTFMaterial, babylonOpenPBRMaterial);
755
792
  const materials = this._exporter._materials;