Browse Source

New tool for debugLayer: You can now dump renderTargets to see their content
Complete shadows code rework: New bias property for ShadowGenerator, new orthogonal shadows for directional shadows, automatic projection size for directional lights

David Catuhe 10 years ago
parent
commit
a31312fef3
33 changed files with 1316 additions and 617 deletions
  1. 41 20
      Babylon/Audio/babylon.sound.js
  2. 42 20
      Babylon/Audio/babylon.sound.ts
  3. 14 0
      Babylon/Audio/babylon.soundtrack.js
  4. 16 0
      Babylon/Audio/babylon.soundtrack.ts
  5. 40 5
      Babylon/Debug/babylon.debugLayer.js
  6. 1 1
      Babylon/Debug/babylon.debugLayer.js.map
  7. 41 6
      Babylon/Debug/babylon.debugLayer.ts
  8. 16 5
      Babylon/Lights/Shadows/babylon.shadowGenerator.js
  9. 22 6
      Babylon/Lights/Shadows/babylon.shadowGenerator.ts
  10. 31 0
      Babylon/Lights/babylon.directionalLight.js
  11. 43 0
      Babylon/Lights/babylon.directionalLight.ts
  12. 7 1
      Babylon/Lights/babylon.light.ts
  13. 10 0
      Babylon/Lights/babylon.spotLight.js
  14. 13 0
      Babylon/Lights/babylon.spotLight.ts
  15. 45 28
      Babylon/Loading/Plugins/babylon.babylonFileLoader.js
  16. 46 30
      Babylon/Loading/Plugins/babylon.babylonFileLoader.ts
  17. 5 1
      Babylon/Materials/Textures/babylon.renderTargetTexture.js
  18. 6 1
      Babylon/Materials/Textures/babylon.renderTargetTexture.ts
  19. 2 2
      Babylon/Materials/babylon.standardMaterial.js
  20. 2 2
      Babylon/Materials/babylon.standardMaterial.ts
  21. 6 1
      Babylon/Math/babylon.math.js
  22. 10 2
      Babylon/Math/babylon.math.ts
  23. 24 24
      Babylon/Shaders/default.fragment.fx
  24. 2 2
      Babylon/Shaders/shadowMap.fragment.fx
  25. 2 3
      Babylon/Shaders/shadowMap.vertex.fx
  26. 64 62
      Babylon/Tools/babylon.filesInput.js
  27. 77 71
      Babylon/Tools/babylon.filesInput.ts
  28. 55 48
      Babylon/Tools/babylon.tools.js
  29. 67 60
      Babylon/Tools/babylon.tools.ts
  30. 69 7
      Babylon/babylon.scene.js
  31. 77 8
      Babylon/babylon.scene.ts
  32. 401 182
      babylon.2.1-alpha.debug.js
  33. 19 19
      babylon.2.1-alpha.js

+ 41 - 20
Babylon/Audio/babylon.sound.js

@@ -27,7 +27,8 @@ var BABYLON;
             this._volume = 1;
             this._volume = 1;
             this._isLoaded = false;
             this._isLoaded = false;
             this._isReadyToPlay = false;
             this._isReadyToPlay = false;
-            this._isPlaying = false;
+            this.isPlaying = false;
+            this.isPaused = false;
             this._isDirectional = false;
             this._isDirectional = false;
             // Used if you'd like to create a directional sound.
             // Used if you'd like to create a directional sound.
             // If not set, the sound will be omnidirectional
             // If not set, the sound will be omnidirectional
@@ -100,7 +101,7 @@ var BABYLON;
         }
         }
         Sound.prototype.dispose = function () {
         Sound.prototype.dispose = function () {
             if (BABYLON.Engine.audioEngine.canUseWebAudio && this._isReadyToPlay) {
             if (BABYLON.Engine.audioEngine.canUseWebAudio && this._isReadyToPlay) {
-                if (this._isPlaying) {
+                if (this.isPlaying) {
                     this.stop();
                     this.stop();
                 }
                 }
                 this._isReadyToPlay = false;
                 this._isReadyToPlay = false;
@@ -185,6 +186,17 @@ var BABYLON;
                 this._inputAudioNode = this._soundPanner;
                 this._inputAudioNode = this._soundPanner;
             }
             }
         };
         };
+        Sound.prototype.switchPanningModelToHRTF = function () {
+            this._switchPanningModel("HRTF");
+        };
+        Sound.prototype.switchPanningModelToEqualPower = function () {
+            this._switchPanningModel("equalpower");
+        };
+        Sound.prototype._switchPanningModel = function (newModel) {
+            if (BABYLON.Engine.audioEngine.canUseWebAudio && this.spatialSound) {
+                this._soundPanner.panningModel = newModel;
+            }
+        };
         Sound.prototype.connectToSoundTrackAudioNode = function (soundTrackAudioNode) {
         Sound.prototype.connectToSoundTrackAudioNode = function (soundTrackAudioNode) {
             if (BABYLON.Engine.audioEngine.canUseWebAudio) {
             if (BABYLON.Engine.audioEngine.canUseWebAudio) {
                 this._ouputAudioNode.disconnect();
                 this._ouputAudioNode.disconnect();
@@ -206,20 +218,20 @@ var BABYLON;
             this._coneOuterAngle = coneOuterAngle;
             this._coneOuterAngle = coneOuterAngle;
             this._coneOuterGain = coneOuterGain;
             this._coneOuterGain = coneOuterGain;
             this._isDirectional = true;
             this._isDirectional = true;
-            if (this._isPlaying && this.loop) {
+            if (this.isPlaying && this.loop) {
                 this.stop();
                 this.stop();
                 this.play();
                 this.play();
             }
             }
         };
         };
         Sound.prototype.setPosition = function (newPosition) {
         Sound.prototype.setPosition = function (newPosition) {
             this._position = newPosition;
             this._position = newPosition;
-            if (this._isPlaying && this.spatialSound) {
+            if (this.isPlaying && this.spatialSound) {
                 this._soundPanner.setPosition(this._position.x, this._position.y, this._position.z);
                 this._soundPanner.setPosition(this._position.x, this._position.y, this._position.z);
             }
             }
         };
         };
         Sound.prototype.setLocalDirectionToMesh = function (newLocalDirection) {
         Sound.prototype.setLocalDirectionToMesh = function (newLocalDirection) {
             this._localDirection = newLocalDirection;
             this._localDirection = newLocalDirection;
-            if (this._connectedMesh && this._isPlaying) {
+            if (this._connectedMesh && this.isPlaying) {
                 this._updateDirection();
                 this._updateDirection();
             }
             }
         };
         };
@@ -243,9 +255,10 @@ var BABYLON;
         * @param time (optional) Start the sound after X seconds. Start immediately (0) by default.
         * @param time (optional) Start the sound after X seconds. Start immediately (0) by default.
         */
         */
         Sound.prototype.play = function (time) {
         Sound.prototype.play = function (time) {
-            if (this._isReadyToPlay) {
+            var _this = this;
+            if (this._isReadyToPlay && this._scene.audioEnabled) {
                 try {
                 try {
-                    var startTime = time ? BABYLON.Engine.audioEngine.audioContext.currentTime + time : 0;
+                    var startTime = time ? BABYLON.Engine.audioEngine.audioContext.currentTime + time : BABYLON.Engine.audioEngine.audioContext.currentTime;
                     if (!this._soundSource) {
                     if (!this._soundSource) {
                         if (this.spatialSound) {
                         if (this.spatialSound) {
                             this._soundPanner.setPosition(this._position.x, this._position.y, this._position.z);
                             this._soundPanner.setPosition(this._position.x, this._position.y, this._position.z);
@@ -268,32 +281,40 @@ var BABYLON;
                     this._soundSource.loop = this.loop;
                     this._soundSource.loop = this.loop;
                     this._soundSource.playbackRate.value = this._playbackRate;
                     this._soundSource.playbackRate.value = this._playbackRate;
                     this._startTime = startTime;
                     this._startTime = startTime;
-                    if (this.onended) {
-                        this._soundSource.onended = this.onended;
-                    }
-                    this._soundSource.start(startTime, this._startOffset % this._soundSource.buffer.duration);
-                    this._isPlaying = true;
+                    this._soundSource.onended = function () {
+                        _this._onended();
+                    };
+                    this._soundSource.start(this._startTime, this.isPaused ? this._startOffset % this._soundSource.buffer.duration : 0);
+                    this.isPlaying = true;
+                    this.isPaused = false;
                 }
                 }
                 catch (ex) {
                 catch (ex) {
                     BABYLON.Tools.Error("Error while trying to play audio: " + this.name + ", " + ex.message);
                     BABYLON.Tools.Error("Error while trying to play audio: " + this.name + ", " + ex.message);
                 }
                 }
             }
             }
         };
         };
+        Sound.prototype._onended = function () {
+            this.isPlaying = false;
+            if (this.onended) {
+                this.onended();
+            }
+        };
         /**
         /**
         * Stop the sound
         * Stop the sound
         * @param time (optional) Stop the sound after X seconds. Stop immediately (0) by default.
         * @param time (optional) Stop the sound after X seconds. Stop immediately (0) by default.
         */
         */
         Sound.prototype.stop = function (time) {
         Sound.prototype.stop = function (time) {
-            if (this._isPlaying) {
-                var stopTime = time ? BABYLON.Engine.audioEngine.audioContext.currentTime + time : 0;
+            if (this.isPlaying) {
+                var stopTime = time ? BABYLON.Engine.audioEngine.audioContext.currentTime + time : BABYLON.Engine.audioEngine.audioContext.currentTime;
                 this._soundSource.stop(stopTime);
                 this._soundSource.stop(stopTime);
-                this._isPlaying = false;
+                this.isPlaying = false;
             }
             }
         };
         };
         Sound.prototype.pause = function () {
         Sound.prototype.pause = function () {
-            if (this._isPlaying) {
-                this._soundSource.stop(0);
+            if (this.isPlaying) {
+                this.stop(0);
                 this._startOffset += BABYLON.Engine.audioEngine.audioContext.currentTime - this._startTime;
                 this._startOffset += BABYLON.Engine.audioEngine.audioContext.currentTime - this._startTime;
+                this.isPaused = true;
             }
             }
         };
         };
         Sound.prototype.setVolume = function (newVolume, time) {
         Sound.prototype.setVolume = function (newVolume, time) {
@@ -310,7 +331,7 @@ var BABYLON;
         };
         };
         Sound.prototype.setPlaybackRate = function (newPlaybackRate) {
         Sound.prototype.setPlaybackRate = function (newPlaybackRate) {
             this._playbackRate = newPlaybackRate;
             this._playbackRate = newPlaybackRate;
-            if (this._isPlaying) {
+            if (this.isPlaying) {
                 this._soundSource.playbackRate.value = this._playbackRate;
                 this._soundSource.playbackRate.value = this._playbackRate;
             }
             }
         };
         };
@@ -323,7 +344,7 @@ var BABYLON;
             if (!this.spatialSound) {
             if (!this.spatialSound) {
                 this._createSpatialParameters();
                 this._createSpatialParameters();
                 this.spatialSound = true;
                 this.spatialSound = true;
-                if (this._isPlaying && this.loop) {
+                if (this.isPlaying && this.loop) {
                     this.stop();
                     this.stop();
                     this.play();
                     this.play();
                 }
                 }
@@ -334,7 +355,7 @@ var BABYLON;
         };
         };
         Sound.prototype._onRegisterAfterWorldMatrixUpdate = function (connectedMesh) {
         Sound.prototype._onRegisterAfterWorldMatrixUpdate = function (connectedMesh) {
             this.setPosition(connectedMesh.getBoundingInfo().boundingSphere.centerWorld);
             this.setPosition(connectedMesh.getBoundingInfo().boundingSphere.centerWorld);
-            if (this._isDirectional && this._isPlaying) {
+            if (this._isDirectional && this.isPlaying) {
                 this._updateDirection();
                 this._updateDirection();
             }
             }
         };
         };

+ 42 - 20
Babylon/Audio/babylon.sound.ts

@@ -20,7 +20,8 @@
         private _volume: number = 1;
         private _volume: number = 1;
         private _isLoaded: boolean = false;
         private _isLoaded: boolean = false;
         private _isReadyToPlay: boolean = false;
         private _isReadyToPlay: boolean = false;
-        private _isPlaying: boolean = false;
+        public isPlaying: boolean = false;
+        public isPaused: boolean = false;
         private _isDirectional: boolean = false;
         private _isDirectional: boolean = false;
         private _readyToPlayCallback: () => any;
         private _readyToPlayCallback: () => any;
         private _audioBuffer: AudioBuffer;
         private _audioBuffer: AudioBuffer;
@@ -113,7 +114,7 @@
 
 
         public dispose() {
         public dispose() {
             if (Engine.audioEngine.canUseWebAudio && this._isReadyToPlay) {
             if (Engine.audioEngine.canUseWebAudio && this._isReadyToPlay) {
-                if (this._isPlaying) {
+                if (this.isPlaying) {
                     this.stop();
                     this.stop();
                 }
                 }
                 this._isReadyToPlay = false;
                 this._isReadyToPlay = false;
@@ -198,6 +199,20 @@
             }
             }
         }
         }
 
 
+        public switchPanningModelToHRTF() {
+            this._switchPanningModel("HRTF");    
+        }
+
+        public switchPanningModelToEqualPower() {
+            this._switchPanningModel("equalpower");
+        }
+
+        private _switchPanningModel(newModel: string) {
+            if (Engine.audioEngine.canUseWebAudio && this.spatialSound) {
+                this._soundPanner.panningModel = newModel;
+            }
+        }
+
         public connectToSoundTrackAudioNode(soundTrackAudioNode: AudioNode) {
         public connectToSoundTrackAudioNode(soundTrackAudioNode: AudioNode) {
             if (Engine.audioEngine.canUseWebAudio) {
             if (Engine.audioEngine.canUseWebAudio) {
                 this._ouputAudioNode.disconnect();
                 this._ouputAudioNode.disconnect();
@@ -221,7 +236,7 @@
             this._coneOuterGain = coneOuterGain;
             this._coneOuterGain = coneOuterGain;
             this._isDirectional = true;
             this._isDirectional = true;
 
 
-            if (this._isPlaying && this.loop) {
+            if (this.isPlaying && this.loop) {
                 this.stop();
                 this.stop();
                 this.play();
                 this.play();
             }
             }
@@ -230,7 +245,7 @@
         public setPosition(newPosition: Vector3) {
         public setPosition(newPosition: Vector3) {
             this._position = newPosition;
             this._position = newPosition;
 
 
-            if (this._isPlaying && this.spatialSound) {
+            if (this.isPlaying && this.spatialSound) {
                 this._soundPanner.setPosition(this._position.x, this._position.y, this._position.z);
                 this._soundPanner.setPosition(this._position.x, this._position.y, this._position.z);
             }
             }
         }
         }
@@ -238,7 +253,7 @@
         public setLocalDirectionToMesh(newLocalDirection: Vector3) {
         public setLocalDirectionToMesh(newLocalDirection: Vector3) {
             this._localDirection = newLocalDirection;
             this._localDirection = newLocalDirection;
 
 
-            if (this._connectedMesh && this._isPlaying) {
+            if (this._connectedMesh && this.isPlaying) {
                 this._updateDirection();
                 this._updateDirection();
             }
             }
         }
         }
@@ -266,9 +281,9 @@
         * @param time (optional) Start the sound after X seconds. Start immediately (0) by default.
         * @param time (optional) Start the sound after X seconds. Start immediately (0) by default.
         */
         */
         public play(time?: number) {
         public play(time?: number) {
-            if (this._isReadyToPlay) {
+            if (this._isReadyToPlay && this._scene.audioEnabled) {
                 try {
                 try {
-                    var startTime = time ? Engine.audioEngine.audioContext.currentTime + time : 0;
+                    var startTime = time ? Engine.audioEngine.audioContext.currentTime + time : Engine.audioEngine.audioContext.currentTime;
                     if (!this._soundSource) {
                     if (!this._soundSource) {
                         if (this.spatialSound) {
                         if (this.spatialSound) {
                             this._soundPanner.setPosition(this._position.x, this._position.y, this._position.z);
                             this._soundPanner.setPosition(this._position.x, this._position.y, this._position.z);
@@ -291,11 +306,10 @@
                     this._soundSource.loop = this.loop;
                     this._soundSource.loop = this.loop;
                     this._soundSource.playbackRate.value = this._playbackRate;
                     this._soundSource.playbackRate.value = this._playbackRate;
                     this._startTime = startTime;
                     this._startTime = startTime;
-                    if (this.onended) {
-                        this._soundSource.onended = this.onended;
-                    }
-                    this._soundSource.start(startTime, this._startOffset % this._soundSource.buffer.duration);
-                    this._isPlaying = true;
+                    this._soundSource.onended = () => { this._onended(); };
+                    this._soundSource.start(this._startTime, this.isPaused ? this._startOffset % this._soundSource.buffer.duration : 0);
+                    this.isPlaying = true;
+                    this.isPaused = false;
                 }
                 }
                 catch (ex) {
                 catch (ex) {
                     Tools.Error("Error while trying to play audio: " + this.name + ", " + ex.message);
                     Tools.Error("Error while trying to play audio: " + this.name + ", " + ex.message);
@@ -303,22 +317,30 @@
             }
             }
         }
         }
 
 
+        private _onended() {
+            this.isPlaying = false;
+            if (this.onended) {
+                this.onended();
+            }
+        }
+
         /**
         /**
         * Stop the sound
         * Stop the sound
         * @param time (optional) Stop the sound after X seconds. Stop immediately (0) by default.
         * @param time (optional) Stop the sound after X seconds. Stop immediately (0) by default.
         */
         */
         public stop(time?: number) {
         public stop(time?: number) {
-            if (this._isPlaying) {
-                var stopTime = time ? Engine.audioEngine.audioContext.currentTime + time : 0;
+            if (this.isPlaying) {
+                var stopTime = time ? Engine.audioEngine.audioContext.currentTime + time : Engine.audioEngine.audioContext.currentTime;
                 this._soundSource.stop(stopTime);
                 this._soundSource.stop(stopTime);
-                this._isPlaying = false;
+                this.isPlaying = false;
             }
             }
         }
         }
 
 
         public pause() {
         public pause() {
-            if (this._isPlaying) {
-                this._soundSource.stop(0);
+            if (this.isPlaying) {
+                this.stop(0);
                 this._startOffset += Engine.audioEngine.audioContext.currentTime - this._startTime;
                 this._startOffset += Engine.audioEngine.audioContext.currentTime - this._startTime;
+                this.isPaused = true;
             }
             }
         }
         }
 
 
@@ -337,7 +359,7 @@
 
 
         public setPlaybackRate(newPlaybackRate: number) {
         public setPlaybackRate(newPlaybackRate: number) {
             this._playbackRate = newPlaybackRate;
             this._playbackRate = newPlaybackRate;
-            if (this._isPlaying) {
+            if (this.isPlaying) {
                 this._soundSource.playbackRate.value = this._playbackRate;
                 this._soundSource.playbackRate.value = this._playbackRate;
             }
             }
         }
         }
@@ -351,7 +373,7 @@
             if (!this.spatialSound) {
             if (!this.spatialSound) {
                 this._createSpatialParameters();
                 this._createSpatialParameters();
                 this.spatialSound = true;
                 this.spatialSound = true;
-                if (this._isPlaying && this.loop) {
+                if (this.isPlaying && this.loop) {
                     this.stop();
                     this.stop();
                     this.play();
                     this.play();
                 }
                 }
@@ -363,7 +385,7 @@
 
 
         private _onRegisterAfterWorldMatrixUpdate(connectedMesh: AbstractMesh) {
         private _onRegisterAfterWorldMatrixUpdate(connectedMesh: AbstractMesh) {
             this.setPosition(connectedMesh.getBoundingInfo().boundingSphere.centerWorld);
             this.setPosition(connectedMesh.getBoundingInfo().boundingSphere.centerWorld);
-            if (this._isDirectional && this._isPlaying) {
+            if (this._isDirectional && this.isPlaying) {
                 this._updateDirection();
                 this._updateDirection();
             }
             }
         }
         }

+ 14 - 0
Babylon/Audio/babylon.soundtrack.js

@@ -62,6 +62,20 @@ var BABYLON;
                 this._trackGain.gain.value = newVolume;
                 this._trackGain.gain.value = newVolume;
             }
             }
         };
         };
+        SoundTrack.prototype.switchPanningModelToHRTF = function () {
+            if (BABYLON.Engine.audioEngine.canUseWebAudio) {
+                for (var i = 0; i < this.soundCollection.length; i++) {
+                    this.soundCollection[i].switchPanningModelToHRTF();
+                }
+            }
+        };
+        SoundTrack.prototype.switchPanningModelToEqualPower = function () {
+            if (BABYLON.Engine.audioEngine.canUseWebAudio) {
+                for (var i = 0; i < this.soundCollection.length; i++) {
+                    this.soundCollection[i].switchPanningModelToEqualPower();
+                }
+            }
+        };
         SoundTrack.prototype.connectToAnalyser = function (analyser) {
         SoundTrack.prototype.connectToAnalyser = function (analyser) {
             if (this._connectedAnalyser) {
             if (this._connectedAnalyser) {
                 this._connectedAnalyser.stopDebugCanvas();
                 this._connectedAnalyser.stopDebugCanvas();

+ 16 - 0
Babylon/Audio/babylon.soundtrack.ts

@@ -71,6 +71,22 @@
             }
             }
         }
         }
 
 
+        public switchPanningModelToHRTF() {
+            if (Engine.audioEngine.canUseWebAudio) {
+                for (var i = 0; i < this.soundCollection.length; i++) {
+                    this.soundCollection[i].switchPanningModelToHRTF();
+                }
+            }
+        }
+
+        public switchPanningModelToEqualPower() {
+            if (Engine.audioEngine.canUseWebAudio) {
+                for (var i = 0; i < this.soundCollection.length; i++) {
+                    this.soundCollection[i].switchPanningModelToEqualPower();
+                }
+            }
+        }
+
         public connectToAnalyser(analyser: Analyser) {
         public connectToAnalyser(analyser: Analyser) {
             if (this._connectedAnalyser) {
             if (this._connectedAnalyser) {
                 this._connectedAnalyser.stopDebugCanvas();
                 this._connectedAnalyser.stopDebugCanvas();

+ 40 - 5
Babylon/Debug/babylon.debugLayer.js

@@ -336,17 +336,29 @@ var BABYLON;
         DebugLayer.prototype._generateCheckBox = function (root, title, initialState, task, tag) {
         DebugLayer.prototype._generateCheckBox = function (root, title, initialState, task, tag) {
             if (tag === void 0) { tag = null; }
             if (tag === void 0) { tag = null; }
             var label = document.createElement("label");
             var label = document.createElement("label");
-            var boundingBoxesCheckbox = document.createElement("input");
-            boundingBoxesCheckbox.type = "checkbox";
-            boundingBoxesCheckbox.checked = initialState;
-            boundingBoxesCheckbox.addEventListener("change", function (evt) {
+            var checkBox = document.createElement("input");
+            checkBox.type = "checkbox";
+            checkBox.checked = initialState;
+            checkBox.addEventListener("change", function (evt) {
                 task(evt.target, tag);
                 task(evt.target, tag);
             });
             });
-            label.appendChild(boundingBoxesCheckbox);
+            label.appendChild(checkBox);
             label.appendChild(document.createTextNode(title));
             label.appendChild(document.createTextNode(title));
             root.appendChild(label);
             root.appendChild(label);
             root.appendChild(document.createElement("br"));
             root.appendChild(document.createElement("br"));
         };
         };
+        DebugLayer.prototype._generateButton = function (root, title, task, tag) {
+            if (tag === void 0) { tag = null; }
+            var button = document.createElement("button");
+            button.innerHTML = title;
+            button.style.height = "20px";
+            button.style.color = "#222222";
+            button.addEventListener("click", function (evt) {
+                task(evt.target, tag);
+            });
+            root.appendChild(button);
+            root.appendChild(document.createElement("br"));
+        };
         DebugLayer.prototype._generateRadio = function (root, title, name, initialState, task, tag) {
         DebugLayer.prototype._generateRadio = function (root, title, name, initialState, task, tag) {
             if (tag === void 0) { tag = null; }
             if (tag === void 0) { tag = null; }
             var label = document.createElement("label");
             var label = document.createElement("label");
@@ -561,6 +573,29 @@ var BABYLON;
                 this._generateCheckBox(this._optionsSubsetDiv, "Textures", this._scene.texturesEnabled, function (element) {
                 this._generateCheckBox(this._optionsSubsetDiv, "Textures", this._scene.texturesEnabled, function (element) {
                     _this._scene.texturesEnabled = element.checked;
                     _this._scene.texturesEnabled = element.checked;
                 });
                 });
+                if (BABYLON.Engine.audioEngine.canUseWebAudio) {
+                    this._optionsSubsetDiv.appendChild(document.createElement("br"));
+                    this._generateTexBox(this._optionsSubsetDiv, "<b>Audio:</b>", this.accentColor);
+                    this._generateRadio(this._optionsSubsetDiv, "Headphones", "panningModel", true, function (element) {
+                        if (element.checked) {
+                            _this._scene.switchAudioModeForHeadphones();
+                        }
+                    });
+                    this._generateRadio(this._optionsSubsetDiv, "Normal Speakers", "panningModel", false, function (element) {
+                        if (element.checked) {
+                            _this._scene.switchAudioModeForNormalSpeakers();
+                        }
+                    });
+                    this._generateCheckBox(this._optionsSubsetDiv, "Disable audio", !this._scene.audioEnabled, function (element) {
+                        _this._scene.audioEnabled = !element.checked;
+                    });
+                }
+                this._optionsSubsetDiv.appendChild(document.createElement("br"));
+                this._generateTexBox(this._optionsSubsetDiv, "<b>Tools:</b>", this.accentColor);
+                this._generateButton(this._optionsSubsetDiv, "Dump rendertargets", function (element) {
+                    _this._scene.dumpNextRenderTargets = true;
+                });
+                this._optionsSubsetDiv.appendChild(document.createElement("br"));
                 this._globalDiv.appendChild(this._statsDiv);
                 this._globalDiv.appendChild(this._statsDiv);
                 this._globalDiv.appendChild(this._logDiv);
                 this._globalDiv.appendChild(this._logDiv);
                 this._globalDiv.appendChild(this._optionsDiv);
                 this._globalDiv.appendChild(this._optionsDiv);

File diff suppressed because it is too large
+ 1 - 1
Babylon/Debug/babylon.debugLayer.js.map


+ 41 - 6
Babylon/Debug/babylon.debugLayer.ts

@@ -460,20 +460,34 @@
         private _generateCheckBox(root: HTMLDivElement, title: string, initialState: boolean, task: (element, tag) => void, tag: any = null): void {
         private _generateCheckBox(root: HTMLDivElement, title: string, initialState: boolean, task: (element, tag) => void, tag: any = null): void {
             var label = document.createElement("label");
             var label = document.createElement("label");
 
 
-            var boundingBoxesCheckbox = document.createElement("input");
-            boundingBoxesCheckbox.type = "checkbox";
-            boundingBoxesCheckbox.checked = initialState;
+            var checkBox = document.createElement("input");
+            checkBox.type = "checkbox";
+            checkBox.checked = initialState;
 
 
-            boundingBoxesCheckbox.addEventListener("change", (evt: Event) => {
+            checkBox.addEventListener("change", (evt: Event) => {
                 task(evt.target, tag);
                 task(evt.target, tag);
             });
             });
 
 
-            label.appendChild(boundingBoxesCheckbox);
+            label.appendChild(checkBox);
             label.appendChild(document.createTextNode(title));
             label.appendChild(document.createTextNode(title));
             root.appendChild(label);
             root.appendChild(label);
             root.appendChild(document.createElement("br"));
             root.appendChild(document.createElement("br"));
         }
         }
 
 
+        private _generateButton(root: HTMLDivElement, title: string, task: (element, tag) => void, tag: any = null): void {
+            var button = document.createElement("button");
+            button.innerHTML = title;
+            button.style.height = "20px";
+            button.style.color = "#222222";
+
+            button.addEventListener("click",(evt: Event) => {
+                task(evt.target, tag);
+            });
+
+            root.appendChild(button);
+            root.appendChild(document.createElement("br"));
+        }
+
         private _generateRadio(root: HTMLDivElement, title: string, name: string, initialState: boolean, task: (element, tag) => void, tag: any = null): void {
         private _generateRadio(root: HTMLDivElement, title: string, name: string, initialState: boolean, task: (element, tag) => void, tag: any = null): void {
             var label = document.createElement("label");
             var label = document.createElement("label");
 
 
@@ -650,7 +664,28 @@
                 this._generateCheckBox(this._optionsSubsetDiv, "Skeletons", this._scene.skeletonsEnabled, (element) => { this._scene.skeletonsEnabled = element.checked });
                 this._generateCheckBox(this._optionsSubsetDiv, "Skeletons", this._scene.skeletonsEnabled, (element) => { this._scene.skeletonsEnabled = element.checked });
                 this._generateCheckBox(this._optionsSubsetDiv, "Sprites", this._scene.spritesEnabled, (element) => { this._scene.spritesEnabled = element.checked });
                 this._generateCheckBox(this._optionsSubsetDiv, "Sprites", this._scene.spritesEnabled, (element) => { this._scene.spritesEnabled = element.checked });
                 this._generateCheckBox(this._optionsSubsetDiv, "Textures", this._scene.texturesEnabled, (element) => { this._scene.texturesEnabled = element.checked });
                 this._generateCheckBox(this._optionsSubsetDiv, "Textures", this._scene.texturesEnabled, (element) => { this._scene.texturesEnabled = element.checked });
-
+                if (Engine.audioEngine.canUseWebAudio) {
+                    this._optionsSubsetDiv.appendChild(document.createElement("br"));
+                    this._generateTexBox(this._optionsSubsetDiv, "<b>Audio:</b>", this.accentColor);
+                    this._generateRadio(this._optionsSubsetDiv, "Headphones", "panningModel", true, (element) => {
+                        if (element.checked) {
+                            this._scene.switchAudioModeForHeadphones();
+                        }
+                    });
+                    this._generateRadio(this._optionsSubsetDiv, "Normal Speakers", "panningModel", false, (element) => {
+                        if (element.checked) {
+                            this._scene.switchAudioModeForNormalSpeakers();
+                        }
+                    });
+                    this._generateCheckBox(this._optionsSubsetDiv, "Disable audio", !this._scene.audioEnabled, (element) => {
+                        this._scene.audioEnabled = !element.checked;
+                    });
+                }
+                this._optionsSubsetDiv.appendChild(document.createElement("br"));
+                this._generateTexBox(this._optionsSubsetDiv, "<b>Tools:</b>", this.accentColor);
+                this._generateButton(this._optionsSubsetDiv, "Dump rendertargets",(element) => { this._scene.dumpNextRenderTargets = true; });
+                this._optionsSubsetDiv.appendChild(document.createElement("br"));
+  
                 this._globalDiv.appendChild(this._statsDiv);
                 this._globalDiv.appendChild(this._statsDiv);
                 this._globalDiv.appendChild(this._logDiv);
                 this._globalDiv.appendChild(this._logDiv);
                 this._globalDiv.appendChild(this._optionsDiv);
                 this._globalDiv.appendChild(this._optionsDiv);

+ 16 - 5
Babylon/Lights/Shadows/babylon.shadowGenerator.js

@@ -6,6 +6,7 @@ var BABYLON;
             // Members
             // Members
             this.filter = ShadowGenerator.FILTER_NONE;
             this.filter = ShadowGenerator.FILTER_NONE;
             this._darkness = 0;
             this._darkness = 0;
+            this._bias = 0.0001;
             this._transparencyShadow = false;
             this._transparencyShadow = false;
             this._viewMatrix = BABYLON.Matrix.Zero();
             this._viewMatrix = BABYLON.Matrix.Zero();
             this._projectionMatrix = BABYLON.Matrix.Zero();
             this._projectionMatrix = BABYLON.Matrix.Zero();
@@ -94,7 +95,7 @@ var BABYLON;
         });
         });
         Object.defineProperty(ShadowGenerator.prototype, "useVarianceShadowMap", {
         Object.defineProperty(ShadowGenerator.prototype, "useVarianceShadowMap", {
             get: function () {
             get: function () {
-                return this.filter === ShadowGenerator.FILTER_VARIANCESHADOWMAP;
+                return this.filter === ShadowGenerator.FILTER_VARIANCESHADOWMAP && this._light.supportsVSM();
             },
             },
             set: function (value) {
             set: function (value) {
                 this.filter = (value ? ShadowGenerator.FILTER_VARIANCESHADOWMAP : ShadowGenerator.FILTER_NONE);
                 this.filter = (value ? ShadowGenerator.FILTER_VARIANCESHADOWMAP : ShadowGenerator.FILTER_NONE);
@@ -104,7 +105,7 @@ var BABYLON;
         });
         });
         Object.defineProperty(ShadowGenerator.prototype, "usePoissonSampling", {
         Object.defineProperty(ShadowGenerator.prototype, "usePoissonSampling", {
             get: function () {
             get: function () {
-                return this.filter === ShadowGenerator.FILTER_POISSONSAMPLING;
+                return this.filter === ShadowGenerator.FILTER_POISSONSAMPLING || (this.filter === ShadowGenerator.FILTER_VARIANCESHADOWMAP && !this._light.supportsVSM());
             },
             },
             set: function (value) {
             set: function (value) {
                 this.filter = (value ? ShadowGenerator.FILTER_POISSONSAMPLING : ShadowGenerator.FILTER_NONE);
                 this.filter = (value ? ShadowGenerator.FILTER_POISSONSAMPLING : ShadowGenerator.FILTER_NONE);
@@ -163,17 +164,21 @@ var BABYLON;
         };
         };
         // Methods
         // Methods
         ShadowGenerator.prototype.getTransformMatrix = function () {
         ShadowGenerator.prototype.getTransformMatrix = function () {
+            var scene = this._scene;
+            if (this._currentRenderID === scene.getRenderId()) {
+                return this._transformMatrix;
+            }
+            this._currentRenderID = scene.getRenderId();
             var lightPosition = this._light.position;
             var lightPosition = this._light.position;
             var lightDirection = this._light.direction;
             var lightDirection = this._light.direction;
             if (this._light.computeTransformedPosition()) {
             if (this._light.computeTransformedPosition()) {
                 lightPosition = this._light.transformedPosition;
                 lightPosition = this._light.transformedPosition;
             }
             }
-            if (!this._cachedPosition || !this._cachedDirection || !lightPosition.equals(this._cachedPosition) || !lightDirection.equals(this._cachedDirection)) {
+            if (this._light.needRefreshPerFrame() || !this._cachedPosition || !this._cachedDirection || !lightPosition.equals(this._cachedPosition) || !lightDirection.equals(this._cachedDirection)) {
                 this._cachedPosition = lightPosition.clone();
                 this._cachedPosition = lightPosition.clone();
                 this._cachedDirection = lightDirection.clone();
                 this._cachedDirection = lightDirection.clone();
-                var activeCamera = this._scene.activeCamera;
                 BABYLON.Matrix.LookAtLHToRef(lightPosition, this._light.position.add(lightDirection), BABYLON.Vector3.Up(), this._viewMatrix);
                 BABYLON.Matrix.LookAtLHToRef(lightPosition, this._light.position.add(lightDirection), BABYLON.Vector3.Up(), this._viewMatrix);
-                BABYLON.Matrix.PerspectiveFovLHToRef(Math.PI / 2.0, 1.0, activeCamera.minZ, activeCamera.maxZ, this._projectionMatrix);
+                this._light.setShadowProjectionMatrix(this._projectionMatrix, this._viewMatrix, this.getShadowMap().renderList);
                 this._viewMatrix.multiplyToRef(this._projectionMatrix, this._transformMatrix);
                 this._viewMatrix.multiplyToRef(this._projectionMatrix, this._transformMatrix);
             }
             }
             return this._transformMatrix;
             return this._transformMatrix;
@@ -189,6 +194,12 @@ var BABYLON;
             else
             else
                 this._darkness = darkness;
                 this._darkness = darkness;
         };
         };
+        ShadowGenerator.prototype.getBias = function () {
+            return this._bias;
+        };
+        ShadowGenerator.prototype.setBias = function (bias) {
+            this._bias = bias;
+        };
         ShadowGenerator.prototype.setTransparencyShadow = function (hasShadow) {
         ShadowGenerator.prototype.setTransparencyShadow = function (hasShadow) {
             this._transparencyShadow = hasShadow;
             this._transparencyShadow = hasShadow;
         };
         };

+ 22 - 6
Babylon/Lights/Shadows/babylon.shadowGenerator.ts

@@ -21,14 +21,14 @@
         public filter = ShadowGenerator.FILTER_NONE;
         public filter = ShadowGenerator.FILTER_NONE;
 
 
         public get useVarianceShadowMap(): boolean {
         public get useVarianceShadowMap(): boolean {
-            return this.filter === ShadowGenerator.FILTER_VARIANCESHADOWMAP;
+            return this.filter === ShadowGenerator.FILTER_VARIANCESHADOWMAP && this._light.supportsVSM();
         }
         }
         public set useVarianceShadowMap(value: boolean) {
         public set useVarianceShadowMap(value: boolean) {
             this.filter = (value ? ShadowGenerator.FILTER_VARIANCESHADOWMAP : ShadowGenerator.FILTER_NONE);
             this.filter = (value ? ShadowGenerator.FILTER_VARIANCESHADOWMAP : ShadowGenerator.FILTER_NONE);
         }
         }
 
 
         public get usePoissonSampling(): boolean {
         public get usePoissonSampling(): boolean {
-            return this.filter === ShadowGenerator.FILTER_POISSONSAMPLING;
+            return this.filter === ShadowGenerator.FILTER_POISSONSAMPLING || (this.filter === ShadowGenerator.FILTER_VARIANCESHADOWMAP && !this._light.supportsVSM());
         }
         }
         public set usePoissonSampling(value: boolean) {
         public set usePoissonSampling(value: boolean) {
             this.filter = (value ? ShadowGenerator.FILTER_POISSONSAMPLING : ShadowGenerator.FILTER_NONE);
             this.filter = (value ? ShadowGenerator.FILTER_POISSONSAMPLING : ShadowGenerator.FILTER_NONE);
@@ -38,6 +38,7 @@
         private _scene: Scene;
         private _scene: Scene;
         private _shadowMap: RenderTargetTexture;
         private _shadowMap: RenderTargetTexture;
         private _darkness = 0;
         private _darkness = 0;
+        private _bias = 0.0001;
         private _transparencyShadow = false;
         private _transparencyShadow = false;
         private _effect: Effect;
         private _effect: Effect;
 
 
@@ -48,6 +49,7 @@
         private _cachedPosition: Vector3;
         private _cachedPosition: Vector3;
         private _cachedDirection: Vector3;
         private _cachedDirection: Vector3;
         private _cachedDefines: string;
         private _cachedDefines: string;
+        private _currentRenderID: number;
 
 
         constructor(mapSize: number, light: IShadowLight) {
         constructor(mapSize: number, light: IShadowLight) {
             this._light = light;
             this._light = light;
@@ -192,6 +194,13 @@
 
 
         // Methods
         // Methods
         public getTransformMatrix(): Matrix {
         public getTransformMatrix(): Matrix {
+            var scene = this._scene;
+            if (this._currentRenderID === scene.getRenderId()) {
+                return this._transformMatrix;
+            }
+
+            this._currentRenderID = scene.getRenderId();
+
             var lightPosition = this._light.position;
             var lightPosition = this._light.position;
             var lightDirection = this._light.direction;
             var lightDirection = this._light.direction;
 
 
@@ -199,15 +208,14 @@
                 lightPosition = this._light.transformedPosition;
                 lightPosition = this._light.transformedPosition;
             }
             }
 
 
-            if (!this._cachedPosition || !this._cachedDirection || !lightPosition.equals(this._cachedPosition) || !lightDirection.equals(this._cachedDirection)) {
+            if (this._light.needRefreshPerFrame() || !this._cachedPosition || !this._cachedDirection || !lightPosition.equals(this._cachedPosition) || !lightDirection.equals(this._cachedDirection)) {
 
 
                 this._cachedPosition = lightPosition.clone();
                 this._cachedPosition = lightPosition.clone();
                 this._cachedDirection = lightDirection.clone();
                 this._cachedDirection = lightDirection.clone();
 
 
-                var activeCamera = this._scene.activeCamera;
-
                 Matrix.LookAtLHToRef(lightPosition, this._light.position.add(lightDirection), Vector3.Up(), this._viewMatrix);
                 Matrix.LookAtLHToRef(lightPosition, this._light.position.add(lightDirection), Vector3.Up(), this._viewMatrix);
-                Matrix.PerspectiveFovLHToRef(Math.PI / 2.0, 1.0, activeCamera.minZ, activeCamera.maxZ, this._projectionMatrix);
+
+                this._light.setShadowProjectionMatrix(this._projectionMatrix, this._viewMatrix, this.getShadowMap().renderList);
 
 
                 this._viewMatrix.multiplyToRef(this._projectionMatrix, this._transformMatrix);
                 this._viewMatrix.multiplyToRef(this._projectionMatrix, this._transformMatrix);
             }
             }
@@ -228,6 +236,14 @@
                 this._darkness = darkness;
                 this._darkness = darkness;
         }
         }
 
 
+        public getBias(): number {
+            return this._bias;
+        }
+
+        public setBias(bias: number): void {
+            this._bias = bias;
+        }
+
         public setTransparencyShadow(hasShadow: boolean): void {
         public setTransparencyShadow(hasShadow: boolean): void {
             this._transparencyShadow = hasShadow;
             this._transparencyShadow = hasShadow;
         }
         }

+ 31 - 0
Babylon/Lights/babylon.directionalLight.js

@@ -20,6 +20,37 @@ var BABYLON;
             this.direction = BABYLON.Vector3.Normalize(target.subtract(this.position));
             this.direction = BABYLON.Vector3.Normalize(target.subtract(this.position));
             return this.direction;
             return this.direction;
         };
         };
+        DirectionalLight.prototype.setShadowProjectionMatrix = function (matrix, viewMatrix, renderList) {
+            var orthoLeft = Number.MAX_VALUE;
+            var orthoRight = Number.MIN_VALUE;
+            var orthoTop = Number.MIN_VALUE;
+            var orthoBottom = Number.MAX_VALUE;
+            var tempVector3 = BABYLON.Vector3.Zero();
+            var activeCamera = this.getScene().activeCamera;
+            for (var meshIndex = 0; meshIndex < renderList.length; meshIndex++) {
+                var boundingBox = renderList[meshIndex].getBoundingInfo().boundingBox;
+                for (var index = 0; index < boundingBox.vectorsWorld.length; index++) {
+                    BABYLON.Vector3.TransformCoordinatesToRef(boundingBox.vectorsWorld[index], viewMatrix, tempVector3);
+                    if (tempVector3.x < orthoLeft)
+                        orthoLeft = tempVector3.x;
+                    if (tempVector3.y < orthoBottom)
+                        orthoBottom = tempVector3.y;
+                    if (tempVector3.x > orthoRight)
+                        orthoRight = tempVector3.x;
+                    if (tempVector3.y > orthoTop)
+                        orthoTop = tempVector3.y;
+                }
+            }
+            var orthoWidth = Math.max(Math.abs(orthoRight), Math.abs(orthoLeft)) * 1.1;
+            var orthoHeight = Math.max(Math.abs(orthoTop), Math.abs(orthoBottom)) * 1.1;
+            BABYLON.Matrix.OrthoOffCenterLHToRef(-orthoWidth, orthoWidth, -orthoHeight, orthoHeight, activeCamera.minZ, activeCamera.maxZ, matrix);
+        };
+        DirectionalLight.prototype.supportsVSM = function () {
+            return false;
+        };
+        DirectionalLight.prototype.needRefreshPerFrame = function () {
+            return true;
+        };
         DirectionalLight.prototype.computeTransformedPosition = function () {
         DirectionalLight.prototype.computeTransformedPosition = function () {
             if (this.parent && this.parent.getWorldMatrix) {
             if (this.parent && this.parent.getWorldMatrix) {
                 if (!this.transformedPosition) {
                 if (!this.transformedPosition) {

+ 43 - 0
Babylon/Lights/babylon.directionalLight.ts

@@ -21,6 +21,49 @@
             return this.direction;
             return this.direction;
         }
         }
 
 
+        public setShadowProjectionMatrix(matrix: Matrix, viewMatrix: Matrix, renderList: Array<AbstractMesh>): void {
+            var orthoLeft = Number.MAX_VALUE;
+            var orthoRight = Number.MIN_VALUE;
+            var orthoTop = Number.MIN_VALUE;
+            var orthoBottom = Number.MAX_VALUE;
+
+            var tempVector3 = Vector3.Zero();
+
+            var activeCamera = this.getScene().activeCamera;
+
+            // Check extends
+            for (var meshIndex = 0; meshIndex < renderList.length; meshIndex++) {
+                var boundingBox = renderList[meshIndex].getBoundingInfo().boundingBox;
+
+                for (var index = 0; index < boundingBox.vectorsWorld.length; index++) {
+                    Vector3.TransformCoordinatesToRef(boundingBox.vectorsWorld[index], viewMatrix, tempVector3);
+
+                    if (tempVector3.x < orthoLeft)
+                        orthoLeft = tempVector3.x;
+                    if (tempVector3.y < orthoBottom)
+                        orthoBottom = tempVector3.y;
+
+                    if (tempVector3.x > orthoRight)
+                        orthoRight = tempVector3.x;
+                    if (tempVector3.y > orthoTop)
+                        orthoTop = tempVector3.y;
+                }
+            }
+
+            var orthoWidth = Math.max(Math.abs(orthoRight), Math.abs(orthoLeft)) * 1.1;
+            var orthoHeight = Math.max(Math.abs(orthoTop), Math.abs(orthoBottom)) * 1.1;
+
+            Matrix.OrthoOffCenterLHToRef(-orthoWidth, orthoWidth, -orthoHeight, orthoHeight, activeCamera.minZ, activeCamera.maxZ, matrix);
+        }
+
+        public supportsVSM(): boolean {
+            return false;
+        }
+
+        public needRefreshPerFrame(): boolean {
+            return true;
+        }
+
         public computeTransformedPosition(): boolean {
         public computeTransformedPosition(): boolean {
             if (this.parent && this.parent.getWorldMatrix) {
             if (this.parent && this.parent.getWorldMatrix) {
                 if (!this.transformedPosition) {
                 if (!this.transformedPosition) {

+ 7 - 1
Babylon/Lights/babylon.light.ts

@@ -9,6 +9,12 @@
         computeTransformedPosition(): boolean;
         computeTransformedPosition(): boolean;
         getScene(): Scene;
         getScene(): Scene;
 
 
+        setShadowProjectionMatrix(matrix: Matrix, viewMatrix: Matrix, renderList: Array<AbstractMesh>): void;
+
+        supportsVSM(): boolean;
+
+        needRefreshPerFrame(): boolean;
+
         _shadowGenerator: ShadowGenerator;
         _shadowGenerator: ShadowGenerator;
     }
     }
 
 
@@ -38,7 +44,7 @@
         public getAbsolutePosition(): Vector3 {
         public getAbsolutePosition(): Vector3 {
             return Vector3.Zero();
             return Vector3.Zero();
         }
         }
-
+       
         public transferToEffect(effect: Effect, uniformName0?: string, uniformName1?: string): void {
         public transferToEffect(effect: Effect, uniformName0?: string, uniformName1?: string): void {
         }
         }
 
 

+ 10 - 0
Babylon/Lights/babylon.spotLight.js

@@ -18,6 +18,16 @@ var BABYLON;
         SpotLight.prototype.getAbsolutePosition = function () {
         SpotLight.prototype.getAbsolutePosition = function () {
             return this.transformedPosition ? this.transformedPosition : this.position;
             return this.transformedPosition ? this.transformedPosition : this.position;
         };
         };
+        SpotLight.prototype.setShadowProjectionMatrix = function (matrix, viewMatrix, renderList) {
+            var activeCamera = this.getScene().activeCamera;
+            BABYLON.Matrix.PerspectiveFovLHToRef(this.angle, 1.0, activeCamera.minZ, activeCamera.maxZ, matrix);
+        };
+        SpotLight.prototype.supportsVSM = function () {
+            return true;
+        };
+        SpotLight.prototype.needRefreshPerFrame = function () {
+            return false;
+        };
         SpotLight.prototype.setDirectionToTarget = function (target) {
         SpotLight.prototype.setDirectionToTarget = function (target) {
             this.direction = BABYLON.Vector3.Normalize(target.subtract(this.position));
             this.direction = BABYLON.Vector3.Normalize(target.subtract(this.position));
             return this.direction;
             return this.direction;

+ 13 - 0
Babylon/Lights/babylon.spotLight.ts

@@ -14,6 +14,19 @@
             return this.transformedPosition ? this.transformedPosition : this.position;
             return this.transformedPosition ? this.transformedPosition : this.position;
         }
         }
 
 
+        public setShadowProjectionMatrix(matrix: Matrix, viewMatrix: Matrix, renderList: Array<AbstractMesh>): void {
+            var activeCamera = this.getScene().activeCamera;
+            Matrix.PerspectiveFovLHToRef(this.angle, 1.0, activeCamera.minZ, activeCamera.maxZ, matrix);
+        }
+
+        public supportsVSM(): boolean {
+            return true;
+        }
+
+        public needRefreshPerFrame(): boolean {
+            return false;
+        }
+
         public setDirectionToTarget(target: Vector3): Vector3 {
         public setDirectionToTarget(target: Vector3): Vector3 {
             this.direction = Vector3.Normalize(target.subtract(this.position));
             this.direction = Vector3.Normalize(target.subtract(this.position));
             return this.direction;
             return this.direction;

+ 45 - 28
Babylon/Loading/Plugins/babylon.babylonFileLoader.js

@@ -688,36 +688,47 @@ var BABYLON;
                 return parseFloat(values[0]);
                 return parseFloat(values[0]);
             };
             };
             // traverse graph per trigger
             // traverse graph per trigger
-            var traverse = function (parsedAction, trigger, condition, action) {
+            var traverse = function (parsedAction, trigger, condition, action, combineArray) {
+                if (combineArray === void 0) { combineArray = null; }
                 if (parsedAction.detached)
                 if (parsedAction.detached)
                     return;
                     return;
                 var parameters = new Array();
                 var parameters = new Array();
                 var target = null;
                 var target = null;
                 var propertyPath = null;
                 var propertyPath = null;
+                var combine = parsedAction.combine && parsedAction.combine.length > 0;
                 // Parameters
                 // Parameters
                 if (parsedAction.type === 2)
                 if (parsedAction.type === 2)
                     parameters.push(actionManager);
                     parameters.push(actionManager);
                 else
                 else
                     parameters.push(trigger);
                     parameters.push(trigger);
-                for (var i = 0; i < parsedAction.properties.length; i++) {
-                    var value = parsedAction.properties[i].value;
-                    var name = parsedAction.properties[i].name;
-                    if (name === "target")
-                        value = target = scene.getNodeByName(value);
-                    else if (name === "parent")
-                        value = scene.getNodeByName(value);
-                    else if (name === "sound")
-                        value = scene.getSoundByName(value);
-                    else if (name !== "propertyPath") {
-                        if (parsedAction.type === 2 && name === "operator")
-                            value = BABYLON.ValueCondition[value];
-                        else
-                            value = parseParameter(name, value, target, name === "value" ? propertyPath : null);
+                if (combine) {
+                    var actions = new Array();
+                    for (var j = 0; j < parsedAction.combine.length; j++) {
+                        traverse(parsedAction.combine[j], BABYLON.ActionManager.NothingTrigger, condition, action, actions);
                     }
                     }
-                    else {
-                        propertyPath = value;
+                    parameters.push(actions);
+                }
+                else {
+                    for (var i = 0; i < parsedAction.properties.length; i++) {
+                        var value = parsedAction.properties[i].value;
+                        var name = parsedAction.properties[i].name;
+                        if (name === "target")
+                            value = target = scene.getNodeByName(value);
+                        else if (name === "parent")
+                            value = scene.getNodeByName(value);
+                        else if (name === "sound")
+                            value = scene.getSoundByName(value);
+                        else if (name !== "propertyPath") {
+                            if (parsedAction.type === 2 && name === "operator")
+                                value = BABYLON.ValueCondition[value];
+                            else
+                                value = parseParameter(name, value, target, name === "value" ? propertyPath : null);
+                        }
+                        else {
+                            propertyPath = value;
+                        }
+                        parameters.push(value);
                     }
                     }
-                    parameters.push(value);
                 }
                 }
                 parameters.push(condition);
                 parameters.push(condition);
                 // If interpolate value action
                 // If interpolate value action
@@ -726,21 +737,27 @@ var BABYLON;
                     parameters[parameters.length - 1] = param;
                     parameters[parameters.length - 1] = param;
                     parameters[parameters.length - 2] = condition;
                     parameters[parameters.length - 2] = condition;
                 }
                 }
-                // Action or condition(s)
+                // Action or condition(s) and not CombineAction
                 var newAction = instanciate(parsedAction.name, parameters);
                 var newAction = instanciate(parsedAction.name, parameters);
-                if (newAction instanceof BABYLON.Condition) {
-                    condition = newAction;
-                    newAction = action;
+                if (combineArray === null) {
+                    if (newAction instanceof BABYLON.Condition) {
+                        condition = newAction;
+                        newAction = action;
+                    }
+                    else {
+                        condition = null;
+                        if (action)
+                            action.then(newAction);
+                        else
+                            actionManager.registerAction(newAction);
+                    }
                 }
                 }
                 else {
                 else {
-                    condition = null;
-                    if (action)
-                        action.then(newAction);
-                    else
-                        actionManager.registerAction(newAction);
+                    if (combineArray !== null)
+                        combineArray.push(newAction);
                 }
                 }
                 for (var i = 0; i < parsedAction.children.length; i++)
                 for (var i = 0; i < parsedAction.children.length; i++)
-                    traverse(parsedAction.children[i], trigger, condition, newAction);
+                    traverse(parsedAction.children[i], trigger, condition, newAction, null);
             };
             };
             for (var i = 0; i < parsedActions.children.length; i++) {
             for (var i = 0; i < parsedActions.children.length; i++) {
                 var triggerParams;
                 var triggerParams;

+ 46 - 30
Babylon/Loading/Plugins/babylon.babylonFileLoader.ts

@@ -870,13 +870,14 @@
         };
         };
 
 
         // traverse graph per trigger
         // traverse graph per trigger
-        var traverse = (parsedAction: any, trigger: any, condition: Condition, action: Action) => {
+        var traverse = (parsedAction: any, trigger: any, condition: Condition, action: Action, combineArray: Array<Action> = null) => {
             if (parsedAction.detached)
             if (parsedAction.detached)
                 return;
                 return;
 
 
             var parameters = new Array<any>();
             var parameters = new Array<any>();
             var target: any = null;
             var target: any = null;
             var propertyPath: string = null;
             var propertyPath: string = null;
+            var combine = parsedAction.combine && parsedAction.combine.length > 0;
 
 
             // Parameters
             // Parameters
             if (parsedAction.type === 2)
             if (parsedAction.type === 2)
@@ -884,26 +885,35 @@
             else
             else
                 parameters.push(trigger);
                 parameters.push(trigger);
 
 
-            for (var i = 0; i < parsedAction.properties.length; i++) {
-                var value = parsedAction.properties[i].value;
-                var name = parsedAction.properties[i].name;
-
-                if (name === "target")
-                    value = target = scene.getNodeByName(value);
-                else if (name === "parent")
-                    value = scene.getNodeByName(value);
-                else if (name === "sound")
-                    value = scene.getSoundByName(value);
-                else if (name !== "propertyPath") {
-                    if (parsedAction.type === 2 && name === "operator")
-                        value = BABYLON.ValueCondition[value];
-                    else
-                        value = parseParameter(name, value, target, name === "value" ? propertyPath : null);
-                } else {
-                    propertyPath = value;
+            if (combine) {
+                var actions = new Array<Action>();
+                for (var j = 0; j < parsedAction.combine.length; j++) {
+                    traverse(parsedAction.combine[j], ActionManager.NothingTrigger, condition, action, actions);
                 }
                 }
+                parameters.push(actions);
+            }
+            else {
+                for (var i = 0; i < parsedAction.properties.length; i++) {
+                    var value = parsedAction.properties[i].value;
+                    var name = parsedAction.properties[i].name;
+
+                    if (name === "target")
+                        value = target = scene.getNodeByName(value);
+                    else if (name === "parent")
+                        value = scene.getNodeByName(value);
+                    else if (name === "sound")
+                        value = scene.getSoundByName(value);
+                    else if (name !== "propertyPath") {
+                        if (parsedAction.type === 2 && name === "operator")
+                            value = BABYLON.ValueCondition[value];
+                        else
+                            value = parseParameter(name, value, target, name === "value" ? propertyPath : null);
+                    } else {
+                        propertyPath = value;
+                    }
 
 
-                parameters.push(value);
+                    parameters.push(value);
+                }
             }
             }
             parameters.push(condition);
             parameters.push(condition);
 
 
@@ -914,21 +924,27 @@
                 parameters[parameters.length - 2] = condition;
                 parameters[parameters.length - 2] = condition;
             }
             }
 
 
-            // Action or condition(s)
+            // Action or condition(s) and not CombineAction
             var newAction = instanciate(parsedAction.name, parameters);
             var newAction = instanciate(parsedAction.name, parameters);
-            if (newAction instanceof BABYLON.Condition) {
-                condition = newAction;
-                newAction = action;
-            } else {
-                condition = null;
-                if (action)
-                    action.then(newAction);
-                else
-                    actionManager.registerAction(newAction);
+            if (combineArray === null) {
+                if (newAction instanceof BABYLON.Condition) {
+                    condition = newAction;
+                    newAction = action;
+                } else {
+                    condition = null;
+                    if (action)
+                        action.then(newAction);
+                    else
+                        actionManager.registerAction(newAction);
+                }
+            }
+            else {
+                if (combineArray !== null)
+                    combineArray.push(newAction);
             }
             }
 
 
             for (var i = 0; i < parsedAction.children.length; i++)
             for (var i = 0; i < parsedAction.children.length; i++)
-                traverse(parsedAction.children[i], trigger, condition, newAction);
+                traverse(parsedAction.children[i], trigger, condition, newAction, null);
         };
         };
 
 
         // triggers
         // triggers

+ 5 - 1
Babylon/Materials/Textures/babylon.renderTargetTexture.js

@@ -78,7 +78,7 @@ var BABYLON;
             this.releaseInternalTexture();
             this.releaseInternalTexture();
             this._texture = this.getScene().getEngine().createRenderTargetTexture(size, generateMipMaps);
             this._texture = this.getScene().getEngine().createRenderTargetTexture(size, generateMipMaps);
         };
         };
-        RenderTargetTexture.prototype.render = function (useCameraPostProcess) {
+        RenderTargetTexture.prototype.render = function (useCameraPostProcess, dumpForDebug) {
             var scene = this.getScene();
             var scene = this.getScene();
             var engine = scene.getEngine();
             var engine = scene.getEngine();
             if (this._waitingRenderList) {
             if (this._waitingRenderList) {
@@ -135,6 +135,10 @@ var BABYLON;
             if (this.onAfterRender) {
             if (this.onAfterRender) {
                 this.onAfterRender();
                 this.onAfterRender();
             }
             }
+            // Dump ?
+            if (dumpForDebug) {
+                BABYLON.Tools.DumpFramebuffer(this._size, this._size, engine);
+            }
             // Unbind
             // Unbind
             engine.unBindFramebuffer(this._texture);
             engine.unBindFramebuffer(this._texture);
         };
         };

+ 6 - 1
Babylon/Materials/Textures/babylon.renderTargetTexture.ts

@@ -87,7 +87,7 @@
             this._texture = this.getScene().getEngine().createRenderTargetTexture(size, generateMipMaps);
             this._texture = this.getScene().getEngine().createRenderTargetTexture(size, generateMipMaps);
         }
         }
 
 
-        public render(useCameraPostProcess?: boolean) {
+        public render(useCameraPostProcess?: boolean, dumpForDebug?: boolean) {
             var scene = this.getScene();
             var scene = this.getScene();
             var engine = scene.getEngine();
             var engine = scene.getEngine();
 
 
@@ -162,6 +162,11 @@
                 this.onAfterRender();
                 this.onAfterRender();
             }
             }
 
 
+            // Dump ?
+            if (dumpForDebug) {
+                Tools.DumpFramebuffer(this._size, this._size, engine);
+            }
+
             // Unbind
             // Unbind
             engine.unBindFramebuffer(this._texture);
             engine.unBindFramebuffer(this._texture);
         }
         }

File diff suppressed because it is too large
+ 2 - 2
Babylon/Materials/babylon.standardMaterial.js


+ 2 - 2
Babylon/Materials/babylon.standardMaterial.ts

@@ -397,7 +397,7 @@
                         "vDiffuseInfos", "vAmbientInfos", "vOpacityInfos", "vReflectionInfos", "vEmissiveInfos", "vSpecularInfos", "vBumpInfos",
                         "vDiffuseInfos", "vAmbientInfos", "vOpacityInfos", "vReflectionInfos", "vEmissiveInfos", "vSpecularInfos", "vBumpInfos",
                         "mBones",
                         "mBones",
                         "vClipPlane", "diffuseMatrix", "ambientMatrix", "opacityMatrix", "reflectionMatrix", "emissiveMatrix", "specularMatrix", "bumpMatrix",
                         "vClipPlane", "diffuseMatrix", "ambientMatrix", "opacityMatrix", "reflectionMatrix", "emissiveMatrix", "specularMatrix", "bumpMatrix",
-                        "darkness0", "darkness1", "darkness2", "darkness3",
+                        "shadowsInfo0", "shadowsInfo1", "shadowsInfo2", "shadowsInfo3",
                         "diffuseLeftColor", "diffuseRightColor", "opacityParts", "reflectionLeftColor", "reflectionRightColor", "emissiveLeftColor", "emissiveRightColor"
                         "diffuseLeftColor", "diffuseRightColor", "opacityParts", "reflectionLeftColor", "reflectionRightColor", "emissiveLeftColor", "emissiveRightColor"
                     ],
                     ],
                     ["diffuseSampler", "ambientSampler", "opacitySampler", "reflectionCubeSampler", "reflection2DSampler", "emissiveSampler", "specularSampler", "bumpSampler",
                     ["diffuseSampler", "ambientSampler", "opacitySampler", "reflectionCubeSampler", "reflection2DSampler", "emissiveSampler", "specularSampler", "bumpSampler",
@@ -585,7 +585,7 @@
                         if (mesh.receiveShadows && shadowGenerator) {
                         if (mesh.receiveShadows && shadowGenerator) {
                             this._effect.setMatrix("lightMatrix" + lightIndex, shadowGenerator.getTransformMatrix());
                             this._effect.setMatrix("lightMatrix" + lightIndex, shadowGenerator.getTransformMatrix());
                             this._effect.setTexture("shadowSampler" + lightIndex, shadowGenerator.getShadowMap());
                             this._effect.setTexture("shadowSampler" + lightIndex, shadowGenerator.getShadowMap());
-                            this._effect.setFloat("darkness" + lightIndex, shadowGenerator.getDarkness());
+                            this._effect.setFloat3("shadowsInfo" + lightIndex, shadowGenerator.getDarkness(), shadowGenerator.getShadowMap().getSize().width, shadowGenerator.getBias());
                         }
                         }
                     }
                     }
 
 

+ 6 - 1
Babylon/Math/babylon.math.js

@@ -1709,11 +1709,16 @@ var BABYLON;
             return Matrix.FromValuesToRef(this._xAxis.x, this._yAxis.x, this._zAxis.x, 0, this._xAxis.y, this._yAxis.y, this._zAxis.y, 0, this._xAxis.z, this._yAxis.z, this._zAxis.z, 0, ex, ey, ez, 1, result);
             return Matrix.FromValuesToRef(this._xAxis.x, this._yAxis.x, this._zAxis.x, 0, this._xAxis.y, this._yAxis.y, this._zAxis.y, 0, this._xAxis.z, this._yAxis.z, this._zAxis.z, 0, ex, ey, ez, 1, result);
         };
         };
         Matrix.OrthoLH = function (width, height, znear, zfar) {
         Matrix.OrthoLH = function (width, height, znear, zfar) {
+            var matrix = Matrix.Zero();
+            Matrix.OrthoLHToRef(width, height, znear, zfar, matrix);
+            return matrix;
+        };
+        Matrix.OrthoLHToRef = function (width, height, znear, zfar, result) {
             var hw = 2.0 / width;
             var hw = 2.0 / width;
             var hh = 2.0 / height;
             var hh = 2.0 / height;
             var id = 1.0 / (zfar - znear);
             var id = 1.0 / (zfar - znear);
             var nid = znear / (znear - zfar);
             var nid = znear / (znear - zfar);
-            return Matrix.FromValues(hw, 0, 0, 0, 0, hh, 0, 0, 0, 0, id, 0, 0, 0, nid, 1);
+            Matrix.FromValuesToRef(hw, 0, 0, 0, 0, hh, 0, 0, 0, 0, id, 0, 0, 0, nid, 1, result);
         };
         };
         Matrix.OrthoOffCenterLH = function (left, right, bottom, top, znear, zfar) {
         Matrix.OrthoOffCenterLH = function (left, right, bottom, top, znear, zfar) {
             var matrix = Matrix.Zero();
             var matrix = Matrix.Zero();

+ 10 - 2
Babylon/Math/babylon.math.ts

@@ -2166,15 +2166,23 @@
         }
         }
 
 
         public static OrthoLH(width: number, height: number, znear: number, zfar: number): Matrix {
         public static OrthoLH(width: number, height: number, znear: number, zfar: number): Matrix {
+            var matrix = Matrix.Zero();
+
+            Matrix.OrthoLHToRef(width, height, znear, zfar, matrix);
+
+            return matrix;
+        }
+
+        public static OrthoLHToRef(width: number, height: number, znear: number, zfar: number, result: Matrix): void {
             var hw = 2.0 / width;
             var hw = 2.0 / width;
             var hh = 2.0 / height;
             var hh = 2.0 / height;
             var id = 1.0 / (zfar - znear);
             var id = 1.0 / (zfar - znear);
             var nid = znear / (znear - zfar);
             var nid = znear / (znear - zfar);
 
 
-            return Matrix.FromValues(hw, 0, 0, 0,
+            Matrix.FromValuesToRef(hw, 0, 0, 0,
                 0, hh, 0, 0,
                 0, hh, 0, 0,
                 0, 0, id, 0,
                 0, 0, id, 0,
-                0, 0, nid, 1);
+                0, 0, nid, 1, result);
         }
         }
 
 
         public static OrthoOffCenterLH(left: number, right: number, bottom: number, top: number, znear: number, zfar: number): Matrix {
         public static OrthoOffCenterLH(left: number, right: number, bottom: number, top: number, znear: number, zfar: number): Matrix {

+ 24 - 24
Babylon/Shaders/default.fragment.fx

@@ -35,7 +35,7 @@ uniform vec3 vLightSpecular0;
 #ifdef SHADOW0
 #ifdef SHADOW0
 varying vec4 vPositionFromLight0;
 varying vec4 vPositionFromLight0;
 uniform sampler2D shadowSampler0;
 uniform sampler2D shadowSampler0;
-uniform float darkness0;
+uniform vec3 shadowsInfo0;
 #endif
 #endif
 #ifdef SPOTLIGHT0
 #ifdef SPOTLIGHT0
 uniform vec4 vLightDirection0;
 uniform vec4 vLightDirection0;
@@ -52,7 +52,7 @@ uniform vec3 vLightSpecular1;
 #ifdef SHADOW1
 #ifdef SHADOW1
 varying vec4 vPositionFromLight1;
 varying vec4 vPositionFromLight1;
 uniform sampler2D shadowSampler1;
 uniform sampler2D shadowSampler1;
-uniform float darkness1;
+uniform vec3 shadowsInfo1;
 #endif
 #endif
 #ifdef SPOTLIGHT1
 #ifdef SPOTLIGHT1
 uniform vec4 vLightDirection1;
 uniform vec4 vLightDirection1;
@@ -69,7 +69,7 @@ uniform vec3 vLightSpecular2;
 #ifdef SHADOW2
 #ifdef SHADOW2
 varying vec4 vPositionFromLight2;
 varying vec4 vPositionFromLight2;
 uniform sampler2D shadowSampler2;
 uniform sampler2D shadowSampler2;
-uniform float darkness2;
+uniform vec3 shadowsInfo2;
 #endif
 #endif
 #ifdef SPOTLIGHT2
 #ifdef SPOTLIGHT2
 uniform vec4 vLightDirection2;
 uniform vec4 vLightDirection2;
@@ -86,7 +86,7 @@ uniform vec3 vLightSpecular3;
 #ifdef SHADOW3
 #ifdef SHADOW3
 varying vec4 vPositionFromLight3;
 varying vec4 vPositionFromLight3;
 uniform sampler2D shadowSampler3;
 uniform sampler2D shadowSampler3;
-uniform float darkness3;
+uniform vec3 shadowsInfo3;
 #endif
 #endif
 #ifdef SPOTLIGHT3
 #ifdef SPOTLIGHT3
 uniform vec4 vLightDirection3;
 uniform vec4 vLightDirection3;
@@ -213,7 +213,7 @@ float unpackHalf(vec2 color)
 	return color.x + (color.y / 255.0);
 	return color.x + (color.y / 255.0);
 }
 }
 
 
-float computeShadow(vec4 vPositionFromLight, sampler2D shadowSampler, float darkness)
+float computeShadow(vec4 vPositionFromLight, sampler2D shadowSampler, float darkness, float bias)
 {
 {
 	vec3 depth = vPositionFromLight.xyz / vPositionFromLight.w;
 	vec3 depth = vPositionFromLight.xyz / vPositionFromLight.w;
 	vec2 uv = 0.5 * depth.xy + vec2(0.5, 0.5);
 	vec2 uv = 0.5 * depth.xy + vec2(0.5, 0.5);
@@ -223,7 +223,7 @@ float computeShadow(vec4 vPositionFromLight, sampler2D shadowSampler, float dark
 		return 1.0;
 		return 1.0;
 	}
 	}
 
 
-	float shadow = unpack(texture2D(shadowSampler, uv));
+	float shadow = unpack(texture2D(shadowSampler, uv)) + bias;
 
 
 	if (depth.z > shadow)
 	if (depth.z > shadow)
 	{
 	{
@@ -232,7 +232,7 @@ float computeShadow(vec4 vPositionFromLight, sampler2D shadowSampler, float dark
 	return 1.;
 	return 1.;
 }
 }
 
 
-float computeShadowWithPCF(vec4 vPositionFromLight, sampler2D shadowSampler)
+float computeShadowWithPCF(vec4 vPositionFromLight, sampler2D shadowSampler, float mapSize, float bias)
 {
 {
 	vec3 depth = vPositionFromLight.xyz / vPositionFromLight.w;
 	vec3 depth = vPositionFromLight.xyz / vPositionFromLight.w;
 	vec2 uv = 0.5 * depth.xy + vec2(0.5, 0.5);
 	vec2 uv = 0.5 * depth.xy + vec2(0.5, 0.5);
@@ -251,10 +251,10 @@ float computeShadowWithPCF(vec4 vPositionFromLight, sampler2D shadowSampler)
 	poissonDisk[3] = vec2(0.34495938, 0.29387760);
 	poissonDisk[3] = vec2(0.34495938, 0.29387760);
 
 
 	// Poisson Sampling
 	// Poisson Sampling
-	if (unpack(texture2D(shadowSampler, uv + poissonDisk[0] / 1500.0))  <  depth.z) visibility -= 0.2;
-	if (unpack(texture2D(shadowSampler, uv + poissonDisk[1] / 1500.0))  <  depth.z) visibility -= 0.2;
-	if (unpack(texture2D(shadowSampler, uv + poissonDisk[2] / 1500.0))  <  depth.z) visibility -= 0.2;
-	if (unpack(texture2D(shadowSampler, uv + poissonDisk[3] / 1500.0))  <  depth.z) visibility -= 0.2;
+	if (unpack(texture2D(shadowSampler, uv + poissonDisk[0] / mapSize)) + bias  <  depth.z) visibility -= 0.25;
+	if (unpack(texture2D(shadowSampler, uv + poissonDisk[1] / mapSize)) + bias  <  depth.z) visibility -= 0.25;
+	if (unpack(texture2D(shadowSampler, uv + poissonDisk[2] / mapSize)) + bias  <  depth.z) visibility -= 0.25;
+	if (unpack(texture2D(shadowSampler, uv + poissonDisk[3] / mapSize)) + bias  <  depth.z) visibility -= 0.25;
 
 
 	return visibility;
 	return visibility;
 }
 }
@@ -268,10 +268,10 @@ float ChebychevInequality(vec2 moments, float t)
 	}
 	}
 
 
 	float variance = moments.y - (moments.x * moments.x);
 	float variance = moments.y - (moments.x * moments.x);
-	variance = max(variance, 0.);
+	variance = max(variance, 0.02);
 
 
 	float d = t - moments.x;
 	float d = t - moments.x;
-	return variance / (variance + d * d);
+	return clamp(variance / (variance + d * d) - 0.2, 0., 1.0);
 }
 }
 
 
 float computeShadowWithVSM(vec4 vPositionFromLight, sampler2D shadowSampler)
 float computeShadowWithVSM(vec4 vPositionFromLight, sampler2D shadowSampler)
@@ -279,7 +279,7 @@ float computeShadowWithVSM(vec4 vPositionFromLight, sampler2D shadowSampler)
 	vec3 depth = vPositionFromLight.xyz / vPositionFromLight.w;
 	vec3 depth = vPositionFromLight.xyz / vPositionFromLight.w;
 	vec2 uv = 0.5 * depth.xy + vec2(0.5, 0.5);
 	vec2 uv = 0.5 * depth.xy + vec2(0.5, 0.5);
 
 
-	if (uv.x < 0. || uv.x > 1.0 || uv.y < 0. || uv.y > 1.0)
+	if (uv.x < 0. || uv.x > 1.0 || uv.y < 0. || uv.y > 1.0 || depth.z > 1.0)
 	{
 	{
 		return 1.0;
 		return 1.0;
 	}
 	}
@@ -287,7 +287,7 @@ float computeShadowWithVSM(vec4 vPositionFromLight, sampler2D shadowSampler)
 	vec4 texel = texture2D(shadowSampler, uv);
 	vec4 texel = texture2D(shadowSampler, uv);
 
 
 	vec2 moments = vec2(unpackHalf(texel.xy), unpackHalf(texel.zw));
 	vec2 moments = vec2(unpackHalf(texel.xy), unpackHalf(texel.zw));
-	return clamp(1.3 - ChebychevInequality(moments, depth.z), 0., 1.0);
+	return 1.0 - ChebychevInequality(moments, depth.z);
 }
 }
 #endif
 #endif
 
 
@@ -420,7 +420,7 @@ lightingInfo computeSpotLighting(vec3 viewDirectionW, vec3 vNormal, vec4 lightDa
 	if (cosAngle >= lightDirection.w)
 	if (cosAngle >= lightDirection.w)
 	{
 	{
 		cosAngle = max(0., pow(cosAngle, lightData.w));
 		cosAngle = max(0., pow(cosAngle, lightData.w));
-		spotAtten = max(0., (cosAngle - lightDirection.w) / (1. - cosAngle));
+		spotAtten = clamp((cosAngle - lightDirection.w) / (1. - cosAngle), 0.0, 1.0);
 
 
 		// Diffuse
 		// Diffuse
 		float ndl = max(0., dot(vNormal, -lightDirection.xyz));
 		float ndl = max(0., dot(vNormal, -lightDirection.xyz));
@@ -534,9 +534,9 @@ void main(void) {
 	shadow = computeShadowWithVSM(vPositionFromLight0, shadowSampler0);
 	shadow = computeShadowWithVSM(vPositionFromLight0, shadowSampler0);
 #else
 #else
 	#ifdef SHADOWPCF0
 	#ifdef SHADOWPCF0
-		shadow = computeShadowWithPCF(vPositionFromLight0, shadowSampler0);
+		shadow = computeShadowWithPCF(vPositionFromLight0, shadowSampler0, shadowsInfo0.y, shadowsInfo0.z);
 	#else
 	#else
-		shadow = computeShadow(vPositionFromLight0, shadowSampler0, darkness0);
+		shadow = computeShadow(vPositionFromLight0, shadowSampler0, shadowsInfo0.x, shadowsInfo0.z);
 	#endif
 	#endif
 #endif
 #endif
 #else
 #else
@@ -561,9 +561,9 @@ void main(void) {
 	shadow = computeShadowWithVSM(vPositionFromLight1, shadowSampler1);
 	shadow = computeShadowWithVSM(vPositionFromLight1, shadowSampler1);
 #else
 #else
 	#ifdef SHADOWPCF1
 	#ifdef SHADOWPCF1
-		shadow = computeShadowWithPCF(vPositionFromLight1, shadowSampler1);
+		shadow = computeShadowWithPCF(vPositionFromLight1, shadowSampler1, shadowsInfo1.y, shadowsInfo1.z);
 	#else
 	#else
-		shadow = computeShadow(vPositionFromLight1, shadowSampler1, darkness1);
+		shadow = computeShadow(vPositionFromLight1, shadowSampler1, shadowsInfo1.x, shadowsInfo1.z);
 	#endif
 	#endif
 #endif
 #endif
 #else
 #else
@@ -588,9 +588,9 @@ void main(void) {
 	shadow = computeShadowWithVSM(vPositionFromLight2, shadowSampler2);
 	shadow = computeShadowWithVSM(vPositionFromLight2, shadowSampler2);
 #else
 #else
 	#ifdef SHADOWPCF2
 	#ifdef SHADOWPCF2
-		shadow = computeShadowWithPCF(vPositionFromLight2, shadowSampler2);
+		shadow = computeShadowWithPCF(vPositionFromLight2, shadowSampler2, shadowsInfo2.y, shadowsInfo2.z);
 	#else
 	#else
-		shadow = computeShadow(vPositionFromLight2, shadowSampler2, darkness2);
+		shadow = computeShadow(vPositionFromLight2, shadowSampler2, shadowsInfo2.x, shadowsInfo2.z);
 	#endif	
 	#endif	
 #endif	
 #endif	
 #else
 #else
@@ -615,9 +615,9 @@ void main(void) {
 	shadow = computeShadowWithVSM(vPositionFromLight3, shadowSampler3);
 	shadow = computeShadowWithVSM(vPositionFromLight3, shadowSampler3);
 #else
 #else
 	#ifdef SHADOWPCF3
 	#ifdef SHADOWPCF3
-		shadow = computeShadowWithPCF(vPositionFromLight3, shadowSampler3);
+		shadow = computeShadowWithPCF(vPositionFromLight3, shadowSampler3, shadowsInfo3.y, shadowsInfo3.z);
 	#else
 	#else
-		shadow = computeShadow(vPositionFromLight3, shadowSampler3, darkness3);
+		shadow = computeShadow(vPositionFromLight3, shadowSampler3, shadowsInfo3.x, shadowsInfo3.z);
 	#endif	
 	#endif	
 #endif	
 #endif	
 #else
 #else

+ 2 - 2
Babylon/Shaders/shadowMap.fragment.fx

@@ -7,7 +7,7 @@ vec4 pack(float depth)
 	const vec4 bitOffset = vec4(255. * 255. * 255., 255. * 255., 255., 1.);
 	const vec4 bitOffset = vec4(255. * 255. * 255., 255. * 255., 255., 1.);
 	const vec4 bitMask = vec4(0., 1. / 255., 1. / 255., 1. / 255.);
 	const vec4 bitMask = vec4(0., 1. / 255., 1. / 255., 1. / 255.);
 	
 	
-	vec4 comp = mod(depth * bitOffset * vec4(254.), vec4(255.)) / vec4(254.);
+	vec4 comp = mod(depth * bitOffset * vec4(255.), vec4(255.)) / vec4(255.);
 	comp -= comp.xxyz * bitMask;
 	comp -= comp.xxyz * bitMask;
 	
 	
 	return comp;
 	return comp;
@@ -39,7 +39,7 @@ void main(void)
 #endif
 #endif
 
 
 #ifdef VSM
 #ifdef VSM
-	float moment1 = gl_FragCoord.z / gl_FragCoord.w;
+	float moment1 = gl_FragCoord.z;
 	float moment2 = moment1 * moment1;
 	float moment2 = moment1 * moment1;
 	gl_FragColor = vec4(packHalf(moment1), packHalf(moment2));
 	gl_FragColor = vec4(packHalf(moment1), packHalf(moment2));
 #else
 #else

+ 2 - 3
Babylon/Shaders/shadowMap.vertex.fx

@@ -53,13 +53,12 @@ void main(void)
 	mat4 m2 = mBones[int(matricesIndices.z)] * matricesWeights.z;
 	mat4 m2 = mBones[int(matricesIndices.z)] * matricesWeights.z;
 	mat4 m3 = mBones[int(matricesIndices.w)] * matricesWeights.w;
 	mat4 m3 = mBones[int(matricesIndices.w)] * matricesWeights.w;
 	finalWorld = finalWorld * (m0 + m1 + m2 + m3);
 	finalWorld = finalWorld * (m0 + m1 + m2 + m3);
-	gl_Position = viewProjection * finalWorld * vec4(position, 1.0);
-#else
+#endif
+
 #ifndef VSM
 #ifndef VSM
 	vPosition = viewProjection * finalWorld * vec4(position, 1.0);
 	vPosition = viewProjection * finalWorld * vec4(position, 1.0);
 #endif
 #endif
 	gl_Position = viewProjection * finalWorld * vec4(position, 1.0);
 	gl_Position = viewProjection * finalWorld * vec4(position, 1.0);
-#endif
 
 
 #ifdef ALPHATEST
 #ifdef ALPHATEST
 #ifdef UV1
 #ifdef UV1

+ 64 - 62
Babylon/Tools/babylon.filesInput.js

@@ -4,42 +4,42 @@ var BABYLON;
         /// Register to core BabylonJS object: engine, scene, rendering canvas, callback function when the scene will be loaded,
         /// Register to core BabylonJS object: engine, scene, rendering canvas, callback function when the scene will be loaded,
         /// loading progress callback and optionnal addionnal logic to call in the rendering loop
         /// loading progress callback and optionnal addionnal logic to call in the rendering loop
         function FilesInput(p_engine, p_scene, p_canvas, p_sceneLoadedCallback, p_progressCallback, p_additionnalRenderLoopLogicCallback, p_textureLoadingCallback, p_startingProcessingFilesCallback) {
         function FilesInput(p_engine, p_scene, p_canvas, p_sceneLoadedCallback, p_progressCallback, p_additionnalRenderLoopLogicCallback, p_textureLoadingCallback, p_startingProcessingFilesCallback) {
-            this.engine = p_engine;
-            this.canvas = p_canvas;
-            this.currentScene = p_scene;
-            this.sceneLoadedCallback = p_sceneLoadedCallback;
-            this.progressCallback = p_progressCallback;
-            this.additionnalRenderLoopLogicCallback = p_additionnalRenderLoopLogicCallback;
-            this.textureLoadingCallback = p_textureLoadingCallback;
-            this.startingProcessingFilesCallback = p_startingProcessingFilesCallback;
+            this._engine = p_engine;
+            this._canvas = p_canvas;
+            this._currentScene = p_scene;
+            this._sceneLoadedCallback = p_sceneLoadedCallback;
+            this._progressCallback = p_progressCallback;
+            this._additionnalRenderLoopLogicCallback = p_additionnalRenderLoopLogicCallback;
+            this._textureLoadingCallback = p_textureLoadingCallback;
+            this._startingProcessingFilesCallback = p_startingProcessingFilesCallback;
         }
         }
         FilesInput.prototype.monitorElementForDragNDrop = function (p_elementToMonitor) {
         FilesInput.prototype.monitorElementForDragNDrop = function (p_elementToMonitor) {
             var _this = this;
             var _this = this;
             if (p_elementToMonitor) {
             if (p_elementToMonitor) {
-                this.elementToMonitor = p_elementToMonitor;
-                this.elementToMonitor.addEventListener("dragenter", function (e) {
+                this._elementToMonitor = p_elementToMonitor;
+                this._elementToMonitor.addEventListener("dragenter", function (e) {
                     _this.drag(e);
                     _this.drag(e);
                 }, false);
                 }, false);
-                this.elementToMonitor.addEventListener("dragover", function (e) {
+                this._elementToMonitor.addEventListener("dragover", function (e) {
                     _this.drag(e);
                     _this.drag(e);
                 }, false);
                 }, false);
-                this.elementToMonitor.addEventListener("drop", function (e) {
+                this._elementToMonitor.addEventListener("drop", function (e) {
                     _this.drop(e);
                     _this.drop(e);
                 }, false);
                 }, false);
             }
             }
         };
         };
         FilesInput.prototype.renderFunction = function () {
         FilesInput.prototype.renderFunction = function () {
-            if (this.additionnalRenderLoopLogicCallback) {
-                this.additionnalRenderLoopLogicCallback();
+            if (this._additionnalRenderLoopLogicCallback) {
+                this._additionnalRenderLoopLogicCallback();
             }
             }
-            if (this.currentScene) {
-                if (this.textureLoadingCallback) {
-                    var remaining = this.currentScene.getWaitingItemsCount();
+            if (this._currentScene) {
+                if (this._textureLoadingCallback) {
+                    var remaining = this._currentScene.getWaitingItemsCount();
                     if (remaining > 0) {
                     if (remaining > 0) {
-                        this.textureLoadingCallback(remaining);
+                        this._textureLoadingCallback(remaining);
                     }
                     }
                 }
                 }
-                this.currentScene.render();
+                this._currentScene.render();
             }
             }
         };
         };
         FilesInput.prototype.drag = function (e) {
         FilesInput.prototype.drag = function (e) {
@@ -52,27 +52,23 @@ var BABYLON;
             this.loadFiles(eventDrop);
             this.loadFiles(eventDrop);
         };
         };
         FilesInput.prototype.loadFiles = function (event) {
         FilesInput.prototype.loadFiles = function (event) {
-            var _this = this;
-            var that = this;
-            if (this.startingProcessingFilesCallback)
-                this.startingProcessingFilesCallback();
-            var sceneFileToLoad;
-            var filesToLoad;
+            if (this._startingProcessingFilesCallback)
+                this._startingProcessingFilesCallback();
             // Handling data transfer via drag'n'drop
             // Handling data transfer via drag'n'drop
             if (event && event.dataTransfer && event.dataTransfer.files) {
             if (event && event.dataTransfer && event.dataTransfer.files) {
-                filesToLoad = event.dataTransfer.files;
+                this._filesToLoad = event.dataTransfer.files;
             }
             }
             // Handling files from input files
             // Handling files from input files
             if (event && event.target && event.target.files) {
             if (event && event.target && event.target.files) {
-                filesToLoad = event.target.files;
+                this._filesToLoad = event.target.files;
             }
             }
-            if (filesToLoad && filesToLoad.length > 0) {
-                for (var i = 0; i < filesToLoad.length; i++) {
-                    switch (filesToLoad[i].type) {
+            if (this._filesToLoad && this._filesToLoad.length > 0) {
+                for (var i = 0; i < this._filesToLoad.length; i++) {
+                    switch (this._filesToLoad[i].type) {
                         case "image/jpeg":
                         case "image/jpeg":
                         case "image/png":
                         case "image/png":
                         case "image/bmp":
                         case "image/bmp":
-                            FilesInput.FilesTextures[filesToLoad[i].name] = filesToLoad[i];
+                            FilesInput.FilesTextures[this._filesToLoad[i].name] = this._filesToLoad[i];
                             break;
                             break;
                         case "image/targa":
                         case "image/targa":
                         case "image/vnd.ms-dds":
                         case "image/vnd.ms-dds":
@@ -83,45 +79,51 @@ var BABYLON;
                         case "audio/mpeg3":
                         case "audio/mpeg3":
                         case "audio/x-mpeg-3":
                         case "audio/x-mpeg-3":
                         case "audio/ogg":
                         case "audio/ogg":
-                            FilesInput.FilesToLoad[filesToLoad[i].name] = filesToLoad[i];
+                            FilesInput.FilesToLoad[this._filesToLoad[i].name] = this._filesToLoad[i];
                             break;
                             break;
                         default:
                         default:
-                            if (filesToLoad[i].name.indexOf(".babylon") !== -1 && filesToLoad[i].name.indexOf(".manifest") === -1 && filesToLoad[i].name.indexOf(".incremental") === -1 && filesToLoad[i].name.indexOf(".babylonmeshdata") === -1 && filesToLoad[i].name.indexOf(".babylongeometrydata") === -1) {
-                                sceneFileToLoad = filesToLoad[i];
+                            if (this._filesToLoad[i].name.indexOf(".babylon") !== -1 && this._filesToLoad[i].name.indexOf(".manifest") === -1 && this._filesToLoad[i].name.indexOf(".incremental") === -1 && this._filesToLoad[i].name.indexOf(".babylonmeshdata") === -1 && this._filesToLoad[i].name.indexOf(".babylongeometrydata") === -1) {
+                                this._sceneFileToLoad = this._filesToLoad[i];
                             }
                             }
                             break;
                             break;
                     }
                     }
                 }
                 }
-                // If a ".babylon" file has been provided
-                if (sceneFileToLoad) {
-                    if (this.currentScene) {
-                        this.engine.stopRenderLoop();
-                        this.currentScene.dispose();
-                    }
-                    BABYLON.SceneLoader.Load("file:", sceneFileToLoad, this.engine, function (newScene) {
-                        that.currentScene = newScene;
-                        // Wait for textures and shaders to be ready
-                        that.currentScene.executeWhenReady(function () {
-                            // Attach camera to canvas inputs
-                            if (that.currentScene.activeCamera) {
-                                that.currentScene.activeCamera.attachControl(that.canvas);
-                            }
-                            if (that.sceneLoadedCallback) {
-                                that.sceneLoadedCallback(sceneFileToLoad, that.currentScene);
-                            }
-                            that.engine.runRenderLoop(function () {
-                                that.renderFunction();
-                            });
-                        });
-                    }, function (progress) {
-                        if (_this.progressCallback) {
-                            _this.progressCallback(progress);
+                this.reload();
+            }
+        };
+        FilesInput.prototype.reload = function () {
+            var _this = this;
+            var that = this;
+            // If a ".babylon" file has been provided
+            if (this._sceneFileToLoad) {
+                if (this._currentScene) {
+                    this._engine.stopRenderLoop();
+                    this._currentScene.dispose();
+                }
+                BABYLON.SceneLoader.Load("file:", this._sceneFileToLoad, this._engine, function (newScene) {
+                    that._currentScene = newScene;
+                    // Wait for textures and shaders to be ready
+                    that._currentScene.executeWhenReady(function () {
+                        // Attach camera to canvas inputs
+                        if (!that._currentScene.activeCamera || that._currentScene.lights.length === 0) {
+                            that._currentScene.createDefaultCameraOrLight();
                         }
                         }
+                        that._currentScene.activeCamera.attachControl(that._canvas);
+                        if (that._sceneLoadedCallback) {
+                            that._sceneLoadedCallback(_this._sceneFileToLoad, that._currentScene);
+                        }
+                        that._engine.runRenderLoop(function () {
+                            that.renderFunction();
+                        });
                     });
                     });
-                }
-                else {
-                    BABYLON.Tools.Error("Please provide a valid .babylon file.");
-                }
+                }, function (progress) {
+                    if (_this._progressCallback) {
+                        _this._progressCallback(progress);
+                    }
+                });
+            }
+            else {
+                BABYLON.Tools.Error("Please provide a valid .babylon file.");
             }
             }
         };
         };
         FilesInput.FilesTextures = new Array();
         FilesInput.FilesTextures = new Array();

+ 77 - 71
Babylon/Tools/babylon.filesInput.ts

@@ -1,54 +1,57 @@
 module BABYLON {
 module BABYLON {
     export class FilesInput {
     export class FilesInput {
-        private engine: Engine;
-        private currentScene: Scene;
-        private canvas: HTMLCanvasElement;
-        private sceneLoadedCallback;
-        private progressCallback;
-        private additionnalRenderLoopLogicCallback;
-        private textureLoadingCallback;
-        private startingProcessingFilesCallback;
-        private elementToMonitor: HTMLElement;
+        private _engine: Engine;
+        private _currentScene: Scene;
+        private _canvas: HTMLCanvasElement;
+        private _sceneLoadedCallback;
+        private _progressCallback;
+        private _additionnalRenderLoopLogicCallback;
+        private _textureLoadingCallback;
+        private _startingProcessingFilesCallback;
+        private _elementToMonitor: HTMLElement;
         public static FilesTextures: any[] = new Array();
         public static FilesTextures: any[] = new Array();
         public static FilesToLoad: any[] = new Array();
         public static FilesToLoad: any[] = new Array();
 
 
+        private _sceneFileToLoad: File;
+        private _filesToLoad: File[];
+
         /// Register to core BabylonJS object: engine, scene, rendering canvas, callback function when the scene will be loaded,
         /// Register to core BabylonJS object: engine, scene, rendering canvas, callback function when the scene will be loaded,
         /// loading progress callback and optionnal addionnal logic to call in the rendering loop
         /// loading progress callback and optionnal addionnal logic to call in the rendering loop
         constructor(p_engine: Engine, p_scene: Scene, p_canvas: HTMLCanvasElement, p_sceneLoadedCallback,
         constructor(p_engine: Engine, p_scene: Scene, p_canvas: HTMLCanvasElement, p_sceneLoadedCallback,
             p_progressCallback, p_additionnalRenderLoopLogicCallback, p_textureLoadingCallback, p_startingProcessingFilesCallback) {
             p_progressCallback, p_additionnalRenderLoopLogicCallback, p_textureLoadingCallback, p_startingProcessingFilesCallback) {
-            this.engine = p_engine;
-            this.canvas = p_canvas;
-            this.currentScene = p_scene;
-            this.sceneLoadedCallback = p_sceneLoadedCallback;
-            this.progressCallback = p_progressCallback;
-            this.additionnalRenderLoopLogicCallback = p_additionnalRenderLoopLogicCallback;
-            this.textureLoadingCallback = p_textureLoadingCallback;
-            this.startingProcessingFilesCallback = p_startingProcessingFilesCallback;
+            this._engine = p_engine;
+            this._canvas = p_canvas;
+            this._currentScene = p_scene;
+            this._sceneLoadedCallback = p_sceneLoadedCallback;
+            this._progressCallback = p_progressCallback;
+            this._additionnalRenderLoopLogicCallback = p_additionnalRenderLoopLogicCallback;
+            this._textureLoadingCallback = p_textureLoadingCallback;
+            this._startingProcessingFilesCallback = p_startingProcessingFilesCallback;
         }
         }
 
 
         public monitorElementForDragNDrop(p_elementToMonitor: HTMLElement): void {
         public monitorElementForDragNDrop(p_elementToMonitor: HTMLElement): void {
             if (p_elementToMonitor) {
             if (p_elementToMonitor) {
-                this.elementToMonitor = p_elementToMonitor;
-                this.elementToMonitor.addEventListener("dragenter", (e) => { this.drag(e); }, false);
-                this.elementToMonitor.addEventListener("dragover", (e) => { this.drag(e); }, false);
-                this.elementToMonitor.addEventListener("drop", (e) => { this.drop(e); }, false);
+                this._elementToMonitor = p_elementToMonitor;
+                this._elementToMonitor.addEventListener("dragenter", (e) => { this.drag(e); }, false);
+                this._elementToMonitor.addEventListener("dragover", (e) => { this.drag(e); }, false);
+                this._elementToMonitor.addEventListener("drop", (e) => { this.drop(e); }, false);
             }
             }
         }
         }
 
 
         private renderFunction(): void {
         private renderFunction(): void {
-            if (this.additionnalRenderLoopLogicCallback) {
-                this.additionnalRenderLoopLogicCallback();
+            if (this._additionnalRenderLoopLogicCallback) {
+                this._additionnalRenderLoopLogicCallback();
             }
             }
 
 
-            if (this.currentScene) {
-                if (this.textureLoadingCallback) {
-                    var remaining = this.currentScene.getWaitingItemsCount();
+            if (this._currentScene) {
+                if (this._textureLoadingCallback) {
+                    var remaining = this._currentScene.getWaitingItemsCount();
 
 
                     if (remaining > 0) {
                     if (remaining > 0) {
-                        this.textureLoadingCallback(remaining);
+                        this._textureLoadingCallback(remaining);
                     }
                     }
                 }
                 }
-                this.currentScene.render();
+                this._currentScene.render();
             }
             }
         }
         }
 
 
@@ -64,30 +67,26 @@
             this.loadFiles(eventDrop);
             this.loadFiles(eventDrop);
         }
         }
 
 
-        private loadFiles(event): void {
-            var that = this;
-            if (this.startingProcessingFilesCallback) this.startingProcessingFilesCallback();
-
-            var sceneFileToLoad: File;
-            var filesToLoad: File[];
+        public loadFiles(event): void {
+            if (this._startingProcessingFilesCallback) this._startingProcessingFilesCallback();
 
 
             // Handling data transfer via drag'n'drop
             // Handling data transfer via drag'n'drop
             if (event && event.dataTransfer && event.dataTransfer.files) {
             if (event && event.dataTransfer && event.dataTransfer.files) {
-                filesToLoad = event.dataTransfer.files;
+                this._filesToLoad = event.dataTransfer.files;
             }
             }
 
 
             // Handling files from input files
             // Handling files from input files
             if (event && event.target && event.target.files) {
             if (event && event.target && event.target.files) {
-                filesToLoad = event.target.files;
+                this._filesToLoad = event.target.files;
             }
             }
 
 
-            if (filesToLoad && filesToLoad.length > 0) {
-                for (var i = 0; i < filesToLoad.length; i++) {
-                    switch (filesToLoad[i].type) {
+            if (this._filesToLoad && this._filesToLoad.length > 0) {
+                for (var i = 0; i < this._filesToLoad.length; i++) {
+                    switch (this._filesToLoad[i].type) {
                         case "image/jpeg":
                         case "image/jpeg":
                         case "image/png":
                         case "image/png":
                         case "image/bmp":
                         case "image/bmp":
-                            FilesInput.FilesTextures[filesToLoad[i].name] = filesToLoad[i];
+                            FilesInput.FilesTextures[this._filesToLoad[i].name] = this._filesToLoad[i];
                             break;
                             break;
                         case "image/targa":
                         case "image/targa":
                         case "image/vnd.ms-dds":
                         case "image/vnd.ms-dds":
@@ -98,48 +97,55 @@
                         case "audio/mpeg3":
                         case "audio/mpeg3":
                         case "audio/x-mpeg-3":
                         case "audio/x-mpeg-3":
                         case "audio/ogg":
                         case "audio/ogg":
-                            FilesInput.FilesToLoad[filesToLoad[i].name] = filesToLoad[i];
+                            FilesInput.FilesToLoad[this._filesToLoad[i].name] = this._filesToLoad[i];
                             break;
                             break;
                         default:
                         default:
-                            if (filesToLoad[i].name.indexOf(".babylon") !== -1 && filesToLoad[i].name.indexOf(".manifest") === -1
-                                && filesToLoad[i].name.indexOf(".incremental") === -1 && filesToLoad[i].name.indexOf(".babylonmeshdata") === -1
-                                && filesToLoad[i].name.indexOf(".babylongeometrydata") === -1) {
-                                sceneFileToLoad = filesToLoad[i];
+                            if (this._filesToLoad[i].name.indexOf(".babylon") !== -1 && this._filesToLoad[i].name.indexOf(".manifest") === -1
+                                && this._filesToLoad[i].name.indexOf(".incremental") === -1 && this._filesToLoad[i].name.indexOf(".babylonmeshdata") === -1
+                                && this._filesToLoad[i].name.indexOf(".babylongeometrydata") === -1) {
+                                this._sceneFileToLoad = this._filesToLoad[i];
                             }
                             }
                             break;
                             break;
                     }
                     }
                 }
                 }
 
 
-                // If a ".babylon" file has been provided
-                if (sceneFileToLoad) {
-                    if (this.currentScene) {
-                        this.engine.stopRenderLoop();
-                        this.currentScene.dispose();
-                    }
+                this.reload();
+            }
+        }
 
 
-                    SceneLoader.Load("file:", sceneFileToLoad, this.engine, (newScene) => {
-                        that.currentScene = newScene;
+        public reload() {
+            var that = this;
+            // If a ".babylon" file has been provided
+            if (this._sceneFileToLoad) {
+                if (this._currentScene) {
+                    this._engine.stopRenderLoop();
+                    this._currentScene.dispose();
+                }
 
 
-                        // Wait for textures and shaders to be ready
-                        that.currentScene.executeWhenReady(() => {
-                            // Attach camera to canvas inputs
-                            if (that.currentScene.activeCamera) {
-                                that.currentScene.activeCamera.attachControl(that.canvas);
-                            }
-                            if (that.sceneLoadedCallback) {
-                                that.sceneLoadedCallback(sceneFileToLoad, that.currentScene);
-                            }
-                            that.engine.runRenderLoop(() => { that.renderFunction(); });
-                        });
-                    }, progress => {
-                        if (this.progressCallback) {
-                            this.progressCallback(progress);
+                SceneLoader.Load("file:", this._sceneFileToLoad, this._engine, (newScene) => {
+                    that._currentScene = newScene;
+
+                    // Wait for textures and shaders to be ready
+                    that._currentScene.executeWhenReady(() => {
+                        // Attach camera to canvas inputs
+                        if (!that._currentScene.activeCamera || that._currentScene.lights.length === 0) {     
+                            that._currentScene.createDefaultCameraOrLight();
                         }
                         }
+                        that._currentScene.activeCamera.attachControl(that._canvas);
+
+                        if (that._sceneLoadedCallback) {
+                            that._sceneLoadedCallback(this._sceneFileToLoad, that._currentScene);
+                        }
+                        that._engine.runRenderLoop(() => { that.renderFunction(); });
                     });
                     });
-                }
-                else {
-                    Tools.Error("Please provide a valid .babylon file.");
-                }
+                }, progress => {
+                        if (this._progressCallback) {
+                            this._progressCallback(progress);
+                        }
+                    });
+            }
+            else {
+                Tools.Error("Please provide a valid .babylon file.");
             }
             }
         }
         }
     }
     }

+ 55 - 48
Babylon/Tools/babylon.tools.js

@@ -228,6 +228,10 @@ var BABYLON;
         };
         };
         Tools.ReadFile = function (fileToLoad, callback, progressCallBack, useArrayBuffer) {
         Tools.ReadFile = function (fileToLoad, callback, progressCallBack, useArrayBuffer) {
             var reader = new FileReader();
             var reader = new FileReader();
+            reader.onerror = function (e) {
+                Tools.Log("Error while reading file: " + fileToLoad.name);
+                callback(JSON.stringify({ autoClear: true, clearColor: [1, 0, 0], ambientColor: [0, 0, 0], gravity: [0, -9.81, 0], meshes: [], cameras: [], lights: [] }));
+            };
             reader.onload = function (e) {
             reader.onload = function (e) {
                 //target doesn't have result from ts 1.3
                 //target doesn't have result from ts 1.3
                 callback(e.target['result']);
                 callback(e.target['result']);
@@ -349,6 +353,56 @@ var BABYLON;
                 }
                 }
             }
             }
         };
         };
+        Tools.DumpFramebuffer = function (width, height, engine) {
+            // Read the contents of the framebuffer
+            var numberOfChannelsByLine = width * 4;
+            var halfHeight = height / 2;
+            //Reading datas from WebGL
+            var data = engine.readPixels(0, 0, width, height);
+            for (var i = 0; i < halfHeight; i++) {
+                for (var j = 0; j < numberOfChannelsByLine; j++) {
+                    var currentCell = j + i * numberOfChannelsByLine;
+                    var targetLine = height - i - 1;
+                    var targetCell = j + targetLine * numberOfChannelsByLine;
+                    var temp = data[currentCell];
+                    data[currentCell] = data[targetCell];
+                    data[targetCell] = temp;
+                }
+            }
+            // Create a 2D canvas to store the result
+            if (!screenshotCanvas) {
+                screenshotCanvas = document.createElement('canvas');
+            }
+            screenshotCanvas.width = width;
+            screenshotCanvas.height = height;
+            var context = screenshotCanvas.getContext('2d');
+            // Copy the pixels to a 2D canvas
+            var imageData = context.createImageData(width, height);
+            //cast is due to ts error in lib.d.ts, see here - https://github.com/Microsoft/TypeScript/issues/949
+            var castData = imageData.data;
+            castData.set(data);
+            context.putImageData(imageData, 0, 0);
+            var base64Image = screenshotCanvas.toDataURL();
+            //Creating a link if the browser have the download attribute on the a tag, to automatically start download generated image.
+            if (("download" in document.createElement("a"))) {
+                var a = window.document.createElement("a");
+                a.href = base64Image;
+                var date = new Date();
+                var stringDate = date.getFullYear() + "/" + date.getMonth() + "/" + date.getDate() + "-" + date.getHours() + ":" + date.getMinutes();
+                a.setAttribute("download", "screenshot-" + stringDate + ".png");
+                window.document.body.appendChild(a);
+                a.addEventListener("click", function () {
+                    a.parentElement.removeChild(a);
+                });
+                a.click();
+            }
+            else {
+                var newWindow = window.open("");
+                var img = newWindow.document.createElement("img");
+                img.src = base64Image;
+                newWindow.document.body.appendChild(img);
+            }
+        };
         Tools.CreateScreenshot = function (engine, camera, size) {
         Tools.CreateScreenshot = function (engine, camera, size) {
             var width;
             var width;
             var height;
             var height;
@@ -390,54 +444,7 @@ var BABYLON;
             var texture = new BABYLON.RenderTargetTexture("screenShot", size, scene, false, false);
             var texture = new BABYLON.RenderTargetTexture("screenShot", size, scene, false, false);
             texture.renderList = scene.meshes;
             texture.renderList = scene.meshes;
             texture.onAfterRender = function () {
             texture.onAfterRender = function () {
-                // Read the contents of the framebuffer
-                var numberOfChannelsByLine = width * 4;
-                var halfHeight = height / 2;
-                //Reading datas from WebGL
-                var data = engine.readPixels(0, 0, width, height);
-                for (var i = 0; i < halfHeight; i++) {
-                    for (var j = 0; j < numberOfChannelsByLine; j++) {
-                        var currentCell = j + i * numberOfChannelsByLine;
-                        var targetLine = height - i - 1;
-                        var targetCell = j + targetLine * numberOfChannelsByLine;
-                        var temp = data[currentCell];
-                        data[currentCell] = data[targetCell];
-                        data[targetCell] = temp;
-                    }
-                }
-                // Create a 2D canvas to store the result
-                if (!screenshotCanvas) {
-                    screenshotCanvas = document.createElement('canvas');
-                }
-                screenshotCanvas.width = width;
-                screenshotCanvas.height = height;
-                var context = screenshotCanvas.getContext('2d');
-                // Copy the pixels to a 2D canvas
-                var imageData = context.createImageData(width, height);
-                //cast is due to ts error in lib.d.ts, see here - https://github.com/Microsoft/TypeScript/issues/949
-                var data = imageData.data;
-                data.set(data);
-                context.putImageData(imageData, 0, 0);
-                var base64Image = screenshotCanvas.toDataURL();
-                //Creating a link if the browser have the download attribute on the a tag, to automatically start download generated image.
-                if (("download" in document.createElement("a"))) {
-                    var a = window.document.createElement("a");
-                    a.href = base64Image;
-                    var date = new Date();
-                    var stringDate = date.getFullYear() + "/" + date.getMonth() + "/" + date.getDate() + "-" + date.getHours() + ":" + date.getMinutes();
-                    a.setAttribute("download", "screenshot-" + stringDate + ".png");
-                    window.document.body.appendChild(a);
-                    a.addEventListener("click", function () {
-                        a.parentElement.removeChild(a);
-                    });
-                    a.click();
-                }
-                else {
-                    var newWindow = window.open("");
-                    var img = newWindow.document.createElement("img");
-                    img.src = base64Image;
-                    newWindow.document.body.appendChild(img);
-                }
+                Tools.DumpFramebuffer(width, height, engine);
             };
             };
             scene.incrementRenderId();
             scene.incrementRenderId();
             texture.render(true);
             texture.render(true);

+ 67 - 60
Babylon/Tools/babylon.tools.ts

@@ -294,6 +294,10 @@
 
 
         public static ReadFile(fileToLoad, callback, progressCallBack, useArrayBuffer?: boolean): void {
         public static ReadFile(fileToLoad, callback, progressCallBack, useArrayBuffer?: boolean): void {
             var reader = new FileReader();
             var reader = new FileReader();
+            reader.onerror = e => {
+                Tools.Log("Error while reading file: " + fileToLoad.name);
+                callback(JSON.stringify({ autoClear: true, clearColor: [1, 0, 0], ambientColor: [0, 0, 0], gravity: [0, -9.81, 0], meshes: [], cameras: [], lights: []}));
+            };
             reader.onload = e => {
             reader.onload = e => {
                 //target doesn't have result from ts 1.3
                 //target doesn't have result from ts 1.3
                 callback(e.target['result']);
                 callback(e.target['result']);
@@ -429,6 +433,68 @@
             }
             }
         }
         }
 
 
+        public static DumpFramebuffer(width: number, height: number, engine: Engine): void {
+            // Read the contents of the framebuffer
+            var numberOfChannelsByLine = width * 4;
+            var halfHeight = height / 2;
+
+            //Reading datas from WebGL
+            var data = engine.readPixels(0, 0, width, height);
+
+            //To flip image on Y axis.
+            for (var i = 0; i < halfHeight; i++) {
+                for (var j = 0; j < numberOfChannelsByLine; j++) {
+                    var currentCell = j + i * numberOfChannelsByLine;
+                    var targetLine = height - i - 1;
+                    var targetCell = j + targetLine * numberOfChannelsByLine;
+
+                    var temp = data[currentCell];
+                    data[currentCell] = data[targetCell];
+                    data[targetCell] = temp;
+                }
+            }
+
+            // Create a 2D canvas to store the result
+            if (!screenshotCanvas) {
+                screenshotCanvas = document.createElement('canvas');
+            }
+            screenshotCanvas.width = width;
+            screenshotCanvas.height = height;
+            var context = screenshotCanvas.getContext('2d');
+
+            // Copy the pixels to a 2D canvas
+            var imageData = context.createImageData(width, height);
+            //cast is due to ts error in lib.d.ts, see here - https://github.com/Microsoft/TypeScript/issues/949
+            var castData = <Uint8Array> (<any> imageData.data);
+            castData.set(data);
+            context.putImageData(imageData, 0, 0);
+
+            var base64Image = screenshotCanvas.toDataURL();
+
+            //Creating a link if the browser have the download attribute on the a tag, to automatically start download generated image.
+            if (("download" in document.createElement("a"))) {
+                var a = window.document.createElement("a");
+                a.href = base64Image;
+                var date = new Date();
+                var stringDate = date.getFullYear() + "/" + date.getMonth() + "/" + date.getDate() + "-" + date.getHours() + ":" + date.getMinutes();
+                a.setAttribute("download", "screenshot-" + stringDate + ".png");
+
+                window.document.body.appendChild(a);
+
+                a.addEventListener("click",() => {
+                    a.parentElement.removeChild(a);
+                });
+                a.click();
+
+                //Or opening a new tab with the image if it is not possible to automatically start download.
+            } else {
+                var newWindow = window.open("");
+                var img = newWindow.document.createElement("img");
+                img.src = base64Image;
+                newWindow.document.body.appendChild(img);
+            }
+        }
+
         public static CreateScreenshot(engine: Engine, camera: Camera, size: any): void {
         public static CreateScreenshot(engine: Engine, camera: Camera, size: any): void {
             var width: number;
             var width: number;
             var height: number;
             var height: number;
@@ -478,66 +544,7 @@
             texture.renderList = scene.meshes;
             texture.renderList = scene.meshes;
 
 
             texture.onAfterRender = () => {
             texture.onAfterRender = () => {
-                // Read the contents of the framebuffer
-                var numberOfChannelsByLine = width * 4;
-                var halfHeight = height / 2;
-
-                //Reading datas from WebGL
-                var data = engine.readPixels(0, 0, width, height);
-
-                //To flip image on Y axis.
-                for (var i = 0; i < halfHeight; i++) {
-                    for (var j = 0; j < numberOfChannelsByLine; j++) {
-                        var currentCell = j + i * numberOfChannelsByLine;
-                        var targetLine = height - i - 1;
-                        var targetCell = j + targetLine * numberOfChannelsByLine;
-
-                        var temp = data[currentCell];
-                        data[currentCell] = data[targetCell];
-                        data[targetCell] = temp;
-                    }
-                }
-
-                // Create a 2D canvas to store the result
-                if (!screenshotCanvas) {
-                    screenshotCanvas = document.createElement('canvas');
-                }
-                screenshotCanvas.width = width;
-                screenshotCanvas.height = height;
-                var context = screenshotCanvas.getContext('2d');
-
-                // Copy the pixels to a 2D canvas
-                var imageData = context.createImageData(width, height);
-                //cast is due to ts error in lib.d.ts, see here - https://github.com/Microsoft/TypeScript/issues/949
-                var data = <Uint8Array> (<any> imageData.data);
-                data.set(data);
-                context.putImageData(imageData, 0, 0);
-
-                var base64Image = screenshotCanvas.toDataURL();
-
-                //Creating a link if the browser have the download attribute on the a tag, to automatically start download generated image.
-                if (("download" in document.createElement("a"))) {
-                    var a = window.document.createElement("a");
-                    a.href = base64Image;
-                    var date = new Date();
-                    var stringDate = date.getFullYear() + "/" + date.getMonth() + "/" + date.getDate() + "-" + date.getHours() + ":" + date.getMinutes();
-                    a.setAttribute("download", "screenshot-" + stringDate + ".png");
-
-                    window.document.body.appendChild(a);
-
-                    a.addEventListener("click",() => {
-                        a.parentElement.removeChild(a);
-                    });
-                    a.click();
-
-                    //Or opening a new tab with the image if it is not possible to automatically start download.
-                } else {
-                    var newWindow = window.open("");
-                    var img = newWindow.document.createElement("img");
-                    img.src = base64Image;
-                    newWindow.document.body.appendChild(img);
-                }
-
+                Tools.DumpFramebuffer(width, height, engine);
             };
             };
 
 
             scene.incrementRenderId();
             scene.incrementRenderId();

+ 69 - 7
Babylon/babylon.scene.js

@@ -91,6 +91,7 @@ var BABYLON;
             this.postProcessesEnabled = true;
             this.postProcessesEnabled = true;
             // Customs render targets
             // Customs render targets
             this.renderTargetsEnabled = true;
             this.renderTargetsEnabled = true;
+            this.dumpNextRenderTargets = false;
             this.customRenderTargets = new Array();
             this.customRenderTargets = new Array();
             // Imported meshes
             // Imported meshes
             this.importedMeshesFiles = new Array();
             this.importedMeshesFiles = new Array();
@@ -100,6 +101,7 @@ var BABYLON;
             this.proceduralTexturesEnabled = true;
             this.proceduralTexturesEnabled = true;
             this._proceduralTextures = new Array();
             this._proceduralTextures = new Array();
             this.soundTracks = new Array();
             this.soundTracks = new Array();
+            this._audioEnabled = true;
             this._totalVertices = 0;
             this._totalVertices = 0;
             this._activeVertices = 0;
             this._activeVertices = 0;
             this._activeParticles = 0;
             this._activeParticles = 0;
@@ -917,7 +919,7 @@ var BABYLON;
                     var renderTarget = this._renderTargets.data[renderIndex];
                     var renderTarget = this._renderTargets.data[renderIndex];
                     if (renderTarget._shouldRender()) {
                     if (renderTarget._shouldRender()) {
                         this._renderId++;
                         this._renderId++;
-                        renderTarget.render();
+                        renderTarget.render(false, this.dumpNextRenderTargets);
                     }
                     }
                 }
                 }
                 BABYLON.Tools.EndPerformanceCounter("Render targets", this._renderTargets.length > 0);
                 BABYLON.Tools.EndPerformanceCounter("Render targets", this._renderTargets.length > 0);
@@ -1076,7 +1078,7 @@ var BABYLON;
                         engine.setViewport(this.activeCamera.viewport);
                         engine.setViewport(this.activeCamera.viewport);
                         // Camera
                         // Camera
                         this.updateTransformMatrix();
                         this.updateTransformMatrix();
-                        renderTarget.render();
+                        renderTarget.render(false, this.dumpNextRenderTargets);
                     }
                     }
                 }
                 }
                 BABYLON.Tools.EndPerformanceCounter("Custom render targets", this.customRenderTargets.length > 0);
                 BABYLON.Tools.EndPerformanceCounter("Custom render targets", this.customRenderTargets.length > 0);
@@ -1146,11 +1148,14 @@ var BABYLON;
                 this._toBeDisposed[index] = null;
                 this._toBeDisposed[index] = null;
             }
             }
             this._toBeDisposed.reset();
             this._toBeDisposed.reset();
+            if (this.dumpNextRenderTargets) {
+                this.dumpNextRenderTargets = false;
+            }
             BABYLON.Tools.EndPerformanceCounter("Scene rendering");
             BABYLON.Tools.EndPerformanceCounter("Scene rendering");
             this._lastFrameDuration = BABYLON.Tools.Now - startDate;
             this._lastFrameDuration = BABYLON.Tools.Now - startDate;
         };
         };
         Scene.prototype._updateAudioParameters = function () {
         Scene.prototype._updateAudioParameters = function () {
-            if (this.mainSoundTrack.soundCollection.length === 0 && this.soundTracks.length === 0) {
+            if (!this.audioEnabled || (this.mainSoundTrack.soundCollection.length === 0 && this.soundTracks.length === 0)) {
                 return;
                 return;
             }
             }
             var listeningCamera;
             var listeningCamera;
@@ -1183,6 +1188,46 @@ var BABYLON;
                 }
                 }
             }
             }
         };
         };
+        Object.defineProperty(Scene.prototype, "audioEnabled", {
+            get: function () {
+                return this._audioEnabled;
+            },
+            set: function (value) {
+                this._audioEnabled = value;
+                if (this._audioEnabled) {
+                    this._enableAudio();
+                }
+                else {
+                    this._disableAudio();
+                }
+            },
+            enumerable: true,
+            configurable: true
+        });
+        Scene.prototype._disableAudio = function () {
+            for (var i = 0; i < this.mainSoundTrack.soundCollection.length; i++) {
+                this.mainSoundTrack.soundCollection[i].pause();
+            }
+            for (i = 0; i < this.soundTracks.length; i++) {
+                for (var j = 0; j < this.soundTracks[i].soundCollection.length; j++) {
+                    this.soundTracks[i].soundCollection[j].pause();
+                }
+            }
+        };
+        Scene.prototype._enableAudio = function () {
+            for (var i = 0; i < this.mainSoundTrack.soundCollection.length; i++) {
+                if (this.mainSoundTrack.soundCollection[i].isPaused) {
+                    this.mainSoundTrack.soundCollection[i].play();
+                }
+            }
+            for (i = 0; i < this.soundTracks.length; i++) {
+                for (var j = 0; j < this.soundTracks[i].soundCollection.length; j++) {
+                    if (this.soundTracks[i].soundCollection[j].isPaused) {
+                        this.soundTracks[i].soundCollection[j].play();
+                    }
+                }
+            }
+        };
         Scene.prototype.enableDepthRenderer = function () {
         Scene.prototype.enableDepthRenderer = function () {
             if (this._depthRenderer) {
             if (this._depthRenderer) {
                 return this._depthRenderer;
                 return this._depthRenderer;
@@ -1215,10 +1260,7 @@ var BABYLON;
             this._onAfterRenderCallbacks = [];
             this._onAfterRenderCallbacks = [];
             this.detachControl();
             this.detachControl();
             // Release sounds & sounds tracks
             // Release sounds & sounds tracks
-            this.mainSoundTrack.dispose();
-            for (var scIndex = 0; scIndex < this.soundTracks.length; scIndex++) {
-                this.soundTracks[scIndex].dispose();
-            }
+            this.disposeSounds();
             // Detach cameras
             // Detach cameras
             var canvas = this._engine.getRenderingCanvas();
             var canvas = this._engine.getRenderingCanvas();
             var index;
             var index;
@@ -1262,6 +1304,13 @@ var BABYLON;
             }
             }
             this._engine.wipeCaches();
             this._engine.wipeCaches();
         };
         };
+        // Release sounds & sounds tracks
+        Scene.prototype.disposeSounds = function () {
+            this.mainSoundTrack.dispose();
+            for (var scIndex = 0; scIndex < this.soundTracks.length; scIndex++) {
+                this.soundTracks[scIndex].dispose();
+            }
+        };
         // Collisions
         // Collisions
         Scene.prototype._getNewPosition = function (position, velocity, collider, maximumRetry, finalPosition, excludedMesh) {
         Scene.prototype._getNewPosition = function (position, velocity, collider, maximumRetry, finalPosition, excludedMesh) {
             if (excludedMesh === void 0) { excludedMesh = null; }
             if (excludedMesh === void 0) { excludedMesh = null; }
@@ -1510,6 +1559,19 @@ var BABYLON;
         Scene.prototype.getMaterialByTags = function (tagsQuery, forEach) {
         Scene.prototype.getMaterialByTags = function (tagsQuery, forEach) {
             return this._getByTags(this.materials, tagsQuery, forEach).concat(this._getByTags(this.multiMaterials, tagsQuery, forEach));
             return this._getByTags(this.materials, tagsQuery, forEach).concat(this._getByTags(this.multiMaterials, tagsQuery, forEach));
         };
         };
+        // Audio
+        Scene.prototype.switchAudioModeForHeadphones = function () {
+            this.mainSoundTrack.switchPanningModelToHRTF();
+            for (var i = 0; i < this.soundTracks.length; i++) {
+                this.soundTracks[i].switchPanningModelToHRTF();
+            }
+        };
+        Scene.prototype.switchAudioModeForNormalSpeakers = function () {
+            this.mainSoundTrack.switchPanningModelToEqualPower();
+            for (var i = 0; i < this.soundTracks.length; i++) {
+                this.soundTracks[i].switchPanningModelToEqualPower();
+            }
+        };
         // Statics
         // Statics
         Scene._FOGMODE_NONE = 0;
         Scene._FOGMODE_NONE = 0;
         Scene._FOGMODE_EXP = 1;
         Scene._FOGMODE_EXP = 1;

+ 77 - 8
Babylon/babylon.scene.ts

@@ -162,6 +162,7 @@
 
 
         // Customs render targets
         // Customs render targets
         public renderTargetsEnabled = true;
         public renderTargetsEnabled = true;
+        public dumpNextRenderTargets = false;
         public customRenderTargets = new Array<RenderTargetTexture>();
         public customRenderTargets = new Array<RenderTargetTexture>();
 
 
         // Delay loading
         // Delay loading
@@ -189,6 +190,7 @@
         // Sound Tracks
         // Sound Tracks
         public mainSoundTrack: SoundTrack;
         public mainSoundTrack: SoundTrack;
         public soundTracks = new Array<SoundTrack>();
         public soundTracks = new Array<SoundTrack>();
+        private _audioEnabled = true;
 
 
         // Private
         // Private
         private _engine: Engine;
         private _engine: Engine;
@@ -1186,10 +1188,12 @@
                     var renderTarget = this._renderTargets.data[renderIndex];
                     var renderTarget = this._renderTargets.data[renderIndex];
                     if (renderTarget._shouldRender()) {
                     if (renderTarget._shouldRender()) {
                         this._renderId++;
                         this._renderId++;
-                        renderTarget.render();
+                        renderTarget.render(false, this.dumpNextRenderTargets);
                     }
                     }
                 }
                 }
                 Tools.EndPerformanceCounter("Render targets", this._renderTargets.length > 0);
                 Tools.EndPerformanceCounter("Render targets", this._renderTargets.length > 0);
+
+
                 this._renderId++;
                 this._renderId++;
             }
             }
 
 
@@ -1381,7 +1385,7 @@
                         // Camera
                         // Camera
                         this.updateTransformMatrix();
                         this.updateTransformMatrix();
 
 
-                        renderTarget.render();
+                        renderTarget.render(false, this.dumpNextRenderTargets);
                     }
                     }
                 }
                 }
                 Tools.EndPerformanceCounter("Custom render targets", this.customRenderTargets.length > 0);
                 Tools.EndPerformanceCounter("Custom render targets", this.customRenderTargets.length > 0);
@@ -1468,13 +1472,16 @@
 
 
             this._toBeDisposed.reset();
             this._toBeDisposed.reset();
 
 
+            if (this.dumpNextRenderTargets) {
+                this.dumpNextRenderTargets = false;
+            }
 
 
             Tools.EndPerformanceCounter("Scene rendering");
             Tools.EndPerformanceCounter("Scene rendering");
             this._lastFrameDuration = Tools.Now - startDate;
             this._lastFrameDuration = Tools.Now - startDate;
         }
         }
 
 
         private _updateAudioParameters() {
         private _updateAudioParameters() {
-            if (this.mainSoundTrack.soundCollection.length === 0 && this.soundTracks.length === 0) {
+            if (!this.audioEnabled || (this.mainSoundTrack.soundCollection.length === 0 && this.soundTracks.length === 0)) {
                 return;
                 return;
             }
             }
 
 
@@ -1510,6 +1517,46 @@
             }
             }
         }
         }
 
 
+        public get audioEnabled(): boolean {
+            return this._audioEnabled;
+        }
+
+        public set audioEnabled(value: boolean) {
+            this._audioEnabled = value;
+            if (this._audioEnabled) {
+                this._enableAudio();
+                }
+            else {
+                this._disableAudio();
+            }
+        }
+
+        private _disableAudio() {
+            for (var i = 0; i < this.mainSoundTrack.soundCollection.length; i++) {
+                this.mainSoundTrack.soundCollection[i].pause();
+            }
+            for (i = 0; i < this.soundTracks.length; i++) {
+                for (var j = 0; j < this.soundTracks[i].soundCollection.length; j++) {
+                    this.soundTracks[i].soundCollection[j].pause();
+                }
+            }
+        }
+
+        private _enableAudio() {
+            for (var i = 0; i < this.mainSoundTrack.soundCollection.length; i++) {
+                if (this.mainSoundTrack.soundCollection[i].isPaused) {
+                    this.mainSoundTrack.soundCollection[i].play();
+                }
+            }
+            for (i = 0; i < this.soundTracks.length; i++) {
+                for (var j = 0; j < this.soundTracks[i].soundCollection.length; j++) {
+                    if (this.soundTracks[i].soundCollection[j].isPaused) {
+                        this.soundTracks[i].soundCollection[j].play();
+                    }
+                }
+            }
+        }
+
         public enableDepthRenderer(): DepthRenderer {
         public enableDepthRenderer(): DepthRenderer {
             if (this._depthRenderer) {
             if (this._depthRenderer) {
                 return this._depthRenderer;
                 return this._depthRenderer;
@@ -1555,11 +1602,7 @@
             this.detachControl();
             this.detachControl();
 
 
             // Release sounds & sounds tracks
             // Release sounds & sounds tracks
-            this.mainSoundTrack.dispose();
-
-            for (var scIndex = 0; scIndex < this.soundTracks.length; scIndex++) {
-                this.soundTracks[scIndex].dispose();
-            }
+            this.disposeSounds();
 
 
             // Detach cameras
             // Detach cameras
             var canvas = this._engine.getRenderingCanvas();
             var canvas = this._engine.getRenderingCanvas();
@@ -1626,6 +1669,15 @@
             this._engine.wipeCaches();
             this._engine.wipeCaches();
         }
         }
 
 
+        // Release sounds & sounds tracks
+        public disposeSounds() {
+            this.mainSoundTrack.dispose();
+
+            for (var scIndex = 0; scIndex < this.soundTracks.length; scIndex++) {
+                this.soundTracks[scIndex].dispose();
+            }
+        }
+
         // Collisions
         // Collisions
         public _getNewPosition(position: Vector3, velocity: Vector3, collider: Collider, maximumRetry: number, finalPosition: Vector3, excludedMesh: AbstractMesh = null): void {
         public _getNewPosition(position: Vector3, velocity: Vector3, collider: Collider, maximumRetry: number, finalPosition: Vector3, excludedMesh: AbstractMesh = null): void {
             position.divideToRef(collider.radius, this._scaledPosition);
             position.divideToRef(collider.radius, this._scaledPosition);
@@ -1935,5 +1987,22 @@
         public getMaterialByTags(tagsQuery: string, forEach?: (material: Material) => void): Material[] {
         public getMaterialByTags(tagsQuery: string, forEach?: (material: Material) => void): Material[] {
             return this._getByTags(this.materials, tagsQuery, forEach).concat(this._getByTags(this.multiMaterials, tagsQuery, forEach));
             return this._getByTags(this.materials, tagsQuery, forEach).concat(this._getByTags(this.multiMaterials, tagsQuery, forEach));
         }
         }
+
+        // Audio
+        public switchAudioModeForHeadphones() {
+            this.mainSoundTrack.switchPanningModelToHRTF();
+
+            for (var i = 0; i < this.soundTracks.length; i++) {
+                this.soundTracks[i].switchPanningModelToHRTF();
+            }
+        }
+
+        public switchAudioModeForNormalSpeakers() {
+            this.mainSoundTrack.switchPanningModelToEqualPower();
+
+            for (var i = 0; i < this.soundTracks.length; i++) {
+                this.soundTracks[i].switchPanningModelToEqualPower();
+            }
+        }
     }
     }
 } 
 } 

File diff suppressed because it is too large
+ 401 - 182
babylon.2.1-alpha.debug.js


File diff suppressed because it is too large
+ 19 - 19
babylon.2.1-alpha.js