Sfoglia il codice sorgente

Merge pull request #9437 from Drigax/gltf-material-export-use-PBRBaseMaterial

Fix PBRSpecularGlossiness excluded from material export.
David Catuhe 4 anni fa
parent
commit
f2088280b9

+ 1 - 0
dist/preview release/what's new.md

@@ -37,6 +37,7 @@
 
 - Fix issue with the Promise polyfill where a return value was expected from resolve() ([Deltakosh](https://github.com/deltakosh))
 - Fix an issue with keyboard control (re)attachment. ([#9411](https://github.com/BabylonJS/Babylon.js/issues/9411)) ([RaananW](https://github.com/RaananW))
+- Fix issue where PBRSpecularGlossiness materials were excluded from export ([Drigax](https://github.com/drigax))
 - Fix direct loading of a glTF string that has base64-encoded URI. ([bghgary](https://github.com/bghgary))
 
 ## Breaking changes

+ 63 - 46
serializers/src/glTF/2.0/glTFMaterialExporter.ts

@@ -11,8 +11,11 @@ import { Texture } from "babylonjs/Materials/Textures/texture";
 import { RawTexture } from "babylonjs/Materials/Textures/rawTexture";
 import { Material } from "babylonjs/Materials/material";
 import { StandardMaterial } from "babylonjs/Materials/standardMaterial";
+import { PBRBaseMaterial } from "babylonjs/Materials/PBR/pbrBaseMaterial";
+import { PBRBaseSimpleMaterial } from "babylonjs/Materials/PBR/pbrBaseSimpleMaterial";
 import { PBRMaterial } from "babylonjs/Materials/PBR/pbrMaterial";
 import { PBRMetallicRoughnessMaterial } from "babylonjs/Materials/PBR/pbrMetallicRoughnessMaterial";
+import { PBRSpecularGlossinessMaterial } from "babylonjs/Materials/PBR/pbrSpecularGlossinessMaterial";
 import { PostProcess } from "babylonjs/PostProcesses/postProcess";
 import { Scene } from "babylonjs/scene";
 
@@ -128,10 +131,7 @@ export class _GLTFMaterialExporter {
             if (babylonMaterial instanceof StandardMaterial) {
                 promises.push(this._convertStandardMaterialAsync(babylonMaterial, mimeType, hasTextureCoords));
             }
-            else if (babylonMaterial instanceof PBRMetallicRoughnessMaterial) {
-                promises.push(this._convertPBRMetallicRoughnessMaterialAsync(babylonMaterial, mimeType, hasTextureCoords));
-            }
-            else if (babylonMaterial instanceof PBRMaterial) {
+            else if (babylonMaterial instanceof PBRBaseMaterial) {
                 promises.push(this._convertPBRMaterialAsync(babylonMaterial, mimeType, hasTextureCoords));
             }
             else {
@@ -846,24 +846,29 @@ export class _GLTFMaterialExporter {
      * @param hasTextureCoords specifies if texture coordinates are present on the submesh to determine if textures should be applied
      * @returns glTF PBR Metallic Roughness factors
      */
-    private _convertMetalRoughFactorsToMetallicRoughnessAsync(babylonPBRMaterial: PBRMaterial, mimeType: ImageMimeType, glTFPbrMetallicRoughness: IMaterialPbrMetallicRoughness, hasTextureCoords: boolean): Promise<_IPBRMetallicRoughness> {
+    private _convertMetalRoughFactorsToMetallicRoughnessAsync(babylonPBRMaterial: PBRBaseMaterial, mimeType: ImageMimeType, glTFPbrMetallicRoughness: IMaterialPbrMetallicRoughness, hasTextureCoords: boolean): Promise<_IPBRMetallicRoughness> {
         const promises = [];
+        const baseColor = (babylonPBRMaterial as PBRMaterial).albedoColor || (babylonPBRMaterial as PBRMetallicRoughnessMaterial).baseColor;
+        const metallic = (babylonPBRMaterial as PBRMaterial).metallic || (babylonPBRMaterial as PBRMetallicRoughnessMaterial).metallic;
+        const roughness = (babylonPBRMaterial as PBRMaterial).roughness || (babylonPBRMaterial as PBRMetallicRoughnessMaterial).roughness;
         const metallicRoughness: _IPBRMetallicRoughness = {
-            baseColor: babylonPBRMaterial.albedoColor,
-            metallic: babylonPBRMaterial.metallic,
-            roughness: babylonPBRMaterial.roughness
+            baseColor: baseColor,
+            metallic: metallic,
+            roughness: roughness
         };
 
         if (hasTextureCoords) {
-            if (babylonPBRMaterial.albedoTexture) {
-                promises.push(this._exportTextureAsync(babylonPBRMaterial.albedoTexture, mimeType).then((glTFTexture) => {
+            const albedoTexture = (babylonPBRMaterial as PBRMaterial).albedoTexture || (babylonPBRMaterial as PBRMetallicRoughnessMaterial).baseTexture;
+            if (albedoTexture) {
+                promises.push(this._exportTextureAsync((babylonPBRMaterial as any).albedoTexture, mimeType).then((glTFTexture) => {
                     if (glTFTexture) {
                         glTFPbrMetallicRoughness.baseColorTexture = glTFTexture;
                     }
                 }));
             }
-            if (babylonPBRMaterial.metallicTexture) {
-                promises.push(this._exportTextureAsync(babylonPBRMaterial.metallicTexture, mimeType).then((glTFTexture) => {
+            const metallicTexture = (babylonPBRMaterial as PBRMaterial).metallicTexture || (babylonPBRMaterial as PBRMetallicRoughnessMaterial).metallicRoughnessTexture;
+            if (metallicTexture) {
+                promises.push(this._exportTextureAsync(metallicTexture, mimeType).then((glTFTexture) => {
                     if (glTFTexture) {
                         glTFPbrMetallicRoughness.metallicRoughnessTexture = glTFTexture;
                     }
@@ -986,34 +991,40 @@ export class _GLTFMaterialExporter {
      * @param hasTextureCoords specifies if texture coordinates are present on the submesh to determine if textures should be applied
      * @returns glTF PBR Metallic Roughness factors
      */
-    private _convertSpecGlossFactorsToMetallicRoughnessAsync(babylonPBRMaterial: PBRMaterial, mimeType: ImageMimeType, glTFPbrMetallicRoughness: IMaterialPbrMetallicRoughness, hasTextureCoords: boolean): Promise<_IPBRMetallicRoughness> {
+    private _convertSpecGlossFactorsToMetallicRoughnessAsync(babylonPBRMaterial: PBRBaseMaterial, mimeType: ImageMimeType, glTFPbrMetallicRoughness: IMaterialPbrMetallicRoughness, hasTextureCoords: boolean): Promise<_IPBRMetallicRoughness> {
         return Promise.resolve().then(() => {
             const samplers = this._exporter._samplers;
             const textures = this._exporter._textures;
+            const diffuseColor = (babylonPBRMaterial as PBRMaterial).albedoColor || (babylonPBRMaterial as PBRSpecularGlossinessMaterial).diffuseColor || Color3.White();
+            const specularColor = (babylonPBRMaterial as PBRMaterial).reflectivityColor || (babylonPBRMaterial as PBRSpecularGlossinessMaterial).specularColor || Color3.White();
+            const glossiness = (babylonPBRMaterial as PBRMaterial).microSurface || (babylonPBRMaterial as PBRSpecularGlossinessMaterial).glossiness || 1;
             const specGloss: _IPBRSpecularGlossiness = {
-                diffuseColor: babylonPBRMaterial.albedoColor || Color3.White(),
-                specularColor: babylonPBRMaterial.reflectivityColor || Color3.White(),
-                glossiness: babylonPBRMaterial.microSurface || 1,
+                diffuseColor: diffuseColor,
+                specularColor: specularColor,
+                glossiness: glossiness,
             };
             let samplerIndex: Nullable<number> = null;
-            const sampler = this._getGLTFTextureSampler(babylonPBRMaterial.albedoTexture);
+            const albedoTexture = (babylonPBRMaterial as PBRMaterial).albedoTexture || (babylonPBRMaterial as PBRSpecularGlossinessMaterial).diffuseTexture;
+            const reflectivityTexture = (babylonPBRMaterial as PBRMaterial).reflectivityTexture || (babylonPBRMaterial as PBRSpecularGlossinessMaterial).specularGlossinessTexture;
+            const sampler = this._getGLTFTextureSampler(albedoTexture);
             if (sampler.magFilter != null && sampler.minFilter != null && sampler.wrapS != null && sampler.wrapT != null) {
                 samplers.push(sampler);
                 samplerIndex = samplers.length - 1;
             }
-            if (babylonPBRMaterial.reflectivityTexture && !babylonPBRMaterial.useMicroSurfaceFromReflectivityMapAlpha) {
+            const useMicrosurfaceFromReflectivityMapAlpha = (babylonPBRMaterial as PBRMaterial).useMicroSurfaceFromReflectivityMapAlpha || (babylonPBRMaterial as PBRSpecularGlossinessMaterial).useMicroSurfaceFromReflectivityMapAlpha;
+            if (reflectivityTexture  && !useMicrosurfaceFromReflectivityMapAlpha) {
                 return Promise.reject("_ConvertPBRMaterial: Glossiness values not included in the reflectivity texture are currently not supported");
             }
-            if ((babylonPBRMaterial.albedoTexture || babylonPBRMaterial.reflectivityTexture) && hasTextureCoords) {
-                return this._convertSpecularGlossinessTexturesToMetallicRoughnessAsync(babylonPBRMaterial.albedoTexture, babylonPBRMaterial.reflectivityTexture, specGloss, mimeType).then((metallicRoughnessFactors) => {
+            if ((albedoTexture || reflectivityTexture) && hasTextureCoords) {
+                return this._convertSpecularGlossinessTexturesToMetallicRoughnessAsync(albedoTexture, reflectivityTexture, specGloss, mimeType).then((metallicRoughnessFactors) => {
                     if (metallicRoughnessFactors.baseColorTextureBase64) {
-                        const glTFBaseColorTexture = this._getTextureInfoFromBase64(metallicRoughnessFactors.baseColorTextureBase64, "bjsBaseColorTexture_" + (textures.length) + ".png", mimeType, babylonPBRMaterial.albedoTexture ? babylonPBRMaterial.albedoTexture.coordinatesIndex : null, samplerIndex);
+                        const glTFBaseColorTexture = this._getTextureInfoFromBase64(metallicRoughnessFactors.baseColorTextureBase64, "bjsBaseColorTexture_" + (textures.length) + ".png", mimeType, albedoTexture ? albedoTexture.coordinatesIndex : null, samplerIndex);
                         if (glTFBaseColorTexture) {
                             glTFPbrMetallicRoughness.baseColorTexture = glTFBaseColorTexture;
                         }
                     }
                     if (metallicRoughnessFactors.metallicRoughnessTextureBase64) {
-                        const glTFMRColorTexture = this._getTextureInfoFromBase64(metallicRoughnessFactors.metallicRoughnessTextureBase64, "bjsMetallicRoughnessTexture_" + (textures.length) + ".png", mimeType, babylonPBRMaterial.reflectivityTexture ? babylonPBRMaterial.reflectivityTexture.coordinatesIndex : null, samplerIndex);
+                        const glTFMRColorTexture = this._getTextureInfoFromBase64(metallicRoughnessFactors.metallicRoughnessTextureBase64, "bjsMetallicRoughnessTexture_" + (textures.length) + ".png", mimeType, reflectivityTexture ? reflectivityTexture.coordinatesIndex : null, samplerIndex);
                         if (glTFMRColorTexture) {
                             glTFPbrMetallicRoughness.metallicRoughnessTexture = glTFMRColorTexture;
                         }
@@ -1029,8 +1040,8 @@ export class _GLTFMaterialExporter {
     }
 
     /**
-     * Converts a Babylon PBR Metallic Roughness Material to a glTF Material
-     * @param babylonPBRMaterial BJS PBR Metallic Roughness Material
+     * Converts a Babylon PBR Base Material to a glTF Material
+     * @param babylonPBRMaterial BJS PBR Base Material
      * @param mimeType mime type to use for the textures
      * @param images array of glTF image interfaces
      * @param textures array of glTF texture interfaces
@@ -1038,7 +1049,7 @@ export class _GLTFMaterialExporter {
      * @param imageData map of image file name to data
      * @param hasTextureCoords specifies if texture coordinates are present on the submesh to determine if textures should be applied
      */
-    public _convertPBRMaterialAsync(babylonPBRMaterial: PBRMaterial, mimeType: ImageMimeType, hasTextureCoords: boolean): Promise<IMaterial> {
+    public _convertPBRMaterialAsync(babylonPBRMaterial: PBRBaseMaterial, mimeType: ImageMimeType, hasTextureCoords: boolean): Promise<IMaterial> {
         const glTFPbrMetallicRoughness: IMaterialPbrMetallicRoughness = {};
         const glTFMaterial: IMaterial = {
             name: babylonPBRMaterial.name
@@ -1046,12 +1057,14 @@ export class _GLTFMaterialExporter {
         const useMetallicRoughness = babylonPBRMaterial.isMetallicWorkflow();
 
         if (useMetallicRoughness) {
-            if (babylonPBRMaterial.albedoColor) {
+            const albedoColor = (babylonPBRMaterial as PBRMaterial).albedoColor || (babylonPBRMaterial as PBRSpecularGlossinessMaterial).diffuseColor || (babylonPBRMaterial as PBRMetallicRoughnessMaterial).baseColor;
+            const alpha = babylonPBRMaterial.alpha;
+            if (albedoColor) {
                 glTFPbrMetallicRoughness.baseColorFactor = [
-                    babylonPBRMaterial.albedoColor.r,
-                    babylonPBRMaterial.albedoColor.g,
-                    babylonPBRMaterial.albedoColor.b,
-                    babylonPBRMaterial.alpha
+                    albedoColor.r,
+                    albedoColor.g,
+                    albedoColor.b,
+                    alpha
                 ];
             }
             return this._convertMetalRoughFactorsToMetallicRoughnessAsync(babylonPBRMaterial, mimeType, glTFPbrMetallicRoughness, hasTextureCoords).then((metallicRoughness) => {
@@ -1065,12 +1078,12 @@ export class _GLTFMaterialExporter {
         }
     }
 
-    private setMetallicRoughnessPbrMaterial(metallicRoughness: Nullable<_IPBRMetallicRoughness>, babylonPBRMaterial: PBRMaterial, glTFMaterial: IMaterial, glTFPbrMetallicRoughness: IMaterialPbrMetallicRoughness, mimeType: ImageMimeType, hasTextureCoords: boolean): Promise<IMaterial> {
+    private setMetallicRoughnessPbrMaterial(metallicRoughness: Nullable<_IPBRMetallicRoughness>, babylonPBRMaterial: PBRBaseMaterial, glTFMaterial: IMaterial, glTFPbrMetallicRoughness: IMaterialPbrMetallicRoughness, mimeType: ImageMimeType, hasTextureCoords: boolean): Promise<IMaterial> {
         const materialMap = this._exporter._materialMap;
         const materials = this._exporter._materials;
         let promises = [];
         if (metallicRoughness) {
-            _GLTFMaterialExporter._SetAlphaMode(glTFMaterial, babylonPBRMaterial);
+            _GLTFMaterialExporter._SetAlphaMode(glTFMaterial, (babylonPBRMaterial as PBRMaterial));
             if (!(_GLTFMaterialExporter.FuzzyEquals(metallicRoughness.baseColor, Color3.White(), _GLTFMaterialExporter._Epsilon) && babylonPBRMaterial.alpha >= _GLTFMaterialExporter._Epsilon)) {
                 glTFPbrMetallicRoughness.baseColorFactor = [
                     metallicRoughness.baseColor.r,
@@ -1088,19 +1101,20 @@ export class _GLTFMaterialExporter {
             }
 
             if (babylonPBRMaterial.backFaceCulling != null && !babylonPBRMaterial.backFaceCulling) {
-                if (!babylonPBRMaterial.twoSidedLighting) {
+                if (!((babylonPBRMaterial as PBRMaterial).twoSidedLighting || (babylonPBRMaterial as PBRBaseSimpleMaterial).doubleSided)) {
                     Tools.Warn(babylonPBRMaterial.name + ": Back-face culling enabled and two-sided lighting disabled is not supported in glTF.");
                 }
                 glTFMaterial.doubleSided = true;
             }
 
             if (hasTextureCoords) {
-                if (babylonPBRMaterial.bumpTexture) {
-                    let promise = this._exportTextureAsync(babylonPBRMaterial.bumpTexture, mimeType).then((glTFTexture) => {
+                const bumpTexture = (babylonPBRMaterial as PBRMaterial).bumpTexture || (babylonPBRMaterial as PBRBaseSimpleMaterial).normalTexture;
+                if (bumpTexture) {
+                    let promise = this._exportTextureAsync(bumpTexture, mimeType).then((glTFTexture) => {
                         if (glTFTexture) {
                             glTFMaterial.normalTexture = glTFTexture;
-                            if (babylonPBRMaterial.bumpTexture.level !== 1) {
-                                glTFMaterial.normalTexture.scale = babylonPBRMaterial.bumpTexture.level;
+                            if (bumpTexture.level !== 1) {
+                                glTFMaterial.normalTexture.scale = bumpTexture.level;
                             }
                         }
                     }
@@ -1108,8 +1122,9 @@ export class _GLTFMaterialExporter {
                     promises.push(promise);
 
                 }
-                if (babylonPBRMaterial.ambientTexture) {
-                    let promise = this._exportTextureAsync(babylonPBRMaterial.ambientTexture, mimeType).then((glTFTexture) => {
+                const ambientTexture = (babylonPBRMaterial as PBRMaterial).ambientTexture || (babylonPBRMaterial as PBRBaseSimpleMaterial).occlusionTexture;
+                if (ambientTexture) {
+                    let promise = this._exportTextureAsync(ambientTexture, mimeType).then((glTFTexture) => {
                         if (glTFTexture) {
                             let occlusionTexture: IMaterialOcclusionTextureInfo = {
                                 index: glTFTexture.index,
@@ -1117,17 +1132,18 @@ export class _GLTFMaterialExporter {
                             };
 
                             glTFMaterial.occlusionTexture = occlusionTexture;
-
-                            if (babylonPBRMaterial.ambientTextureStrength) {
-                                occlusionTexture.strength = babylonPBRMaterial.ambientTextureStrength;
+                            const ambientTextureStrength = (babylonPBRMaterial as PBRMaterial).ambientTextureStrength || (babylonPBRMaterial as PBRBaseSimpleMaterial).occlusionStrength;
+                            if (ambientTextureStrength) {
+                                occlusionTexture.strength = ambientTextureStrength;
                             }
                         }
                     });
                     promises.push(promise);
 
                 }
-                if (babylonPBRMaterial.emissiveTexture) {
-                    let promise = this._exportTextureAsync(babylonPBRMaterial.emissiveTexture, mimeType).then((glTFTexture) => {
+                const emissiveTexture = (babylonPBRMaterial as PBRMaterial).emissiveTexture || (babylonPBRMaterial as PBRBaseSimpleMaterial).emissiveTexture;
+                if (emissiveTexture) {
+                    let promise = this._exportTextureAsync(emissiveTexture, mimeType).then((glTFTexture) => {
                         if (glTFTexture) {
                             glTFMaterial.emissiveTexture = glTFTexture;
                         }
@@ -1135,8 +1151,9 @@ export class _GLTFMaterialExporter {
                     promises.push(promise);
                 }
             }
-            if (!_GLTFMaterialExporter.FuzzyEquals(babylonPBRMaterial.emissiveColor, Color3.Black(), _GLTFMaterialExporter._Epsilon)) {
-                glTFMaterial.emissiveFactor = babylonPBRMaterial.emissiveColor.asArray();
+            const emissiveColor = (babylonPBRMaterial as PBRMaterial).emissiveColor || (babylonPBRMaterial as PBRBaseSimpleMaterial).emissiveColor;
+            if (!_GLTFMaterialExporter.FuzzyEquals(emissiveColor, Color3.Black(), _GLTFMaterialExporter._Epsilon)) {
+                glTFMaterial.emissiveFactor = emissiveColor.asArray();
             }
 
             glTFMaterial.pbrMetallicRoughness = glTFPbrMetallicRoughness;

+ 7 - 0
src/Materials/PBR/pbrSpecularGlossinessMaterial.ts

@@ -50,6 +50,13 @@ export class PBRSpecularGlossinessMaterial extends PBRBaseSimpleMaterial {
     public specularGlossinessTexture: BaseTexture;
 
     /**
+     * Specifies if the reflectivity texture contains the glossiness information in its alpha channel.
+    */
+    public get useMicroSurfaceFromReflectivityMapAlpha() {
+        return this._useMicroSurfaceFromReflectivityMapAlpha;
+    }
+
+    /**
      * Instantiates a new PBRSpecularGlossinessMaterial instance.
      *
      * @param name The material name