소스 검색

Merge remote-tracking branch 'BabylonJS/master' into animations-viewer

Raanan Weber 7 년 전
부모
커밋
4b82cc0189
62개의 변경된 파일27929개의 추가작업 그리고 29657개의 파일을 삭제
  1. 4768 4687
      Playground/babylon.d.txt
  2. BIN
      Playground/scenes/TwoQuads/TwoQuads.bin
  3. 17 5
      Playground/scenes/TwoQuads/TwoQuads.gltf
  4. 31 3
      Tools/Gulp/config.json
  5. 4821 4739
      dist/preview release/babylon.d.ts
  6. 55 55
      dist/preview release/babylon.js
  7. 745 514
      dist/preview release/babylon.max.js
  8. 56 56
      dist/preview release/babylon.worker.js
  9. 12252 12170
      dist/preview release/customConfigurations/minimalGLTFViewer/babylon.d.ts
  10. 56 56
      dist/preview release/customConfigurations/minimalGLTFViewer/babylon.js
  11. 798 515
      dist/preview release/customConfigurations/minimalGLTFViewer/babylon.max.js
  12. 800 517
      dist/preview release/customConfigurations/minimalGLTFViewer/es6.js
  13. 747 516
      dist/preview release/es6.js
  14. 3 3
      dist/preview release/gui/babylon.gui.min.js
  15. 4 4
      dist/preview release/inspector/babylon.inspector.bundle.js
  16. 3 3
      dist/preview release/inspector/babylon.inspector.min.js
  17. 2 2
      dist/preview release/loaders/babylon.glTF1FileLoader.d.ts
  18. 2 2
      dist/preview release/loaders/babylon.glTF1FileLoader.js
  19. 2 2
      dist/preview release/loaders/babylon.glTF1FileLoader.min.js
  20. 5 4
      dist/preview release/loaders/babylon.glTF2FileLoader.d.ts
  21. 70 54
      dist/preview release/loaders/babylon.glTF2FileLoader.js
  22. 2 2
      dist/preview release/loaders/babylon.glTF2FileLoader.min.js
  23. 5 4
      dist/preview release/loaders/babylon.glTFFileLoader.d.ts
  24. 70 54
      dist/preview release/loaders/babylon.glTFFileLoader.js
  25. 3 3
      dist/preview release/loaders/babylon.glTFFileLoader.min.js
  26. 1 1
      dist/preview release/loaders/babylon.objFileLoader.min.js
  27. 70 54
      dist/preview release/loaders/babylonjs.loaders.js
  28. 3 3
      dist/preview release/loaders/babylonjs.loaders.min.js
  29. 5 4
      dist/preview release/loaders/babylonjs.loaders.module.d.ts
  30. 4 282
      dist/preview release/materialsLibrary/babylon.customMaterial.d.ts
  31. 19 1908
      dist/preview release/materialsLibrary/babylon.customMaterial.js
  32. 1 2
      dist/preview release/materialsLibrary/babylon.customMaterial.min.js
  33. 1 1
      dist/preview release/materialsLibrary/babylon.shadowOnlyMaterial.min.js
  34. 1 1
      dist/preview release/materialsLibrary/babylon.waterMaterial.min.js
  35. 22 1906
      dist/preview release/materialsLibrary/babylonjs.materials.js
  36. 4 6
      dist/preview release/materialsLibrary/babylonjs.materials.min.js
  37. 4 282
      dist/preview release/materialsLibrary/babylonjs.materials.module.d.ts
  38. 1 1
      dist/preview release/postProcessesLibrary/babylon.asciiArtPostProcess.min.js
  39. 1 1
      dist/preview release/postProcessesLibrary/babylon.digitalRainPostProcess.min.js
  40. 1 1
      dist/preview release/postProcessesLibrary/babylonjs.postProcess.min.js
  41. 86 29
      dist/preview release/serializers/babylon.glTF2Serializer.d.ts
  42. 385 158
      dist/preview release/serializers/babylon.glTF2Serializer.js
  43. 1 1
      dist/preview release/serializers/babylon.glTF2Serializer.min.js
  44. 385 158
      dist/preview release/serializers/babylonjs.serializers.js
  45. 1 1
      dist/preview release/serializers/babylonjs.serializers.min.js
  46. 86 29
      dist/preview release/serializers/babylonjs.serializers.module.d.ts
  47. 2 24
      dist/preview release/typedocValidationBaseline.json
  48. 68 68
      dist/preview release/viewer/babylon.viewer.js
  49. 1222 664
      dist/preview release/viewer/babylon.viewer.max.js
  50. 2 1
      dist/preview release/what's new.md
  51. 10 1
      loaders/src/glTF/2.0/Extensions/MSFT_lod.ts
  52. 39 32
      loaders/src/glTF/2.0/babylon.glTFLoader.ts
  53. 28 20
      serializers/src/glTF/2.0/babylon.glTFMaterial.ts
  54. 1 0
      src/Cameras/VR/babylon.vrExperienceHelper.ts
  55. 53 0
      src/Materials/babylon.effect.ts
  56. 19 3
      src/Math/babylon.math.ts
  57. 4 0
      src/Mesh/Compression/babylon.dracoCompression.ts
  58. 14 0
      src/Particles/babylon.gpuParticleSystem.ts
  59. 6 7
      src/PostProcess/RenderPipeline/Pipelines/babylon.defaultRenderingPipeline.ts
  60. 1 1
      src/Shaders/gpuRenderParticles.vertex.fx
  61. 7 3
      src/Tools/babylon.tga.ts
  62. 54 34
      tests/unit/babylon/src/Loading/babylon.sceneLoader.tests.ts

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 4768 - 4687
Playground/babylon.d.txt


BIN
Playground/scenes/TwoQuads/TwoQuads.bin


+ 17 - 5
Playground/scenes/TwoQuads/TwoQuads.gltf

@@ -20,10 +20,16 @@
       "bufferView": 1,
       "componentType": 5126,
       "count": 4,
-      "type": "VEC2"
+      "type": "VEC3"
     },
     {
       "bufferView": 2,
+      "componentType": 5126,
+      "count": 4,
+      "type": "VEC2"
+    },
+    {
+      "bufferView": 3,
       "componentType": 5125,
       "count": 6,
       "type": "SCALAR"
@@ -35,7 +41,7 @@
   "buffers": [
     {
       "uri": "TwoQuads.bin",
-      "byteLength": 104
+      "byteLength": 152
     }
   ],
   "bufferViews": [
@@ -46,11 +52,16 @@
     {
       "buffer": 0,
       "byteOffset": 48,
+      "byteLength": 48
+    },
+    {
+      "buffer": 0,
+      "byteOffset": 96,
       "byteLength": 32
     },
     {
       "buffer": 0,
-      "byteOffset": 80,
+      "byteOffset": 128,
       "byteLength": 24
     }
   ],
@@ -111,9 +122,10 @@
         {
           "attributes": {
             "POSITION": 0,
-            "TEXCOORD_0": 1
+            "NORMAL": 1,
+            "TEXCOORD_0": 2
           },
-          "indices": 2,
+          "indices": 3,
           "material": 0
         }
       ]

+ 31 - 3
Tools/Gulp/config.json

@@ -744,7 +744,8 @@
                 "../../src/PostProcess/babylon.depthOfFieldBlurPostProcess.js"
             ],
             "dependUpon": [
-                "postProcesses"
+                "postProcesses",
+                "additionalPostProcess_blur"
             ],
             "shaders": [
                 "kernelBlur.vertex",
@@ -768,6 +769,28 @@
                 "circleOfConfusion.fragment"
             ]
         },
+        "additionalPostProcess_sharpen": {
+            "files": [
+                "../../src/PostProcess/babylon.sharpenPostProcess.js"
+            ],
+            "dependUpon": [
+                "postProcesses"
+            ],
+            "shaders": [
+                "sharpen.fragment"
+            ]
+        },
+        "additionalPostProcess_chromaticAberration": {
+            "files": [
+                "../../src/PostProcess/babylon.chromaticAberrationPostProcess.js"
+            ],
+            "dependUpon": [
+                "postProcesses"
+            ],
+            "shaders": [
+                "chromaticAberration.fragment"
+            ]
+        },
         "additionalPostProcess_depthOfFieldMerge": {
             "files": [
                 "../../src/PostProcess/babylon.depthOfFieldMergePostProcess.js"
@@ -782,6 +805,11 @@
         "additionalPostProcess_depthOfFieldEffect": {
             "files": [
                 "../../src/PostProcess/babylon.depthOfFieldEffect.js"
+            ],
+            "dependUpon": [
+                "additionalPostProcess_depthOfFieldBlur",
+                "additionalPostProcess_depthOfFieldMerge",
+                "additionalPostProcess_circleOfConfusion"
             ]
         },
         "additionalPostProcess_fxaa": {
@@ -892,8 +920,8 @@
             "dependUpon": [
                 "renderingPipeline",
                 "additionalPostProcess_fxaa",
-                "additionalPostProcess_circleOfConfusion",
-                "additionalPostProcess_depthOfFieldMerge",
+                "additionalPostProcess_chromaticAberration",
+                "additionalPostProcess_sharpen",
                 "additionalPostProcess_depthOfFieldEffect"
             ]
         },

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 4821 - 4739
dist/preview release/babylon.d.ts


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 55 - 55
dist/preview release/babylon.js


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 745 - 514
dist/preview release/babylon.max.js


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 56 - 56
dist/preview release/babylon.worker.js


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 12252 - 12170
dist/preview release/customConfigurations/minimalGLTFViewer/babylon.d.ts


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 56 - 56
dist/preview release/customConfigurations/minimalGLTFViewer/babylon.js


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 798 - 515
dist/preview release/customConfigurations/minimalGLTFViewer/babylon.max.js


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 800 - 517
dist/preview release/customConfigurations/minimalGLTFViewer/es6.js


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 747 - 516
dist/preview release/es6.js


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 3 - 3
dist/preview release/gui/babylon.gui.min.js


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 4 - 4
dist/preview release/inspector/babylon.inspector.bundle.js


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 3 - 3
dist/preview release/inspector/babylon.inspector.min.js


+ 2 - 2
dist/preview release/loaders/babylon.glTF1FileLoader.d.ts

@@ -116,7 +116,7 @@ declare module BABYLON {
         private _onMaterialLoadedObserver;
         onMaterialLoaded: (material: Material) => void;
         /**
-         * Raised when the loader creates an animation group after parsing the glTF properties of the material.
+         * Raised when the loader creates an animation group after parsing the glTF properties of the animation.
          */
         readonly onAnimationGroupLoadedObservable: Observable<AnimationGroup>;
         private _onAnimationGroupLoadedObserver;
@@ -143,7 +143,7 @@ declare module BABYLON {
         private _onExtensionLoadedObserver;
         onExtensionLoaded: (extension: IGLTFLoaderExtension) => void;
         /**
-         * Gets a promise that resolves when the asset to be completely loaded.
+         * Gets a promise that resolves when the asset is completely loaded.
          * @returns A promise that resolves when the asset is completely loaded.
          */
         whenCompleteAsync(): Promise<void>;

+ 2 - 2
dist/preview release/loaders/babylon.glTF1FileLoader.js

@@ -77,7 +77,7 @@ var BABYLON;
              */
             this.onMaterialLoadedObservable = new BABYLON.Observable();
             /**
-             * Raised when the loader creates an animation group after parsing the glTF properties of the material.
+             * Raised when the loader creates an animation group after parsing the glTF properties of the animation.
              */
             this.onAnimationGroupLoadedObservable = new BABYLON.Observable();
             /**
@@ -184,7 +184,7 @@ var BABYLON;
             configurable: true
         });
         /**
-         * Gets a promise that resolves when the asset to be completely loaded.
+         * Gets a promise that resolves when the asset is completely loaded.
          * @returns A promise that resolves when the asset is completely loaded.
          */
         GLTFFileLoader.prototype.whenCompleteAsync = function () {

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 2 - 2
dist/preview release/loaders/babylon.glTF1FileLoader.min.js


+ 5 - 4
dist/preview release/loaders/babylon.glTF2FileLoader.d.ts

@@ -116,7 +116,7 @@ declare module BABYLON {
         private _onMaterialLoadedObserver;
         onMaterialLoaded: (material: Material) => void;
         /**
-         * Raised when the loader creates an animation group after parsing the glTF properties of the material.
+         * Raised when the loader creates an animation group after parsing the glTF properties of the animation.
          */
         readonly onAnimationGroupLoadedObservable: Observable<AnimationGroup>;
         private _onAnimationGroupLoadedObserver;
@@ -143,7 +143,7 @@ declare module BABYLON {
         private _onExtensionLoadedObserver;
         onExtensionLoaded: (extension: IGLTFLoaderExtension) => void;
         /**
-         * Gets a promise that resolves when the asset to be completely loaded.
+         * Gets a promise that resolves when the asset is completely loaded.
          * @returns A promise that resolves when the asset is completely loaded.
          */
         whenCompleteAsync(): Promise<void>;
@@ -321,12 +321,13 @@ declare module BABYLON.GLTF2 {
         private _createRootNode();
         private _loadNodesAsync(nodes);
         _loadSceneAsync(context: string, scene: ILoaderScene): Promise<void>;
+        private _forEachNodeMesh(node, callback);
         private _getMeshes();
         private _getSkeletons();
         private _startAnimations();
         _loadNodeAsync(context: string, node: ILoaderNode): Promise<void>;
-        private _loadMeshAsync(context, node, mesh);
-        private _loadPrimitiveAsync(context, node, mesh, primitive);
+        private _loadMeshAsync(context, node, mesh, babylonMesh);
+        private _loadPrimitiveAsync(context, node, mesh, primitive, babylonMesh);
         private _loadVertexDataAsync(context, primitive, babylonMesh);
         private _createMorphTargets(context, node, mesh, primitive, babylonMesh);
         private _loadMorphTargetsAsync(context, primitive, babylonMesh, babylonVertexData);

+ 70 - 54
dist/preview release/loaders/babylon.glTF2FileLoader.js

@@ -77,7 +77,7 @@ var BABYLON;
              */
             this.onMaterialLoadedObservable = new BABYLON.Observable();
             /**
-             * Raised when the loader creates an animation group after parsing the glTF properties of the material.
+             * Raised when the loader creates an animation group after parsing the glTF properties of the animation.
              */
             this.onAnimationGroupLoadedObservable = new BABYLON.Observable();
             /**
@@ -184,7 +184,7 @@ var BABYLON;
             configurable: true
         });
         /**
-         * Gets a promise that resolves when the asset to be completely loaded.
+         * Gets a promise that resolves when the asset is completely loaded.
          * @returns A promise that resolves when the asset is completely loaded.
          */
         GLTFFileLoader.prototype.whenCompleteAsync = function () {
@@ -572,7 +572,7 @@ var BABYLON;
                         nodes = names.map(function (name) {
                             var node = nodeMap_1[name];
                             if (!node) {
-                                throw new Error("Failed to find node " + name);
+                                throw new Error("Failed to find node '" + name + "'");
                             }
                             return node;
                         });
@@ -728,7 +728,7 @@ var BABYLON;
                         break;
                     }
                     default: {
-                        throw new Error("Invalid coordinate system mode " + this.coordinateSystemMode);
+                        throw new Error("Invalid coordinate system mode (" + this.coordinateSystemMode + ")");
                     }
                 }
                 this.onMeshLoadedObservable.notifyObservers(this._rootBabylonMesh);
@@ -757,6 +757,17 @@ var BABYLON;
                 promises.push(this._loadAnimationsAsync());
                 return Promise.all(promises).then(function () { });
             };
+            GLTFLoader.prototype._forEachNodeMesh = function (node, callback) {
+                if (node._babylonMesh) {
+                    callback(node._babylonMesh);
+                }
+                if (node._primitiveBabylonMeshes) {
+                    for (var _i = 0, _a = node._primitiveBabylonMeshes; _i < _a.length; _i++) {
+                        var babylonMesh = _a[_i];
+                        callback(babylonMesh);
+                    }
+                }
+            };
             GLTFLoader.prototype._getMeshes = function () {
                 var meshes = new Array();
                 // Root mesh is always first.
@@ -765,15 +776,9 @@ var BABYLON;
                 if (nodes) {
                     for (var _i = 0, nodes_2 = nodes; _i < nodes_2.length; _i++) {
                         var node = nodes_2[_i];
-                        if (node._babylonMesh) {
-                            meshes.push(node._babylonMesh);
-                        }
-                        if (node._primitiveBabylonMeshes) {
-                            for (var _a = 0, _b = node._primitiveBabylonMeshes; _a < _b.length; _a++) {
-                                var babylonMesh = _b[_a];
-                                meshes.push(babylonMesh);
-                            }
-                        }
+                        this._forEachNodeMesh(node, function (mesh) {
+                            meshes.push(mesh);
+                        });
                     }
                 }
                 return meshes;
@@ -814,7 +819,7 @@ var BABYLON;
                         break;
                     }
                     default: {
-                        BABYLON.Tools.Error("Invalid animation start mode " + this.animationStartMode);
+                        BABYLON.Tools.Error("Invalid animation start mode (" + this.animationStartMode + ")");
                         return;
                     }
                 }
@@ -835,7 +840,7 @@ var BABYLON;
                 GLTFLoader._LoadTransform(node, babylonMesh);
                 if (node.mesh != undefined) {
                     var mesh = GLTFLoader._GetProperty(context + "/mesh", this._gltf.meshes, node.mesh);
-                    promises.push(this._loadMeshAsync("#/meshes/" + mesh._index, node, mesh));
+                    promises.push(this._loadMeshAsync("#/meshes/" + mesh._index, node, mesh, babylonMesh));
                 }
                 if (node.children) {
                     for (var _i = 0, _a = node.children; _i < _a.length; _i++) {
@@ -847,37 +852,42 @@ var BABYLON;
                 this.onMeshLoadedObservable.notifyObservers(babylonMesh);
                 return Promise.all(promises).then(function () { });
             };
-            GLTFLoader.prototype._loadMeshAsync = function (context, node, mesh) {
+            GLTFLoader.prototype._loadMeshAsync = function (context, node, mesh, babylonMesh) {
                 // TODO: instancing
+                var _this = this;
                 var promises = new Array();
                 var primitives = mesh.primitives;
                 if (!primitives || primitives.length === 0) {
                     throw new Error(context + ": Primitives are missing");
                 }
                 GLTF2.ArrayItem.Assign(primitives);
-                for (var _i = 0, primitives_1 = primitives; _i < primitives_1.length; _i++) {
-                    var primitive = primitives_1[_i];
-                    promises.push(this._loadPrimitiveAsync(context + "/primitives/" + primitive._index, node, mesh, primitive));
+                if (primitives.length === 1) {
+                    var primitive = primitives[0];
+                    promises.push(this._loadPrimitiveAsync(context + "/primitives/" + primitive._index, node, mesh, primitive, babylonMesh));
+                }
+                else {
+                    node._primitiveBabylonMeshes = [];
+                    for (var _i = 0, primitives_1 = primitives; _i < primitives_1.length; _i++) {
+                        var primitive = primitives_1[_i];
+                        var primitiveBabylonMesh = new BABYLON.Mesh((mesh.name || babylonMesh.name) + "_" + primitive._index, this._babylonScene, babylonMesh);
+                        node._primitiveBabylonMeshes.push(babylonMesh);
+                        promises.push(this._loadPrimitiveAsync(context + "/primitives/" + primitive._index, node, mesh, primitive, primitiveBabylonMesh));
+                        this.onMeshLoadedObservable.notifyObservers(babylonMesh);
+                    }
                 }
                 if (node.skin != undefined) {
                     var skin = GLTFLoader._GetProperty(context + "/skin", this._gltf.skins, node.skin);
                     promises.push(this._loadSkinAsync("#/skins/" + skin._index, node, mesh, skin));
                 }
                 return Promise.all(promises).then(function () {
-                    if (node._primitiveBabylonMeshes) {
-                        for (var _i = 0, _a = node._primitiveBabylonMeshes; _i < _a.length; _i++) {
-                            var primitiveBabylonMesh = _a[_i];
-                            primitiveBabylonMesh._refreshBoundingInfo(true);
-                        }
-                    }
+                    _this._forEachNodeMesh(node, function (babylonMesh) {
+                        babylonMesh._refreshBoundingInfo(true);
+                    });
                 });
             };
-            GLTFLoader.prototype._loadPrimitiveAsync = function (context, node, mesh, primitive) {
+            GLTFLoader.prototype._loadPrimitiveAsync = function (context, node, mesh, primitive, babylonMesh) {
                 var _this = this;
                 var promises = new Array();
-                var babylonMesh = new BABYLON.Mesh((mesh.name || node._babylonMesh.name) + "_" + primitive._index, this._babylonScene, node._babylonMesh);
-                node._primitiveBabylonMeshes = node._primitiveBabylonMeshes || [];
-                node._primitiveBabylonMeshes[primitive._index] = babylonMesh;
                 this._createMorphTargets(context, node, mesh, primitive, babylonMesh);
                 promises.push(this._loadVertexDataAsync(context, primitive, babylonMesh).then(function (babylonVertexData) {
                     new BABYLON.Geometry(babylonMesh.name, _this._babylonScene, babylonVertexData, false, babylonMesh);
@@ -887,12 +897,11 @@ var BABYLON;
                     babylonMesh.material = this._getDefaultMaterial();
                 }
                 else {
-                    var material = GLTFLoader._GetProperty(context + "/material", this._gltf.materials, primitive.material);
+                    var material = GLTFLoader._GetProperty(context + "/material}", this._gltf.materials, primitive.material);
                     promises.push(this._loadMaterialAsync("#/materials/" + material._index, material, babylonMesh, function (babylonMaterial) {
                         babylonMesh.material = babylonMaterial;
                     }));
                 }
-                this.onMeshLoadedObservable.notifyObservers(babylonMesh);
                 return Promise.all(promises).then(function () { });
             };
             GLTFLoader.prototype._loadVertexDataAsync = function (context, primitive, babylonMesh) {
@@ -907,7 +916,7 @@ var BABYLON;
                 }
                 if (primitive.mode != undefined && primitive.mode !== 4 /* TRIANGLES */) {
                     // TODO: handle other primitive modes
-                    throw new Error(context + ": Mode " + primitive.mode + " is not currently supported");
+                    throw new Error(context + ": Mode (" + primitive.mode + ") is not currently supported");
                 }
                 var promises = new Array();
                 var babylonVertexData = new BABYLON.VertexData();
@@ -1049,7 +1058,7 @@ var BABYLON;
                             break;
                         }
                         default: {
-                            throw new Error(context + ": Invalid component type " + accessor.componentType);
+                            throw new Error(context + ": Invalid component type (" + accessor.componentType + ")");
                         }
                     }
                 }
@@ -1095,10 +1104,9 @@ var BABYLON;
             GLTFLoader.prototype._loadSkinAsync = function (context, node, mesh, skin) {
                 var _this = this;
                 var assignSkeleton = function () {
-                    for (var _i = 0, _a = node._primitiveBabylonMeshes; _i < _a.length; _i++) {
-                        var babylonMesh = _a[_i];
+                    _this._forEachNodeMesh(node, function (babylonMesh) {
                         babylonMesh.skeleton = skin._babylonSkeleton;
-                    }
+                    });
                     node._babylonMesh.parent = _this._rootBabylonMesh;
                     node._babylonMesh.position = BABYLON.Vector3.Zero();
                     node._babylonMesh.rotationQuaternion = BABYLON.Quaternion.Identity();
@@ -1194,6 +1202,7 @@ var BABYLON;
                 });
             };
             GLTFLoader.prototype._loadAnimationChannelAsync = function (context, animationContext, animation, channel, babylonAnimationGroup) {
+                var _this = this;
                 var targetNode = GLTFLoader._GetProperty(context + "/target/node", this._gltf.nodes, channel.target.node);
                 if (!targetNode._babylonMesh || targetNode.skin != undefined) {
                     return Promise.resolve();
@@ -1224,7 +1233,7 @@ var BABYLON;
                             break;
                         }
                         default: {
-                            throw new Error(context + ": Invalid target path " + channel.target.path);
+                            throw new Error(context + ": Invalid target path (" + channel.target.path + ")");
                         }
                     }
                     var outputBufferOffset = 0;
@@ -1316,11 +1325,10 @@ var BABYLON;
                                 value: key.value[targetIndex],
                                 outTangent: key.outTangent ? key.outTangent[targetIndex] : undefined
                             }); }));
-                            for (var _i = 0, _a = targetNode._primitiveBabylonMeshes; _i < _a.length; _i++) {
-                                var babylonMesh = _a[_i];
+                            _this._forEachNodeMesh(targetNode, function (babylonMesh) {
                                 var morphTarget = babylonMesh.morphTargetManager.getTarget(targetIndex);
                                 babylonAnimationGroup.addTargetedAnimation(babylonAnimation, morphTarget);
-                            }
+                            });
                         };
                         for (var targetIndex = 0; targetIndex < targetNode._numMorphTargets; targetIndex++) {
                             _loop_1(targetIndex);
@@ -1351,7 +1359,7 @@ var BABYLON;
                         break;
                     }
                     default: {
-                        throw new Error(context + ": Invalid interpolation " + sampler.interpolation);
+                        throw new Error(context + ": Invalid interpolation (" + sampler.interpolation + ")");
                     }
                 }
                 var inputData;
@@ -1436,12 +1444,12 @@ var BABYLON;
                                 return _this._buildArrayBuffer(Float32Array, bufferViewData, byteOffset, accessor.count, numComponents, byteStride);
                             }
                             default: {
-                                throw new Error(context + ": Invalid component type " + accessor.componentType);
+                                throw new Error(context + ": Invalid component type (" + accessor.componentType + ")");
                             }
                         }
                     }
                     catch (e) {
-                        throw new Error(context + ": " + e);
+                        throw new Error(context + ": " + e.messsage);
                     }
                 });
                 return accessor._data;
@@ -1605,7 +1613,7 @@ var BABYLON;
                         break;
                     }
                     default: {
-                        throw new Error(context + ": Invalid alpha mode " + material.alphaMode);
+                        throw new Error(context + ": Invalid alpha mode (" + material.alphaMode + ")");
                     }
                 }
             };
@@ -1623,7 +1631,7 @@ var BABYLON;
                     }
                 }, function (message, exception) {
                     if (!_this._disposed) {
-                        deferred.reject(new Error(context + ": " + (exception && exception.message) ? exception.message : message || "Failed to load texture"));
+                        deferred.reject(new Error(context + ": " + ((exception && exception.message) ? exception.message : message || "Failed to load texture")));
                     }
                 });
                 promises.push(deferred.promise);
@@ -1727,7 +1735,7 @@ var BABYLON;
             };
             GLTFLoader._GetProperty = function (context, array, index) {
                 if (!array || index == undefined || !array[index]) {
-                    throw new Error(context + ": Failed to find index " + index);
+                    throw new Error(context + ": Failed to find index (" + index + ")");
                 }
                 return array[index];
             };
@@ -1739,7 +1747,7 @@ var BABYLON;
                     case 33648 /* MIRRORED_REPEAT */: return BABYLON.Texture.MIRROR_ADDRESSMODE;
                     case 10497 /* REPEAT */: return BABYLON.Texture.WRAP_ADDRESSMODE;
                     default:
-                        BABYLON.Tools.Warn(context + ": Invalid texture wrap mode " + mode);
+                        BABYLON.Tools.Warn(context + ": Invalid texture wrap mode (" + mode + ")");
                         return BABYLON.Texture.WRAP_ADDRESSMODE;
                 }
             };
@@ -1756,13 +1764,13 @@ var BABYLON;
                         case 9986 /* NEAREST_MIPMAP_LINEAR */: return BABYLON.Texture.LINEAR_NEAREST_MIPLINEAR;
                         case 9987 /* LINEAR_MIPMAP_LINEAR */: return BABYLON.Texture.LINEAR_LINEAR_MIPLINEAR;
                         default:
-                            BABYLON.Tools.Warn(context + ": Invalid texture minification filter " + minFilter);
+                            BABYLON.Tools.Warn(context + ": Invalid texture minification filter (" + minFilter + ")");
                             return BABYLON.Texture.LINEAR_LINEAR_MIPLINEAR;
                     }
                 }
                 else {
                     if (magFilter !== 9728 /* NEAREST */) {
-                        BABYLON.Tools.Warn(context + ": Invalid texture magnification filter " + magFilter);
+                        BABYLON.Tools.Warn(context + ": Invalid texture magnification filter (" + magFilter + ")");
                     }
                     switch (minFilter) {
                         case 9728 /* NEAREST */: return BABYLON.Texture.NEAREST_NEAREST;
@@ -1772,7 +1780,7 @@ var BABYLON;
                         case 9986 /* NEAREST_MIPMAP_LINEAR */: return BABYLON.Texture.NEAREST_NEAREST_MIPLINEAR;
                         case 9987 /* LINEAR_MIPMAP_LINEAR */: return BABYLON.Texture.NEAREST_LINEAR_MIPLINEAR;
                         default:
-                            BABYLON.Tools.Warn(context + ": Invalid texture minification filter " + minFilter);
+                            BABYLON.Tools.Warn(context + ": Invalid texture minification filter (" + minFilter + ")");
                             return BABYLON.Texture.NEAREST_NEAREST_MIPNEAREST;
                     }
                 }
@@ -1787,7 +1795,7 @@ var BABYLON;
                     case "MAT3": return 9;
                     case "MAT4": return 16;
                 }
-                throw new Error(context + ": Invalid type " + type);
+                throw new Error(context + ": Invalid type (" + type + ")");
             };
             GLTFLoader._ValidateUri = function (uri) {
                 return (BABYLON.Tools.IsBase64(uri) || uri.indexOf("..") === -1);
@@ -2001,7 +2009,10 @@ var BABYLON;
                             var promise = _this._loader._loadNodeAsync("#/nodes/" + nodeLOD._index, nodeLOD).then(function () {
                                 if (indexLOD !== 0) {
                                     var previousNodeLOD = nodeLODs[indexLOD - 1];
-                                    previousNodeLOD._babylonMesh.setEnabled(false);
+                                    if (previousNodeLOD._babylonMesh) {
+                                        previousNodeLOD._babylonMesh.dispose();
+                                        delete previousNodeLOD._babylonMesh;
+                                    }
                                 }
                                 if (indexLOD !== nodeLODs.length - 1) {
                                     var nodeIndex = nodeLODs[indexLOD + 1]._index;
@@ -2045,6 +2056,11 @@ var BABYLON;
                             var promise = _this._loader._loadMaterialAsync("#/materials/" + materialLOD._index, materialLOD, babylonMesh, indexLOD === 0 ? assign : function () { }).then(function () {
                                 if (indexLOD !== 0) {
                                     assign(materialLOD._babylonMaterial);
+                                    var previousMaterialLOD = materialLODs[indexLOD - 1];
+                                    if (previousMaterialLOD._babylonMaterial) {
+                                        previousMaterialLOD._babylonMaterial.dispose();
+                                        delete previousMaterialLOD._babylonMaterial;
+                                    }
                                 }
                                 if (indexLOD !== materialLODs.length - 1) {
                                     var materialIndex = materialLODs[indexLOD + 1]._index;
@@ -2360,7 +2376,7 @@ var BABYLON;
                                 break;
                             }
                             default: {
-                                throw new Error(context + ": Invalid light type " + light.type);
+                                throw new Error(context + ": Invalid light type (" + light.type + ")");
                             }
                         }
                         babylonLight.diffuse = light.color ? BABYLON.Color3.FromArray(light.color) : BABYLON.Color3.White();
@@ -2373,7 +2389,7 @@ var BABYLON;
                     get: function () {
                         var extensions = this._loader._gltf.extensions;
                         if (!extensions || !extensions[this.name]) {
-                            throw new Error("#/extensions: " + this.name + " not found");
+                            throw new Error("#/extensions: '" + this.name + "' not found");
                         }
                         var extension = extensions[this.name];
                         return extension.lights;

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 2 - 2
dist/preview release/loaders/babylon.glTF2FileLoader.min.js


+ 5 - 4
dist/preview release/loaders/babylon.glTFFileLoader.d.ts

@@ -116,7 +116,7 @@ declare module BABYLON {
         private _onMaterialLoadedObserver;
         onMaterialLoaded: (material: Material) => void;
         /**
-         * Raised when the loader creates an animation group after parsing the glTF properties of the material.
+         * Raised when the loader creates an animation group after parsing the glTF properties of the animation.
          */
         readonly onAnimationGroupLoadedObservable: Observable<AnimationGroup>;
         private _onAnimationGroupLoadedObserver;
@@ -143,7 +143,7 @@ declare module BABYLON {
         private _onExtensionLoadedObserver;
         onExtensionLoaded: (extension: IGLTFLoaderExtension) => void;
         /**
-         * Gets a promise that resolves when the asset to be completely loaded.
+         * Gets a promise that resolves when the asset is completely loaded.
          * @returns A promise that resolves when the asset is completely loaded.
          */
         whenCompleteAsync(): Promise<void>;
@@ -877,12 +877,13 @@ declare module BABYLON.GLTF2 {
         private _createRootNode();
         private _loadNodesAsync(nodes);
         _loadSceneAsync(context: string, scene: ILoaderScene): Promise<void>;
+        private _forEachNodeMesh(node, callback);
         private _getMeshes();
         private _getSkeletons();
         private _startAnimations();
         _loadNodeAsync(context: string, node: ILoaderNode): Promise<void>;
-        private _loadMeshAsync(context, node, mesh);
-        private _loadPrimitiveAsync(context, node, mesh, primitive);
+        private _loadMeshAsync(context, node, mesh, babylonMesh);
+        private _loadPrimitiveAsync(context, node, mesh, primitive, babylonMesh);
         private _loadVertexDataAsync(context, primitive, babylonMesh);
         private _createMorphTargets(context, node, mesh, primitive, babylonMesh);
         private _loadMorphTargetsAsync(context, primitive, babylonMesh, babylonVertexData);

+ 70 - 54
dist/preview release/loaders/babylon.glTFFileLoader.js

@@ -77,7 +77,7 @@ var BABYLON;
              */
             this.onMaterialLoadedObservable = new BABYLON.Observable();
             /**
-             * Raised when the loader creates an animation group after parsing the glTF properties of the material.
+             * Raised when the loader creates an animation group after parsing the glTF properties of the animation.
              */
             this.onAnimationGroupLoadedObservable = new BABYLON.Observable();
             /**
@@ -184,7 +184,7 @@ var BABYLON;
             configurable: true
         });
         /**
-         * Gets a promise that resolves when the asset to be completely loaded.
+         * Gets a promise that resolves when the asset is completely loaded.
          * @returns A promise that resolves when the asset is completely loaded.
          */
         GLTFFileLoader.prototype.whenCompleteAsync = function () {
@@ -2749,7 +2749,7 @@ var BABYLON;
                         nodes = names.map(function (name) {
                             var node = nodeMap_1[name];
                             if (!node) {
-                                throw new Error("Failed to find node " + name);
+                                throw new Error("Failed to find node '" + name + "'");
                             }
                             return node;
                         });
@@ -2905,7 +2905,7 @@ var BABYLON;
                         break;
                     }
                     default: {
-                        throw new Error("Invalid coordinate system mode " + this.coordinateSystemMode);
+                        throw new Error("Invalid coordinate system mode (" + this.coordinateSystemMode + ")");
                     }
                 }
                 this.onMeshLoadedObservable.notifyObservers(this._rootBabylonMesh);
@@ -2934,6 +2934,17 @@ var BABYLON;
                 promises.push(this._loadAnimationsAsync());
                 return Promise.all(promises).then(function () { });
             };
+            GLTFLoader.prototype._forEachNodeMesh = function (node, callback) {
+                if (node._babylonMesh) {
+                    callback(node._babylonMesh);
+                }
+                if (node._primitiveBabylonMeshes) {
+                    for (var _i = 0, _a = node._primitiveBabylonMeshes; _i < _a.length; _i++) {
+                        var babylonMesh = _a[_i];
+                        callback(babylonMesh);
+                    }
+                }
+            };
             GLTFLoader.prototype._getMeshes = function () {
                 var meshes = new Array();
                 // Root mesh is always first.
@@ -2942,15 +2953,9 @@ var BABYLON;
                 if (nodes) {
                     for (var _i = 0, nodes_2 = nodes; _i < nodes_2.length; _i++) {
                         var node = nodes_2[_i];
-                        if (node._babylonMesh) {
-                            meshes.push(node._babylonMesh);
-                        }
-                        if (node._primitiveBabylonMeshes) {
-                            for (var _a = 0, _b = node._primitiveBabylonMeshes; _a < _b.length; _a++) {
-                                var babylonMesh = _b[_a];
-                                meshes.push(babylonMesh);
-                            }
-                        }
+                        this._forEachNodeMesh(node, function (mesh) {
+                            meshes.push(mesh);
+                        });
                     }
                 }
                 return meshes;
@@ -2991,7 +2996,7 @@ var BABYLON;
                         break;
                     }
                     default: {
-                        BABYLON.Tools.Error("Invalid animation start mode " + this.animationStartMode);
+                        BABYLON.Tools.Error("Invalid animation start mode (" + this.animationStartMode + ")");
                         return;
                     }
                 }
@@ -3012,7 +3017,7 @@ var BABYLON;
                 GLTFLoader._LoadTransform(node, babylonMesh);
                 if (node.mesh != undefined) {
                     var mesh = GLTFLoader._GetProperty(context + "/mesh", this._gltf.meshes, node.mesh);
-                    promises.push(this._loadMeshAsync("#/meshes/" + mesh._index, node, mesh));
+                    promises.push(this._loadMeshAsync("#/meshes/" + mesh._index, node, mesh, babylonMesh));
                 }
                 if (node.children) {
                     for (var _i = 0, _a = node.children; _i < _a.length; _i++) {
@@ -3024,37 +3029,42 @@ var BABYLON;
                 this.onMeshLoadedObservable.notifyObservers(babylonMesh);
                 return Promise.all(promises).then(function () { });
             };
-            GLTFLoader.prototype._loadMeshAsync = function (context, node, mesh) {
+            GLTFLoader.prototype._loadMeshAsync = function (context, node, mesh, babylonMesh) {
                 // TODO: instancing
+                var _this = this;
                 var promises = new Array();
                 var primitives = mesh.primitives;
                 if (!primitives || primitives.length === 0) {
                     throw new Error(context + ": Primitives are missing");
                 }
                 GLTF2.ArrayItem.Assign(primitives);
-                for (var _i = 0, primitives_1 = primitives; _i < primitives_1.length; _i++) {
-                    var primitive = primitives_1[_i];
-                    promises.push(this._loadPrimitiveAsync(context + "/primitives/" + primitive._index, node, mesh, primitive));
+                if (primitives.length === 1) {
+                    var primitive = primitives[0];
+                    promises.push(this._loadPrimitiveAsync(context + "/primitives/" + primitive._index, node, mesh, primitive, babylonMesh));
+                }
+                else {
+                    node._primitiveBabylonMeshes = [];
+                    for (var _i = 0, primitives_1 = primitives; _i < primitives_1.length; _i++) {
+                        var primitive = primitives_1[_i];
+                        var primitiveBabylonMesh = new BABYLON.Mesh((mesh.name || babylonMesh.name) + "_" + primitive._index, this._babylonScene, babylonMesh);
+                        node._primitiveBabylonMeshes.push(babylonMesh);
+                        promises.push(this._loadPrimitiveAsync(context + "/primitives/" + primitive._index, node, mesh, primitive, primitiveBabylonMesh));
+                        this.onMeshLoadedObservable.notifyObservers(babylonMesh);
+                    }
                 }
                 if (node.skin != undefined) {
                     var skin = GLTFLoader._GetProperty(context + "/skin", this._gltf.skins, node.skin);
                     promises.push(this._loadSkinAsync("#/skins/" + skin._index, node, mesh, skin));
                 }
                 return Promise.all(promises).then(function () {
-                    if (node._primitiveBabylonMeshes) {
-                        for (var _i = 0, _a = node._primitiveBabylonMeshes; _i < _a.length; _i++) {
-                            var primitiveBabylonMesh = _a[_i];
-                            primitiveBabylonMesh._refreshBoundingInfo(true);
-                        }
-                    }
+                    _this._forEachNodeMesh(node, function (babylonMesh) {
+                        babylonMesh._refreshBoundingInfo(true);
+                    });
                 });
             };
-            GLTFLoader.prototype._loadPrimitiveAsync = function (context, node, mesh, primitive) {
+            GLTFLoader.prototype._loadPrimitiveAsync = function (context, node, mesh, primitive, babylonMesh) {
                 var _this = this;
                 var promises = new Array();
-                var babylonMesh = new BABYLON.Mesh((mesh.name || node._babylonMesh.name) + "_" + primitive._index, this._babylonScene, node._babylonMesh);
-                node._primitiveBabylonMeshes = node._primitiveBabylonMeshes || [];
-                node._primitiveBabylonMeshes[primitive._index] = babylonMesh;
                 this._createMorphTargets(context, node, mesh, primitive, babylonMesh);
                 promises.push(this._loadVertexDataAsync(context, primitive, babylonMesh).then(function (babylonVertexData) {
                     new BABYLON.Geometry(babylonMesh.name, _this._babylonScene, babylonVertexData, false, babylonMesh);
@@ -3064,12 +3074,11 @@ var BABYLON;
                     babylonMesh.material = this._getDefaultMaterial();
                 }
                 else {
-                    var material = GLTFLoader._GetProperty(context + "/material", this._gltf.materials, primitive.material);
+                    var material = GLTFLoader._GetProperty(context + "/material}", this._gltf.materials, primitive.material);
                     promises.push(this._loadMaterialAsync("#/materials/" + material._index, material, babylonMesh, function (babylonMaterial) {
                         babylonMesh.material = babylonMaterial;
                     }));
                 }
-                this.onMeshLoadedObservable.notifyObservers(babylonMesh);
                 return Promise.all(promises).then(function () { });
             };
             GLTFLoader.prototype._loadVertexDataAsync = function (context, primitive, babylonMesh) {
@@ -3084,7 +3093,7 @@ var BABYLON;
                 }
                 if (primitive.mode != undefined && primitive.mode !== 4 /* TRIANGLES */) {
                     // TODO: handle other primitive modes
-                    throw new Error(context + ": Mode " + primitive.mode + " is not currently supported");
+                    throw new Error(context + ": Mode (" + primitive.mode + ") is not currently supported");
                 }
                 var promises = new Array();
                 var babylonVertexData = new BABYLON.VertexData();
@@ -3226,7 +3235,7 @@ var BABYLON;
                             break;
                         }
                         default: {
-                            throw new Error(context + ": Invalid component type " + accessor.componentType);
+                            throw new Error(context + ": Invalid component type (" + accessor.componentType + ")");
                         }
                     }
                 }
@@ -3272,10 +3281,9 @@ var BABYLON;
             GLTFLoader.prototype._loadSkinAsync = function (context, node, mesh, skin) {
                 var _this = this;
                 var assignSkeleton = function () {
-                    for (var _i = 0, _a = node._primitiveBabylonMeshes; _i < _a.length; _i++) {
-                        var babylonMesh = _a[_i];
+                    _this._forEachNodeMesh(node, function (babylonMesh) {
                         babylonMesh.skeleton = skin._babylonSkeleton;
-                    }
+                    });
                     node._babylonMesh.parent = _this._rootBabylonMesh;
                     node._babylonMesh.position = BABYLON.Vector3.Zero();
                     node._babylonMesh.rotationQuaternion = BABYLON.Quaternion.Identity();
@@ -3371,6 +3379,7 @@ var BABYLON;
                 });
             };
             GLTFLoader.prototype._loadAnimationChannelAsync = function (context, animationContext, animation, channel, babylonAnimationGroup) {
+                var _this = this;
                 var targetNode = GLTFLoader._GetProperty(context + "/target/node", this._gltf.nodes, channel.target.node);
                 if (!targetNode._babylonMesh || targetNode.skin != undefined) {
                     return Promise.resolve();
@@ -3401,7 +3410,7 @@ var BABYLON;
                             break;
                         }
                         default: {
-                            throw new Error(context + ": Invalid target path " + channel.target.path);
+                            throw new Error(context + ": Invalid target path (" + channel.target.path + ")");
                         }
                     }
                     var outputBufferOffset = 0;
@@ -3493,11 +3502,10 @@ var BABYLON;
                                 value: key.value[targetIndex],
                                 outTangent: key.outTangent ? key.outTangent[targetIndex] : undefined
                             }); }));
-                            for (var _i = 0, _a = targetNode._primitiveBabylonMeshes; _i < _a.length; _i++) {
-                                var babylonMesh = _a[_i];
+                            _this._forEachNodeMesh(targetNode, function (babylonMesh) {
                                 var morphTarget = babylonMesh.morphTargetManager.getTarget(targetIndex);
                                 babylonAnimationGroup.addTargetedAnimation(babylonAnimation, morphTarget);
-                            }
+                            });
                         };
                         for (var targetIndex = 0; targetIndex < targetNode._numMorphTargets; targetIndex++) {
                             _loop_1(targetIndex);
@@ -3528,7 +3536,7 @@ var BABYLON;
                         break;
                     }
                     default: {
-                        throw new Error(context + ": Invalid interpolation " + sampler.interpolation);
+                        throw new Error(context + ": Invalid interpolation (" + sampler.interpolation + ")");
                     }
                 }
                 var inputData;
@@ -3613,12 +3621,12 @@ var BABYLON;
                                 return _this._buildArrayBuffer(Float32Array, bufferViewData, byteOffset, accessor.count, numComponents, byteStride);
                             }
                             default: {
-                                throw new Error(context + ": Invalid component type " + accessor.componentType);
+                                throw new Error(context + ": Invalid component type (" + accessor.componentType + ")");
                             }
                         }
                     }
                     catch (e) {
-                        throw new Error(context + ": " + e);
+                        throw new Error(context + ": " + e.messsage);
                     }
                 });
                 return accessor._data;
@@ -3782,7 +3790,7 @@ var BABYLON;
                         break;
                     }
                     default: {
-                        throw new Error(context + ": Invalid alpha mode " + material.alphaMode);
+                        throw new Error(context + ": Invalid alpha mode (" + material.alphaMode + ")");
                     }
                 }
             };
@@ -3800,7 +3808,7 @@ var BABYLON;
                     }
                 }, function (message, exception) {
                     if (!_this._disposed) {
-                        deferred.reject(new Error(context + ": " + (exception && exception.message) ? exception.message : message || "Failed to load texture"));
+                        deferred.reject(new Error(context + ": " + ((exception && exception.message) ? exception.message : message || "Failed to load texture")));
                     }
                 });
                 promises.push(deferred.promise);
@@ -3904,7 +3912,7 @@ var BABYLON;
             };
             GLTFLoader._GetProperty = function (context, array, index) {
                 if (!array || index == undefined || !array[index]) {
-                    throw new Error(context + ": Failed to find index " + index);
+                    throw new Error(context + ": Failed to find index (" + index + ")");
                 }
                 return array[index];
             };
@@ -3916,7 +3924,7 @@ var BABYLON;
                     case 33648 /* MIRRORED_REPEAT */: return BABYLON.Texture.MIRROR_ADDRESSMODE;
                     case 10497 /* REPEAT */: return BABYLON.Texture.WRAP_ADDRESSMODE;
                     default:
-                        BABYLON.Tools.Warn(context + ": Invalid texture wrap mode " + mode);
+                        BABYLON.Tools.Warn(context + ": Invalid texture wrap mode (" + mode + ")");
                         return BABYLON.Texture.WRAP_ADDRESSMODE;
                 }
             };
@@ -3933,13 +3941,13 @@ var BABYLON;
                         case 9986 /* NEAREST_MIPMAP_LINEAR */: return BABYLON.Texture.LINEAR_NEAREST_MIPLINEAR;
                         case 9987 /* LINEAR_MIPMAP_LINEAR */: return BABYLON.Texture.LINEAR_LINEAR_MIPLINEAR;
                         default:
-                            BABYLON.Tools.Warn(context + ": Invalid texture minification filter " + minFilter);
+                            BABYLON.Tools.Warn(context + ": Invalid texture minification filter (" + minFilter + ")");
                             return BABYLON.Texture.LINEAR_LINEAR_MIPLINEAR;
                     }
                 }
                 else {
                     if (magFilter !== 9728 /* NEAREST */) {
-                        BABYLON.Tools.Warn(context + ": Invalid texture magnification filter " + magFilter);
+                        BABYLON.Tools.Warn(context + ": Invalid texture magnification filter (" + magFilter + ")");
                     }
                     switch (minFilter) {
                         case 9728 /* NEAREST */: return BABYLON.Texture.NEAREST_NEAREST;
@@ -3949,7 +3957,7 @@ var BABYLON;
                         case 9986 /* NEAREST_MIPMAP_LINEAR */: return BABYLON.Texture.NEAREST_NEAREST_MIPLINEAR;
                         case 9987 /* LINEAR_MIPMAP_LINEAR */: return BABYLON.Texture.NEAREST_LINEAR_MIPLINEAR;
                         default:
-                            BABYLON.Tools.Warn(context + ": Invalid texture minification filter " + minFilter);
+                            BABYLON.Tools.Warn(context + ": Invalid texture minification filter (" + minFilter + ")");
                             return BABYLON.Texture.NEAREST_NEAREST_MIPNEAREST;
                     }
                 }
@@ -3964,7 +3972,7 @@ var BABYLON;
                     case "MAT3": return 9;
                     case "MAT4": return 16;
                 }
-                throw new Error(context + ": Invalid type " + type);
+                throw new Error(context + ": Invalid type (" + type + ")");
             };
             GLTFLoader._ValidateUri = function (uri) {
                 return (BABYLON.Tools.IsBase64(uri) || uri.indexOf("..") === -1);
@@ -4178,7 +4186,10 @@ var BABYLON;
                             var promise = _this._loader._loadNodeAsync("#/nodes/" + nodeLOD._index, nodeLOD).then(function () {
                                 if (indexLOD !== 0) {
                                     var previousNodeLOD = nodeLODs[indexLOD - 1];
-                                    previousNodeLOD._babylonMesh.setEnabled(false);
+                                    if (previousNodeLOD._babylonMesh) {
+                                        previousNodeLOD._babylonMesh.dispose();
+                                        delete previousNodeLOD._babylonMesh;
+                                    }
                                 }
                                 if (indexLOD !== nodeLODs.length - 1) {
                                     var nodeIndex = nodeLODs[indexLOD + 1]._index;
@@ -4222,6 +4233,11 @@ var BABYLON;
                             var promise = _this._loader._loadMaterialAsync("#/materials/" + materialLOD._index, materialLOD, babylonMesh, indexLOD === 0 ? assign : function () { }).then(function () {
                                 if (indexLOD !== 0) {
                                     assign(materialLOD._babylonMaterial);
+                                    var previousMaterialLOD = materialLODs[indexLOD - 1];
+                                    if (previousMaterialLOD._babylonMaterial) {
+                                        previousMaterialLOD._babylonMaterial.dispose();
+                                        delete previousMaterialLOD._babylonMaterial;
+                                    }
                                 }
                                 if (indexLOD !== materialLODs.length - 1) {
                                     var materialIndex = materialLODs[indexLOD + 1]._index;
@@ -4537,7 +4553,7 @@ var BABYLON;
                                 break;
                             }
                             default: {
-                                throw new Error(context + ": Invalid light type " + light.type);
+                                throw new Error(context + ": Invalid light type (" + light.type + ")");
                             }
                         }
                         babylonLight.diffuse = light.color ? BABYLON.Color3.FromArray(light.color) : BABYLON.Color3.White();
@@ -4550,7 +4566,7 @@ var BABYLON;
                     get: function () {
                         var extensions = this._loader._gltf.extensions;
                         if (!extensions || !extensions[this.name]) {
-                            throw new Error("#/extensions: " + this.name + " not found");
+                            throw new Error("#/extensions: '" + this.name + "' not found");
                         }
                         var extension = extensions[this.name];
                         return extension.lights;

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 3 - 3
dist/preview release/loaders/babylon.glTFFileLoader.min.js


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 1 - 1
dist/preview release/loaders/babylon.objFileLoader.min.js


+ 70 - 54
dist/preview release/loaders/babylonjs.loaders.js

@@ -1073,7 +1073,7 @@ var BABYLON;
              */
             this.onMaterialLoadedObservable = new BABYLON.Observable();
             /**
-             * Raised when the loader creates an animation group after parsing the glTF properties of the material.
+             * Raised when the loader creates an animation group after parsing the glTF properties of the animation.
              */
             this.onAnimationGroupLoadedObservable = new BABYLON.Observable();
             /**
@@ -1180,7 +1180,7 @@ var BABYLON;
             configurable: true
         });
         /**
-         * Gets a promise that resolves when the asset to be completely loaded.
+         * Gets a promise that resolves when the asset is completely loaded.
          * @returns A promise that resolves when the asset is completely loaded.
          */
         GLTFFileLoader.prototype.whenCompleteAsync = function () {
@@ -3727,7 +3727,7 @@ var BABYLON;
                         nodes = names.map(function (name) {
                             var node = nodeMap_1[name];
                             if (!node) {
-                                throw new Error("Failed to find node " + name);
+                                throw new Error("Failed to find node '" + name + "'");
                             }
                             return node;
                         });
@@ -3883,7 +3883,7 @@ var BABYLON;
                         break;
                     }
                     default: {
-                        throw new Error("Invalid coordinate system mode " + this.coordinateSystemMode);
+                        throw new Error("Invalid coordinate system mode (" + this.coordinateSystemMode + ")");
                     }
                 }
                 this.onMeshLoadedObservable.notifyObservers(this._rootBabylonMesh);
@@ -3912,6 +3912,17 @@ var BABYLON;
                 promises.push(this._loadAnimationsAsync());
                 return Promise.all(promises).then(function () { });
             };
+            GLTFLoader.prototype._forEachNodeMesh = function (node, callback) {
+                if (node._babylonMesh) {
+                    callback(node._babylonMesh);
+                }
+                if (node._primitiveBabylonMeshes) {
+                    for (var _i = 0, _a = node._primitiveBabylonMeshes; _i < _a.length; _i++) {
+                        var babylonMesh = _a[_i];
+                        callback(babylonMesh);
+                    }
+                }
+            };
             GLTFLoader.prototype._getMeshes = function () {
                 var meshes = new Array();
                 // Root mesh is always first.
@@ -3920,15 +3931,9 @@ var BABYLON;
                 if (nodes) {
                     for (var _i = 0, nodes_2 = nodes; _i < nodes_2.length; _i++) {
                         var node = nodes_2[_i];
-                        if (node._babylonMesh) {
-                            meshes.push(node._babylonMesh);
-                        }
-                        if (node._primitiveBabylonMeshes) {
-                            for (var _a = 0, _b = node._primitiveBabylonMeshes; _a < _b.length; _a++) {
-                                var babylonMesh = _b[_a];
-                                meshes.push(babylonMesh);
-                            }
-                        }
+                        this._forEachNodeMesh(node, function (mesh) {
+                            meshes.push(mesh);
+                        });
                     }
                 }
                 return meshes;
@@ -3969,7 +3974,7 @@ var BABYLON;
                         break;
                     }
                     default: {
-                        BABYLON.Tools.Error("Invalid animation start mode " + this.animationStartMode);
+                        BABYLON.Tools.Error("Invalid animation start mode (" + this.animationStartMode + ")");
                         return;
                     }
                 }
@@ -3990,7 +3995,7 @@ var BABYLON;
                 GLTFLoader._LoadTransform(node, babylonMesh);
                 if (node.mesh != undefined) {
                     var mesh = GLTFLoader._GetProperty(context + "/mesh", this._gltf.meshes, node.mesh);
-                    promises.push(this._loadMeshAsync("#/meshes/" + mesh._index, node, mesh));
+                    promises.push(this._loadMeshAsync("#/meshes/" + mesh._index, node, mesh, babylonMesh));
                 }
                 if (node.children) {
                     for (var _i = 0, _a = node.children; _i < _a.length; _i++) {
@@ -4002,37 +4007,42 @@ var BABYLON;
                 this.onMeshLoadedObservable.notifyObservers(babylonMesh);
                 return Promise.all(promises).then(function () { });
             };
-            GLTFLoader.prototype._loadMeshAsync = function (context, node, mesh) {
+            GLTFLoader.prototype._loadMeshAsync = function (context, node, mesh, babylonMesh) {
                 // TODO: instancing
+                var _this = this;
                 var promises = new Array();
                 var primitives = mesh.primitives;
                 if (!primitives || primitives.length === 0) {
                     throw new Error(context + ": Primitives are missing");
                 }
                 GLTF2.ArrayItem.Assign(primitives);
-                for (var _i = 0, primitives_1 = primitives; _i < primitives_1.length; _i++) {
-                    var primitive = primitives_1[_i];
-                    promises.push(this._loadPrimitiveAsync(context + "/primitives/" + primitive._index, node, mesh, primitive));
+                if (primitives.length === 1) {
+                    var primitive = primitives[0];
+                    promises.push(this._loadPrimitiveAsync(context + "/primitives/" + primitive._index, node, mesh, primitive, babylonMesh));
+                }
+                else {
+                    node._primitiveBabylonMeshes = [];
+                    for (var _i = 0, primitives_1 = primitives; _i < primitives_1.length; _i++) {
+                        var primitive = primitives_1[_i];
+                        var primitiveBabylonMesh = new BABYLON.Mesh((mesh.name || babylonMesh.name) + "_" + primitive._index, this._babylonScene, babylonMesh);
+                        node._primitiveBabylonMeshes.push(babylonMesh);
+                        promises.push(this._loadPrimitiveAsync(context + "/primitives/" + primitive._index, node, mesh, primitive, primitiveBabylonMesh));
+                        this.onMeshLoadedObservable.notifyObservers(babylonMesh);
+                    }
                 }
                 if (node.skin != undefined) {
                     var skin = GLTFLoader._GetProperty(context + "/skin", this._gltf.skins, node.skin);
                     promises.push(this._loadSkinAsync("#/skins/" + skin._index, node, mesh, skin));
                 }
                 return Promise.all(promises).then(function () {
-                    if (node._primitiveBabylonMeshes) {
-                        for (var _i = 0, _a = node._primitiveBabylonMeshes; _i < _a.length; _i++) {
-                            var primitiveBabylonMesh = _a[_i];
-                            primitiveBabylonMesh._refreshBoundingInfo(true);
-                        }
-                    }
+                    _this._forEachNodeMesh(node, function (babylonMesh) {
+                        babylonMesh._refreshBoundingInfo(true);
+                    });
                 });
             };
-            GLTFLoader.prototype._loadPrimitiveAsync = function (context, node, mesh, primitive) {
+            GLTFLoader.prototype._loadPrimitiveAsync = function (context, node, mesh, primitive, babylonMesh) {
                 var _this = this;
                 var promises = new Array();
-                var babylonMesh = new BABYLON.Mesh((mesh.name || node._babylonMesh.name) + "_" + primitive._index, this._babylonScene, node._babylonMesh);
-                node._primitiveBabylonMeshes = node._primitiveBabylonMeshes || [];
-                node._primitiveBabylonMeshes[primitive._index] = babylonMesh;
                 this._createMorphTargets(context, node, mesh, primitive, babylonMesh);
                 promises.push(this._loadVertexDataAsync(context, primitive, babylonMesh).then(function (babylonVertexData) {
                     new BABYLON.Geometry(babylonMesh.name, _this._babylonScene, babylonVertexData, false, babylonMesh);
@@ -4042,12 +4052,11 @@ var BABYLON;
                     babylonMesh.material = this._getDefaultMaterial();
                 }
                 else {
-                    var material = GLTFLoader._GetProperty(context + "/material", this._gltf.materials, primitive.material);
+                    var material = GLTFLoader._GetProperty(context + "/material}", this._gltf.materials, primitive.material);
                     promises.push(this._loadMaterialAsync("#/materials/" + material._index, material, babylonMesh, function (babylonMaterial) {
                         babylonMesh.material = babylonMaterial;
                     }));
                 }
-                this.onMeshLoadedObservable.notifyObservers(babylonMesh);
                 return Promise.all(promises).then(function () { });
             };
             GLTFLoader.prototype._loadVertexDataAsync = function (context, primitive, babylonMesh) {
@@ -4062,7 +4071,7 @@ var BABYLON;
                 }
                 if (primitive.mode != undefined && primitive.mode !== 4 /* TRIANGLES */) {
                     // TODO: handle other primitive modes
-                    throw new Error(context + ": Mode " + primitive.mode + " is not currently supported");
+                    throw new Error(context + ": Mode (" + primitive.mode + ") is not currently supported");
                 }
                 var promises = new Array();
                 var babylonVertexData = new BABYLON.VertexData();
@@ -4204,7 +4213,7 @@ var BABYLON;
                             break;
                         }
                         default: {
-                            throw new Error(context + ": Invalid component type " + accessor.componentType);
+                            throw new Error(context + ": Invalid component type (" + accessor.componentType + ")");
                         }
                     }
                 }
@@ -4250,10 +4259,9 @@ var BABYLON;
             GLTFLoader.prototype._loadSkinAsync = function (context, node, mesh, skin) {
                 var _this = this;
                 var assignSkeleton = function () {
-                    for (var _i = 0, _a = node._primitiveBabylonMeshes; _i < _a.length; _i++) {
-                        var babylonMesh = _a[_i];
+                    _this._forEachNodeMesh(node, function (babylonMesh) {
                         babylonMesh.skeleton = skin._babylonSkeleton;
-                    }
+                    });
                     node._babylonMesh.parent = _this._rootBabylonMesh;
                     node._babylonMesh.position = BABYLON.Vector3.Zero();
                     node._babylonMesh.rotationQuaternion = BABYLON.Quaternion.Identity();
@@ -4349,6 +4357,7 @@ var BABYLON;
                 });
             };
             GLTFLoader.prototype._loadAnimationChannelAsync = function (context, animationContext, animation, channel, babylonAnimationGroup) {
+                var _this = this;
                 var targetNode = GLTFLoader._GetProperty(context + "/target/node", this._gltf.nodes, channel.target.node);
                 if (!targetNode._babylonMesh || targetNode.skin != undefined) {
                     return Promise.resolve();
@@ -4379,7 +4388,7 @@ var BABYLON;
                             break;
                         }
                         default: {
-                            throw new Error(context + ": Invalid target path " + channel.target.path);
+                            throw new Error(context + ": Invalid target path (" + channel.target.path + ")");
                         }
                     }
                     var outputBufferOffset = 0;
@@ -4471,11 +4480,10 @@ var BABYLON;
                                 value: key.value[targetIndex],
                                 outTangent: key.outTangent ? key.outTangent[targetIndex] : undefined
                             }); }));
-                            for (var _i = 0, _a = targetNode._primitiveBabylonMeshes; _i < _a.length; _i++) {
-                                var babylonMesh = _a[_i];
+                            _this._forEachNodeMesh(targetNode, function (babylonMesh) {
                                 var morphTarget = babylonMesh.morphTargetManager.getTarget(targetIndex);
                                 babylonAnimationGroup.addTargetedAnimation(babylonAnimation, morphTarget);
-                            }
+                            });
                         };
                         for (var targetIndex = 0; targetIndex < targetNode._numMorphTargets; targetIndex++) {
                             _loop_1(targetIndex);
@@ -4506,7 +4514,7 @@ var BABYLON;
                         break;
                     }
                     default: {
-                        throw new Error(context + ": Invalid interpolation " + sampler.interpolation);
+                        throw new Error(context + ": Invalid interpolation (" + sampler.interpolation + ")");
                     }
                 }
                 var inputData;
@@ -4591,12 +4599,12 @@ var BABYLON;
                                 return _this._buildArrayBuffer(Float32Array, bufferViewData, byteOffset, accessor.count, numComponents, byteStride);
                             }
                             default: {
-                                throw new Error(context + ": Invalid component type " + accessor.componentType);
+                                throw new Error(context + ": Invalid component type (" + accessor.componentType + ")");
                             }
                         }
                     }
                     catch (e) {
-                        throw new Error(context + ": " + e);
+                        throw new Error(context + ": " + e.messsage);
                     }
                 });
                 return accessor._data;
@@ -4760,7 +4768,7 @@ var BABYLON;
                         break;
                     }
                     default: {
-                        throw new Error(context + ": Invalid alpha mode " + material.alphaMode);
+                        throw new Error(context + ": Invalid alpha mode (" + material.alphaMode + ")");
                     }
                 }
             };
@@ -4778,7 +4786,7 @@ var BABYLON;
                     }
                 }, function (message, exception) {
                     if (!_this._disposed) {
-                        deferred.reject(new Error(context + ": " + (exception && exception.message) ? exception.message : message || "Failed to load texture"));
+                        deferred.reject(new Error(context + ": " + ((exception && exception.message) ? exception.message : message || "Failed to load texture")));
                     }
                 });
                 promises.push(deferred.promise);
@@ -4882,7 +4890,7 @@ var BABYLON;
             };
             GLTFLoader._GetProperty = function (context, array, index) {
                 if (!array || index == undefined || !array[index]) {
-                    throw new Error(context + ": Failed to find index " + index);
+                    throw new Error(context + ": Failed to find index (" + index + ")");
                 }
                 return array[index];
             };
@@ -4894,7 +4902,7 @@ var BABYLON;
                     case 33648 /* MIRRORED_REPEAT */: return BABYLON.Texture.MIRROR_ADDRESSMODE;
                     case 10497 /* REPEAT */: return BABYLON.Texture.WRAP_ADDRESSMODE;
                     default:
-                        BABYLON.Tools.Warn(context + ": Invalid texture wrap mode " + mode);
+                        BABYLON.Tools.Warn(context + ": Invalid texture wrap mode (" + mode + ")");
                         return BABYLON.Texture.WRAP_ADDRESSMODE;
                 }
             };
@@ -4911,13 +4919,13 @@ var BABYLON;
                         case 9986 /* NEAREST_MIPMAP_LINEAR */: return BABYLON.Texture.LINEAR_NEAREST_MIPLINEAR;
                         case 9987 /* LINEAR_MIPMAP_LINEAR */: return BABYLON.Texture.LINEAR_LINEAR_MIPLINEAR;
                         default:
-                            BABYLON.Tools.Warn(context + ": Invalid texture minification filter " + minFilter);
+                            BABYLON.Tools.Warn(context + ": Invalid texture minification filter (" + minFilter + ")");
                             return BABYLON.Texture.LINEAR_LINEAR_MIPLINEAR;
                     }
                 }
                 else {
                     if (magFilter !== 9728 /* NEAREST */) {
-                        BABYLON.Tools.Warn(context + ": Invalid texture magnification filter " + magFilter);
+                        BABYLON.Tools.Warn(context + ": Invalid texture magnification filter (" + magFilter + ")");
                     }
                     switch (minFilter) {
                         case 9728 /* NEAREST */: return BABYLON.Texture.NEAREST_NEAREST;
@@ -4927,7 +4935,7 @@ var BABYLON;
                         case 9986 /* NEAREST_MIPMAP_LINEAR */: return BABYLON.Texture.NEAREST_NEAREST_MIPLINEAR;
                         case 9987 /* LINEAR_MIPMAP_LINEAR */: return BABYLON.Texture.NEAREST_LINEAR_MIPLINEAR;
                         default:
-                            BABYLON.Tools.Warn(context + ": Invalid texture minification filter " + minFilter);
+                            BABYLON.Tools.Warn(context + ": Invalid texture minification filter (" + minFilter + ")");
                             return BABYLON.Texture.NEAREST_NEAREST_MIPNEAREST;
                     }
                 }
@@ -4942,7 +4950,7 @@ var BABYLON;
                     case "MAT3": return 9;
                     case "MAT4": return 16;
                 }
-                throw new Error(context + ": Invalid type " + type);
+                throw new Error(context + ": Invalid type (" + type + ")");
             };
             GLTFLoader._ValidateUri = function (uri) {
                 return (BABYLON.Tools.IsBase64(uri) || uri.indexOf("..") === -1);
@@ -5147,7 +5155,10 @@ var BABYLON;
                             var promise = _this._loader._loadNodeAsync("#/nodes/" + nodeLOD._index, nodeLOD).then(function () {
                                 if (indexLOD !== 0) {
                                     var previousNodeLOD = nodeLODs[indexLOD - 1];
-                                    previousNodeLOD._babylonMesh.setEnabled(false);
+                                    if (previousNodeLOD._babylonMesh) {
+                                        previousNodeLOD._babylonMesh.dispose();
+                                        delete previousNodeLOD._babylonMesh;
+                                    }
                                 }
                                 if (indexLOD !== nodeLODs.length - 1) {
                                     var nodeIndex = nodeLODs[indexLOD + 1]._index;
@@ -5191,6 +5202,11 @@ var BABYLON;
                             var promise = _this._loader._loadMaterialAsync("#/materials/" + materialLOD._index, materialLOD, babylonMesh, indexLOD === 0 ? assign : function () { }).then(function () {
                                 if (indexLOD !== 0) {
                                     assign(materialLOD._babylonMaterial);
+                                    var previousMaterialLOD = materialLODs[indexLOD - 1];
+                                    if (previousMaterialLOD._babylonMaterial) {
+                                        previousMaterialLOD._babylonMaterial.dispose();
+                                        delete previousMaterialLOD._babylonMaterial;
+                                    }
                                 }
                                 if (indexLOD !== materialLODs.length - 1) {
                                     var materialIndex = materialLODs[indexLOD + 1]._index;
@@ -5479,7 +5495,7 @@ var BABYLON;
                                 break;
                             }
                             default: {
-                                throw new Error(context + ": Invalid light type " + light.type);
+                                throw new Error(context + ": Invalid light type (" + light.type + ")");
                             }
                         }
                         babylonLight.diffuse = light.color ? BABYLON.Color3.FromArray(light.color) : BABYLON.Color3.White();
@@ -5492,7 +5508,7 @@ var BABYLON;
                     get: function () {
                         var extensions = this._loader._gltf.extensions;
                         if (!extensions || !extensions[this.name]) {
-                            throw new Error("#/extensions: " + this.name + " not found");
+                            throw new Error("#/extensions: '" + this.name + "' not found");
                         }
                         var extension = extensions[this.name];
                         return extension.lights;

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 3 - 3
dist/preview release/loaders/babylonjs.loaders.min.js


+ 5 - 4
dist/preview release/loaders/babylonjs.loaders.module.d.ts

@@ -218,7 +218,7 @@ declare module BABYLON {
         private _onMaterialLoadedObserver;
         onMaterialLoaded: (material: Material) => void;
         /**
-         * Raised when the loader creates an animation group after parsing the glTF properties of the material.
+         * Raised when the loader creates an animation group after parsing the glTF properties of the animation.
          */
         readonly onAnimationGroupLoadedObservable: Observable<AnimationGroup>;
         private _onAnimationGroupLoadedObserver;
@@ -245,7 +245,7 @@ declare module BABYLON {
         private _onExtensionLoadedObserver;
         onExtensionLoaded: (extension: IGLTFLoaderExtension) => void;
         /**
-         * Gets a promise that resolves when the asset to be completely loaded.
+         * Gets a promise that resolves when the asset is completely loaded.
          * @returns A promise that resolves when the asset is completely loaded.
          */
         whenCompleteAsync(): Promise<void>;
@@ -979,12 +979,13 @@ declare module BABYLON.GLTF2 {
         private _createRootNode();
         private _loadNodesAsync(nodes);
         _loadSceneAsync(context: string, scene: ILoaderScene): Promise<void>;
+        private _forEachNodeMesh(node, callback);
         private _getMeshes();
         private _getSkeletons();
         private _startAnimations();
         _loadNodeAsync(context: string, node: ILoaderNode): Promise<void>;
-        private _loadMeshAsync(context, node, mesh);
-        private _loadPrimitiveAsync(context, node, mesh, primitive);
+        private _loadMeshAsync(context, node, mesh, babylonMesh);
+        private _loadPrimitiveAsync(context, node, mesh, primitive, babylonMesh);
         private _loadVertexDataAsync(context, primitive, babylonMesh);
         private _createMorphTargets(context, node, mesh, primitive, babylonMesh);
         private _loadMorphTargetsAsync(context, primitive, babylonMesh, babylonVertexData);

+ 4 - 282
dist/preview release/materialsLibrary/babylon.customMaterial.d.ts

@@ -1,277 +1,5 @@
 
 declare module BABYLON {
-    class StandardMaterialDefines_OldVer extends MaterialDefines implements IImageProcessingConfigurationDefines {
-        DIFFUSE: boolean;
-        AMBIENT: boolean;
-        OPACITY: boolean;
-        OPACITYRGB: boolean;
-        REFLECTION: boolean;
-        EMISSIVE: boolean;
-        SPECULAR: boolean;
-        BUMP: boolean;
-        PARALLAX: boolean;
-        PARALLAXOCCLUSION: boolean;
-        SPECULAROVERALPHA: boolean;
-        CLIPPLANE: boolean;
-        ALPHATEST: boolean;
-        ALPHAFROMDIFFUSE: boolean;
-        POINTSIZE: boolean;
-        FOG: boolean;
-        SPECULARTERM: boolean;
-        DIFFUSEFRESNEL: boolean;
-        OPACITYFRESNEL: boolean;
-        REFLECTIONFRESNEL: boolean;
-        REFRACTIONFRESNEL: boolean;
-        EMISSIVEFRESNEL: boolean;
-        FRESNEL: boolean;
-        NORMAL: boolean;
-        UV1: boolean;
-        UV2: boolean;
-        VERTEXCOLOR: boolean;
-        VERTEXALPHA: boolean;
-        NUM_BONE_INFLUENCERS: number;
-        BonesPerMesh: number;
-        INSTANCES: boolean;
-        GLOSSINESS: boolean;
-        ROUGHNESS: boolean;
-        EMISSIVEASILLUMINATION: boolean;
-        LINKEMISSIVEWITHDIFFUSE: boolean;
-        REFLECTIONFRESNELFROMSPECULAR: boolean;
-        LIGHTMAP: boolean;
-        USELIGHTMAPASSHADOWMAP: boolean;
-        REFLECTIONMAP_3D: boolean;
-        REFLECTIONMAP_SPHERICAL: boolean;
-        REFLECTIONMAP_PLANAR: boolean;
-        REFLECTIONMAP_CUBIC: boolean;
-        REFLECTIONMAP_PROJECTION: boolean;
-        REFLECTIONMAP_SKYBOX: boolean;
-        REFLECTIONMAP_EXPLICIT: boolean;
-        REFLECTIONMAP_EQUIRECTANGULAR: boolean;
-        REFLECTIONMAP_EQUIRECTANGULAR_FIXED: boolean;
-        REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED: boolean;
-        INVERTCUBICMAP: boolean;
-        LOGARITHMICDEPTH: boolean;
-        REFRACTION: boolean;
-        REFRACTIONMAP_3D: boolean;
-        REFLECTIONOVERALPHA: boolean;
-        TWOSIDEDLIGHTING: boolean;
-        SHADOWFLOAT: boolean;
-        MORPHTARGETS: boolean;
-        MORPHTARGETS_NORMAL: boolean;
-        MORPHTARGETS_TANGENT: boolean;
-        NUM_MORPH_INFLUENCERS: number;
-        IMAGEPROCESSING: boolean;
-        VIGNETTE: boolean;
-        VIGNETTEBLENDMODEMULTIPLY: boolean;
-        VIGNETTEBLENDMODEOPAQUE: boolean;
-        TONEMAPPING: boolean;
-        CONTRAST: boolean;
-        COLORCURVES: boolean;
-        COLORGRADING: boolean;
-        COLORGRADING3D: boolean;
-        SAMPLER3DGREENDEPTH: boolean;
-        SAMPLER3DBGRMAP: boolean;
-        IMAGEPROCESSINGPOSTPROCESS: boolean;
-        EXPOSURE: boolean;
-        GRAIN: boolean;
-        constructor();
-        setReflectionMode(modeToEnable: string): void;
-    }
-    class StandardMaterial_OldVer extends PushMaterial {
-        private _diffuseTexture;
-        diffuseTexture: BaseTexture;
-        private _ambientTexture;
-        ambientTexture: BaseTexture;
-        private _opacityTexture;
-        opacityTexture: BaseTexture;
-        private _reflectionTexture;
-        reflectionTexture: BaseTexture;
-        private _emissiveTexture;
-        emissiveTexture: BaseTexture;
-        private _specularTexture;
-        specularTexture: BaseTexture;
-        private _bumpTexture;
-        bumpTexture: BaseTexture;
-        private _lightmapTexture;
-        lightmapTexture: BaseTexture;
-        private _refractionTexture;
-        refractionTexture: BaseTexture;
-        ambientColor: Color3;
-        diffuseColor: Color3;
-        specularColor: Color3;
-        emissiveColor: Color3;
-        specularPower: number;
-        private _useAlphaFromDiffuseTexture;
-        useAlphaFromDiffuseTexture: boolean;
-        private _useEmissiveAsIllumination;
-        useEmissiveAsIllumination: boolean;
-        private _linkEmissiveWithDiffuse;
-        linkEmissiveWithDiffuse: boolean;
-        private _useSpecularOverAlpha;
-        useSpecularOverAlpha: boolean;
-        private _useReflectionOverAlpha;
-        useReflectionOverAlpha: boolean;
-        private _disableLighting;
-        disableLighting: boolean;
-        private _useParallax;
-        useParallax: boolean;
-        private _useParallaxOcclusion;
-        useParallaxOcclusion: boolean;
-        parallaxScaleBias: number;
-        private _roughness;
-        roughness: number;
-        indexOfRefraction: number;
-        invertRefractionY: boolean;
-        private _useLightmapAsShadowmap;
-        useLightmapAsShadowmap: boolean;
-        private _diffuseFresnelParameters;
-        diffuseFresnelParameters: FresnelParameters;
-        private _opacityFresnelParameters;
-        opacityFresnelParameters: FresnelParameters;
-        private _reflectionFresnelParameters;
-        reflectionFresnelParameters: FresnelParameters;
-        private _refractionFresnelParameters;
-        refractionFresnelParameters: FresnelParameters;
-        private _emissiveFresnelParameters;
-        emissiveFresnelParameters: FresnelParameters;
-        private _useReflectionFresnelFromSpecular;
-        useReflectionFresnelFromSpecular: boolean;
-        private _useGlossinessFromSpecularMapAlpha;
-        useGlossinessFromSpecularMapAlpha: boolean;
-        private _maxSimultaneousLights;
-        maxSimultaneousLights: number;
-        /**
-         * If sets to true, x component of normal map value will invert (x = 1.0 - x).
-         */
-        private _invertNormalMapX;
-        invertNormalMapX: boolean;
-        /**
-         * If sets to true, y component of normal map value will invert (y = 1.0 - y).
-         */
-        private _invertNormalMapY;
-        invertNormalMapY: boolean;
-        /**
-         * If sets to true and backfaceCulling is false, normals will be flipped on the backside.
-         */
-        private _twoSidedLighting;
-        twoSidedLighting: boolean;
-        /**
-         * Default configuration related to image processing available in the standard Material.
-         */
-        protected _imageProcessingConfiguration: ImageProcessingConfiguration;
-        /**
-         * Gets the image processing configuration used either in this material.
-         */
-        /**
-         * Sets the Default image processing configuration used either in the this material.
-         *
-         * If sets to null, the scene one is in use.
-         */
-        imageProcessingConfiguration: ImageProcessingConfiguration;
-        /**
-         * Keep track of the image processing observer to allow dispose and replace.
-         */
-        private _imageProcessingObserver;
-        /**
-         * Attaches a new image processing configuration to the Standard Material.
-         * @param configuration
-         */
-        protected _attachImageProcessingConfiguration(configuration: Nullable<ImageProcessingConfiguration>): void;
-        /**
-         * Gets wether the color curves effect is enabled.
-         */
-        /**
-         * Sets wether the color curves effect is enabled.
-         */
-        cameraColorCurvesEnabled: boolean;
-        /**
-         * Gets wether the color grading effect is enabled.
-         */
-        /**
-         * Gets wether the color grading effect is enabled.
-         */
-        cameraColorGradingEnabled: boolean;
-        /**
-         * Gets wether tonemapping is enabled or not.
-         */
-        /**
-         * Sets wether tonemapping is enabled or not
-         */
-        cameraToneMappingEnabled: boolean;
-        /**
-         * The camera exposure used on this material.
-         * This property is here and not in the camera to allow controlling exposure without full screen post process.
-         * This corresponds to a photographic exposure.
-         */
-        /**
-         * The camera exposure used on this material.
-         * This property is here and not in the camera to allow controlling exposure without full screen post process.
-         * This corresponds to a photographic exposure.
-         */
-        cameraExposure: number;
-        /**
-         * Gets The camera contrast used on this material.
-         */
-        /**
-         * Sets The camera contrast used on this material.
-         */
-        cameraContrast: number;
-        /**
-         * Gets the Color Grading 2D Lookup Texture.
-         */
-        /**
-         * Sets the Color Grading 2D Lookup Texture.
-         */
-        cameraColorGradingTexture: Nullable<BaseTexture>;
-        protected _shouldTurnAlphaTestOn(mesh: AbstractMesh): boolean;
-        customShaderNameResolve: (shaderName: string, uniforms: string[], uniformBuffers: string[], samplers: string[], defines: StandardMaterialDefines_OldVer) => string;
-        protected _renderTargets: SmartArray<RenderTargetTexture>;
-        protected _worldViewProjectionMatrix: Matrix;
-        protected _globalAmbientColor: Color3;
-        protected _useLogarithmicDepth: boolean;
-        constructor(name: string, scene: Scene);
-        getClassName(): string;
-        useLogarithmicDepth: boolean;
-        needAlphaBlending(): boolean;
-        needAlphaTesting(): boolean;
-        protected _shouldUseAlphaFromDiffuseTexture(): boolean;
-        getAlphaTestTexture(): BaseTexture;
-        /**
-         * Child classes can use it to update shaders
-         */
-        isReadyForSubMesh(mesh: AbstractMesh, subMesh: SubMesh, useInstances?: boolean): boolean;
-        buildUniformLayout(): void;
-        unbind(): void;
-        bindForSubMesh(world: Matrix, mesh: Mesh, subMesh: SubMesh): void;
-        getAnimatables(): IAnimatable[];
-        getActiveTextures(): BaseTexture[];
-        dispose(forceDisposeEffect?: boolean, forceDisposeTextures?: boolean): void;
-        clone(name: string): StandardMaterial_OldVer;
-        serialize(): any;
-        static Parse(source: any, scene: Scene, rootUrl: string): StandardMaterial_OldVer;
-        static _DiffuseTextureEnabled: boolean;
-        static DiffuseTextureEnabled: boolean;
-        static _AmbientTextureEnabled: boolean;
-        static AmbientTextureEnabled: boolean;
-        static _OpacityTextureEnabled: boolean;
-        static OpacityTextureEnabled: boolean;
-        static _ReflectionTextureEnabled: boolean;
-        static ReflectionTextureEnabled: boolean;
-        static _EmissiveTextureEnabled: boolean;
-        static EmissiveTextureEnabled: boolean;
-        static _SpecularTextureEnabled: boolean;
-        static SpecularTextureEnabled: boolean;
-        static _BumpTextureEnabled: boolean;
-        static BumpTextureEnabled: boolean;
-        static _LightmapTextureEnabled: boolean;
-        static LightmapTextureEnabled: boolean;
-        static _RefractionTextureEnabled: boolean;
-        static RefractionTextureEnabled: boolean;
-        static _ColorGradingTextureEnabled: boolean;
-        static ColorGradingTextureEnabled: boolean;
-        static _FresnelEnabled: boolean;
-        static FresnelEnabled: boolean;
-    }
     class CustomShaderStructure {
         FragmentStore: string;
         VertexStore: string;
@@ -291,26 +19,20 @@ declare module BABYLON {
         Vertex_Before_PositionUpdated: string;
         Vertex_Before_NormalUpdated: string;
     }
-    class ShaderForVer3_0 extends CustomShaderStructure {
-        constructor();
-    }
-    class StandardShaderVersions {
-        static Ver3_0: string;
-    }
-    class CustomMaterial extends StandardMaterial_OldVer {
+    class CustomMaterial extends StandardMaterial {
         static ShaderIndexer: number;
         CustomParts: ShaderSpecialParts;
-        ShaderVersion: CustomShaderStructure;
         _isCreatedShader: boolean;
         _createdShaderName: string;
         _customUniform: string[];
         _newUniforms: string[];
         _newUniformInstances: any[];
         _newSamplerInstances: Texture[];
+        FragmentShader: string;
+        VertexShader: string;
         AttachAfterBind(mesh: Mesh, effect: Effect): void;
         ReviewUniform(name: string, arr: string[]): string[];
-        Builder(shaderName: string, uniforms: string[], uniformBuffers: string[], samplers: string[], defines: StandardMaterialDefines_OldVer): string;
-        SelectVersion(ver: string): void;
+        Builder(shaderName: string, uniforms: string[], uniformBuffers: string[], samplers: string[], defines: StandardMaterialDefines): string;
         constructor(name: string, scene: Scene);
         AddUniform(name: string, kind: string, param: any): CustomMaterial;
         Fragment_Begin(shaderPart: string): CustomMaterial;

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 19 - 1908
dist/preview release/materialsLibrary/babylon.customMaterial.js


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 1 - 2
dist/preview release/materialsLibrary/babylon.customMaterial.min.js


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 1 - 1
dist/preview release/materialsLibrary/babylon.shadowOnlyMaterial.min.js


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 1 - 1
dist/preview release/materialsLibrary/babylon.waterMaterial.min.js


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 22 - 1906
dist/preview release/materialsLibrary/babylonjs.materials.js


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 4 - 6
dist/preview release/materialsLibrary/babylonjs.materials.min.js


+ 4 - 282
dist/preview release/materialsLibrary/babylonjs.materials.module.d.ts

@@ -506,278 +506,6 @@ declare module BABYLON {
 
 
 declare module BABYLON {
-    class StandardMaterialDefines_OldVer extends MaterialDefines implements IImageProcessingConfigurationDefines {
-        DIFFUSE: boolean;
-        AMBIENT: boolean;
-        OPACITY: boolean;
-        OPACITYRGB: boolean;
-        REFLECTION: boolean;
-        EMISSIVE: boolean;
-        SPECULAR: boolean;
-        BUMP: boolean;
-        PARALLAX: boolean;
-        PARALLAXOCCLUSION: boolean;
-        SPECULAROVERALPHA: boolean;
-        CLIPPLANE: boolean;
-        ALPHATEST: boolean;
-        ALPHAFROMDIFFUSE: boolean;
-        POINTSIZE: boolean;
-        FOG: boolean;
-        SPECULARTERM: boolean;
-        DIFFUSEFRESNEL: boolean;
-        OPACITYFRESNEL: boolean;
-        REFLECTIONFRESNEL: boolean;
-        REFRACTIONFRESNEL: boolean;
-        EMISSIVEFRESNEL: boolean;
-        FRESNEL: boolean;
-        NORMAL: boolean;
-        UV1: boolean;
-        UV2: boolean;
-        VERTEXCOLOR: boolean;
-        VERTEXALPHA: boolean;
-        NUM_BONE_INFLUENCERS: number;
-        BonesPerMesh: number;
-        INSTANCES: boolean;
-        GLOSSINESS: boolean;
-        ROUGHNESS: boolean;
-        EMISSIVEASILLUMINATION: boolean;
-        LINKEMISSIVEWITHDIFFUSE: boolean;
-        REFLECTIONFRESNELFROMSPECULAR: boolean;
-        LIGHTMAP: boolean;
-        USELIGHTMAPASSHADOWMAP: boolean;
-        REFLECTIONMAP_3D: boolean;
-        REFLECTIONMAP_SPHERICAL: boolean;
-        REFLECTIONMAP_PLANAR: boolean;
-        REFLECTIONMAP_CUBIC: boolean;
-        REFLECTIONMAP_PROJECTION: boolean;
-        REFLECTIONMAP_SKYBOX: boolean;
-        REFLECTIONMAP_EXPLICIT: boolean;
-        REFLECTIONMAP_EQUIRECTANGULAR: boolean;
-        REFLECTIONMAP_EQUIRECTANGULAR_FIXED: boolean;
-        REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED: boolean;
-        INVERTCUBICMAP: boolean;
-        LOGARITHMICDEPTH: boolean;
-        REFRACTION: boolean;
-        REFRACTIONMAP_3D: boolean;
-        REFLECTIONOVERALPHA: boolean;
-        TWOSIDEDLIGHTING: boolean;
-        SHADOWFLOAT: boolean;
-        MORPHTARGETS: boolean;
-        MORPHTARGETS_NORMAL: boolean;
-        MORPHTARGETS_TANGENT: boolean;
-        NUM_MORPH_INFLUENCERS: number;
-        IMAGEPROCESSING: boolean;
-        VIGNETTE: boolean;
-        VIGNETTEBLENDMODEMULTIPLY: boolean;
-        VIGNETTEBLENDMODEOPAQUE: boolean;
-        TONEMAPPING: boolean;
-        CONTRAST: boolean;
-        COLORCURVES: boolean;
-        COLORGRADING: boolean;
-        COLORGRADING3D: boolean;
-        SAMPLER3DGREENDEPTH: boolean;
-        SAMPLER3DBGRMAP: boolean;
-        IMAGEPROCESSINGPOSTPROCESS: boolean;
-        EXPOSURE: boolean;
-        GRAIN: boolean;
-        constructor();
-        setReflectionMode(modeToEnable: string): void;
-    }
-    class StandardMaterial_OldVer extends PushMaterial {
-        private _diffuseTexture;
-        diffuseTexture: BaseTexture;
-        private _ambientTexture;
-        ambientTexture: BaseTexture;
-        private _opacityTexture;
-        opacityTexture: BaseTexture;
-        private _reflectionTexture;
-        reflectionTexture: BaseTexture;
-        private _emissiveTexture;
-        emissiveTexture: BaseTexture;
-        private _specularTexture;
-        specularTexture: BaseTexture;
-        private _bumpTexture;
-        bumpTexture: BaseTexture;
-        private _lightmapTexture;
-        lightmapTexture: BaseTexture;
-        private _refractionTexture;
-        refractionTexture: BaseTexture;
-        ambientColor: Color3;
-        diffuseColor: Color3;
-        specularColor: Color3;
-        emissiveColor: Color3;
-        specularPower: number;
-        private _useAlphaFromDiffuseTexture;
-        useAlphaFromDiffuseTexture: boolean;
-        private _useEmissiveAsIllumination;
-        useEmissiveAsIllumination: boolean;
-        private _linkEmissiveWithDiffuse;
-        linkEmissiveWithDiffuse: boolean;
-        private _useSpecularOverAlpha;
-        useSpecularOverAlpha: boolean;
-        private _useReflectionOverAlpha;
-        useReflectionOverAlpha: boolean;
-        private _disableLighting;
-        disableLighting: boolean;
-        private _useParallax;
-        useParallax: boolean;
-        private _useParallaxOcclusion;
-        useParallaxOcclusion: boolean;
-        parallaxScaleBias: number;
-        private _roughness;
-        roughness: number;
-        indexOfRefraction: number;
-        invertRefractionY: boolean;
-        private _useLightmapAsShadowmap;
-        useLightmapAsShadowmap: boolean;
-        private _diffuseFresnelParameters;
-        diffuseFresnelParameters: FresnelParameters;
-        private _opacityFresnelParameters;
-        opacityFresnelParameters: FresnelParameters;
-        private _reflectionFresnelParameters;
-        reflectionFresnelParameters: FresnelParameters;
-        private _refractionFresnelParameters;
-        refractionFresnelParameters: FresnelParameters;
-        private _emissiveFresnelParameters;
-        emissiveFresnelParameters: FresnelParameters;
-        private _useReflectionFresnelFromSpecular;
-        useReflectionFresnelFromSpecular: boolean;
-        private _useGlossinessFromSpecularMapAlpha;
-        useGlossinessFromSpecularMapAlpha: boolean;
-        private _maxSimultaneousLights;
-        maxSimultaneousLights: number;
-        /**
-         * If sets to true, x component of normal map value will invert (x = 1.0 - x).
-         */
-        private _invertNormalMapX;
-        invertNormalMapX: boolean;
-        /**
-         * If sets to true, y component of normal map value will invert (y = 1.0 - y).
-         */
-        private _invertNormalMapY;
-        invertNormalMapY: boolean;
-        /**
-         * If sets to true and backfaceCulling is false, normals will be flipped on the backside.
-         */
-        private _twoSidedLighting;
-        twoSidedLighting: boolean;
-        /**
-         * Default configuration related to image processing available in the standard Material.
-         */
-        protected _imageProcessingConfiguration: ImageProcessingConfiguration;
-        /**
-         * Gets the image processing configuration used either in this material.
-         */
-        /**
-         * Sets the Default image processing configuration used either in the this material.
-         *
-         * If sets to null, the scene one is in use.
-         */
-        imageProcessingConfiguration: ImageProcessingConfiguration;
-        /**
-         * Keep track of the image processing observer to allow dispose and replace.
-         */
-        private _imageProcessingObserver;
-        /**
-         * Attaches a new image processing configuration to the Standard Material.
-         * @param configuration
-         */
-        protected _attachImageProcessingConfiguration(configuration: Nullable<ImageProcessingConfiguration>): void;
-        /**
-         * Gets wether the color curves effect is enabled.
-         */
-        /**
-         * Sets wether the color curves effect is enabled.
-         */
-        cameraColorCurvesEnabled: boolean;
-        /**
-         * Gets wether the color grading effect is enabled.
-         */
-        /**
-         * Gets wether the color grading effect is enabled.
-         */
-        cameraColorGradingEnabled: boolean;
-        /**
-         * Gets wether tonemapping is enabled or not.
-         */
-        /**
-         * Sets wether tonemapping is enabled or not
-         */
-        cameraToneMappingEnabled: boolean;
-        /**
-         * The camera exposure used on this material.
-         * This property is here and not in the camera to allow controlling exposure without full screen post process.
-         * This corresponds to a photographic exposure.
-         */
-        /**
-         * The camera exposure used on this material.
-         * This property is here and not in the camera to allow controlling exposure without full screen post process.
-         * This corresponds to a photographic exposure.
-         */
-        cameraExposure: number;
-        /**
-         * Gets The camera contrast used on this material.
-         */
-        /**
-         * Sets The camera contrast used on this material.
-         */
-        cameraContrast: number;
-        /**
-         * Gets the Color Grading 2D Lookup Texture.
-         */
-        /**
-         * Sets the Color Grading 2D Lookup Texture.
-         */
-        cameraColorGradingTexture: Nullable<BaseTexture>;
-        protected _shouldTurnAlphaTestOn(mesh: AbstractMesh): boolean;
-        customShaderNameResolve: (shaderName: string, uniforms: string[], uniformBuffers: string[], samplers: string[], defines: StandardMaterialDefines_OldVer) => string;
-        protected _renderTargets: SmartArray<RenderTargetTexture>;
-        protected _worldViewProjectionMatrix: Matrix;
-        protected _globalAmbientColor: Color3;
-        protected _useLogarithmicDepth: boolean;
-        constructor(name: string, scene: Scene);
-        getClassName(): string;
-        useLogarithmicDepth: boolean;
-        needAlphaBlending(): boolean;
-        needAlphaTesting(): boolean;
-        protected _shouldUseAlphaFromDiffuseTexture(): boolean;
-        getAlphaTestTexture(): BaseTexture;
-        /**
-         * Child classes can use it to update shaders
-         */
-        isReadyForSubMesh(mesh: AbstractMesh, subMesh: SubMesh, useInstances?: boolean): boolean;
-        buildUniformLayout(): void;
-        unbind(): void;
-        bindForSubMesh(world: Matrix, mesh: Mesh, subMesh: SubMesh): void;
-        getAnimatables(): IAnimatable[];
-        getActiveTextures(): BaseTexture[];
-        dispose(forceDisposeEffect?: boolean, forceDisposeTextures?: boolean): void;
-        clone(name: string): StandardMaterial_OldVer;
-        serialize(): any;
-        static Parse(source: any, scene: Scene, rootUrl: string): StandardMaterial_OldVer;
-        static _DiffuseTextureEnabled: boolean;
-        static DiffuseTextureEnabled: boolean;
-        static _AmbientTextureEnabled: boolean;
-        static AmbientTextureEnabled: boolean;
-        static _OpacityTextureEnabled: boolean;
-        static OpacityTextureEnabled: boolean;
-        static _ReflectionTextureEnabled: boolean;
-        static ReflectionTextureEnabled: boolean;
-        static _EmissiveTextureEnabled: boolean;
-        static EmissiveTextureEnabled: boolean;
-        static _SpecularTextureEnabled: boolean;
-        static SpecularTextureEnabled: boolean;
-        static _BumpTextureEnabled: boolean;
-        static BumpTextureEnabled: boolean;
-        static _LightmapTextureEnabled: boolean;
-        static LightmapTextureEnabled: boolean;
-        static _RefractionTextureEnabled: boolean;
-        static RefractionTextureEnabled: boolean;
-        static _ColorGradingTextureEnabled: boolean;
-        static ColorGradingTextureEnabled: boolean;
-        static _FresnelEnabled: boolean;
-        static FresnelEnabled: boolean;
-    }
     class CustomShaderStructure {
         FragmentStore: string;
         VertexStore: string;
@@ -797,26 +525,20 @@ declare module BABYLON {
         Vertex_Before_PositionUpdated: string;
         Vertex_Before_NormalUpdated: string;
     }
-    class ShaderForVer3_0 extends CustomShaderStructure {
-        constructor();
-    }
-    class StandardShaderVersions {
-        static Ver3_0: string;
-    }
-    class CustomMaterial extends StandardMaterial_OldVer {
+    class CustomMaterial extends StandardMaterial {
         static ShaderIndexer: number;
         CustomParts: ShaderSpecialParts;
-        ShaderVersion: CustomShaderStructure;
         _isCreatedShader: boolean;
         _createdShaderName: string;
         _customUniform: string[];
         _newUniforms: string[];
         _newUniformInstances: any[];
         _newSamplerInstances: Texture[];
+        FragmentShader: string;
+        VertexShader: string;
         AttachAfterBind(mesh: Mesh, effect: Effect): void;
         ReviewUniform(name: string, arr: string[]): string[];
-        Builder(shaderName: string, uniforms: string[], uniformBuffers: string[], samplers: string[], defines: StandardMaterialDefines_OldVer): string;
-        SelectVersion(ver: string): void;
+        Builder(shaderName: string, uniforms: string[], uniformBuffers: string[], samplers: string[], defines: StandardMaterialDefines): string;
         constructor(name: string, scene: Scene);
         AddUniform(name: string, kind: string, param: any): CustomMaterial;
         Fragment_Begin(shaderPart: string): CustomMaterial;

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 1 - 1
dist/preview release/postProcessesLibrary/babylon.asciiArtPostProcess.min.js


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 1 - 1
dist/preview release/postProcessesLibrary/babylon.digitalRainPostProcess.min.js


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 1 - 1
dist/preview release/postProcessesLibrary/babylonjs.postProcess.min.js


+ 86 - 29
dist/preview release/serializers/babylon.glTF2Serializer.d.ts

@@ -290,23 +290,33 @@ declare module BABYLON.GLTF2 {
         /**
          * Represents the dielectric specular values for R, G and B.
          */
-        private static readonly dielectricSpecular;
+        private static readonly _dielectricSpecular;
         /**
          * Allows the maximum specular power to be defined for material calculations.
          */
-        private static maxSpecularPower;
-        private static epsilon;
+        private static _maxSpecularPower;
+        /**
+         * Numeric tolerance value
+         */
+        private static _epsilon;
+        /**
+         * Specifies if two colors are approximately equal in value.
+         * @param color1 - first color to compare to.
+         * @param color2 - second color to compare to.
+         * @param epsilon - threshold value
+         */
+        private static FuzzyEquals(color1, color2, epsilon);
         /**
          * Gets the materials from a Babylon scene and converts them to glTF materials.
-         * @param scene
-         * @param mimeType
-         * @param images
-         * @param textures
-         * @param materials
-         * @param imageData
-         * @param hasTextureCoords
-         */
-        static ConvertMaterialsToGLTF(babylonMaterials: Material[], mimeType: ImageMimeType, images: IImage[], textures: ITexture[], materials: IMaterial[], imageData: {
+         * @param scene - babylonjs scene.
+         * @param mimeType - texture mime type.
+         * @param images - array of images.
+         * @param textures - array of textures.
+         * @param materials - array of materials.
+         * @param imageData - mapping of texture names to base64 textures
+         * @param hasTextureCoords - specifies if texture coordinates are present on the material.
+         */
+        static _ConvertMaterialsToGLTF(babylonMaterials: Material[], mimeType: ImageMimeType, images: IImage[], textures: ITexture[], materials: IMaterial[], imageData: {
             [fileName: string]: {
                 data: Uint8Array;
                 mimeType: ImageMimeType;
@@ -317,19 +327,19 @@ declare module BABYLON.GLTF2 {
          * @param originalMaterial - original glTF material.
          * @returns glTF material without texture parameters
          */
-        static StripTexturesFromMaterial(originalMaterial: IMaterial): IMaterial;
+        static _StripTexturesFromMaterial(originalMaterial: IMaterial): IMaterial;
         /**
          * Specifies if the material has any texture parameters present.
          * @param material - glTF Material.
          * @returns boolean specifying if texture parameters are present
          */
-        static HasTexturesPresent(material: IMaterial): boolean;
+        static _HasTexturesPresent(material: IMaterial): boolean;
         /**
          * Converts a Babylon StandardMaterial to a glTF Metallic Roughness Material.
          * @param babylonStandardMaterial
          * @returns - glTF Metallic Roughness Material representation
          */
-        static ConvertToGLTFPBRMetallicRoughness(babylonStandardMaterial: StandardMaterial): IMaterialPbrMetallicRoughness;
+        static _ConvertToGLTFPBRMetallicRoughness(babylonStandardMaterial: StandardMaterial): IMaterialPbrMetallicRoughness;
         /**
          * Computes the metallic factor
          * @param diffuse - diffused value
@@ -337,13 +347,13 @@ declare module BABYLON.GLTF2 {
          * @param oneMinusSpecularStrength - one minus the specular strength
          * @returns - metallic value
          */
-        static SolveMetallic(diffuse: number, specular: number, oneMinusSpecularStrength: number): number;
+        static _SolveMetallic(diffuse: number, specular: number, oneMinusSpecularStrength: number): number;
         /**
          * Gets the glTF alpha mode from the Babylon Material
          * @param babylonMaterial - Babylon Material
          * @returns - The Babylon alpha mode value
          */
-        static GetAlphaMode(babylonMaterial: Material): MaterialAlphaMode;
+        static _GetAlphaMode(babylonMaterial: Material): MaterialAlphaMode;
         /**
          * Converts a Babylon Standard Material to a glTF Material.
          * @param babylonStandardMaterial - BJS Standard Material.
@@ -354,7 +364,7 @@ declare module BABYLON.GLTF2 {
          * @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.
          */
-        static ConvertStandardMaterial(babylonStandardMaterial: StandardMaterial, mimeType: ImageMimeType, images: IImage[], textures: ITexture[], materials: IMaterial[], imageData: {
+        static _ConvertStandardMaterial(babylonStandardMaterial: StandardMaterial, mimeType: ImageMimeType, images: IImage[], textures: ITexture[], materials: IMaterial[], imageData: {
             [fileName: string]: {
                 data: Uint8Array;
                 mimeType: ImageMimeType;
@@ -370,25 +380,66 @@ declare module BABYLON.GLTF2 {
          * @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.
          */
-        static ConvertPBRMetallicRoughnessMaterial(babylonPBRMetalRoughMaterial: PBRMetallicRoughnessMaterial, mimeType: ImageMimeType, images: IImage[], textures: ITexture[], materials: IMaterial[], imageData: {
+        static _ConvertPBRMetallicRoughnessMaterial(babylonPBRMetalRoughMaterial: PBRMetallicRoughnessMaterial, mimeType: ImageMimeType, images: IImage[], textures: ITexture[], materials: IMaterial[], imageData: {
             [fileName: string]: {
                 data: Uint8Array;
                 mimeType: ImageMimeType;
             };
         }, hasTextureCoords: boolean): void;
         /**
+         * Converts an image typed array buffer to a base64 image.
+         * @param buffer - typed array buffer.
+         * @param width - width of the image.
+         * @param height - height of the image.
+         * @param mimeType - mimetype of the image.
+         * @returns - base64 image string.
+         */
+        private static _CreateBase64FromCanvas(buffer, width, height, mimeType);
+        /**
+         * Generates a white texture based on the specified width and height.
+         * @param width - width of the texture in pixels.
+         * @param height - height of the texture in pixels.
+         * @param scene - babylonjs scene.
+         * @returns - white texture.
+         */
+        private static _CreateWhiteTexture(width, height, scene);
+        /**
+         * Resizes the two source textures to the same dimensions.  If a texture is null, a default white texture is generated.  If both textures are null, returns null.
+         * @param texture1 - first texture to resize.
+         * @param texture2 - second texture to resize.
+         * @param scene - babylonjs scene.
+         * @returns resized textures or null.
+         */
+        private static _ResizeTexturesToSameDimensions(texture1, texture2, scene);
+        /**
+         * Convert Specular Glossiness Textures to Metallic Roughness.
          * See link below for info on the material conversions from PBR Metallic/Roughness and Specular/Glossiness
          * @link https://github.com/KhronosGroup/glTF/blob/master/extensions/2.0/Khronos/KHR_materials_pbrSpecularGlossiness/examples/convert-between-workflows-bjs/js/babylon.pbrUtilities.js
+         * @param diffuseTexture - texture used to store diffuse information.
+         * @param specularGlossinessTexture - texture used to store specular and glossiness information.
+         * @param factors - specular glossiness material factors.
+         * @param mimeType - the mime type to use for the texture.
+         * @returns pbr metallic roughness interface or null.
+         */
+        private static _ConvertSpecularGlossinessTexturesToMetallicRoughness(diffuseTexture, specularGlossinessTexture, factors, mimeType);
+        /**
+         * Converts specular glossiness material properties to metallic roughness.
+         * @param specularGlossiness - interface with specular glossiness material properties.
+         * @returns - interface with metallic roughness material properties.
+         */
+        private static _ConvertSpecularGlossinessToMetallicRoughness(specularGlossiness);
+        /**
+         * Calculates the surface reflectance, independent of lighting conditions.
          * @param color - Color source to calculate brightness from.
          * @returns number representing the perceived brightness, or zero if color is undefined.
          */
-        static GetPerceivedBrightness(color: Color3): number;
+        private static _GetPerceivedBrightness(color);
         /**
          * Returns the maximum color component value.
          * @param color
          * @returns maximum color component value, or zero if color is null or undefined.
          */
-        static GetMaxComponent(color: Color3): number;
+        private static _GetMaxComponent(color);
         /**
          * Converts a Babylon PBR Metallic Roughness Material to a glTF Material.
          * @param babylonPBRMaterial - BJS PBR Metallic Roughness Material.
@@ -399,7 +450,7 @@ declare module BABYLON.GLTF2 {
          * @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.
          */
-        static ConvertPBRMaterial(babylonPBRMaterial: PBRMaterial, mimeType: ImageMimeType, images: IImage[], textures: ITexture[], materials: IMaterial[], imageData: {
+        static _ConvertPBRMaterial(babylonPBRMaterial: PBRMaterial, mimeType: ImageMimeType, images: IImage[], textures: ITexture[], materials: IMaterial[], imageData: {
             [fileName: string]: {
                 data: Uint8Array;
                 mimeType: ImageMimeType;
@@ -412,13 +463,19 @@ declare module BABYLON.GLTF2 {
          * @param images - Array of glTF images.
          * @param textures - Array of glTF textures.
          * @param imageData - map of image file name and data.
-         * @return - glTF texture, or null if the texture format is not supported.
+         * @return - glTF texture info, or null if the texture format is not supported.
          */
-        static ExportTexture(babylonTexture: BaseTexture, mimeType: ImageMimeType, images: IImage[], textures: ITexture[], imageData: {
-            [fileName: string]: {
-                data: Uint8Array;
-                mimeType: ImageMimeType;
-            };
-        }): Nullable<ITextureInfo>;
+        private static _ExportTexture(babylonTexture, mimeType, images, textures, imageData);
+        /**
+         * Builds a texture from base64 string.
+         * @param base64Texture - base64 texture string.
+         * @param textureName - Name to use for the texture.
+         * @param mimeType - image mime type for the texture.
+         * @param images - array of images.
+         * @param textures - array of textures.
+         * @param imageData - map of image data.
+         * @returns - glTF texture info, or null if the texture format is not supported.
+         */
+        private static _GetTextureInfoFromBase64(base64Texture, textureName, mimeType, images, textures, imageData);
     }
 }

+ 385 - 158
dist/preview release/serializers/babylon.glTF2Serializer.js

@@ -613,13 +613,13 @@ var BABYLON;
                                 else {
                                     BABYLON.Tools.Warn("Material type " + bufferMesh.material.getClassName() + " for material " + bufferMesh.material.name + " is not yet implemented in glTF serializer.");
                                 }
-                                if (materialIndex != null) {
-                                    if (uvCoordsPresent || !GLTF2._GLTFMaterial.HasTexturesPresent(this.materials[materialIndex])) {
+                                if (materialIndex != null && Object.keys(meshPrimitive.attributes).length > 0) {
+                                    if (uvCoordsPresent || !GLTF2._GLTFMaterial._HasTexturesPresent(this.materials[materialIndex])) {
                                         meshPrimitive.material = materialIndex;
                                     }
                                     else {
                                         // If no texture coordinate information is present, make a copy of the material without the textures to be glTF compliant.
-                                        var newMat = GLTF2._GLTFMaterial.StripTexturesFromMaterial(this.materials[materialIndex]);
+                                        var newMat = GLTF2._GLTFMaterial._StripTexturesFromMaterial(this.materials[materialIndex]);
                                         this.materials.push(newMat);
                                         meshPrimitive.material = this.materials.length - 1;
                                     }
@@ -642,7 +642,7 @@ var BABYLON;
                 if (babylonScene.meshes.length) {
                     var babylonMeshes = babylonScene.meshes;
                     var scene = { nodes: new Array() };
-                    GLTF2._GLTFMaterial.ConvertMaterialsToGLTF(babylonScene.materials, "image/jpeg" /* JPEG */, this.images, this.textures, this.materials, this.imageData, true);
+                    GLTF2._GLTFMaterial._ConvertMaterialsToGLTF(babylonScene.materials, "image/png" /* PNG */, this.images, this.textures, this.materials, this.imageData, true);
                     var result = this.createNodeMap(babylonScene, byteOffset);
                     this.nodeMap = result.nodeMap;
                     this.totalByteLength = result.byteOffset;
@@ -799,29 +799,40 @@ var BABYLON;
             function _GLTFMaterial() {
             }
             /**
+             * Specifies if two colors are approximately equal in value.
+             * @param color1 - first color to compare to.
+             * @param color2 - second color to compare to.
+             * @param epsilon - threshold value
+             */
+            _GLTFMaterial.FuzzyEquals = function (color1, color2, epsilon) {
+                return BABYLON.Scalar.WithinEpsilon(color1.r, color2.r, epsilon) &&
+                    BABYLON.Scalar.WithinEpsilon(color1.g, color2.g, epsilon) &&
+                    BABYLON.Scalar.WithinEpsilon(color1.b, color2.b, epsilon);
+            };
+            /**
              * Gets the materials from a Babylon scene and converts them to glTF materials.
-             * @param scene
-             * @param mimeType
-             * @param images
-             * @param textures
-             * @param materials
-             * @param imageData
-             * @param hasTextureCoords
+             * @param scene - babylonjs scene.
+             * @param mimeType - texture mime type.
+             * @param images - array of images.
+             * @param textures - array of textures.
+             * @param materials - array of materials.
+             * @param imageData - mapping of texture names to base64 textures
+             * @param hasTextureCoords - specifies if texture coordinates are present on the material.
              */
-            _GLTFMaterial.ConvertMaterialsToGLTF = function (babylonMaterials, mimeType, images, textures, materials, imageData, hasTextureCoords) {
+            _GLTFMaterial._ConvertMaterialsToGLTF = function (babylonMaterials, mimeType, images, textures, materials, imageData, hasTextureCoords) {
                 for (var i = 0; i < babylonMaterials.length; ++i) {
                     var babylonMaterial = babylonMaterials[i];
                     if (babylonMaterial instanceof BABYLON.StandardMaterial) {
-                        _GLTFMaterial.ConvertStandardMaterial(babylonMaterial, mimeType, images, textures, materials, imageData, hasTextureCoords);
+                        _GLTFMaterial._ConvertStandardMaterial(babylonMaterial, mimeType, images, textures, materials, imageData, hasTextureCoords);
                     }
                     else if (babylonMaterial instanceof BABYLON.PBRMetallicRoughnessMaterial) {
-                        _GLTFMaterial.ConvertPBRMetallicRoughnessMaterial(babylonMaterial, mimeType, images, textures, materials, imageData, hasTextureCoords);
+                        _GLTFMaterial._ConvertPBRMetallicRoughnessMaterial(babylonMaterial, mimeType, images, textures, materials, imageData, hasTextureCoords);
                     }
                     else if (babylonMaterial instanceof BABYLON.PBRMaterial) {
-                        _GLTFMaterial.ConvertPBRMaterial(babylonMaterial, mimeType, images, textures, materials, imageData, hasTextureCoords);
+                        _GLTFMaterial._ConvertPBRMaterial(babylonMaterial, mimeType, images, textures, materials, imageData, hasTextureCoords);
                     }
                     else {
-                        BABYLON.Tools.Error("Unsupported material type: " + babylonMaterial.name);
+                        throw new Error("Unsupported material type: " + babylonMaterial.name);
                     }
                 }
             };
@@ -830,7 +841,7 @@ var BABYLON;
              * @param originalMaterial - original glTF material.
              * @returns glTF material without texture parameters
              */
-            _GLTFMaterial.StripTexturesFromMaterial = function (originalMaterial) {
+            _GLTFMaterial._StripTexturesFromMaterial = function (originalMaterial) {
                 var newMaterial = {};
                 if (originalMaterial) {
                     newMaterial.name = originalMaterial.name;
@@ -853,7 +864,7 @@ var BABYLON;
              * @param material - glTF Material.
              * @returns boolean specifying if texture parameters are present
              */
-            _GLTFMaterial.HasTexturesPresent = function (material) {
+            _GLTFMaterial._HasTexturesPresent = function (material) {
                 if (material.emissiveTexture || material.normalTexture || material.occlusionTexture) {
                     return true;
                 }
@@ -870,7 +881,7 @@ var BABYLON;
              * @param babylonStandardMaterial
              * @returns - glTF Metallic Roughness Material representation
              */
-            _GLTFMaterial.ConvertToGLTFPBRMetallicRoughness = function (babylonStandardMaterial) {
+            _GLTFMaterial._ConvertToGLTFPBRMetallicRoughness = function (babylonStandardMaterial) {
                 var P0 = new BABYLON.Vector2(0, 1);
                 var P1 = new BABYLON.Vector2(0, 0.1);
                 var P2 = new BABYLON.Vector2(0, 0.1);
@@ -884,7 +895,7 @@ var BABYLON;
                  * @param p3 - fourth control point.
                  * @returns - number result of cubic bezier curve at the specified t.
                  */
-                function cubicBezierCurve(t, p0, p1, p2, p3) {
+                function _cubicBezierCurve(t, p0, p1, p2, p3) {
                     return ((1 - t) * (1 - t) * (1 - t) * p0 +
                         3 * (1 - t) * (1 - t) * t * p1 +
                         3 * (1 - t) * t * t * p2 +
@@ -897,14 +908,14 @@ var BABYLON;
                  * @param specularPower - specular power of standard material.
                  * @returns - Number representing the roughness value.
                  */
-                function solveForRoughness(specularPower) {
+                function _solveForRoughness(specularPower) {
                     var t = Math.pow(specularPower / P3.x, 0.333333);
-                    return cubicBezierCurve(t, P0.y, P1.y, P2.y, P3.y);
+                    return _cubicBezierCurve(t, P0.y, P1.y, P2.y, P3.y);
                 }
                 var diffuse = babylonStandardMaterial.diffuseColor.toLinearSpace().scale(0.5);
                 var opacity = babylonStandardMaterial.alpha;
-                var specularPower = BABYLON.Scalar.Clamp(babylonStandardMaterial.specularPower, 0, this.maxSpecularPower);
-                var roughness = solveForRoughness(specularPower);
+                var specularPower = BABYLON.Scalar.Clamp(babylonStandardMaterial.specularPower, 0, this._maxSpecularPower);
+                var roughness = _solveForRoughness(specularPower);
                 var glTFPbrMetallicRoughness = {
                     baseColorFactor: [
                         diffuse.r,
@@ -924,14 +935,14 @@ var BABYLON;
              * @param oneMinusSpecularStrength - one minus the specular strength
              * @returns - metallic value
              */
-            _GLTFMaterial.SolveMetallic = function (diffuse, specular, oneMinusSpecularStrength) {
-                if (specular < _GLTFMaterial.dielectricSpecular.r) {
-                    _GLTFMaterial.dielectricSpecular;
+            _GLTFMaterial._SolveMetallic = function (diffuse, specular, oneMinusSpecularStrength) {
+                if (specular < _GLTFMaterial._dielectricSpecular.r) {
+                    _GLTFMaterial._dielectricSpecular;
                     return 0;
                 }
-                var a = _GLTFMaterial.dielectricSpecular.r;
-                var b = diffuse * oneMinusSpecularStrength / (1.0 - _GLTFMaterial.dielectricSpecular.r) + specular - 2.0 * _GLTFMaterial.dielectricSpecular.r;
-                var c = _GLTFMaterial.dielectricSpecular.r - specular;
+                var a = _GLTFMaterial._dielectricSpecular.r;
+                var b = diffuse * oneMinusSpecularStrength / (1.0 - _GLTFMaterial._dielectricSpecular.r) + specular - 2.0 * _GLTFMaterial._dielectricSpecular.r;
+                var c = _GLTFMaterial._dielectricSpecular.r - specular;
                 var D = b * b - 4.0 * a * c;
                 return BABYLON.Scalar.Clamp((-b + Math.sqrt(D)) / (2.0 * a), 0, 1);
             };
@@ -940,7 +951,7 @@ var BABYLON;
              * @param babylonMaterial - Babylon Material
              * @returns - The Babylon alpha mode value
              */
-            _GLTFMaterial.GetAlphaMode = function (babylonMaterial) {
+            _GLTFMaterial._GetAlphaMode = function (babylonMaterial) {
                 if (babylonMaterial instanceof BABYLON.StandardMaterial) {
                     var babylonStandardMaterial = babylonMaterial;
                     if ((babylonStandardMaterial.alpha != 1.0) ||
@@ -1008,11 +1019,11 @@ var BABYLON;
              * @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.
              */
-            _GLTFMaterial.ConvertStandardMaterial = function (babylonStandardMaterial, mimeType, images, textures, materials, imageData, hasTextureCoords) {
+            _GLTFMaterial._ConvertStandardMaterial = function (babylonStandardMaterial, mimeType, images, textures, materials, imageData, hasTextureCoords) {
                 BABYLON.Tools.Warn(babylonStandardMaterial.name + ": Standard Material is currently not fully supported/implemented in glTF serializer");
-                var glTFPbrMetallicRoughness = _GLTFMaterial.ConvertToGLTFPBRMetallicRoughness(babylonStandardMaterial);
+                var glTFPbrMetallicRoughness = _GLTFMaterial._ConvertToGLTFPBRMetallicRoughness(babylonStandardMaterial);
                 var glTFMaterial = { name: babylonStandardMaterial.name };
-                if (babylonStandardMaterial.backFaceCulling) {
+                if (babylonStandardMaterial.backFaceCulling != null && !babylonStandardMaterial.backFaceCulling) {
                     if (!babylonStandardMaterial.twoSidedLighting) {
                         BABYLON.Tools.Warn(babylonStandardMaterial.name + ": Back-face culling enabled and two-sided lighting disabled is not supported in glTF.");
                     }
@@ -1020,26 +1031,26 @@ var BABYLON;
                 }
                 if (hasTextureCoords) {
                     if (babylonStandardMaterial.diffuseTexture) {
-                        var glTFTexture = _GLTFMaterial.ExportTexture(babylonStandardMaterial.diffuseTexture, mimeType, images, textures, imageData);
+                        var glTFTexture = _GLTFMaterial._ExportTexture(babylonStandardMaterial.diffuseTexture, mimeType, images, textures, imageData);
                         if (glTFTexture != null) {
                             glTFPbrMetallicRoughness.baseColorTexture = glTFTexture;
                         }
                     }
                     if (babylonStandardMaterial.bumpTexture) {
-                        var glTFTexture = _GLTFMaterial.ExportTexture(babylonStandardMaterial.bumpTexture, mimeType, images, textures, imageData);
+                        var glTFTexture = _GLTFMaterial._ExportTexture(babylonStandardMaterial.bumpTexture, mimeType, images, textures, imageData);
                         if (glTFTexture) {
                             glTFMaterial.normalTexture = glTFTexture;
                         }
                     }
                     if (babylonStandardMaterial.emissiveTexture) {
-                        var glTFEmissiveTexture = _GLTFMaterial.ExportTexture(babylonStandardMaterial.emissiveTexture, mimeType, images, textures, imageData);
+                        var glTFEmissiveTexture = _GLTFMaterial._ExportTexture(babylonStandardMaterial.emissiveTexture, mimeType, images, textures, imageData);
                         if (glTFEmissiveTexture) {
                             glTFMaterial.emissiveTexture = glTFEmissiveTexture;
                         }
                         glTFMaterial.emissiveFactor = [1.0, 1.0, 1.0];
                     }
                     if (babylonStandardMaterial.ambientTexture) {
-                        var glTFTexture = _GLTFMaterial.ExportTexture(babylonStandardMaterial.ambientTexture, mimeType, images, textures, imageData);
+                        var glTFTexture = _GLTFMaterial._ExportTexture(babylonStandardMaterial.ambientTexture, mimeType, images, textures, imageData);
                         if (glTFTexture) {
                             var occlusionTexture = {
                                 index: glTFTexture.index
@@ -1057,7 +1068,7 @@ var BABYLON;
                         BABYLON.Tools.Warn(babylonStandardMaterial.name + ": glTF 2.0 does not support alpha mode: " + babylonStandardMaterial.alphaMode.toString());
                     }
                 }
-                if (babylonStandardMaterial.emissiveColor) {
+                if (babylonStandardMaterial.emissiveColor && !this.FuzzyEquals(babylonStandardMaterial.emissiveColor, BABYLON.Color3.Black(), this._epsilon)) {
                     glTFMaterial.emissiveFactor = babylonStandardMaterial.emissiveColor.asArray();
                 }
                 glTFMaterial.pbrMetallicRoughness = glTFPbrMetallicRoughness;
@@ -1073,7 +1084,7 @@ var BABYLON;
              * @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.
              */
-            _GLTFMaterial.ConvertPBRMetallicRoughnessMaterial = function (babylonPBRMetalRoughMaterial, mimeType, images, textures, materials, imageData, hasTextureCoords) {
+            _GLTFMaterial._ConvertPBRMetallicRoughnessMaterial = function (babylonPBRMetalRoughMaterial, mimeType, images, textures, materials, imageData, hasTextureCoords) {
                 var glTFPbrMetallicRoughness = {};
                 if (babylonPBRMetalRoughMaterial.baseColor) {
                     glTFPbrMetallicRoughness.baseColorFactor = [
@@ -1083,10 +1094,10 @@ var BABYLON;
                         babylonPBRMetalRoughMaterial.alpha
                     ];
                 }
-                if (babylonPBRMetalRoughMaterial.metallic != null) {
+                if (babylonPBRMetalRoughMaterial.metallic != null && babylonPBRMetalRoughMaterial.metallic !== 1) {
                     glTFPbrMetallicRoughness.metallicFactor = babylonPBRMetalRoughMaterial.metallic;
                 }
-                if (babylonPBRMetalRoughMaterial.roughness != null) {
+                if (babylonPBRMetalRoughMaterial.roughness != null && babylonPBRMetalRoughMaterial.roughness !== 1) {
                     glTFPbrMetallicRoughness.roughnessFactor = babylonPBRMetalRoughMaterial.roughness;
                 }
                 var glTFMaterial = {
@@ -1097,19 +1108,19 @@ var BABYLON;
                 }
                 if (hasTextureCoords) {
                     if (babylonPBRMetalRoughMaterial.baseTexture != null) {
-                        var glTFTexture = _GLTFMaterial.ExportTexture(babylonPBRMetalRoughMaterial.baseTexture, mimeType, images, textures, imageData);
+                        var glTFTexture = _GLTFMaterial._ExportTexture(babylonPBRMetalRoughMaterial.baseTexture, mimeType, images, textures, imageData);
                         if (glTFTexture != null) {
                             glTFPbrMetallicRoughness.baseColorTexture = glTFTexture;
                         }
                     }
                     if (babylonPBRMetalRoughMaterial.normalTexture) {
-                        var glTFTexture = _GLTFMaterial.ExportTexture(babylonPBRMetalRoughMaterial.normalTexture, mimeType, images, textures, imageData);
+                        var glTFTexture = _GLTFMaterial._ExportTexture(babylonPBRMetalRoughMaterial.normalTexture, mimeType, images, textures, imageData);
                         if (glTFTexture) {
                             glTFMaterial.normalTexture = glTFTexture;
                         }
                     }
                     if (babylonPBRMetalRoughMaterial.occlusionTexture) {
-                        var glTFTexture = _GLTFMaterial.ExportTexture(babylonPBRMetalRoughMaterial.occlusionTexture, mimeType, images, textures, imageData);
+                        var glTFTexture = _GLTFMaterial._ExportTexture(babylonPBRMetalRoughMaterial.occlusionTexture, mimeType, images, textures, imageData);
                         if (glTFTexture) {
                             glTFMaterial.occlusionTexture = glTFTexture;
                             if (babylonPBRMetalRoughMaterial.occlusionStrength != null) {
@@ -1118,17 +1129,17 @@ var BABYLON;
                         }
                     }
                     if (babylonPBRMetalRoughMaterial.emissiveTexture) {
-                        var glTFTexture = _GLTFMaterial.ExportTexture(babylonPBRMetalRoughMaterial.emissiveTexture, mimeType, images, textures, imageData);
+                        var glTFTexture = _GLTFMaterial._ExportTexture(babylonPBRMetalRoughMaterial.emissiveTexture, mimeType, images, textures, imageData);
                         if (glTFTexture != null) {
                             glTFMaterial.emissiveTexture = glTFTexture;
                         }
                     }
                 }
-                if (babylonPBRMetalRoughMaterial.emissiveColor.equalsFloats(0.0, 0.0, 0.0)) {
+                if (this.FuzzyEquals(babylonPBRMetalRoughMaterial.emissiveColor, BABYLON.Color3.Black(), this._epsilon)) {
                     glTFMaterial.emissiveFactor = babylonPBRMetalRoughMaterial.emissiveColor.asArray();
                 }
                 if (babylonPBRMetalRoughMaterial.transparencyMode != null) {
-                    var alphaMode = _GLTFMaterial.GetAlphaMode(babylonPBRMetalRoughMaterial);
+                    var alphaMode = _GLTFMaterial._GetAlphaMode(babylonPBRMetalRoughMaterial);
                     if (alphaMode !== "OPAQUE" /* OPAQUE */) {
                         glTFMaterial.alphaMode = alphaMode;
                         if (alphaMode === "BLEND" /* BLEND */) {
@@ -1140,12 +1151,213 @@ var BABYLON;
                 materials.push(glTFMaterial);
             };
             /**
+             * Converts an image typed array buffer to a base64 image.
+             * @param buffer - typed array buffer.
+             * @param width - width of the image.
+             * @param height - height of the image.
+             * @param mimeType - mimetype of the image.
+             * @returns - base64 image string.
+             */
+            _GLTFMaterial._CreateBase64FromCanvas = function (buffer, width, height, mimeType) {
+                var imageCanvas = document.createElement('canvas');
+                imageCanvas.id = "WriteCanvas";
+                var ctx = imageCanvas.getContext('2d');
+                imageCanvas.width = width;
+                imageCanvas.height = height;
+                var imgData = ctx.createImageData(width, height);
+                imgData.data.set(buffer);
+                ctx.putImageData(imgData, 0, 0);
+                return imageCanvas.toDataURL(mimeType);
+            };
+            /**
+             * Generates a white texture based on the specified width and height.
+             * @param width - width of the texture in pixels.
+             * @param height - height of the texture in pixels.
+             * @param scene - babylonjs scene.
+             * @returns - white texture.
+             */
+            _GLTFMaterial._CreateWhiteTexture = function (width, height, scene) {
+                var data = new Uint8Array(width * height * 4);
+                for (var i = 0; i < data.length; ++i) {
+                    data[i] = 255;
+                }
+                var rawTexture = BABYLON.RawTexture.CreateRGBATexture(data, width, height, scene);
+                return rawTexture;
+            };
+            /**
+             * Resizes the two source textures to the same dimensions.  If a texture is null, a default white texture is generated.  If both textures are null, returns null.
+             * @param texture1 - first texture to resize.
+             * @param texture2 - second texture to resize.
+             * @param scene - babylonjs scene.
+             * @returns resized textures or null.
+             */
+            _GLTFMaterial._ResizeTexturesToSameDimensions = function (texture1, texture2, scene) {
+                var texture1Size = texture1 ? texture1.getSize() : { width: 0, height: 0 };
+                var texture2Size = texture2 ? texture2.getSize() : { width: 0, height: 0 };
+                var resizedTexture1;
+                var resizedTexture2;
+                if (texture1Size.width < texture2Size.width) {
+                    if (texture1) {
+                        resizedTexture1 = BABYLON.TextureTools.CreateResizedCopy(texture1, texture2Size.width, texture2Size.height, true);
+                    }
+                    else {
+                        resizedTexture1 = this._CreateWhiteTexture(texture2Size.width, texture2Size.height, scene);
+                    }
+                    resizedTexture2 = texture2;
+                }
+                else if (texture1Size.width > texture2Size.width) {
+                    if (texture2) {
+                        resizedTexture2 = BABYLON.TextureTools.CreateResizedCopy(texture2, texture1Size.width, texture1Size.height, true);
+                    }
+                    else {
+                        resizedTexture2 = this._CreateWhiteTexture(texture1Size.width, texture1Size.height, scene);
+                    }
+                    resizedTexture1 = texture1;
+                }
+                else {
+                    resizedTexture1 = texture1;
+                    resizedTexture2 = texture2;
+                }
+                return {
+                    "texture1": resizedTexture1,
+                    "texture2": resizedTexture2
+                };
+            };
+            /**
+             * Convert Specular Glossiness Textures to Metallic Roughness.
              * See link below for info on the material conversions from PBR Metallic/Roughness and Specular/Glossiness
              * @link https://github.com/KhronosGroup/glTF/blob/master/extensions/2.0/Khronos/KHR_materials_pbrSpecularGlossiness/examples/convert-between-workflows-bjs/js/babylon.pbrUtilities.js
+             * @param diffuseTexture - texture used to store diffuse information.
+             * @param specularGlossinessTexture - texture used to store specular and glossiness information.
+             * @param factors - specular glossiness material factors.
+             * @param mimeType - the mime type to use for the texture.
+             * @returns pbr metallic roughness interface or null.
+             */
+            _GLTFMaterial._ConvertSpecularGlossinessTexturesToMetallicRoughness = function (diffuseTexture, specularGlossinessTexture, factors, mimeType) {
+                if (!(diffuseTexture || specularGlossinessTexture)) {
+                    return null;
+                }
+                var scene = diffuseTexture ? diffuseTexture.getScene() : specularGlossinessTexture.getScene();
+                if (!scene) {
+                    throw new Error("_ConvertSpecularGlossinessTexturesToMetallicRoughness: Scene from textures is missing!");
+                }
+                var resizedTextures = this._ResizeTexturesToSameDimensions(diffuseTexture, specularGlossinessTexture, scene);
+                var diffuseSize = resizedTextures.texture1.getSize();
+                var diffuseBuffer;
+                var specularGlossinessBuffer;
+                var width = diffuseSize.width;
+                var height = diffuseSize.height;
+                var pixels = (resizedTextures.texture1.readPixels());
+                if (pixels instanceof Uint8Array) {
+                    diffuseBuffer = (resizedTextures.texture1.readPixels());
+                }
+                else {
+                    throw new Error("_ConvertSpecularGlossinessTexturesToMetallicRoughness: Pixel array buffer type not supported for texture: " + resizedTextures.texture1.name);
+                }
+                pixels = resizedTextures.texture2.readPixels();
+                if (pixels instanceof Uint8Array) {
+                    specularGlossinessBuffer = (resizedTextures.texture2.readPixels());
+                }
+                else {
+                    throw new Error("_ConvertSpecularGlossinessTexturesToMetallicRoughness: Pixel array buffer type not supported for texture: " + resizedTextures.texture2.name);
+                }
+                var byteLength = specularGlossinessBuffer.byteLength;
+                var metallicRoughnessBuffer = new Uint8Array(byteLength);
+                var baseColorBuffer = new Uint8Array(byteLength);
+                var strideSize = 4;
+                var maxBaseColor = BABYLON.Color3.Black();
+                var maxMetallic = 0;
+                var maxRoughness = 0;
+                for (var h = 0; h < height; ++h) {
+                    for (var w = 0; w < width; ++w) {
+                        var offset = (width * h + w) * strideSize;
+                        var diffuseColor = BABYLON.Color3.FromInts(diffuseBuffer[offset], diffuseBuffer[offset + 1], diffuseBuffer[offset + 2]).multiply(factors.diffuseColor);
+                        var specularColor = BABYLON.Color3.FromInts(specularGlossinessBuffer[offset], specularGlossinessBuffer[offset + 1], specularGlossinessBuffer[offset + 2]).multiply(factors.specularColor);
+                        var glossiness = (specularGlossinessBuffer[offset + 3] / 255) * factors.glossiness;
+                        var specularGlossiness = {
+                            diffuseColor: diffuseColor,
+                            specularColor: specularColor,
+                            glossiness: glossiness
+                        };
+                        var metallicRoughness = this._ConvertSpecularGlossinessToMetallicRoughness(specularGlossiness);
+                        maxBaseColor.r = Math.max(maxBaseColor.r, metallicRoughness.baseColor.r);
+                        maxBaseColor.g = Math.max(maxBaseColor.g, metallicRoughness.baseColor.g);
+                        maxBaseColor.b = Math.max(maxBaseColor.b, metallicRoughness.baseColor.b);
+                        maxMetallic = Math.max(maxMetallic, metallicRoughness.metallic);
+                        maxRoughness = Math.max(maxRoughness, metallicRoughness.roughness);
+                        baseColorBuffer[offset] = metallicRoughness.baseColor.r * 255;
+                        baseColorBuffer[offset + 1] = metallicRoughness.baseColor.g * 255;
+                        baseColorBuffer[offset + 2] = metallicRoughness.baseColor.b * 255;
+                        baseColorBuffer[offset + 3] = resizedTextures.texture1.hasAlpha ? diffuseBuffer[offset + 3] : 255;
+                        metallicRoughnessBuffer[offset] = 255;
+                        metallicRoughnessBuffer[offset + 1] = metallicRoughness.roughness * 255;
+                        metallicRoughnessBuffer[offset + 2] = metallicRoughness.metallic * 255;
+                        metallicRoughnessBuffer[offset + 3] = 255;
+                    }
+                }
+                // Retrieves the metallic roughness factors from the maximum texture values.
+                var metallicRoughnessFactors = {
+                    baseColor: maxBaseColor,
+                    metallic: maxMetallic,
+                    roughness: maxRoughness
+                };
+                var writeOutMetallicRoughnessTexture = false;
+                var writeOutBaseColorTexture = false;
+                for (var h = 0; h < height; ++h) {
+                    for (var w = 0; w < width; ++w) {
+                        var destinationOffset = (width * h + w) * strideSize;
+                        baseColorBuffer[destinationOffset] /= metallicRoughnessFactors.baseColor.r > this._epsilon ? metallicRoughnessFactors.baseColor.r : 1;
+                        baseColorBuffer[destinationOffset + 1] /= metallicRoughnessFactors.baseColor.g > this._epsilon ? metallicRoughnessFactors.baseColor.g : 1;
+                        baseColorBuffer[destinationOffset + 2] /= metallicRoughnessFactors.baseColor.b > this._epsilon ? metallicRoughnessFactors.baseColor.b : 1;
+                        var baseColorPixel = new BABYLON.Color3(baseColorBuffer[destinationOffset], baseColorBuffer[destinationOffset + 1], baseColorBuffer[destinationOffset + 2]);
+                        if (!this.FuzzyEquals(baseColorPixel, BABYLON.Color3.White(), this._epsilon)) {
+                            writeOutBaseColorTexture = true;
+                        }
+                        metallicRoughnessBuffer[destinationOffset + 1] /= metallicRoughnessFactors.roughness > this._epsilon ? metallicRoughnessFactors.roughness : 1;
+                        metallicRoughnessBuffer[destinationOffset + 2] /= metallicRoughnessFactors.metallic > this._epsilon ? metallicRoughnessFactors.metallic : 1;
+                        var metallicRoughnessPixel = new BABYLON.Color3(metallicRoughnessBuffer[destinationOffset], metallicRoughnessBuffer[destinationOffset + 1], metallicRoughnessBuffer[destinationOffset + 2]);
+                        if (!this.FuzzyEquals(metallicRoughnessPixel, BABYLON.Color3.White(), this._epsilon)) {
+                            writeOutMetallicRoughnessTexture = true;
+                        }
+                    }
+                }
+                if (writeOutMetallicRoughnessTexture) {
+                    var metallicRoughnessBase64 = this._CreateBase64FromCanvas(metallicRoughnessBuffer, width, height, mimeType);
+                    metallicRoughnessFactors.metallicRoughnessTextureBase64 = metallicRoughnessBase64;
+                }
+                if (writeOutBaseColorTexture) {
+                    var baseColorBase64 = this._CreateBase64FromCanvas(baseColorBuffer, width, height, mimeType);
+                    metallicRoughnessFactors.baseColorTextureBase64 = baseColorBase64;
+                }
+                return metallicRoughnessFactors;
+            };
+            /**
+             * Converts specular glossiness material properties to metallic roughness.
+             * @param specularGlossiness - interface with specular glossiness material properties.
+             * @returns - interface with metallic roughness material properties.
+             */
+            _GLTFMaterial._ConvertSpecularGlossinessToMetallicRoughness = function (specularGlossiness) {
+                var diffusePerceivedBrightness = _GLTFMaterial._GetPerceivedBrightness(specularGlossiness.diffuseColor);
+                var specularPerceivedBrightness = _GLTFMaterial._GetPerceivedBrightness(specularGlossiness.specularColor);
+                var oneMinusSpecularStrength = 1 - _GLTFMaterial._GetMaxComponent(specularGlossiness.specularColor);
+                var metallic = _GLTFMaterial._SolveMetallic(diffusePerceivedBrightness, specularPerceivedBrightness, oneMinusSpecularStrength);
+                var baseColorFromDiffuse = specularGlossiness.diffuseColor.scale(oneMinusSpecularStrength / (1.0 - this._dielectricSpecular.r) / Math.max(1 - metallic, this._epsilon));
+                var baseColorFromSpecular = specularGlossiness.specularColor.subtract(this._dielectricSpecular.scale(1 - metallic)).scale(1 / Math.max(metallic, this._epsilon));
+                var baseColor = BABYLON.Color3.Lerp(baseColorFromDiffuse, baseColorFromSpecular, metallic * metallic);
+                baseColor = baseColor.clampToRef(0, 1, baseColor);
+                var metallicRoughness = {
+                    baseColor: baseColor,
+                    metallic: metallic,
+                    roughness: 1 - specularGlossiness.glossiness
+                };
+                return metallicRoughness;
+            };
+            /**
+             * Calculates the surface reflectance, independent of lighting conditions.
              * @param color - Color source to calculate brightness from.
              * @returns number representing the perceived brightness, or zero if color is undefined.
              */
-            _GLTFMaterial.GetPerceivedBrightness = function (color) {
+            _GLTFMaterial._GetPerceivedBrightness = function (color) {
                 if (color) {
                     return Math.sqrt(0.299 * color.r * color.r + 0.587 * color.g * color.g + 0.114 * color.b * color.b);
                 }
@@ -1156,7 +1368,7 @@ var BABYLON;
              * @param color
              * @returns maximum color component value, or zero if color is null or undefined.
              */
-            _GLTFMaterial.GetMaxComponent = function (color) {
+            _GLTFMaterial._GetMaxComponent = function (color) {
                 if (color) {
                     return Math.max(color.r, Math.max(color.g, color.b));
                 }
@@ -1172,110 +1384,117 @@ var BABYLON;
              * @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.
              */
-            _GLTFMaterial.ConvertPBRMaterial = function (babylonPBRMaterial, mimeType, images, textures, materials, imageData, hasTextureCoords) {
+            _GLTFMaterial._ConvertPBRMaterial = function (babylonPBRMaterial, mimeType, images, textures, materials, imageData, hasTextureCoords) {
                 var glTFPbrMetallicRoughness = {};
+                var metallicRoughness;
                 var glTFMaterial = {
                     name: babylonPBRMaterial.name
                 };
                 var useMetallicRoughness = babylonPBRMaterial.isMetallicWorkflow();
-                if (babylonPBRMaterial) {
-                    if (useMetallicRoughness) {
-                        glTFPbrMetallicRoughness.baseColorFactor = [
-                            babylonPBRMaterial.albedoColor.r,
-                            babylonPBRMaterial.albedoColor.g,
-                            babylonPBRMaterial.albedoColor.b,
-                            babylonPBRMaterial.alpha
-                        ];
-                        if (babylonPBRMaterial.metallic != null) {
-                            if (babylonPBRMaterial.metallic !== 1) {
-                                glTFPbrMetallicRoughness.metallicFactor = babylonPBRMaterial.metallic;
+                if (!useMetallicRoughness) {
+                    var specGloss = {
+                        diffuseColor: babylonPBRMaterial.albedoColor || BABYLON.Color3.White(),
+                        specularColor: babylonPBRMaterial.reflectivityColor || BABYLON.Color3.White(),
+                        glossiness: babylonPBRMaterial.microSurface || 1,
+                    };
+                    if (babylonPBRMaterial.reflectivityTexture && !babylonPBRMaterial.useMicroSurfaceFromReflectivityMapAlpha) {
+                        throw new Error("_ConvertPBRMaterial: Glossiness values not included in the reflectivity texture currently not supported");
+                    }
+                    metallicRoughness = this._ConvertSpecularGlossinessTexturesToMetallicRoughness(babylonPBRMaterial.albedoTexture, babylonPBRMaterial.reflectivityTexture, specGloss, mimeType);
+                    if (!metallicRoughness) {
+                        metallicRoughness = this._ConvertSpecularGlossinessToMetallicRoughness(specGloss);
+                    }
+                    else {
+                        if (hasTextureCoords) {
+                            if (metallicRoughness.baseColorTextureBase64) {
+                                var glTFBaseColorTexture = _GLTFMaterial._GetTextureInfoFromBase64(metallicRoughness.baseColorTextureBase64, "bjsBaseColorTexture_" + (textures.length) + ".png", mimeType, images, textures, imageData);
+                                if (glTFBaseColorTexture != null) {
+                                    glTFPbrMetallicRoughness.baseColorTexture = glTFBaseColorTexture;
+                                }
                             }
-                        }
-                        if (babylonPBRMaterial.roughness != null) {
-                            if (babylonPBRMaterial.roughness !== 1) {
-                                glTFPbrMetallicRoughness.roughnessFactor = babylonPBRMaterial.roughness;
+                            if (metallicRoughness.metallicRoughnessTextureBase64) {
+                                var glTFMRColorTexture = _GLTFMaterial._GetTextureInfoFromBase64(metallicRoughness.metallicRoughnessTextureBase64, "bjsMetallicRoughnessTexture_" + (textures.length) + ".png", mimeType, images, textures, imageData);
+                                if (glTFMRColorTexture != null) {
+                                    glTFPbrMetallicRoughness.metallicRoughnessTexture = glTFMRColorTexture;
+                                }
                             }
                         }
                     }
-                    else {
-                        var diffuseColor = babylonPBRMaterial.albedoColor || BABYLON.Color3.Black();
-                        var specularColor = babylonPBRMaterial.reflectionColor || BABYLON.Color3.Black();
-                        var diffusePerceivedBrightness = _GLTFMaterial.GetPerceivedBrightness(diffuseColor);
-                        var specularPerceivedBrightness = _GLTFMaterial.GetPerceivedBrightness(specularColor);
-                        var oneMinusSpecularStrength = 1 - _GLTFMaterial.GetMaxComponent(babylonPBRMaterial.reflectionColor);
-                        var metallic = _GLTFMaterial.SolveMetallic(diffusePerceivedBrightness, specularPerceivedBrightness, oneMinusSpecularStrength);
-                        var glossiness = babylonPBRMaterial.microSurface || 0;
-                        var baseColorFromDiffuse = diffuseColor.scale(oneMinusSpecularStrength / (1.0 - this.dielectricSpecular.r) / Math.max(1 - metallic, this.epsilon));
-                        var baseColorFromSpecular = specularColor.subtract(this.dielectricSpecular.scale(1 - metallic)).scale(1 / Math.max(metallic, this.epsilon));
-                        var baseColor = BABYLON.Color3.Lerp(baseColorFromDiffuse, baseColorFromSpecular, metallic * metallic);
-                        baseColor = baseColor.clampToRef(0, 1, baseColor);
-                        glTFPbrMetallicRoughness.baseColorFactor = [
-                            baseColor.r,
-                            baseColor.g,
-                            baseColor.b,
-                            babylonPBRMaterial.alpha
-                        ];
-                        if (metallic !== 1) {
-                            glTFPbrMetallicRoughness.metallicFactor = metallic;
-                        }
-                        if (glossiness) {
-                            glTFPbrMetallicRoughness.roughnessFactor = 1 - glossiness;
-                        }
+                }
+                else {
+                    metallicRoughness = {
+                        baseColor: babylonPBRMaterial.albedoColor,
+                        metallic: babylonPBRMaterial.metallic,
+                        roughness: babylonPBRMaterial.roughness
+                    };
+                }
+                if (!(this.FuzzyEquals(metallicRoughness.baseColor, BABYLON.Color3.White(), this._epsilon) && babylonPBRMaterial.alpha >= this._epsilon)) {
+                    glTFPbrMetallicRoughness.baseColorFactor = [
+                        metallicRoughness.baseColor.r,
+                        metallicRoughness.baseColor.g,
+                        metallicRoughness.baseColor.b,
+                        babylonPBRMaterial.alpha
+                    ];
+                }
+                if (metallicRoughness.metallic != null && metallicRoughness.metallic !== 1) {
+                    glTFPbrMetallicRoughness.metallicFactor = metallicRoughness.metallic;
+                }
+                if (metallicRoughness.roughness != null && metallicRoughness.roughness !== 1) {
+                    glTFPbrMetallicRoughness.roughnessFactor = metallicRoughness.roughness;
+                }
+                if (babylonPBRMaterial.backFaceCulling != null && !babylonPBRMaterial.backFaceCulling) {
+                    if (!babylonPBRMaterial.twoSidedLighting) {
+                        BABYLON.Tools.Warn(babylonPBRMaterial.name + ": Back-face culling enabled and two-sided lighting disabled is not supported in glTF.");
                     }
-                    if (babylonPBRMaterial.backFaceCulling) {
-                        if (!babylonPBRMaterial.twoSidedLighting) {
-                            BABYLON.Tools.Warn(babylonPBRMaterial.name + ": Back-face culling enabled and two-sided lighting disabled is not supported in glTF.");
+                    glTFMaterial.doubleSided = true;
+                }
+                if (hasTextureCoords) {
+                    if (useMetallicRoughness && babylonPBRMaterial.albedoTexture) {
+                        var glTFTexture = _GLTFMaterial._ExportTexture(babylonPBRMaterial.albedoTexture, mimeType, images, textures, imageData);
+                        if (glTFTexture) {
+                            glTFPbrMetallicRoughness.baseColorTexture = glTFTexture;
                         }
-                        glTFMaterial.doubleSided = true;
                     }
-                    if (hasTextureCoords) {
-                        if (babylonPBRMaterial.albedoTexture) {
-                            var glTFTexture = _GLTFMaterial.ExportTexture(babylonPBRMaterial.albedoTexture, mimeType, images, textures, imageData);
-                            if (glTFTexture) {
-                                glTFPbrMetallicRoughness.baseColorTexture = glTFTexture;
-                            }
-                        }
-                        if (babylonPBRMaterial.bumpTexture) {
-                            var glTFTexture = _GLTFMaterial.ExportTexture(babylonPBRMaterial.bumpTexture, mimeType, images, textures, imageData);
-                            if (glTFTexture) {
-                                glTFMaterial.normalTexture = glTFTexture;
-                            }
-                        }
-                        if (babylonPBRMaterial.ambientTexture) {
-                            var glTFTexture = _GLTFMaterial.ExportTexture(babylonPBRMaterial.ambientTexture, mimeType, images, textures, imageData);
-                            if (glTFTexture) {
-                                var occlusionTexture = {
-                                    index: glTFTexture.index
-                                };
-                                glTFMaterial.occlusionTexture = occlusionTexture;
-                                if (babylonPBRMaterial.ambientTextureStrength) {
-                                    occlusionTexture.strength = babylonPBRMaterial.ambientTextureStrength;
-                                }
-                            }
+                    if (babylonPBRMaterial.bumpTexture) {
+                        var glTFTexture = _GLTFMaterial._ExportTexture(babylonPBRMaterial.bumpTexture, mimeType, images, textures, imageData);
+                        if (glTFTexture) {
+                            glTFMaterial.normalTexture = glTFTexture;
                         }
-                        if (babylonPBRMaterial.emissiveTexture) {
-                            var glTFTexture = _GLTFMaterial.ExportTexture(babylonPBRMaterial.emissiveTexture, mimeType, images, textures, imageData);
-                            if (glTFTexture != null) {
-                                glTFMaterial.emissiveTexture = glTFTexture;
+                    }
+                    if (babylonPBRMaterial.ambientTexture) {
+                        var glTFTexture = _GLTFMaterial._ExportTexture(babylonPBRMaterial.ambientTexture, mimeType, images, textures, imageData);
+                        if (glTFTexture) {
+                            var occlusionTexture = {
+                                index: glTFTexture.index
+                            };
+                            glTFMaterial.occlusionTexture = occlusionTexture;
+                            if (babylonPBRMaterial.ambientTextureStrength) {
+                                occlusionTexture.strength = babylonPBRMaterial.ambientTextureStrength;
                             }
                         }
-                        if (babylonPBRMaterial.metallicTexture) {
-                            var glTFTexture = _GLTFMaterial.ExportTexture(babylonPBRMaterial.metallicTexture, mimeType, images, textures, imageData);
-                            if (glTFTexture != null) {
-                                glTFPbrMetallicRoughness.metallicRoughnessTexture = glTFTexture;
-                            }
+                    }
+                    if (babylonPBRMaterial.emissiveTexture) {
+                        var glTFTexture = _GLTFMaterial._ExportTexture(babylonPBRMaterial.emissiveTexture, mimeType, images, textures, imageData);
+                        if (glTFTexture != null) {
+                            glTFMaterial.emissiveTexture = glTFTexture;
                         }
                     }
-                    if (!babylonPBRMaterial.emissiveColor.equalsFloats(0.0, 0.0, 0.0)) {
-                        glTFMaterial.emissiveFactor = babylonPBRMaterial.emissiveColor.asArray();
+                    if (babylonPBRMaterial.metallicTexture) {
+                        var glTFTexture = _GLTFMaterial._ExportTexture(babylonPBRMaterial.metallicTexture, mimeType, images, textures, imageData);
+                        if (glTFTexture != null) {
+                            glTFPbrMetallicRoughness.metallicRoughnessTexture = glTFTexture;
+                        }
                     }
-                    if (babylonPBRMaterial.transparencyMode != null) {
-                        var alphaMode = _GLTFMaterial.GetAlphaMode(babylonPBRMaterial);
-                        if (alphaMode !== "OPAQUE" /* OPAQUE */) {
-                            glTFMaterial.alphaMode = alphaMode;
-                            if (alphaMode === "BLEND" /* BLEND */) {
-                                glTFMaterial.alphaCutoff = babylonPBRMaterial.alphaCutOff;
-                            }
+                }
+                if (!this.FuzzyEquals(babylonPBRMaterial.emissiveColor, BABYLON.Color3.Black(), this._epsilon)) {
+                    glTFMaterial.emissiveFactor = babylonPBRMaterial.emissiveColor.asArray();
+                }
+                if (babylonPBRMaterial.transparencyMode != null) {
+                    var alphaMode = _GLTFMaterial._GetAlphaMode(babylonPBRMaterial);
+                    if (alphaMode !== "OPAQUE" /* OPAQUE */) {
+                        glTFMaterial.alphaMode = alphaMode;
+                        if (alphaMode === "BLEND" /* BLEND */) {
+                            glTFMaterial.alphaCutoff = babylonPBRMaterial.alphaCutOff;
                         }
                     }
                 }
@@ -1289,17 +1508,13 @@ var BABYLON;
              * @param images - Array of glTF images.
              * @param textures - Array of glTF textures.
              * @param imageData - map of image file name and data.
-             * @return - glTF texture, or null if the texture format is not supported.
+             * @return - glTF texture info, or null if the texture format is not supported.
              */
-            _GLTFMaterial.ExportTexture = function (babylonTexture, mimeType, images, textures, imageData) {
-                var textureInfo = null;
-                var glTFTexture = {
-                    source: images.length
-                };
+            _GLTFMaterial._ExportTexture = function (babylonTexture, mimeType, images, textures, imageData) {
                 var textureName = "texture_" + (textures.length - 1).toString();
                 var textureData = babylonTexture.getInternalTexture();
                 if (textureData != null) {
-                    textureName = textureData.url;
+                    textureName = textureData.url || textureName;
                 }
                 textureName = BABYLON.Tools.GetFilename(textureName);
                 var baseFile = textureName.split('.')[0];
@@ -1311,28 +1526,37 @@ var BABYLON;
                     extension = ".png";
                 }
                 else {
-                    BABYLON.Tools.Error("Unsupported mime type " + mimeType);
+                    throw new Error("Unsupported mime type " + mimeType);
                 }
                 textureName = baseFile + extension;
                 var pixels = babylonTexture.readPixels();
-                var imageCanvas = document.createElement('canvas');
-                imageCanvas.id = "ImageCanvas";
-                var ctx = imageCanvas.getContext('2d');
                 var size = babylonTexture.getSize();
-                imageCanvas.width = size.width;
-                imageCanvas.height = size.height;
-                var imgData = ctx.createImageData(size.width, size.height);
-                imgData.data.set(pixels);
-                ctx.putImageData(imgData, 0, 0);
-                var base64Data = imageCanvas.toDataURL(mimeType);
-                var binStr = atob(base64Data.split(',')[1]);
+                var base64Data = this._CreateBase64FromCanvas(pixels, size.width, size.height, mimeType);
+                return this._GetTextureInfoFromBase64(base64Data, textureName, mimeType, images, textures, imageData);
+            };
+            /**
+             * Builds a texture from base64 string.
+             * @param base64Texture - base64 texture string.
+             * @param textureName - Name to use for the texture.
+             * @param mimeType - image mime type for the texture.
+             * @param images - array of images.
+             * @param textures - array of textures.
+             * @param imageData - map of image data.
+             * @returns - glTF texture info, or null if the texture format is not supported.
+             */
+            _GLTFMaterial._GetTextureInfoFromBase64 = function (base64Texture, textureName, mimeType, images, textures, imageData) {
+                var textureInfo = null;
+                var glTFTexture = {
+                    source: images.length
+                };
+                var binStr = atob(base64Texture.split(',')[1]);
                 var arr = new Uint8Array(binStr.length);
                 for (var i = 0; i < binStr.length; ++i) {
                     arr[i] = binStr.charCodeAt(i);
                 }
                 var imageValues = { data: arr, mimeType: mimeType };
                 imageData[textureName] = imageValues;
-                if (mimeType === "image/jpeg" /* JPEG */) {
+                if (mimeType === "image/jpeg" /* JPEG */ || mimeType === "image/png" /* PNG */) {
                     var glTFImage = {
                         uri: textureName
                     };
@@ -1365,12 +1589,15 @@ var BABYLON;
             /**
              * Represents the dielectric specular values for R, G and B.
              */
-            _GLTFMaterial.dielectricSpecular = new BABYLON.Color3(0.04, 0.04, 0.04);
+            _GLTFMaterial._dielectricSpecular = new BABYLON.Color3(0.04, 0.04, 0.04);
             /**
              * Allows the maximum specular power to be defined for material calculations.
              */
-            _GLTFMaterial.maxSpecularPower = 1024;
-            _GLTFMaterial.epsilon = 1e-6;
+            _GLTFMaterial._maxSpecularPower = 1024;
+            /**
+             * Numeric tolerance value
+             */
+            _GLTFMaterial._epsilon = 1e-6;
             return _GLTFMaterial;
         }());
         GLTF2._GLTFMaterial = _GLTFMaterial;

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 1 - 1
dist/preview release/serializers/babylon.glTF2Serializer.min.js


+ 385 - 158
dist/preview release/serializers/babylonjs.serializers.js

@@ -767,13 +767,13 @@ var BABYLON;
                                 else {
                                     BABYLON.Tools.Warn("Material type " + bufferMesh.material.getClassName() + " for material " + bufferMesh.material.name + " is not yet implemented in glTF serializer.");
                                 }
-                                if (materialIndex != null) {
-                                    if (uvCoordsPresent || !GLTF2._GLTFMaterial.HasTexturesPresent(this.materials[materialIndex])) {
+                                if (materialIndex != null && Object.keys(meshPrimitive.attributes).length > 0) {
+                                    if (uvCoordsPresent || !GLTF2._GLTFMaterial._HasTexturesPresent(this.materials[materialIndex])) {
                                         meshPrimitive.material = materialIndex;
                                     }
                                     else {
                                         // If no texture coordinate information is present, make a copy of the material without the textures to be glTF compliant.
-                                        var newMat = GLTF2._GLTFMaterial.StripTexturesFromMaterial(this.materials[materialIndex]);
+                                        var newMat = GLTF2._GLTFMaterial._StripTexturesFromMaterial(this.materials[materialIndex]);
                                         this.materials.push(newMat);
                                         meshPrimitive.material = this.materials.length - 1;
                                     }
@@ -796,7 +796,7 @@ var BABYLON;
                 if (babylonScene.meshes.length) {
                     var babylonMeshes = babylonScene.meshes;
                     var scene = { nodes: new Array() };
-                    GLTF2._GLTFMaterial.ConvertMaterialsToGLTF(babylonScene.materials, "image/jpeg" /* JPEG */, this.images, this.textures, this.materials, this.imageData, true);
+                    GLTF2._GLTFMaterial._ConvertMaterialsToGLTF(babylonScene.materials, "image/png" /* PNG */, this.images, this.textures, this.materials, this.imageData, true);
                     var result = this.createNodeMap(babylonScene, byteOffset);
                     this.nodeMap = result.nodeMap;
                     this.totalByteLength = result.byteOffset;
@@ -953,29 +953,40 @@ var BABYLON;
             function _GLTFMaterial() {
             }
             /**
+             * Specifies if two colors are approximately equal in value.
+             * @param color1 - first color to compare to.
+             * @param color2 - second color to compare to.
+             * @param epsilon - threshold value
+             */
+            _GLTFMaterial.FuzzyEquals = function (color1, color2, epsilon) {
+                return BABYLON.Scalar.WithinEpsilon(color1.r, color2.r, epsilon) &&
+                    BABYLON.Scalar.WithinEpsilon(color1.g, color2.g, epsilon) &&
+                    BABYLON.Scalar.WithinEpsilon(color1.b, color2.b, epsilon);
+            };
+            /**
              * Gets the materials from a Babylon scene and converts them to glTF materials.
-             * @param scene
-             * @param mimeType
-             * @param images
-             * @param textures
-             * @param materials
-             * @param imageData
-             * @param hasTextureCoords
+             * @param scene - babylonjs scene.
+             * @param mimeType - texture mime type.
+             * @param images - array of images.
+             * @param textures - array of textures.
+             * @param materials - array of materials.
+             * @param imageData - mapping of texture names to base64 textures
+             * @param hasTextureCoords - specifies if texture coordinates are present on the material.
              */
-            _GLTFMaterial.ConvertMaterialsToGLTF = function (babylonMaterials, mimeType, images, textures, materials, imageData, hasTextureCoords) {
+            _GLTFMaterial._ConvertMaterialsToGLTF = function (babylonMaterials, mimeType, images, textures, materials, imageData, hasTextureCoords) {
                 for (var i = 0; i < babylonMaterials.length; ++i) {
                     var babylonMaterial = babylonMaterials[i];
                     if (babylonMaterial instanceof BABYLON.StandardMaterial) {
-                        _GLTFMaterial.ConvertStandardMaterial(babylonMaterial, mimeType, images, textures, materials, imageData, hasTextureCoords);
+                        _GLTFMaterial._ConvertStandardMaterial(babylonMaterial, mimeType, images, textures, materials, imageData, hasTextureCoords);
                     }
                     else if (babylonMaterial instanceof BABYLON.PBRMetallicRoughnessMaterial) {
-                        _GLTFMaterial.ConvertPBRMetallicRoughnessMaterial(babylonMaterial, mimeType, images, textures, materials, imageData, hasTextureCoords);
+                        _GLTFMaterial._ConvertPBRMetallicRoughnessMaterial(babylonMaterial, mimeType, images, textures, materials, imageData, hasTextureCoords);
                     }
                     else if (babylonMaterial instanceof BABYLON.PBRMaterial) {
-                        _GLTFMaterial.ConvertPBRMaterial(babylonMaterial, mimeType, images, textures, materials, imageData, hasTextureCoords);
+                        _GLTFMaterial._ConvertPBRMaterial(babylonMaterial, mimeType, images, textures, materials, imageData, hasTextureCoords);
                     }
                     else {
-                        BABYLON.Tools.Error("Unsupported material type: " + babylonMaterial.name);
+                        throw new Error("Unsupported material type: " + babylonMaterial.name);
                     }
                 }
             };
@@ -984,7 +995,7 @@ var BABYLON;
              * @param originalMaterial - original glTF material.
              * @returns glTF material without texture parameters
              */
-            _GLTFMaterial.StripTexturesFromMaterial = function (originalMaterial) {
+            _GLTFMaterial._StripTexturesFromMaterial = function (originalMaterial) {
                 var newMaterial = {};
                 if (originalMaterial) {
                     newMaterial.name = originalMaterial.name;
@@ -1007,7 +1018,7 @@ var BABYLON;
              * @param material - glTF Material.
              * @returns boolean specifying if texture parameters are present
              */
-            _GLTFMaterial.HasTexturesPresent = function (material) {
+            _GLTFMaterial._HasTexturesPresent = function (material) {
                 if (material.emissiveTexture || material.normalTexture || material.occlusionTexture) {
                     return true;
                 }
@@ -1024,7 +1035,7 @@ var BABYLON;
              * @param babylonStandardMaterial
              * @returns - glTF Metallic Roughness Material representation
              */
-            _GLTFMaterial.ConvertToGLTFPBRMetallicRoughness = function (babylonStandardMaterial) {
+            _GLTFMaterial._ConvertToGLTFPBRMetallicRoughness = function (babylonStandardMaterial) {
                 var P0 = new BABYLON.Vector2(0, 1);
                 var P1 = new BABYLON.Vector2(0, 0.1);
                 var P2 = new BABYLON.Vector2(0, 0.1);
@@ -1038,7 +1049,7 @@ var BABYLON;
                  * @param p3 - fourth control point.
                  * @returns - number result of cubic bezier curve at the specified t.
                  */
-                function cubicBezierCurve(t, p0, p1, p2, p3) {
+                function _cubicBezierCurve(t, p0, p1, p2, p3) {
                     return ((1 - t) * (1 - t) * (1 - t) * p0 +
                         3 * (1 - t) * (1 - t) * t * p1 +
                         3 * (1 - t) * t * t * p2 +
@@ -1051,14 +1062,14 @@ var BABYLON;
                  * @param specularPower - specular power of standard material.
                  * @returns - Number representing the roughness value.
                  */
-                function solveForRoughness(specularPower) {
+                function _solveForRoughness(specularPower) {
                     var t = Math.pow(specularPower / P3.x, 0.333333);
-                    return cubicBezierCurve(t, P0.y, P1.y, P2.y, P3.y);
+                    return _cubicBezierCurve(t, P0.y, P1.y, P2.y, P3.y);
                 }
                 var diffuse = babylonStandardMaterial.diffuseColor.toLinearSpace().scale(0.5);
                 var opacity = babylonStandardMaterial.alpha;
-                var specularPower = BABYLON.Scalar.Clamp(babylonStandardMaterial.specularPower, 0, this.maxSpecularPower);
-                var roughness = solveForRoughness(specularPower);
+                var specularPower = BABYLON.Scalar.Clamp(babylonStandardMaterial.specularPower, 0, this._maxSpecularPower);
+                var roughness = _solveForRoughness(specularPower);
                 var glTFPbrMetallicRoughness = {
                     baseColorFactor: [
                         diffuse.r,
@@ -1078,14 +1089,14 @@ var BABYLON;
              * @param oneMinusSpecularStrength - one minus the specular strength
              * @returns - metallic value
              */
-            _GLTFMaterial.SolveMetallic = function (diffuse, specular, oneMinusSpecularStrength) {
-                if (specular < _GLTFMaterial.dielectricSpecular.r) {
-                    _GLTFMaterial.dielectricSpecular;
+            _GLTFMaterial._SolveMetallic = function (diffuse, specular, oneMinusSpecularStrength) {
+                if (specular < _GLTFMaterial._dielectricSpecular.r) {
+                    _GLTFMaterial._dielectricSpecular;
                     return 0;
                 }
-                var a = _GLTFMaterial.dielectricSpecular.r;
-                var b = diffuse * oneMinusSpecularStrength / (1.0 - _GLTFMaterial.dielectricSpecular.r) + specular - 2.0 * _GLTFMaterial.dielectricSpecular.r;
-                var c = _GLTFMaterial.dielectricSpecular.r - specular;
+                var a = _GLTFMaterial._dielectricSpecular.r;
+                var b = diffuse * oneMinusSpecularStrength / (1.0 - _GLTFMaterial._dielectricSpecular.r) + specular - 2.0 * _GLTFMaterial._dielectricSpecular.r;
+                var c = _GLTFMaterial._dielectricSpecular.r - specular;
                 var D = b * b - 4.0 * a * c;
                 return BABYLON.Scalar.Clamp((-b + Math.sqrt(D)) / (2.0 * a), 0, 1);
             };
@@ -1094,7 +1105,7 @@ var BABYLON;
              * @param babylonMaterial - Babylon Material
              * @returns - The Babylon alpha mode value
              */
-            _GLTFMaterial.GetAlphaMode = function (babylonMaterial) {
+            _GLTFMaterial._GetAlphaMode = function (babylonMaterial) {
                 if (babylonMaterial instanceof BABYLON.StandardMaterial) {
                     var babylonStandardMaterial = babylonMaterial;
                     if ((babylonStandardMaterial.alpha != 1.0) ||
@@ -1162,11 +1173,11 @@ var BABYLON;
              * @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.
              */
-            _GLTFMaterial.ConvertStandardMaterial = function (babylonStandardMaterial, mimeType, images, textures, materials, imageData, hasTextureCoords) {
+            _GLTFMaterial._ConvertStandardMaterial = function (babylonStandardMaterial, mimeType, images, textures, materials, imageData, hasTextureCoords) {
                 BABYLON.Tools.Warn(babylonStandardMaterial.name + ": Standard Material is currently not fully supported/implemented in glTF serializer");
-                var glTFPbrMetallicRoughness = _GLTFMaterial.ConvertToGLTFPBRMetallicRoughness(babylonStandardMaterial);
+                var glTFPbrMetallicRoughness = _GLTFMaterial._ConvertToGLTFPBRMetallicRoughness(babylonStandardMaterial);
                 var glTFMaterial = { name: babylonStandardMaterial.name };
-                if (babylonStandardMaterial.backFaceCulling) {
+                if (babylonStandardMaterial.backFaceCulling != null && !babylonStandardMaterial.backFaceCulling) {
                     if (!babylonStandardMaterial.twoSidedLighting) {
                         BABYLON.Tools.Warn(babylonStandardMaterial.name + ": Back-face culling enabled and two-sided lighting disabled is not supported in glTF.");
                     }
@@ -1174,26 +1185,26 @@ var BABYLON;
                 }
                 if (hasTextureCoords) {
                     if (babylonStandardMaterial.diffuseTexture) {
-                        var glTFTexture = _GLTFMaterial.ExportTexture(babylonStandardMaterial.diffuseTexture, mimeType, images, textures, imageData);
+                        var glTFTexture = _GLTFMaterial._ExportTexture(babylonStandardMaterial.diffuseTexture, mimeType, images, textures, imageData);
                         if (glTFTexture != null) {
                             glTFPbrMetallicRoughness.baseColorTexture = glTFTexture;
                         }
                     }
                     if (babylonStandardMaterial.bumpTexture) {
-                        var glTFTexture = _GLTFMaterial.ExportTexture(babylonStandardMaterial.bumpTexture, mimeType, images, textures, imageData);
+                        var glTFTexture = _GLTFMaterial._ExportTexture(babylonStandardMaterial.bumpTexture, mimeType, images, textures, imageData);
                         if (glTFTexture) {
                             glTFMaterial.normalTexture = glTFTexture;
                         }
                     }
                     if (babylonStandardMaterial.emissiveTexture) {
-                        var glTFEmissiveTexture = _GLTFMaterial.ExportTexture(babylonStandardMaterial.emissiveTexture, mimeType, images, textures, imageData);
+                        var glTFEmissiveTexture = _GLTFMaterial._ExportTexture(babylonStandardMaterial.emissiveTexture, mimeType, images, textures, imageData);
                         if (glTFEmissiveTexture) {
                             glTFMaterial.emissiveTexture = glTFEmissiveTexture;
                         }
                         glTFMaterial.emissiveFactor = [1.0, 1.0, 1.0];
                     }
                     if (babylonStandardMaterial.ambientTexture) {
-                        var glTFTexture = _GLTFMaterial.ExportTexture(babylonStandardMaterial.ambientTexture, mimeType, images, textures, imageData);
+                        var glTFTexture = _GLTFMaterial._ExportTexture(babylonStandardMaterial.ambientTexture, mimeType, images, textures, imageData);
                         if (glTFTexture) {
                             var occlusionTexture = {
                                 index: glTFTexture.index
@@ -1211,7 +1222,7 @@ var BABYLON;
                         BABYLON.Tools.Warn(babylonStandardMaterial.name + ": glTF 2.0 does not support alpha mode: " + babylonStandardMaterial.alphaMode.toString());
                     }
                 }
-                if (babylonStandardMaterial.emissiveColor) {
+                if (babylonStandardMaterial.emissiveColor && !this.FuzzyEquals(babylonStandardMaterial.emissiveColor, BABYLON.Color3.Black(), this._epsilon)) {
                     glTFMaterial.emissiveFactor = babylonStandardMaterial.emissiveColor.asArray();
                 }
                 glTFMaterial.pbrMetallicRoughness = glTFPbrMetallicRoughness;
@@ -1227,7 +1238,7 @@ var BABYLON;
              * @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.
              */
-            _GLTFMaterial.ConvertPBRMetallicRoughnessMaterial = function (babylonPBRMetalRoughMaterial, mimeType, images, textures, materials, imageData, hasTextureCoords) {
+            _GLTFMaterial._ConvertPBRMetallicRoughnessMaterial = function (babylonPBRMetalRoughMaterial, mimeType, images, textures, materials, imageData, hasTextureCoords) {
                 var glTFPbrMetallicRoughness = {};
                 if (babylonPBRMetalRoughMaterial.baseColor) {
                     glTFPbrMetallicRoughness.baseColorFactor = [
@@ -1237,10 +1248,10 @@ var BABYLON;
                         babylonPBRMetalRoughMaterial.alpha
                     ];
                 }
-                if (babylonPBRMetalRoughMaterial.metallic != null) {
+                if (babylonPBRMetalRoughMaterial.metallic != null && babylonPBRMetalRoughMaterial.metallic !== 1) {
                     glTFPbrMetallicRoughness.metallicFactor = babylonPBRMetalRoughMaterial.metallic;
                 }
-                if (babylonPBRMetalRoughMaterial.roughness != null) {
+                if (babylonPBRMetalRoughMaterial.roughness != null && babylonPBRMetalRoughMaterial.roughness !== 1) {
                     glTFPbrMetallicRoughness.roughnessFactor = babylonPBRMetalRoughMaterial.roughness;
                 }
                 var glTFMaterial = {
@@ -1251,19 +1262,19 @@ var BABYLON;
                 }
                 if (hasTextureCoords) {
                     if (babylonPBRMetalRoughMaterial.baseTexture != null) {
-                        var glTFTexture = _GLTFMaterial.ExportTexture(babylonPBRMetalRoughMaterial.baseTexture, mimeType, images, textures, imageData);
+                        var glTFTexture = _GLTFMaterial._ExportTexture(babylonPBRMetalRoughMaterial.baseTexture, mimeType, images, textures, imageData);
                         if (glTFTexture != null) {
                             glTFPbrMetallicRoughness.baseColorTexture = glTFTexture;
                         }
                     }
                     if (babylonPBRMetalRoughMaterial.normalTexture) {
-                        var glTFTexture = _GLTFMaterial.ExportTexture(babylonPBRMetalRoughMaterial.normalTexture, mimeType, images, textures, imageData);
+                        var glTFTexture = _GLTFMaterial._ExportTexture(babylonPBRMetalRoughMaterial.normalTexture, mimeType, images, textures, imageData);
                         if (glTFTexture) {
                             glTFMaterial.normalTexture = glTFTexture;
                         }
                     }
                     if (babylonPBRMetalRoughMaterial.occlusionTexture) {
-                        var glTFTexture = _GLTFMaterial.ExportTexture(babylonPBRMetalRoughMaterial.occlusionTexture, mimeType, images, textures, imageData);
+                        var glTFTexture = _GLTFMaterial._ExportTexture(babylonPBRMetalRoughMaterial.occlusionTexture, mimeType, images, textures, imageData);
                         if (glTFTexture) {
                             glTFMaterial.occlusionTexture = glTFTexture;
                             if (babylonPBRMetalRoughMaterial.occlusionStrength != null) {
@@ -1272,17 +1283,17 @@ var BABYLON;
                         }
                     }
                     if (babylonPBRMetalRoughMaterial.emissiveTexture) {
-                        var glTFTexture = _GLTFMaterial.ExportTexture(babylonPBRMetalRoughMaterial.emissiveTexture, mimeType, images, textures, imageData);
+                        var glTFTexture = _GLTFMaterial._ExportTexture(babylonPBRMetalRoughMaterial.emissiveTexture, mimeType, images, textures, imageData);
                         if (glTFTexture != null) {
                             glTFMaterial.emissiveTexture = glTFTexture;
                         }
                     }
                 }
-                if (babylonPBRMetalRoughMaterial.emissiveColor.equalsFloats(0.0, 0.0, 0.0)) {
+                if (this.FuzzyEquals(babylonPBRMetalRoughMaterial.emissiveColor, BABYLON.Color3.Black(), this._epsilon)) {
                     glTFMaterial.emissiveFactor = babylonPBRMetalRoughMaterial.emissiveColor.asArray();
                 }
                 if (babylonPBRMetalRoughMaterial.transparencyMode != null) {
-                    var alphaMode = _GLTFMaterial.GetAlphaMode(babylonPBRMetalRoughMaterial);
+                    var alphaMode = _GLTFMaterial._GetAlphaMode(babylonPBRMetalRoughMaterial);
                     if (alphaMode !== "OPAQUE" /* OPAQUE */) {
                         glTFMaterial.alphaMode = alphaMode;
                         if (alphaMode === "BLEND" /* BLEND */) {
@@ -1294,12 +1305,213 @@ var BABYLON;
                 materials.push(glTFMaterial);
             };
             /**
+             * Converts an image typed array buffer to a base64 image.
+             * @param buffer - typed array buffer.
+             * @param width - width of the image.
+             * @param height - height of the image.
+             * @param mimeType - mimetype of the image.
+             * @returns - base64 image string.
+             */
+            _GLTFMaterial._CreateBase64FromCanvas = function (buffer, width, height, mimeType) {
+                var imageCanvas = document.createElement('canvas');
+                imageCanvas.id = "WriteCanvas";
+                var ctx = imageCanvas.getContext('2d');
+                imageCanvas.width = width;
+                imageCanvas.height = height;
+                var imgData = ctx.createImageData(width, height);
+                imgData.data.set(buffer);
+                ctx.putImageData(imgData, 0, 0);
+                return imageCanvas.toDataURL(mimeType);
+            };
+            /**
+             * Generates a white texture based on the specified width and height.
+             * @param width - width of the texture in pixels.
+             * @param height - height of the texture in pixels.
+             * @param scene - babylonjs scene.
+             * @returns - white texture.
+             */
+            _GLTFMaterial._CreateWhiteTexture = function (width, height, scene) {
+                var data = new Uint8Array(width * height * 4);
+                for (var i = 0; i < data.length; ++i) {
+                    data[i] = 255;
+                }
+                var rawTexture = BABYLON.RawTexture.CreateRGBATexture(data, width, height, scene);
+                return rawTexture;
+            };
+            /**
+             * Resizes the two source textures to the same dimensions.  If a texture is null, a default white texture is generated.  If both textures are null, returns null.
+             * @param texture1 - first texture to resize.
+             * @param texture2 - second texture to resize.
+             * @param scene - babylonjs scene.
+             * @returns resized textures or null.
+             */
+            _GLTFMaterial._ResizeTexturesToSameDimensions = function (texture1, texture2, scene) {
+                var texture1Size = texture1 ? texture1.getSize() : { width: 0, height: 0 };
+                var texture2Size = texture2 ? texture2.getSize() : { width: 0, height: 0 };
+                var resizedTexture1;
+                var resizedTexture2;
+                if (texture1Size.width < texture2Size.width) {
+                    if (texture1) {
+                        resizedTexture1 = BABYLON.TextureTools.CreateResizedCopy(texture1, texture2Size.width, texture2Size.height, true);
+                    }
+                    else {
+                        resizedTexture1 = this._CreateWhiteTexture(texture2Size.width, texture2Size.height, scene);
+                    }
+                    resizedTexture2 = texture2;
+                }
+                else if (texture1Size.width > texture2Size.width) {
+                    if (texture2) {
+                        resizedTexture2 = BABYLON.TextureTools.CreateResizedCopy(texture2, texture1Size.width, texture1Size.height, true);
+                    }
+                    else {
+                        resizedTexture2 = this._CreateWhiteTexture(texture1Size.width, texture1Size.height, scene);
+                    }
+                    resizedTexture1 = texture1;
+                }
+                else {
+                    resizedTexture1 = texture1;
+                    resizedTexture2 = texture2;
+                }
+                return {
+                    "texture1": resizedTexture1,
+                    "texture2": resizedTexture2
+                };
+            };
+            /**
+             * Convert Specular Glossiness Textures to Metallic Roughness.
              * See link below for info on the material conversions from PBR Metallic/Roughness and Specular/Glossiness
              * @link https://github.com/KhronosGroup/glTF/blob/master/extensions/2.0/Khronos/KHR_materials_pbrSpecularGlossiness/examples/convert-between-workflows-bjs/js/babylon.pbrUtilities.js
+             * @param diffuseTexture - texture used to store diffuse information.
+             * @param specularGlossinessTexture - texture used to store specular and glossiness information.
+             * @param factors - specular glossiness material factors.
+             * @param mimeType - the mime type to use for the texture.
+             * @returns pbr metallic roughness interface or null.
+             */
+            _GLTFMaterial._ConvertSpecularGlossinessTexturesToMetallicRoughness = function (diffuseTexture, specularGlossinessTexture, factors, mimeType) {
+                if (!(diffuseTexture || specularGlossinessTexture)) {
+                    return null;
+                }
+                var scene = diffuseTexture ? diffuseTexture.getScene() : specularGlossinessTexture.getScene();
+                if (!scene) {
+                    throw new Error("_ConvertSpecularGlossinessTexturesToMetallicRoughness: Scene from textures is missing!");
+                }
+                var resizedTextures = this._ResizeTexturesToSameDimensions(diffuseTexture, specularGlossinessTexture, scene);
+                var diffuseSize = resizedTextures.texture1.getSize();
+                var diffuseBuffer;
+                var specularGlossinessBuffer;
+                var width = diffuseSize.width;
+                var height = diffuseSize.height;
+                var pixels = (resizedTextures.texture1.readPixels());
+                if (pixels instanceof Uint8Array) {
+                    diffuseBuffer = (resizedTextures.texture1.readPixels());
+                }
+                else {
+                    throw new Error("_ConvertSpecularGlossinessTexturesToMetallicRoughness: Pixel array buffer type not supported for texture: " + resizedTextures.texture1.name);
+                }
+                pixels = resizedTextures.texture2.readPixels();
+                if (pixels instanceof Uint8Array) {
+                    specularGlossinessBuffer = (resizedTextures.texture2.readPixels());
+                }
+                else {
+                    throw new Error("_ConvertSpecularGlossinessTexturesToMetallicRoughness: Pixel array buffer type not supported for texture: " + resizedTextures.texture2.name);
+                }
+                var byteLength = specularGlossinessBuffer.byteLength;
+                var metallicRoughnessBuffer = new Uint8Array(byteLength);
+                var baseColorBuffer = new Uint8Array(byteLength);
+                var strideSize = 4;
+                var maxBaseColor = BABYLON.Color3.Black();
+                var maxMetallic = 0;
+                var maxRoughness = 0;
+                for (var h = 0; h < height; ++h) {
+                    for (var w = 0; w < width; ++w) {
+                        var offset = (width * h + w) * strideSize;
+                        var diffuseColor = BABYLON.Color3.FromInts(diffuseBuffer[offset], diffuseBuffer[offset + 1], diffuseBuffer[offset + 2]).multiply(factors.diffuseColor);
+                        var specularColor = BABYLON.Color3.FromInts(specularGlossinessBuffer[offset], specularGlossinessBuffer[offset + 1], specularGlossinessBuffer[offset + 2]).multiply(factors.specularColor);
+                        var glossiness = (specularGlossinessBuffer[offset + 3] / 255) * factors.glossiness;
+                        var specularGlossiness = {
+                            diffuseColor: diffuseColor,
+                            specularColor: specularColor,
+                            glossiness: glossiness
+                        };
+                        var metallicRoughness = this._ConvertSpecularGlossinessToMetallicRoughness(specularGlossiness);
+                        maxBaseColor.r = Math.max(maxBaseColor.r, metallicRoughness.baseColor.r);
+                        maxBaseColor.g = Math.max(maxBaseColor.g, metallicRoughness.baseColor.g);
+                        maxBaseColor.b = Math.max(maxBaseColor.b, metallicRoughness.baseColor.b);
+                        maxMetallic = Math.max(maxMetallic, metallicRoughness.metallic);
+                        maxRoughness = Math.max(maxRoughness, metallicRoughness.roughness);
+                        baseColorBuffer[offset] = metallicRoughness.baseColor.r * 255;
+                        baseColorBuffer[offset + 1] = metallicRoughness.baseColor.g * 255;
+                        baseColorBuffer[offset + 2] = metallicRoughness.baseColor.b * 255;
+                        baseColorBuffer[offset + 3] = resizedTextures.texture1.hasAlpha ? diffuseBuffer[offset + 3] : 255;
+                        metallicRoughnessBuffer[offset] = 255;
+                        metallicRoughnessBuffer[offset + 1] = metallicRoughness.roughness * 255;
+                        metallicRoughnessBuffer[offset + 2] = metallicRoughness.metallic * 255;
+                        metallicRoughnessBuffer[offset + 3] = 255;
+                    }
+                }
+                // Retrieves the metallic roughness factors from the maximum texture values.
+                var metallicRoughnessFactors = {
+                    baseColor: maxBaseColor,
+                    metallic: maxMetallic,
+                    roughness: maxRoughness
+                };
+                var writeOutMetallicRoughnessTexture = false;
+                var writeOutBaseColorTexture = false;
+                for (var h = 0; h < height; ++h) {
+                    for (var w = 0; w < width; ++w) {
+                        var destinationOffset = (width * h + w) * strideSize;
+                        baseColorBuffer[destinationOffset] /= metallicRoughnessFactors.baseColor.r > this._epsilon ? metallicRoughnessFactors.baseColor.r : 1;
+                        baseColorBuffer[destinationOffset + 1] /= metallicRoughnessFactors.baseColor.g > this._epsilon ? metallicRoughnessFactors.baseColor.g : 1;
+                        baseColorBuffer[destinationOffset + 2] /= metallicRoughnessFactors.baseColor.b > this._epsilon ? metallicRoughnessFactors.baseColor.b : 1;
+                        var baseColorPixel = new BABYLON.Color3(baseColorBuffer[destinationOffset], baseColorBuffer[destinationOffset + 1], baseColorBuffer[destinationOffset + 2]);
+                        if (!this.FuzzyEquals(baseColorPixel, BABYLON.Color3.White(), this._epsilon)) {
+                            writeOutBaseColorTexture = true;
+                        }
+                        metallicRoughnessBuffer[destinationOffset + 1] /= metallicRoughnessFactors.roughness > this._epsilon ? metallicRoughnessFactors.roughness : 1;
+                        metallicRoughnessBuffer[destinationOffset + 2] /= metallicRoughnessFactors.metallic > this._epsilon ? metallicRoughnessFactors.metallic : 1;
+                        var metallicRoughnessPixel = new BABYLON.Color3(metallicRoughnessBuffer[destinationOffset], metallicRoughnessBuffer[destinationOffset + 1], metallicRoughnessBuffer[destinationOffset + 2]);
+                        if (!this.FuzzyEquals(metallicRoughnessPixel, BABYLON.Color3.White(), this._epsilon)) {
+                            writeOutMetallicRoughnessTexture = true;
+                        }
+                    }
+                }
+                if (writeOutMetallicRoughnessTexture) {
+                    var metallicRoughnessBase64 = this._CreateBase64FromCanvas(metallicRoughnessBuffer, width, height, mimeType);
+                    metallicRoughnessFactors.metallicRoughnessTextureBase64 = metallicRoughnessBase64;
+                }
+                if (writeOutBaseColorTexture) {
+                    var baseColorBase64 = this._CreateBase64FromCanvas(baseColorBuffer, width, height, mimeType);
+                    metallicRoughnessFactors.baseColorTextureBase64 = baseColorBase64;
+                }
+                return metallicRoughnessFactors;
+            };
+            /**
+             * Converts specular glossiness material properties to metallic roughness.
+             * @param specularGlossiness - interface with specular glossiness material properties.
+             * @returns - interface with metallic roughness material properties.
+             */
+            _GLTFMaterial._ConvertSpecularGlossinessToMetallicRoughness = function (specularGlossiness) {
+                var diffusePerceivedBrightness = _GLTFMaterial._GetPerceivedBrightness(specularGlossiness.diffuseColor);
+                var specularPerceivedBrightness = _GLTFMaterial._GetPerceivedBrightness(specularGlossiness.specularColor);
+                var oneMinusSpecularStrength = 1 - _GLTFMaterial._GetMaxComponent(specularGlossiness.specularColor);
+                var metallic = _GLTFMaterial._SolveMetallic(diffusePerceivedBrightness, specularPerceivedBrightness, oneMinusSpecularStrength);
+                var baseColorFromDiffuse = specularGlossiness.diffuseColor.scale(oneMinusSpecularStrength / (1.0 - this._dielectricSpecular.r) / Math.max(1 - metallic, this._epsilon));
+                var baseColorFromSpecular = specularGlossiness.specularColor.subtract(this._dielectricSpecular.scale(1 - metallic)).scale(1 / Math.max(metallic, this._epsilon));
+                var baseColor = BABYLON.Color3.Lerp(baseColorFromDiffuse, baseColorFromSpecular, metallic * metallic);
+                baseColor = baseColor.clampToRef(0, 1, baseColor);
+                var metallicRoughness = {
+                    baseColor: baseColor,
+                    metallic: metallic,
+                    roughness: 1 - specularGlossiness.glossiness
+                };
+                return metallicRoughness;
+            };
+            /**
+             * Calculates the surface reflectance, independent of lighting conditions.
              * @param color - Color source to calculate brightness from.
              * @returns number representing the perceived brightness, or zero if color is undefined.
              */
-            _GLTFMaterial.GetPerceivedBrightness = function (color) {
+            _GLTFMaterial._GetPerceivedBrightness = function (color) {
                 if (color) {
                     return Math.sqrt(0.299 * color.r * color.r + 0.587 * color.g * color.g + 0.114 * color.b * color.b);
                 }
@@ -1310,7 +1522,7 @@ var BABYLON;
              * @param color
              * @returns maximum color component value, or zero if color is null or undefined.
              */
-            _GLTFMaterial.GetMaxComponent = function (color) {
+            _GLTFMaterial._GetMaxComponent = function (color) {
                 if (color) {
                     return Math.max(color.r, Math.max(color.g, color.b));
                 }
@@ -1326,110 +1538,117 @@ var BABYLON;
              * @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.
              */
-            _GLTFMaterial.ConvertPBRMaterial = function (babylonPBRMaterial, mimeType, images, textures, materials, imageData, hasTextureCoords) {
+            _GLTFMaterial._ConvertPBRMaterial = function (babylonPBRMaterial, mimeType, images, textures, materials, imageData, hasTextureCoords) {
                 var glTFPbrMetallicRoughness = {};
+                var metallicRoughness;
                 var glTFMaterial = {
                     name: babylonPBRMaterial.name
                 };
                 var useMetallicRoughness = babylonPBRMaterial.isMetallicWorkflow();
-                if (babylonPBRMaterial) {
-                    if (useMetallicRoughness) {
-                        glTFPbrMetallicRoughness.baseColorFactor = [
-                            babylonPBRMaterial.albedoColor.r,
-                            babylonPBRMaterial.albedoColor.g,
-                            babylonPBRMaterial.albedoColor.b,
-                            babylonPBRMaterial.alpha
-                        ];
-                        if (babylonPBRMaterial.metallic != null) {
-                            if (babylonPBRMaterial.metallic !== 1) {
-                                glTFPbrMetallicRoughness.metallicFactor = babylonPBRMaterial.metallic;
+                if (!useMetallicRoughness) {
+                    var specGloss = {
+                        diffuseColor: babylonPBRMaterial.albedoColor || BABYLON.Color3.White(),
+                        specularColor: babylonPBRMaterial.reflectivityColor || BABYLON.Color3.White(),
+                        glossiness: babylonPBRMaterial.microSurface || 1,
+                    };
+                    if (babylonPBRMaterial.reflectivityTexture && !babylonPBRMaterial.useMicroSurfaceFromReflectivityMapAlpha) {
+                        throw new Error("_ConvertPBRMaterial: Glossiness values not included in the reflectivity texture currently not supported");
+                    }
+                    metallicRoughness = this._ConvertSpecularGlossinessTexturesToMetallicRoughness(babylonPBRMaterial.albedoTexture, babylonPBRMaterial.reflectivityTexture, specGloss, mimeType);
+                    if (!metallicRoughness) {
+                        metallicRoughness = this._ConvertSpecularGlossinessToMetallicRoughness(specGloss);
+                    }
+                    else {
+                        if (hasTextureCoords) {
+                            if (metallicRoughness.baseColorTextureBase64) {
+                                var glTFBaseColorTexture = _GLTFMaterial._GetTextureInfoFromBase64(metallicRoughness.baseColorTextureBase64, "bjsBaseColorTexture_" + (textures.length) + ".png", mimeType, images, textures, imageData);
+                                if (glTFBaseColorTexture != null) {
+                                    glTFPbrMetallicRoughness.baseColorTexture = glTFBaseColorTexture;
+                                }
                             }
-                        }
-                        if (babylonPBRMaterial.roughness != null) {
-                            if (babylonPBRMaterial.roughness !== 1) {
-                                glTFPbrMetallicRoughness.roughnessFactor = babylonPBRMaterial.roughness;
+                            if (metallicRoughness.metallicRoughnessTextureBase64) {
+                                var glTFMRColorTexture = _GLTFMaterial._GetTextureInfoFromBase64(metallicRoughness.metallicRoughnessTextureBase64, "bjsMetallicRoughnessTexture_" + (textures.length) + ".png", mimeType, images, textures, imageData);
+                                if (glTFMRColorTexture != null) {
+                                    glTFPbrMetallicRoughness.metallicRoughnessTexture = glTFMRColorTexture;
+                                }
                             }
                         }
                     }
-                    else {
-                        var diffuseColor = babylonPBRMaterial.albedoColor || BABYLON.Color3.Black();
-                        var specularColor = babylonPBRMaterial.reflectionColor || BABYLON.Color3.Black();
-                        var diffusePerceivedBrightness = _GLTFMaterial.GetPerceivedBrightness(diffuseColor);
-                        var specularPerceivedBrightness = _GLTFMaterial.GetPerceivedBrightness(specularColor);
-                        var oneMinusSpecularStrength = 1 - _GLTFMaterial.GetMaxComponent(babylonPBRMaterial.reflectionColor);
-                        var metallic = _GLTFMaterial.SolveMetallic(diffusePerceivedBrightness, specularPerceivedBrightness, oneMinusSpecularStrength);
-                        var glossiness = babylonPBRMaterial.microSurface || 0;
-                        var baseColorFromDiffuse = diffuseColor.scale(oneMinusSpecularStrength / (1.0 - this.dielectricSpecular.r) / Math.max(1 - metallic, this.epsilon));
-                        var baseColorFromSpecular = specularColor.subtract(this.dielectricSpecular.scale(1 - metallic)).scale(1 / Math.max(metallic, this.epsilon));
-                        var baseColor = BABYLON.Color3.Lerp(baseColorFromDiffuse, baseColorFromSpecular, metallic * metallic);
-                        baseColor = baseColor.clampToRef(0, 1, baseColor);
-                        glTFPbrMetallicRoughness.baseColorFactor = [
-                            baseColor.r,
-                            baseColor.g,
-                            baseColor.b,
-                            babylonPBRMaterial.alpha
-                        ];
-                        if (metallic !== 1) {
-                            glTFPbrMetallicRoughness.metallicFactor = metallic;
-                        }
-                        if (glossiness) {
-                            glTFPbrMetallicRoughness.roughnessFactor = 1 - glossiness;
-                        }
+                }
+                else {
+                    metallicRoughness = {
+                        baseColor: babylonPBRMaterial.albedoColor,
+                        metallic: babylonPBRMaterial.metallic,
+                        roughness: babylonPBRMaterial.roughness
+                    };
+                }
+                if (!(this.FuzzyEquals(metallicRoughness.baseColor, BABYLON.Color3.White(), this._epsilon) && babylonPBRMaterial.alpha >= this._epsilon)) {
+                    glTFPbrMetallicRoughness.baseColorFactor = [
+                        metallicRoughness.baseColor.r,
+                        metallicRoughness.baseColor.g,
+                        metallicRoughness.baseColor.b,
+                        babylonPBRMaterial.alpha
+                    ];
+                }
+                if (metallicRoughness.metallic != null && metallicRoughness.metallic !== 1) {
+                    glTFPbrMetallicRoughness.metallicFactor = metallicRoughness.metallic;
+                }
+                if (metallicRoughness.roughness != null && metallicRoughness.roughness !== 1) {
+                    glTFPbrMetallicRoughness.roughnessFactor = metallicRoughness.roughness;
+                }
+                if (babylonPBRMaterial.backFaceCulling != null && !babylonPBRMaterial.backFaceCulling) {
+                    if (!babylonPBRMaterial.twoSidedLighting) {
+                        BABYLON.Tools.Warn(babylonPBRMaterial.name + ": Back-face culling enabled and two-sided lighting disabled is not supported in glTF.");
                     }
-                    if (babylonPBRMaterial.backFaceCulling) {
-                        if (!babylonPBRMaterial.twoSidedLighting) {
-                            BABYLON.Tools.Warn(babylonPBRMaterial.name + ": Back-face culling enabled and two-sided lighting disabled is not supported in glTF.");
+                    glTFMaterial.doubleSided = true;
+                }
+                if (hasTextureCoords) {
+                    if (useMetallicRoughness && babylonPBRMaterial.albedoTexture) {
+                        var glTFTexture = _GLTFMaterial._ExportTexture(babylonPBRMaterial.albedoTexture, mimeType, images, textures, imageData);
+                        if (glTFTexture) {
+                            glTFPbrMetallicRoughness.baseColorTexture = glTFTexture;
                         }
-                        glTFMaterial.doubleSided = true;
                     }
-                    if (hasTextureCoords) {
-                        if (babylonPBRMaterial.albedoTexture) {
-                            var glTFTexture = _GLTFMaterial.ExportTexture(babylonPBRMaterial.albedoTexture, mimeType, images, textures, imageData);
-                            if (glTFTexture) {
-                                glTFPbrMetallicRoughness.baseColorTexture = glTFTexture;
-                            }
-                        }
-                        if (babylonPBRMaterial.bumpTexture) {
-                            var glTFTexture = _GLTFMaterial.ExportTexture(babylonPBRMaterial.bumpTexture, mimeType, images, textures, imageData);
-                            if (glTFTexture) {
-                                glTFMaterial.normalTexture = glTFTexture;
-                            }
-                        }
-                        if (babylonPBRMaterial.ambientTexture) {
-                            var glTFTexture = _GLTFMaterial.ExportTexture(babylonPBRMaterial.ambientTexture, mimeType, images, textures, imageData);
-                            if (glTFTexture) {
-                                var occlusionTexture = {
-                                    index: glTFTexture.index
-                                };
-                                glTFMaterial.occlusionTexture = occlusionTexture;
-                                if (babylonPBRMaterial.ambientTextureStrength) {
-                                    occlusionTexture.strength = babylonPBRMaterial.ambientTextureStrength;
-                                }
-                            }
+                    if (babylonPBRMaterial.bumpTexture) {
+                        var glTFTexture = _GLTFMaterial._ExportTexture(babylonPBRMaterial.bumpTexture, mimeType, images, textures, imageData);
+                        if (glTFTexture) {
+                            glTFMaterial.normalTexture = glTFTexture;
                         }
-                        if (babylonPBRMaterial.emissiveTexture) {
-                            var glTFTexture = _GLTFMaterial.ExportTexture(babylonPBRMaterial.emissiveTexture, mimeType, images, textures, imageData);
-                            if (glTFTexture != null) {
-                                glTFMaterial.emissiveTexture = glTFTexture;
+                    }
+                    if (babylonPBRMaterial.ambientTexture) {
+                        var glTFTexture = _GLTFMaterial._ExportTexture(babylonPBRMaterial.ambientTexture, mimeType, images, textures, imageData);
+                        if (glTFTexture) {
+                            var occlusionTexture = {
+                                index: glTFTexture.index
+                            };
+                            glTFMaterial.occlusionTexture = occlusionTexture;
+                            if (babylonPBRMaterial.ambientTextureStrength) {
+                                occlusionTexture.strength = babylonPBRMaterial.ambientTextureStrength;
                             }
                         }
-                        if (babylonPBRMaterial.metallicTexture) {
-                            var glTFTexture = _GLTFMaterial.ExportTexture(babylonPBRMaterial.metallicTexture, mimeType, images, textures, imageData);
-                            if (glTFTexture != null) {
-                                glTFPbrMetallicRoughness.metallicRoughnessTexture = glTFTexture;
-                            }
+                    }
+                    if (babylonPBRMaterial.emissiveTexture) {
+                        var glTFTexture = _GLTFMaterial._ExportTexture(babylonPBRMaterial.emissiveTexture, mimeType, images, textures, imageData);
+                        if (glTFTexture != null) {
+                            glTFMaterial.emissiveTexture = glTFTexture;
                         }
                     }
-                    if (!babylonPBRMaterial.emissiveColor.equalsFloats(0.0, 0.0, 0.0)) {
-                        glTFMaterial.emissiveFactor = babylonPBRMaterial.emissiveColor.asArray();
+                    if (babylonPBRMaterial.metallicTexture) {
+                        var glTFTexture = _GLTFMaterial._ExportTexture(babylonPBRMaterial.metallicTexture, mimeType, images, textures, imageData);
+                        if (glTFTexture != null) {
+                            glTFPbrMetallicRoughness.metallicRoughnessTexture = glTFTexture;
+                        }
                     }
-                    if (babylonPBRMaterial.transparencyMode != null) {
-                        var alphaMode = _GLTFMaterial.GetAlphaMode(babylonPBRMaterial);
-                        if (alphaMode !== "OPAQUE" /* OPAQUE */) {
-                            glTFMaterial.alphaMode = alphaMode;
-                            if (alphaMode === "BLEND" /* BLEND */) {
-                                glTFMaterial.alphaCutoff = babylonPBRMaterial.alphaCutOff;
-                            }
+                }
+                if (!this.FuzzyEquals(babylonPBRMaterial.emissiveColor, BABYLON.Color3.Black(), this._epsilon)) {
+                    glTFMaterial.emissiveFactor = babylonPBRMaterial.emissiveColor.asArray();
+                }
+                if (babylonPBRMaterial.transparencyMode != null) {
+                    var alphaMode = _GLTFMaterial._GetAlphaMode(babylonPBRMaterial);
+                    if (alphaMode !== "OPAQUE" /* OPAQUE */) {
+                        glTFMaterial.alphaMode = alphaMode;
+                        if (alphaMode === "BLEND" /* BLEND */) {
+                            glTFMaterial.alphaCutoff = babylonPBRMaterial.alphaCutOff;
                         }
                     }
                 }
@@ -1443,17 +1662,13 @@ var BABYLON;
              * @param images - Array of glTF images.
              * @param textures - Array of glTF textures.
              * @param imageData - map of image file name and data.
-             * @return - glTF texture, or null if the texture format is not supported.
+             * @return - glTF texture info, or null if the texture format is not supported.
              */
-            _GLTFMaterial.ExportTexture = function (babylonTexture, mimeType, images, textures, imageData) {
-                var textureInfo = null;
-                var glTFTexture = {
-                    source: images.length
-                };
+            _GLTFMaterial._ExportTexture = function (babylonTexture, mimeType, images, textures, imageData) {
                 var textureName = "texture_" + (textures.length - 1).toString();
                 var textureData = babylonTexture.getInternalTexture();
                 if (textureData != null) {
-                    textureName = textureData.url;
+                    textureName = textureData.url || textureName;
                 }
                 textureName = BABYLON.Tools.GetFilename(textureName);
                 var baseFile = textureName.split('.')[0];
@@ -1465,28 +1680,37 @@ var BABYLON;
                     extension = ".png";
                 }
                 else {
-                    BABYLON.Tools.Error("Unsupported mime type " + mimeType);
+                    throw new Error("Unsupported mime type " + mimeType);
                 }
                 textureName = baseFile + extension;
                 var pixels = babylonTexture.readPixels();
-                var imageCanvas = document.createElement('canvas');
-                imageCanvas.id = "ImageCanvas";
-                var ctx = imageCanvas.getContext('2d');
                 var size = babylonTexture.getSize();
-                imageCanvas.width = size.width;
-                imageCanvas.height = size.height;
-                var imgData = ctx.createImageData(size.width, size.height);
-                imgData.data.set(pixels);
-                ctx.putImageData(imgData, 0, 0);
-                var base64Data = imageCanvas.toDataURL(mimeType);
-                var binStr = atob(base64Data.split(',')[1]);
+                var base64Data = this._CreateBase64FromCanvas(pixels, size.width, size.height, mimeType);
+                return this._GetTextureInfoFromBase64(base64Data, textureName, mimeType, images, textures, imageData);
+            };
+            /**
+             * Builds a texture from base64 string.
+             * @param base64Texture - base64 texture string.
+             * @param textureName - Name to use for the texture.
+             * @param mimeType - image mime type for the texture.
+             * @param images - array of images.
+             * @param textures - array of textures.
+             * @param imageData - map of image data.
+             * @returns - glTF texture info, or null if the texture format is not supported.
+             */
+            _GLTFMaterial._GetTextureInfoFromBase64 = function (base64Texture, textureName, mimeType, images, textures, imageData) {
+                var textureInfo = null;
+                var glTFTexture = {
+                    source: images.length
+                };
+                var binStr = atob(base64Texture.split(',')[1]);
                 var arr = new Uint8Array(binStr.length);
                 for (var i = 0; i < binStr.length; ++i) {
                     arr[i] = binStr.charCodeAt(i);
                 }
                 var imageValues = { data: arr, mimeType: mimeType };
                 imageData[textureName] = imageValues;
-                if (mimeType === "image/jpeg" /* JPEG */) {
+                if (mimeType === "image/jpeg" /* JPEG */ || mimeType === "image/png" /* PNG */) {
                     var glTFImage = {
                         uri: textureName
                     };
@@ -1519,12 +1743,15 @@ var BABYLON;
             /**
              * Represents the dielectric specular values for R, G and B.
              */
-            _GLTFMaterial.dielectricSpecular = new BABYLON.Color3(0.04, 0.04, 0.04);
+            _GLTFMaterial._dielectricSpecular = new BABYLON.Color3(0.04, 0.04, 0.04);
             /**
              * Allows the maximum specular power to be defined for material calculations.
              */
-            _GLTFMaterial.maxSpecularPower = 1024;
-            _GLTFMaterial.epsilon = 1e-6;
+            _GLTFMaterial._maxSpecularPower = 1024;
+            /**
+             * Numeric tolerance value
+             */
+            _GLTFMaterial._epsilon = 1e-6;
             return _GLTFMaterial;
         }());
         GLTF2._GLTFMaterial = _GLTFMaterial;

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 1 - 1
dist/preview release/serializers/babylonjs.serializers.min.js


+ 86 - 29
dist/preview release/serializers/babylonjs.serializers.module.d.ts

@@ -305,23 +305,33 @@ declare module BABYLON.GLTF2 {
         /**
          * Represents the dielectric specular values for R, G and B.
          */
-        private static readonly dielectricSpecular;
+        private static readonly _dielectricSpecular;
         /**
          * Allows the maximum specular power to be defined for material calculations.
          */
-        private static maxSpecularPower;
-        private static epsilon;
+        private static _maxSpecularPower;
+        /**
+         * Numeric tolerance value
+         */
+        private static _epsilon;
+        /**
+         * Specifies if two colors are approximately equal in value.
+         * @param color1 - first color to compare to.
+         * @param color2 - second color to compare to.
+         * @param epsilon - threshold value
+         */
+        private static FuzzyEquals(color1, color2, epsilon);
         /**
          * Gets the materials from a Babylon scene and converts them to glTF materials.
-         * @param scene
-         * @param mimeType
-         * @param images
-         * @param textures
-         * @param materials
-         * @param imageData
-         * @param hasTextureCoords
-         */
-        static ConvertMaterialsToGLTF(babylonMaterials: Material[], mimeType: ImageMimeType, images: IImage[], textures: ITexture[], materials: IMaterial[], imageData: {
+         * @param scene - babylonjs scene.
+         * @param mimeType - texture mime type.
+         * @param images - array of images.
+         * @param textures - array of textures.
+         * @param materials - array of materials.
+         * @param imageData - mapping of texture names to base64 textures
+         * @param hasTextureCoords - specifies if texture coordinates are present on the material.
+         */
+        static _ConvertMaterialsToGLTF(babylonMaterials: Material[], mimeType: ImageMimeType, images: IImage[], textures: ITexture[], materials: IMaterial[], imageData: {
             [fileName: string]: {
                 data: Uint8Array;
                 mimeType: ImageMimeType;
@@ -332,19 +342,19 @@ declare module BABYLON.GLTF2 {
          * @param originalMaterial - original glTF material.
          * @returns glTF material without texture parameters
          */
-        static StripTexturesFromMaterial(originalMaterial: IMaterial): IMaterial;
+        static _StripTexturesFromMaterial(originalMaterial: IMaterial): IMaterial;
         /**
          * Specifies if the material has any texture parameters present.
          * @param material - glTF Material.
          * @returns boolean specifying if texture parameters are present
          */
-        static HasTexturesPresent(material: IMaterial): boolean;
+        static _HasTexturesPresent(material: IMaterial): boolean;
         /**
          * Converts a Babylon StandardMaterial to a glTF Metallic Roughness Material.
          * @param babylonStandardMaterial
          * @returns - glTF Metallic Roughness Material representation
          */
-        static ConvertToGLTFPBRMetallicRoughness(babylonStandardMaterial: StandardMaterial): IMaterialPbrMetallicRoughness;
+        static _ConvertToGLTFPBRMetallicRoughness(babylonStandardMaterial: StandardMaterial): IMaterialPbrMetallicRoughness;
         /**
          * Computes the metallic factor
          * @param diffuse - diffused value
@@ -352,13 +362,13 @@ declare module BABYLON.GLTF2 {
          * @param oneMinusSpecularStrength - one minus the specular strength
          * @returns - metallic value
          */
-        static SolveMetallic(diffuse: number, specular: number, oneMinusSpecularStrength: number): number;
+        static _SolveMetallic(diffuse: number, specular: number, oneMinusSpecularStrength: number): number;
         /**
          * Gets the glTF alpha mode from the Babylon Material
          * @param babylonMaterial - Babylon Material
          * @returns - The Babylon alpha mode value
          */
-        static GetAlphaMode(babylonMaterial: Material): MaterialAlphaMode;
+        static _GetAlphaMode(babylonMaterial: Material): MaterialAlphaMode;
         /**
          * Converts a Babylon Standard Material to a glTF Material.
          * @param babylonStandardMaterial - BJS Standard Material.
@@ -369,7 +379,7 @@ declare module BABYLON.GLTF2 {
          * @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.
          */
-        static ConvertStandardMaterial(babylonStandardMaterial: StandardMaterial, mimeType: ImageMimeType, images: IImage[], textures: ITexture[], materials: IMaterial[], imageData: {
+        static _ConvertStandardMaterial(babylonStandardMaterial: StandardMaterial, mimeType: ImageMimeType, images: IImage[], textures: ITexture[], materials: IMaterial[], imageData: {
             [fileName: string]: {
                 data: Uint8Array;
                 mimeType: ImageMimeType;
@@ -385,25 +395,66 @@ declare module BABYLON.GLTF2 {
          * @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.
          */
-        static ConvertPBRMetallicRoughnessMaterial(babylonPBRMetalRoughMaterial: PBRMetallicRoughnessMaterial, mimeType: ImageMimeType, images: IImage[], textures: ITexture[], materials: IMaterial[], imageData: {
+        static _ConvertPBRMetallicRoughnessMaterial(babylonPBRMetalRoughMaterial: PBRMetallicRoughnessMaterial, mimeType: ImageMimeType, images: IImage[], textures: ITexture[], materials: IMaterial[], imageData: {
             [fileName: string]: {
                 data: Uint8Array;
                 mimeType: ImageMimeType;
             };
         }, hasTextureCoords: boolean): void;
         /**
+         * Converts an image typed array buffer to a base64 image.
+         * @param buffer - typed array buffer.
+         * @param width - width of the image.
+         * @param height - height of the image.
+         * @param mimeType - mimetype of the image.
+         * @returns - base64 image string.
+         */
+        private static _CreateBase64FromCanvas(buffer, width, height, mimeType);
+        /**
+         * Generates a white texture based on the specified width and height.
+         * @param width - width of the texture in pixels.
+         * @param height - height of the texture in pixels.
+         * @param scene - babylonjs scene.
+         * @returns - white texture.
+         */
+        private static _CreateWhiteTexture(width, height, scene);
+        /**
+         * Resizes the two source textures to the same dimensions.  If a texture is null, a default white texture is generated.  If both textures are null, returns null.
+         * @param texture1 - first texture to resize.
+         * @param texture2 - second texture to resize.
+         * @param scene - babylonjs scene.
+         * @returns resized textures or null.
+         */
+        private static _ResizeTexturesToSameDimensions(texture1, texture2, scene);
+        /**
+         * Convert Specular Glossiness Textures to Metallic Roughness.
          * See link below for info on the material conversions from PBR Metallic/Roughness and Specular/Glossiness
          * @link https://github.com/KhronosGroup/glTF/blob/master/extensions/2.0/Khronos/KHR_materials_pbrSpecularGlossiness/examples/convert-between-workflows-bjs/js/babylon.pbrUtilities.js
+         * @param diffuseTexture - texture used to store diffuse information.
+         * @param specularGlossinessTexture - texture used to store specular and glossiness information.
+         * @param factors - specular glossiness material factors.
+         * @param mimeType - the mime type to use for the texture.
+         * @returns pbr metallic roughness interface or null.
+         */
+        private static _ConvertSpecularGlossinessTexturesToMetallicRoughness(diffuseTexture, specularGlossinessTexture, factors, mimeType);
+        /**
+         * Converts specular glossiness material properties to metallic roughness.
+         * @param specularGlossiness - interface with specular glossiness material properties.
+         * @returns - interface with metallic roughness material properties.
+         */
+        private static _ConvertSpecularGlossinessToMetallicRoughness(specularGlossiness);
+        /**
+         * Calculates the surface reflectance, independent of lighting conditions.
          * @param color - Color source to calculate brightness from.
          * @returns number representing the perceived brightness, or zero if color is undefined.
          */
-        static GetPerceivedBrightness(color: Color3): number;
+        private static _GetPerceivedBrightness(color);
         /**
          * Returns the maximum color component value.
          * @param color
          * @returns maximum color component value, or zero if color is null or undefined.
          */
-        static GetMaxComponent(color: Color3): number;
+        private static _GetMaxComponent(color);
         /**
          * Converts a Babylon PBR Metallic Roughness Material to a glTF Material.
          * @param babylonPBRMaterial - BJS PBR Metallic Roughness Material.
@@ -414,7 +465,7 @@ declare module BABYLON.GLTF2 {
          * @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.
          */
-        static ConvertPBRMaterial(babylonPBRMaterial: PBRMaterial, mimeType: ImageMimeType, images: IImage[], textures: ITexture[], materials: IMaterial[], imageData: {
+        static _ConvertPBRMaterial(babylonPBRMaterial: PBRMaterial, mimeType: ImageMimeType, images: IImage[], textures: ITexture[], materials: IMaterial[], imageData: {
             [fileName: string]: {
                 data: Uint8Array;
                 mimeType: ImageMimeType;
@@ -427,13 +478,19 @@ declare module BABYLON.GLTF2 {
          * @param images - Array of glTF images.
          * @param textures - Array of glTF textures.
          * @param imageData - map of image file name and data.
-         * @return - glTF texture, or null if the texture format is not supported.
+         * @return - glTF texture info, or null if the texture format is not supported.
          */
-        static ExportTexture(babylonTexture: BaseTexture, mimeType: ImageMimeType, images: IImage[], textures: ITexture[], imageData: {
-            [fileName: string]: {
-                data: Uint8Array;
-                mimeType: ImageMimeType;
-            };
-        }): Nullable<ITextureInfo>;
+        private static _ExportTexture(babylonTexture, mimeType, images, textures, imageData);
+        /**
+         * Builds a texture from base64 string.
+         * @param base64Texture - base64 texture string.
+         * @param textureName - Name to use for the texture.
+         * @param mimeType - image mime type for the texture.
+         * @param images - array of images.
+         * @param textures - array of textures.
+         * @param imageData - map of image data.
+         * @returns - glTF texture info, or null if the texture format is not supported.
+         */
+        private static _GetTextureInfoFromBase64(base64Texture, textureName, mimeType, images, textures, imageData);
     }
 }

+ 2 - 24
dist/preview release/typedocValidationBaseline.json

@@ -1,7 +1,7 @@
 {
-  "errors": 7193,
+  "errors": 7189,
   "babylon.typedoc.json": {
-    "errors": 7193,
+    "errors": 7189,
     "AnimationKeyInterpolation": {
       "Enumeration": {
         "Comments": {
@@ -16462,28 +16462,6 @@
             }
           }
         },
-        "Lerp": {
-          "Comments": {
-            "MissingReturn": true
-          },
-          "Parameter": {
-            "startValue": {
-              "Comments": {
-                "MissingText": true
-              }
-            },
-            "endValue": {
-              "Comments": {
-                "MissingText": true
-              }
-            },
-            "gradient": {
-              "Comments": {
-                "MissingText": true
-              }
-            }
-          }
-        },
         "LookAtLH": {
           "Comments": {
             "MissingReturn": true

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 68 - 68
dist/preview release/viewer/babylon.viewer.js


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 1222 - 664
dist/preview release/viewer/babylon.viewer.max.js


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

@@ -19,6 +19,7 @@
 ## Updates
 
 - Tons of functions and classes received the code comments they deserved (All the community)
+- Added support for 16bits TGA ([deltakosh](https://github.com/deltakosh))
 - New `AnimationPropertiesOverride` class used to simplify setting animation properties on child animations. [Documentation](http://doc.babylonjs.com/babylon101/animations#overriding-properties) ([deltakosh](https://github.com/deltakosh))
 - New `Texture.UseSerializedUrlIfAny` static property to let textures serialize complete URL instead of using side by side loading ([deltakosh](https://github.com/deltakosh))
 - Added `particleSystem.reset()` to clear a particle system ([deltakosh](https://github.com/deltakosh))
@@ -108,5 +109,5 @@
 
 - Removed the unused PostProcessRenderPass class and extended postProcessingRenderingEffect to support multiple PostProcesses ([trevordev](https://github.com/trevordev))
 - VertexData.merge no longer supports merging of data that do not have the same set of attributes. ([bghgary](https://github.com/bghgary)]
-- glTF 2.0 loader will now create a mesh for each primitive instead of merging the primitives together into one mesh. ([bghgary](https://github.com/bghgary)]
+- glTF 2.0 loader now creates a mesh for each primitive instead of merging the primitives together into one mesh. If a mesh only has one primitive, the behavior is the same as before. This change only affects meshes that have multiple primitives. ([bghgary](https://github.com/bghgary)]
 - Engine's onCanvasPointerOutObservable will now return a PointerEvent instead of the Engine. ([trevordev](https://github.com/trevordev))

+ 10 - 1
loaders/src/glTF/2.0/Extensions/MSFT_lod.ts

@@ -42,7 +42,10 @@ module BABYLON.GLTF2.Extensions {
                     const promise = this._loader._loadNodeAsync(`#/nodes/${nodeLOD._index}`, nodeLOD).then(() => {
                         if (indexLOD !== 0) {
                             const previousNodeLOD = nodeLODs[indexLOD - 1];
-                            previousNodeLOD._babylonMesh!.setEnabled(false);
+                            if (previousNodeLOD._babylonMesh) {
+                                previousNodeLOD._babylonMesh.dispose();
+                                delete previousNodeLOD._babylonMesh;
+                            }
                         }
 
                         if (indexLOD !== nodeLODs.length - 1) {
@@ -92,6 +95,12 @@ module BABYLON.GLTF2.Extensions {
                     const promise = this._loader._loadMaterialAsync(`#/materials/${materialLOD._index}`, materialLOD, babylonMesh, indexLOD === 0 ? assign : () => {}).then(() => {
                         if (indexLOD !== 0) {
                             assign(materialLOD._babylonMaterial!);
+
+                            const previousMaterialLOD = materialLODs[indexLOD - 1];
+                            if (previousMaterialLOD._babylonMaterial) {
+                                previousMaterialLOD._babylonMaterial.dispose();
+                                delete previousMaterialLOD._babylonMaterial;
+                            }
                         }
 
                         if (indexLOD !== materialLODs.length - 1) {

+ 39 - 32
loaders/src/glTF/2.0/babylon.glTFLoader.ts

@@ -307,8 +307,20 @@ module BABYLON.GLTF2 {
             return Promise.all(promises).then(() => {});
         }
 
-        private _getMeshes(): AbstractMesh[] {
-            const meshes = new Array<AbstractMesh>();
+        private _forEachNodeMesh(node: ILoaderNode, callback: (babylonMesh: Mesh) => void): void {
+            if (node._babylonMesh) {
+                callback(node._babylonMesh);
+            }
+
+            if (node._primitiveBabylonMeshes) {
+                for (const babylonMesh of node._primitiveBabylonMeshes) {
+                    callback(babylonMesh);
+                }
+            }
+        }
+
+        private _getMeshes(): Mesh[] {
+            const meshes = new Array<Mesh>();
 
             // Root mesh is always first.
             meshes.push(this._rootBabylonMesh);
@@ -316,15 +328,9 @@ module BABYLON.GLTF2 {
             const nodes = this._gltf.nodes;
             if (nodes) {
                 for (const node of nodes) {
-                    if (node._babylonMesh) {
-                        meshes.push(node._babylonMesh);
-                    }
-
-                    if (node._primitiveBabylonMeshes) {
-                        for (const babylonMesh of node._primitiveBabylonMeshes) {
-                            meshes.push(babylonMesh);
-                        }
-                    }
+                    this._forEachNodeMesh(node, mesh => {
+                        meshes.push(mesh);
+                    });
                 }
             }
 
@@ -397,7 +403,7 @@ module BABYLON.GLTF2 {
 
             if (node.mesh != undefined) {
                 const mesh = GLTFLoader._GetProperty(`${context}/mesh`, this._gltf.meshes, node.mesh);
-                promises.push(this._loadMeshAsync(`#/meshes/${mesh._index}`, node, mesh));
+                promises.push(this._loadMeshAsync(`#/meshes/${mesh._index}`, node, mesh, babylonMesh));
             }
 
             if (node.children) {
@@ -412,7 +418,7 @@ module BABYLON.GLTF2 {
             return Promise.all(promises).then(() => {});
         }
 
-        private _loadMeshAsync(context: string, node: ILoaderNode, mesh: ILoaderMesh): Promise<void> {
+        private _loadMeshAsync(context: string, node: ILoaderNode, mesh: ILoaderMesh, babylonMesh: Mesh): Promise<void> {
             // TODO: instancing
 
             const promises = new Array<Promise<void>>();
@@ -423,8 +429,18 @@ module BABYLON.GLTF2 {
             }
 
             ArrayItem.Assign(primitives);
-            for (const primitive of primitives) {
-                promises.push(this._loadPrimitiveAsync(context + "/primitives/" + primitive._index, node, mesh, primitive));
+            if (primitives.length === 1) {
+                const primitive = primitives[0];
+                promises.push(this._loadPrimitiveAsync(`${context}/primitives/${primitive._index}`, node, mesh, primitive, babylonMesh));
+            }
+            else {
+                node._primitiveBabylonMeshes = [];
+                for (const primitive of primitives) {
+                    const primitiveBabylonMesh = new Mesh(`${mesh.name || babylonMesh.name}_${primitive._index}`, this._babylonScene, babylonMesh);
+                    node._primitiveBabylonMeshes.push(babylonMesh);
+                    promises.push(this._loadPrimitiveAsync(`${context}/primitives/${primitive._index}`, node, mesh, primitive, primitiveBabylonMesh));
+                    this.onMeshLoadedObservable.notifyObservers(babylonMesh);
+                }
             }
 
             if (node.skin != undefined) {
@@ -433,22 +449,15 @@ module BABYLON.GLTF2 {
             }
 
             return Promise.all(promises).then(() => {
-                if (node._primitiveBabylonMeshes) {
-                    for (const primitiveBabylonMesh of node._primitiveBabylonMeshes) {
-                        primitiveBabylonMesh._refreshBoundingInfo(true);
-                    }
-                }
+                this._forEachNodeMesh(node, babylonMesh => {
+                    babylonMesh._refreshBoundingInfo(true);
+                });
             });
         }
 
-        private _loadPrimitiveAsync(context: string, node: ILoaderNode, mesh: ILoaderMesh, primitive: ILoaderMeshPrimitive): Promise<void> {
+        private _loadPrimitiveAsync(context: string, node: ILoaderNode, mesh: ILoaderMesh, primitive: ILoaderMeshPrimitive, babylonMesh: Mesh): Promise<void> {
             const promises = new Array<Promise<void>>();
 
-            const babylonMesh = new Mesh((mesh.name || node._babylonMesh!.name) + "_" + primitive._index, this._babylonScene, node._babylonMesh);
-
-            node._primitiveBabylonMeshes = node._primitiveBabylonMeshes || [];
-            node._primitiveBabylonMeshes[primitive._index] = babylonMesh;
-
             this._createMorphTargets(context, node, mesh, primitive, babylonMesh);
 
             promises.push(this._loadVertexDataAsync(context, primitive, babylonMesh).then(babylonVertexData => {
@@ -466,8 +475,6 @@ module BABYLON.GLTF2 {
                 }));
             }
 
-            this.onMeshLoadedObservable.notifyObservers(babylonMesh);
-
             return Promise.all(promises).then(() => {});
         }
 
@@ -703,9 +710,9 @@ module BABYLON.GLTF2 {
 
         private _loadSkinAsync(context: string, node: ILoaderNode, mesh: ILoaderMesh, skin: ILoaderSkin): Promise<void> {
             const assignSkeleton = () => {
-                for (const babylonMesh of node._primitiveBabylonMeshes!) {
+                this._forEachNodeMesh(node, babylonMesh => {
                     babylonMesh.skeleton = skin._babylonSkeleton;
-                }
+                });
 
                 node._babylonMesh!.parent = this._rootBabylonMesh;
                 node._babylonMesh!.position = Vector3.Zero();
@@ -957,10 +964,10 @@ module BABYLON.GLTF2 {
                             outTangent: key.outTangent ? key.outTangent[targetIndex] : undefined
                         })));
 
-                        for (const babylonMesh of targetNode._primitiveBabylonMeshes!) {
+                        this._forEachNodeMesh(targetNode, babylonMesh => {
                             const morphTarget = babylonMesh.morphTargetManager!.getTarget(targetIndex);
                             babylonAnimationGroup.addTargetedAnimation(babylonAnimation, morphTarget);
-                        }
+                        });
                     }
                 }
                 else {

+ 28 - 20
serializers/src/glTF/2.0/babylon.glTFMaterial.ts

@@ -641,7 +641,7 @@ module BABYLON.GLTF2 {
                     baseColorBuffer[destinationOffset + 1] /= metallicRoughnessFactors.baseColor.g > this._epsilon ? metallicRoughnessFactors.baseColor.g : 1;
                     baseColorBuffer[destinationOffset + 2] /= metallicRoughnessFactors.baseColor.b > this._epsilon ? metallicRoughnessFactors.baseColor.b : 1;
 
-                    const baseColorPixel = Color3.FromArray([baseColorBuffer[destinationOffset], baseColorBuffer[destinationOffset + 1], baseColorBuffer[destinationOffset + 2]]);
+                    const baseColorPixel = new Color3(baseColorBuffer[destinationOffset], baseColorBuffer[destinationOffset + 1], baseColorBuffer[destinationOffset + 2]);
 
                     if (!this.FuzzyEquals(baseColorPixel, Color3.White(), this._epsilon)) {
                         writeOutBaseColorTexture = true;
@@ -650,7 +650,7 @@ module BABYLON.GLTF2 {
                     metallicRoughnessBuffer[destinationOffset + 1] /= metallicRoughnessFactors.roughness > this._epsilon ? metallicRoughnessFactors.roughness : 1;
                     metallicRoughnessBuffer[destinationOffset + 2] /= metallicRoughnessFactors.metallic > this._epsilon ? metallicRoughnessFactors.metallic : 1;
 
-                    const metallicRoughnessPixel = Color3.FromArray([metallicRoughnessBuffer[destinationOffset], metallicRoughnessBuffer[destinationOffset + 1], metallicRoughnessBuffer[destinationOffset + 2]]);
+                    const metallicRoughnessPixel = new Color3(metallicRoughnessBuffer[destinationOffset], metallicRoughnessBuffer[destinationOffset + 1], metallicRoughnessBuffer[destinationOffset + 2]);
 
                     if (!this.FuzzyEquals(metallicRoughnessPixel, Color3.White(), this._epsilon)) {
                         writeOutMetallicRoughnessTexture = true;
@@ -752,36 +752,44 @@ module BABYLON.GLTF2 {
                     metallicRoughness = this._ConvertSpecularGlossinessToMetallicRoughness(specGloss);
                 }
                 else {
-                    if (metallicRoughness.baseColorTextureBase64) {
-                        const glTFBaseColorTexture = _GLTFMaterial._GetTextureInfoFromBase64(metallicRoughness.baseColorTextureBase64, "bjsBaseColorTexture_" + (textures.length) + ".png", mimeType, images, textures, imageData);
-                        if (glTFBaseColorTexture != null) {
-                            glTFPbrMetallicRoughness.baseColorTexture = glTFBaseColorTexture;
+                    if (hasTextureCoords) {
+                        if (metallicRoughness.baseColorTextureBase64) {
+                            const glTFBaseColorTexture = _GLTFMaterial._GetTextureInfoFromBase64(metallicRoughness.baseColorTextureBase64, "bjsBaseColorTexture_" + (textures.length) + ".png", mimeType, images, textures, imageData);
+                            if (glTFBaseColorTexture != null) {
+                                glTFPbrMetallicRoughness.baseColorTexture = glTFBaseColorTexture;
+                            }
                         }
-                    }
-                    if (metallicRoughness.metallicRoughnessTextureBase64) {
-                        const glTFMRColorTexture = _GLTFMaterial._GetTextureInfoFromBase64(metallicRoughness.metallicRoughnessTextureBase64, "bjsMetallicRoughnessTexture_" + (textures.length) + ".png", mimeType, images, textures, imageData);
-                        if (glTFMRColorTexture != null) {
-                            glTFPbrMetallicRoughness.metallicRoughnessTexture = glTFMRColorTexture;
+                        if (metallicRoughness.metallicRoughnessTextureBase64) {
+                            const glTFMRColorTexture = _GLTFMaterial._GetTextureInfoFromBase64(metallicRoughness.metallicRoughnessTextureBase64, "bjsMetallicRoughnessTexture_" + (textures.length) + ".png", mimeType, images, textures, imageData);
+                            if (glTFMRColorTexture != null) {
+                                glTFPbrMetallicRoughness.metallicRoughnessTexture = glTFMRColorTexture;
+                            }
                         }
                     }
                 }
             }
+            else {
+                metallicRoughness = {
+                    baseColor: babylonPBRMaterial.albedoColor,
+                    metallic: babylonPBRMaterial.metallic,
+                    roughness: babylonPBRMaterial.roughness
+                };
+            }
 
-            if (!(this.FuzzyEquals(babylonPBRMaterial.albedoColor, Color3.White(), this._epsilon) && babylonPBRMaterial.alpha >= this._epsilon)) {
+            if (!(this.FuzzyEquals(metallicRoughness.baseColor, Color3.White(), this._epsilon) && babylonPBRMaterial.alpha >= this._epsilon)) {
                 glTFPbrMetallicRoughness.baseColorFactor = [
-                    babylonPBRMaterial.albedoColor.r,
-                    babylonPBRMaterial.albedoColor.g,
-                    babylonPBRMaterial.albedoColor.b,
+                    metallicRoughness.baseColor.r,
+                    metallicRoughness.baseColor.g,
+                    metallicRoughness.baseColor.b,
                     babylonPBRMaterial.alpha
                 ];
             }
 
-
-            if (babylonPBRMaterial.metallic != null && babylonPBRMaterial.metallic !== 1) {
-                glTFPbrMetallicRoughness.metallicFactor = babylonPBRMaterial.metallic;
+            if (metallicRoughness.metallic != null && metallicRoughness.metallic !== 1) {
+                glTFPbrMetallicRoughness.metallicFactor = metallicRoughness.metallic;
             }
-            if (babylonPBRMaterial.roughness != null && babylonPBRMaterial.roughness !== 1) {
-                glTFPbrMetallicRoughness.roughnessFactor = babylonPBRMaterial.roughness;
+            if (metallicRoughness.roughness != null && metallicRoughness.roughness !== 1) {
+                glTFPbrMetallicRoughness.roughnessFactor = metallicRoughness.roughness;
             }
 
             if (babylonPBRMaterial.backFaceCulling != null && !babylonPBRMaterial.backFaceCulling) {

+ 1 - 0
src/Cameras/VR/babylon.vrExperienceHelper.ts

@@ -157,6 +157,7 @@ module BABYLON {
             makeNotPick(mesh);
             var childMeshes = mesh.getChildMeshes();
 
+            this.webVRController._pointingPoseNode = null;
             for (var i = 0; i < childMeshes.length; i++) {
                 if (childMeshes[i].name && childMeshes[i].name.indexOf(PoseEnabledController.POINTING_POSE) >= 0) {
                     mesh = childMeshes[i];

+ 53 - 0
src/Materials/babylon.effect.ts

@@ -288,6 +288,11 @@
 
             this.uniqueId = Effect._uniqueIdSeed++;
 
+            if (this._getFromCache(baseName)) {
+                this._prepareEffect();
+                return;
+            }
+
             var vertexSource: any;
             var fragmentSource: any;
 
@@ -336,10 +341,58 @@
                     this._vertexSourceCode = finalVertexCode;
                     this._fragmentSourceCode = migratedFragmentCode;
                 }
+
+                this._setInCache(baseName);
                 this._prepareEffect(); 
             });
         }
 
+        private static _sourceCache: { [baseName: string]: { vertex: string, fragment: string } } = { };
+
+        private _getSourceCacheKey(baseName: string): string {
+            let cacheKey: string = baseName;
+            if (this._indexParameters) {
+                for (let key in this._indexParameters) {
+                    if (this._indexParameters.hasOwnProperty(key)) {
+                        cacheKey += "|";
+                        cacheKey += key
+                        cacheKey += "_";
+                        cacheKey += this._indexParameters[key];
+                    }
+                }
+            }
+
+            return cacheKey;
+        }
+
+        private _getFromCache(baseName: string): boolean {
+            if (typeof baseName !== "string") {
+                return false;
+            }
+
+            let cacheKey = this._getSourceCacheKey(baseName);
+            let sources = Effect._sourceCache[cacheKey];
+            if (!sources) {
+                return false;
+            }
+
+            this._vertexSourceCode = sources.vertex;
+            this._fragmentSourceCode = sources.fragment;
+            return true;
+        }
+
+        private _setInCache(baseName: string): void {
+            if (typeof baseName !== "string") {
+                return;
+            }
+
+            let cacheKey = this._getSourceCacheKey(baseName);
+            Effect._sourceCache[cacheKey] = {
+                vertex: this._vertexSourceCode,
+                fragment: this._fragmentSourceCode
+            };
+        }
+
         /**
          * Unique key for this effect
          */

+ 19 - 3
src/Math/babylon.math.ts

@@ -4369,17 +4369,33 @@
                 0.0, 0.0, 1.0, 0.0,
                 x, y, z, 1.0, result);
         }
+
         /**
-         * Returns a new Matrix whose values are the interpolated values for "gradien" (float) between the ones of the matrices "startValue" and "endValue".
+         * Returns a new Matrix whose values are the interpolated values for "gradient" (float) between the ones of the matrices "startValue" and "endValue".
+         * @param startValue defines the start value
+         * @param endValue defines the end value
+         * @param gradient defines the gradient factor
+         * @returns the new matrix
          */
         public static Lerp(startValue: Matrix, endValue: Matrix, gradient: number): Matrix {
             var result = Matrix.Zero();
+            Matrix.LerpToRef(startValue, endValue, gradient, result);
+            return result;
+        }
+
+        /**
+         * Set the passed matrix "result" as the interpolated values for "gradient" (float) between the ones of the matrices "startValue" and "endValue".
+         * @param startValue defines the start value
+         * @param endValue defines the end value
+         * @param gradient defines the gradient factor
+         * @param result defines the Matrix object where to store data
+         */
+        public static LerpToRef(startValue: Matrix, endValue: Matrix, gradient: number, result: Matrix): void {
             for (var index = 0; index < 16; index++) {
                 result.m[index] = startValue.m[index] * (1.0 - gradient) + endValue.m[index] * gradient;
             }
             result._markAsUpdated();
-            return result;
-        }
+        }        
 
         /**
          * Returns a new Matrix whose values are computed by : 

+ 4 - 0
src/Mesh/Compression/babylon.dracoCompression.ts

@@ -188,6 +188,10 @@ module BABYLON {
         }
 
         private static _GetDefaultDecoderUrl(): Nullable<string> {
+            if (!Tools.IsWindowObjectExist) {
+                return null;
+            }
+
             for (let i = 0; i < document.scripts.length; i++) {
                 if (document.scripts[i].type === "text/x-draco-decoder") {
                     return document.scripts[i].src;

+ 14 - 0
src/Particles/babylon.gpuParticleSystem.ts

@@ -241,6 +241,12 @@
         }
 
         /**
+         * Forces the particle to write their depth information to the depth buffer. This can help preventing other draw calls
+         * to override the particles.
+         */
+        public forceDepthWrite = false;        
+
+        /**
          * Gets or set the number of active particles
          */
         public get activeParticleCount(): number {
@@ -582,6 +588,10 @@
                 this._engine.setAlphaMode(Engine.ALPHA_COMBINE);
             }            
 
+            if (this.forceDepthWrite) {
+                this._engine.setDepthWrite(true);
+            }
+
             // Bind source VAO
             this._engine.bindVertexArrayObject(this._renderVAO[this._targetIndex], null);
 
@@ -626,6 +636,10 @@
         }
 
         private _releaseVAOs() {
+            if (!this._updateVAO) {
+                return;
+            }
+            
             for (var index = 0; index < this._updateVAO.length; index++) {
                 this._engine.releaseVertexArrayObject(this._updateVAO[index]);
             }

+ 6 - 7
src/PostProcess/RenderPipeline/Pipelines/babylon.defaultRenderingPipeline.ts

@@ -413,13 +413,6 @@
             this._prevPostProcess = null;
             this._prevPrevPostProcess = null;
 
-            if (this.fxaaEnabled) {
-                this.fxaa = new FxaaPostProcess("fxaa", 1.0, null, Texture.BILINEAR_SAMPLINGMODE, engine, false, this._defaultPipelineTextureType);
-                this.addEffect(new PostProcessRenderEffect(engine, this.FxaaPostProcessId, () => { return this.fxaa; }, true));
-                this._setAutoClearAndTextureSharing(this.fxaa);
-                
-            }
-
             if (this.sharpenEnabled) {
                 this.addEffect(this._sharpenEffect);
                 this._setAutoClearAndTextureSharing(this.sharpen);
@@ -509,6 +502,12 @@
                 }
             }
 
+            if (this.fxaaEnabled) {
+                this.fxaa = new FxaaPostProcess("fxaa", 1.0, null, Texture.BILINEAR_SAMPLINGMODE, engine, false, this._defaultPipelineTextureType);
+                this.addEffect(new PostProcessRenderEffect(engine, this.FxaaPostProcessId, () => { return this.fxaa; }, true));
+                this._setAutoClearAndTextureSharing(this.fxaa);
+            }
+
             if (this.chromaticAberrationEnabled) {
                 this.addEffect(this._chromaticAberrationEffect);
                 this._setAutoClearAndTextureSharing(this.chromaticAberration);

+ 1 - 1
src/Shaders/gpuRenderParticles.vertex.fx

@@ -30,7 +30,7 @@ void main() {
 
   // Expand position
   vec4 viewPosition = view * vec4(position, 1.0);
-  gl_Position = projection * (viewPosition + vec4(offset * size, 0, 1.0));
+  gl_Position = projection * (viewPosition + vec4(offset * size, 0., 0.));
 
 	// Clip plane
 #ifdef CLIPPLANE

+ 7 - 3
src/Tools/babylon.tga.ts

@@ -225,9 +225,13 @@
             for (y = y_start; y !== y_end; y += y_step) {
                 for (x = x_start; x !== x_end; x += x_step, i += 2) {
                     color = image[i + 0] + (image[i + 1] << 8); // Inversed ?
-                    imageData[(x + width * y) * 4 + 0] = (color & 0x7C00) >> 7;
-                    imageData[(x + width * y) * 4 + 1] = (color & 0x03E0) >> 2;
-                    imageData[(x + width * y) * 4 + 2] = (color & 0x001F) >> 3;
+                    let r = (((color & 0x7C00) >> 10) * 255) / 0x1F | 0;
+                    let g = (((color & 0x03E0) >> 5) * 255) / 0x1F | 0;
+                    let b = ((color & 0x001F) * 255) / 0x1F | 0;
+
+                    imageData[(x + width * y) * 4 + 0] = r;
+                    imageData[(x + width * y) * 4 + 1] = g;
+                    imageData[(x + width * y) * 4 + 2] = b;
                     imageData[(x + width * y) * 4 + 3] = (color & 0x8000) ? 0 : 255;
                 }
             }

+ 54 - 34
tests/unit/babylon/src/Loading/babylon.sceneLoader.tests.ts

@@ -40,7 +40,7 @@ describe('Babylon Scene Loader', function () {
         it('Load BoomBox', () => {
             const scene = new BABYLON.Scene(subject);
             return BABYLON.SceneLoader.AppendAsync("/Playground/scenes/BoomBox/", "BoomBox.gltf", scene).then(scene => {
-                expect(scene.meshes.length, "scene.meshes.length").to.equal(3);
+                expect(scene.meshes.length, "scene.meshes.length").to.equal(2);
                 expect(scene.materials.length, "scene.materials.length").to.equal(1);
             });
         });
@@ -48,7 +48,7 @@ describe('Babylon Scene Loader', function () {
         it('Load BoomBox GLB', () => {
             const scene = new BABYLON.Scene(subject);
             return BABYLON.SceneLoader.AppendAsync("/Playground/scenes/", "BoomBox.glb", scene).then(scene => {
-                expect(scene.meshes.length, "scene.meshes.length").to.equal(3);
+                expect(scene.meshes.length, "scene.meshes.length").to.equal(2);
                 expect(scene.materials.length, "scene.materials.length").to.equal(1);
             });
         });
@@ -161,6 +161,12 @@ describe('Babylon Scene Loader', function () {
 
             const scene = new BABYLON.Scene(subject);
             promises.push(BABYLON.SceneLoader.AppendAsync("/Playground/scenes/BoomBox/", "BoomBox.gltf", scene).then(() => {
+                for (const mesh of scene.meshes) {
+                    if (mesh.material) {
+                        expect(mesh.material.isReady(mesh)).to.be.true;
+                    }
+                }
+
                 createShaderProgramSpy = sinon.spy(subject, "createShaderProgram");
             }));
 
@@ -200,14 +206,14 @@ describe('Babylon Scene Loader', function () {
                 expect(result.skeletons.length, "skeletons.length").to.equal(scene.skeletons.length);
 
                 const mapping = {
-                    "AlienHead_0": "skeleton0",
-                    "Collar_0": "skeleton1",
-                    "LeftEye_0": "skeleton2",
-                    "RightEye_0": "skeleton3",
-                    "CollarClasp_0": "skeleton1",
-                    "Shirt_0": "skeleton1",
-                    "ShirtPlate_0": "skeleton1",
-                    "Teeth_0": "skeleton1",
+                    "AlienHead": "skeleton0",
+                    "Collar": "skeleton1",
+                    "LeftEye": "skeleton2",
+                    "RightEye": "skeleton3",
+                    "CollarClasp": "skeleton1",
+                    "Shirt": "skeleton1",
+                    "ShirtPlate": "skeleton1",
+                    "Teeth": "skeleton1",
                 };
 
                 for (const meshName in mapping) {
@@ -220,45 +226,59 @@ describe('Babylon Scene Loader', function () {
         it('Load TwoQuads with LODs', () => {
             const scene = new BABYLON.Scene(subject);
             const promises = new Array<Promise<void>>();
-            const materials: { [name: string]: BABYLON.Material } = {};
 
             subject.runRenderLoop(() => {
                 for (const mesh of scene.meshes) {
                     if (mesh.material && mesh.isEnabled()) {
-                        expect(mesh.material.getActiveTextures().every(texture => texture.isReady()), "active mesh material textures are ready").to.be.true;
+                        expect(mesh.material.isReady(mesh), "mesh material is ready").to.be.true;
                     }
                 }
             });
 
             BABYLON.SceneLoader.OnPluginActivatedObservable.add((loader: BABYLON.GLTFFileLoader) => {
-                loader.onMaterialLoaded = material => {
-                    expect(materials[material.name], `materials["${material.name}"]`).to.be.undefined;
-                    materials[material.name] = material;
-                };
+                loader.compileMaterials = true;
 
                 promises.push(loader.whenCompleteAsync().then(() => {
-                    expect(materials["LOD0"].getActiveTextures().every(texture => texture.isReady()), "All textures of LOD 0 ready").to.be.true;
-                    expect(materials["LOD1"].getActiveTextures().every(texture => texture.isReady()), "All textures of LOD 1 ready").to.be.true;
-                    expect(materials["LOD2"].getActiveTextures().every(texture => texture.isReady()), "All textures of LOD 2 ready").to.be.true;
+                    const meshes = [
+                        scene.getMeshByName("node0"),
+                        scene.getMeshByName("node1")
+                    ];
+
+                    expect(meshes[0].material.name, "Material for node 0").to.equal("LOD0");
+                    expect(meshes[1].material.name, "Material for node 1").to.equal("LOD0");
+
+                    expect(scene.materials, "scene.materials").to.have.lengthOf(1);
+                    const materials = [
+                        scene.getMaterialByName("LOD0")
+                    ];
 
-                    expect(scene.getMeshByName("node0_0").material.name, "node 0 primitive 0 material").to.equal("LOD0");
-                    expect(scene.getMeshByName("node1_0").material.name, "node 1 primitive 0 material").to.equal("LOD0");
+                    expect(materials[0].isReady(meshes[0]), "Material of LOD 0 is ready for node 0").to.be.true;
+                    expect(materials[0].isReady(meshes[1]), "Material of LOD 0 is ready for node 1").to.be.true;
                 }));
             }, undefined, undefined, undefined, true);
 
             promises.push(BABYLON.SceneLoader.AppendAsync("/Playground/scenes/TwoQuads/", "TwoQuads.gltf", scene).then(() => {
-                expect(Object.keys(materials), "materials").to.have.lengthOf(3);
-
-                expect(materials["LOD0"].getActiveTextures(), "material LOD 0 active textures").to.have.lengthOf(1);
-                expect(materials["LOD1"].getActiveTextures(), "material LOD 1 active textures").to.have.lengthOf(1);
-                expect(materials["LOD2"].getActiveTextures(), "material LOD 2 active textures").to.have.lengthOf(1);
-
-                expect(materials["LOD0"].getActiveTextures().some(texture => texture.isReady()), "Some textures of LOD 0 ready").to.be.false;
-                expect(materials["LOD1"].getActiveTextures().some(texture => texture.isReady()), "Some textures of LOD 1 ready").to.be.false;
-                expect(materials["LOD2"].getActiveTextures().every(texture => texture.isReady()), "All textures of LOD 2 ready").to.be.true;
-
-                expect(scene.getMeshByName("node0_0").material.name, "node 0 primitive 0 material").to.equal("LOD2");
-                expect(scene.getMeshByName("node1_0").material.name, "node 1 primitive 0 material").to.equal("LOD2");
+                const meshes = [
+                    scene.getMeshByName("node0"),
+                    scene.getMeshByName("node1")
+                ];
+
+                expect(meshes[0].material.name, "Material for node 0").to.equal("LOD2");
+                expect(meshes[1].material.name, "Material for node 1").to.equal("LOD2");
+
+                expect(scene.materials, "scene.materials").to.have.lengthOf(3);
+                const materials = [
+                    scene.getMaterialByName("LOD0"),
+                    scene.getMaterialByName("LOD1"),
+                    scene.getMaterialByName("LOD2")
+                ];
+
+                expect(materials[0].isReady(meshes[0]), "Material of LOD 0 is ready for node 0").to.be.false;
+                expect(materials[0].isReady(meshes[1]), "Material of LOD 0 is ready for node 1").to.be.false;
+                expect(materials[1].isReady(meshes[0]), "Material of LOD 1 is ready for node 0").to.be.false;
+                expect(materials[1].isReady(meshes[1]), "Material of LOD 1 is ready for node 1").to.be.false;
+                expect(materials[2].isReady(meshes[0]), "Material of LOD 2 is ready for node 0").to.be.true;
+                expect(materials[2].isReady(meshes[1]), "Material of LOD 2 is ready for node 1").to.be.true;
             }));
 
             return Promise.all(promises);
@@ -275,7 +295,7 @@ describe('Babylon Scene Loader', function () {
         it('should be loaded from BoomBox GLTF', () => {
             var scene = new BABYLON.Scene(subject);
             return BABYLON.SceneLoader.LoadAssetContainerAsync("/Playground/scenes/BoomBox/", "BoomBox.gltf", scene).then(container => {
-                expect(container.meshes.length).to.eq(3);
+                expect(container.meshes.length).to.eq(2);
             });
         });
         it('should be adding and removing objects from scene', () => {