Browse Source

Merge remote-tracking branch 'upstream/master'

Sebastien Vandenberghe 7 năm trước cách đây
mục cha
commit
557bc34c13
87 tập tin đã thay đổi với 24538 bổ sung24453 xóa
  1. 8575 8546
      Playground/babylon.d.txt
  2. 8612 8578
      dist/preview release/babylon.d.ts
  3. 43 43
      dist/preview release/babylon.js
  4. 126 98
      dist/preview release/babylon.max.js
  5. 43 43
      dist/preview release/babylon.worker.js
  6. 5937 5903
      dist/preview release/customConfigurations/minimalGLTFViewer/babylon.d.ts
  7. 45 45
      dist/preview release/customConfigurations/minimalGLTFViewer/babylon.js
  8. 139 115
      dist/preview release/customConfigurations/minimalGLTFViewer/babylon.max.js
  9. 139 115
      dist/preview release/customConfigurations/minimalGLTFViewer/es6.js
  10. 126 98
      dist/preview release/es6.js
  11. 4 4
      dist/preview release/inspector/babylon.inspector.bundle.js
  12. 2 0
      dist/preview release/inspector/babylon.inspector.d.ts
  13. 6 4
      dist/preview release/inspector/babylon.inspector.js
  14. 4 4
      dist/preview release/inspector/babylon.inspector.min.js
  15. 1 1
      dist/preview release/loaders/babylon.glTF2FileLoader.d.ts
  16. 13 17
      dist/preview release/loaders/babylon.glTF2FileLoader.js
  17. 2 2
      dist/preview release/loaders/babylon.glTF2FileLoader.min.js
  18. 1 1
      dist/preview release/loaders/babylon.glTFFileLoader.d.ts
  19. 13 17
      dist/preview release/loaders/babylon.glTFFileLoader.js
  20. 2 2
      dist/preview release/loaders/babylon.glTFFileLoader.min.js
  21. 13 17
      dist/preview release/loaders/babylonjs.loaders.js
  22. 3 3
      dist/preview release/loaders/babylonjs.loaders.min.js
  23. 1 1
      dist/preview release/loaders/babylonjs.loaders.module.d.ts
  24. 1 1
      dist/preview release/materialsLibrary/babylon.cellMaterial.js
  25. 1 1
      dist/preview release/materialsLibrary/babylon.cellMaterial.min.js
  26. 1 0
      dist/preview release/materialsLibrary/babylon.customMaterial.d.ts
  27. 4 1
      dist/preview release/materialsLibrary/babylon.customMaterial.js
  28. 2 2
      dist/preview release/materialsLibrary/babylon.customMaterial.min.js
  29. 1 1
      dist/preview release/materialsLibrary/babylon.fireMaterial.js
  30. 1 1
      dist/preview release/materialsLibrary/babylon.fireMaterial.min.js
  31. 1 1
      dist/preview release/materialsLibrary/babylon.furMaterial.js
  32. 1 1
      dist/preview release/materialsLibrary/babylon.furMaterial.min.js
  33. 1 1
      dist/preview release/materialsLibrary/babylon.gradientMaterial.js
  34. 1 1
      dist/preview release/materialsLibrary/babylon.gradientMaterial.min.js
  35. 1 1
      dist/preview release/materialsLibrary/babylon.lavaMaterial.js
  36. 1 1
      dist/preview release/materialsLibrary/babylon.lavaMaterial.min.js
  37. 1 1
      dist/preview release/materialsLibrary/babylon.normalMaterial.js
  38. 1 1
      dist/preview release/materialsLibrary/babylon.normalMaterial.min.js
  39. 1 1
      dist/preview release/materialsLibrary/babylon.shadowOnlyMaterial.js
  40. 1 1
      dist/preview release/materialsLibrary/babylon.shadowOnlyMaterial.min.js
  41. 1 1
      dist/preview release/materialsLibrary/babylon.simpleMaterial.js
  42. 1 1
      dist/preview release/materialsLibrary/babylon.simpleMaterial.min.js
  43. 1 1
      dist/preview release/materialsLibrary/babylon.terrainMaterial.js
  44. 1 1
      dist/preview release/materialsLibrary/babylon.terrainMaterial.min.js
  45. 1 1
      dist/preview release/materialsLibrary/babylon.triPlanarMaterial.js
  46. 1 1
      dist/preview release/materialsLibrary/babylon.triPlanarMaterial.min.js
  47. 1 1
      dist/preview release/materialsLibrary/babylon.waterMaterial.js
  48. 1 1
      dist/preview release/materialsLibrary/babylon.waterMaterial.min.js
  49. 15 12
      dist/preview release/materialsLibrary/babylonjs.materials.js
  50. 7 7
      dist/preview release/materialsLibrary/babylonjs.materials.min.js
  51. 1 0
      dist/preview release/materialsLibrary/babylonjs.materials.module.d.ts
  52. 2 149
      dist/preview release/typedocValidationBaseline.json
  53. 48 48
      dist/preview release/viewer/babylon.viewer.js
  54. 2 2
      dist/preview release/what's new.md
  55. 7 6
      inspector/src/Inspector.ts
  56. 0 1
      inspector/src/adapters/MeshAdapter.ts
  57. 12 6
      inspector/src/scheduler/Scheduler.ts
  58. 11 13
      loaders/src/glTF/2.0/babylon.glTFLoader.ts
  59. 1 1
      loaders/src/glTF/2.0/babylon.glTFLoaderInterfaces.ts
  60. 22 22
      materialsLibrary/src/cell/babylon.cellMaterial.ts
  61. 5 1
      materialsLibrary/src/custom/babylon.customMaterial.ts
  62. 54 54
      materialsLibrary/src/fire/babylon.fireMaterial.ts
  63. 73 73
      materialsLibrary/src/fur/babylon.furMaterial.ts
  64. 19 19
      materialsLibrary/src/gradient/babylon.gradientMaterial.ts
  65. 29 29
      materialsLibrary/src/lava/babylon.lavaMaterial.ts
  66. 23 23
      materialsLibrary/src/normal/babylon.normalMaterial.ts
  67. 18 18
      materialsLibrary/src/shadowOnly/babylon.shadowOnlyMaterial.ts
  68. 27 27
      materialsLibrary/src/simple/babylon.simpleMaterial.ts
  69. 39 39
      materialsLibrary/src/terrain/babylon.terrainMaterial.ts
  70. 49 49
      materialsLibrary/src/triPlanar/babylon.triPlanarMaterial.ts
  71. 6 6
      materialsLibrary/src/water/babylon.waterMaterial.ts
  72. 19 10
      src/Animations/babylon.animationGroup.ts
  73. 23 23
      src/Debug/babylon.rayHelper.ts
  74. 80 79
      src/Engine/babylon.engine.ts
  75. 1 1
      src/Engine/babylon.nullEngine.ts
  76. 1 1
      src/Materials/Background/babylon.backgroundMaterial.ts
  77. 1 1
      src/Materials/PBR/babylon.pbrBaseMaterial.ts
  78. 5 8
      src/Materials/babylon.material.ts
  79. 10 2
      src/Materials/babylon.materialHelper.ts
  80. 1 1
      src/Materials/babylon.shaderMaterial.ts
  81. 1 1
      src/Materials/babylon.standardMaterial.ts
  82. 0 8
      src/Mesh/babylon.mesh.ts
  83. 0 2
      src/PostProcess/babylon.volumetricLightScatteringPostProcess.ts
  84. 14 20
      src/Rendering/babylon.renderingGroup.ts
  85. 20 0
      src/Tools/babylon.tools.ts
  86. 5 1
      src/babylon.mixins.ts
  87. 8 8
      tests/validation/validation.js

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 8575 - 8546
Playground/babylon.d.txt


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 8612 - 8578
dist/preview release/babylon.d.ts


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 43 - 43
dist/preview release/babylon.js


+ 126 - 98
dist/preview release/babylon.max.js

@@ -7483,6 +7483,26 @@ var BABYLON;
             }
             Tools.EncodeScreenshotCanvasData(successCallback, mimeType);
         };
+        /**
+         * Generates an image screenshot from the specified camera.
+         *
+         * @param engine The engine to use for rendering
+         * @param camera The camera to use for rendering
+         * @param size This parameter can be set to a single number or to an object with the
+         * following (optional) properties: precision, width, height. If a single number is passed,
+         * it will be used for both width and height. If an object is passed, the screenshot size
+         * will be derived from the parameters. The precision property is a multiplier allowing
+         * rendering at a higher or lower resolution.
+         * @param successCallback The callback receives a single parameter which contains the
+         * screenshot as a string of base64-encoded characters. This string can be assigned to the
+         * src parameter of an <img> to display it.
+         * @param mimeType The MIME type of the screenshot image (default: image/png).
+         * Check your browser for supported MIME types.
+         * @param samples Texture samples (default: 1)
+         * @param antialiasing Whether antialiasing should be turned on or not (default: false)
+         * @param fileName A name for for the downloaded file.
+         * @constructor
+         */
         Tools.CreateScreenshotUsingRenderTarget = function (engine, camera, size, successCallback, mimeType, samples, antialiasing, fileName) {
             if (mimeType === void 0) { mimeType = "image/png"; }
             if (samples === void 0) { samples = 1; }
@@ -8885,9 +8905,10 @@ var BABYLON;
     var Engine = /** @class */ (function () {
         /**
          * @constructor
-         * @param {HTMLCanvasElement | WebGLRenderingContext} canvasOrContext - the canvas or the webgl context to be used for rendering
-         * @param {boolean} [antialias] - enable antialias
-         * @param options - further options to be sent to the getContext function
+         * @param canvasOrContext defines the canvas or WebGL context to use for rendering
+         * @param antialias defines enable antialiasing (default: false)
+         * @param options defines further options to be sent to the getContext() function
+         * @param adaptToDeviceRatio defines whether to adapt to the device's viewport characteristics (default: false)
          */
         function Engine(canvasOrContext, antialias, options, adaptToDeviceRatio) {
             if (adaptToDeviceRatio === void 0) { adaptToDeviceRatio = false; }
@@ -8989,6 +9010,8 @@ var BABYLON;
             this._alphaMode = Engine.ALPHA_DISABLE;
             // Cache
             this._internalTexturesCache = new Array();
+            this._activeChannel = 0;
+            this._currentTextureChannel = -1;
             this._boundTexturesCache = {};
             this._boundTexturesStack = new Array();
             this._compiledEffects = {};
@@ -9904,7 +9927,7 @@ var BABYLON;
             for (var slot = 0; slot < this._maxSimultaneousTextures; slot++) {
                 this._nextFreeTextureSlots.push(slot);
             }
-            this._activeChannel = -1;
+            this._currentTextureChannel = -1;
         };
         Engine.prototype.isDeterministicLockStep = function () {
             return this._deterministicLockstep;
@@ -11294,12 +11317,6 @@ var BABYLON;
         Engine.prototype.getAlphaMode = function () {
             return this._alphaMode;
         };
-        Engine.prototype.setAlphaTesting = function (enable) {
-            this._alphaTest = enable;
-        };
-        Engine.prototype.getAlphaTesting = function () {
-            return !!this._alphaTest;
-        };
         // Textures
         Engine.prototype.wipeCaches = function (bruteForce) {
             if (this.preventCacheWipeBetweenFrames && !bruteForce) {
@@ -12687,12 +12704,6 @@ var BABYLON;
             }
             this._currentEffect = null;
         };
-        Engine.prototype._activateTextureChannel = function (channel) {
-            if (this._activeChannel !== channel && channel > -1) {
-                this._gl.activeTexture(this._gl.TEXTURE0 + channel);
-                this._activeChannel = channel;
-            }
-        };
         Engine.prototype._moveBoundTextureOnTop = function (internalTexture) {
             var index = this._boundTexturesStack.indexOf(internalTexture);
             if (index > -1 && index !== this._boundTexturesStack.length - 1) {
@@ -12700,6 +12711,34 @@ var BABYLON;
                 this._boundTexturesStack.push(internalTexture);
             }
         };
+        Engine.prototype._getCorrectTextureChannel = function (channel, internalTexture) {
+            if (!internalTexture) {
+                return -1;
+            }
+            internalTexture._initialSlot = channel;
+            if (this.disableTextureBindingOptimization) {
+                if (channel !== internalTexture._designatedSlot) {
+                    this._textureCollisions.addCount(1, false);
+                }
+            }
+            else {
+                if (channel !== internalTexture._designatedSlot) {
+                    if (internalTexture._designatedSlot > -1) {
+                        return internalTexture._designatedSlot;
+                    }
+                    else {
+                        // No slot for this texture, let's pick a new one (if we find a free slot)
+                        if (this._nextFreeTextureSlots.length) {
+                            return this._nextFreeTextureSlots[0];
+                        }
+                        // We need to recycle the oldest bound texture, sorry.
+                        this._textureCollisions.addCount(1, false);
+                        return this._removeDesignatedSlot(this._boundTexturesStack[0]);
+                    }
+                }
+            }
+            return channel;
+        };
         Engine.prototype._removeDesignatedSlot = function (internalTexture) {
             var currentSlot = internalTexture._designatedSlot;
             internalTexture._designatedSlot = -1;
@@ -12713,31 +12752,42 @@ var BABYLON;
             }
             return currentSlot;
         };
-        Engine.prototype._bindTextureDirectly = function (target, texture, doNotBindUniformToTextureChannel) {
-            if (doNotBindUniformToTextureChannel === void 0) { doNotBindUniformToTextureChannel = false; }
+        Engine.prototype._activateCurrentTexture = function () {
+            if (this._currentTextureChannel !== this._activeChannel) {
+                this._gl.activeTexture(this._gl.TEXTURE0 + this._activeChannel);
+                this._currentTextureChannel = this._activeChannel;
+            }
+        };
+        Engine.prototype._bindTextureDirectly = function (target, texture, forTextureDataUpdate) {
+            if (forTextureDataUpdate === void 0) { forTextureDataUpdate = false; }
+            if (forTextureDataUpdate && texture && texture._designatedSlot > -1) {
+                this._activeChannel = texture._designatedSlot;
+            }
             var currentTextureBound = this._boundTexturesCache[this._activeChannel];
             var isTextureForRendering = texture && texture._initialSlot > -1;
             if (currentTextureBound !== texture) {
                 if (currentTextureBound && !this.disableTextureBindingOptimization) {
                     this._removeDesignatedSlot(currentTextureBound);
                 }
+                this._activateCurrentTexture();
                 this._gl.bindTexture(target, texture ? texture._webGLTexture : null);
-                if (this._activeChannel >= 0) {
-                    this._boundTexturesCache[this._activeChannel] = texture;
-                    if (isTextureForRendering && !this.disableTextureBindingOptimization) {
+                this._boundTexturesCache[this._activeChannel] = texture;
+                if (texture) {
+                    if (!this.disableTextureBindingOptimization) {
                         var slotIndex = this._nextFreeTextureSlots.indexOf(this._activeChannel);
                         if (slotIndex > -1) {
                             this._nextFreeTextureSlots.splice(slotIndex, 1);
                         }
                         this._boundTexturesStack.push(texture);
                     }
+                    texture._designatedSlot = this._activeChannel;
                 }
             }
-            if (isTextureForRendering && this._activeChannel > -1) {
-                texture._designatedSlot = this._activeChannel;
-                if (!doNotBindUniformToTextureChannel) {
-                    this._bindSamplerUniformToChannel(texture._initialSlot, this._activeChannel);
-                }
+            else if (forTextureDataUpdate) {
+                this._activateCurrentTexture();
+            }
+            if (isTextureForRendering && !forTextureDataUpdate) {
+                this._bindSamplerUniformToChannel(texture._initialSlot, this._activeChannel);
             }
         };
         Engine.prototype._bindTexture = function (channel, texture) {
@@ -12747,7 +12797,7 @@ var BABYLON;
             if (texture) {
                 channel = this._getCorrectTextureChannel(channel, texture);
             }
-            this._activateTextureChannel(channel);
+            this._activeChannel = channel;
             this._bindTextureDirectly(this._gl.TEXTURE_2D, texture);
         };
         Engine.prototype.setTextureFromPostProcess = function (channel, postProcess) {
@@ -12755,7 +12805,7 @@ var BABYLON;
         };
         Engine.prototype.unbindAllTextures = function () {
             for (var channel = 0; channel < this._maxSimultaneousTextures; channel++) {
-                this._activateTextureChannel(channel);
+                this._activeChannel = channel;
                 this._bindTextureDirectly(this._gl.TEXTURE_2D, null);
                 this._bindTextureDirectly(this._gl.TEXTURE_CUBE_MAP, null);
                 if (this.webGLVersion > 1) {
@@ -12772,44 +12822,20 @@ var BABYLON;
             }
             this._setTexture(channel, texture);
         };
-        Engine.prototype._getCorrectTextureChannel = function (channel, internalTexture) {
-            if (!internalTexture) {
-                return -1;
-            }
-            internalTexture._initialSlot = channel;
-            if (this.disableTextureBindingOptimization) {
-                if (channel !== internalTexture._designatedSlot) {
-                    this._textureCollisions.addCount(1, false);
-                }
-            }
-            else {
-                if (channel !== internalTexture._designatedSlot) {
-                    if (internalTexture._designatedSlot > -1) {
-                        return internalTexture._designatedSlot;
-                    }
-                    else {
-                        // No slot for this texture, let's pick a new one (if we find a free slot)
-                        if (this._nextFreeTextureSlots.length) {
-                            return this._nextFreeTextureSlots[0];
-                        }
-                        // We need to recycle the oldest bound texture, sorry.
-                        this._textureCollisions.addCount(1, false);
-                        return this._removeDesignatedSlot(this._boundTexturesStack[0]);
-                    }
-                }
-            }
-            return channel;
-        };
         Engine.prototype._bindSamplerUniformToChannel = function (sourceSlot, destination) {
             var uniform = this._boundUniforms[sourceSlot];
+            if (uniform._currentState === destination) {
+                return;
+            }
             this._gl.uniform1i(uniform, destination);
+            uniform._currentState = destination;
         };
         Engine.prototype._setTexture = function (channel, texture, isPartOfTextureArray) {
             if (isPartOfTextureArray === void 0) { isPartOfTextureArray = false; }
             // Not ready?
             if (!texture) {
                 if (this._boundTexturesCache[channel] != null) {
-                    this._activateTextureChannel(channel);
+                    this._activeChannel = channel;
                     this._bindTextureDirectly(this._gl.TEXTURE_2D, null);
                     this._bindTextureDirectly(this._gl.TEXTURE_CUBE_MAP, null);
                     if (this.webGLVersion > 1) {
@@ -12819,10 +12845,8 @@ var BABYLON;
                 return false;
             }
             // Video
-            var alreadyActivated = false;
             if (texture.video) {
-                this._activateTextureChannel(channel);
-                alreadyActivated = true;
+                this._activeChannel = channel;
                 texture.update();
             }
             else if (texture.delayLoadState === Engine.DELAYLOADSTATE_NOTLOADED) {
@@ -12852,9 +12876,7 @@ var BABYLON;
                 }
                 return false;
             }
-            if (!alreadyActivated) {
-                this._activateTextureChannel(channel);
-            }
+            this._activeChannel = channel;
             if (internalTexture && internalTexture.is3D) {
                 this._bindTextureDirectly(this._gl.TEXTURE_3D, internalTexture, isPartOfTextureArray);
                 if (internalTexture && internalTexture._cachedWrapU !== texture.wrapU) {
@@ -13132,7 +13154,7 @@ var BABYLON;
             // Remove from Instances
             var index = Engine.Instances.indexOf(this);
             if (index >= 0) {
-                Engine.Instances.splice(index, 1);
+                delete Engine.Instances[index];
             }
             this._workingCanvas = null;
             this._workingContext = null;
@@ -13527,7 +13549,7 @@ var BABYLON;
             var request = BABYLON.Tools.LoadFile(url, onSuccess, onProgress, database, useArrayBuffer, onError);
             this._activeRequests.push(request);
             request.onCompleteObservable.add(function (request) {
-                _this._activeRequests.splice(_this._activeRequests.indexOf(request), 1);
+                delete _this._activeRequests[_this._activeRequests.indexOf(request)];
             });
             return request;
         };
@@ -18891,10 +18913,8 @@ var BABYLON;
             var engine = this._scene.getEngine();
             // Depth only
             if (this._depthOnlySubMeshes.length !== 0) {
-                engine.setAlphaTesting(true);
                 engine.setColorWrite(false);
                 this._renderAlphaTest(this._depthOnlySubMeshes);
-                engine.setAlphaTesting(false);
                 engine.setColorWrite(true);
             }
             // Opaque
@@ -18903,9 +18923,7 @@ var BABYLON;
             }
             // Alpha test
             if (this._alphaTestSubMeshes.length !== 0) {
-                engine.setAlphaTesting(true);
                 this._renderAlphaTest(this._alphaTestSubMeshes);
-                engine.setAlphaTesting(false);
             }
             var stencilState = engine.getStencilBuffer();
             engine.setStencilBuffer(false);
@@ -18982,10 +19000,8 @@ var BABYLON;
                     if (material && material.needDepthPrePass) {
                         var engine = material.getScene().getEngine();
                         engine.setColorWrite(false);
-                        engine.setAlphaTesting(true);
                         engine.setAlphaMode(BABYLON.Engine.ALPHA_DISABLE);
                         subMesh.render(false);
-                        engine.setAlphaTesting(false);
                         engine.setColorWrite(true);
                     }
                 }
@@ -25377,28 +25393,22 @@ var BABYLON;
             this.computeWorldMatrix();
             var mat = this.material || scene.defaultMaterial;
             if (mat) {
-                var currentAlphaTestingState = engine.getAlphaTesting();
                 if (mat.storeEffectOnSubMeshes) {
                     for (var _i = 0, _a = this.subMeshes; _i < _a.length; _i++) {
                         var subMesh = _a[_i];
                         var effectiveMaterial = subMesh.getMaterial();
                         if (effectiveMaterial) {
-                            engine.setAlphaTesting(effectiveMaterial.needAlphaTesting() && !effectiveMaterial.needAlphaBlendingForMesh(this));
                             if (!effectiveMaterial.isReadyForSubMesh(this, subMesh, hardwareInstancedRendering)) {
-                                engine.setAlphaTesting(currentAlphaTestingState);
                                 return false;
                             }
                         }
                     }
                 }
                 else {
-                    engine.setAlphaTesting(mat.needAlphaTesting() && !mat.needAlphaBlendingForMesh(this));
                     if (!mat.isReady(this, hardwareInstancedRendering)) {
-                        engine.setAlphaTesting(currentAlphaTestingState);
                         return false;
                     }
                 }
-                engine.setAlphaTesting(currentAlphaTestingState);
             }
             // Shadows
             for (var _b = 0, _c = this._lightSources; _b < _c.length; _b++) {
@@ -28670,6 +28680,9 @@ var BABYLON;
                 this.bindSceneUniformBuffer(effect, this.getScene().getSceneUniformBuffer());
             }
         };
+        Material.prototype._shouldTurnAlphaTestOn = function (mesh) {
+            return (!this.needAlphaBlendingForMesh(mesh) && this.needAlphaTesting());
+        };
         Material.prototype._afterBind = function (mesh) {
             this._scene._cachedMaterial = this;
             if (mesh) {
@@ -28718,10 +28731,9 @@ var BABYLON;
          */
         Material.prototype.forceCompilation = function (mesh, onCompiled, options) {
             var _this = this;
-            var localOptions = __assign({ alphaTest: null, clipPlane: false }, options);
+            var localOptions = __assign({ clipPlane: false }, options);
             var subMesh = new BABYLON.BaseSubMesh();
             var scene = this.getScene();
-            var engine = scene.getEngine();
             var checkReady = function () {
                 if (!_this._scene || !_this._scene.getEngine()) {
                     return;
@@ -28729,9 +28741,7 @@ var BABYLON;
                 if (subMesh._materialDefines) {
                     subMesh._materialDefines._renderId = -1;
                 }
-                var alphaTestState = engine.getAlphaTesting();
                 var clipPlaneState = scene.clipPlane;
-                engine.setAlphaTesting(localOptions.alphaTest || (!_this.needAlphaBlendingForMesh(mesh) && _this.needAlphaTesting()));
                 if (localOptions.clipPlane) {
                     scene.clipPlane = new BABYLON.Plane(0, 0, 0, 1);
                 }
@@ -28755,7 +28765,6 @@ var BABYLON;
                         setTimeout(checkReady, 16);
                     }
                 }
-                engine.setAlphaTesting(alphaTestState);
                 if (options && options.clipPlane) {
                     scene.clipPlane = clipPlaneState;
                 }
@@ -34757,14 +34766,21 @@ var BABYLON;
                 defines["NONUNIFORMSCALING"] = mesh.nonUniformScaling;
             }
         };
-        MaterialHelper.PrepareDefinesForFrameBoundValues = function (scene, engine, defines, useInstances, forceAlphaTest) {
-            if (forceAlphaTest === void 0) { forceAlphaTest = false; }
+        /**
+         * Helper used to prepare the list of defines for shader compilation
+         * @param scene defines the current scene
+         * @param engine defines the current engine
+         * @param defines specifies the list of active defines
+         * @param useInstances defines if instances have to be turned on
+         * @param alphaTest defines if alpha testing has to be turned on
+         */
+        MaterialHelper.PrepareDefinesForFrameBoundValues = function (scene, engine, defines, useInstances, alphaTest) {
             var changed = false;
             if (defines["CLIPPLANE"] !== (scene.clipPlane !== undefined && scene.clipPlane !== null)) {
                 defines["CLIPPLANE"] = !defines["CLIPPLANE"];
                 changed = true;
             }
-            if (defines["ALPHATEST"] !== (engine.getAlphaTesting() || forceAlphaTest)) {
+            if (defines["ALPHATEST"] !== alphaTest) {
                 defines["ALPHATEST"] = !defines["ALPHATEST"];
                 changed = true;
             }
@@ -35747,7 +35763,7 @@ var BABYLON;
             // Attribs
             BABYLON.MaterialHelper.PrepareDefinesForAttributes(mesh, defines, true, true, true);
             // Values that need to be evaluated on every frame
-            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances);
+            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances, this._shouldTurnAlphaTestOn(mesh));
             // Get correct effect      
             if (defines.isDirty) {
                 defines.markAsProcessed();
@@ -37342,7 +37358,7 @@ var BABYLON;
             // Misc.
             BABYLON.MaterialHelper.PrepareDefinesForMisc(mesh, scene, this._useLogarithmicDepth, this.pointsCloud, this.fogEnabled, defines);
             // Values that need to be evaluated on every frame
-            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false, this._forceAlphaTest);
+            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false, this._shouldTurnAlphaTestOn(mesh) || this._forceAlphaTest);
             // Attribs
             if (BABYLON.MaterialHelper.PrepareDefinesForAttributes(mesh, defines, true, true, true, this._transparencyMode !== BABYLON.PBRMaterial.PBRMATERIAL_OPAQUE) && mesh) {
                 var bufferMesh = null;
@@ -42677,7 +42693,7 @@ var BABYLON;
             this._targetedAnimations = new Array();
             this._animatables = new Array();
             this._from = Number.MAX_VALUE;
-            this._to = Number.MIN_VALUE;
+            this._to = -Number.MAX_VALUE;
             this._speedRatio = 1;
             this.onAnimationEndObservable = new BABYLON.Observable();
             this._scene = scene || BABYLON.Engine.LastCreatedScene;
@@ -42716,6 +42732,16 @@ var BABYLON;
             enumerable: true,
             configurable: true
         });
+        Object.defineProperty(AnimationGroup.prototype, "targetedAnimations", {
+            /**
+             * Gets the targeted animations for this animation group
+             */
+            get: function () {
+                return this._targetedAnimations;
+            },
+            enumerable: true,
+            configurable: true
+        });
         /**
          * Add an animation (with its target) in the group
          * @param animation defines the animation we want to add
@@ -42740,11 +42766,13 @@ var BABYLON;
         /**
          * This function will normalize every animation in the group to make sure they all go from beginFrame to endFrame
          * It can add constant keys at begin or end
-         * @param beginFrame defines the new begin frame for all animations. It can't be bigger than the smaller begin frame of all animations
-         * @param endFrame defines the new end frame for all animations. It can't be smaller than the larger end frame of all animations
+         * @param beginFrame defines the new begin frame for all animations. It can't be bigger than the smallest begin frame of all animations
+         * @param endFrame defines the new end frame for all animations. It can't be smaller than the largest end frame of all animations
          */
         AnimationGroup.prototype.normalize = function (beginFrame, endFrame) {
-            beginFrame = Math.min(beginFrame, this._from);
+            if (beginFrame === void 0) { beginFrame = -Number.MAX_VALUE; }
+            if (endFrame === void 0) { endFrame = Number.MAX_VALUE; }
+            beginFrame = Math.max(beginFrame, this._from);
             endFrame = Math.min(endFrame, this._to);
             for (var index = 0; index < this._targetedAnimations.length; index++) {
                 var targetedAnimation = this._targetedAnimations[index];
@@ -42756,7 +42784,8 @@ var BABYLON;
                         frame: beginFrame,
                         value: startKey.value,
                         inTangent: startKey.inTangent,
-                        outTangent: startKey.outTangent
+                        outTangent: startKey.outTangent,
+                        interpolation: startKey.interpolation
                     };
                     keys.splice(0, 0, newKey);
                 }
@@ -42764,8 +42793,9 @@ var BABYLON;
                     var newKey = {
                         frame: endFrame,
                         value: endKey.value,
-                        inTangent: startKey.outTangent,
-                        outTangent: startKey.outTangent
+                        inTangent: endKey.outTangent,
+                        outTangent: endKey.outTangent,
+                        interpolation: endKey.interpolation
                     };
                     keys.push(newKey);
                 }
@@ -48770,7 +48800,7 @@ var BABYLON;
                 }
             }
             // Alpha test
-            if (engine.getAlphaTesting()) {
+            if (mesh && this._shouldTurnAlphaTestOn(mesh)) {
                 defines.push("#define ALPHATEST");
             }
             var previousEffect = this._effect;
@@ -63048,11 +63078,9 @@ var BABYLON;
                 for (index = 0; index < opaqueSubMeshes.length; index++) {
                     renderSubMesh(opaqueSubMeshes.data[index]);
                 }
-                engine.setAlphaTesting(true);
                 for (index = 0; index < alphaTestSubMeshes.length; index++) {
                     renderSubMesh(alphaTestSubMeshes.data[index]);
                 }
-                engine.setAlphaTesting(false);
                 if (transparentSubMeshes.length) {
                     // Sort sub meshes
                     for (index = 0; index < transparentSubMeshes.length; index++) {
@@ -81964,7 +81992,7 @@ var BABYLON;
             // Misc.
             BABYLON.MaterialHelper.PrepareDefinesForMisc(mesh, scene, false, this.pointsCloud, this.fogEnabled, defines);
             // Values that need to be evaluated on every frame
-            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances, false);
+            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances, this._shouldTurnAlphaTestOn(mesh));
             // Attribs
             if (BABYLON.MaterialHelper.PrepareDefinesForAttributes(mesh, defines, false, true, false)) {
                 if (mesh) {

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 43 - 43
dist/preview release/babylon.worker.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 5937 - 5903
dist/preview release/customConfigurations/minimalGLTFViewer/babylon.d.ts


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 45 - 45
dist/preview release/customConfigurations/minimalGLTFViewer/babylon.js


+ 139 - 115
dist/preview release/customConfigurations/minimalGLTFViewer/babylon.max.js

@@ -7483,6 +7483,26 @@ var BABYLON;
             }
             Tools.EncodeScreenshotCanvasData(successCallback, mimeType);
         };
+        /**
+         * Generates an image screenshot from the specified camera.
+         *
+         * @param engine The engine to use for rendering
+         * @param camera The camera to use for rendering
+         * @param size This parameter can be set to a single number or to an object with the
+         * following (optional) properties: precision, width, height. If a single number is passed,
+         * it will be used for both width and height. If an object is passed, the screenshot size
+         * will be derived from the parameters. The precision property is a multiplier allowing
+         * rendering at a higher or lower resolution.
+         * @param successCallback The callback receives a single parameter which contains the
+         * screenshot as a string of base64-encoded characters. This string can be assigned to the
+         * src parameter of an <img> to display it.
+         * @param mimeType The MIME type of the screenshot image (default: image/png).
+         * Check your browser for supported MIME types.
+         * @param samples Texture samples (default: 1)
+         * @param antialiasing Whether antialiasing should be turned on or not (default: false)
+         * @param fileName A name for for the downloaded file.
+         * @constructor
+         */
         Tools.CreateScreenshotUsingRenderTarget = function (engine, camera, size, successCallback, mimeType, samples, antialiasing, fileName) {
             if (mimeType === void 0) { mimeType = "image/png"; }
             if (samples === void 0) { samples = 1; }
@@ -8885,9 +8905,10 @@ var BABYLON;
     var Engine = /** @class */ (function () {
         /**
          * @constructor
-         * @param {HTMLCanvasElement | WebGLRenderingContext} canvasOrContext - the canvas or the webgl context to be used for rendering
-         * @param {boolean} [antialias] - enable antialias
-         * @param options - further options to be sent to the getContext function
+         * @param canvasOrContext defines the canvas or WebGL context to use for rendering
+         * @param antialias defines enable antialiasing (default: false)
+         * @param options defines further options to be sent to the getContext() function
+         * @param adaptToDeviceRatio defines whether to adapt to the device's viewport characteristics (default: false)
          */
         function Engine(canvasOrContext, antialias, options, adaptToDeviceRatio) {
             if (adaptToDeviceRatio === void 0) { adaptToDeviceRatio = false; }
@@ -8989,6 +9010,8 @@ var BABYLON;
             this._alphaMode = Engine.ALPHA_DISABLE;
             // Cache
             this._internalTexturesCache = new Array();
+            this._activeChannel = 0;
+            this._currentTextureChannel = -1;
             this._boundTexturesCache = {};
             this._boundTexturesStack = new Array();
             this._compiledEffects = {};
@@ -9904,7 +9927,7 @@ var BABYLON;
             for (var slot = 0; slot < this._maxSimultaneousTextures; slot++) {
                 this._nextFreeTextureSlots.push(slot);
             }
-            this._activeChannel = -1;
+            this._currentTextureChannel = -1;
         };
         Engine.prototype.isDeterministicLockStep = function () {
             return this._deterministicLockstep;
@@ -11294,12 +11317,6 @@ var BABYLON;
         Engine.prototype.getAlphaMode = function () {
             return this._alphaMode;
         };
-        Engine.prototype.setAlphaTesting = function (enable) {
-            this._alphaTest = enable;
-        };
-        Engine.prototype.getAlphaTesting = function () {
-            return !!this._alphaTest;
-        };
         // Textures
         Engine.prototype.wipeCaches = function (bruteForce) {
             if (this.preventCacheWipeBetweenFrames && !bruteForce) {
@@ -12687,12 +12704,6 @@ var BABYLON;
             }
             this._currentEffect = null;
         };
-        Engine.prototype._activateTextureChannel = function (channel) {
-            if (this._activeChannel !== channel && channel > -1) {
-                this._gl.activeTexture(this._gl.TEXTURE0 + channel);
-                this._activeChannel = channel;
-            }
-        };
         Engine.prototype._moveBoundTextureOnTop = function (internalTexture) {
             var index = this._boundTexturesStack.indexOf(internalTexture);
             if (index > -1 && index !== this._boundTexturesStack.length - 1) {
@@ -12700,6 +12711,34 @@ var BABYLON;
                 this._boundTexturesStack.push(internalTexture);
             }
         };
+        Engine.prototype._getCorrectTextureChannel = function (channel, internalTexture) {
+            if (!internalTexture) {
+                return -1;
+            }
+            internalTexture._initialSlot = channel;
+            if (this.disableTextureBindingOptimization) {
+                if (channel !== internalTexture._designatedSlot) {
+                    this._textureCollisions.addCount(1, false);
+                }
+            }
+            else {
+                if (channel !== internalTexture._designatedSlot) {
+                    if (internalTexture._designatedSlot > -1) {
+                        return internalTexture._designatedSlot;
+                    }
+                    else {
+                        // No slot for this texture, let's pick a new one (if we find a free slot)
+                        if (this._nextFreeTextureSlots.length) {
+                            return this._nextFreeTextureSlots[0];
+                        }
+                        // We need to recycle the oldest bound texture, sorry.
+                        this._textureCollisions.addCount(1, false);
+                        return this._removeDesignatedSlot(this._boundTexturesStack[0]);
+                    }
+                }
+            }
+            return channel;
+        };
         Engine.prototype._removeDesignatedSlot = function (internalTexture) {
             var currentSlot = internalTexture._designatedSlot;
             internalTexture._designatedSlot = -1;
@@ -12713,31 +12752,42 @@ var BABYLON;
             }
             return currentSlot;
         };
-        Engine.prototype._bindTextureDirectly = function (target, texture, doNotBindUniformToTextureChannel) {
-            if (doNotBindUniformToTextureChannel === void 0) { doNotBindUniformToTextureChannel = false; }
+        Engine.prototype._activateCurrentTexture = function () {
+            if (this._currentTextureChannel !== this._activeChannel) {
+                this._gl.activeTexture(this._gl.TEXTURE0 + this._activeChannel);
+                this._currentTextureChannel = this._activeChannel;
+            }
+        };
+        Engine.prototype._bindTextureDirectly = function (target, texture, forTextureDataUpdate) {
+            if (forTextureDataUpdate === void 0) { forTextureDataUpdate = false; }
+            if (forTextureDataUpdate && texture && texture._designatedSlot > -1) {
+                this._activeChannel = texture._designatedSlot;
+            }
             var currentTextureBound = this._boundTexturesCache[this._activeChannel];
             var isTextureForRendering = texture && texture._initialSlot > -1;
             if (currentTextureBound !== texture) {
                 if (currentTextureBound && !this.disableTextureBindingOptimization) {
                     this._removeDesignatedSlot(currentTextureBound);
                 }
+                this._activateCurrentTexture();
                 this._gl.bindTexture(target, texture ? texture._webGLTexture : null);
-                if (this._activeChannel >= 0) {
-                    this._boundTexturesCache[this._activeChannel] = texture;
-                    if (isTextureForRendering && !this.disableTextureBindingOptimization) {
+                this._boundTexturesCache[this._activeChannel] = texture;
+                if (texture) {
+                    if (!this.disableTextureBindingOptimization) {
                         var slotIndex = this._nextFreeTextureSlots.indexOf(this._activeChannel);
                         if (slotIndex > -1) {
                             this._nextFreeTextureSlots.splice(slotIndex, 1);
                         }
                         this._boundTexturesStack.push(texture);
                     }
+                    texture._designatedSlot = this._activeChannel;
                 }
             }
-            if (isTextureForRendering && this._activeChannel > -1) {
-                texture._designatedSlot = this._activeChannel;
-                if (!doNotBindUniformToTextureChannel) {
-                    this._bindSamplerUniformToChannel(texture._initialSlot, this._activeChannel);
-                }
+            else if (forTextureDataUpdate) {
+                this._activateCurrentTexture();
+            }
+            if (isTextureForRendering && !forTextureDataUpdate) {
+                this._bindSamplerUniformToChannel(texture._initialSlot, this._activeChannel);
             }
         };
         Engine.prototype._bindTexture = function (channel, texture) {
@@ -12747,7 +12797,7 @@ var BABYLON;
             if (texture) {
                 channel = this._getCorrectTextureChannel(channel, texture);
             }
-            this._activateTextureChannel(channel);
+            this._activeChannel = channel;
             this._bindTextureDirectly(this._gl.TEXTURE_2D, texture);
         };
         Engine.prototype.setTextureFromPostProcess = function (channel, postProcess) {
@@ -12755,7 +12805,7 @@ var BABYLON;
         };
         Engine.prototype.unbindAllTextures = function () {
             for (var channel = 0; channel < this._maxSimultaneousTextures; channel++) {
-                this._activateTextureChannel(channel);
+                this._activeChannel = channel;
                 this._bindTextureDirectly(this._gl.TEXTURE_2D, null);
                 this._bindTextureDirectly(this._gl.TEXTURE_CUBE_MAP, null);
                 if (this.webGLVersion > 1) {
@@ -12772,44 +12822,20 @@ var BABYLON;
             }
             this._setTexture(channel, texture);
         };
-        Engine.prototype._getCorrectTextureChannel = function (channel, internalTexture) {
-            if (!internalTexture) {
-                return -1;
-            }
-            internalTexture._initialSlot = channel;
-            if (this.disableTextureBindingOptimization) {
-                if (channel !== internalTexture._designatedSlot) {
-                    this._textureCollisions.addCount(1, false);
-                }
-            }
-            else {
-                if (channel !== internalTexture._designatedSlot) {
-                    if (internalTexture._designatedSlot > -1) {
-                        return internalTexture._designatedSlot;
-                    }
-                    else {
-                        // No slot for this texture, let's pick a new one (if we find a free slot)
-                        if (this._nextFreeTextureSlots.length) {
-                            return this._nextFreeTextureSlots[0];
-                        }
-                        // We need to recycle the oldest bound texture, sorry.
-                        this._textureCollisions.addCount(1, false);
-                        return this._removeDesignatedSlot(this._boundTexturesStack[0]);
-                    }
-                }
-            }
-            return channel;
-        };
         Engine.prototype._bindSamplerUniformToChannel = function (sourceSlot, destination) {
             var uniform = this._boundUniforms[sourceSlot];
+            if (uniform._currentState === destination) {
+                return;
+            }
             this._gl.uniform1i(uniform, destination);
+            uniform._currentState = destination;
         };
         Engine.prototype._setTexture = function (channel, texture, isPartOfTextureArray) {
             if (isPartOfTextureArray === void 0) { isPartOfTextureArray = false; }
             // Not ready?
             if (!texture) {
                 if (this._boundTexturesCache[channel] != null) {
-                    this._activateTextureChannel(channel);
+                    this._activeChannel = channel;
                     this._bindTextureDirectly(this._gl.TEXTURE_2D, null);
                     this._bindTextureDirectly(this._gl.TEXTURE_CUBE_MAP, null);
                     if (this.webGLVersion > 1) {
@@ -12819,10 +12845,8 @@ var BABYLON;
                 return false;
             }
             // Video
-            var alreadyActivated = false;
             if (texture.video) {
-                this._activateTextureChannel(channel);
-                alreadyActivated = true;
+                this._activeChannel = channel;
                 texture.update();
             }
             else if (texture.delayLoadState === Engine.DELAYLOADSTATE_NOTLOADED) {
@@ -12852,9 +12876,7 @@ var BABYLON;
                 }
                 return false;
             }
-            if (!alreadyActivated) {
-                this._activateTextureChannel(channel);
-            }
+            this._activeChannel = channel;
             if (internalTexture && internalTexture.is3D) {
                 this._bindTextureDirectly(this._gl.TEXTURE_3D, internalTexture, isPartOfTextureArray);
                 if (internalTexture && internalTexture._cachedWrapU !== texture.wrapU) {
@@ -13132,7 +13154,7 @@ var BABYLON;
             // Remove from Instances
             var index = Engine.Instances.indexOf(this);
             if (index >= 0) {
-                Engine.Instances.splice(index, 1);
+                delete Engine.Instances[index];
             }
             this._workingCanvas = null;
             this._workingContext = null;
@@ -13527,7 +13549,7 @@ var BABYLON;
             var request = BABYLON.Tools.LoadFile(url, onSuccess, onProgress, database, useArrayBuffer, onError);
             this._activeRequests.push(request);
             request.onCompleteObservable.add(function (request) {
-                _this._activeRequests.splice(_this._activeRequests.indexOf(request), 1);
+                delete _this._activeRequests[_this._activeRequests.indexOf(request)];
             });
             return request;
         };
@@ -18891,10 +18913,8 @@ var BABYLON;
             var engine = this._scene.getEngine();
             // Depth only
             if (this._depthOnlySubMeshes.length !== 0) {
-                engine.setAlphaTesting(true);
                 engine.setColorWrite(false);
                 this._renderAlphaTest(this._depthOnlySubMeshes);
-                engine.setAlphaTesting(false);
                 engine.setColorWrite(true);
             }
             // Opaque
@@ -18903,9 +18923,7 @@ var BABYLON;
             }
             // Alpha test
             if (this._alphaTestSubMeshes.length !== 0) {
-                engine.setAlphaTesting(true);
                 this._renderAlphaTest(this._alphaTestSubMeshes);
-                engine.setAlphaTesting(false);
             }
             var stencilState = engine.getStencilBuffer();
             engine.setStencilBuffer(false);
@@ -18982,10 +19000,8 @@ var BABYLON;
                     if (material && material.needDepthPrePass) {
                         var engine = material.getScene().getEngine();
                         engine.setColorWrite(false);
-                        engine.setAlphaTesting(true);
                         engine.setAlphaMode(BABYLON.Engine.ALPHA_DISABLE);
                         subMesh.render(false);
-                        engine.setAlphaTesting(false);
                         engine.setColorWrite(true);
                     }
                 }
@@ -25377,28 +25393,22 @@ var BABYLON;
             this.computeWorldMatrix();
             var mat = this.material || scene.defaultMaterial;
             if (mat) {
-                var currentAlphaTestingState = engine.getAlphaTesting();
                 if (mat.storeEffectOnSubMeshes) {
                     for (var _i = 0, _a = this.subMeshes; _i < _a.length; _i++) {
                         var subMesh = _a[_i];
                         var effectiveMaterial = subMesh.getMaterial();
                         if (effectiveMaterial) {
-                            engine.setAlphaTesting(effectiveMaterial.needAlphaTesting() && !effectiveMaterial.needAlphaBlendingForMesh(this));
                             if (!effectiveMaterial.isReadyForSubMesh(this, subMesh, hardwareInstancedRendering)) {
-                                engine.setAlphaTesting(currentAlphaTestingState);
                                 return false;
                             }
                         }
                     }
                 }
                 else {
-                    engine.setAlphaTesting(mat.needAlphaTesting() && !mat.needAlphaBlendingForMesh(this));
                     if (!mat.isReady(this, hardwareInstancedRendering)) {
-                        engine.setAlphaTesting(currentAlphaTestingState);
                         return false;
                     }
                 }
-                engine.setAlphaTesting(currentAlphaTestingState);
             }
             // Shadows
             for (var _b = 0, _c = this._lightSources; _b < _c.length; _b++) {
@@ -28670,6 +28680,9 @@ var BABYLON;
                 this.bindSceneUniformBuffer(effect, this.getScene().getSceneUniformBuffer());
             }
         };
+        Material.prototype._shouldTurnAlphaTestOn = function (mesh) {
+            return (!this.needAlphaBlendingForMesh(mesh) && this.needAlphaTesting());
+        };
         Material.prototype._afterBind = function (mesh) {
             this._scene._cachedMaterial = this;
             if (mesh) {
@@ -28718,10 +28731,9 @@ var BABYLON;
          */
         Material.prototype.forceCompilation = function (mesh, onCompiled, options) {
             var _this = this;
-            var localOptions = __assign({ alphaTest: null, clipPlane: false }, options);
+            var localOptions = __assign({ clipPlane: false }, options);
             var subMesh = new BABYLON.BaseSubMesh();
             var scene = this.getScene();
-            var engine = scene.getEngine();
             var checkReady = function () {
                 if (!_this._scene || !_this._scene.getEngine()) {
                     return;
@@ -28729,9 +28741,7 @@ var BABYLON;
                 if (subMesh._materialDefines) {
                     subMesh._materialDefines._renderId = -1;
                 }
-                var alphaTestState = engine.getAlphaTesting();
                 var clipPlaneState = scene.clipPlane;
-                engine.setAlphaTesting(localOptions.alphaTest || (!_this.needAlphaBlendingForMesh(mesh) && _this.needAlphaTesting()));
                 if (localOptions.clipPlane) {
                     scene.clipPlane = new BABYLON.Plane(0, 0, 0, 1);
                 }
@@ -28755,7 +28765,6 @@ var BABYLON;
                         setTimeout(checkReady, 16);
                     }
                 }
-                engine.setAlphaTesting(alphaTestState);
                 if (options && options.clipPlane) {
                     scene.clipPlane = clipPlaneState;
                 }
@@ -34757,14 +34766,21 @@ var BABYLON;
                 defines["NONUNIFORMSCALING"] = mesh.nonUniformScaling;
             }
         };
-        MaterialHelper.PrepareDefinesForFrameBoundValues = function (scene, engine, defines, useInstances, forceAlphaTest) {
-            if (forceAlphaTest === void 0) { forceAlphaTest = false; }
+        /**
+         * Helper used to prepare the list of defines for shader compilation
+         * @param scene defines the current scene
+         * @param engine defines the current engine
+         * @param defines specifies the list of active defines
+         * @param useInstances defines if instances have to be turned on
+         * @param alphaTest defines if alpha testing has to be turned on
+         */
+        MaterialHelper.PrepareDefinesForFrameBoundValues = function (scene, engine, defines, useInstances, alphaTest) {
             var changed = false;
             if (defines["CLIPPLANE"] !== (scene.clipPlane !== undefined && scene.clipPlane !== null)) {
                 defines["CLIPPLANE"] = !defines["CLIPPLANE"];
                 changed = true;
             }
-            if (defines["ALPHATEST"] !== (engine.getAlphaTesting() || forceAlphaTest)) {
+            if (defines["ALPHATEST"] !== alphaTest) {
                 defines["ALPHATEST"] = !defines["ALPHATEST"];
                 changed = true;
             }
@@ -35747,7 +35763,7 @@ var BABYLON;
             // Attribs
             BABYLON.MaterialHelper.PrepareDefinesForAttributes(mesh, defines, true, true, true);
             // Values that need to be evaluated on every frame
-            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances);
+            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances, this._shouldTurnAlphaTestOn(mesh));
             // Get correct effect      
             if (defines.isDirty) {
                 defines.markAsProcessed();
@@ -37342,7 +37358,7 @@ var BABYLON;
             // Misc.
             BABYLON.MaterialHelper.PrepareDefinesForMisc(mesh, scene, this._useLogarithmicDepth, this.pointsCloud, this.fogEnabled, defines);
             // Values that need to be evaluated on every frame
-            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false, this._forceAlphaTest);
+            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false, this._shouldTurnAlphaTestOn(mesh) || this._forceAlphaTest);
             // Attribs
             if (BABYLON.MaterialHelper.PrepareDefinesForAttributes(mesh, defines, true, true, true, this._transparencyMode !== BABYLON.PBRMaterial.PBRMATERIAL_OPAQUE) && mesh) {
                 var bufferMesh = null;
@@ -42677,7 +42693,7 @@ var BABYLON;
             this._targetedAnimations = new Array();
             this._animatables = new Array();
             this._from = Number.MAX_VALUE;
-            this._to = Number.MIN_VALUE;
+            this._to = -Number.MAX_VALUE;
             this._speedRatio = 1;
             this.onAnimationEndObservable = new BABYLON.Observable();
             this._scene = scene || BABYLON.Engine.LastCreatedScene;
@@ -42716,6 +42732,16 @@ var BABYLON;
             enumerable: true,
             configurable: true
         });
+        Object.defineProperty(AnimationGroup.prototype, "targetedAnimations", {
+            /**
+             * Gets the targeted animations for this animation group
+             */
+            get: function () {
+                return this._targetedAnimations;
+            },
+            enumerable: true,
+            configurable: true
+        });
         /**
          * Add an animation (with its target) in the group
          * @param animation defines the animation we want to add
@@ -42740,11 +42766,13 @@ var BABYLON;
         /**
          * This function will normalize every animation in the group to make sure they all go from beginFrame to endFrame
          * It can add constant keys at begin or end
-         * @param beginFrame defines the new begin frame for all animations. It can't be bigger than the smaller begin frame of all animations
-         * @param endFrame defines the new end frame for all animations. It can't be smaller than the larger end frame of all animations
+         * @param beginFrame defines the new begin frame for all animations. It can't be bigger than the smallest begin frame of all animations
+         * @param endFrame defines the new end frame for all animations. It can't be smaller than the largest end frame of all animations
          */
         AnimationGroup.prototype.normalize = function (beginFrame, endFrame) {
-            beginFrame = Math.min(beginFrame, this._from);
+            if (beginFrame === void 0) { beginFrame = -Number.MAX_VALUE; }
+            if (endFrame === void 0) { endFrame = Number.MAX_VALUE; }
+            beginFrame = Math.max(beginFrame, this._from);
             endFrame = Math.min(endFrame, this._to);
             for (var index = 0; index < this._targetedAnimations.length; index++) {
                 var targetedAnimation = this._targetedAnimations[index];
@@ -42756,7 +42784,8 @@ var BABYLON;
                         frame: beginFrame,
                         value: startKey.value,
                         inTangent: startKey.inTangent,
-                        outTangent: startKey.outTangent
+                        outTangent: startKey.outTangent,
+                        interpolation: startKey.interpolation
                     };
                     keys.splice(0, 0, newKey);
                 }
@@ -42764,8 +42793,9 @@ var BABYLON;
                     var newKey = {
                         frame: endFrame,
                         value: endKey.value,
-                        inTangent: startKey.outTangent,
-                        outTangent: startKey.outTangent
+                        inTangent: endKey.outTangent,
+                        outTangent: endKey.outTangent,
+                        interpolation: endKey.interpolation
                     };
                     keys.push(newKey);
                 }
@@ -48616,7 +48646,7 @@ var BABYLON;
                 }
             }
             // Alpha test
-            if (engine.getAlphaTesting()) {
+            if (mesh && this._shouldTurnAlphaTestOn(mesh)) {
                 defines.push("#define ALPHATEST");
             }
             var previousEffect = this._effect;
@@ -62894,11 +62924,9 @@ var BABYLON;
                 for (index = 0; index < opaqueSubMeshes.length; index++) {
                     renderSubMesh(opaqueSubMeshes.data[index]);
                 }
-                engine.setAlphaTesting(true);
                 for (index = 0; index < alphaTestSubMeshes.length; index++) {
                     renderSubMesh(alphaTestSubMeshes.data[index]);
                 }
-                engine.setAlphaTesting(false);
                 if (transparentSubMeshes.length) {
                     // Sort sub meshes
                     for (index = 0; index < transparentSubMeshes.length; index++) {
@@ -81460,7 +81488,7 @@ var BABYLON;
             // Misc.
             BABYLON.MaterialHelper.PrepareDefinesForMisc(mesh, scene, false, this.pointsCloud, this.fogEnabled, defines);
             // Values that need to be evaluated on every frame
-            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances, false);
+            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances, this._shouldTurnAlphaTestOn(mesh));
             // Attribs
             if (BABYLON.MaterialHelper.PrepareDefinesForAttributes(mesh, defines, false, true, false)) {
                 if (mesh) {
@@ -85377,6 +85405,10 @@ var BABYLON;
                 if (!animations) {
                     return;
                 }
+                for (var _i = 0, animations_1 = animations; _i < animations_1.length; _i++) {
+                    var animation = animations_1[_i];
+                    animation.babylonAnimationGroup.normalize();
+                }
                 switch (this.animationStartMode) {
                     case BABYLON.GLTFLoaderAnimationStartMode.NONE: {
                         // do nothing
@@ -85384,19 +85416,13 @@ var BABYLON;
                     }
                     case BABYLON.GLTFLoaderAnimationStartMode.FIRST: {
                         var animation = animations[0];
-                        for (var _i = 0, _a = animation.targets; _i < _a.length; _i++) {
-                            var target = _a[_i];
-                            this._babylonScene.beginAnimation(target, 0, Number.MAX_VALUE, true);
-                        }
+                        animation.babylonAnimationGroup.start(true);
                         break;
                     }
                     case BABYLON.GLTFLoaderAnimationStartMode.ALL: {
-                        for (var _b = 0, animations_1 = animations; _b < animations_1.length; _b++) {
-                            var animation = animations_1[_b];
-                            for (var _c = 0, _d = animation.targets; _c < _d.length; _c++) {
-                                var target = _d[_c];
-                                this._babylonScene.beginAnimation(target, 0, Number.MAX_VALUE, true);
-                            }
+                        for (var _a = 0, animations_2 = animations; _a < animations_2.length; _a++) {
+                            var animation = animations_2[_a];
+                            animation.babylonAnimationGroup.start(true);
                         }
                         break;
                     }
@@ -86008,7 +86034,7 @@ var BABYLON;
                 }
             };
             GLTFLoader.prototype._loadAnimation = function (context, animation) {
-                animation.targets = [];
+                animation.babylonAnimationGroup = new BABYLON.AnimationGroup(animation.name || "animation" + animation.index, this._babylonScene);
                 for (var index = 0; index < animation.channels.length; index++) {
                     var channel = GLTFLoader._GetProperty(animation.channels, index);
                     if (!channel) {
@@ -86148,7 +86174,7 @@ var BABYLON;
                         var morphTargetManager = targetNode.babylonMesh.morphTargetManager;
                         var _loop_7 = function (targetIndex) {
                             var morphTarget = morphTargetManager.getTarget(targetIndex);
-                            var animationName = (animation.name || "anim" + animation.index) + "_" + targetIndex;
+                            var animationName = animation.babylonAnimationGroup.name + "_channel" + animation.babylonAnimationGroup.targetedAnimations.length;
                             var babylonAnimation = new BABYLON.Animation(animationName, targetPath, 1, animationType);
                             babylonAnimation.setKeys(keys.map(function (key) { return ({
                                 frame: key.frame,
@@ -86156,22 +86182,20 @@ var BABYLON;
                                 value: key.value[targetIndex],
                                 outTangent: key.outTangent ? key.outTangent[targetIndex] : undefined
                             }); }));
-                            morphTarget.animations.push(babylonAnimation);
-                            animation.targets.push(morphTarget);
+                            animation.babylonAnimationGroup.addTargetedAnimation(babylonAnimation, morphTarget);
                         };
                         for (var targetIndex = 0; targetIndex < morphTargetManager.numTargets; targetIndex++) {
                             _loop_7(targetIndex);
                         }
                     }
                     else {
-                        var animationName = animation.name || "anim" + animation.index;
+                        var animationName = animation.babylonAnimationGroup.name + "_channel" + animation.babylonAnimationGroup.targetedAnimations.length;
                         var babylonAnimation = new BABYLON.Animation(animationName, targetPath, 1, animationType);
                         babylonAnimation.setKeys(keys);
                         if (targetNode.babylonAnimationTargets) {
                             for (var _i = 0, _a = targetNode.babylonAnimationTargets; _i < _a.length; _i++) {
                                 var target = _a[_i];
-                                target.animations.push(babylonAnimation.clone());
-                                animation.targets.push(target);
+                                animation.babylonAnimationGroup.addTargetedAnimation(babylonAnimation, target);
                             }
                         }
                     }

+ 139 - 115
dist/preview release/customConfigurations/minimalGLTFViewer/es6.js

@@ -7469,6 +7469,26 @@ var BABYLON;
             }
             Tools.EncodeScreenshotCanvasData(successCallback, mimeType);
         };
+        /**
+         * Generates an image screenshot from the specified camera.
+         *
+         * @param engine The engine to use for rendering
+         * @param camera The camera to use for rendering
+         * @param size This parameter can be set to a single number or to an object with the
+         * following (optional) properties: precision, width, height. If a single number is passed,
+         * it will be used for both width and height. If an object is passed, the screenshot size
+         * will be derived from the parameters. The precision property is a multiplier allowing
+         * rendering at a higher or lower resolution.
+         * @param successCallback The callback receives a single parameter which contains the
+         * screenshot as a string of base64-encoded characters. This string can be assigned to the
+         * src parameter of an <img> to display it.
+         * @param mimeType The MIME type of the screenshot image (default: image/png).
+         * Check your browser for supported MIME types.
+         * @param samples Texture samples (default: 1)
+         * @param antialiasing Whether antialiasing should be turned on or not (default: false)
+         * @param fileName A name for for the downloaded file.
+         * @constructor
+         */
         Tools.CreateScreenshotUsingRenderTarget = function (engine, camera, size, successCallback, mimeType, samples, antialiasing, fileName) {
             if (mimeType === void 0) { mimeType = "image/png"; }
             if (samples === void 0) { samples = 1; }
@@ -8871,9 +8891,10 @@ var BABYLON;
     var Engine = /** @class */ (function () {
         /**
          * @constructor
-         * @param {HTMLCanvasElement | WebGLRenderingContext} canvasOrContext - the canvas or the webgl context to be used for rendering
-         * @param {boolean} [antialias] - enable antialias
-         * @param options - further options to be sent to the getContext function
+         * @param canvasOrContext defines the canvas or WebGL context to use for rendering
+         * @param antialias defines enable antialiasing (default: false)
+         * @param options defines further options to be sent to the getContext() function
+         * @param adaptToDeviceRatio defines whether to adapt to the device's viewport characteristics (default: false)
          */
         function Engine(canvasOrContext, antialias, options, adaptToDeviceRatio) {
             if (adaptToDeviceRatio === void 0) { adaptToDeviceRatio = false; }
@@ -8975,6 +8996,8 @@ var BABYLON;
             this._alphaMode = Engine.ALPHA_DISABLE;
             // Cache
             this._internalTexturesCache = new Array();
+            this._activeChannel = 0;
+            this._currentTextureChannel = -1;
             this._boundTexturesCache = {};
             this._boundTexturesStack = new Array();
             this._compiledEffects = {};
@@ -9890,7 +9913,7 @@ var BABYLON;
             for (var slot = 0; slot < this._maxSimultaneousTextures; slot++) {
                 this._nextFreeTextureSlots.push(slot);
             }
-            this._activeChannel = -1;
+            this._currentTextureChannel = -1;
         };
         Engine.prototype.isDeterministicLockStep = function () {
             return this._deterministicLockstep;
@@ -11280,12 +11303,6 @@ var BABYLON;
         Engine.prototype.getAlphaMode = function () {
             return this._alphaMode;
         };
-        Engine.prototype.setAlphaTesting = function (enable) {
-            this._alphaTest = enable;
-        };
-        Engine.prototype.getAlphaTesting = function () {
-            return !!this._alphaTest;
-        };
         // Textures
         Engine.prototype.wipeCaches = function (bruteForce) {
             if (this.preventCacheWipeBetweenFrames && !bruteForce) {
@@ -12673,12 +12690,6 @@ var BABYLON;
             }
             this._currentEffect = null;
         };
-        Engine.prototype._activateTextureChannel = function (channel) {
-            if (this._activeChannel !== channel && channel > -1) {
-                this._gl.activeTexture(this._gl.TEXTURE0 + channel);
-                this._activeChannel = channel;
-            }
-        };
         Engine.prototype._moveBoundTextureOnTop = function (internalTexture) {
             var index = this._boundTexturesStack.indexOf(internalTexture);
             if (index > -1 && index !== this._boundTexturesStack.length - 1) {
@@ -12686,6 +12697,34 @@ var BABYLON;
                 this._boundTexturesStack.push(internalTexture);
             }
         };
+        Engine.prototype._getCorrectTextureChannel = function (channel, internalTexture) {
+            if (!internalTexture) {
+                return -1;
+            }
+            internalTexture._initialSlot = channel;
+            if (this.disableTextureBindingOptimization) {
+                if (channel !== internalTexture._designatedSlot) {
+                    this._textureCollisions.addCount(1, false);
+                }
+            }
+            else {
+                if (channel !== internalTexture._designatedSlot) {
+                    if (internalTexture._designatedSlot > -1) {
+                        return internalTexture._designatedSlot;
+                    }
+                    else {
+                        // No slot for this texture, let's pick a new one (if we find a free slot)
+                        if (this._nextFreeTextureSlots.length) {
+                            return this._nextFreeTextureSlots[0];
+                        }
+                        // We need to recycle the oldest bound texture, sorry.
+                        this._textureCollisions.addCount(1, false);
+                        return this._removeDesignatedSlot(this._boundTexturesStack[0]);
+                    }
+                }
+            }
+            return channel;
+        };
         Engine.prototype._removeDesignatedSlot = function (internalTexture) {
             var currentSlot = internalTexture._designatedSlot;
             internalTexture._designatedSlot = -1;
@@ -12699,31 +12738,42 @@ var BABYLON;
             }
             return currentSlot;
         };
-        Engine.prototype._bindTextureDirectly = function (target, texture, doNotBindUniformToTextureChannel) {
-            if (doNotBindUniformToTextureChannel === void 0) { doNotBindUniformToTextureChannel = false; }
+        Engine.prototype._activateCurrentTexture = function () {
+            if (this._currentTextureChannel !== this._activeChannel) {
+                this._gl.activeTexture(this._gl.TEXTURE0 + this._activeChannel);
+                this._currentTextureChannel = this._activeChannel;
+            }
+        };
+        Engine.prototype._bindTextureDirectly = function (target, texture, forTextureDataUpdate) {
+            if (forTextureDataUpdate === void 0) { forTextureDataUpdate = false; }
+            if (forTextureDataUpdate && texture && texture._designatedSlot > -1) {
+                this._activeChannel = texture._designatedSlot;
+            }
             var currentTextureBound = this._boundTexturesCache[this._activeChannel];
             var isTextureForRendering = texture && texture._initialSlot > -1;
             if (currentTextureBound !== texture) {
                 if (currentTextureBound && !this.disableTextureBindingOptimization) {
                     this._removeDesignatedSlot(currentTextureBound);
                 }
+                this._activateCurrentTexture();
                 this._gl.bindTexture(target, texture ? texture._webGLTexture : null);
-                if (this._activeChannel >= 0) {
-                    this._boundTexturesCache[this._activeChannel] = texture;
-                    if (isTextureForRendering && !this.disableTextureBindingOptimization) {
+                this._boundTexturesCache[this._activeChannel] = texture;
+                if (texture) {
+                    if (!this.disableTextureBindingOptimization) {
                         var slotIndex = this._nextFreeTextureSlots.indexOf(this._activeChannel);
                         if (slotIndex > -1) {
                             this._nextFreeTextureSlots.splice(slotIndex, 1);
                         }
                         this._boundTexturesStack.push(texture);
                     }
+                    texture._designatedSlot = this._activeChannel;
                 }
             }
-            if (isTextureForRendering && this._activeChannel > -1) {
-                texture._designatedSlot = this._activeChannel;
-                if (!doNotBindUniformToTextureChannel) {
-                    this._bindSamplerUniformToChannel(texture._initialSlot, this._activeChannel);
-                }
+            else if (forTextureDataUpdate) {
+                this._activateCurrentTexture();
+            }
+            if (isTextureForRendering && !forTextureDataUpdate) {
+                this._bindSamplerUniformToChannel(texture._initialSlot, this._activeChannel);
             }
         };
         Engine.prototype._bindTexture = function (channel, texture) {
@@ -12733,7 +12783,7 @@ var BABYLON;
             if (texture) {
                 channel = this._getCorrectTextureChannel(channel, texture);
             }
-            this._activateTextureChannel(channel);
+            this._activeChannel = channel;
             this._bindTextureDirectly(this._gl.TEXTURE_2D, texture);
         };
         Engine.prototype.setTextureFromPostProcess = function (channel, postProcess) {
@@ -12741,7 +12791,7 @@ var BABYLON;
         };
         Engine.prototype.unbindAllTextures = function () {
             for (var channel = 0; channel < this._maxSimultaneousTextures; channel++) {
-                this._activateTextureChannel(channel);
+                this._activeChannel = channel;
                 this._bindTextureDirectly(this._gl.TEXTURE_2D, null);
                 this._bindTextureDirectly(this._gl.TEXTURE_CUBE_MAP, null);
                 if (this.webGLVersion > 1) {
@@ -12758,44 +12808,20 @@ var BABYLON;
             }
             this._setTexture(channel, texture);
         };
-        Engine.prototype._getCorrectTextureChannel = function (channel, internalTexture) {
-            if (!internalTexture) {
-                return -1;
-            }
-            internalTexture._initialSlot = channel;
-            if (this.disableTextureBindingOptimization) {
-                if (channel !== internalTexture._designatedSlot) {
-                    this._textureCollisions.addCount(1, false);
-                }
-            }
-            else {
-                if (channel !== internalTexture._designatedSlot) {
-                    if (internalTexture._designatedSlot > -1) {
-                        return internalTexture._designatedSlot;
-                    }
-                    else {
-                        // No slot for this texture, let's pick a new one (if we find a free slot)
-                        if (this._nextFreeTextureSlots.length) {
-                            return this._nextFreeTextureSlots[0];
-                        }
-                        // We need to recycle the oldest bound texture, sorry.
-                        this._textureCollisions.addCount(1, false);
-                        return this._removeDesignatedSlot(this._boundTexturesStack[0]);
-                    }
-                }
-            }
-            return channel;
-        };
         Engine.prototype._bindSamplerUniformToChannel = function (sourceSlot, destination) {
             var uniform = this._boundUniforms[sourceSlot];
+            if (uniform._currentState === destination) {
+                return;
+            }
             this._gl.uniform1i(uniform, destination);
+            uniform._currentState = destination;
         };
         Engine.prototype._setTexture = function (channel, texture, isPartOfTextureArray) {
             if (isPartOfTextureArray === void 0) { isPartOfTextureArray = false; }
             // Not ready?
             if (!texture) {
                 if (this._boundTexturesCache[channel] != null) {
-                    this._activateTextureChannel(channel);
+                    this._activeChannel = channel;
                     this._bindTextureDirectly(this._gl.TEXTURE_2D, null);
                     this._bindTextureDirectly(this._gl.TEXTURE_CUBE_MAP, null);
                     if (this.webGLVersion > 1) {
@@ -12805,10 +12831,8 @@ var BABYLON;
                 return false;
             }
             // Video
-            var alreadyActivated = false;
             if (texture.video) {
-                this._activateTextureChannel(channel);
-                alreadyActivated = true;
+                this._activeChannel = channel;
                 texture.update();
             }
             else if (texture.delayLoadState === Engine.DELAYLOADSTATE_NOTLOADED) {
@@ -12838,9 +12862,7 @@ var BABYLON;
                 }
                 return false;
             }
-            if (!alreadyActivated) {
-                this._activateTextureChannel(channel);
-            }
+            this._activeChannel = channel;
             if (internalTexture && internalTexture.is3D) {
                 this._bindTextureDirectly(this._gl.TEXTURE_3D, internalTexture, isPartOfTextureArray);
                 if (internalTexture && internalTexture._cachedWrapU !== texture.wrapU) {
@@ -13118,7 +13140,7 @@ var BABYLON;
             // Remove from Instances
             var index = Engine.Instances.indexOf(this);
             if (index >= 0) {
-                Engine.Instances.splice(index, 1);
+                delete Engine.Instances[index];
             }
             this._workingCanvas = null;
             this._workingContext = null;
@@ -13513,7 +13535,7 @@ var BABYLON;
             var request = BABYLON.Tools.LoadFile(url, onSuccess, onProgress, database, useArrayBuffer, onError);
             this._activeRequests.push(request);
             request.onCompleteObservable.add(function (request) {
-                _this._activeRequests.splice(_this._activeRequests.indexOf(request), 1);
+                delete _this._activeRequests[_this._activeRequests.indexOf(request)];
             });
             return request;
         };
@@ -18877,10 +18899,8 @@ var BABYLON;
             var engine = this._scene.getEngine();
             // Depth only
             if (this._depthOnlySubMeshes.length !== 0) {
-                engine.setAlphaTesting(true);
                 engine.setColorWrite(false);
                 this._renderAlphaTest(this._depthOnlySubMeshes);
-                engine.setAlphaTesting(false);
                 engine.setColorWrite(true);
             }
             // Opaque
@@ -18889,9 +18909,7 @@ var BABYLON;
             }
             // Alpha test
             if (this._alphaTestSubMeshes.length !== 0) {
-                engine.setAlphaTesting(true);
                 this._renderAlphaTest(this._alphaTestSubMeshes);
-                engine.setAlphaTesting(false);
             }
             var stencilState = engine.getStencilBuffer();
             engine.setStencilBuffer(false);
@@ -18968,10 +18986,8 @@ var BABYLON;
                     if (material && material.needDepthPrePass) {
                         var engine = material.getScene().getEngine();
                         engine.setColorWrite(false);
-                        engine.setAlphaTesting(true);
                         engine.setAlphaMode(BABYLON.Engine.ALPHA_DISABLE);
                         subMesh.render(false);
-                        engine.setAlphaTesting(false);
                         engine.setColorWrite(true);
                     }
                 }
@@ -25363,28 +25379,22 @@ var BABYLON;
             this.computeWorldMatrix();
             var mat = this.material || scene.defaultMaterial;
             if (mat) {
-                var currentAlphaTestingState = engine.getAlphaTesting();
                 if (mat.storeEffectOnSubMeshes) {
                     for (var _i = 0, _a = this.subMeshes; _i < _a.length; _i++) {
                         var subMesh = _a[_i];
                         var effectiveMaterial = subMesh.getMaterial();
                         if (effectiveMaterial) {
-                            engine.setAlphaTesting(effectiveMaterial.needAlphaTesting() && !effectiveMaterial.needAlphaBlendingForMesh(this));
                             if (!effectiveMaterial.isReadyForSubMesh(this, subMesh, hardwareInstancedRendering)) {
-                                engine.setAlphaTesting(currentAlphaTestingState);
                                 return false;
                             }
                         }
                     }
                 }
                 else {
-                    engine.setAlphaTesting(mat.needAlphaTesting() && !mat.needAlphaBlendingForMesh(this));
                     if (!mat.isReady(this, hardwareInstancedRendering)) {
-                        engine.setAlphaTesting(currentAlphaTestingState);
                         return false;
                     }
                 }
-                engine.setAlphaTesting(currentAlphaTestingState);
             }
             // Shadows
             for (var _b = 0, _c = this._lightSources; _b < _c.length; _b++) {
@@ -28656,6 +28666,9 @@ var BABYLON;
                 this.bindSceneUniformBuffer(effect, this.getScene().getSceneUniformBuffer());
             }
         };
+        Material.prototype._shouldTurnAlphaTestOn = function (mesh) {
+            return (!this.needAlphaBlendingForMesh(mesh) && this.needAlphaTesting());
+        };
         Material.prototype._afterBind = function (mesh) {
             this._scene._cachedMaterial = this;
             if (mesh) {
@@ -28704,10 +28717,9 @@ var BABYLON;
          */
         Material.prototype.forceCompilation = function (mesh, onCompiled, options) {
             var _this = this;
-            var localOptions = __assign({ alphaTest: null, clipPlane: false }, options);
+            var localOptions = __assign({ clipPlane: false }, options);
             var subMesh = new BABYLON.BaseSubMesh();
             var scene = this.getScene();
-            var engine = scene.getEngine();
             var checkReady = function () {
                 if (!_this._scene || !_this._scene.getEngine()) {
                     return;
@@ -28715,9 +28727,7 @@ var BABYLON;
                 if (subMesh._materialDefines) {
                     subMesh._materialDefines._renderId = -1;
                 }
-                var alphaTestState = engine.getAlphaTesting();
                 var clipPlaneState = scene.clipPlane;
-                engine.setAlphaTesting(localOptions.alphaTest || (!_this.needAlphaBlendingForMesh(mesh) && _this.needAlphaTesting()));
                 if (localOptions.clipPlane) {
                     scene.clipPlane = new BABYLON.Plane(0, 0, 0, 1);
                 }
@@ -28741,7 +28751,6 @@ var BABYLON;
                         setTimeout(checkReady, 16);
                     }
                 }
-                engine.setAlphaTesting(alphaTestState);
                 if (options && options.clipPlane) {
                     scene.clipPlane = clipPlaneState;
                 }
@@ -34743,14 +34752,21 @@ var BABYLON;
                 defines["NONUNIFORMSCALING"] = mesh.nonUniformScaling;
             }
         };
-        MaterialHelper.PrepareDefinesForFrameBoundValues = function (scene, engine, defines, useInstances, forceAlphaTest) {
-            if (forceAlphaTest === void 0) { forceAlphaTest = false; }
+        /**
+         * Helper used to prepare the list of defines for shader compilation
+         * @param scene defines the current scene
+         * @param engine defines the current engine
+         * @param defines specifies the list of active defines
+         * @param useInstances defines if instances have to be turned on
+         * @param alphaTest defines if alpha testing has to be turned on
+         */
+        MaterialHelper.PrepareDefinesForFrameBoundValues = function (scene, engine, defines, useInstances, alphaTest) {
             var changed = false;
             if (defines["CLIPPLANE"] !== (scene.clipPlane !== undefined && scene.clipPlane !== null)) {
                 defines["CLIPPLANE"] = !defines["CLIPPLANE"];
                 changed = true;
             }
-            if (defines["ALPHATEST"] !== (engine.getAlphaTesting() || forceAlphaTest)) {
+            if (defines["ALPHATEST"] !== alphaTest) {
                 defines["ALPHATEST"] = !defines["ALPHATEST"];
                 changed = true;
             }
@@ -35733,7 +35749,7 @@ var BABYLON;
             // Attribs
             BABYLON.MaterialHelper.PrepareDefinesForAttributes(mesh, defines, true, true, true);
             // Values that need to be evaluated on every frame
-            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances);
+            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances, this._shouldTurnAlphaTestOn(mesh));
             // Get correct effect      
             if (defines.isDirty) {
                 defines.markAsProcessed();
@@ -37328,7 +37344,7 @@ var BABYLON;
             // Misc.
             BABYLON.MaterialHelper.PrepareDefinesForMisc(mesh, scene, this._useLogarithmicDepth, this.pointsCloud, this.fogEnabled, defines);
             // Values that need to be evaluated on every frame
-            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false, this._forceAlphaTest);
+            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false, this._shouldTurnAlphaTestOn(mesh) || this._forceAlphaTest);
             // Attribs
             if (BABYLON.MaterialHelper.PrepareDefinesForAttributes(mesh, defines, true, true, true, this._transparencyMode !== BABYLON.PBRMaterial.PBRMATERIAL_OPAQUE) && mesh) {
                 var bufferMesh = null;
@@ -42663,7 +42679,7 @@ var BABYLON;
             this._targetedAnimations = new Array();
             this._animatables = new Array();
             this._from = Number.MAX_VALUE;
-            this._to = Number.MIN_VALUE;
+            this._to = -Number.MAX_VALUE;
             this._speedRatio = 1;
             this.onAnimationEndObservable = new BABYLON.Observable();
             this._scene = scene || BABYLON.Engine.LastCreatedScene;
@@ -42702,6 +42718,16 @@ var BABYLON;
             enumerable: true,
             configurable: true
         });
+        Object.defineProperty(AnimationGroup.prototype, "targetedAnimations", {
+            /**
+             * Gets the targeted animations for this animation group
+             */
+            get: function () {
+                return this._targetedAnimations;
+            },
+            enumerable: true,
+            configurable: true
+        });
         /**
          * Add an animation (with its target) in the group
          * @param animation defines the animation we want to add
@@ -42726,11 +42752,13 @@ var BABYLON;
         /**
          * This function will normalize every animation in the group to make sure they all go from beginFrame to endFrame
          * It can add constant keys at begin or end
-         * @param beginFrame defines the new begin frame for all animations. It can't be bigger than the smaller begin frame of all animations
-         * @param endFrame defines the new end frame for all animations. It can't be smaller than the larger end frame of all animations
+         * @param beginFrame defines the new begin frame for all animations. It can't be bigger than the smallest begin frame of all animations
+         * @param endFrame defines the new end frame for all animations. It can't be smaller than the largest end frame of all animations
          */
         AnimationGroup.prototype.normalize = function (beginFrame, endFrame) {
-            beginFrame = Math.min(beginFrame, this._from);
+            if (beginFrame === void 0) { beginFrame = -Number.MAX_VALUE; }
+            if (endFrame === void 0) { endFrame = Number.MAX_VALUE; }
+            beginFrame = Math.max(beginFrame, this._from);
             endFrame = Math.min(endFrame, this._to);
             for (var index = 0; index < this._targetedAnimations.length; index++) {
                 var targetedAnimation = this._targetedAnimations[index];
@@ -42742,7 +42770,8 @@ var BABYLON;
                         frame: beginFrame,
                         value: startKey.value,
                         inTangent: startKey.inTangent,
-                        outTangent: startKey.outTangent
+                        outTangent: startKey.outTangent,
+                        interpolation: startKey.interpolation
                     };
                     keys.splice(0, 0, newKey);
                 }
@@ -42750,8 +42779,9 @@ var BABYLON;
                     var newKey = {
                         frame: endFrame,
                         value: endKey.value,
-                        inTangent: startKey.outTangent,
-                        outTangent: startKey.outTangent
+                        inTangent: endKey.outTangent,
+                        outTangent: endKey.outTangent,
+                        interpolation: endKey.interpolation
                     };
                     keys.push(newKey);
                 }
@@ -48602,7 +48632,7 @@ var BABYLON;
                 }
             }
             // Alpha test
-            if (engine.getAlphaTesting()) {
+            if (mesh && this._shouldTurnAlphaTestOn(mesh)) {
                 defines.push("#define ALPHATEST");
             }
             var previousEffect = this._effect;
@@ -62880,11 +62910,9 @@ var BABYLON;
                 for (index = 0; index < opaqueSubMeshes.length; index++) {
                     renderSubMesh(opaqueSubMeshes.data[index]);
                 }
-                engine.setAlphaTesting(true);
                 for (index = 0; index < alphaTestSubMeshes.length; index++) {
                     renderSubMesh(alphaTestSubMeshes.data[index]);
                 }
-                engine.setAlphaTesting(false);
                 if (transparentSubMeshes.length) {
                     // Sort sub meshes
                     for (index = 0; index < transparentSubMeshes.length; index++) {
@@ -81446,7 +81474,7 @@ var BABYLON;
             // Misc.
             BABYLON.MaterialHelper.PrepareDefinesForMisc(mesh, scene, false, this.pointsCloud, this.fogEnabled, defines);
             // Values that need to be evaluated on every frame
-            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances, false);
+            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances, this._shouldTurnAlphaTestOn(mesh));
             // Attribs
             if (BABYLON.MaterialHelper.PrepareDefinesForAttributes(mesh, defines, false, true, false)) {
                 if (mesh) {
@@ -85363,6 +85391,10 @@ var BABYLON;
                 if (!animations) {
                     return;
                 }
+                for (var _i = 0, animations_1 = animations; _i < animations_1.length; _i++) {
+                    var animation = animations_1[_i];
+                    animation.babylonAnimationGroup.normalize();
+                }
                 switch (this.animationStartMode) {
                     case BABYLON.GLTFLoaderAnimationStartMode.NONE: {
                         // do nothing
@@ -85370,19 +85402,13 @@ var BABYLON;
                     }
                     case BABYLON.GLTFLoaderAnimationStartMode.FIRST: {
                         var animation = animations[0];
-                        for (var _i = 0, _a = animation.targets; _i < _a.length; _i++) {
-                            var target = _a[_i];
-                            this._babylonScene.beginAnimation(target, 0, Number.MAX_VALUE, true);
-                        }
+                        animation.babylonAnimationGroup.start(true);
                         break;
                     }
                     case BABYLON.GLTFLoaderAnimationStartMode.ALL: {
-                        for (var _b = 0, animations_1 = animations; _b < animations_1.length; _b++) {
-                            var animation = animations_1[_b];
-                            for (var _c = 0, _d = animation.targets; _c < _d.length; _c++) {
-                                var target = _d[_c];
-                                this._babylonScene.beginAnimation(target, 0, Number.MAX_VALUE, true);
-                            }
+                        for (var _a = 0, animations_2 = animations; _a < animations_2.length; _a++) {
+                            var animation = animations_2[_a];
+                            animation.babylonAnimationGroup.start(true);
                         }
                         break;
                     }
@@ -85994,7 +86020,7 @@ var BABYLON;
                 }
             };
             GLTFLoader.prototype._loadAnimation = function (context, animation) {
-                animation.targets = [];
+                animation.babylonAnimationGroup = new BABYLON.AnimationGroup(animation.name || "animation" + animation.index, this._babylonScene);
                 for (var index = 0; index < animation.channels.length; index++) {
                     var channel = GLTFLoader._GetProperty(animation.channels, index);
                     if (!channel) {
@@ -86134,7 +86160,7 @@ var BABYLON;
                         var morphTargetManager = targetNode.babylonMesh.morphTargetManager;
                         var _loop_7 = function (targetIndex) {
                             var morphTarget = morphTargetManager.getTarget(targetIndex);
-                            var animationName = (animation.name || "anim" + animation.index) + "_" + targetIndex;
+                            var animationName = animation.babylonAnimationGroup.name + "_channel" + animation.babylonAnimationGroup.targetedAnimations.length;
                             var babylonAnimation = new BABYLON.Animation(animationName, targetPath, 1, animationType);
                             babylonAnimation.setKeys(keys.map(function (key) { return ({
                                 frame: key.frame,
@@ -86142,22 +86168,20 @@ var BABYLON;
                                 value: key.value[targetIndex],
                                 outTangent: key.outTangent ? key.outTangent[targetIndex] : undefined
                             }); }));
-                            morphTarget.animations.push(babylonAnimation);
-                            animation.targets.push(morphTarget);
+                            animation.babylonAnimationGroup.addTargetedAnimation(babylonAnimation, morphTarget);
                         };
                         for (var targetIndex = 0; targetIndex < morphTargetManager.numTargets; targetIndex++) {
                             _loop_7(targetIndex);
                         }
                     }
                     else {
-                        var animationName = animation.name || "anim" + animation.index;
+                        var animationName = animation.babylonAnimationGroup.name + "_channel" + animation.babylonAnimationGroup.targetedAnimations.length;
                         var babylonAnimation = new BABYLON.Animation(animationName, targetPath, 1, animationType);
                         babylonAnimation.setKeys(keys);
                         if (targetNode.babylonAnimationTargets) {
                             for (var _i = 0, _a = targetNode.babylonAnimationTargets; _i < _a.length; _i++) {
                                 var target = _a[_i];
-                                target.animations.push(babylonAnimation.clone());
-                                animation.targets.push(target);
+                                animation.babylonAnimationGroup.addTargetedAnimation(babylonAnimation, target);
                             }
                         }
                     }

+ 126 - 98
dist/preview release/es6.js

@@ -7469,6 +7469,26 @@ var BABYLON;
             }
             Tools.EncodeScreenshotCanvasData(successCallback, mimeType);
         };
+        /**
+         * Generates an image screenshot from the specified camera.
+         *
+         * @param engine The engine to use for rendering
+         * @param camera The camera to use for rendering
+         * @param size This parameter can be set to a single number or to an object with the
+         * following (optional) properties: precision, width, height. If a single number is passed,
+         * it will be used for both width and height. If an object is passed, the screenshot size
+         * will be derived from the parameters. The precision property is a multiplier allowing
+         * rendering at a higher or lower resolution.
+         * @param successCallback The callback receives a single parameter which contains the
+         * screenshot as a string of base64-encoded characters. This string can be assigned to the
+         * src parameter of an <img> to display it.
+         * @param mimeType The MIME type of the screenshot image (default: image/png).
+         * Check your browser for supported MIME types.
+         * @param samples Texture samples (default: 1)
+         * @param antialiasing Whether antialiasing should be turned on or not (default: false)
+         * @param fileName A name for for the downloaded file.
+         * @constructor
+         */
         Tools.CreateScreenshotUsingRenderTarget = function (engine, camera, size, successCallback, mimeType, samples, antialiasing, fileName) {
             if (mimeType === void 0) { mimeType = "image/png"; }
             if (samples === void 0) { samples = 1; }
@@ -8871,9 +8891,10 @@ var BABYLON;
     var Engine = /** @class */ (function () {
         /**
          * @constructor
-         * @param {HTMLCanvasElement | WebGLRenderingContext} canvasOrContext - the canvas or the webgl context to be used for rendering
-         * @param {boolean} [antialias] - enable antialias
-         * @param options - further options to be sent to the getContext function
+         * @param canvasOrContext defines the canvas or WebGL context to use for rendering
+         * @param antialias defines enable antialiasing (default: false)
+         * @param options defines further options to be sent to the getContext() function
+         * @param adaptToDeviceRatio defines whether to adapt to the device's viewport characteristics (default: false)
          */
         function Engine(canvasOrContext, antialias, options, adaptToDeviceRatio) {
             if (adaptToDeviceRatio === void 0) { adaptToDeviceRatio = false; }
@@ -8975,6 +8996,8 @@ var BABYLON;
             this._alphaMode = Engine.ALPHA_DISABLE;
             // Cache
             this._internalTexturesCache = new Array();
+            this._activeChannel = 0;
+            this._currentTextureChannel = -1;
             this._boundTexturesCache = {};
             this._boundTexturesStack = new Array();
             this._compiledEffects = {};
@@ -9890,7 +9913,7 @@ var BABYLON;
             for (var slot = 0; slot < this._maxSimultaneousTextures; slot++) {
                 this._nextFreeTextureSlots.push(slot);
             }
-            this._activeChannel = -1;
+            this._currentTextureChannel = -1;
         };
         Engine.prototype.isDeterministicLockStep = function () {
             return this._deterministicLockstep;
@@ -11280,12 +11303,6 @@ var BABYLON;
         Engine.prototype.getAlphaMode = function () {
             return this._alphaMode;
         };
-        Engine.prototype.setAlphaTesting = function (enable) {
-            this._alphaTest = enable;
-        };
-        Engine.prototype.getAlphaTesting = function () {
-            return !!this._alphaTest;
-        };
         // Textures
         Engine.prototype.wipeCaches = function (bruteForce) {
             if (this.preventCacheWipeBetweenFrames && !bruteForce) {
@@ -12673,12 +12690,6 @@ var BABYLON;
             }
             this._currentEffect = null;
         };
-        Engine.prototype._activateTextureChannel = function (channel) {
-            if (this._activeChannel !== channel && channel > -1) {
-                this._gl.activeTexture(this._gl.TEXTURE0 + channel);
-                this._activeChannel = channel;
-            }
-        };
         Engine.prototype._moveBoundTextureOnTop = function (internalTexture) {
             var index = this._boundTexturesStack.indexOf(internalTexture);
             if (index > -1 && index !== this._boundTexturesStack.length - 1) {
@@ -12686,6 +12697,34 @@ var BABYLON;
                 this._boundTexturesStack.push(internalTexture);
             }
         };
+        Engine.prototype._getCorrectTextureChannel = function (channel, internalTexture) {
+            if (!internalTexture) {
+                return -1;
+            }
+            internalTexture._initialSlot = channel;
+            if (this.disableTextureBindingOptimization) {
+                if (channel !== internalTexture._designatedSlot) {
+                    this._textureCollisions.addCount(1, false);
+                }
+            }
+            else {
+                if (channel !== internalTexture._designatedSlot) {
+                    if (internalTexture._designatedSlot > -1) {
+                        return internalTexture._designatedSlot;
+                    }
+                    else {
+                        // No slot for this texture, let's pick a new one (if we find a free slot)
+                        if (this._nextFreeTextureSlots.length) {
+                            return this._nextFreeTextureSlots[0];
+                        }
+                        // We need to recycle the oldest bound texture, sorry.
+                        this._textureCollisions.addCount(1, false);
+                        return this._removeDesignatedSlot(this._boundTexturesStack[0]);
+                    }
+                }
+            }
+            return channel;
+        };
         Engine.prototype._removeDesignatedSlot = function (internalTexture) {
             var currentSlot = internalTexture._designatedSlot;
             internalTexture._designatedSlot = -1;
@@ -12699,31 +12738,42 @@ var BABYLON;
             }
             return currentSlot;
         };
-        Engine.prototype._bindTextureDirectly = function (target, texture, doNotBindUniformToTextureChannel) {
-            if (doNotBindUniformToTextureChannel === void 0) { doNotBindUniformToTextureChannel = false; }
+        Engine.prototype._activateCurrentTexture = function () {
+            if (this._currentTextureChannel !== this._activeChannel) {
+                this._gl.activeTexture(this._gl.TEXTURE0 + this._activeChannel);
+                this._currentTextureChannel = this._activeChannel;
+            }
+        };
+        Engine.prototype._bindTextureDirectly = function (target, texture, forTextureDataUpdate) {
+            if (forTextureDataUpdate === void 0) { forTextureDataUpdate = false; }
+            if (forTextureDataUpdate && texture && texture._designatedSlot > -1) {
+                this._activeChannel = texture._designatedSlot;
+            }
             var currentTextureBound = this._boundTexturesCache[this._activeChannel];
             var isTextureForRendering = texture && texture._initialSlot > -1;
             if (currentTextureBound !== texture) {
                 if (currentTextureBound && !this.disableTextureBindingOptimization) {
                     this._removeDesignatedSlot(currentTextureBound);
                 }
+                this._activateCurrentTexture();
                 this._gl.bindTexture(target, texture ? texture._webGLTexture : null);
-                if (this._activeChannel >= 0) {
-                    this._boundTexturesCache[this._activeChannel] = texture;
-                    if (isTextureForRendering && !this.disableTextureBindingOptimization) {
+                this._boundTexturesCache[this._activeChannel] = texture;
+                if (texture) {
+                    if (!this.disableTextureBindingOptimization) {
                         var slotIndex = this._nextFreeTextureSlots.indexOf(this._activeChannel);
                         if (slotIndex > -1) {
                             this._nextFreeTextureSlots.splice(slotIndex, 1);
                         }
                         this._boundTexturesStack.push(texture);
                     }
+                    texture._designatedSlot = this._activeChannel;
                 }
             }
-            if (isTextureForRendering && this._activeChannel > -1) {
-                texture._designatedSlot = this._activeChannel;
-                if (!doNotBindUniformToTextureChannel) {
-                    this._bindSamplerUniformToChannel(texture._initialSlot, this._activeChannel);
-                }
+            else if (forTextureDataUpdate) {
+                this._activateCurrentTexture();
+            }
+            if (isTextureForRendering && !forTextureDataUpdate) {
+                this._bindSamplerUniformToChannel(texture._initialSlot, this._activeChannel);
             }
         };
         Engine.prototype._bindTexture = function (channel, texture) {
@@ -12733,7 +12783,7 @@ var BABYLON;
             if (texture) {
                 channel = this._getCorrectTextureChannel(channel, texture);
             }
-            this._activateTextureChannel(channel);
+            this._activeChannel = channel;
             this._bindTextureDirectly(this._gl.TEXTURE_2D, texture);
         };
         Engine.prototype.setTextureFromPostProcess = function (channel, postProcess) {
@@ -12741,7 +12791,7 @@ var BABYLON;
         };
         Engine.prototype.unbindAllTextures = function () {
             for (var channel = 0; channel < this._maxSimultaneousTextures; channel++) {
-                this._activateTextureChannel(channel);
+                this._activeChannel = channel;
                 this._bindTextureDirectly(this._gl.TEXTURE_2D, null);
                 this._bindTextureDirectly(this._gl.TEXTURE_CUBE_MAP, null);
                 if (this.webGLVersion > 1) {
@@ -12758,44 +12808,20 @@ var BABYLON;
             }
             this._setTexture(channel, texture);
         };
-        Engine.prototype._getCorrectTextureChannel = function (channel, internalTexture) {
-            if (!internalTexture) {
-                return -1;
-            }
-            internalTexture._initialSlot = channel;
-            if (this.disableTextureBindingOptimization) {
-                if (channel !== internalTexture._designatedSlot) {
-                    this._textureCollisions.addCount(1, false);
-                }
-            }
-            else {
-                if (channel !== internalTexture._designatedSlot) {
-                    if (internalTexture._designatedSlot > -1) {
-                        return internalTexture._designatedSlot;
-                    }
-                    else {
-                        // No slot for this texture, let's pick a new one (if we find a free slot)
-                        if (this._nextFreeTextureSlots.length) {
-                            return this._nextFreeTextureSlots[0];
-                        }
-                        // We need to recycle the oldest bound texture, sorry.
-                        this._textureCollisions.addCount(1, false);
-                        return this._removeDesignatedSlot(this._boundTexturesStack[0]);
-                    }
-                }
-            }
-            return channel;
-        };
         Engine.prototype._bindSamplerUniformToChannel = function (sourceSlot, destination) {
             var uniform = this._boundUniforms[sourceSlot];
+            if (uniform._currentState === destination) {
+                return;
+            }
             this._gl.uniform1i(uniform, destination);
+            uniform._currentState = destination;
         };
         Engine.prototype._setTexture = function (channel, texture, isPartOfTextureArray) {
             if (isPartOfTextureArray === void 0) { isPartOfTextureArray = false; }
             // Not ready?
             if (!texture) {
                 if (this._boundTexturesCache[channel] != null) {
-                    this._activateTextureChannel(channel);
+                    this._activeChannel = channel;
                     this._bindTextureDirectly(this._gl.TEXTURE_2D, null);
                     this._bindTextureDirectly(this._gl.TEXTURE_CUBE_MAP, null);
                     if (this.webGLVersion > 1) {
@@ -12805,10 +12831,8 @@ var BABYLON;
                 return false;
             }
             // Video
-            var alreadyActivated = false;
             if (texture.video) {
-                this._activateTextureChannel(channel);
-                alreadyActivated = true;
+                this._activeChannel = channel;
                 texture.update();
             }
             else if (texture.delayLoadState === Engine.DELAYLOADSTATE_NOTLOADED) {
@@ -12838,9 +12862,7 @@ var BABYLON;
                 }
                 return false;
             }
-            if (!alreadyActivated) {
-                this._activateTextureChannel(channel);
-            }
+            this._activeChannel = channel;
             if (internalTexture && internalTexture.is3D) {
                 this._bindTextureDirectly(this._gl.TEXTURE_3D, internalTexture, isPartOfTextureArray);
                 if (internalTexture && internalTexture._cachedWrapU !== texture.wrapU) {
@@ -13118,7 +13140,7 @@ var BABYLON;
             // Remove from Instances
             var index = Engine.Instances.indexOf(this);
             if (index >= 0) {
-                Engine.Instances.splice(index, 1);
+                delete Engine.Instances[index];
             }
             this._workingCanvas = null;
             this._workingContext = null;
@@ -13513,7 +13535,7 @@ var BABYLON;
             var request = BABYLON.Tools.LoadFile(url, onSuccess, onProgress, database, useArrayBuffer, onError);
             this._activeRequests.push(request);
             request.onCompleteObservable.add(function (request) {
-                _this._activeRequests.splice(_this._activeRequests.indexOf(request), 1);
+                delete _this._activeRequests[_this._activeRequests.indexOf(request)];
             });
             return request;
         };
@@ -18877,10 +18899,8 @@ var BABYLON;
             var engine = this._scene.getEngine();
             // Depth only
             if (this._depthOnlySubMeshes.length !== 0) {
-                engine.setAlphaTesting(true);
                 engine.setColorWrite(false);
                 this._renderAlphaTest(this._depthOnlySubMeshes);
-                engine.setAlphaTesting(false);
                 engine.setColorWrite(true);
             }
             // Opaque
@@ -18889,9 +18909,7 @@ var BABYLON;
             }
             // Alpha test
             if (this._alphaTestSubMeshes.length !== 0) {
-                engine.setAlphaTesting(true);
                 this._renderAlphaTest(this._alphaTestSubMeshes);
-                engine.setAlphaTesting(false);
             }
             var stencilState = engine.getStencilBuffer();
             engine.setStencilBuffer(false);
@@ -18968,10 +18986,8 @@ var BABYLON;
                     if (material && material.needDepthPrePass) {
                         var engine = material.getScene().getEngine();
                         engine.setColorWrite(false);
-                        engine.setAlphaTesting(true);
                         engine.setAlphaMode(BABYLON.Engine.ALPHA_DISABLE);
                         subMesh.render(false);
-                        engine.setAlphaTesting(false);
                         engine.setColorWrite(true);
                     }
                 }
@@ -25363,28 +25379,22 @@ var BABYLON;
             this.computeWorldMatrix();
             var mat = this.material || scene.defaultMaterial;
             if (mat) {
-                var currentAlphaTestingState = engine.getAlphaTesting();
                 if (mat.storeEffectOnSubMeshes) {
                     for (var _i = 0, _a = this.subMeshes; _i < _a.length; _i++) {
                         var subMesh = _a[_i];
                         var effectiveMaterial = subMesh.getMaterial();
                         if (effectiveMaterial) {
-                            engine.setAlphaTesting(effectiveMaterial.needAlphaTesting() && !effectiveMaterial.needAlphaBlendingForMesh(this));
                             if (!effectiveMaterial.isReadyForSubMesh(this, subMesh, hardwareInstancedRendering)) {
-                                engine.setAlphaTesting(currentAlphaTestingState);
                                 return false;
                             }
                         }
                     }
                 }
                 else {
-                    engine.setAlphaTesting(mat.needAlphaTesting() && !mat.needAlphaBlendingForMesh(this));
                     if (!mat.isReady(this, hardwareInstancedRendering)) {
-                        engine.setAlphaTesting(currentAlphaTestingState);
                         return false;
                     }
                 }
-                engine.setAlphaTesting(currentAlphaTestingState);
             }
             // Shadows
             for (var _b = 0, _c = this._lightSources; _b < _c.length; _b++) {
@@ -28656,6 +28666,9 @@ var BABYLON;
                 this.bindSceneUniformBuffer(effect, this.getScene().getSceneUniformBuffer());
             }
         };
+        Material.prototype._shouldTurnAlphaTestOn = function (mesh) {
+            return (!this.needAlphaBlendingForMesh(mesh) && this.needAlphaTesting());
+        };
         Material.prototype._afterBind = function (mesh) {
             this._scene._cachedMaterial = this;
             if (mesh) {
@@ -28704,10 +28717,9 @@ var BABYLON;
          */
         Material.prototype.forceCompilation = function (mesh, onCompiled, options) {
             var _this = this;
-            var localOptions = __assign({ alphaTest: null, clipPlane: false }, options);
+            var localOptions = __assign({ clipPlane: false }, options);
             var subMesh = new BABYLON.BaseSubMesh();
             var scene = this.getScene();
-            var engine = scene.getEngine();
             var checkReady = function () {
                 if (!_this._scene || !_this._scene.getEngine()) {
                     return;
@@ -28715,9 +28727,7 @@ var BABYLON;
                 if (subMesh._materialDefines) {
                     subMesh._materialDefines._renderId = -1;
                 }
-                var alphaTestState = engine.getAlphaTesting();
                 var clipPlaneState = scene.clipPlane;
-                engine.setAlphaTesting(localOptions.alphaTest || (!_this.needAlphaBlendingForMesh(mesh) && _this.needAlphaTesting()));
                 if (localOptions.clipPlane) {
                     scene.clipPlane = new BABYLON.Plane(0, 0, 0, 1);
                 }
@@ -28741,7 +28751,6 @@ var BABYLON;
                         setTimeout(checkReady, 16);
                     }
                 }
-                engine.setAlphaTesting(alphaTestState);
                 if (options && options.clipPlane) {
                     scene.clipPlane = clipPlaneState;
                 }
@@ -34743,14 +34752,21 @@ var BABYLON;
                 defines["NONUNIFORMSCALING"] = mesh.nonUniformScaling;
             }
         };
-        MaterialHelper.PrepareDefinesForFrameBoundValues = function (scene, engine, defines, useInstances, forceAlphaTest) {
-            if (forceAlphaTest === void 0) { forceAlphaTest = false; }
+        /**
+         * Helper used to prepare the list of defines for shader compilation
+         * @param scene defines the current scene
+         * @param engine defines the current engine
+         * @param defines specifies the list of active defines
+         * @param useInstances defines if instances have to be turned on
+         * @param alphaTest defines if alpha testing has to be turned on
+         */
+        MaterialHelper.PrepareDefinesForFrameBoundValues = function (scene, engine, defines, useInstances, alphaTest) {
             var changed = false;
             if (defines["CLIPPLANE"] !== (scene.clipPlane !== undefined && scene.clipPlane !== null)) {
                 defines["CLIPPLANE"] = !defines["CLIPPLANE"];
                 changed = true;
             }
-            if (defines["ALPHATEST"] !== (engine.getAlphaTesting() || forceAlphaTest)) {
+            if (defines["ALPHATEST"] !== alphaTest) {
                 defines["ALPHATEST"] = !defines["ALPHATEST"];
                 changed = true;
             }
@@ -35733,7 +35749,7 @@ var BABYLON;
             // Attribs
             BABYLON.MaterialHelper.PrepareDefinesForAttributes(mesh, defines, true, true, true);
             // Values that need to be evaluated on every frame
-            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances);
+            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances, this._shouldTurnAlphaTestOn(mesh));
             // Get correct effect      
             if (defines.isDirty) {
                 defines.markAsProcessed();
@@ -37328,7 +37344,7 @@ var BABYLON;
             // Misc.
             BABYLON.MaterialHelper.PrepareDefinesForMisc(mesh, scene, this._useLogarithmicDepth, this.pointsCloud, this.fogEnabled, defines);
             // Values that need to be evaluated on every frame
-            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false, this._forceAlphaTest);
+            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false, this._shouldTurnAlphaTestOn(mesh) || this._forceAlphaTest);
             // Attribs
             if (BABYLON.MaterialHelper.PrepareDefinesForAttributes(mesh, defines, true, true, true, this._transparencyMode !== BABYLON.PBRMaterial.PBRMATERIAL_OPAQUE) && mesh) {
                 var bufferMesh = null;
@@ -42663,7 +42679,7 @@ var BABYLON;
             this._targetedAnimations = new Array();
             this._animatables = new Array();
             this._from = Number.MAX_VALUE;
-            this._to = Number.MIN_VALUE;
+            this._to = -Number.MAX_VALUE;
             this._speedRatio = 1;
             this.onAnimationEndObservable = new BABYLON.Observable();
             this._scene = scene || BABYLON.Engine.LastCreatedScene;
@@ -42702,6 +42718,16 @@ var BABYLON;
             enumerable: true,
             configurable: true
         });
+        Object.defineProperty(AnimationGroup.prototype, "targetedAnimations", {
+            /**
+             * Gets the targeted animations for this animation group
+             */
+            get: function () {
+                return this._targetedAnimations;
+            },
+            enumerable: true,
+            configurable: true
+        });
         /**
          * Add an animation (with its target) in the group
          * @param animation defines the animation we want to add
@@ -42726,11 +42752,13 @@ var BABYLON;
         /**
          * This function will normalize every animation in the group to make sure they all go from beginFrame to endFrame
          * It can add constant keys at begin or end
-         * @param beginFrame defines the new begin frame for all animations. It can't be bigger than the smaller begin frame of all animations
-         * @param endFrame defines the new end frame for all animations. It can't be smaller than the larger end frame of all animations
+         * @param beginFrame defines the new begin frame for all animations. It can't be bigger than the smallest begin frame of all animations
+         * @param endFrame defines the new end frame for all animations. It can't be smaller than the largest end frame of all animations
          */
         AnimationGroup.prototype.normalize = function (beginFrame, endFrame) {
-            beginFrame = Math.min(beginFrame, this._from);
+            if (beginFrame === void 0) { beginFrame = -Number.MAX_VALUE; }
+            if (endFrame === void 0) { endFrame = Number.MAX_VALUE; }
+            beginFrame = Math.max(beginFrame, this._from);
             endFrame = Math.min(endFrame, this._to);
             for (var index = 0; index < this._targetedAnimations.length; index++) {
                 var targetedAnimation = this._targetedAnimations[index];
@@ -42742,7 +42770,8 @@ var BABYLON;
                         frame: beginFrame,
                         value: startKey.value,
                         inTangent: startKey.inTangent,
-                        outTangent: startKey.outTangent
+                        outTangent: startKey.outTangent,
+                        interpolation: startKey.interpolation
                     };
                     keys.splice(0, 0, newKey);
                 }
@@ -42750,8 +42779,9 @@ var BABYLON;
                     var newKey = {
                         frame: endFrame,
                         value: endKey.value,
-                        inTangent: startKey.outTangent,
-                        outTangent: startKey.outTangent
+                        inTangent: endKey.outTangent,
+                        outTangent: endKey.outTangent,
+                        interpolation: endKey.interpolation
                     };
                     keys.push(newKey);
                 }
@@ -48756,7 +48786,7 @@ var BABYLON;
                 }
             }
             // Alpha test
-            if (engine.getAlphaTesting()) {
+            if (mesh && this._shouldTurnAlphaTestOn(mesh)) {
                 defines.push("#define ALPHATEST");
             }
             var previousEffect = this._effect;
@@ -63034,11 +63064,9 @@ var BABYLON;
                 for (index = 0; index < opaqueSubMeshes.length; index++) {
                     renderSubMesh(opaqueSubMeshes.data[index]);
                 }
-                engine.setAlphaTesting(true);
                 for (index = 0; index < alphaTestSubMeshes.length; index++) {
                     renderSubMesh(alphaTestSubMeshes.data[index]);
                 }
-                engine.setAlphaTesting(false);
                 if (transparentSubMeshes.length) {
                     // Sort sub meshes
                     for (index = 0; index < transparentSubMeshes.length; index++) {
@@ -81950,7 +81978,7 @@ var BABYLON;
             // Misc.
             BABYLON.MaterialHelper.PrepareDefinesForMisc(mesh, scene, false, this.pointsCloud, this.fogEnabled, defines);
             // Values that need to be evaluated on every frame
-            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances, false);
+            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances, this._shouldTurnAlphaTestOn(mesh));
             // Attribs
             if (BABYLON.MaterialHelper.PrepareDefinesForAttributes(mesh, defines, false, true, false)) {
                 if (mesh) {

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 4 - 4
dist/preview release/inspector/babylon.inspector.bundle.js


+ 2 - 0
dist/preview release/inspector/babylon.inspector.d.ts

@@ -780,6 +780,7 @@ declare module INSPECTOR {
         static REFRESH_TIME: number;
         /** The list of data to update */
         private _updatableProperties;
+        private interval;
         constructor();
         static getInstance(): Scheduler;
         /** Add a property line to be updated every X ms */
@@ -787,6 +788,7 @@ declare module INSPECTOR {
         /** Removes the given property from the list of properties to update */
         remove(prop: PropertyLine): void;
         private _update();
+        dispose(): void;
     }
 }
 

+ 6 - 4
dist/preview release/inspector/babylon.inspector.js

@@ -289,6 +289,7 @@ var INSPECTOR;
                     }
                 }
             }
+            INSPECTOR.Scheduler.getInstance().dispose();
         };
         /** Open the inspector in a new popup
          * Set 'firstTime' to true if there is no inspector created beforehands
@@ -1041,9 +1042,7 @@ var INSPECTOR;
     var MeshAdapter = /** @class */ (function (_super) {
         __extends(MeshAdapter, _super);
         function MeshAdapter(mesh) {
-            var _this = _super.call(this, mesh) || this;
-            new BABYLON.Debug.AxesViewer(mesh.getScene());
-            return _this;
+            return _super.call(this, mesh) || this;
         }
         /** Returns the name displayed in the tree */
         MeshAdapter.prototype.id = function () {
@@ -2433,7 +2432,7 @@ var INSPECTOR;
             this.pause = false;
             /** The list of data to update */
             this._updatableProperties = [];
-            setInterval(this._update.bind(this), Scheduler.REFRESH_TIME);
+            this.interval = setInterval(this._update.bind(this), Scheduler.REFRESH_TIME);
         }
         Scheduler.getInstance = function () {
             if (!Scheduler._instance) {
@@ -2461,6 +2460,9 @@ var INSPECTOR;
                 }
             }
         };
+        Scheduler.prototype.dispose = function () {
+            window.clearInterval(this.interval);
+        };
         /** All properties are refreshed every 250ms */
         Scheduler.REFRESH_TIME = 250;
         return Scheduler;

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 4 - 4
dist/preview release/inspector/babylon.inspector.min.js


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

@@ -225,7 +225,7 @@ declare module BABYLON.GLTF2 {
         channels: IGLTFAnimationChannel[];
         samplers: IGLTFAnimationSampler[];
         index: number;
-        targets: any[];
+        babylonAnimationGroup: AnimationGroup;
     }
     interface IGLTFAsset extends IGLTFChildRootProperty {
         copyright?: string;

+ 13 - 17
dist/preview release/loaders/babylon.glTF2FileLoader.js

@@ -673,6 +673,10 @@ var BABYLON;
                 if (!animations) {
                     return;
                 }
+                for (var _i = 0, animations_1 = animations; _i < animations_1.length; _i++) {
+                    var animation = animations_1[_i];
+                    animation.babylonAnimationGroup.normalize();
+                }
                 switch (this.animationStartMode) {
                     case BABYLON.GLTFLoaderAnimationStartMode.NONE: {
                         // do nothing
@@ -680,19 +684,13 @@ var BABYLON;
                     }
                     case BABYLON.GLTFLoaderAnimationStartMode.FIRST: {
                         var animation = animations[0];
-                        for (var _i = 0, _a = animation.targets; _i < _a.length; _i++) {
-                            var target = _a[_i];
-                            this._babylonScene.beginAnimation(target, 0, Number.MAX_VALUE, true);
-                        }
+                        animation.babylonAnimationGroup.start(true);
                         break;
                     }
                     case BABYLON.GLTFLoaderAnimationStartMode.ALL: {
-                        for (var _b = 0, animations_1 = animations; _b < animations_1.length; _b++) {
-                            var animation = animations_1[_b];
-                            for (var _c = 0, _d = animation.targets; _c < _d.length; _c++) {
-                                var target = _d[_c];
-                                this._babylonScene.beginAnimation(target, 0, Number.MAX_VALUE, true);
-                            }
+                        for (var _a = 0, animations_2 = animations; _a < animations_2.length; _a++) {
+                            var animation = animations_2[_a];
+                            animation.babylonAnimationGroup.start(true);
                         }
                         break;
                     }
@@ -1304,7 +1302,7 @@ var BABYLON;
                 }
             };
             GLTFLoader.prototype._loadAnimation = function (context, animation) {
-                animation.targets = [];
+                animation.babylonAnimationGroup = new BABYLON.AnimationGroup(animation.name || "animation" + animation.index, this._babylonScene);
                 for (var index = 0; index < animation.channels.length; index++) {
                     var channel = GLTFLoader._GetProperty(animation.channels, index);
                     if (!channel) {
@@ -1444,7 +1442,7 @@ var BABYLON;
                         var morphTargetManager = targetNode.babylonMesh.morphTargetManager;
                         var _loop_7 = function (targetIndex) {
                             var morphTarget = morphTargetManager.getTarget(targetIndex);
-                            var animationName = (animation.name || "anim" + animation.index) + "_" + targetIndex;
+                            var animationName = animation.babylonAnimationGroup.name + "_channel" + animation.babylonAnimationGroup.targetedAnimations.length;
                             var babylonAnimation = new BABYLON.Animation(animationName, targetPath, 1, animationType);
                             babylonAnimation.setKeys(keys.map(function (key) { return ({
                                 frame: key.frame,
@@ -1452,22 +1450,20 @@ var BABYLON;
                                 value: key.value[targetIndex],
                                 outTangent: key.outTangent ? key.outTangent[targetIndex] : undefined
                             }); }));
-                            morphTarget.animations.push(babylonAnimation);
-                            animation.targets.push(morphTarget);
+                            animation.babylonAnimationGroup.addTargetedAnimation(babylonAnimation, morphTarget);
                         };
                         for (var targetIndex = 0; targetIndex < morphTargetManager.numTargets; targetIndex++) {
                             _loop_7(targetIndex);
                         }
                     }
                     else {
-                        var animationName = animation.name || "anim" + animation.index;
+                        var animationName = animation.babylonAnimationGroup.name + "_channel" + animation.babylonAnimationGroup.targetedAnimations.length;
                         var babylonAnimation = new BABYLON.Animation(animationName, targetPath, 1, animationType);
                         babylonAnimation.setKeys(keys);
                         if (targetNode.babylonAnimationTargets) {
                             for (var _i = 0, _a = targetNode.babylonAnimationTargets; _i < _a.length; _i++) {
                                 var target = _a[_i];
-                                target.animations.push(babylonAnimation.clone());
-                                animation.targets.push(target);
+                                animation.babylonAnimationGroup.addTargetedAnimation(babylonAnimation, target);
                             }
                         }
                     }

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 2 - 2
dist/preview release/loaders/babylon.glTF2FileLoader.min.js


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

@@ -782,7 +782,7 @@ declare module BABYLON.GLTF2 {
         channels: IGLTFAnimationChannel[];
         samplers: IGLTFAnimationSampler[];
         index: number;
-        targets: any[];
+        babylonAnimationGroup: AnimationGroup;
     }
     interface IGLTFAsset extends IGLTFChildRootProperty {
         copyright?: string;

+ 13 - 17
dist/preview release/loaders/babylon.glTFFileLoader.js

@@ -2839,6 +2839,10 @@ var BABYLON;
                 if (!animations) {
                     return;
                 }
+                for (var _i = 0, animations_1 = animations; _i < animations_1.length; _i++) {
+                    var animation = animations_1[_i];
+                    animation.babylonAnimationGroup.normalize();
+                }
                 switch (this.animationStartMode) {
                     case BABYLON.GLTFLoaderAnimationStartMode.NONE: {
                         // do nothing
@@ -2846,19 +2850,13 @@ var BABYLON;
                     }
                     case BABYLON.GLTFLoaderAnimationStartMode.FIRST: {
                         var animation = animations[0];
-                        for (var _i = 0, _a = animation.targets; _i < _a.length; _i++) {
-                            var target = _a[_i];
-                            this._babylonScene.beginAnimation(target, 0, Number.MAX_VALUE, true);
-                        }
+                        animation.babylonAnimationGroup.start(true);
                         break;
                     }
                     case BABYLON.GLTFLoaderAnimationStartMode.ALL: {
-                        for (var _b = 0, animations_1 = animations; _b < animations_1.length; _b++) {
-                            var animation = animations_1[_b];
-                            for (var _c = 0, _d = animation.targets; _c < _d.length; _c++) {
-                                var target = _d[_c];
-                                this._babylonScene.beginAnimation(target, 0, Number.MAX_VALUE, true);
-                            }
+                        for (var _a = 0, animations_2 = animations; _a < animations_2.length; _a++) {
+                            var animation = animations_2[_a];
+                            animation.babylonAnimationGroup.start(true);
                         }
                         break;
                     }
@@ -3470,7 +3468,7 @@ var BABYLON;
                 }
             };
             GLTFLoader.prototype._loadAnimation = function (context, animation) {
-                animation.targets = [];
+                animation.babylonAnimationGroup = new BABYLON.AnimationGroup(animation.name || "animation" + animation.index, this._babylonScene);
                 for (var index = 0; index < animation.channels.length; index++) {
                     var channel = GLTFLoader._GetProperty(animation.channels, index);
                     if (!channel) {
@@ -3610,7 +3608,7 @@ var BABYLON;
                         var morphTargetManager = targetNode.babylonMesh.morphTargetManager;
                         var _loop_7 = function (targetIndex) {
                             var morphTarget = morphTargetManager.getTarget(targetIndex);
-                            var animationName = (animation.name || "anim" + animation.index) + "_" + targetIndex;
+                            var animationName = animation.babylonAnimationGroup.name + "_channel" + animation.babylonAnimationGroup.targetedAnimations.length;
                             var babylonAnimation = new BABYLON.Animation(animationName, targetPath, 1, animationType);
                             babylonAnimation.setKeys(keys.map(function (key) { return ({
                                 frame: key.frame,
@@ -3618,22 +3616,20 @@ var BABYLON;
                                 value: key.value[targetIndex],
                                 outTangent: key.outTangent ? key.outTangent[targetIndex] : undefined
                             }); }));
-                            morphTarget.animations.push(babylonAnimation);
-                            animation.targets.push(morphTarget);
+                            animation.babylonAnimationGroup.addTargetedAnimation(babylonAnimation, morphTarget);
                         };
                         for (var targetIndex = 0; targetIndex < morphTargetManager.numTargets; targetIndex++) {
                             _loop_7(targetIndex);
                         }
                     }
                     else {
-                        var animationName = animation.name || "anim" + animation.index;
+                        var animationName = animation.babylonAnimationGroup.name + "_channel" + animation.babylonAnimationGroup.targetedAnimations.length;
                         var babylonAnimation = new BABYLON.Animation(animationName, targetPath, 1, animationType);
                         babylonAnimation.setKeys(keys);
                         if (targetNode.babylonAnimationTargets) {
                             for (var _i = 0, _a = targetNode.babylonAnimationTargets; _i < _a.length; _i++) {
                                 var target = _a[_i];
-                                target.animations.push(babylonAnimation.clone());
-                                animation.targets.push(target);
+                                animation.babylonAnimationGroup.addTargetedAnimation(babylonAnimation, target);
                             }
                         }
                     }

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 2 - 2
dist/preview release/loaders/babylon.glTFFileLoader.min.js


+ 13 - 17
dist/preview release/loaders/babylonjs.loaders.js

@@ -3813,6 +3813,10 @@ var BABYLON;
                 if (!animations) {
                     return;
                 }
+                for (var _i = 0, animations_1 = animations; _i < animations_1.length; _i++) {
+                    var animation = animations_1[_i];
+                    animation.babylonAnimationGroup.normalize();
+                }
                 switch (this.animationStartMode) {
                     case BABYLON.GLTFLoaderAnimationStartMode.NONE: {
                         // do nothing
@@ -3820,19 +3824,13 @@ var BABYLON;
                     }
                     case BABYLON.GLTFLoaderAnimationStartMode.FIRST: {
                         var animation = animations[0];
-                        for (var _i = 0, _a = animation.targets; _i < _a.length; _i++) {
-                            var target = _a[_i];
-                            this._babylonScene.beginAnimation(target, 0, Number.MAX_VALUE, true);
-                        }
+                        animation.babylonAnimationGroup.start(true);
                         break;
                     }
                     case BABYLON.GLTFLoaderAnimationStartMode.ALL: {
-                        for (var _b = 0, animations_1 = animations; _b < animations_1.length; _b++) {
-                            var animation = animations_1[_b];
-                            for (var _c = 0, _d = animation.targets; _c < _d.length; _c++) {
-                                var target = _d[_c];
-                                this._babylonScene.beginAnimation(target, 0, Number.MAX_VALUE, true);
-                            }
+                        for (var _a = 0, animations_2 = animations; _a < animations_2.length; _a++) {
+                            var animation = animations_2[_a];
+                            animation.babylonAnimationGroup.start(true);
                         }
                         break;
                     }
@@ -4444,7 +4442,7 @@ var BABYLON;
                 }
             };
             GLTFLoader.prototype._loadAnimation = function (context, animation) {
-                animation.targets = [];
+                animation.babylonAnimationGroup = new BABYLON.AnimationGroup(animation.name || "animation" + animation.index, this._babylonScene);
                 for (var index = 0; index < animation.channels.length; index++) {
                     var channel = GLTFLoader._GetProperty(animation.channels, index);
                     if (!channel) {
@@ -4584,7 +4582,7 @@ var BABYLON;
                         var morphTargetManager = targetNode.babylonMesh.morphTargetManager;
                         var _loop_7 = function (targetIndex) {
                             var morphTarget = morphTargetManager.getTarget(targetIndex);
-                            var animationName = (animation.name || "anim" + animation.index) + "_" + targetIndex;
+                            var animationName = animation.babylonAnimationGroup.name + "_channel" + animation.babylonAnimationGroup.targetedAnimations.length;
                             var babylonAnimation = new BABYLON.Animation(animationName, targetPath, 1, animationType);
                             babylonAnimation.setKeys(keys.map(function (key) { return ({
                                 frame: key.frame,
@@ -4592,22 +4590,20 @@ var BABYLON;
                                 value: key.value[targetIndex],
                                 outTangent: key.outTangent ? key.outTangent[targetIndex] : undefined
                             }); }));
-                            morphTarget.animations.push(babylonAnimation);
-                            animation.targets.push(morphTarget);
+                            animation.babylonAnimationGroup.addTargetedAnimation(babylonAnimation, morphTarget);
                         };
                         for (var targetIndex = 0; targetIndex < morphTargetManager.numTargets; targetIndex++) {
                             _loop_7(targetIndex);
                         }
                     }
                     else {
-                        var animationName = animation.name || "anim" + animation.index;
+                        var animationName = animation.babylonAnimationGroup.name + "_channel" + animation.babylonAnimationGroup.targetedAnimations.length;
                         var babylonAnimation = new BABYLON.Animation(animationName, targetPath, 1, animationType);
                         babylonAnimation.setKeys(keys);
                         if (targetNode.babylonAnimationTargets) {
                             for (var _i = 0, _a = targetNode.babylonAnimationTargets; _i < _a.length; _i++) {
                                 var target = _a[_i];
-                                target.animations.push(babylonAnimation.clone());
-                                animation.targets.push(target);
+                                animation.babylonAnimationGroup.addTargetedAnimation(babylonAnimation, target);
                             }
                         }
                     }

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 3 - 3
dist/preview release/loaders/babylonjs.loaders.min.js


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

@@ -883,7 +883,7 @@ declare module BABYLON.GLTF2 {
         channels: IGLTFAnimationChannel[];
         samplers: IGLTFAnimationSampler[];
         index: number;
-        targets: any[];
+        babylonAnimationGroup: AnimationGroup;
     }
     interface IGLTFAsset extends IGLTFChildRootProperty {
         copyright?: string;

+ 1 - 1
dist/preview release/materialsLibrary/babylon.cellMaterial.js

@@ -102,7 +102,7 @@ var BABYLON;
             // Lights
             defines._needNormals = BABYLON.MaterialHelper.PrepareDefinesForLights(scene, mesh, defines, false, this._maxSimultaneousLights, this._disableLighting);
             // Values that need to be evaluated on every frame
-            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false);
+            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false, this._shouldTurnAlphaTestOn(mesh));
             // Attribs
             BABYLON.MaterialHelper.PrepareDefinesForAttributes(mesh, defines, true, true);
             // Get correct effect      

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 1 - 1
dist/preview release/materialsLibrary/babylon.cellMaterial.min.js


+ 1 - 0
dist/preview release/materialsLibrary/babylon.customMaterial.d.ts

@@ -222,6 +222,7 @@ declare module BABYLON {
          * 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;

+ 4 - 1
dist/preview release/materialsLibrary/babylon.customMaterial.js

@@ -315,6 +315,9 @@ var BABYLON;
             enumerable: true,
             configurable: true
         });
+        StandardMaterial_OldVer.prototype._shouldTurnAlphaTestOn = function (mesh) {
+            return (!this.needAlphaBlendingForMesh(mesh) && this.needAlphaTesting());
+        };
         StandardMaterial_OldVer.prototype.getClassName = function () {
             return "StandardMaterial_OldVer";
         };
@@ -564,7 +567,7 @@ var BABYLON;
             // Attribs
             BABYLON.MaterialHelper.PrepareDefinesForAttributes(mesh, defines, true, true, true);
             // Values that need to be evaluated on every frame
-            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false);
+            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false, this._shouldTurnAlphaTestOn(mesh));
             // Get correct effect      
             if (defines.isDirty) {
                 defines.markAsProcessed();

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 2 - 2
dist/preview release/materialsLibrary/babylon.customMaterial.min.js


+ 1 - 1
dist/preview release/materialsLibrary/babylon.fireMaterial.js

@@ -94,7 +94,7 @@ var BABYLON;
                 defines.FOG = (scene.fogEnabled && mesh.applyFog && scene.fogMode !== BABYLON.Scene.FOGMODE_NONE && this.fogEnabled);
             }
             // Values that need to be evaluated on every frame
-            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false);
+            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false, this._shouldTurnAlphaTestOn(mesh));
             // Attribs
             BABYLON.MaterialHelper.PrepareDefinesForAttributes(mesh, defines, false, true);
             // Get correct effect      

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 1 - 1
dist/preview release/materialsLibrary/babylon.fireMaterial.min.js


+ 1 - 1
dist/preview release/materialsLibrary/babylon.furMaterial.js

@@ -147,7 +147,7 @@ var BABYLON;
             // Lights
             defines._needNormals = BABYLON.MaterialHelper.PrepareDefinesForLights(scene, mesh, defines, false, this._maxSimultaneousLights, this._disableLighting);
             // Values that need to be evaluated on every frame
-            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false);
+            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false, this._shouldTurnAlphaTestOn(mesh));
             // Attribs
             BABYLON.MaterialHelper.PrepareDefinesForAttributes(mesh, defines, true, true);
             // Get correct effect      

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 1 - 1
dist/preview release/materialsLibrary/babylon.furMaterial.min.js


+ 1 - 1
dist/preview release/materialsLibrary/babylon.gradientMaterial.js

@@ -118,7 +118,7 @@ var BABYLON;
                 }
             }
             var engine = scene.getEngine();
-            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false);
+            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false, this._shouldTurnAlphaTestOn(mesh));
             BABYLON.MaterialHelper.PrepareDefinesForMisc(mesh, scene, false, this.pointsCloud, this.fogEnabled, defines);
             defines._needNormals = BABYLON.MaterialHelper.PrepareDefinesForLights(scene, mesh, defines, false, this._maxSimultaneousLights);
             // Attribs

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 1 - 1
dist/preview release/materialsLibrary/babylon.gradientMaterial.min.js


+ 1 - 1
dist/preview release/materialsLibrary/babylon.lavaMaterial.js

@@ -135,7 +135,7 @@ var BABYLON;
             // Lights
             defines._needNormals = BABYLON.MaterialHelper.PrepareDefinesForLights(scene, mesh, defines, false, this._maxSimultaneousLights, this._disableLighting);
             // Values that need to be evaluated on every frame
-            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false);
+            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false, this._shouldTurnAlphaTestOn(mesh));
             // Attribs
             BABYLON.MaterialHelper.PrepareDefinesForAttributes(mesh, defines, true, true);
             // Get correct effect      

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 1 - 1
dist/preview release/materialsLibrary/babylon.lavaMaterial.min.js


+ 1 - 1
dist/preview release/materialsLibrary/babylon.normalMaterial.js

@@ -129,7 +129,7 @@ var BABYLON;
             // Lights
             defines._needNormals = BABYLON.MaterialHelper.PrepareDefinesForLights(scene, mesh, defines, false, this._maxSimultaneousLights, this._disableLighting);
             // Values that need to be evaluated on every frame
-            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false);
+            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false, this._shouldTurnAlphaTestOn(mesh));
             // Attribs
             BABYLON.MaterialHelper.PrepareDefinesForAttributes(mesh, defines, true, true);
             // Get correct effect      

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 1 - 1
dist/preview release/materialsLibrary/babylon.normalMaterial.min.js


+ 1 - 1
dist/preview release/materialsLibrary/babylon.shadowOnlyMaterial.js

@@ -86,7 +86,7 @@ var BABYLON;
                     }
                 }
             }
-            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false);
+            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false, this._shouldTurnAlphaTestOn(mesh));
             BABYLON.MaterialHelper.PrepareDefinesForMisc(mesh, scene, false, this.pointsCloud, this.fogEnabled, defines);
             defines._needNormals = BABYLON.MaterialHelper.PrepareDefinesForLights(scene, mesh, defines, false, 1);
             // Attribs

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 1 - 1
dist/preview release/materialsLibrary/babylon.shadowOnlyMaterial.min.js


+ 1 - 1
dist/preview release/materialsLibrary/babylon.simpleMaterial.js

@@ -96,7 +96,7 @@ var BABYLON;
             // Lights
             defines._needNormals = BABYLON.MaterialHelper.PrepareDefinesForLights(scene, mesh, defines, false, this._maxSimultaneousLights, this._disableLighting);
             // Values that need to be evaluated on every frame
-            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false);
+            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false, this._shouldTurnAlphaTestOn(mesh));
             // Attribs
             BABYLON.MaterialHelper.PrepareDefinesForAttributes(mesh, defines, true, true);
             // Get correct effect      

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 1 - 1
dist/preview release/materialsLibrary/babylon.simpleMaterial.min.js


+ 1 - 1
dist/preview release/materialsLibrary/babylon.terrainMaterial.js

@@ -102,7 +102,7 @@ var BABYLON;
             // Lights
             defines._needNormals = BABYLON.MaterialHelper.PrepareDefinesForLights(scene, mesh, defines, false, this._maxSimultaneousLights, this._disableLighting);
             // Values that need to be evaluated on every frame
-            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false);
+            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false, this._shouldTurnAlphaTestOn(mesh));
             // Attribs
             BABYLON.MaterialHelper.PrepareDefinesForAttributes(mesh, defines, true, true);
             // Get correct effect      

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 1 - 1
dist/preview release/materialsLibrary/babylon.terrainMaterial.min.js


+ 1 - 1
dist/preview release/materialsLibrary/babylon.triPlanarMaterial.js

@@ -121,7 +121,7 @@ var BABYLON;
             // Lights
             defines._needNormals = BABYLON.MaterialHelper.PrepareDefinesForLights(scene, mesh, defines, false, this._maxSimultaneousLights, this._disableLighting);
             // Values that need to be evaluated on every frame
-            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false);
+            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false, this._shouldTurnAlphaTestOn(mesh));
             // Attribs
             BABYLON.MaterialHelper.PrepareDefinesForAttributes(mesh, defines, true, true);
             // Get correct effect      

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 1 - 1
dist/preview release/materialsLibrary/babylon.triPlanarMaterial.min.js


+ 1 - 1
dist/preview release/materialsLibrary/babylon.waterMaterial.js

@@ -228,7 +228,7 @@ var BABYLON;
                     }
                 }
             }
-            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false);
+            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false, this._shouldTurnAlphaTestOn(mesh));
             BABYLON.MaterialHelper.PrepareDefinesForMisc(mesh, scene, this._useLogarithmicDepth, this.pointsCloud, this.fogEnabled, defines);
             if (defines._areMiscDirty) {
                 if (this._fresnelSeparate) {

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 1 - 1
dist/preview release/materialsLibrary/babylon.waterMaterial.min.js


+ 15 - 12
dist/preview release/materialsLibrary/babylonjs.materials.js

@@ -96,7 +96,7 @@ var BABYLON;
                     }
                 }
             }
-            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false);
+            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false, this._shouldTurnAlphaTestOn(mesh));
             BABYLON.MaterialHelper.PrepareDefinesForMisc(mesh, scene, false, this.pointsCloud, this.fogEnabled, defines);
             defines._needNormals = BABYLON.MaterialHelper.PrepareDefinesForLights(scene, mesh, defines, false, 1);
             // Attribs
@@ -326,7 +326,7 @@ var BABYLON;
                 }
             }
             var engine = scene.getEngine();
-            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false);
+            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false, this._shouldTurnAlphaTestOn(mesh));
             BABYLON.MaterialHelper.PrepareDefinesForMisc(mesh, scene, false, this.pointsCloud, this.fogEnabled, defines);
             defines._needNormals = BABYLON.MaterialHelper.PrepareDefinesForLights(scene, mesh, defines, false, this._maxSimultaneousLights);
             // Attribs
@@ -615,7 +615,7 @@ var BABYLON;
             // Lights
             defines._needNormals = BABYLON.MaterialHelper.PrepareDefinesForLights(scene, mesh, defines, false, this._maxSimultaneousLights, this._disableLighting);
             // Values that need to be evaluated on every frame
-            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false);
+            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false, this._shouldTurnAlphaTestOn(mesh));
             // Attribs
             BABYLON.MaterialHelper.PrepareDefinesForAttributes(mesh, defines, true, true);
             // Get correct effect      
@@ -926,7 +926,7 @@ var BABYLON;
             // Lights
             defines._needNormals = BABYLON.MaterialHelper.PrepareDefinesForLights(scene, mesh, defines, false, this._maxSimultaneousLights, this._disableLighting);
             // Values that need to be evaluated on every frame
-            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false);
+            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false, this._shouldTurnAlphaTestOn(mesh));
             // Attribs
             BABYLON.MaterialHelper.PrepareDefinesForAttributes(mesh, defines, true, true);
             // Get correct effect      
@@ -1238,7 +1238,7 @@ var BABYLON;
             // Lights
             defines._needNormals = BABYLON.MaterialHelper.PrepareDefinesForLights(scene, mesh, defines, false, this._maxSimultaneousLights, this._disableLighting);
             // Values that need to be evaluated on every frame
-            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false);
+            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false, this._shouldTurnAlphaTestOn(mesh));
             // Attribs
             BABYLON.MaterialHelper.PrepareDefinesForAttributes(mesh, defines, true, true);
             // Get correct effect      
@@ -1642,7 +1642,7 @@ var BABYLON;
                     }
                 }
             }
-            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false);
+            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false, this._shouldTurnAlphaTestOn(mesh));
             BABYLON.MaterialHelper.PrepareDefinesForMisc(mesh, scene, this._useLogarithmicDepth, this.pointsCloud, this.fogEnabled, defines);
             if (defines._areMiscDirty) {
                 if (this._fresnelSeparate) {
@@ -2124,7 +2124,7 @@ var BABYLON;
                 defines.FOG = (scene.fogEnabled && mesh.applyFog && scene.fogMode !== BABYLON.Scene.FOGMODE_NONE && this.fogEnabled);
             }
             // Values that need to be evaluated on every frame
-            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false);
+            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false, this._shouldTurnAlphaTestOn(mesh));
             // Attribs
             BABYLON.MaterialHelper.PrepareDefinesForAttributes(mesh, defines, false, true);
             // Get correct effect      
@@ -2498,7 +2498,7 @@ var BABYLON;
             // Lights
             defines._needNormals = BABYLON.MaterialHelper.PrepareDefinesForLights(scene, mesh, defines, false, this._maxSimultaneousLights, this._disableLighting);
             // Values that need to be evaluated on every frame
-            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false);
+            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false, this._shouldTurnAlphaTestOn(mesh));
             // Attribs
             BABYLON.MaterialHelper.PrepareDefinesForAttributes(mesh, defines, true, true);
             // Get correct effect      
@@ -2915,7 +2915,7 @@ var BABYLON;
             // Lights
             defines._needNormals = BABYLON.MaterialHelper.PrepareDefinesForLights(scene, mesh, defines, false, this._maxSimultaneousLights, this._disableLighting);
             // Values that need to be evaluated on every frame
-            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false);
+            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false, this._shouldTurnAlphaTestOn(mesh));
             // Attribs
             BABYLON.MaterialHelper.PrepareDefinesForAttributes(mesh, defines, true, true);
             // Get correct effect      
@@ -3321,7 +3321,7 @@ var BABYLON;
             // Lights
             defines._needNormals = BABYLON.MaterialHelper.PrepareDefinesForLights(scene, mesh, defines, false, this._maxSimultaneousLights, this._disableLighting);
             // Values that need to be evaluated on every frame
-            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false);
+            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false, this._shouldTurnAlphaTestOn(mesh));
             // Attribs
             BABYLON.MaterialHelper.PrepareDefinesForAttributes(mesh, defines, true, true);
             // Get correct effect      
@@ -4311,6 +4311,9 @@ var BABYLON;
             enumerable: true,
             configurable: true
         });
+        StandardMaterial_OldVer.prototype._shouldTurnAlphaTestOn = function (mesh) {
+            return (!this.needAlphaBlendingForMesh(mesh) && this.needAlphaTesting());
+        };
         StandardMaterial_OldVer.prototype.getClassName = function () {
             return "StandardMaterial_OldVer";
         };
@@ -4560,7 +4563,7 @@ var BABYLON;
             // Attribs
             BABYLON.MaterialHelper.PrepareDefinesForAttributes(mesh, defines, true, true, true);
             // Values that need to be evaluated on every frame
-            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false);
+            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false, this._shouldTurnAlphaTestOn(mesh));
             // Get correct effect      
             if (defines.isDirty) {
                 defines.markAsProcessed();
@@ -6150,7 +6153,7 @@ var BABYLON;
             // Lights
             defines._needNormals = BABYLON.MaterialHelper.PrepareDefinesForLights(scene, mesh, defines, false, this._maxSimultaneousLights, this._disableLighting);
             // Values that need to be evaluated on every frame
-            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false);
+            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false, this._shouldTurnAlphaTestOn(mesh));
             // Attribs
             BABYLON.MaterialHelper.PrepareDefinesForAttributes(mesh, defines, true, true);
             // Get correct effect      

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 7 - 7
dist/preview release/materialsLibrary/babylonjs.materials.min.js


+ 1 - 0
dist/preview release/materialsLibrary/babylonjs.materials.module.d.ts

@@ -728,6 +728,7 @@ declare module BABYLON {
          * 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;

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

@@ -1,7 +1,7 @@
 {
-  "errors": 10973,
+  "errors": 10946,
   "babylon.typedoc.json": {
-    "errors": 10973,
+    "errors": 10946,
     "AnimationKeyInterpolation": {
       "Enumeration": {
         "Comments": {
@@ -13792,18 +13792,6 @@
           "Comments": {
             "MissingText": true,
             "MissingReturn": true
-          },
-          "Parameter": {
-            "antialias": {
-              "Comments": {
-                "MissingText": true
-              }
-            },
-            "adaptToDeviceRatio": {
-              "Comments": {
-                "MissingText": true
-              }
-            }
           }
         }
       },
@@ -14250,28 +14238,6 @@
             }
           }
         },
-        "_bindTextureDirectly": {
-          "Comments": {
-            "MissingText": true
-          },
-          "Parameter": {
-            "target": {
-              "Comments": {
-                "MissingText": true
-              }
-            },
-            "texture": {
-              "Comments": {
-                "MissingText": true
-              }
-            },
-            "doNotBindUniformToTextureChannel": {
-              "Comments": {
-                "MissingText": true
-              }
-            }
-          }
-        },
         "_createTexture": {
           "Comments": {
             "MissingText": true
@@ -15764,11 +15730,6 @@
             "MissingText": true
           }
         },
-        "getAlphaTesting": {
-          "Comments": {
-            "MissingText": true
-          }
-        },
         "getAspectRatio": {
           "Comments": {
             "MissingText": true
@@ -16179,18 +16140,6 @@
             }
           }
         },
-        "setAlphaTesting": {
-          "Comments": {
-            "MissingText": true
-          },
-          "Parameter": {
-            "enable": {
-              "Comments": {
-                "MissingText": true
-              }
-            }
-          }
-        },
         "setArray": {
           "Comments": {
             "MissingText": true
@@ -24310,38 +24259,6 @@
             }
           }
         },
-        "PrepareDefinesForFrameBoundValues": {
-          "Comments": {
-            "MissingText": true
-          },
-          "Parameter": {
-            "scene": {
-              "Comments": {
-                "MissingText": true
-              }
-            },
-            "engine": {
-              "Comments": {
-                "MissingText": true
-              }
-            },
-            "defines": {
-              "Comments": {
-                "MissingText": true
-              }
-            },
-            "useInstances": {
-              "Comments": {
-                "MissingText": true
-              }
-            },
-            "forceAlphaTest": {
-              "Comments": {
-                "MissingText": true
-              }
-            }
-          }
-        },
         "PrepareDefinesForLights": {
           "Comments": {
             "MissingText": true
@@ -29864,23 +29781,6 @@
             }
           }
         },
-        "_bindTextureDirectly": {
-          "Comments": {
-            "MissingText": true
-          },
-          "Parameter": {
-            "target": {
-              "Comments": {
-                "MissingText": true
-              }
-            },
-            "texture": {
-              "Comments": {
-                "MissingText": true
-              }
-            }
-          }
-        },
         "_createTexture": {
           "Comments": {
             "MissingText": true
@@ -50555,53 +50455,6 @@
             }
           }
         },
-        "CreateScreenshotUsingRenderTarget": {
-          "Comments": {
-            "MissingText": true
-          },
-          "Parameter": {
-            "engine": {
-              "Comments": {
-                "MissingText": true
-              }
-            },
-            "camera": {
-              "Comments": {
-                "MissingText": true
-              }
-            },
-            "size": {
-              "Comments": {
-                "MissingText": true
-              }
-            },
-            "successCallback": {
-              "Comments": {
-                "MissingText": true
-              }
-            },
-            "mimeType": {
-              "Comments": {
-                "MissingText": true
-              }
-            },
-            "samples": {
-              "Comments": {
-                "MissingText": true
-              }
-            },
-            "antialiasing": {
-              "Comments": {
-                "MissingText": true
-              }
-            },
-            "fileName": {
-              "Comments": {
-                "MissingText": true
-              }
-            }
-          }
-        },
         "DeepCopy": {
           "Comments": {
             "MissingText": true

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 48 - 48
dist/preview release/viewer/babylon.viewer.js


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

@@ -6,6 +6,7 @@
 
 ## Updates
 - Improved [SceneOptimizer](http://doc.babylonjs.com/how_to/how_to_use_sceneoptimizer) to provide better adapatability ([deltakosh](https://github.com/deltakosh))
+- Improved `scene.isReady()` function which now takes in account shadows and LOD ([deltakosh](https://github.com/deltakosh))
 - New watcher configuration for VSCode. Now the task only compiles changed files ([sebavan](https://github.com/sebavan))
 - Added new draw modes to engine (points, lines, linesloop, linestrip, trianglestrip, trianglefan) ([benaadams](https://github.com/benaadams))
 - Added GUI Textblock.lineSpacing setter and getter to configure vertical space between lines in pixels or percentage values when working with text wrapping ([carloslanderas](https://github.com/carloslanderas))
@@ -17,8 +18,7 @@
    ([carloslanderas](https://github.com/carloslanderas))
 - VRHelper now exposes onNewMeshPicked observable that will notify a PickingInfo object after meshSelectionPredicate evaluation
    ([carloslanderas](https://github.com/carloslanderas))
-  
-  
+- `AssetsManager` will now clear its `tasks` lsit from all successfully loaded tasks ([deltakosh](https://github.com/deltakosh))
 
 ## Bug fixes
 

+ 7 - 6
inspector/src/Inspector.ts

@@ -39,15 +39,15 @@ module INSPECTOR {
         }) {
 
             // Load GUI library if not already done
-            if(!BABYLON.GUI){
-            	BABYLON.Tools.LoadScript("https://preview.babylonjs.com/gui/babylon.gui.js", () => { 
+            if (!BABYLON.GUI) {
+                BABYLON.Tools.LoadScript("https://preview.babylonjs.com/gui/babylon.gui.js", () => {
                     //Load properties of GUI objects now as BABYLON.GUI has to be declared before 
                     loadGUIProperties();
                 }, () => {
                     console.warn("Please add script https://preview.babylonjs.com/gui/babylon.gui.js to the HTML file")
                 });
             }
-            else{
+            else {
                 //Load properties of GUI objects now as BABYLON.GUI has to be declared before 
                 loadGUIProperties();
             }
@@ -139,7 +139,7 @@ module INSPECTOR {
                             this._c2diwrapper.style.maxWidth = `${widthPx - leftPx}px`;
                         }
                     }
-                    
+
 
                     // Check if the parent of the canvas is the body page. If yes, the size ratio is computed
                     let parent = this._getRelativeParent(canvas);
@@ -357,6 +357,7 @@ module INSPECTOR {
                     }
                 }
             }
+            Scheduler.getInstance().dispose();
         }
 
         /** Open the inspector in a new popup
@@ -412,8 +413,8 @@ module INSPECTOR {
             }
         }
 
-        public getActiveTabIndex():number {
-           return this._tabbar.getActiveTabIndex();
+        public getActiveTabIndex(): number {
+            return this._tabbar.getActiveTabIndex();
         }
     }
 }

+ 0 - 1
inspector/src/adapters/MeshAdapter.ts

@@ -10,7 +10,6 @@ module INSPECTOR {
 
         constructor(mesh: BABYLON.Node) {
             super(mesh);
-            new BABYLON.Debug.AxesViewer(mesh.getScene());
         }
 
         /** Returns the name displayed in the tree */

+ 12 - 6
inspector/src/scheduler/Scheduler.ts

@@ -13,11 +13,13 @@ module INSPECTOR {
         /** The list of data to update */
         private _updatableProperties: Array<PropertyLine> = [];
 
-        constructor () {
-            setInterval(this._update.bind(this), Scheduler.REFRESH_TIME);
+        private interval: number;
+
+        constructor() {
+            this.interval = setInterval(this._update.bind(this), Scheduler.REFRESH_TIME);
         }
 
-        public static getInstance() : Scheduler {
+        public static getInstance(): Scheduler {
             if (!Scheduler._instance) {
                 Scheduler._instance = new Scheduler();
             }
@@ -25,12 +27,12 @@ module INSPECTOR {
         }
 
         /** Add a property line to be updated every X ms */
-        public add(prop:PropertyLine) {
+        public add(prop: PropertyLine) {
             this._updatableProperties.push(prop);
         }
-        
+
         /** Removes the given property from the list of properties to update */
-        public remove(prop:PropertyLine) {
+        public remove(prop: PropertyLine) {
             let index = this._updatableProperties.indexOf(prop);
             if (index != -1) {
                 this._updatableProperties.splice(index, 1);
@@ -45,5 +47,9 @@ module INSPECTOR {
                 }
             }
         }
+
+        public dispose() {
+            window.clearInterval(this.interval);
+        }
     }
 }

+ 11 - 13
loaders/src/glTF/2.0/babylon.glTFLoader.ts

@@ -253,6 +253,10 @@ module BABYLON.GLTF2 {
                 return;
             }
 
+            for (const animation of animations) {
+                animation.babylonAnimationGroup.normalize();
+            }
+
             switch (this.animationStartMode) {
                 case GLTFLoaderAnimationStartMode.NONE: {
                     // do nothing
@@ -260,16 +264,12 @@ module BABYLON.GLTF2 {
                 }
                 case GLTFLoaderAnimationStartMode.FIRST: {
                     const animation = animations[0];
-                    for (const target of animation.targets) {
-                        this._babylonScene.beginAnimation(target, 0, Number.MAX_VALUE, true);
-                    }
+                    animation.babylonAnimationGroup.start(true);
                     break;
                 }
                 case GLTFLoaderAnimationStartMode.ALL: {
                     for (const animation of animations) {
-                        for (const target of animation.targets) {
-                            this._babylonScene.beginAnimation(target, 0, Number.MAX_VALUE, true);
-                        }
+                        animation.babylonAnimationGroup.start(true);
                     }
                     break;
                 }
@@ -941,7 +941,7 @@ module BABYLON.GLTF2 {
         }
 
         private _loadAnimation(context: string, animation: IGLTFAnimation): void {
-            animation.targets = [];
+            animation.babylonAnimationGroup = new AnimationGroup(animation.name || "animation" + animation.index, this._babylonScene);
 
             for (let index = 0; index < animation.channels.length; index++) {
                 const channel = GLTFLoader._GetProperty(animation.channels, index);
@@ -1096,7 +1096,7 @@ module BABYLON.GLTF2 {
 
                     for (let targetIndex = 0; targetIndex < morphTargetManager.numTargets; targetIndex++) {
                         const morphTarget = morphTargetManager.getTarget(targetIndex);
-                        const animationName = (animation.name || "anim" + animation.index) + "_" + targetIndex;
+                        const animationName = animation.babylonAnimationGroup.name + "_channel" + animation.babylonAnimationGroup.targetedAnimations.length;
                         const babylonAnimation = new Animation(animationName, targetPath, 1, animationType);
                         babylonAnimation.setKeys(keys.map(key => ({
                             frame: key.frame,
@@ -1105,19 +1105,17 @@ module BABYLON.GLTF2 {
                             outTangent: key.outTangent ? key.outTangent[targetIndex] : undefined
                         })));
 
-                        morphTarget.animations.push(babylonAnimation);
-                        animation.targets.push(morphTarget);
+                        animation.babylonAnimationGroup.addTargetedAnimation(babylonAnimation, morphTarget);
                     }
                 }
                 else {
-                    const animationName = animation.name || "anim" + animation.index;
+                    const animationName = animation.babylonAnimationGroup.name + "_channel" + animation.babylonAnimationGroup.targetedAnimations.length;
                     const babylonAnimation = new Animation(animationName, targetPath, 1, animationType);
                     babylonAnimation.setKeys(keys);
 
                     if (targetNode.babylonAnimationTargets) {
                         for (const target of targetNode.babylonAnimationTargets) {
-                            target.animations.push(babylonAnimation.clone());
-                            animation.targets.push(target);
+                            animation.babylonAnimationGroup.addTargetedAnimation(babylonAnimation, target);
                         }
                     }
                 }

+ 1 - 1
loaders/src/glTF/2.0/babylon.glTFLoaderInterfaces.ts

@@ -109,7 +109,7 @@ module BABYLON.GLTF2 {
 
         // Runtime values
         index: number;
-        targets: any[];
+        babylonAnimationGroup: AnimationGroup;
     }
 
     export interface IGLTFAsset extends IGLTFChildRootProperty {

+ 22 - 22
materialsLibrary/src/cell/babylon.cellMaterial.ts

@@ -39,16 +39,16 @@ module BABYLON {
         public _computeHighLevel: boolean = false;
         @expandToProperty("_markAllSubMeshesAsTexturesDirty")
         public computeHighLevel: boolean;
-        
+
         @serialize("disableLighting")
         private _disableLighting = false;
         @expandToProperty("_markAllSubMeshesAsLightsDirty")
-        public disableLighting: boolean;   
-        
+        public disableLighting: boolean;
+
         @serialize("maxSimultaneousLights")
         private _maxSimultaneousLights = 4;
         @expandToProperty("_markAllSubMeshesAsLightsDirty")
-        public maxSimultaneousLights: number; 
+        public maxSimultaneousLights: number;
 
         private _renderId: number;
 
@@ -69,7 +69,7 @@ module BABYLON {
         }
 
         // Methods   
-        public isReadyForSubMesh(mesh: AbstractMesh, subMesh: SubMesh, useInstances?: boolean): boolean {   
+        public isReadyForSubMesh(mesh: AbstractMesh, subMesh: SubMesh, useInstances?: boolean): boolean {
             if (this.isFrozen) {
                 if (this._wasPreviouslyReady && subMesh.effect) {
                     return true;
@@ -102,7 +102,7 @@ module BABYLON {
                             defines._needUVs = true;
                             defines.DIFFUSE = true;
                         }
-                    }                
+                    }
                 }
             }
 
@@ -116,8 +116,8 @@ module BABYLON {
             defines._needNormals = MaterialHelper.PrepareDefinesForLights(scene, mesh, defines, false, this._maxSimultaneousLights, this._disableLighting);
 
             // Values that need to be evaluated on every frame
-            MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false);
-            
+            MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false, this._shouldTurnAlphaTestOn(mesh));
+
             // Attribs
             MaterialHelper.PrepareDefinesForAttributes(mesh, defines, true, true);
 
@@ -127,13 +127,13 @@ module BABYLON {
                 scene.resetCachedMaterial();
 
                 // Fallbacks
-                var fallbacks = new EffectFallbacks();             
+                var fallbacks = new EffectFallbacks();
                 if (defines.FOG) {
                     fallbacks.addFallback(1, "FOG");
                 }
 
                 MaterialHelper.HandleFallbacksForShadows(defines, fallbacks, this.maxSimultaneousLights);
-                
+
                 if (defines.NUM_BONE_INFLUENCERS > 0) {
                     fallbacks.addCPUSkinningFallback(0, mesh);
                 }
@@ -163,19 +163,19 @@ module BABYLON {
                 var shaderName = "cell";
                 var join = defines.toString();
                 var uniforms = ["world", "view", "viewProjection", "vEyePosition", "vLightsType", "vDiffuseColor",
-                                "vFogInfos", "vFogColor", "pointSize",
-                                "vDiffuseInfos", 
-                                "mBones",
-                                "vClipPlane", "diffuseMatrix"
+                    "vFogInfos", "vFogColor", "pointSize",
+                    "vDiffuseInfos",
+                    "mBones",
+                    "vClipPlane", "diffuseMatrix"
                 ];
                 var samplers = ["diffuseSampler"];
                 var uniformBuffers = new Array<string>()
 
                 MaterialHelper.PrepareUniformsAndSamplersList(<EffectCreationOptions>{
-                    uniformsNames: uniforms, 
+                    uniformsNames: uniforms,
                     uniformBuffersNames: uniformBuffers,
-                    samplers: samplers, 
-                    defines: defines, 
+                    samplers: samplers,
+                    defines: defines,
                     maxSimultaneousLights: this.maxSimultaneousLights
                 });
                 subMesh.setEffect(scene.getEngine().createEffect(shaderName,
@@ -231,7 +231,7 @@ module BABYLON {
                     this._activeEffect.setFloat2("vDiffuseInfos", this._diffuseTexture.coordinatesIndex, this._diffuseTexture.level);
                     this._activeEffect.setMatrix("diffuseMatrix", this._diffuseTexture.getTextureMatrix());
                 }
-                
+
                 // Clip plane
                 MaterialHelper.BindClipPlane(this._activeEffect, scene);
 
@@ -240,14 +240,14 @@ module BABYLON {
                     this._activeEffect.setFloat("pointSize", this.pointSize);
                 }
 
-                MaterialHelper.BindEyePosition(effect, scene);               
+                MaterialHelper.BindEyePosition(effect, scene);
             }
 
             this._activeEffect.setColor4("vDiffuseColor", this.diffuseColor, this.alpha * mesh.visibility);
 
             // Lights
             if (scene.lightsEnabled && !this.disableLighting) {
-                MaterialHelper.BindLights(scene, mesh, this._activeEffect, defines, this._maxSimultaneousLights);          
+                MaterialHelper.BindLights(scene, mesh, this._activeEffect, defines, this._maxSimultaneousLights);
             }
 
             // View
@@ -304,7 +304,7 @@ module BABYLON {
         public clone(name: string): CellMaterial {
             return SerializationHelper.Clone<CellMaterial>(() => new CellMaterial(name, this.getScene()), this);
         }
-        
+
         public serialize(): any {
             var serializationObject = SerializationHelper.Serialize(this);
             serializationObject.customType = "BABYLON.CellMaterial";
@@ -316,5 +316,5 @@ module BABYLON {
             return SerializationHelper.Parse(() => new CellMaterial(source.name, scene), source, scene, rootUrl);
         }
     }
-} 
+}
 

+ 5 - 1
materialsLibrary/src/custom/babylon.customMaterial.ts

@@ -423,6 +423,10 @@ module BABYLON {
             this._imageProcessingConfiguration.colorGradingTexture = value;
         }
 
+        protected _shouldTurnAlphaTestOn(mesh: AbstractMesh): boolean {
+            return (!this.needAlphaBlendingForMesh(mesh) && this.needAlphaTesting());
+        }
+
         public customShaderNameResolve: (shaderName: string, uniforms: string[], uniformBuffers: string[], samplers: string[], defines: StandardMaterialDefines_OldVer) => string;
 
         protected _renderTargets = new SmartArray<RenderTargetTexture>(16);
@@ -721,7 +725,7 @@ module BABYLON {
             MaterialHelper.PrepareDefinesForAttributes(mesh, defines, true, true, true);
 
             // Values that need to be evaluated on every frame
-            MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false);
+            MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false, this._shouldTurnAlphaTestOn(mesh));
 
             // Get correct effect      
             if (defines.isDirty) {

+ 54 - 54
materialsLibrary/src/fire/babylon.fireMaterial.ts

@@ -26,24 +26,24 @@ module BABYLON {
         @serializeAsTexture("diffuseTexture")
         private _diffuseTexture: Nullable<BaseTexture>;
         @expandToProperty("_markAllSubMeshesAsTexturesDirty")
-        public diffuseTexture: Nullable<BaseTexture>;        
-        
+        public diffuseTexture: Nullable<BaseTexture>;
+
         @serializeAsTexture("distortionTexture")
         private _distortionTexture: Nullable<BaseTexture>;
         @expandToProperty("_markAllSubMeshesAsTexturesDirty")
-        public distortionTexture: Nullable<BaseTexture>;       
-        
+        public distortionTexture: Nullable<BaseTexture>;
+
         @serializeAsTexture("opacityTexture")
         private _opacityTexture: Nullable<BaseTexture>;
         @expandToProperty("_markAllSubMeshesAsTexturesDirty")
         public opacityTexture: Nullable<BaseTexture>;
-        
+
         @serializeAsColor3("diffuse")
         public diffuseColor = new Color3(1, 1, 1);
-        
+
         @serialize()
         public speed = 1.0;
-        
+
         private _scaledDiffuse = new Color3();
         private _renderId: number;
         private _lastTime: number = 0;
@@ -65,7 +65,7 @@ module BABYLON {
         }
 
         // Methods   
-        public isReadyForSubMesh(mesh: AbstractMesh, subMesh: SubMesh, useInstances?: boolean): boolean {   
+        public isReadyForSubMesh(mesh: AbstractMesh, subMesh: SubMesh, useInstances?: boolean): boolean {
             if (this.isFrozen) {
                 if (this._wasPreviouslyReady && subMesh.effect) {
                     return true;
@@ -97,7 +97,7 @@ module BABYLON {
                         defines._needUVs = true;
                         defines.DIFFUSE = true;
                     }
-                }              
+                }
             }
 
             // Misc.
@@ -105,10 +105,10 @@ module BABYLON {
                 defines.POINTSIZE = (this.pointsCloud || scene.forcePointsCloud);
                 defines.FOG = (scene.fogEnabled && mesh.applyFog && scene.fogMode !== Scene.FOGMODE_NONE && this.fogEnabled);
             }
-            
+
             // Values that need to be evaluated on every frame
-            MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false);
-            
+            MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false, this._shouldTurnAlphaTestOn(mesh));
+
             // Attribs
             MaterialHelper.PrepareDefinesForAttributes(mesh, defines, false, true);
 
@@ -119,11 +119,11 @@ module BABYLON {
                 scene.resetCachedMaterial();
 
                 // Fallbacks
-                var fallbacks = new EffectFallbacks();             
+                var fallbacks = new EffectFallbacks();
                 if (defines.FOG) {
                     fallbacks.addFallback(1, "FOG");
                 }
-                
+
                 if (defines.NUM_BONE_INFLUENCERS > 0) {
                     fallbacks.addCPUSkinningFallback(0, mesh);
                 }
@@ -144,24 +144,24 @@ module BABYLON {
 
                 // Legacy browser patch
                 var shaderName = "fire";
-                
+
                 var join = defines.toString();
                 subMesh.setEffect(scene.getEngine().createEffect(shaderName,
                     {
                         attributes: attribs,
                         uniformsNames: ["world", "view", "viewProjection", "vEyePosition",
-                                "vFogInfos", "vFogColor", "pointSize",
-                                "vDiffuseInfos", 
-                                "mBones",
-                                "vClipPlane", "diffuseMatrix",
-                                // Fire
-                                "time", "speed"
-                            ],
+                            "vFogInfos", "vFogColor", "pointSize",
+                            "vDiffuseInfos",
+                            "mBones",
+                            "vClipPlane", "diffuseMatrix",
+                            // Fire
+                            "time", "speed"
+                        ],
                         uniformBuffersNames: [],
                         samplers: ["diffuseSampler",
-                                // Fire
-                                "distortionSampler", "opacitySampler"
-                            ],
+                            // Fire
+                            "distortionSampler", "opacitySampler"
+                        ],
                         defines: join,
                         fallbacks: fallbacks,
                         onCompiled: this.onCompiled,
@@ -171,7 +171,7 @@ module BABYLON {
                         transformFeedbackVaryings: null
                     }, engine), defines);
             }
-            
+
             if (!subMesh.effect || !subMesh.effect.isReady()) {
                 return false;
             }
@@ -210,11 +210,11 @@ module BABYLON {
 
                     this._activeEffect.setFloat2("vDiffuseInfos", this._diffuseTexture.coordinatesIndex, this._diffuseTexture.level);
                     this._activeEffect.setMatrix("diffuseMatrix", this._diffuseTexture.getTextureMatrix());
-                    
+
                     this._activeEffect.setTexture("distortionSampler", this._distortionTexture);
                     this._activeEffect.setTexture("opacitySampler", this._opacityTexture);
                 }
-                
+
                 // Clip plane
                 if (scene.clipPlane) {
                     var clipPlane = scene.clipPlane;
@@ -226,7 +226,7 @@ module BABYLON {
                     this._activeEffect.setFloat("pointSize", this.pointSize);
                 }
 
-                MaterialHelper.BindEyePosition(effect, scene);               
+                MaterialHelper.BindEyePosition(effect, scene);
             }
 
             this._activeEffect.setColor4("vDiffuseColor", this._scaledDiffuse, this.alpha * mesh.visibility);
@@ -235,14 +235,14 @@ module BABYLON {
             if (scene.fogEnabled && mesh.applyFog && scene.fogMode !== Scene.FOGMODE_NONE) {
                 this._activeEffect.setMatrix("view", scene.getViewMatrix());
             }
-            
+
             // Fog
             MaterialHelper.BindFogParameters(scene, mesh, this._activeEffect);
-            
+
             // Time
             this._lastTime += scene.getEngine().getDeltaTime();
             this._activeEffect.setFloat("time", this._lastTime);
-            
+
             // Speed
             this._activeEffect.setFloat("speed", this.speed);
 
@@ -294,18 +294,18 @@ module BABYLON {
 
             if (this._distortionTexture === texture) {
                 return true;
-            }    
+            }
 
             if (this._opacityTexture === texture) {
                 return true;
-            }            
+            }
 
-            return false;    
-        }         
+            return false;
+        }
 
         public getClassName(): string {
             return "FireMaterial";
-        }        
+        }
 
         public dispose(forceDisposeEffect?: boolean): void {
             if (this._diffuseTexture) {
@@ -321,23 +321,23 @@ module BABYLON {
         public clone(name: string): FireMaterial {
             return SerializationHelper.Clone<FireMaterial>(() => new FireMaterial(name, this.getScene()), this);
         }
-		
-		public serialize(): any {
-		
+
+        public serialize(): any {
+
             var serializationObject = super.serialize();
-            serializationObject.customType      = "BABYLON.FireMaterial";
-            serializationObject.diffuseColor    = this.diffuseColor.asArray();
-            serializationObject.speed           = this.speed;
+            serializationObject.customType = "BABYLON.FireMaterial";
+            serializationObject.diffuseColor = this.diffuseColor.asArray();
+            serializationObject.speed = this.speed;
 
             if (this._diffuseTexture) {
                 serializationObject._diffuseTexture = this._diffuseTexture.serialize();
             }
-            
-			if (this._distortionTexture) {
+
+            if (this._distortionTexture) {
                 serializationObject._distortionTexture = this._distortionTexture.serialize();
             }
-			
-			if (this._opacityTexture) {
+
+            if (this._opacityTexture) {
                 serializationObject._opacityTexture = this._opacityTexture.serialize();
             }
 
@@ -347,12 +347,12 @@ module BABYLON {
         public static Parse(source: any, scene: Scene, rootUrl: string): FireMaterial {
             var material = new FireMaterial(source.name, scene);
 
-            material.diffuseColor   = Color3.FromArray(source.diffuseColor);
-            material.speed          = source.speed;
+            material.diffuseColor = Color3.FromArray(source.diffuseColor);
+            material.speed = source.speed;
 
-            material.alpha          = source.alpha;
+            material.alpha = source.alpha;
 
-            material.id             = source.id;
+            material.id = source.id;
 
             Tags.AddTagsTo(material, source.tags);
             material.backFaceCulling = source.backFaceCulling;
@@ -365,8 +365,8 @@ module BABYLON {
             if (source._distortionTexture) {
                 material._distortionTexture = Texture.Parse(source._distortionTexture, scene, rootUrl);
             }
-			
-			if (source._opacityTexture) {
+
+            if (source._opacityTexture) {
                 material._opacityTexture = Texture.Parse(source._opacityTexture, scene, rootUrl);
             }
 
@@ -377,5 +377,5 @@ module BABYLON {
             return material;
         }
     }
-} 
+}
 

+ 73 - 73
materialsLibrary/src/fur/babylon.furMaterial.ts

@@ -26,75 +26,75 @@ module BABYLON {
     }
 
     export class FurMaterial extends PushMaterial {
-        
+
         @serializeAsTexture("diffuseTexture")
         private _diffuseTexture: BaseTexture;
         @expandToProperty("_markAllSubMeshesAsTexturesDirty")
         public diffuseTexture: BaseTexture;
-        
+
         @serializeAsTexture("heightTexture")
         private _heightTexture: BaseTexture;
         @expandToProperty("_markAllSubMeshesAsTexturesDirty")
-        public heightTexture: BaseTexture;        
-        
+        public heightTexture: BaseTexture;
+
         @serializeAsColor3()
         public diffuseColor = new Color3(1, 1, 1);
-        
+
         @serialize()
         public furLength: number = 1;
-        
+
         @serialize()
         public furAngle: number = 0;
-        
+
         @serializeAsColor3()
-        public furColor = new Color3(0.44,0.21,0.02);
-        
+        public furColor = new Color3(0.44, 0.21, 0.02);
+
         @serialize()
         public furOffset: number = 0.0;
-        
+
         @serialize()
         public furSpacing: number = 12;
-        
+
         @serializeAsVector3()
         public furGravity = new Vector3(0, 0, 0);
-        
+
         @serialize()
         public furSpeed: number = 100;
-        
+
         @serialize()
         public furDensity: number = 20;
-        
+
         public furTexture: DynamicTexture;
-        
-        
+
+
         @serialize("disableLighting")
         private _disableLighting = false;
         @expandToProperty("_markAllSubMeshesAsLightsDirty")
-        public disableLighting: boolean;   
-        
+        public disableLighting: boolean;
+
         @serialize("maxSimultaneousLights")
         private _maxSimultaneousLights = 4;
         @expandToProperty("_markAllSubMeshesAsLightsDirty")
-        public maxSimultaneousLights: number; 
-        
+        public maxSimultaneousLights: number;
+
         @serialize()
         public highLevelFur: boolean = true;
-               
+
         public _meshes: AbstractMesh[];
 
         private _renderId: number;
-        
+
         private _furTime: number = 0;
 
         constructor(name: string, scene: Scene) {
             super(name, scene);
         }
-        
+
         @serialize()
         public get furTime() {
             return this._furTime;
         }
-        
+
         public set furTime(furTime: number) {
             this._furTime = furTime;
         }
@@ -110,11 +110,11 @@ module BABYLON {
         public getAlphaTestTexture(): Nullable<BaseTexture> {
             return null;
         }
-        
+
         public updateFur(): void {
             for (var i = 1; i < this._meshes.length; i++) {
                 var offsetFur = <FurMaterial>this._meshes[i].material;
-                
+
                 offsetFur.furLength = this.furLength;
                 offsetFur.furAngle = this.furAngle;
                 offsetFur.furGravity = this.furGravity;
@@ -130,7 +130,7 @@ module BABYLON {
         }
 
         // Methods   
-        public isReadyForSubMesh(mesh: AbstractMesh, subMesh: SubMesh, useInstances?: boolean): boolean {   
+        public isReadyForSubMesh(mesh: AbstractMesh, subMesh: SubMesh, useInstances?: boolean): boolean {
             if (this.isFrozen) {
                 if (this._wasPreviouslyReady && subMesh.effect) {
                     return true;
@@ -162,7 +162,7 @@ module BABYLON {
                             defines._needUVs = true;
                             defines.DIFFUSE = true;
                         }
-                    } 
+                    }
                     if (this.heightTexture && engine.getCaps().maxVertexTextureImageUnits) {
                         if (!this.heightTexture.isReady()) {
                             return false;
@@ -170,7 +170,7 @@ module BABYLON {
                             defines._needUVs = true;
                             defines.HEIGHTMAP = true;
                         }
-                    }               
+                    }
                 }
             }
 
@@ -187,8 +187,8 @@ module BABYLON {
             defines._needNormals = MaterialHelper.PrepareDefinesForLights(scene, mesh, defines, false, this._maxSimultaneousLights, this._disableLighting);
 
             // Values that need to be evaluated on every frame
-            MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false);
-            
+            MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false, this._shouldTurnAlphaTestOn(mesh));
+
             // Attribs
             MaterialHelper.PrepareDefinesForAttributes(mesh, defines, true, true);
 
@@ -199,13 +199,13 @@ module BABYLON {
                 scene.resetCachedMaterial();
 
                 // Fallbacks
-                var fallbacks = new EffectFallbacks();             
+                var fallbacks = new EffectFallbacks();
                 if (defines.FOG) {
                     fallbacks.addFallback(1, "FOG");
                 }
 
                 MaterialHelper.HandleFallbacksForShadows(defines, fallbacks, this.maxSimultaneousLights);
-             
+
                 if (defines.NUM_BONE_INFLUENCERS > 0) {
                     fallbacks.addCPUSkinningFallback(0, mesh);
                 }
@@ -237,7 +237,7 @@ module BABYLON {
                 var join = defines.toString();
                 var uniforms = ["world", "view", "viewProjection", "vEyePosition", "vLightsType", "vDiffuseColor",
                     "vFogInfos", "vFogColor", "pointSize",
-                    "vDiffuseInfos", 
+                    "vDiffuseInfos",
                     "mBones",
                     "vClipPlane", "diffuseMatrix",
                     "furLength", "furAngle", "furColor", "furOffset", "furGravity", "furTime", "furSpacing", "furDensity"
@@ -245,17 +245,17 @@ module BABYLON {
                 var samplers = ["diffuseSampler",
                     "heightTexture", "furTexture"
                 ];
-                
+
                 var uniformBuffers = new Array<string>()
 
                 MaterialHelper.PrepareUniformsAndSamplersList(<EffectCreationOptions>{
-                    uniformsNames: uniforms, 
+                    uniformsNames: uniforms,
                     uniformBuffersNames: uniformBuffers,
-                    samplers: samplers, 
-                    defines: defines, 
+                    samplers: samplers,
+                    defines: defines,
                     maxSimultaneousLights: this.maxSimultaneousLights
                 });
-                
+
                 subMesh.setEffect(scene.getEngine().createEffect(shaderName,
                     <EffectCreationOptions>{
                         attributes: attribs,
@@ -308,11 +308,11 @@ module BABYLON {
                     this._activeEffect.setFloat2("vDiffuseInfos", this._diffuseTexture.coordinatesIndex, this._diffuseTexture.level);
                     this._activeEffect.setMatrix("diffuseMatrix", this._diffuseTexture.getTextureMatrix());
                 }
-                
+
                 if (this._heightTexture) {
                     this._activeEffect.setTexture("heightTexture", this._heightTexture);
                 }
-                
+
                 // Clip plane
                 MaterialHelper.BindClipPlane(this._activeEffect, scene);
 
@@ -321,7 +321,7 @@ module BABYLON {
                     this._activeEffect.setFloat("pointSize", this.pointSize);
                 }
 
-                MaterialHelper.BindEyePosition(effect, scene);               
+                MaterialHelper.BindEyePosition(effect, scene);
             }
 
             this._activeEffect.setColor4("vDiffuseColor", this.diffuseColor, this.alpha * mesh.visibility);
@@ -337,23 +337,23 @@ module BABYLON {
 
             // Fog
             MaterialHelper.BindFogParameters(scene, mesh, this._activeEffect);
-            
+
             this._activeEffect.setFloat("furLength", this.furLength);
             this._activeEffect.setFloat("furAngle", this.furAngle);
             this._activeEffect.setColor4("furColor", this.furColor, 1.0);
-            
+
             if (this.highLevelFur) {
                 this._activeEffect.setVector3("furGravity", this.furGravity);
                 this._activeEffect.setFloat("furOffset", this.furOffset);
                 this._activeEffect.setFloat("furSpacing", this.furSpacing);
                 this._activeEffect.setFloat("furDensity", this.furDensity);
-                
+
                 this._furTime += this.getScene().getEngine().getDeltaTime() / this.furSpeed;
                 this._activeEffect.setFloat("furTime", this._furTime);
-                
+
                 this._activeEffect.setTexture("furTexture", this.furTexture);
             }
- 
+
             this._afterBind(mesh, this._activeEffect);
         }
 
@@ -363,7 +363,7 @@ module BABYLON {
             if (this.diffuseTexture && this.diffuseTexture.animations && this.diffuseTexture.animations.length > 0) {
                 results.push(this.diffuseTexture);
             }
-            
+
             if (this.heightTexture && this.heightTexture.animations && this.heightTexture.animations.length > 0) {
                 results.push(this.heightTexture);
             }
@@ -396,16 +396,16 @@ module BABYLON {
 
             if (this._heightTexture === texture) {
                 return true;
-            }        
+            }
 
-            return false;    
-        }        
+            return false;
+        }
 
         public dispose(forceDisposeEffect?: boolean): void {
             if (this.diffuseTexture) {
                 this.diffuseTexture.dispose();
             }
-            
+
             if (this._meshes) {
                 for (var i = 1; i < this._meshes.length; i++) {
                     let mat = this._meshes[i].material;
@@ -419,7 +419,7 @@ module BABYLON {
 
             super.dispose(forceDisposeEffect);
         }
-        
+
         public clone(name: string): FurMaterial {
             return SerializationHelper.Clone(() => new FurMaterial(name, this.getScene()), this);
         }
@@ -427,23 +427,23 @@ module BABYLON {
         public serialize(): any {
             var serializationObject = SerializationHelper.Serialize(this);
             serializationObject.customType = "BABYLON.FurMaterial";
-            
+
             if (this._meshes) {
                 serializationObject.sourceMeshName = this._meshes[0].name;
                 serializationObject.quality = this._meshes.length;
             }
-            
+
             return serializationObject;
         }
 
         public getClassName(): string {
             return "FurMaterial";
-        }          
+        }
 
         // Statics
         public static Parse(source: any, scene: Scene, rootUrl: string): FurMaterial {
             var material = SerializationHelper.Parse(() => new FurMaterial(source.name, scene), source, scene, rootUrl);
-            
+
             if (source.sourceMeshName && material.highLevelFur) {
                 scene.executeWhenReady(() => {
                     var sourceMesh = <Mesh>scene.getMeshByName(source.sourceMeshName);
@@ -454,27 +454,27 @@ module BABYLON {
                     }
                 });
             }
-            
+
             return material;
         }
-        
+
         public static GenerateTexture(name: string, scene: Scene): DynamicTexture {
             // Generate fur textures
             var texture = new DynamicTexture("FurTexture " + name, 256, scene, true);
             var context = texture.getContext();
-            
-            for ( var i = 0; i < 20000; ++i ) {
+
+            for (var i = 0; i < 20000; ++i) {
                 context.fillStyle = "rgba(255, " + Math.floor(Math.random() * 255) + ", " + Math.floor(Math.random() * 255) + ", 1)";
                 context.fillRect((Math.random() * texture.getSize().width), (Math.random() * texture.getSize().height), 2, 2);
             }
-            
+
             texture.update(false);
             texture.wrapU = Texture.WRAP_ADDRESSMODE;
             texture.wrapV = Texture.WRAP_ADDRESSMODE;
-            
+
             return texture;
         }
-        
+
         // Creates and returns an array of meshes used as shells for the Fur Material
         // that can be disposed later in your code
         // The quality is in interval [0, 100]
@@ -482,17 +482,17 @@ module BABYLON {
             var meshes = [sourceMesh];
             var mat: FurMaterial = <FurMaterial>sourceMesh.material;
             var i;
-            
+
             if (!(mat instanceof FurMaterial)) {
                 throw "The material of the source mesh must be a Fur Material";
             }
-            
+
             for (i = 1; i < quality; i++) {
                 var offsetFur = new BABYLON.FurMaterial(mat.name + i, sourceMesh.getScene());
                 sourceMesh.getScene().materials.pop();
                 Tags.EnableFor(offsetFur);
                 Tags.AddTagsTo(offsetFur, "furShellMaterial");
-                
+
                 offsetFur.furLength = mat.furLength;
                 offsetFur.furAngle = mat.furAngle;
                 offsetFur.furGravity = mat.furGravity;
@@ -505,23 +505,23 @@ module BABYLON {
                 offsetFur.highLevelFur = mat.highLevelFur;
                 offsetFur.furTime = mat.furTime;
                 offsetFur.furDensity = mat.furDensity;
-                
+
                 var offsetMesh = sourceMesh.clone(sourceMesh.name + i);
-                
+
                 offsetMesh.material = offsetFur;
                 offsetMesh.skeleton = sourceMesh.skeleton;
                 offsetMesh.position = Vector3.Zero();
                 meshes.push(offsetMesh);
             }
-            
+
             for (i = 1; i < meshes.length; i++) {
                 meshes[i].parent = sourceMesh;
             }
-            
+
             (<FurMaterial>sourceMesh.material)._meshes = meshes;
-            
+
             return meshes;
         }
     }
-} 
+}
 

+ 19 - 19
materialsLibrary/src/gradient/babylon.gradientMaterial.ts

@@ -27,7 +27,7 @@ module BABYLON {
         public POINTLIGHT0 = false;
         public POINTLIGHT1 = false;
         public POINTLIGHT2 = false;
-        public POINTLIGHT3 = false;        
+        public POINTLIGHT3 = false;
         public SHADOW0 = false;
         public SHADOW1 = false;
         public SHADOW2 = false;
@@ -57,30 +57,30 @@ module BABYLON {
     }
 
     export class GradientMaterial extends PushMaterial {
-          
+
         @serialize("maxSimultaneousLights")
         private _maxSimultaneousLights = 4;
         @expandToProperty("_markAllSubMeshesAsLightsDirty")
-        public maxSimultaneousLights: number;       
+        public maxSimultaneousLights: number;
 
         // The gradient top color, red by default
         @serializeAsColor3()
         public topColor = new Color3(1, 0, 0);
-        
+
         @serialize()
         public topColorAlpha = 1.0;
 
         // The gradient top color, blue by default
         @serializeAsColor3()
         public bottomColor = new Color3(0, 0, 1);
-        
+
         @serialize()
         public bottomColorAlpha = 1.0;
 
         // Gradient offset
         @serialize()
         public offset = 0;
-        
+
         @serialize()
         public smoothness = 1.0;
 
@@ -106,7 +106,7 @@ module BABYLON {
         }
 
         // Methods   
-        public isReadyForSubMesh(mesh: AbstractMesh, subMesh: SubMesh, useInstances?: boolean): boolean {   
+        public isReadyForSubMesh(mesh: AbstractMesh, subMesh: SubMesh, useInstances?: boolean): boolean {
             if (this.isFrozen) {
                 if (this._wasPreviouslyReady && subMesh.effect) {
                     return true;
@@ -128,7 +128,7 @@ module BABYLON {
 
             var engine = scene.getEngine();
 
-            MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false);
+            MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false, this._shouldTurnAlphaTestOn(mesh));
 
             MaterialHelper.PrepareDefinesForMisc(mesh, scene, false, this.pointsCloud, this.fogEnabled, defines);
 
@@ -144,13 +144,13 @@ module BABYLON {
                 scene.resetCachedMaterial();
 
                 // Fallbacks
-                var fallbacks = new EffectFallbacks();             
+                var fallbacks = new EffectFallbacks();
                 if (defines.FOG) {
                     fallbacks.addFallback(1, "FOG");
                 }
 
                 MaterialHelper.HandleFallbacksForShadows(defines, fallbacks);
-             
+
                 if (defines.NUM_BONE_INFLUENCERS > 0) {
                     fallbacks.addCPUSkinningFallback(0, mesh);
                 }
@@ -184,7 +184,7 @@ module BABYLON {
 
                 var uniforms = ["world", "view", "viewProjection", "vEyePosition", "vLightsType", "vDiffuseColor",
                     "vFogInfos", "vFogColor", "pointSize",
-                    "vDiffuseInfos", 
+                    "vDiffuseInfos",
                     "mBones",
                     "vClipPlane", "diffuseMatrix",
                     "topColor", "bottomColor", "offset", "smoothness"
@@ -193,13 +193,13 @@ module BABYLON {
                 var uniformBuffers = new Array<string>();
 
                 MaterialHelper.PrepareUniformsAndSamplersList(<EffectCreationOptions>{
-                    uniformsNames: uniforms, 
+                    uniformsNames: uniforms,
                     uniformBuffersNames: uniformBuffers,
-                    samplers: samplers, 
-                    defines: defines, 
+                    samplers: samplers,
+                    defines: defines,
                     maxSimultaneousLights: 4
                 });
-                
+
                 subMesh.setEffect(scene.getEngine().createEffect(shaderName,
                     <EffectCreationOptions>{
                         attributes: attribs,
@@ -237,7 +237,7 @@ module BABYLON {
             }
 
             this._activeEffect = effect;
-            
+
             // Matrices        
             this.bindOnlyWorldMatrix(world);
             this._activeEffect.setMatrix("viewProjection", scene.getTransformMatrix());
@@ -254,7 +254,7 @@ module BABYLON {
                     this._activeEffect.setFloat("pointSize", this.pointSize);
                 }
 
-                MaterialHelper.BindEyePosition(effect, scene);              
+                MaterialHelper.BindEyePosition(effect, scene);
             }
 
             this._activeEffect.setColor4("vDiffuseColor", this._scaledDiffuse, this.alpha * mesh.visibility);
@@ -300,12 +300,12 @@ module BABYLON {
 
         public getClassName(): string {
             return "GradientMaterial";
-        }              
+        }
 
         // Statics
         public static Parse(source: any, scene: Scene, rootUrl: string): GradientMaterial {
             return SerializationHelper.Parse(() => new GradientMaterial(source.name, scene), source, scene, rootUrl);
         }
     }
-} 
+}
 

+ 29 - 29
materialsLibrary/src/lava/babylon.lavaMaterial.ts

@@ -61,39 +61,39 @@ module BABYLON {
         private _diffuseTexture: BaseTexture;
         @expandToProperty("_markAllSubMeshesAsTexturesDirty")
         public diffuseTexture: BaseTexture;
-        
+
         @serializeAsTexture()
         public noiseTexture: BaseTexture;
-        
+
         @serializeAsColor3()
         public fogColor: Color3;
-        
+
         @serialize()
-        public speed : number = 1;
-        
+        public speed: number = 1;
+
         @serialize()
-        public movingSpeed : number = 1;
-        
+        public movingSpeed: number = 1;
+
         @serialize()
-        public lowFrequencySpeed : number = 1;
-        
+        public lowFrequencySpeed: number = 1;
+
         @serialize()
-        public fogDensity : number = 0.15;
+        public fogDensity: number = 0.15;
 
-        private _lastTime : number = 0;
+        private _lastTime: number = 0;
 
         @serializeAsColor3()
         public diffuseColor = new Color3(1, 1, 1);
-        
+
         @serialize("disableLighting")
         private _disableLighting = false;
         @expandToProperty("_markAllSubMeshesAsLightsDirty")
-        public disableLighting: boolean;   
+        public disableLighting: boolean;
 
         @serialize("maxSimultaneousLights")
         private _maxSimultaneousLights = 4;
         @expandToProperty("_markAllSubMeshesAsLightsDirty")
-        public maxSimultaneousLights: number; 
+        public maxSimultaneousLights: number;
 
         private _scaledDiffuse = new Color3();
         private _renderId: number;
@@ -115,7 +115,7 @@ module BABYLON {
         }
 
         // Methods   
-        public isReadyForSubMesh(mesh: AbstractMesh, subMesh: SubMesh, useInstances?: boolean): boolean {   
+        public isReadyForSubMesh(mesh: AbstractMesh, subMesh: SubMesh, useInstances?: boolean): boolean {
             if (this.isFrozen) {
                 if (this._wasPreviouslyReady && subMesh.effect) {
                     return true;
@@ -148,19 +148,19 @@ module BABYLON {
                             defines._needUVs = true;
                             defines.DIFFUSE = true;
                         }
-                    }                
+                    }
                 }
             }
 
-               // Misc.
+            // Misc.
             MaterialHelper.PrepareDefinesForMisc(mesh, scene, false, this.pointsCloud, this.fogEnabled, defines);
 
             // Lights
             defines._needNormals = MaterialHelper.PrepareDefinesForLights(scene, mesh, defines, false, this._maxSimultaneousLights, this._disableLighting);
 
             // Values that need to be evaluated on every frame
-            MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false);
-            
+            MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false, this._shouldTurnAlphaTestOn(mesh));
+
             // Attribs
             MaterialHelper.PrepareDefinesForAttributes(mesh, defines, true, true);
 
@@ -212,8 +212,8 @@ module BABYLON {
                     "vDiffuseInfos",
                     "mBones",
                     "vClipPlane", "diffuseMatrix",
-                    "time", "speed","movingSpeed",
-                    "fogColor","fogDensity", "lowFrequencySpeed"
+                    "time", "speed", "movingSpeed",
+                    "fogColor", "fogDensity", "lowFrequencySpeed"
                 ];
 
                 var samplers = ["diffuseSampler",
@@ -222,10 +222,10 @@ module BABYLON {
                 var uniformBuffers = new Array<string>()
 
                 MaterialHelper.PrepareUniformsAndSamplersList(<EffectCreationOptions>{
-                    uniformsNames: uniforms, 
+                    uniformsNames: uniforms,
                     uniformBuffersNames: uniformBuffers,
-                    samplers: samplers, 
-                    defines: defines, 
+                    samplers: samplers,
+                    defines: defines,
                     maxSimultaneousLights: this.maxSimultaneousLights
                 });
 
@@ -248,7 +248,7 @@ module BABYLON {
 
             this._renderId = scene.getRenderId();
             this._wasPreviouslyReady = true;
-            
+
             return true;
         }
 
@@ -316,7 +316,7 @@ module BABYLON {
             this._lastTime += scene.getEngine().getDeltaTime();
             this._activeEffect.setFloat("time", this._lastTime * this.speed / 1000);
 
-            if (! this.fogColor) {
+            if (!this.fogColor) {
                 this.fogColor = Color3.Black();
             }
             this._activeEffect.setColor3("fogColor", this.fogColor);
@@ -360,9 +360,9 @@ module BABYLON {
             if (this.diffuseTexture === texture) {
                 return true;
             }
-            
-            return false;    
-        }        
+
+            return false;
+        }
 
         public dispose(forceDisposeEffect?: boolean): void {
             if (this.diffuseTexture) {

+ 23 - 23
materialsLibrary/src/normal/babylon.normalMaterial.ts

@@ -27,7 +27,7 @@ module BABYLON {
         public POINTLIGHT0 = false;
         public POINTLIGHT1 = false;
         public POINTLIGHT2 = false;
-        public POINTLIGHT3 = false;        
+        public POINTLIGHT3 = false;
         public SHADOW0 = false;
         public SHADOW1 = false;
         public SHADOW2 = false;
@@ -64,16 +64,16 @@ module BABYLON {
 
         @serializeAsColor3()
         public diffuseColor = new Color3(1, 1, 1);
-        
+
         @serialize("disableLighting")
         private _disableLighting = false;
         @expandToProperty("_markAllSubMeshesAsLightsDirty")
-        public disableLighting: boolean;   
-        
+        public disableLighting: boolean;
+
         @serialize("maxSimultaneousLights")
         private _maxSimultaneousLights = 4;
         @expandToProperty("_markAllSubMeshesAsLightsDirty")
-        public maxSimultaneousLights: number; 
+        public maxSimultaneousLights: number;
 
         private _renderId: number;
 
@@ -94,7 +94,7 @@ module BABYLON {
         }
 
         // Methods   
-        public isReadyForSubMesh(mesh: AbstractMesh, subMesh: SubMesh, useInstances?: boolean): boolean {   
+        public isReadyForSubMesh(mesh: AbstractMesh, subMesh: SubMesh, useInstances?: boolean): boolean {
             if (this.isFrozen) {
                 if (this._wasPreviouslyReady && subMesh.effect) {
                     return true;
@@ -116,7 +116,7 @@ module BABYLON {
 
             var engine = scene.getEngine();
 
-             // Textures
+            // Textures
             if (defines._areTexturesDirty) {
                 defines._needUVs = false;
                 if (scene.texturesEnabled) {
@@ -127,7 +127,7 @@ module BABYLON {
                             defines._needUVs = true;
                             defines.DIFFUSE = true;
                         }
-                    }                
+                    }
                 }
             }
 
@@ -138,8 +138,8 @@ module BABYLON {
             defines._needNormals = MaterialHelper.PrepareDefinesForLights(scene, mesh, defines, false, this._maxSimultaneousLights, this._disableLighting);
 
             // Values that need to be evaluated on every frame
-            MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false);
-            
+            MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false, this._shouldTurnAlphaTestOn(mesh));
+
             // Attribs
             MaterialHelper.PrepareDefinesForAttributes(mesh, defines, true, true);
 
@@ -150,13 +150,13 @@ module BABYLON {
                 scene.resetCachedMaterial();
 
                 // Fallbacks
-                var fallbacks = new EffectFallbacks();             
+                var fallbacks = new EffectFallbacks();
                 if (defines.FOG) {
                     fallbacks.addFallback(1, "FOG");
                 }
 
                 MaterialHelper.HandleFallbacksForShadows(defines, fallbacks);
-                
+
                 if (defines.NUM_BONE_INFLUENCERS > 0) {
                     fallbacks.addCPUSkinningFallback(0, mesh);
                 }
@@ -188,7 +188,7 @@ module BABYLON {
 
                 var uniforms = ["world", "view", "viewProjection", "vEyePosition", "vLightsType", "vDiffuseColor",
                     "vFogInfos", "vFogColor", "pointSize",
-                    "vDiffuseInfos", 
+                    "vDiffuseInfos",
                     "mBones",
                     "vClipPlane", "diffuseMatrix"
                 ];
@@ -196,10 +196,10 @@ module BABYLON {
                 var uniformBuffers = new Array<string>()
 
                 MaterialHelper.PrepareUniformsAndSamplersList(<EffectCreationOptions>{
-                    uniformsNames: uniforms, 
+                    uniformsNames: uniforms,
                     uniformBuffersNames: uniformBuffers,
-                    samplers: samplers, 
-                    defines: defines, 
+                    samplers: samplers,
+                    defines: defines,
                     maxSimultaneousLights: 4
                 });
 
@@ -263,14 +263,14 @@ module BABYLON {
                     this._activeEffect.setFloat("pointSize", this.pointSize);
                 }
 
-                MaterialHelper.BindEyePosition(effect, scene);            
+                MaterialHelper.BindEyePosition(effect, scene);
             }
 
             this._activeEffect.setColor4("vDiffuseColor", this.diffuseColor, this.alpha * mesh.visibility);
 
             // Lights
             if (scene.lightsEnabled && !this.disableLighting) {
-                MaterialHelper.BindLights(scene, mesh, this._activeEffect, defines);          
+                MaterialHelper.BindLights(scene, mesh, this._activeEffect, defines);
             }
 
             // View
@@ -311,10 +311,10 @@ module BABYLON {
 
             if (this.diffuseTexture === texture) {
                 return true;
-            }  
+            }
 
-            return false;    
-        }        
+            return false;
+        }
 
         public dispose(forceDisposeEffect?: boolean): void {
             if (this.diffuseTexture) {
@@ -336,12 +336,12 @@ module BABYLON {
 
         public getClassName(): string {
             return "NormalMaterial";
-        }        
+        }
 
         // Statics
         public static Parse(source: any, scene: Scene, rootUrl: string): NormalMaterial {
             return SerializationHelper.Parse(() => new NormalMaterial(source.name, scene), source, scene, rootUrl);
         }
     }
-} 
+}
 

+ 18 - 18
materialsLibrary/src/shadowOnly/babylon.shadowOnlyMaterial.ts

@@ -42,10 +42,10 @@ module BABYLON {
 
         public set activeLight(light: IShadowLight) {
             this._activeLight = light;
-        }        
+        }
 
         // Methods   
-        public isReadyForSubMesh(mesh: AbstractMesh, subMesh: SubMesh, useInstances?: boolean): boolean {   
+        public isReadyForSubMesh(mesh: AbstractMesh, subMesh: SubMesh, useInstances?: boolean): boolean {
             if (this.isFrozen) {
                 if (this._wasPreviouslyReady && subMesh.effect) {
                     return true;
@@ -86,7 +86,7 @@ module BABYLON {
                 }
             }
 
-            MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false);
+            MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false, this._shouldTurnAlphaTestOn(mesh));
 
             MaterialHelper.PrepareDefinesForMisc(mesh, scene, false, this.pointsCloud, this.fogEnabled, defines);
 
@@ -102,13 +102,13 @@ module BABYLON {
                 scene.resetCachedMaterial();
 
                 // Fallbacks
-                var fallbacks = new EffectFallbacks();             
+                var fallbacks = new EffectFallbacks();
                 if (defines.FOG) {
                     fallbacks.addFallback(1, "FOG");
                 }
 
                 MaterialHelper.HandleFallbacksForShadows(defines, fallbacks, 1);
-                
+
                 if (defines.NUM_BONE_INFLUENCERS > 0) {
                     fallbacks.addCPUSkinningFallback(0, mesh);
                 }
@@ -126,22 +126,22 @@ module BABYLON {
                 var shaderName = "shadowOnly";
                 var join = defines.toString();
                 var uniforms = ["world", "view", "viewProjection", "vEyePosition", "vLightsType",
-                                "vFogInfos", "vFogColor", "pointSize", "alpha",
-                                "mBones",
-                                "vClipPlane"
+                    "vFogInfos", "vFogColor", "pointSize", "alpha",
+                    "mBones",
+                    "vClipPlane"
                 ];
                 var samplers = new Array<string>();
-                
+
                 var uniformBuffers = new Array<string>()
 
                 MaterialHelper.PrepareUniformsAndSamplersList(<EffectCreationOptions>{
-                    uniformsNames: uniforms, 
+                    uniformsNames: uniforms,
                     uniformBuffersNames: uniformBuffers,
-                    samplers: samplers, 
-                    defines: defines, 
+                    samplers: samplers,
+                    defines: defines,
                     maxSimultaneousLights: 1
                 });
-                
+
                 subMesh.setEffect(scene.getEngine().createEffect(shaderName,
                     <EffectCreationOptions>{
                         attributes: attribs,
@@ -197,12 +197,12 @@ module BABYLON {
 
                 this._activeEffect.setFloat("alpha", this.alpha);
 
-                MaterialHelper.BindEyePosition(effect, scene);             
+                MaterialHelper.BindEyePosition(effect, scene);
             }
 
             // Lights
             if (scene.lightsEnabled) {
-                MaterialHelper.BindLights(scene, mesh, this._activeEffect, defines, 1);          
+                MaterialHelper.BindLights(scene, mesh, this._activeEffect, defines, 1);
             }
 
             // View
@@ -219,7 +219,7 @@ module BABYLON {
         public clone(name: string): ShadowOnlyMaterial {
             return SerializationHelper.Clone<ShadowOnlyMaterial>(() => new ShadowOnlyMaterial(name, this.getScene()), this);
         }
-        
+
         public serialize(): any {
             var serializationObject = SerializationHelper.Serialize(this);
             serializationObject.customType = "BABYLON.ShadowOnlyMaterial";
@@ -228,12 +228,12 @@ module BABYLON {
 
         public getClassName(): string {
             return "ShadowOnlyMaterial";
-        }               
+        }
 
         // Statics
         public static Parse(source: any, scene: Scene, rootUrl: string): ShadowOnlyMaterial {
             return SerializationHelper.Parse(() => new ShadowOnlyMaterial(source.name, scene), source, scene, rootUrl);
         }
     }
-} 
+}
 

+ 27 - 27
materialsLibrary/src/simple/babylon.simpleMaterial.ts

@@ -31,16 +31,16 @@ module BABYLON {
 
         @serializeAsColor3("diffuse")
         public diffuseColor = new Color3(1, 1, 1);
-        
+
         @serialize("disableLighting")
         private _disableLighting = false;
         @expandToProperty("_markAllSubMeshesAsLightsDirty")
-        public disableLighting: boolean;   
-        
+        public disableLighting: boolean;
+
         @serialize("maxSimultaneousLights")
         private _maxSimultaneousLights = 4;
         @expandToProperty("_markAllSubMeshesAsLightsDirty")
-        public maxSimultaneousLights: number; 
+        public maxSimultaneousLights: number;
 
         private _renderId: number;
 
@@ -61,7 +61,7 @@ module BABYLON {
         }
 
         // Methods   
-        public isReadyForSubMesh(mesh: AbstractMesh, subMesh: SubMesh, useInstances?: boolean): boolean {   
+        public isReadyForSubMesh(mesh: AbstractMesh, subMesh: SubMesh, useInstances?: boolean): boolean {
             if (this.isFrozen) {
                 if (this._wasPreviouslyReady && subMesh.effect) {
                     return true;
@@ -94,7 +94,7 @@ module BABYLON {
                             defines._needUVs = true;
                             defines.DIFFUSE = true;
                         }
-                    }                
+                    }
                 }
             }
 
@@ -105,8 +105,8 @@ module BABYLON {
             defines._needNormals = MaterialHelper.PrepareDefinesForLights(scene, mesh, defines, false, this._maxSimultaneousLights, this._disableLighting);
 
             // Values that need to be evaluated on every frame
-            MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false);
-            
+            MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false, this._shouldTurnAlphaTestOn(mesh));
+
             // Attribs
             MaterialHelper.PrepareDefinesForAttributes(mesh, defines, true, true);
 
@@ -116,13 +116,13 @@ module BABYLON {
                 scene.resetCachedMaterial();
 
                 // Fallbacks
-                var fallbacks = new EffectFallbacks();             
+                var fallbacks = new EffectFallbacks();
                 if (defines.FOG) {
                     fallbacks.addFallback(1, "FOG");
                 }
 
                 MaterialHelper.HandleFallbacksForShadows(defines, fallbacks, this.maxSimultaneousLights);
-                
+
                 if (defines.NUM_BONE_INFLUENCERS > 0) {
                     fallbacks.addCPUSkinningFallback(0, mesh);
                 }
@@ -152,19 +152,19 @@ module BABYLON {
                 var shaderName = "simple";
                 var join = defines.toString();
                 var uniforms = ["world", "view", "viewProjection", "vEyePosition", "vLightsType", "vDiffuseColor",
-                                "vFogInfos", "vFogColor", "pointSize",
-                                "vDiffuseInfos", 
-                                "mBones",
-                                "vClipPlane", "diffuseMatrix"
+                    "vFogInfos", "vFogColor", "pointSize",
+                    "vDiffuseInfos",
+                    "mBones",
+                    "vClipPlane", "diffuseMatrix"
                 ];
                 var samplers = ["diffuseSampler"];
                 var uniformBuffers = new Array<string>()
 
                 MaterialHelper.PrepareUniformsAndSamplersList(<EffectCreationOptions>{
-                    uniformsNames: uniforms, 
+                    uniformsNames: uniforms,
                     uniformBuffersNames: uniformBuffers,
-                    samplers: samplers, 
-                    defines: defines, 
+                    samplers: samplers,
+                    defines: defines,
                     maxSimultaneousLights: this.maxSimultaneousLights
                 });
                 subMesh.setEffect(scene.getEngine().createEffect(shaderName,
@@ -220,7 +220,7 @@ module BABYLON {
                     this._activeEffect.setFloat2("vDiffuseInfos", this._diffuseTexture.coordinatesIndex, this._diffuseTexture.level);
                     this._activeEffect.setMatrix("diffuseMatrix", this._diffuseTexture.getTextureMatrix());
                 }
-                
+
                 // Clip plane
                 MaterialHelper.BindClipPlane(this._activeEffect, scene);
 
@@ -229,14 +229,14 @@ module BABYLON {
                     this._activeEffect.setFloat("pointSize", this.pointSize);
                 }
 
-                MaterialHelper.BindEyePosition(effect, scene);            
+                MaterialHelper.BindEyePosition(effect, scene);
             }
 
             this._activeEffect.setColor4("vDiffuseColor", this.diffuseColor, this.alpha * mesh.visibility);
 
             // Lights
             if (scene.lightsEnabled && !this.disableLighting) {
-                MaterialHelper.BindLights(scene, mesh, this._activeEffect, defines, this.maxSimultaneousLights);          
+                MaterialHelper.BindLights(scene, mesh, this._activeEffect, defines, this.maxSimultaneousLights);
             }
 
             // View
@@ -277,10 +277,10 @@ module BABYLON {
 
             if (this.diffuseTexture === texture) {
                 return true;
-            } 
+            }
 
-            return false;    
-        }        
+            return false;
+        }
 
         public dispose(forceDisposeEffect?: boolean): void {
             if (this._diffuseTexture) {
@@ -293,7 +293,7 @@ module BABYLON {
         public clone(name: string): SimpleMaterial {
             return SerializationHelper.Clone<SimpleMaterial>(() => new SimpleMaterial(name, this.getScene()), this);
         }
-        
+
         public serialize(): any {
             var serializationObject = SerializationHelper.Serialize(this);
             serializationObject.customType = "BABYLON.SimpleMaterial";
@@ -302,12 +302,12 @@ module BABYLON {
 
         public getClassName(): string {
             return "SimpleMaterial";
-        }               
-        
+        }
+
         // Statics
         public static Parse(source: any, scene: Scene, rootUrl: string): SimpleMaterial {
             return SerializationHelper.Parse(() => new SimpleMaterial(source.name, scene), source, scene, rootUrl);
         }
     }
-} 
+}
 

+ 39 - 39
materialsLibrary/src/terrain/babylon.terrainMaterial.ts

@@ -30,8 +30,8 @@ module BABYLON {
         @serializeAsTexture("mixTexture")
         private _mixTexture: BaseTexture;
         @expandToProperty("_markAllSubMeshesAsTexturesDirty")
-        public mixTexture: BaseTexture;        
-        
+        public mixTexture: BaseTexture;
+
         @serializeAsTexture("diffuseTexture1")
         private _diffuseTexture1: Texture;
         @expandToProperty("_markAllSubMeshesAsTexturesDirty")
@@ -41,45 +41,45 @@ module BABYLON {
         private _diffuseTexture2: Texture;
         @expandToProperty("_markAllSubMeshesAsTexturesDirty")
         public diffuseTexture2: Texture;
-        
+
         @serializeAsTexture("diffuseTexture3")
         private _diffuseTexture3: Texture;
         @expandToProperty("_markAllSubMeshesAsTexturesDirty")
         public diffuseTexture3: Texture;
-        
+
         @serializeAsTexture("bumpTexture1")
         private _bumpTexture1: Texture;
         @expandToProperty("_markAllSubMeshesAsTexturesDirty")
-        public bumpTexture1: Texture;        
-        
+        public bumpTexture1: Texture;
+
         @serializeAsTexture("bumpTexture2")
         private _bumpTexture2: Texture;
         @expandToProperty("_markAllSubMeshesAsTexturesDirty")
-        public bumpTexture2: Texture;        
-        
+        public bumpTexture2: Texture;
+
         @serializeAsTexture("bumpTexture3")
         private _bumpTexture3: Texture;
         @expandToProperty("_markAllSubMeshesAsTexturesDirty")
-        public bumpTexture3: Texture;   
-        
+        public bumpTexture3: Texture;
+
         @serializeAsColor3()
         public diffuseColor = new Color3(1, 1, 1);
-        
+
         @serializeAsColor3()
         public specularColor = new Color3(0, 0, 0);
-        
+
         @serialize()
         public specularPower = 64;
-        
+
         @serialize("disableLighting")
         private _disableLighting = false;
         @expandToProperty("_markAllSubMeshesAsLightsDirty")
-        public disableLighting: boolean;   
-        
+        public disableLighting: boolean;
+
         @serialize("maxSimultaneousLights")
         private _maxSimultaneousLights = 4;
         @expandToProperty("_markAllSubMeshesAsLightsDirty")
-        public maxSimultaneousLights: number; 
+        public maxSimultaneousLights: number;
 
         private _renderId: number;
 
@@ -100,7 +100,7 @@ module BABYLON {
         }
 
         // Methods   
-        public isReadyForSubMesh(mesh: AbstractMesh, subMesh: SubMesh, useInstances?: boolean): boolean {   
+        public isReadyForSubMesh(mesh: AbstractMesh, subMesh: SubMesh, useInstances?: boolean): boolean {
             if (this.isFrozen) {
                 if (this._wasPreviouslyReady && subMesh.effect) {
                     return true;
@@ -138,7 +138,7 @@ module BABYLON {
                     defines.BUMP = true;
                 }
             }
-            
+
             // Misc.
             MaterialHelper.PrepareDefinesForMisc(mesh, scene, false, this.pointsCloud, this.fogEnabled, defines);
 
@@ -146,8 +146,8 @@ module BABYLON {
             defines._needNormals = MaterialHelper.PrepareDefinesForLights(scene, mesh, defines, false, this._maxSimultaneousLights, this._disableLighting);
 
             // Values that need to be evaluated on every frame
-            MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false);
-            
+            MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false, this._shouldTurnAlphaTestOn(mesh));
+
             // Attribs
             MaterialHelper.PrepareDefinesForAttributes(mesh, defines, true, true);
 
@@ -157,13 +157,13 @@ module BABYLON {
                 scene.resetCachedMaterial();
 
                 // Fallbacks
-                var fallbacks = new EffectFallbacks();             
+                var fallbacks = new EffectFallbacks();
                 if (defines.FOG) {
                     fallbacks.addFallback(1, "FOG");
                 }
 
                 MaterialHelper.HandleFallbacksForShadows(defines, fallbacks, this.maxSimultaneousLights);
-             
+
                 if (defines.NUM_BONE_INFLUENCERS > 0) {
                     fallbacks.addCPUSkinningFallback(0, mesh);
                 }
@@ -195,7 +195,7 @@ module BABYLON {
                 var join = defines.toString();
                 var uniforms = ["world", "view", "viewProjection", "vEyePosition", "vLightsType", "vDiffuseColor", "vSpecularColor",
                     "vFogInfos", "vFogColor", "pointSize",
-                    "vTextureInfos", 
+                    "vTextureInfos",
                     "mBones",
                     "vClipPlane", "textureMatrix",
                     "diffuse1Infos", "diffuse2Infos", "diffuse3Infos"
@@ -207,13 +207,13 @@ module BABYLON {
                 var uniformBuffers = new Array<string>()
 
                 MaterialHelper.PrepareUniformsAndSamplersList(<EffectCreationOptions>{
-                    uniformsNames: uniforms, 
+                    uniformsNames: uniforms,
                     uniformBuffersNames: uniformBuffers,
-                    samplers: samplers, 
-                    defines: defines, 
+                    samplers: samplers,
+                    defines: defines,
                     maxSimultaneousLights: this.maxSimultaneousLights
                 });
-                
+
                 subMesh.setEffect(scene.getEngine().createEffect(shaderName,
                     <EffectCreationOptions>{
                         attributes: attribs,
@@ -264,7 +264,7 @@ module BABYLON {
                     this._activeEffect.setTexture("textureSampler", this._mixTexture);
                     this._activeEffect.setFloat2("vTextureInfos", this._mixTexture.coordinatesIndex, this._mixTexture.level);
                     this._activeEffect.setMatrix("textureMatrix", this._mixTexture.getTextureMatrix());
-                    
+
                     if (StandardMaterial.DiffuseTextureEnabled) {
                         if (this._diffuseTexture1) {
                             this._activeEffect.setTexture("diffuse1Sampler", this._diffuseTexture1);
@@ -279,7 +279,7 @@ module BABYLON {
                             this._activeEffect.setFloat2("diffuse3Infos", this._diffuseTexture3.uScale, this._diffuseTexture3.vScale);
                         }
                     }
-                    
+
                     if (StandardMaterial.BumpTextureEnabled && scene.getEngine().getCaps().standardDerivatives) {
                         if (this._bumpTexture1) {
                             this._activeEffect.setTexture("bump1Sampler", this._bumpTexture1);
@@ -300,11 +300,11 @@ module BABYLON {
                     this._activeEffect.setFloat("pointSize", this.pointSize);
                 }
 
-                MaterialHelper.BindEyePosition(effect, scene);             
+                MaterialHelper.BindEyePosition(effect, scene);
             }
 
             this._activeEffect.setColor4("vDiffuseColor", this.diffuseColor, this.alpha * mesh.visibility);
-            
+
             if (defines.SPECULARTERM) {
                 this._activeEffect.setColor4("vSpecularColor", this.specularColor, this.specularPower);
             }
@@ -379,7 +379,7 @@ module BABYLON {
 
             if (this._diffuseTexture1 === texture) {
                 return true;
-            }    
+            }
 
             if (this._diffuseTexture2 === texture) {
                 return true;
@@ -387,7 +387,7 @@ module BABYLON {
 
             if (this._diffuseTexture3 === texture) {
                 return true;
-            }        
+            }
 
             if (this._bumpTexture1 === texture) {
                 return true;
@@ -395,14 +395,14 @@ module BABYLON {
 
             if (this._bumpTexture2 === texture) {
                 return true;
-            }        
+            }
 
             if (this._bumpTexture3 === texture) {
                 return true;
-            }      
+            }
 
-            return false;    
-        }        
+            return false;
+        }
 
         public dispose(forceDisposeEffect?: boolean): void {
             if (this.mixTexture) {
@@ -411,7 +411,7 @@ module BABYLON {
 
             super.dispose(forceDisposeEffect);
         }
-        
+
         public clone(name: string): TerrainMaterial {
             return SerializationHelper.Clone(() => new TerrainMaterial(name, this.getScene()), this);
         }
@@ -431,5 +431,5 @@ module BABYLON {
             return SerializationHelper.Parse(() => new TerrainMaterial(source.name, scene), source, scene, rootUrl);
         }
     }
-} 
+}
 

+ 49 - 49
materialsLibrary/src/triPlanar/babylon.triPlanarMaterial.ts

@@ -5,11 +5,11 @@ module BABYLON {
         public DIFFUSEX = false;
         public DIFFUSEY = false;
         public DIFFUSEZ = false;
-        
+
         public BUMPX = false;
         public BUMPY = false;
         public BUMPZ = false;
-        
+
         public CLIPPLANE = false;
         public ALPHATEST = false;
         public DEPTHPREPASS = false;
@@ -32,59 +32,59 @@ module BABYLON {
     export class TriPlanarMaterial extends PushMaterial {
         @serializeAsTexture()
         public mixTexture: BaseTexture;
-        
+
         @serializeAsTexture("diffuseTextureX")
         private _diffuseTextureX: BaseTexture;
         @expandToProperty("_markAllSubMeshesAsTexturesDirty")
         public diffuseTextureX: BaseTexture;
-        
+
         @serializeAsTexture("diffuseTexturY")
         private _diffuseTextureY: BaseTexture;
         @expandToProperty("_markAllSubMeshesAsTexturesDirty")
-        public diffuseTextureY: BaseTexture;        
-        
+        public diffuseTextureY: BaseTexture;
+
         @serializeAsTexture("diffuseTextureZ")
         private _diffuseTextureZ: BaseTexture;
         @expandToProperty("_markAllSubMeshesAsTexturesDirty")
-        public diffuseTextureZ: BaseTexture;        
-        
+        public diffuseTextureZ: BaseTexture;
+
         @serializeAsTexture("normalTextureX")
         private _normalTextureX: BaseTexture;
         @expandToProperty("_markAllSubMeshesAsTexturesDirty")
-        public normalTextureX: BaseTexture;        
-        
+        public normalTextureX: BaseTexture;
+
         @serializeAsTexture("normalTextureY")
         private _normalTextureY: BaseTexture;
         @expandToProperty("_markAllSubMeshesAsTexturesDirty")
-        public normalTextureY: BaseTexture;        
-        
+        public normalTextureY: BaseTexture;
+
         @serializeAsTexture("normalTextureZ")
         private _normalTextureZ: BaseTexture;
         @expandToProperty("_markAllSubMeshesAsTexturesDirty")
-        public normalTextureZ: BaseTexture;        
-               
+        public normalTextureZ: BaseTexture;
+
         @serialize()
         public tileSize: number = 1;
-        
+
         @serializeAsColor3()
         public diffuseColor = new Color3(1, 1, 1);
-        
+
         @serializeAsColor3()
         public specularColor = new Color3(0.2, 0.2, 0.2);
-        
+
         @serialize()
         public specularPower = 64;
-        
+
         @serialize("disableLighting")
         private _disableLighting = false;
         @expandToProperty("_markAllSubMeshesAsLightsDirty")
-        public disableLighting: boolean;   
-        
+        public disableLighting: boolean;
+
         @serialize("maxSimultaneousLights")
         private _maxSimultaneousLights = 4;
         @expandToProperty("_markAllSubMeshesAsLightsDirty")
-        public maxSimultaneousLights: number; 
-        
+        public maxSimultaneousLights: number;
+
         private _renderId: number;
 
         constructor(name: string, scene: Scene) {
@@ -104,7 +104,7 @@ module BABYLON {
         }
 
         // Methods   
-        public isReadyForSubMesh(mesh: AbstractMesh, subMesh: SubMesh, useInstances?: boolean): boolean {   
+        public isReadyForSubMesh(mesh: AbstractMesh, subMesh: SubMesh, useInstances?: boolean): boolean {
             if (this.isFrozen) {
                 if (this._wasPreviouslyReady && subMesh.effect) {
                     return true;
@@ -127,13 +127,13 @@ module BABYLON {
             var engine = scene.getEngine();
 
             // Textures
-            if (defines._areTexturesDirty) {                
+            if (defines._areTexturesDirty) {
                 if (scene.texturesEnabled) {
                     if (StandardMaterial.DiffuseTextureEnabled) {
                         var textures = [this.diffuseTextureX, this.diffuseTextureY, this.diffuseTextureZ];
                         var textureDefines = ["DIFFUSEX", "DIFFUSEY", "DIFFUSEZ"];
-                        
-                        for (var i=0; i < textures.length; i++) {
+
+                        for (var i = 0; i < textures.length; i++) {
                             if (textures[i]) {
                                 if (!textures[i].isReady()) {
                                     return false;
@@ -146,8 +146,8 @@ module BABYLON {
                     if (StandardMaterial.BumpTextureEnabled) {
                         var textures = [this.normalTextureX, this.normalTextureY, this.normalTextureZ];
                         var textureDefines = ["BUMPX", "BUMPY", "BUMPZ"];
-                        
-                        for (var i=0; i < textures.length; i++) {
+
+                        for (var i = 0; i < textures.length; i++) {
                             if (textures[i]) {
                                 if (!textures[i].isReady()) {
                                     return false;
@@ -167,8 +167,8 @@ module BABYLON {
             defines._needNormals = MaterialHelper.PrepareDefinesForLights(scene, mesh, defines, false, this._maxSimultaneousLights, this._disableLighting);
 
             // Values that need to be evaluated on every frame
-            MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false);
-            
+            MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false, this._shouldTurnAlphaTestOn(mesh));
+
             // Attribs
             MaterialHelper.PrepareDefinesForAttributes(mesh, defines, true, true);
 
@@ -178,13 +178,13 @@ module BABYLON {
                 scene.resetCachedMaterial();
 
                 // Fallbacks
-                var fallbacks = new EffectFallbacks();             
+                var fallbacks = new EffectFallbacks();
                 if (defines.FOG) {
                     fallbacks.addFallback(1, "FOG");
                 }
 
                 MaterialHelper.HandleFallbacksForShadows(defines, fallbacks, this.maxSimultaneousLights);
-             
+
                 if (defines.NUM_BONE_INFLUENCERS > 0) {
                     fallbacks.addCPUSkinningFallback(0, mesh);
                 }
@@ -219,13 +219,13 @@ module BABYLON {
                 var uniformBuffers = new Array<string>()
 
                 MaterialHelper.PrepareUniformsAndSamplersList(<EffectCreationOptions>{
-                    uniformsNames: uniforms, 
+                    uniformsNames: uniforms,
                     uniformBuffersNames: uniformBuffers,
-                    samplers: samplers, 
-                    defines: defines, 
+                    samplers: samplers,
+                    defines: defines,
                     maxSimultaneousLights: this.maxSimultaneousLights
                 });
-                
+
                 subMesh.setEffect(scene.getEngine().createEffect(shaderName,
                     <EffectCreationOptions>{
                         attributes: attribs,
@@ -245,7 +245,7 @@ module BABYLON {
 
             this._renderId = scene.getRenderId();
             this._wasPreviouslyReady = true;
-            
+
             return true;
         }
 
@@ -269,7 +269,7 @@ module BABYLON {
 
             // Bones
             MaterialHelper.BindBonesParameters(mesh, this._activeEffect);
-            
+
             this._activeEffect.setFloat("tileSize", this.tileSize);
 
             if (scene.getCachedMaterial() !== this) {
@@ -300,11 +300,11 @@ module BABYLON {
                     this._activeEffect.setFloat("pointSize", this.pointSize);
                 }
 
-                MaterialHelper.BindEyePosition(effect, scene);               
+                MaterialHelper.BindEyePosition(effect, scene);
             }
 
             this._activeEffect.setColor4("vDiffuseColor", this.diffuseColor, this.alpha * mesh.visibility);
-            
+
             if (defines.SPECULARTERM) {
                 this._activeEffect.setColor4("vSpecularColor", this.specularColor, this.specularPower);
             }
@@ -371,11 +371,11 @@ module BABYLON {
 
             if (this._diffuseTextureX === texture) {
                 return true;
-            }    
+            }
 
             if (this._diffuseTextureY === texture) {
                 return true;
-            }         
+            }
 
             if (this._diffuseTextureZ === texture) {
                 return true;
@@ -383,17 +383,17 @@ module BABYLON {
 
             if (this._normalTextureX === texture) {
                 return true;
-            }     
+            }
 
             if (this._normalTextureY === texture) {
                 return true;
-            }     
+            }
 
             if (this._normalTextureZ === texture) {
                 return true;
-            }                                 
-            return false;    
-        }        
+            }
+            return false;
+        }
 
         public dispose(forceDisposeEffect?: boolean): void {
             if (this.mixTexture) {
@@ -402,7 +402,7 @@ module BABYLON {
 
             super.dispose(forceDisposeEffect);
         }
-        
+
         public clone(name: string): TriPlanarMaterial {
             return SerializationHelper.Clone(() => new TriPlanarMaterial(name, this.getScene()), this);
         }
@@ -422,5 +422,5 @@ module BABYLON {
             return SerializationHelper.Parse(() => new TriPlanarMaterial(source.name, scene), source, scene, rootUrl);
         }
     }
-} 
+}
 

+ 6 - 6
materialsLibrary/src/water/babylon.waterMaterial.ts

@@ -164,8 +164,8 @@ module BABYLON {
             // Create render targets
             this.getRenderTargetTextures = (): SmartArray<RenderTargetTexture> => {
                 this._renderTargets.reset();
-                this._renderTargets.push(<RenderTargetTexture> this._reflectionRTT);
-                this._renderTargets.push(<RenderTargetTexture> this._refractionRTT);
+                this._renderTargets.push(<RenderTargetTexture>this._reflectionRTT);
+                this._renderTargets.push(<RenderTargetTexture>this._refractionRTT);
 
                 return this._renderTargets;
             }
@@ -275,7 +275,7 @@ module BABYLON {
                 }
             }
 
-            MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false);
+            MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false, this._shouldTurnAlphaTestOn(mesh));
 
             MaterialHelper.PrepareDefinesForMisc(mesh, scene, this._useLogarithmicDepth, this.pointsCloud, this.fogEnabled, defines);
 
@@ -614,12 +614,12 @@ module BABYLON {
                 this.bumpTexture.dispose();
             }
 
-            var index = this.getScene().customRenderTargets.indexOf(<RenderTargetTexture> this._refractionRTT);
+            var index = this.getScene().customRenderTargets.indexOf(<RenderTargetTexture>this._refractionRTT);
             if (index != -1) {
                 this.getScene().customRenderTargets.splice(index, 1);
             }
             index = -1;
-            index = this.getScene().customRenderTargets.indexOf(<RenderTargetTexture> this._reflectionRTT);
+            index = this.getScene().customRenderTargets.indexOf(<RenderTargetTexture>this._reflectionRTT);
             if (index != -1) {
                 this.getScene().customRenderTargets.splice(index, 1);
             }
@@ -641,7 +641,7 @@ module BABYLON {
         public serialize(): any {
             var serializationObject = SerializationHelper.Serialize(this);
             serializationObject.customType = "BABYLON.WaterMaterial";
-            
+
             serializationObject.renderList = [];
             if (this._refractionRTT && this._refractionRTT.renderList) {
                 for (var i = 0; i < this._refractionRTT.renderList.length; i++) {

+ 19 - 10
src/Animations/babylon.animationGroup.ts

@@ -16,7 +16,7 @@ module BABYLON {
         private _targetedAnimations = new Array<TargetedAnimation>();
         private _animatables = new Array<Animatable>();
         private _from = Number.MAX_VALUE;
-        private _to = Number.MIN_VALUE;
+        private _to = -Number.MAX_VALUE;
         private _isStarted: boolean;
         private _speedRatio = 1;
 
@@ -52,6 +52,13 @@ module BABYLON {
             }
         }
 
+        /**
+         * Gets the targeted animations for this animation group
+         */
+        public get targetedAnimations(): Array<TargetedAnimation> {
+            return this._targetedAnimations;
+        }
+
         public constructor(public name: string, scene: Nullable<Scene> = null) {
             this._scene = scene || Engine.LastCreatedScene!;
 
@@ -87,11 +94,11 @@ module BABYLON {
         /**
          * This function will normalize every animation in the group to make sure they all go from beginFrame to endFrame
          * It can add constant keys at begin or end
-         * @param beginFrame defines the new begin frame for all animations. It can't be bigger than the smaller begin frame of all animations
-         * @param endFrame defines the new end frame for all animations. It can't be smaller than the larger end frame of all animations
+         * @param beginFrame defines the new begin frame for all animations. It can't be bigger than the smallest begin frame of all animations
+         * @param endFrame defines the new end frame for all animations. It can't be smaller than the largest end frame of all animations
          */
-        public normalize(beginFrame: number, endFrame: number): AnimationGroup {
-            beginFrame = Math.min(beginFrame, this._from);
+        public normalize(beginFrame = -Number.MAX_VALUE, endFrame = Number.MAX_VALUE): AnimationGroup {
+            beginFrame = Math.max(beginFrame, this._from);
             endFrame = Math.min(endFrame, this._to);
 
             for (var index = 0; index < this._targetedAnimations.length; index++) {
@@ -101,21 +108,23 @@ module BABYLON {
                 let endKey = keys[keys.length - 1];
 
                 if (startKey.frame > beginFrame) {
-                    let newKey = {
+                    let newKey: IAnimationKey = {
                         frame: beginFrame,
                         value: startKey.value,
                         inTangent: startKey.inTangent,
-                        outTangent: startKey.outTangent
+                        outTangent: startKey.outTangent,
+                        interpolation: startKey.interpolation
                     }
                     keys.splice(0, 0, newKey);
                 }
 
                 if (endKey.frame < endFrame) {
-                    let newKey = {
+                    let newKey: IAnimationKey = {
                         frame: endFrame,
                         value: endKey.value,
-                        inTangent: startKey.outTangent,
-                        outTangent: startKey.outTangent
+                        inTangent: endKey.outTangent,
+                        outTangent: endKey.outTangent,
+                        interpolation: endKey.interpolation
                     }
                     keys.push(newKey);
                 }

+ 23 - 23
src/Debug/babylon.rayHelper.ts

@@ -1,19 +1,19 @@
 module BABYLON {
     export class RayHelper {
-        
+
         public ray: Nullable<Ray>;
 
         private _renderPoints: Vector3[];
         private _renderLine: Nullable<LinesMesh>;
         private _renderFunction: Nullable<() => void>;
         private _scene: Nullable<Scene>;
-        
+
         private _updateToMeshFunction: Nullable<() => void>;
         private _attachedToMesh: Nullable<AbstractMesh>;
         private _meshSpaceDirection: Vector3;
         private _meshSpaceOrigin: Vector3;
 
-        public static CreateAndShow(ray: Ray, scene: Scene, color:Color3): RayHelper {
+        public static CreateAndShow(ray: Ray, scene: Scene, color: Color3): RayHelper {
             var helper = new RayHelper(ray);
 
             helper.show(scene, color);
@@ -21,13 +21,13 @@ module BABYLON {
             return helper;
         }
 
-        constructor(ray:Ray) {
+        constructor(ray: Ray) {
             this.ray = ray;
         }
 
-        public show(scene:Scene, color:Color3): void{
+        public show(scene: Scene, color: Color3): void {
 
-            if(!this._renderFunction && this.ray){
+            if (!this._renderFunction && this.ray) {
 
                 var ray = this.ray;
 
@@ -47,9 +47,9 @@ module BABYLON {
 
         }
 
-        public hide(): void{
+        public hide(): void {
 
-            if(this._renderFunction && this._scene){
+            if (this._renderFunction && this._scene) {
                 this._scene.unregisterBeforeRender(this._renderFunction);
                 this._scene = null;
                 this._renderFunction = null;
@@ -73,7 +73,7 @@ module BABYLON {
 
             var point = this._renderPoints[1];
             var len = Math.min(ray.length, 1000000);
-            
+
             point.copyFrom(ray.direction);
             point.scaleInPlace(len);
             point.addInPlace(ray.origin);
@@ -82,7 +82,7 @@ module BABYLON {
 
         }
 
-        public attachToMesh(mesh:AbstractMesh, meshSpaceDirection?:Vector3, meshSpaceOrigin?:Vector3, length?:number): void{
+        public attachToMesh(mesh: AbstractMesh, meshSpaceDirection?: Vector3, meshSpaceOrigin?: Vector3, length?: number): void {
 
             this._attachedToMesh = mesh;
 
@@ -92,36 +92,36 @@ module BABYLON {
                 return;
             }
 
-            if(!ray.direction){
+            if (!ray.direction) {
                 ray.direction = Vector3.Zero();
             }
 
-            if(!ray.origin){
+            if (!ray.origin) {
                 ray.origin = Vector3.Zero();
             }
 
-            if(length){
+            if (length) {
                 ray.length = length;
             }
 
-            if(!meshSpaceOrigin){
+            if (!meshSpaceOrigin) {
                 meshSpaceOrigin = Vector3.Zero();
             }
 
-            if(!meshSpaceDirection){
+            if (!meshSpaceDirection) {
                 // -1 so that this will work with Mesh.lookAt
                 meshSpaceDirection = new Vector3(0, 0, -1);
             }
 
-            if(!this._meshSpaceDirection){
+            if (!this._meshSpaceDirection) {
                 this._meshSpaceDirection = meshSpaceDirection.clone();
                 this._meshSpaceOrigin = meshSpaceOrigin.clone();
-            }else{
+            } else {
                 this._meshSpaceDirection.copyFrom(meshSpaceDirection);
                 this._meshSpaceOrigin.copyFrom(meshSpaceOrigin);
             }
 
-            if(!this._updateToMeshFunction){
+            if (!this._updateToMeshFunction) {
                 this._updateToMeshFunction = (<() => void>this._updateToMesh.bind(this));
                 this._attachedToMesh.getScene().registerBeforeRender(this._updateToMeshFunction);
             }
@@ -130,9 +130,9 @@ module BABYLON {
 
         }
 
-        public detachFromMesh(): void{
+        public detachFromMesh(): void {
 
-            if(this._attachedToMesh){
+            if (this._attachedToMesh) {
                 if (this._updateToMeshFunction) {
                     this._attachedToMesh.getScene().unregisterBeforeRender(this._updateToMeshFunction);
                 }
@@ -142,7 +142,7 @@ module BABYLON {
 
         }
 
-        private _updateToMesh(): void{
+        private _updateToMesh(): void {
 
             var ray = this.ray;
 
@@ -150,7 +150,7 @@ module BABYLON {
                 return;
             }
 
-            if(this._attachedToMesh._isDisposed){
+            if (this._attachedToMesh._isDisposed) {
                 this.detachFromMesh();
                 return;
             }
@@ -160,7 +160,7 @@ module BABYLON {
 
         }
 
-        public dispose(): void{
+        public dispose(): void {
 
             this.hide();
             this.detachFromMesh();

+ 80 - 79
src/Engine/babylon.engine.ts

@@ -654,7 +654,7 @@
          */
         public disableTextureBindingOptimization = false;
 
-        public static audioEngine: AudioEngine;       
+        public static audioEngine: AudioEngine;
 
         // Focus
         private _onFocus: () => void;
@@ -680,7 +680,6 @@
         private _hardwareScalingLevel: number;
         protected _caps: EngineCapabilities;
         private _pointerLockRequested: boolean;
-        private _alphaTest: boolean;
         private _isStencilEnable: boolean;
         private _colorWrite = true;
 
@@ -731,7 +730,8 @@
 
         // Cache
         private _internalTexturesCache = new Array<InternalTexture>();
-        protected _activeChannel: number;
+        protected _activeChannel = 0;
+        private _currentTextureChannel = -1;
         protected _boundTexturesCache: { [key: string]: Nullable<InternalTexture> } = {};
         protected _boundTexturesStack = new Array<InternalTexture>();
         protected _currentEffect: Nullable<Effect>;
@@ -818,12 +818,12 @@
 
         /**
          * @constructor
-         * @param {HTMLCanvasElement | WebGLRenderingContext} canvasOrContext - the canvas or WebGL context to use for rendering
-         * @param {boolean} [antialias] - enable antialiasing (default: false)
-         * @param {EngineOptions} [options] - further options to be sent to the getContext() function
-         * @param {boolean} [adaptToDeviceRatio] - whether to adapt to the device's viewport characteristics (default: false)
+         * @param canvasOrContext defines the canvas or WebGL context to use for rendering
+         * @param antialias defines enable antialiasing (default: false)
+         * @param options defines further options to be sent to the getContext() function
+         * @param adaptToDeviceRatio defines whether to adapt to the device's viewport characteristics (default: false)
          */
-        constructor(canvasOrContext: Nullable<HTMLCanvasElement | WebGLRenderingContext>, antialias?: boolean, options?: EngineOptions, adaptToDeviceRatio:boolean = false) {
+        constructor(canvasOrContext: Nullable<HTMLCanvasElement | WebGLRenderingContext>, antialias?: boolean, options?: EngineOptions, adaptToDeviceRatio: boolean = false) {
             let canvas: Nullable<HTMLCanvasElement> = null;
             Engine.Instances.push(this);
 
@@ -895,8 +895,8 @@
                                         this.disableUniformBuffers = true;
                                         break;
                                     case "textureBindingOptimization":
-                                        this.disableTextureBindingOptimization = true;    
-                                        break;    
+                                        this.disableTextureBindingOptimization = true;
+                                        break;
                                 }
                             }
                             break;
@@ -1349,7 +1349,7 @@
             for (let slot = 0; slot < this._maxSimultaneousTextures; slot++) {
                 this._nextFreeTextureSlots.push(slot);
             }
-            this._activeChannel = -1;
+            this._currentTextureChannel = -1;
         }
 
         public isDeterministicLockStep(): boolean {
@@ -3027,14 +3027,6 @@
             return this._alphaMode;
         }
 
-        public setAlphaTesting(enable: boolean): void {
-            this._alphaTest = enable;
-        }
-
-        public getAlphaTesting(): boolean {
-            return !!this._alphaTest;
-        }
-
         // Textures
         public wipeCaches(bruteForce?: boolean): void {
             if (this.preventCacheWipeBetweenFrames && !bruteForce) {
@@ -4747,13 +4739,6 @@
             this._currentEffect = null;
         }
 
-        private _activateTextureChannel(channel: number): void {
-            if (this._activeChannel !== channel && channel > -1) {
-                this._gl.activeTexture(this._gl.TEXTURE0 + channel);
-                this._activeChannel = channel;
-            }
-        }
-
         private _moveBoundTextureOnTop(internalTexture: InternalTexture): void {
             let index = this._boundTexturesStack.indexOf(internalTexture);
 
@@ -4763,8 +4748,42 @@
             }
         }
 
+
+        private _getCorrectTextureChannel(channel: number, internalTexture: Nullable<InternalTexture>): number {
+            if (!internalTexture) {
+                return -1;
+            }
+
+            internalTexture._initialSlot = channel;
+
+            if (this.disableTextureBindingOptimization) { // We want texture sampler ID === texture channel
+                if (channel !== internalTexture._designatedSlot) {
+                    this._textureCollisions.addCount(1, false);
+                }
+            } else {
+                if (channel !== internalTexture._designatedSlot) {
+                    if (internalTexture._designatedSlot > -1) { // Texture is already assigned to a slot
+                        return internalTexture._designatedSlot;
+                    } else {
+                        // No slot for this texture, let's pick a new one (if we find a free slot)
+                        if (this._nextFreeTextureSlots.length) {
+                            return this._nextFreeTextureSlots[0];
+                        }
+
+                        // We need to recycle the oldest bound texture, sorry.
+                        this._textureCollisions.addCount(1, false);
+                        return this._removeDesignatedSlot(this._boundTexturesStack[0]);
+                    }
+                }
+            }
+
+            return channel;
+        }
+
+
         private _removeDesignatedSlot(internalTexture: InternalTexture): number {
             let currentSlot = internalTexture._designatedSlot;
+
             internalTexture._designatedSlot = -1;
             let index = this._boundTexturesStack.indexOf(internalTexture);
 
@@ -4779,7 +4798,18 @@
             return currentSlot;
         }
 
-        public _bindTextureDirectly(target: number, texture: Nullable<InternalTexture>, doNotBindUniformToTextureChannel = false): void {
+        private _activateCurrentTexture() {
+            if (this._currentTextureChannel !== this._activeChannel) {
+                this._gl.activeTexture(this._gl.TEXTURE0 + this._activeChannel);
+                this._currentTextureChannel = this._activeChannel;
+            }
+        }
+
+        protected _bindTextureDirectly(target: number, texture: Nullable<InternalTexture>, forTextureDataUpdate = false): void {
+            if (forTextureDataUpdate && texture && texture._designatedSlot > -1) {
+                this._activeChannel = texture._designatedSlot;
+            }
+
             let currentTextureBound = this._boundTexturesCache[this._activeChannel];
             let isTextureForRendering = texture && texture._initialSlot > -1;
 
@@ -4788,26 +4818,28 @@
                     this._removeDesignatedSlot(currentTextureBound);
                 }
 
-                this._gl.bindTexture(target, texture ? texture._webGLTexture : null);
+                this._activateCurrentTexture();
 
-                if (this._activeChannel >= 0) {
-                    this._boundTexturesCache[this._activeChannel] = texture;
+                this._gl.bindTexture(target, texture ? texture._webGLTexture : null);
+                this._boundTexturesCache[this._activeChannel] = texture;
 
-                    if (isTextureForRendering && !this.disableTextureBindingOptimization) {
+                if (texture) {
+                    if (!this.disableTextureBindingOptimization) {
                         let slotIndex = this._nextFreeTextureSlots.indexOf(this._activeChannel);
                         if (slotIndex > -1) {
                             this._nextFreeTextureSlots.splice(slotIndex, 1);
                         }
-                        this._boundTexturesStack.push(texture!);
+                        this._boundTexturesStack.push(texture);
                     }
+
+                    texture._designatedSlot = this._activeChannel;
                 }
+            } else if (forTextureDataUpdate) {
+                this._activateCurrentTexture();
             }
 
-            if (isTextureForRendering && this._activeChannel > -1) {
-                texture!._designatedSlot = this._activeChannel;
-                if (!doNotBindUniformToTextureChannel) {
-                    this._bindSamplerUniformToChannel(texture!._initialSlot, this._activeChannel);
-                }
+            if (isTextureForRendering && !forTextureDataUpdate) {
+                this._bindSamplerUniformToChannel(texture!._initialSlot, this._activeChannel);
             }
         }
 
@@ -4820,7 +4852,7 @@
                 channel = this._getCorrectTextureChannel(channel, texture);
             }
 
-            this._activateTextureChannel(channel);
+            this._activeChannel = channel;
             this._bindTextureDirectly(this._gl.TEXTURE_2D, texture);
         }
 
@@ -4830,7 +4862,7 @@
 
         public unbindAllTextures(): void {
             for (var channel = 0; channel < this._maxSimultaneousTextures; channel++) {
-                this._activateTextureChannel(channel);
+                this._activeChannel = channel;
                 this._bindTextureDirectly(this._gl.TEXTURE_2D, null);
                 this._bindTextureDirectly(this._gl.TEXTURE_CUBE_MAP, null);
                 if (this.webGLVersion > 1) {
@@ -4851,47 +4883,20 @@
             this._setTexture(channel, texture);
         }
 
-        private _getCorrectTextureChannel(channel: number, internalTexture: Nullable<InternalTexture>): number {
-            if (!internalTexture) {
-                return -1;
-            }
-
-            internalTexture._initialSlot = channel;
-
-            if (this.disableTextureBindingOptimization) { // We want texture sampler ID == texture channel
-                if (channel !== internalTexture._designatedSlot) {              
-                    this._textureCollisions.addCount(1, false);
-                }
-            } else {          
-                if (channel !== internalTexture._designatedSlot) {
-                    if (internalTexture._designatedSlot > -1) { // Texture is already assigned to a slot
-                        return internalTexture._designatedSlot;
-                    } else {
-                        // No slot for this texture, let's pick a new one (if we find a free slot)
-                        if (this._nextFreeTextureSlots.length) {
-                            return this._nextFreeTextureSlots[0];
-                        }
-
-                        // We need to recycle the oldest bound texture, sorry.
-                        this._textureCollisions.addCount(1, false);
-                        return this._removeDesignatedSlot(this._boundTexturesStack[0]);
-                    }
-                }
-            }    
-
-            return channel;
-        }
-
         private _bindSamplerUniformToChannel(sourceSlot: number, destination: number) {
             let uniform = this._boundUniforms[sourceSlot];
+            if (uniform._currentState === destination) {
+                return;
+            }
             this._gl.uniform1i(uniform, destination);
+            uniform._currentState = destination;
         }
 
         private _setTexture(channel: number, texture: Nullable<BaseTexture>, isPartOfTextureArray = false): boolean {
             // Not ready?
             if (!texture) {
                 if (this._boundTexturesCache[channel] != null) {
-                    this._activateTextureChannel(channel);
+                    this._activeChannel = channel;
                     this._bindTextureDirectly(this._gl.TEXTURE_2D, null);
                     this._bindTextureDirectly(this._gl.TEXTURE_CUBE_MAP, null);
                     if (this.webGLVersion > 1) {
@@ -4902,10 +4907,8 @@
             }
 
             // Video
-            var alreadyActivated = false;
             if ((<VideoTexture>texture).video) {
-                this._activateTextureChannel(channel);
-                alreadyActivated = true;
+                this._activeChannel = channel;
                 (<VideoTexture>texture).update();
             } else if (texture.delayLoadState === Engine.DELAYLOADSTATE_NOTLOADED) { // Delay loading
                 texture.delayLoad();
@@ -4938,9 +4941,7 @@
                 return false;
             }
 
-            if (!alreadyActivated) {
-                this._activateTextureChannel(channel);
-            }
+            this._activeChannel = channel;
 
             if (internalTexture && internalTexture.is3D) {
                 this._bindTextureDirectly(this._gl.TEXTURE_3D, internalTexture, isPartOfTextureArray);
@@ -5268,7 +5269,7 @@
             var index = Engine.Instances.indexOf(this);
 
             if (index >= 0) {
-                Engine.Instances.splice(index, 1);
+                delete Engine.Instances[index];
             }
 
             this._workingCanvas = null;
@@ -5729,7 +5730,7 @@
             let request = Tools.LoadFile(url, onSuccess, onProgress, database, useArrayBuffer, onError);
             this._activeRequests.push(request);
             request.onCompleteObservable.add(request => {
-                this._activeRequests.splice(this._activeRequests.indexOf(request), 1);
+                delete this._activeRequests[this._activeRequests.indexOf(request)];
             });
             return request;
         }

+ 1 - 1
src/Engine/babylon.nullEngine.ts

@@ -392,7 +392,7 @@
         public updateDynamicVertexBuffer(vertexBuffer: WebGLBuffer, vertices: FloatArray, offset?: number, count?: number): void {
         }
 
-        public _bindTextureDirectly(target: number, texture: InternalTexture): void {
+        protected _bindTextureDirectly(target: number, texture: InternalTexture): void {
             if (this._boundTexturesCache[this._activeChannel] !== texture) {
                 this._boundTexturesCache[this._activeChannel] = texture;
             }

+ 1 - 1
src/Materials/Background/babylon.backgroundMaterial.ts

@@ -699,7 +699,7 @@
             MaterialHelper.PrepareDefinesForMisc(mesh, scene, false, this.pointsCloud, this.fogEnabled, defines);
 
             // Values that need to be evaluated on every frame
-            MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances, false);
+            MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances, this._shouldTurnAlphaTestOn(mesh));
 
             // Attribs
             if (MaterialHelper.PrepareDefinesForAttributes(mesh, defines, false, true, false)) {

+ 1 - 1
src/Materials/PBR/babylon.pbrBaseMaterial.ts

@@ -904,7 +904,7 @@
             MaterialHelper.PrepareDefinesForMisc(mesh, scene, this._useLogarithmicDepth, this.pointsCloud, this.fogEnabled, defines);
 
             // Values that need to be evaluated on every frame
-            MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false, this._forceAlphaTest);
+            MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false, this._shouldTurnAlphaTestOn(mesh) || this._forceAlphaTest);
 
             // Attribs
             if (MaterialHelper.PrepareDefinesForAttributes(mesh, defines, true, true, true, this._transparencyMode !== PBRMaterial.PBRMATERIAL_OPAQUE) && mesh) {

+ 5 - 8
src/Materials/babylon.material.ts

@@ -539,6 +539,10 @@
             }
         }
 
+        protected _shouldTurnAlphaTestOn(mesh: AbstractMesh): boolean {
+            return (!this.needAlphaBlendingForMesh(mesh) && this.needAlphaTesting());
+        }
+
         protected _afterBind(mesh?: Mesh): void {
             this._scene._cachedMaterial = this;
             if (mesh) {
@@ -597,16 +601,14 @@
         /**
          * Force shader compilation including textures ready check
          */
-        public forceCompilation(mesh: AbstractMesh, onCompiled?: (material: Material) => void, options?: Partial<{ alphaTest: Nullable<boolean>, clipPlane: boolean }>): void {
+        public forceCompilation(mesh: AbstractMesh, onCompiled?: (material: Material) => void, options?: Partial<{ clipPlane: boolean }>): void {
             let localOptions = {
-                alphaTest: null,
                 clipPlane: false,
                 ...options
             };
 
             var subMesh = new BaseSubMesh();
             var scene = this.getScene();
-            var engine = scene.getEngine();
 
             var checkReady = () => {
                 if (!this._scene || !this._scene.getEngine()) {
@@ -617,11 +619,8 @@
                     subMesh._materialDefines._renderId = -1;
                 }
 
-                var alphaTestState = engine.getAlphaTesting();
                 var clipPlaneState = scene.clipPlane;
 
-                engine.setAlphaTesting(localOptions.alphaTest || (!this.needAlphaBlendingForMesh(mesh) && this.needAlphaTesting()));
-
                 if (localOptions.clipPlane) {
                     scene.clipPlane = new Plane(0, 0, 0, 1);
                 }
@@ -646,8 +645,6 @@
                     }
                 }
 
-                engine.setAlphaTesting(alphaTestState);
-
                 if (options && options.clipPlane) {
                     scene.clipPlane = clipPlaneState;
                 }

+ 10 - 2
src/Materials/babylon.materialHelper.ts

@@ -41,7 +41,15 @@
             }
         }
 
-        public static PrepareDefinesForFrameBoundValues(scene: Scene, engine: Engine, defines: any, useInstances: boolean, forceAlphaTest = false): void {
+        /**
+         * Helper used to prepare the list of defines for shader compilation
+         * @param scene defines the current scene
+         * @param engine defines the current engine
+         * @param defines specifies the list of active defines
+         * @param useInstances defines if instances have to be turned on
+         * @param alphaTest defines if alpha testing has to be turned on
+         */
+        public static PrepareDefinesForFrameBoundValues(scene: Scene, engine: Engine, defines: any, useInstances: boolean, alphaTest: boolean): void {
             var changed = false;
 
             if (defines["CLIPPLANE"] !== (scene.clipPlane !== undefined && scene.clipPlane !== null)) {
@@ -49,7 +57,7 @@
                 changed = true;
             }
 
-            if (defines["ALPHATEST"] !== (engine.getAlphaTesting() || forceAlphaTest)) {
+            if (defines["ALPHATEST"] !== alphaTest) {
                 defines["ALPHATEST"] = !defines["ALPHATEST"];
                 changed = true;
             }

+ 1 - 1
src/Materials/babylon.shaderMaterial.ts

@@ -247,7 +247,7 @@
             }
 
             // Alpha test
-            if (engine.getAlphaTesting()) {
+            if (mesh && this._shouldTurnAlphaTestOn(mesh)) {
                 defines.push("#define ALPHATEST");
             }
 

+ 1 - 1
src/Materials/babylon.standardMaterial.ts

@@ -745,7 +745,7 @@ module BABYLON {
             MaterialHelper.PrepareDefinesForAttributes(mesh, defines, true, true, true);
 
             // Values that need to be evaluated on every frame
-            MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances);
+            MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances, this._shouldTurnAlphaTestOn(mesh));
 
             // Get correct effect      
             if (defines.isDirty) {

+ 0 - 8
src/Mesh/babylon.mesh.ts

@@ -623,28 +623,20 @@
 
             let mat = this.material || scene.defaultMaterial;
             if (mat) {
-                let currentAlphaTestingState = engine.getAlphaTesting();
-
                 if (mat.storeEffectOnSubMeshes) {
                     for (var subMesh of this.subMeshes) {
                         let effectiveMaterial = subMesh.getMaterial();
                         if (effectiveMaterial) {
-                            engine.setAlphaTesting(effectiveMaterial.needAlphaTesting() && !effectiveMaterial.needAlphaBlendingForMesh(this));
                             if (!effectiveMaterial.isReadyForSubMesh(this, subMesh, hardwareInstancedRendering)) {
-                                engine.setAlphaTesting(currentAlphaTestingState);
                                 return false;
                             }
                         }
                     }
                 } else {
-                    engine.setAlphaTesting(mat.needAlphaTesting() && !mat.needAlphaBlendingForMesh(this));
                     if (!mat.isReady(this, hardwareInstancedRendering)) {
-                        engine.setAlphaTesting(currentAlphaTestingState);
                         return false;
                     }
                 }
-
-                engine.setAlphaTesting(currentAlphaTestingState);
             }
 
             // Shadows

+ 0 - 2
src/PostProcess/babylon.volumetricLightScatteringPostProcess.ts

@@ -358,11 +358,9 @@
                     renderSubMesh(opaqueSubMeshes.data[index]);
                 }
 
-                engine.setAlphaTesting(true);
                 for (index = 0; index < alphaTestSubMeshes.length; index++) {
                     renderSubMesh(alphaTestSubMeshes.data[index]);
                 }
-                engine.setAlphaTesting(false);
 
                 if (transparentSubMeshes.length) {
                     // Sort sub meshes

+ 14 - 20
src/Rendering/babylon.renderingGroup.ts

@@ -6,12 +6,12 @@
         private _alphaTestSubMeshes = new SmartArray<SubMesh>(256);
         private _depthOnlySubMeshes = new SmartArray<SubMesh>(256);
         private _particleSystems = new SmartArray<IParticleSystem>(256);
-        private _spriteManagers = new SmartArray<SpriteManager>(256);        
+        private _spriteManagers = new SmartArray<SpriteManager>(256);
 
         private _opaqueSortCompareFn: Nullable<(a: SubMesh, b: SubMesh) => number>;
         private _alphaTestSortCompareFn: Nullable<(a: SubMesh, b: SubMesh) => number>;
         private _transparentSortCompareFn: (a: SubMesh, b: SubMesh) => number;
-        
+
         private _renderOpaque: (subMeshes: SmartArray<SubMesh>) => void;
         private _renderAlphaTest: (subMeshes: SmartArray<SubMesh>) => void;
         private _renderTransparent: (subMeshes: SmartArray<SubMesh>) => void;
@@ -77,7 +77,7 @@
 
             this.opaqueSortCompareFn = opaqueSortCompareFn;
             this.alphaTestSortCompareFn = alphaTestSortCompareFn;
-            this.transparentSortCompareFn = transparentSortCompareFn;            
+            this.transparentSortCompareFn = transparentSortCompareFn;
         }
 
         /**
@@ -95,13 +95,11 @@
 
             // Depth only
             if (this._depthOnlySubMeshes.length !== 0) {
-                engine.setAlphaTesting(true);
                 engine.setColorWrite(false);
                 this._renderAlphaTest(this._depthOnlySubMeshes);
-                engine.setAlphaTesting(false);
                 engine.setColorWrite(true);
-            }            
-            
+            }
+
             // Opaque
             if (this._opaqueSubMeshes.length !== 0) {
                 this._renderOpaque(this._opaqueSubMeshes);
@@ -109,9 +107,7 @@
 
             // Alpha test
             if (this._alphaTestSubMeshes.length !== 0) {
-                engine.setAlphaTesting(true);
                 this._renderAlphaTest(this._alphaTestSubMeshes);
-                engine.setAlphaTesting(false);
             }
 
             var stencilState = engine.getStencilBuffer();
@@ -121,7 +117,7 @@
             if (renderSprites) {
                 this._renderSprites();
             }
-            
+
             // Particles
             if (renderParticles) {
                 this._renderParticles(activeMeshes);
@@ -205,10 +201,8 @@
                     if (material && material.needDepthPrePass) {
                         let engine = material.getScene().getEngine();
                         engine.setColorWrite(false);
-                        engine.setAlphaTesting(true);
                         engine.setAlphaMode(Engine.ALPHA_DISABLE);
                         subMesh.render(false);
-                        engine.setAlphaTesting(false);
                         engine.setColorWrite(true);
                     }
                 }
@@ -236,7 +230,7 @@
          * @param b The second submesh
          * @returns The result of the comparison
          */
-        public static defaultTransparentSortCompare(a: SubMesh, b:SubMesh) : number {
+        public static defaultTransparentSortCompare(a: SubMesh, b: SubMesh): number {
             // Alpha index first
             if (a._alphaIndex > b._alphaIndex) {
                 return 1;
@@ -257,7 +251,7 @@
          * @param b The second submesh
          * @returns The result of the comparison
          */
-        public static backToFrontSortCompare(a: SubMesh, b:SubMesh) : number {
+        public static backToFrontSortCompare(a: SubMesh, b: SubMesh): number {
             // Then distance to camera
             if (a._distanceToCamera < b._distanceToCamera) {
                 return 1;
@@ -277,7 +271,7 @@
          * @param b The second submesh
          * @returns The result of the comparison
          */
-        public static frontToBackSortCompare(a: SubMesh, b:SubMesh) : number {
+        public static frontToBackSortCompare(a: SubMesh, b: SubMesh): number {
             // Then distance to camera
             if (a._distanceToCamera < b._distanceToCamera) {
                 return -1;
@@ -298,7 +292,7 @@
             this._alphaTestSubMeshes.reset();
             this._depthOnlySubMeshes.reset();
             this._particleSystems.reset();
-            this._spriteManagers.reset();            
+            this._spriteManagers.reset();
             this._edgesRenderers.reset();
         }
 
@@ -308,7 +302,7 @@
             this._alphaTestSubMeshes.dispose();
             this._depthOnlySubMeshes.dispose();
             this._particleSystems.dispose();
-            this._spriteManagers.dispose();                      
+            this._spriteManagers.dispose();
             this._edgesRenderers.dispose();
         }
 
@@ -337,13 +331,13 @@
                 if (material.needDepthPrePass) {
                     this._depthOnlySubMeshes.push(subMesh);
                 }
-                
+
                 this._alphaTestSubMeshes.push(subMesh);
             } else {
                 if (material.needDepthPrePass) {
                     this._depthOnlySubMeshes.push(subMesh);
                 }
-                
+
                 this._opaqueSubMeshes.push(subMesh); // Opaque
             }
 
@@ -381,7 +375,7 @@
                 }
             }
             this._scene.onAfterParticlesRenderingObservable.notifyObservers(this._scene);
-            
+
         }
 
         private _renderSprites(): void {

+ 20 - 0
src/Tools/babylon.tools.ts

@@ -1014,6 +1014,26 @@
             Tools.EncodeScreenshotCanvasData(successCallback, mimeType);
         }
 
+        /**
+         * Generates an image screenshot from the specified camera.
+         *
+         * @param engine The engine to use for rendering
+         * @param camera The camera to use for rendering
+         * @param size This parameter can be set to a single number or to an object with the
+         * following (optional) properties: precision, width, height. If a single number is passed,
+         * it will be used for both width and height. If an object is passed, the screenshot size
+         * will be derived from the parameters. The precision property is a multiplier allowing
+         * rendering at a higher or lower resolution.
+         * @param successCallback The callback receives a single parameter which contains the
+         * screenshot as a string of base64-encoded characters. This string can be assigned to the
+         * src parameter of an <img> to display it.
+         * @param mimeType The MIME type of the screenshot image (default: image/png).
+         * Check your browser for supported MIME types.
+         * @param samples Texture samples (default: 1)
+         * @param antialiasing Whether antialiasing should be turned on or not (default: false)
+         * @param fileName A name for for the downloaded file.
+         * @constructor
+         */
         public static CreateScreenshotUsingRenderTarget(engine: Engine, camera: Camera, size: any, successCallback?: (data: string) => void, mimeType: string = "image/png", samples: number = 1, antialiasing: boolean = false, fileName?: string): void {
             var width: number;
             var height: number;

+ 5 - 1
src/babylon.mixins.ts

@@ -164,4 +164,8 @@ interface EXT_disjoint_timer_query {
     endQueryEXT(target: number): void;
     getQueryObjectEXT(query: WebGLQuery, target: number): any;
     deleteQueryEXT(query: WebGLQuery): void;
-}
+}
+
+interface WebGLUniformLocation {
+    _currentState: any;
+}

+ 8 - 8
tests/validation/validation.js

@@ -210,11 +210,11 @@ function runTest(index, done) {
             currentScene = newScene;
             processCurrentScene(test, resultCanvas, result, renderImage, index, waitRing, done);
         },
-        null,
-        function (loadedScene, msg) {
-            console.error(msg);
-            done(false);
-        });
+            null,
+            function (loadedScene, msg) {
+                console.error(msg);
+                done(false);
+            });
     }
     else if (test.playgroundId) {
         var snippetUrl = "//babylonjs-api2.azurewebsites.net/snippets";
@@ -223,7 +223,7 @@ function runTest(index, done) {
         xmlHttp.onreadystatechange = function () {
             if (xmlHttp.readyState === 4) {
                 try {
-                    request.onreadystatechange = null;
+                    xmlHttp.onreadystatechange = null;
                     var snippet = JSON.parse(xmlHttp.responseText)[0];
                     var code = JSON.parse(snippet.jsonPayload).code.toString();
                     code = code.replace(/\/textures\//g, pgRoot + "/textures/");
@@ -239,7 +239,7 @@ function runTest(index, done) {
                 }
             }
         }
-        xmlHttp.onerror = function() {
+        xmlHttp.onerror = function () {
             console.error("Network error during test load.");
             done(false);
         }
@@ -292,7 +292,7 @@ function runTest(index, done) {
                 }
             }
         };
-        request.onerror = function() {
+        request.onerror = function () {
             console.error("Network error during test load.");
             done(false);
         }