Skip to content

Commit 6f7ba8d

Browse files
author
Mike Bond
committed
Adding support to export GLB with OpenPBR
1 parent dfa997c commit 6f7ba8d

File tree

3 files changed

+124
-17
lines changed

3 files changed

+124
-17
lines changed

packages/dev/serializers/src/glTF/2.0/Extensions/KHR_materials_clearcoat.ts

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { PBRBaseMaterial } from "core/Materials/PBR/pbrBaseMaterial";
66
import type { BaseTexture } from "core/Materials/Textures/baseTexture";
77

88
import { Tools } from "core/Misc/tools";
9+
import { OpenPBRMaterial } from "core/Materials/PBR/openPbrMaterial";
910

1011
const NAME = "KHR_materials_clearcoat";
1112

@@ -53,6 +54,19 @@ export class KHR_materials_clearcoat implements IGLTFExporterExtensionV2 {
5354
}
5455
return additionalTextures;
5556
}
57+
} else if (babylonMaterial instanceof OpenPBRMaterial) {
58+
if (babylonMaterial.coatWeight > 0) {
59+
if (babylonMaterial.coatWeightTexture) {
60+
additionalTextures.push(babylonMaterial.coatWeightTexture);
61+
}
62+
if (babylonMaterial.geometryCoatNormalTexture) {
63+
additionalTextures.push(babylonMaterial.geometryCoatNormalTexture);
64+
}
65+
if (babylonMaterial.coatRoughnessTexture) {
66+
additionalTextures.push(babylonMaterial.coatRoughnessTexture);
67+
}
68+
return additionalTextures;
69+
}
5670
}
5771

5872
return [];
@@ -101,6 +115,43 @@ export class KHR_materials_clearcoat implements IGLTFExporterExtensionV2 {
101115
this._exporter._materialNeedsUVsSet.add(babylonMaterial);
102116
}
103117

118+
node.extensions[NAME] = clearCoatInfo;
119+
} else if (babylonMaterial instanceof OpenPBRMaterial) {
120+
if (babylonMaterial.coatWeight == 0.0) {
121+
resolve(node);
122+
return;
123+
}
124+
125+
this._wasUsed = true;
126+
127+
node.extensions = node.extensions || {};
128+
129+
const clearCoatTextureInfo = this._exporter._materialExporter.getTextureInfo(babylonMaterial.coatWeightTexture);
130+
let clearCoatTextureRoughnessInfo;
131+
if (babylonMaterial.useCoatRoughnessFromWeightTexture) {
132+
clearCoatTextureRoughnessInfo = this._exporter._materialExporter.getTextureInfo(babylonMaterial.coatWeightTexture);
133+
} else {
134+
clearCoatTextureRoughnessInfo = this._exporter._materialExporter.getTextureInfo(babylonMaterial.coatRoughnessTexture);
135+
}
136+
137+
if (babylonMaterial.coatColorTexture) {
138+
Tools.Warn(`Clear Color tint is not supported for glTF export. Ignoring for: ${babylonMaterial.name}`);
139+
}
140+
141+
const clearCoatNormalTextureInfo = this._exporter._materialExporter.getTextureInfo(babylonMaterial.geometryCoatNormalTexture);
142+
143+
const clearCoatInfo: IKHRMaterialsClearcoat = {
144+
clearcoatFactor: babylonMaterial.coatWeight,
145+
clearcoatTexture: clearCoatTextureInfo ?? undefined,
146+
clearcoatRoughnessFactor: babylonMaterial.coatRoughness,
147+
clearcoatRoughnessTexture: clearCoatTextureRoughnessInfo ?? undefined,
148+
clearcoatNormalTexture: clearCoatNormalTextureInfo ?? undefined,
149+
};
150+
151+
if (clearCoatInfo.clearcoatTexture !== null || clearCoatInfo.clearcoatRoughnessTexture !== null || clearCoatInfo.clearcoatRoughnessTexture !== null) {
152+
this._exporter._materialNeedsUVsSet.add(babylonMaterial);
153+
}
154+
104155
node.extensions[NAME] = clearCoatInfo;
105156
}
106157
resolve(node);

packages/dev/serializers/src/glTF/2.0/glTFExporter.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ import { Color3, Color4 } from "core/Maths/math.color";
8080
import { TargetCamera } from "core/Cameras/targetCamera";
8181
import { Epsilon } from "core/Maths/math.constants";
8282
import { DataWriter } from "./dataWriter";
83+
import { OpenPBRMaterial } from "core/Materials";
8384

8485
class ExporterState {
8586
// Babylon indices array, start, count, offset, flip -> glTF accessor index
@@ -1417,6 +1418,8 @@ export class GLTFExporter {
14171418
materialIndex = await this._materialExporter.exportPBRMaterialAsync(babylonMaterial, ImageMimeType.PNG, hasUVs);
14181419
} else if (babylonMaterial instanceof StandardMaterial) {
14191420
materialIndex = await this._materialExporter.exportStandardMaterialAsync(babylonMaterial, ImageMimeType.PNG, hasUVs);
1421+
} else if (babylonMaterial instanceof OpenPBRMaterial) {
1422+
materialIndex = await this._materialExporter.exportOpenPBRMaterialAsync(babylonMaterial, ImageMimeType.PNG, hasUVs);
14201423
} else {
14211424
Logger.Warn(`Unsupported material '${babylonMaterial.name}' with type ${babylonMaterial.getClassName()}`);
14221425
return;

packages/dev/serializers/src/glTF/2.0/glTFMaterialExporter.ts

Lines changed: 70 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,9 @@ import { DumpTools } from "core/Misc/dumpTools";
2222

2323
import type { Material } from "core/Materials/material";
2424
import type { StandardMaterial } from "core/Materials/standardMaterial";
25-
import type { PBRBaseMaterial } from "core/Materials/PBR/pbrBaseMaterial";
25+
import { PBRBaseMaterial } from "core/Materials/PBR/pbrBaseMaterial";
2626
import { SpecularPowerToRoughness } from "core/Helpers/materialConversionHelper";
27+
import type { OpenPBRMaterial } from "core/Materials/PBR/openPbrMaterial";
2728

2829
const Epsilon = 1e-6;
2930
const DielectricSpecular = new Color3(0.04, 0.04, 0.04);
@@ -524,41 +525,49 @@ export class GLTFMaterialExporter {
524525

525526
/**
526527
* Convert a PBRMaterial (Metallic/Roughness) to Metallic Roughness factors
528+
* @param baseColor Base color of the material
529+
* @param metallic Metallic factor of the material
530+
* @param roughness Roughness factor of the material
531+
* @param albedoTexture Albedo texture of the material
532+
* @param metallicRoughnessTexture Metallic roughness texture of the material
527533
* @param babylonPBRMaterial BJS PBR Metallic Roughness Material
528534
* @param mimeType mime type to use for the textures
529535
* @param glTFPbrMetallicRoughness glTF PBR Metallic Roughness interface
530536
* @param hasUVs specifies if texture coordinates are present on the submesh to determine if textures should be applied
531537
* @returns glTF PBR Metallic Roughness factors
532538
*/
533539
private async _convertMetalRoughFactorsToMetallicRoughnessAsync(
534-
babylonPBRMaterial: PBRBaseMaterial,
540+
baseColor: Color3,
541+
metallic: Nullable<number>,
542+
roughness: Nullable<number>,
543+
albedoTexture: Nullable<BaseTexture>,
544+
metallicRoughnessTexture: Nullable<BaseTexture>,
545+
babylonPBRMaterial: PBRBaseMaterial | OpenPBRMaterial,
535546
mimeType: ImageMimeType,
536547
glTFPbrMetallicRoughness: IMaterialPbrMetallicRoughness,
537548
hasUVs: boolean
538549
): Promise<IPBRMetallicRoughness> {
539550
const promises: Promise<void>[] = [];
540551

541552
const metallicRoughness: IPBRMetallicRoughness = {
542-
baseColor: babylonPBRMaterial._albedoColor,
543-
metallic: babylonPBRMaterial._metallic,
544-
roughness: babylonPBRMaterial._roughness,
553+
baseColor: baseColor,
554+
metallic: metallic,
555+
roughness: roughness,
545556
};
546557

547558
if (hasUVs) {
548-
const albedoTexture = babylonPBRMaterial._albedoTexture;
549559
if (albedoTexture) {
550560
promises.push(
551-
this.exportTextureAsync(babylonPBRMaterial._albedoTexture!, mimeType).then((glTFTexture) => {
561+
this.exportTextureAsync(albedoTexture, mimeType).then((glTFTexture) => {
552562
if (glTFTexture) {
553563
glTFPbrMetallicRoughness.baseColorTexture = glTFTexture;
554564
}
555565
})
556566
);
557567
}
558-
const metallicTexture = babylonPBRMaterial._metallicTexture;
559-
if (metallicTexture) {
568+
if (metallicRoughnessTexture) {
560569
promises.push(
561-
this.exportTextureAsync(metallicTexture, mimeType).then((glTFTexture) => {
570+
this.exportTextureAsync(metallicRoughnessTexture, mimeType).then((glTFTexture) => {
562571
if (glTFTexture) {
563572
glTFPbrMetallicRoughness.metallicRoughnessTexture = glTFTexture;
564573
}
@@ -744,7 +753,17 @@ export class GLTFMaterialExporter {
744753
}
745754

746755
const metallicRoughness = useMetallicRoughness
747-
? await this._convertMetalRoughFactorsToMetallicRoughnessAsync(babylonPBRMaterial, mimeType, glTFPbrMetallicRoughness, hasUVs)
756+
? await this._convertMetalRoughFactorsToMetallicRoughnessAsync(
757+
babylonPBRMaterial._albedoColor,
758+
babylonPBRMaterial._metallic,
759+
babylonPBRMaterial._roughness,
760+
babylonPBRMaterial._albedoTexture,
761+
babylonPBRMaterial._metallicTexture,
762+
babylonPBRMaterial,
763+
mimeType,
764+
glTFPbrMetallicRoughness,
765+
hasUVs
766+
)
748767
: await this._convertSpecGlossFactorsToMetallicRoughnessAsync(babylonPBRMaterial, mimeType, glTFPbrMetallicRoughness, hasUVs);
749768

750769
await this._setMetallicRoughnessPbrMaterialAsync(metallicRoughness, babylonPBRMaterial, glTFMaterial, glTFPbrMetallicRoughness, mimeType, hasUVs);
@@ -757,7 +776,7 @@ export class GLTFMaterialExporter {
757776

758777
private async _setMetallicRoughnessPbrMaterialAsync(
759778
metallicRoughness: IPBRMetallicRoughness,
760-
babylonPBRMaterial: PBRBaseMaterial,
779+
babylonPBRMaterial: PBRBaseMaterial | OpenPBRMaterial,
761780
glTFMaterial: IMaterial,
762781
glTFPbrMetallicRoughness: IMaterialPbrMetallicRoughness,
763782
mimeType: ImageMimeType,
@@ -786,7 +805,7 @@ export class GLTFMaterialExporter {
786805
if (hasUVs) {
787806
const promises: Promise<void>[] = [];
788807

789-
const bumpTexture = babylonPBRMaterial._bumpTexture;
808+
const bumpTexture = babylonPBRMaterial instanceof PBRBaseMaterial ? babylonPBRMaterial._bumpTexture : babylonPBRMaterial.geometryNormalTexture;
790809
if (bumpTexture) {
791810
promises.push(
792811
this.exportTextureAsync(bumpTexture, mimeType).then((glTFTexture) => {
@@ -800,7 +819,7 @@ export class GLTFMaterialExporter {
800819
);
801820
}
802821

803-
const ambientTexture = babylonPBRMaterial._ambientTexture;
822+
const ambientTexture = babylonPBRMaterial instanceof PBRBaseMaterial ? babylonPBRMaterial._ambientTexture : babylonPBRMaterial.ambientOcclusionTexture;
804823
if (ambientTexture) {
805824
promises.push(
806825
this.exportTextureAsync(ambientTexture, mimeType).then((glTFTexture) => {
@@ -812,7 +831,8 @@ export class GLTFMaterialExporter {
812831
};
813832

814833
glTFMaterial.occlusionTexture = occlusionTexture;
815-
const ambientTextureStrength = babylonPBRMaterial._ambientTextureStrength;
834+
const ambientTextureStrength =
835+
babylonPBRMaterial instanceof PBRBaseMaterial ? babylonPBRMaterial._ambientTextureStrength : babylonPBRMaterial.ambientOcclusionTexture.level;
816836
if (ambientTextureStrength) {
817837
occlusionTexture.strength = ambientTextureStrength;
818838
}
@@ -821,7 +841,7 @@ export class GLTFMaterialExporter {
821841
);
822842
}
823843

824-
const emissiveTexture = babylonPBRMaterial._emissiveTexture;
844+
const emissiveTexture = babylonPBRMaterial instanceof PBRBaseMaterial ? babylonPBRMaterial._emissiveTexture : babylonPBRMaterial.emissionColorTexture;
825845
if (emissiveTexture) {
826846
promises.push(
827847
this.exportTextureAsync(emissiveTexture, mimeType).then((glTFTexture) => {
@@ -838,14 +858,47 @@ export class GLTFMaterialExporter {
838858
}
839859
}
840860

841-
const emissiveColor = babylonPBRMaterial._emissiveColor;
861+
const emissiveColor = babylonPBRMaterial instanceof PBRBaseMaterial ? babylonPBRMaterial._emissiveColor : babylonPBRMaterial.emissionColor;
842862
if (!emissiveColor.equalsWithEpsilon(Black, Epsilon)) {
843863
glTFMaterial.emissiveFactor = emissiveColor.asArray();
844864
}
845865

846866
glTFMaterial.pbrMetallicRoughness = glTFPbrMetallicRoughness;
847867
}
848868

869+
public async exportOpenPBRMaterialAsync(babylonOpenPBRMaterial: OpenPBRMaterial, mimeType: ImageMimeType, hasUVs: boolean): Promise<number> {
870+
const glTFPbrMetallicRoughness: IMaterialPbrMetallicRoughness = {};
871+
872+
const glTFMaterial: IMaterial = {
873+
name: babylonOpenPBRMaterial.name,
874+
};
875+
876+
const albedoColor = babylonOpenPBRMaterial.baseColor;
877+
const alpha = babylonOpenPBRMaterial.geometryOpacity;
878+
if (albedoColor) {
879+
glTFPbrMetallicRoughness.baseColorFactor = [albedoColor.r, albedoColor.g, albedoColor.b, alpha];
880+
}
881+
882+
const metallicRoughness = await this._convertMetalRoughFactorsToMetallicRoughnessAsync(
883+
babylonOpenPBRMaterial.baseColor,
884+
babylonOpenPBRMaterial.baseMetalness,
885+
babylonOpenPBRMaterial.specularRoughness,
886+
babylonOpenPBRMaterial.baseColorTexture,
887+
babylonOpenPBRMaterial.baseMetalRoughTexture,
888+
babylonOpenPBRMaterial,
889+
mimeType,
890+
glTFPbrMetallicRoughness,
891+
hasUVs
892+
);
893+
894+
await this._setMetallicRoughnessPbrMaterialAsync(metallicRoughness, babylonOpenPBRMaterial, glTFMaterial, glTFPbrMetallicRoughness, mimeType, hasUVs);
895+
await this._finishMaterialAsync(glTFMaterial, babylonOpenPBRMaterial, mimeType);
896+
897+
const materials = this._exporter._materials;
898+
materials.push(glTFMaterial);
899+
return materials.length - 1;
900+
}
901+
849902
public async exportTextureAsync(babylonTexture: BaseTexture, mimeType: ImageMimeType): Promise<Nullable<ITextureInfo>> {
850903
const extensionPromise = this._exporter._extensionsPreExportTextureAsync("exporter", babylonTexture as Texture, mimeType);
851904
if (!extensionPromise) {

0 commit comments

Comments
 (0)