浏览代码

glTFSerializer: Exported textures no longer premultiplied with canvas

Kacey Coley 7 年之前
父节点
当前提交
2847a88769

+ 1 - 1
Playground/js/index.js

@@ -483,7 +483,7 @@
                 var code = jsEditor.getValue();
 
                 var createDefaultEngine = function () {
-                    return new BABYLON.Engine(canvas, true, { preserveDrawingBuffer: true, stencil: true });
+                    return new BABYLON.Engine(canvas, true, { premultipliedAlpha: false, preserveDrawingBuffer: true, stencil: true });
                 }
 
                 var scene;

+ 0 - 3
Tools/Gulp/config.json

@@ -1695,9 +1695,6 @@
                     "../../serializers/src/glTF/2.0/babylon.glTFAnimation.ts",
                     "../../serializers/src/glTF/2.0/babylon.glTFUtilities.ts"
                 ],
-                "shaderFiles": [
-                    "../../serializers/src/glTF/2.0/shaders/setAlphaToOne.fragment.fx"
-                ],
                 "output": "babylon.glTF2Serializer.js"
             }
         ],

+ 10 - 0
serializers/src/glTF/2.0/babylon.glTFExporter.ts

@@ -618,12 +618,22 @@ module BABYLON.GLTF2 {
         }
 
         /**
+         * Resets the exporter variables
+         */
+        private _resetExporter() {
+            _GLTFMaterial._Reset();
+        }
+
+        /**
          * Creates a binary buffer for glTF
          * @returns array buffer for binary data
          */
         private _generateBinaryAsync(): Promise<ArrayBuffer> {
             let binaryWriter = new _BinaryWriter(4);
             return this.createSceneAsync(this.babylonScene, binaryWriter).then(() => {
+                // reset the material map and texture map
+                this._resetExporter();
+                
                 return binaryWriter.getArrayBuffer();
             });
         }

+ 246 - 169
serializers/src/glTF/2.0/babylon.glTFMaterial.ts

@@ -62,12 +62,26 @@ module BABYLON.GLTF2 {
          */
         private static _maxSpecularPower = 1024;
 
+
+        private static _localEngine: Engine;
+
+        private static _localCanvas: HTMLCanvasElement;
+
+        private static _textureMap: { [textureId: string]: ITextureInfo } = {};
+
         /**
          * Numeric tolerance value
          */
         private static _epsilon = 1e-6;
 
         /**
+         * Reset the material static variables
+         */
+        public static _Reset() {
+            this._textureMap = {};
+        }
+
+        /**
          * Specifies if two colors are approximately equal in value
          * @param color1 first color to compare to
          * @param color2 second color to compare to
@@ -242,7 +256,7 @@ module BABYLON.GLTF2 {
             if (babylonMaterial.needAlphaBlending()) {
                 return MaterialAlphaMode.BLEND;
             }
-            else if (babylonMaterial.needAlphaTesting) {
+            else if (babylonMaterial.needAlphaTesting()) {
                 return MaterialAlphaMode.MASK;
             }
             else {
@@ -262,7 +276,6 @@ module BABYLON.GLTF2 {
          */
         public static _ConvertStandardMaterialAsync(babylonStandardMaterial: StandardMaterial, mimeType: ImageMimeType, images: IImage[], textures: ITexture[], samplers: ISampler[], materials: IMaterial[], materialMap: { [materialID: number]: number }, imageData: { [fileName: string]: { data: Uint8Array, mimeType: ImageMimeType } }, hasTextureCoords: boolean): Promise<void> {
             const alphaMode = this._GetAlphaMode(babylonStandardMaterial);
-            let useAlpha = alphaMode !== MaterialAlphaMode.OPAQUE ? true : false;
             let promises = [];
             const glTFPbrMetallicRoughness = _GLTFMaterial._ConvertToGLTFPBRMetallicRoughness(babylonStandardMaterial);
 
@@ -275,44 +288,69 @@ module BABYLON.GLTF2 {
             }
             if (hasTextureCoords) {
                 if (babylonStandardMaterial.diffuseTexture) {
-                    let promise = _GLTFMaterial._ExportTextureAsync(babylonStandardMaterial.diffuseTexture, mimeType, images, textures, samplers, imageData, useAlpha).then(glTFTexture => {
-                        if (glTFTexture) {
-                            glTFPbrMetallicRoughness.baseColorTexture = glTFTexture;
-                        }
-                    });
-                    promises.push(promise);
+                    if (babylonStandardMaterial.diffuseTexture.uid in this._textureMap) {
+                        glTFPbrMetallicRoughness.baseColorTexture = this._textureMap[babylonStandardMaterial.diffuseTexture.uid];
+                    }
+                    else {
+                        let promise = _GLTFMaterial._ExportTextureAsync(babylonStandardMaterial.diffuseTexture, mimeType, images, textures, samplers, imageData).then(glTFTexture => {
+                            if (glTFTexture) {
+                                glTFPbrMetallicRoughness.baseColorTexture = glTFTexture;
+                                this._textureMap[babylonStandardMaterial.diffuseTexture!.uid] = glTFTexture;
+                            }
+                        });
+                        promises.push(promise);
+                    }
                 }
                 if (babylonStandardMaterial.bumpTexture) {
-                    let promise = _GLTFMaterial._ExportTextureAsync(babylonStandardMaterial.bumpTexture, mimeType, images, textures, samplers, imageData, useAlpha).then(glTFTexture => {
-                        if (glTFTexture) {
-                            glTFMaterial.normalTexture = glTFTexture;
-                            if (babylonStandardMaterial.bumpTexture != null && babylonStandardMaterial.bumpTexture.level !== 1) {
-                                glTFMaterial.normalTexture.scale = babylonStandardMaterial.bumpTexture.level;
+                    if (babylonStandardMaterial.bumpTexture.uid in this._textureMap) {
+                        glTFMaterial.normalTexture = this._textureMap[babylonStandardMaterial.bumpTexture.uid];
+                    }
+                    else {
+                        let promise = _GLTFMaterial._ExportTextureAsync(babylonStandardMaterial.bumpTexture, mimeType, images, textures, samplers, imageData).then(glTFTexture => {
+                            if (glTFTexture) {
+                                glTFMaterial.normalTexture = glTFTexture;
+                                if (babylonStandardMaterial.bumpTexture != null && babylonStandardMaterial.bumpTexture.level !== 1) {
+                                    glTFMaterial.normalTexture.scale = babylonStandardMaterial.bumpTexture.level;
+                                }
+                                this._textureMap[babylonStandardMaterial.bumpTexture!.uid] = glTFTexture;
                             }
-                        }
-                    });
-                    promises.push(promise);
+                        });
+                        promises.push(promise);
+                    }
                 }
                 if (babylonStandardMaterial.emissiveTexture) {
-                    let promise = _GLTFMaterial._ExportTextureAsync(babylonStandardMaterial.emissiveTexture, mimeType, images, textures, samplers, imageData, useAlpha).then(glTFEmissiveTexture => {
-                        if (glTFEmissiveTexture) {
-                            glTFMaterial.emissiveTexture = glTFEmissiveTexture;
-                        }
-                        glTFMaterial.emissiveFactor = [1.0, 1.0, 1.0];
-                    });
-                    promises.push(promise);
+                    glTFMaterial.emissiveFactor = [1.0, 1.0, 1.0];
+                    if (babylonStandardMaterial.emissiveTexture.uid in this._textureMap) {
+                        glTFMaterial.emissiveTexture = this._textureMap[babylonStandardMaterial.emissiveTexture.uid];
+                    }
+                    else {
+                        let promise = _GLTFMaterial._ExportTextureAsync(babylonStandardMaterial.emissiveTexture, mimeType, images, textures, samplers, imageData).then(glTFEmissiveTexture => {
+                            if (glTFEmissiveTexture) {
+                                glTFMaterial.emissiveTexture = glTFEmissiveTexture;
+                                this._textureMap[babylonStandardMaterial.emissiveTexture!.uid] = glTFEmissiveTexture;
+                            }
+                        });
+                        promises.push(promise);
+                    }
                 }
                 if (babylonStandardMaterial.ambientTexture) {
-                    let promise = _GLTFMaterial._ExportTextureAsync(babylonStandardMaterial.ambientTexture, mimeType, images, textures, samplers, imageData, useAlpha).then(glTFTexture => {
-                        if (glTFTexture) {
-                            const occlusionTexture: IMaterialOcclusionTextureInfo = {
-                                index: glTFTexture.index
-                            };
-                            glTFMaterial.occlusionTexture = occlusionTexture;
-                            occlusionTexture.strength = 1.0;
-                        }
-                    });
-                    promises.push(promise);
+                    if (babylonStandardMaterial.ambientTexture.uid in this._textureMap) {
+                        glTFMaterial.occlusionTexture = this._textureMap[babylonStandardMaterial.ambientTexture.uid];
+                    }
+                    else {
+                        let promise = _GLTFMaterial._ExportTextureAsync(babylonStandardMaterial.ambientTexture, mimeType, images, textures, samplers, imageData).then(glTFTexture => {
+                            if (glTFTexture) {
+                                const occlusionTexture: IMaterialOcclusionTextureInfo = {
+                                    index: glTFTexture.index
+                                };
+                                glTFMaterial.occlusionTexture = occlusionTexture;
+                                occlusionTexture.strength = 1.0;
+
+                                this._textureMap[babylonStandardMaterial.ambientTexture!.uid] = occlusionTexture;
+                            }
+                        });
+                        promises.push(promise);
+                    }
                 }
             }
 
@@ -353,40 +391,6 @@ module BABYLON.GLTF2 {
         }
 
         /**
-         * 
-         * @param texture Texture with alpha to overwrite to one
-         * @param useAlpha Specifies if alpha should be preserved or not
-         * @returns Promise with texture
-         */
-        public static _SetAlphaToOneAsync(texture: BaseTexture, useAlpha: boolean): Promise<BaseTexture> {
-            return new Promise((resolve, reject) => {
-                if (useAlpha) {
-                    resolve(texture);
-                }
-                else {
-                    if (texture instanceof Texture) {
-                        const scene = texture.getScene();
-                        if (scene) {
-                            const proceduralTexture = new ProceduralTexture('texture', texture.getSize(), 'setAlphaToOne', scene);
-
-                            proceduralTexture.setTexture('textureSampler', texture);
-                            proceduralTexture.onGenerated = () => {
-                                resolve(proceduralTexture);
-                            };
-                        }
-                        else {
-                            reject(`Scene not available for texture ${texture.name}`);
-                        }
-                    }
-                    else {
-                        Tools.Warn(`Removing alpha for ${texture.textureType} not supported`);
-                        resolve(texture);
-                    }
-                }
-            });
-        }
-
-        /**
          * Converts a Babylon PBR Metallic Roughness Material to a glTF Material
          * @param babylonPBRMetalRoughMaterial BJS PBR Metallic Roughness Material
          * @param mimeType mime type to use for the textures
@@ -423,7 +427,6 @@ module BABYLON.GLTF2 {
                 glTFMaterial.doubleSided = babylonPBRMetalRoughMaterial.doubleSided;
             }
             let alphaMode: Nullable<MaterialAlphaMode> = null;
-            let useAlpha = false;
             if (babylonPBRMetalRoughMaterial.transparencyMode != null) {
                 alphaMode = _GLTFMaterial._GetAlphaMode(babylonPBRMetalRoughMaterial);
                 if (alphaMode) {
@@ -435,48 +438,66 @@ module BABYLON.GLTF2 {
                     }
                 }
             }
-            if (alphaMode !== MaterialAlphaMode.OPAQUE) {
-                useAlpha = true;
-            }
-
             if (hasTextureCoords) {
                 if (babylonPBRMetalRoughMaterial.baseTexture != null) {
-                    let promise = _GLTFMaterial._ExportTextureAsync(babylonPBRMetalRoughMaterial.baseTexture, mimeType, images, textures, samplers, imageData, useAlpha).then(glTFTexture => {
-                        if (glTFTexture) {
-                            glTFPbrMetallicRoughness.baseColorTexture = glTFTexture;
-                        }
-                    });
-                    promises.push(promise);
+                    if (babylonPBRMetalRoughMaterial.baseTexture.uid in this._textureMap) {
+                        glTFPbrMetallicRoughness.baseColorTexture = this._textureMap[babylonPBRMetalRoughMaterial.baseTexture.uid];
+                    }
+                    else {
+                        let promise = _GLTFMaterial._ExportTextureAsync(babylonPBRMetalRoughMaterial.baseTexture, mimeType, images, textures, samplers, imageData).then(glTFTexture => {
+                            if (glTFTexture) {
+                                glTFPbrMetallicRoughness.baseColorTexture = glTFTexture;
+                            }
+                        });
+                        promises.push(promise);
+                    }
                 }
                 if (babylonPBRMetalRoughMaterial.normalTexture) {
-                    let promise = _GLTFMaterial._ExportTextureAsync(babylonPBRMetalRoughMaterial.normalTexture, mimeType, images, textures, samplers, imageData, useAlpha).then(glTFTexture => {
-                        if (glTFTexture) {
-                            glTFMaterial.normalTexture = glTFTexture;
-                            if (babylonPBRMetalRoughMaterial.normalTexture.level !== 1) {
-                                glTFMaterial.normalTexture.scale = babylonPBRMetalRoughMaterial.normalTexture.level;
+                    if (babylonPBRMetalRoughMaterial.normalTexture.uid in this._textureMap) {
+                        glTFMaterial.normalTexture = this._textureMap[babylonPBRMetalRoughMaterial.normalTexture.uid];
+                    }
+                    else {
+                        let promise = _GLTFMaterial._ExportTextureAsync(babylonPBRMetalRoughMaterial.normalTexture, mimeType, images, textures, samplers, imageData).then(glTFTexture => {
+                            if (glTFTexture) {
+                                glTFMaterial.normalTexture = glTFTexture;
+                                if (babylonPBRMetalRoughMaterial.normalTexture.level !== 1) {
+                                    glTFMaterial.normalTexture.scale = babylonPBRMetalRoughMaterial.normalTexture.level;
+                                }
                             }
-                        }
-                    });
-                    promises.push(promise);
+                        });
+                        promises.push(promise);
+                    }
                 }
                 if (babylonPBRMetalRoughMaterial.occlusionTexture) {
-                    let promise = _GLTFMaterial._ExportTextureAsync(babylonPBRMetalRoughMaterial.occlusionTexture, mimeType, images, textures, samplers, imageData, useAlpha).then(glTFTexture => {
-                        if (glTFTexture) {
-                            glTFMaterial.occlusionTexture = glTFTexture;
-                            if (babylonPBRMetalRoughMaterial.occlusionStrength != null) {
-                                glTFMaterial.occlusionTexture.strength = babylonPBRMetalRoughMaterial.occlusionStrength;
+                    if (babylonPBRMetalRoughMaterial.occlusionTexture.uid in this._textureMap) {
+                        glTFMaterial.occlusionTexture = this._textureMap[babylonPBRMetalRoughMaterial.occlusionTexture.uid];
+                    }
+                    else {
+                        let promise = _GLTFMaterial._ExportTextureAsync(babylonPBRMetalRoughMaterial.occlusionTexture, mimeType, images, textures, samplers, imageData).then(glTFTexture => {
+                            if (glTFTexture) {
+                                glTFMaterial.occlusionTexture = glTFTexture;
+                                if (babylonPBRMetalRoughMaterial.occlusionStrength != null) {
+                                    glTFMaterial.occlusionTexture.strength = babylonPBRMetalRoughMaterial.occlusionStrength;
+                                }
+                                this._textureMap[babylonPBRMetalRoughMaterial.occlusionTexture.uid] = glTFTexture;
                             }
-                        }
-                    });
-                    promises.push(promise);
+                        });
+                        promises.push(promise);
+                    }
                 }
                 if (babylonPBRMetalRoughMaterial.emissiveTexture) {
-                    let promise = _GLTFMaterial._ExportTextureAsync(babylonPBRMetalRoughMaterial.emissiveTexture, mimeType, images, textures, samplers, imageData, useAlpha).then(glTFTexture => {
-                        if (glTFTexture) {
-                            glTFMaterial.emissiveTexture = glTFTexture;
-                        }
-                    });
-                    promises.push(promise);
+                    if (babylonPBRMetalRoughMaterial.emissiveTexture.uid in this._textureMap) {
+                        glTFMaterial.emissiveTexture = this._textureMap[babylonPBRMetalRoughMaterial.emissiveTexture.uid];
+                    }
+                    else {
+                        let promise = _GLTFMaterial._ExportTextureAsync(babylonPBRMetalRoughMaterial.emissiveTexture, mimeType, images, textures, samplers, imageData).then(glTFTexture => {
+                            if (glTFTexture) {
+                                this._textureMap[babylonPBRMetalRoughMaterial.emissiveTexture.uid] = glTFTexture;
+                                glTFMaterial.emissiveTexture = glTFTexture;
+                            }
+                        });
+                        promises.push(promise);
+                    }
                 }
             }
 
@@ -500,20 +521,64 @@ module BABYLON.GLTF2 {
          * @param mimeType mimetype of the image
          * @returns base64 image string
          */
-        private static _CreateBase64FromCanvas(buffer: Uint8ClampedArray | Float32Array, width: number, height: number, mimeType: ImageMimeType): string {
-            const imageCanvas = document.createElement('canvas');
-            imageCanvas.width = width;
-            imageCanvas.height = height;
-            imageCanvas.id = "WriteCanvas";
+        private static _CreateBase64FromCanvasAsync(buffer: Uint8ClampedArray | Float32Array, width: number, height: number, mimeType: ImageMimeType): Promise<string> {
+            return new Promise((resolve, reject) => {
+                // Create an image canvas
+                if (!this._localCanvas) {
+                    this._localCanvas = document.createElement('canvas');
+                    this._localCanvas.id = "WriteCanvas";
+                }
 
-            const ctx = imageCanvas.getContext('2d') as CanvasRenderingContext2D;
+                this._localCanvas.width = width;
+                this._localCanvas.height = height;
+                
+                let hostingScene: Scene;
 
-            const imgData = ctx.createImageData(width, height);
+                if (!this._localEngine) {
+                    this._localEngine = new Engine(this._localCanvas, true, { premultipliedAlpha: false, preserveDrawingBuffer: true });
+                }
 
-            imgData.data.set(buffer);
-            ctx.putImageData(imgData, 0, 0);
+                let textureType = Engine.TEXTURETYPE_UNSIGNED_INT;
+                hostingScene = new Scene(this._localEngine);
 
-            return imageCanvas.toDataURL(mimeType);
+                // Create a temporary texture with the texture buffer data
+                let tempTexture = this._localEngine.createRawTexture(buffer, width, height, Engine.TEXTUREFORMAT_RGBA, false, true, Texture.NEAREST_SAMPLINGMODE, null, textureType);
+                let rgbdPostProcess = new PostProcess("pass", "pass", null, null, 1, null, Texture.NEAREST_SAMPLINGMODE, this._localEngine, false, undefined, Engine.TEXTURETYPE_UNSIGNED_INT, undefined, null, false);
+                rgbdPostProcess.getEffect().executeWhenCompiled(() => {
+                    rgbdPostProcess.onApply = (effect) => {
+                        effect._bindTexture("textureSampler", tempTexture);
+                    }
+
+                    // Track the main canvas's size since it is used to process the texture
+                    let currentW = this._localEngine.getRenderWidth();
+                    let currentH = this._localEngine.getRenderHeight();
+
+                    // Set the size of the texture
+                    this._localEngine.setSize(width, height);
+                    this._localEngine.setDirectViewport(0,0,width, height);
+                    hostingScene.postProcessManager.directRender([rgbdPostProcess], null);
+                    tempTexture.dispose();
+
+                    // Read data from WebGL
+                    this._localCanvas.toBlob((blob) => {
+                        if (blob) {
+                            let fileReader = new FileReader();
+                            fileReader.onload = (event: any) => {
+                                let base64String = event.target.result as string;
+                                hostingScene.dispose();
+                                resolve(base64String);
+                            };
+                            fileReader.readAsDataURL(blob);
+                        }
+                        else {
+                            reject("Failed to get blob from image canvas!");
+                        }
+                    });
+
+                    // Reapply the previous canvas size
+                    this._localEngine.setSize(currentW, currentH);
+                });
+            });
         }
 
         /**
@@ -587,10 +652,10 @@ module BABYLON.GLTF2 {
          * @param mimeType the mime type to use for the texture
          * @returns pbr metallic roughness interface or null
          */
-        private static _ConvertSpecularGlossinessTexturesToMetallicRoughness(diffuseTexture: BaseTexture, specularGlossinessTexture: BaseTexture, factors: _IPBRSpecularGlossiness, mimeType: ImageMimeType): Nullable<_IPBRMetallicRoughness> {
+        private static _ConvertSpecularGlossinessTexturesToMetallicRoughnessAsync(diffuseTexture: BaseTexture, specularGlossinessTexture: BaseTexture, factors: _IPBRSpecularGlossiness, mimeType: ImageMimeType): Promise<Nullable<_IPBRMetallicRoughness>> {
+            let promises = [];
             if (!(diffuseTexture || specularGlossinessTexture)) {
-                Tools.Warn('_ConvertSpecularGlosinessTexturesToMetallicRoughness: diffuse and specular glossiness textures are not defined!');
-                return null;
+                return Promise.reject('_ConvertSpecularGlosinessTexturesToMetallicRoughness: diffuse and specular glossiness textures are not defined!');
             }
 
             const scene: Nullable<Scene> = diffuseTexture ? diffuseTexture.getScene() : specularGlossinessTexture ? specularGlossinessTexture.getScene() : null;
@@ -698,30 +763,33 @@ module BABYLON.GLTF2 {
                         }
 
                         if (writeOutMetallicRoughnessTexture) {
-                            const metallicRoughnessBase64 = this._CreateBase64FromCanvas(metallicRoughnessBuffer, width, height, mimeType);
-                            metallicRoughnessFactors.metallicRoughnessTextureBase64 = metallicRoughnessBase64;
+                            let promise = this._CreateBase64FromCanvasAsync(metallicRoughnessBuffer, width, height, mimeType).then(metallicRoughnessBase64 => {
+                                metallicRoughnessFactors.metallicRoughnessTextureBase64 = metallicRoughnessBase64;
+                            });
+                            promises.push(promise);
                         }
                         if (writeOutBaseColorTexture) {
-                            const baseColorBase64 = this._CreateBase64FromCanvas(baseColorBuffer, width, height, mimeType);
-                            metallicRoughnessFactors.baseColorTextureBase64 = baseColorBase64;
-
+                            let promise = this._CreateBase64FromCanvasAsync(baseColorBuffer, width, height, mimeType).then(baseColorBase64 => {
+                                metallicRoughnessFactors.baseColorTextureBase64 = baseColorBase64;
+                            });
+                            promises.push(promise);
                         }
 
-                        return metallicRoughnessFactors;
+                        return Promise.all(promises).then(() => {
+                            return metallicRoughnessFactors;
+                        });
                     }
                     else {
-                        Tools.Error("_ConvertSpecularGlossinessTexturesToMetallicRoughness: Pixel array buffer type not supported for texture: " + resizedTextures.texture2.name);
+                        return Promise.reject("_ConvertSpecularGlossinessTexturesToMetallicRoughness: Pixel array buffer type not supported for texture: " + resizedTextures.texture2.name);
                     }
                 }
                 else {
-                    Tools.Error("_ConvertSpecularGlossinessTexturesToMetallicRoughness: Pixel array buffer type not supported for texture: " + resizedTextures.texture1.name);
+                    return Promise.reject("_ConvertSpecularGlossinessTexturesToMetallicRoughness: Pixel array buffer type not supported for texture: " + resizedTextures.texture1.name);
                 }
             }
             else {
-                Tools.Error("_ConvertSpecularGlossinessTexturesToMetallicRoughness: Scene from textures is missing!");
+                return Promise.reject("_ConvertSpecularGlossinessTexturesToMetallicRoughness: Scene from textures is missing!");
             }
-
-            return null;
         }
 
         /**
@@ -784,8 +852,6 @@ module BABYLON.GLTF2 {
          * @returns glTF PBR Metallic Roughness factors
          */
         private static _ConvertMetalRoughFactorsToMetallicRoughnessAsync(babylonPBRMaterial: PBRMaterial, mimeType: ImageMimeType, images: IImage[], textures: ITexture[], samplers: ISampler[], glTFPbrMetallicRoughness: IMaterialPbrMetallicRoughness, imageData: { [fileName: string]: { data: Uint8Array, mimeType: ImageMimeType } }, hasTextureCoords: boolean): Promise<_IPBRMetallicRoughness> {
-            const alphaMode = this._GetAlphaMode(babylonPBRMaterial);
-            const useAlpha = alphaMode !== MaterialAlphaMode.OPAQUE ? true : false;
             const promises = [];
             const metallicRoughness: _IPBRMetallicRoughness = {
                 baseColor: babylonPBRMaterial.albedoColor,
@@ -795,21 +861,33 @@ module BABYLON.GLTF2 {
 
             if (hasTextureCoords) {
                 if (babylonPBRMaterial.albedoTexture) {
-                    let promise = _GLTFMaterial._ExportTextureAsync(babylonPBRMaterial.albedoTexture, mimeType, images, textures, samplers, imageData, useAlpha).then(glTFTexture => {
-                        if (glTFTexture) {
-                            glTFPbrMetallicRoughness.baseColorTexture = glTFTexture;
-                        }
-                    });
-                    promises.push(promise);
+                    if (babylonPBRMaterial.albedoTexture.uid in this._textureMap) {
+                        glTFPbrMetallicRoughness.baseColorTexture = this._textureMap[babylonPBRMaterial.albedoTexture.uid];
+                    }
+                    else {
+                        let promise = _GLTFMaterial._ExportTextureAsync(babylonPBRMaterial.albedoTexture, mimeType, images, textures, samplers, imageData).then(glTFTexture => {
+                            if (glTFTexture) {
+                                glTFPbrMetallicRoughness.baseColorTexture = glTFTexture;
+                                this._textureMap[babylonPBRMaterial.albedoTexture.uid] = glTFTexture;
+                            }
+                        });
+                        promises.push(promise);
+                    }
 
                 }
                 if (babylonPBRMaterial.metallicTexture) {
-                    let promise = _GLTFMaterial._ExportTextureAsync(babylonPBRMaterial.metallicTexture, mimeType, images, textures, samplers, imageData, useAlpha).then(glTFTexture => {
-                        if (glTFTexture) {
-                            glTFPbrMetallicRoughness.metallicRoughnessTexture = glTFTexture;
-                        }
-                    });
-                    promises.push(promise);
+                    if (babylonPBRMaterial.metallicTexture.uid in this._textureMap) {
+                        glTFPbrMetallicRoughness.metallicRoughnessTexture = this._textureMap[babylonPBRMaterial.metallicTexture.uid];
+                    }
+                    else {
+                        let promise = _GLTFMaterial._ExportTextureAsync(babylonPBRMaterial.metallicTexture, mimeType, images, textures, samplers, imageData).then(glTFTexture => {
+                            if (glTFTexture) {
+                                glTFPbrMetallicRoughness.metallicRoughnessTexture = glTFTexture;
+                                this._textureMap[babylonPBRMaterial.metallicTexture.uid] = glTFTexture;
+                            }
+                        });
+                        promises.push(promise);
+                    }
                 }
             }
             return Promise.all(promises).then(() => {
@@ -929,7 +1007,7 @@ module BABYLON.GLTF2 {
          * @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 static _ConvertSpecGlossFactorsToMetallicRoughness(babylonPBRMaterial: PBRMaterial, mimeType: ImageMimeType, images: IImage[], textures: ITexture[], samplers: ISampler[], glTFPbrMetallicRoughness: IMaterialPbrMetallicRoughness, imageData: { [fileName: string]: { data: Uint8Array, mimeType: ImageMimeType } }, hasTextureCoords: boolean): Nullable<_IPBRMetallicRoughness> {
+        private static _ConvertSpecGlossFactorsToMetallicRoughness(babylonPBRMaterial: PBRMaterial, mimeType: ImageMimeType, images: IImage[], textures: ITexture[], samplers: ISampler[], glTFPbrMetallicRoughness: IMaterialPbrMetallicRoughness, imageData: { [fileName: string]: { data: Uint8Array, mimeType: ImageMimeType } }, hasTextureCoords: boolean): Promise<Nullable<_IPBRMetallicRoughness>> {
             const specGloss: _IPBRSpecularGlossiness = {
                 diffuseColor: babylonPBRMaterial.albedoColor || Color3.White(),
                 specularColor: babylonPBRMaterial.reflectivityColor || Color3.White(),
@@ -942,30 +1020,30 @@ module BABYLON.GLTF2 {
                 samplerIndex = samplers.length - 1;
             }
             if (babylonPBRMaterial.reflectivityTexture && !babylonPBRMaterial.useMicroSurfaceFromReflectivityMapAlpha) {
-                Tools.Error("_ConvertPBRMaterial: Glossiness values not included in the reflectivity texture are currently not supported");
-                return null;
+                return Promise.reject("_ConvertPBRMaterial: Glossiness values not included in the reflectivity texture are currently not supported");
             }
 
-            const metallicRoughnessFactors = this._ConvertSpecularGlossinessTexturesToMetallicRoughness(babylonPBRMaterial.albedoTexture, babylonPBRMaterial.reflectivityTexture, specGloss, mimeType);
-            if (metallicRoughnessFactors) {
-                if (hasTextureCoords) {
-                    if (metallicRoughnessFactors.baseColorTextureBase64) {
-                        const glTFBaseColorTexture = _GLTFMaterial._GetTextureInfoFromBase64(metallicRoughnessFactors.baseColorTextureBase64, "bjsBaseColorTexture", mimeType, images, textures, babylonPBRMaterial.albedoTexture ? babylonPBRMaterial.albedoTexture.coordinatesIndex : null, samplerIndex, imageData);
-                        if (glTFBaseColorTexture != null) {
-                            glTFPbrMetallicRoughness.baseColorTexture = glTFBaseColorTexture;
+            return this._ConvertSpecularGlossinessTexturesToMetallicRoughnessAsync(babylonPBRMaterial.albedoTexture, babylonPBRMaterial.reflectivityTexture, specGloss, mimeType).then(metallicRoughnessFactors => {
+                if (metallicRoughnessFactors) {
+                    if (hasTextureCoords) {
+                        if (metallicRoughnessFactors.baseColorTextureBase64) {
+                            const glTFBaseColorTexture = _GLTFMaterial._GetTextureInfoFromBase64(metallicRoughnessFactors.baseColorTextureBase64, "bjsBaseColorTexture_" + (textures.length) + ".png", mimeType, images, textures, babylonPBRMaterial.albedoTexture ? babylonPBRMaterial.albedoTexture.coordinatesIndex : null, samplerIndex, imageData);
+                            if (glTFBaseColorTexture) {
+                                glTFPbrMetallicRoughness.baseColorTexture = glTFBaseColorTexture;
+                            }
                         }
-                    }
-                    if (metallicRoughnessFactors.metallicRoughnessTextureBase64) {
-                        const glTFMRColorTexture = _GLTFMaterial._GetTextureInfoFromBase64(metallicRoughnessFactors.metallicRoughnessTextureBase64, "bjsMetallicRoughnessTexture", mimeType, images, textures, babylonPBRMaterial.reflectivityTexture ? babylonPBRMaterial.reflectivityTexture.coordinatesIndex : null, samplerIndex, imageData);
-                        if (glTFMRColorTexture != null) {
-                            glTFPbrMetallicRoughness.metallicRoughnessTexture = glTFMRColorTexture;
+                        if (metallicRoughnessFactors.metallicRoughnessTextureBase64) {
+                            const glTFMRColorTexture = _GLTFMaterial._GetTextureInfoFromBase64(metallicRoughnessFactors.metallicRoughnessTextureBase64, "bjsMetallicRoughnessTexture_" + (textures.length) + ".png", mimeType, images, textures, babylonPBRMaterial.reflectivityTexture ? babylonPBRMaterial.reflectivityTexture.coordinatesIndex : null, samplerIndex, imageData);
+                            if (glTFMRColorTexture) {
+                                glTFPbrMetallicRoughness.metallicRoughnessTexture = glTFMRColorTexture;
+                            }
                         }
-                    }
 
-                    return metallicRoughnessFactors;
+                        return metallicRoughnessFactors;
+                    }
                 }
-            }
-            return this._ConvertSpecularGlossinessToMetallicRoughness(specGloss);
+                return this._ConvertSpecularGlossinessToMetallicRoughness(specGloss);
+            });
 
         }
 
@@ -1000,8 +1078,9 @@ module BABYLON.GLTF2 {
                 });
             }
             else {
-                const metallicRoughness = this._ConvertSpecGlossFactorsToMetallicRoughness(babylonPBRMaterial, mimeType, images, textures, samplers, glTFPbrMetallicRoughness, imageData, hasTextureCoords);
-                return _GLTFMaterial.SetMetallicRoughnessPbrMaterial(metallicRoughness, babylonPBRMaterial, glTFMaterial, glTFPbrMetallicRoughness, mimeType, images, textures, samplers, materials, materialMap, imageData, hasTextureCoords);
+                return this._ConvertSpecGlossFactorsToMetallicRoughness(babylonPBRMaterial, mimeType, images, textures, samplers, glTFPbrMetallicRoughness, imageData, hasTextureCoords).then(metallicRoughness => {
+                    return _GLTFMaterial.SetMetallicRoughnessPbrMaterial(metallicRoughness, babylonPBRMaterial, glTFMaterial, glTFPbrMetallicRoughness, mimeType, images, textures, samplers, materials, materialMap, imageData, hasTextureCoords);
+                });
             }
         }
 
@@ -1009,12 +1088,10 @@ module BABYLON.GLTF2 {
             let promises = [];
             if (metallicRoughness) {
                 let alphaMode: Nullable<MaterialAlphaMode> = null;
-                let useAlpha = false;
                 if (babylonPBRMaterial.transparencyMode != null) {
                     alphaMode = _GLTFMaterial._GetAlphaMode(babylonPBRMaterial);
                     if (alphaMode) {
                         if (alphaMode !== MaterialAlphaMode.OPAQUE) { //glTF defaults to opaque
-                            useAlpha = true;
                             glTFMaterial.alphaMode = alphaMode;
                             if (alphaMode === MaterialAlphaMode.MASK) {
                                 glTFMaterial.alphaCutoff = babylonPBRMaterial.alphaCutOff;
@@ -1047,7 +1124,7 @@ module BABYLON.GLTF2 {
 
                 if (hasTextureCoords) {
                     if (babylonPBRMaterial.bumpTexture) {
-                        let promise = _GLTFMaterial._ExportTextureAsync(babylonPBRMaterial.bumpTexture, mimeType, images, textures, samplers, imageData, useAlpha).then(glTFTexture => {
+                        let promise = _GLTFMaterial._ExportTextureAsync(babylonPBRMaterial.bumpTexture, mimeType, images, textures, samplers, imageData).then(glTFTexture => {
                             if (glTFTexture) {
                                 glTFMaterial.normalTexture = glTFTexture;
                                 if (babylonPBRMaterial.bumpTexture.level !== 1) {
@@ -1061,7 +1138,7 @@ module BABYLON.GLTF2 {
 
                     }
                     if (babylonPBRMaterial.ambientTexture) {
-                        let promise = _GLTFMaterial._ExportTextureAsync(babylonPBRMaterial.ambientTexture, mimeType, images, textures, samplers, imageData, useAlpha).then(glTFTexture => {
+                        let promise = _GLTFMaterial._ExportTextureAsync(babylonPBRMaterial.ambientTexture, mimeType, images, textures, samplers, imageData).then(glTFTexture => {
                             if (glTFTexture) {
                                 let occlusionTexture: IMaterialOcclusionTextureInfo = {
                                     index: glTFTexture.index
@@ -1078,7 +1155,7 @@ module BABYLON.GLTF2 {
 
                     }
                     if (babylonPBRMaterial.emissiveTexture) {
-                        let promise = _GLTFMaterial._ExportTextureAsync(babylonPBRMaterial.emissiveTexture, mimeType, images, textures, samplers, imageData, useAlpha).then(glTFTexture => {
+                        let promise = _GLTFMaterial._ExportTextureAsync(babylonPBRMaterial.emissiveTexture, mimeType, images, textures, samplers, imageData).then(glTFTexture => {
                             if (glTFTexture) {
                                 glTFMaterial.emissiveTexture = glTFTexture;
                             }
@@ -1112,7 +1189,7 @@ module BABYLON.GLTF2 {
          * @param imageData map of image file name and data
          * @return glTF texture info, or null if the texture format is not supported
          */
-        private static _ExportTextureAsync(babylonTexture: BaseTexture, mimeType: ImageMimeType, images: IImage[], textures: ITexture[], samplers: ISampler[], imageData: { [fileName: string]: { data: Uint8Array, mimeType: ImageMimeType } }, useAlpha: boolean): Promise<Nullable<ITextureInfo>> {
+        private static _ExportTextureAsync(babylonTexture: BaseTexture, mimeType: ImageMimeType, images: IImage[], textures: ITexture[], samplers: ISampler[], imageData: { [fileName: string]: { data: Uint8Array, mimeType: ImageMimeType } }): Promise<Nullable<ITextureInfo>> {
             const sampler = _GLTFMaterial._GetGLTFTextureSampler(babylonTexture);
             let samplerIndex: Nullable<number> = null;
 
@@ -1133,10 +1210,10 @@ module BABYLON.GLTF2 {
             else {
                 samplerIndex = foundSamplerIndex;
             }
-            return this._SetAlphaToOneAsync(babylonTexture, useAlpha).then((texture) => {
-                const pixels = _GLTFMaterial.GetPixelsFromTexture(texture);
-                const size = babylonTexture.getSize();
-                const base64Data = this._CreateBase64FromCanvas(pixels, size.width, size.height, mimeType);
+            const pixels = _GLTFMaterial.GetPixelsFromTexture(babylonTexture);
+            const size = babylonTexture.getSize();
+
+            return this._CreateBase64FromCanvasAsync(pixels, size.width, size.height, mimeType).then(base64Data => {
                 const textureInfo = this._GetTextureInfoFromBase64(base64Data, babylonTexture.name, mimeType, images, textures, babylonTexture.coordinatesIndex, samplerIndex, imageData);
                 return textureInfo;
             });

+ 0 - 10
serializers/src/glTF/2.0/shaders/setAlphaToOne.fragment.fx

@@ -1,10 +0,0 @@
-precision highp float;
-
-uniform sampler2D textureSampler;
-
-varying vec2 vUV;
-
-void main(void) {
-    vec4 color = texture2D(textureSampler, vUV);
-    gl_FragColor = vec4(color.rgb, 1.0);
-}

+ 0 - 53
tests/unit/babylon/serializers/babylon.glTFSerializer.tests.ts

@@ -35,29 +35,6 @@ describe('Babylon glTF Serializer', () => {
      * This tests the glTF serializer help functions 
      */
     describe('#GLTF', () => {
-        // it('should get alpha mode from Babylon metallic roughness', () => {
-        //     let alphaMode: string;
-
-        //     const scene = new BABYLON.Scene(subject);
-        //     const babylonMaterial = new BABYLON.PBRMetallicRoughnessMaterial("metallicroughness", scene);
-        //     babylonMaterial.transparencyMode = BABYLON.PBRMaterial.PBRMATERIAL_OPAQUE;
-
-        //     alphaMode = BABYLON.GLTF2._GLTFMaterial._GetAlphaMode(babylonMaterial);
-        //     alphaMode.should.be.equal('OPAQUE');
-
-        //     babylonMaterial.transparencyMode = BABYLON.PBRMaterial.PBRMATERIAL_ALPHABLEND;
-        //     alphaMode = BABYLON.GLTF2._GLTFMaterial._GetAlphaMode(babylonMaterial);
-        //     alphaMode.should.be.equal('BLEND');
-
-        //     babylonMaterial.transparencyMode = BABYLON.PBRMaterial.PBRMATERIAL_ALPHATESTANDBLEND;
-        //     alphaMode = BABYLON.GLTF2._GLTFMaterial._GetAlphaMode(babylonMaterial);
-        //     alphaMode.should.be.equal('BLEND');
-
-        //     babylonMaterial.transparencyMode = BABYLON.PBRMaterial.PBRMATERIAL_ALPHATEST;
-        //     alphaMode = BABYLON.GLTF2._GLTFMaterial._GetAlphaMode(babylonMaterial);
-        //     alphaMode.should.be.equal('MASK');
-        // });
-
         it('should convert Babylon standard material to metallic roughness', () => {
             const scene = new BABYLON.Scene(subject);
             const babylonStandardMaterial = new BABYLON.StandardMaterial("specGloss", scene);
@@ -74,12 +51,10 @@ describe('Babylon glTF Serializer', () => {
 
             metalRough.roughnessFactor.should.be.approximately(0.328809, 1e-6);
         });
-
         it('should solve for metallic', () => {
             BABYLON.GLTF2._GLTFMaterial._SolveMetallic(1.0, 0.0, 1.0).should.be.equal(0);
             BABYLON.GLTF2._GLTFMaterial._SolveMetallic(0.0, 1.0, 1.0).should.be.approximately(1, 1e-6);
         });
-
         it('should serialize empty Babylon scene to glTF with only asset property', () => {
             const scene = new BABYLON.Scene(subject);
 
@@ -92,7 +67,6 @@ describe('Babylon glTF Serializer', () => {
                 jsonData.asset.generator.should.be.equal("BabylonJS");
             });
         });
-
         it('should serialize sphere geometry in scene to glTF', () => {
             const scene = new BABYLON.Scene(subject);
             BABYLON.Mesh.CreateSphere('sphere', 16, 2, scene);
@@ -125,33 +99,6 @@ describe('Babylon glTF Serializer', () => {
                     jsonData.scene.should.be.equal(0);
                 });
         });
-
-        // it('should serialize alpha mode and cutoff', () => {
-        //     const scene = new BABYLON.Scene(subject);
-
-        //     const plane = BABYLON.Mesh.CreatePlane('plane', 120, scene);
-        //     const babylonPBRMetalRoughMaterial = new BABYLON.PBRMetallicRoughnessMaterial('metalRoughMat', scene);
-        //     babylonPBRMetalRoughMaterial.transparencyMode = BABYLON.PBRMaterial.PBRMATERIAL_ALPHATEST;
-        //     const alphaCutoff = 0.8;
-        //     babylonPBRMetalRoughMaterial.alphaCutOff = alphaCutoff;
-
-        //     plane.material = babylonPBRMetalRoughMaterial;
-
-
-        //     return BABYLON.GLTF2Export.GLTFAsync(scene, 'test').then(glTFData => {
-        //         const jsonString = glTFData.glTFFiles['test.gltf'] as string;
-        //         const jsonData = JSON.parse(jsonString);
-
-        //         // accessors, asset, buffers, bufferViews, meshes, nodes, scene, scenes, materials
-        //         Object.keys(jsonData).length.should.be.equal(9);
-
-        //         jsonData.materials.length.should.be.equal(2);
-
-        //         jsonData.materials[0].alphaMode.should.be.equal('MASK');
-
-        //         jsonData.materials[0].alphaCutoff.should.be.equal(alphaCutoff);
-        //     });
-        // });
         it('should serialize single component translation animation to glTF', () => {
             const scene = new BABYLON.Scene(subject);
             const box = BABYLON.Mesh.CreateBox('box', 1, scene);