فهرست منبع

Fixing bias for shadows filters
Adding more SIMD.js functions

David Catuhe 10 سال پیش
والد
کامیت
e98c6d93d8
32فایلهای تغییر یافته به همراه632 افزوده شده و 381 حذف شده
  1. 12 9
      Babylon/Audio/babylon.sound.js
  2. 12 9
      Babylon/Audio/babylon.sound.ts
  3. 4 4
      Babylon/Debug/babylon.debugLayer.js
  4. 1 1
      Babylon/Debug/babylon.debugLayer.js.map
  5. 4 4
      Babylon/Debug/babylon.debugLayer.ts
  6. 25 1
      Babylon/Lights/Shadows/babylon.shadowGenerator.js
  7. 28 5
      Babylon/Lights/Shadows/babylon.shadowGenerator.ts
  8. 0 1
      Babylon/Loading/Plugins/babylon.babylonFileLoader.js
  9. 0 1
      Babylon/Loading/Plugins/babylon.babylonFileLoader.ts
  10. 11 5
      Babylon/Materials/Textures/babylon.texture.js
  11. 28 20
      Babylon/Materials/Textures/babylon.texture.ts
  12. 24 0
      Babylon/Math/babylon.math.js
  13. 44 10
      Babylon/Math/babylon.math.ts
  14. 2 1
      Babylon/Mesh/babylon.geometry.js
  15. 4 2
      Babylon/Mesh/babylon.geometry.ts
  16. 6 34
      Babylon/Mesh/babylon.mesh.js
  17. 17 41
      Babylon/Mesh/babylon.mesh.ts
  18. 10 3
      Babylon/PostProcess/babylon.volumetricLightScatteringPostProcess.js
  19. 11 3
      Babylon/PostProcess/babylon.volumetricLightScatteringPostProcess.ts
  20. 4 5
      Babylon/Shaders/default.fragment.fx
  21. 2 2
      Babylon/Shaders/depth.vertex.fx
  22. 15 6
      Babylon/Shaders/volumetricLightScatteringPass.fragment.fx
  23. 7 6
      Babylon/Sprites/babylon.spriteManager.js
  24. 12 11
      Babylon/Sprites/babylon.spriteManager.ts
  25. 10 10
      Babylon/Tools/babylon.sceneSerializer.js
  26. 12 12
      Babylon/Tools/babylon.sceneSerializer.ts
  27. 15 8
      Babylon/babylon.engine.js
  28. 20 11
      Babylon/babylon.engine.ts
  29. 30 13
      Babylon/babylon.scene.js
  30. 32 17
      Babylon/babylon.scene.ts
  31. 210 107
      babylon.2.1-alpha.debug.js
  32. 20 19
      babylon.2.1-alpha.js

+ 12 - 9
Babylon/Audio/babylon.sound.js

@@ -18,7 +18,7 @@ var BABYLON;
             this.rolloffFactor = 1;
             this.maxDistance = 100;
             this.distanceModel = "linear";
-            this.panningModel = "HRTF";
+            this._panningModel = "equalpower";
             this._playbackRate = 1;
             this._startTime = 0;
             this._startOffset = 0;
@@ -60,7 +60,6 @@ var BABYLON;
                 this.rolloffFactor = options.rolloffFactor || 1;
                 this.refDistance = options.refDistance || 1;
                 this.distanceModel = options.distanceModel || "linear";
-                this.panningModel = options.panningModel || "HRTF";
                 this._playbackRate = options.playbackRate || 1;
             }
             if (BABYLON.Engine.audioEngine.canUseWebAudio) {
@@ -160,12 +159,14 @@ var BABYLON;
                 this.rolloffFactor = options.rolloffFactor || this.rolloffFactor;
                 this.refDistance = options.refDistance || this.refDistance;
                 this.distanceModel = options.distanceModel || this.distanceModel;
-                this.panningModel = options.panningModel || this.panningModel;
                 this._playbackRate = options.playbackRate || this._playbackRate;
             }
         };
         Sound.prototype._createSpatialParameters = function () {
             if (BABYLON.Engine.audioEngine.canUseWebAudio) {
+                if (this._scene.headphone) {
+                    this._panningModel = "HRTF";
+                }
                 this._soundPanner = BABYLON.Engine.audioEngine.audioContext.createPanner();
                 if (this.useCustomAttenuation) {
                     // Tricks to disable in a way embedded Web Audio attenuation 
@@ -173,28 +174,30 @@ var BABYLON;
                     this._soundPanner.maxDistance = Number.MAX_VALUE;
                     this._soundPanner.refDistance = 1;
                     this._soundPanner.rolloffFactor = 1;
-                    this._soundPanner.panningModel = "HRTF";
+                    this._soundPanner.panningModel = this._panningModel;
                 }
                 else {
                     this._soundPanner.distanceModel = this.distanceModel;
                     this._soundPanner.maxDistance = this.maxDistance;
                     this._soundPanner.refDistance = this.refDistance;
                     this._soundPanner.rolloffFactor = this.rolloffFactor;
-                    this._soundPanner.panningModel = this.panningModel;
+                    this._soundPanner.panningModel = this._panningModel;
                 }
                 this._soundPanner.connect(this._ouputAudioNode);
                 this._inputAudioNode = this._soundPanner;
             }
         };
         Sound.prototype.switchPanningModelToHRTF = function () {
-            this._switchPanningModel("HRTF");
+            this._panningModel = "HRTF";
+            this._switchPanningModel();
         };
         Sound.prototype.switchPanningModelToEqualPower = function () {
-            this._switchPanningModel("equalpower");
+            this._panningModel = "equalpower";
+            this._switchPanningModel();
         };
-        Sound.prototype._switchPanningModel = function (newModel) {
+        Sound.prototype._switchPanningModel = function () {
             if (BABYLON.Engine.audioEngine.canUseWebAudio && this.spatialSound) {
-                this._soundPanner.panningModel = newModel;
+                this._soundPanner.panningModel = this._panningModel;
             }
         };
         Sound.prototype.connectToSoundTrackAudioNode = function (soundTrackAudioNode) {

+ 12 - 9
Babylon/Audio/babylon.sound.ts

@@ -10,7 +10,7 @@
         public rolloffFactor: number = 1;
         public maxDistance: number = 100;
         public distanceModel: string = "linear";
-        public panningModel: string = "HRTF";
+        private _panningModel: string = "equalpower";
         public onended: () => any;
         private _playbackRate: number = 1;
         private _startTime: number = 0;
@@ -73,7 +73,6 @@
                 this.rolloffFactor = options.rolloffFactor || 1;
                 this.refDistance = options.refDistance || 1;
                 this.distanceModel = options.distanceModel || "linear";
-                this.panningModel = options.panningModel || "HRTF";
                 this._playbackRate = options.playbackRate || 1;
             }
 
@@ -170,13 +169,15 @@
                 this.rolloffFactor = options.rolloffFactor || this.rolloffFactor;
                 this.refDistance = options.refDistance || this.refDistance;
                 this.distanceModel = options.distanceModel || this.distanceModel;
-                this.panningModel = options.panningModel || this.panningModel;
                 this._playbackRate = options.playbackRate || this._playbackRate;
             }
         }
 
         private _createSpatialParameters() {
             if (Engine.audioEngine.canUseWebAudio) {
+                if (this._scene.headphone) {
+                    this._panningModel = "HRTF";
+                }
                 this._soundPanner = Engine.audioEngine.audioContext.createPanner();
 
                 if (this.useCustomAttenuation) {
@@ -185,14 +186,14 @@
                     this._soundPanner.maxDistance = Number.MAX_VALUE;
                     this._soundPanner.refDistance = 1;
                     this._soundPanner.rolloffFactor = 1;
-                    this._soundPanner.panningModel = "HRTF";
+                    this._soundPanner.panningModel = this._panningModel;
                 }
                 else {
                     this._soundPanner.distanceModel = this.distanceModel;
                     this._soundPanner.maxDistance = this.maxDistance;
                     this._soundPanner.refDistance = this.refDistance;
                     this._soundPanner.rolloffFactor = this.rolloffFactor;
-                    this._soundPanner.panningModel = this.panningModel;
+                    this._soundPanner.panningModel = this._panningModel;
                 }
                 this._soundPanner.connect(this._ouputAudioNode);
                 this._inputAudioNode = this._soundPanner;
@@ -200,16 +201,18 @@
         }
 
         public switchPanningModelToHRTF() {
-            this._switchPanningModel("HRTF");    
+            this._panningModel = "HRTF";
+            this._switchPanningModel();    
         }
 
         public switchPanningModelToEqualPower() {
-            this._switchPanningModel("equalpower");
+            this._panningModel = "equalpower";
+            this._switchPanningModel();
         }
 
-        private _switchPanningModel(newModel: string) {
+        private _switchPanningModel() {
             if (Engine.audioEngine.canUseWebAudio && this.spatialSound) {
-                this._soundPanner.panningModel = newModel;
+                this._soundPanner.panningModel = this._panningModel;
             }
         }
 

+ 4 - 4
Babylon/Debug/babylon.debugLayer.js

@@ -582,14 +582,14 @@ var BABYLON;
                 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) {
+                    this._generateRadio(this._optionsSubsetDiv, "Headphones", "panningModel", this._scene.headphone, function (element) {
                         if (element.checked) {
-                            _this._scene.switchAudioModeForHeadphones();
+                            _this._scene.headphone = true;
                         }
                     });
-                    this._generateRadio(this._optionsSubsetDiv, "Normal Speakers", "panningModel", false, function (element) {
+                    this._generateRadio(this._optionsSubsetDiv, "Normal Speakers", "panningModel", !this._scene.headphone, function (element) {
                         if (element.checked) {
-                            _this._scene.switchAudioModeForNormalSpeakers();
+                            _this._scene.headphone = false;
                         }
                     });
                     this._generateCheckBox(this._optionsSubsetDiv, "Disable audio", !this._scene.audioEnabled, function (element) {

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 1 - 1
Babylon/Debug/babylon.debugLayer.js.map


+ 4 - 4
Babylon/Debug/babylon.debugLayer.ts

@@ -674,14 +674,14 @@
                 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) => {
+                    this._generateRadio(this._optionsSubsetDiv, "Headphones", "panningModel", this._scene.headphone, (element) => {
                         if (element.checked) {
-                            this._scene.switchAudioModeForHeadphones();
+                            this._scene.headphone = true;
                         }
                     });
-                    this._generateRadio(this._optionsSubsetDiv, "Normal Speakers", "panningModel", false, (element) => {
+                    this._generateRadio(this._optionsSubsetDiv, "Normal Speakers", "panningModel", !this._scene.headphone, (element) => {
                         if (element.checked) {
-                            this._scene.switchAudioModeForNormalSpeakers();
+                            this._scene.headphone = false;
                         }
                     });
                     this._generateCheckBox(this._optionsSubsetDiv, "Disable audio", !this._scene.audioEnabled, (element) => {

+ 25 - 1
Babylon/Lights/Shadows/babylon.shadowGenerator.js

@@ -4,7 +4,7 @@ var BABYLON;
         function ShadowGenerator(mapSize, light) {
             var _this = this;
             // Members
-            this.filter = ShadowGenerator.FILTER_NONE;
+            this._filter = ShadowGenerator.FILTER_NONE;
             this.blurScale = 2;
             this._blurBoxOffset = 0;
             this._bias = 0.00005;
@@ -22,6 +22,7 @@ var BABYLON;
             this._shadowMap = new BABYLON.RenderTargetTexture(light.name + "_shadowMap", mapSize, this._scene, false);
             this._shadowMap.wrapU = BABYLON.Texture.CLAMP_ADDRESSMODE;
             this._shadowMap.wrapV = BABYLON.Texture.CLAMP_ADDRESSMODE;
+            this._shadowMap.updateSamplingMode(BABYLON.Texture.NEAREST_SAMPLINGMODE);
             this._shadowMap.renderParticles = false;
             this._shadowMap.onAfterUnbind = function () {
                 if (!_this.useBlurVarianceShadowMap) {
@@ -31,6 +32,8 @@ var BABYLON;
                     _this._shadowMap2 = new BABYLON.RenderTargetTexture(light.name + "_shadowMap", mapSize, _this._scene, false);
                     _this._shadowMap2.wrapU = BABYLON.Texture.CLAMP_ADDRESSMODE;
                     _this._shadowMap2.wrapV = BABYLON.Texture.CLAMP_ADDRESSMODE;
+                    _this._shadowMap2.anisotropicFilteringLevel = 16;
+                    _this._shadowMap2.updateSamplingMode(BABYLON.Texture.TRILINEAR_SAMPLINGMODE);
                     _this._downSamplePostprocess = new BABYLON.PassPostProcess("downScale", 1.0 / _this.blurScale, null, BABYLON.Texture.NEAREST_SAMPLINGMODE, _this._scene.getEngine());
                     _this._downSamplePostprocess.onApply = function (effect) {
                         effect.setTexture("textureSampler", _this._shadowMap);
@@ -158,6 +161,27 @@ var BABYLON;
             enumerable: true,
             configurable: true
         });
+        Object.defineProperty(ShadowGenerator.prototype, "filter", {
+            get: function () {
+                return this._filter;
+            },
+            set: function (value) {
+                if (this._filter === value) {
+                    return;
+                }
+                this._filter = value;
+                if (this.useVarianceShadowMap || this.useBlurVarianceShadowMap) {
+                    this._shadowMap.anisotropicFilteringLevel = 16;
+                    this._shadowMap.updateSamplingMode(BABYLON.Texture.TRILINEAR_SAMPLINGMODE);
+                }
+                else {
+                    this._shadowMap.anisotropicFilteringLevel = 1;
+                    this._shadowMap.updateSamplingMode(BABYLON.Texture.NEAREST_SAMPLINGMODE);
+                }
+            },
+            enumerable: true,
+            configurable: true
+        });
         Object.defineProperty(ShadowGenerator.prototype, "useVarianceShadowMap", {
             get: function () {
                 return this.filter === ShadowGenerator.FILTER_VARIANCESHADOWMAP && this._light.supportsVSM();

+ 28 - 5
Babylon/Lights/Shadows/babylon.shadowGenerator.ts

@@ -23,7 +23,7 @@
         }
 
         // Members
-        public filter = ShadowGenerator.FILTER_NONE;
+        private _filter = ShadowGenerator.FILTER_NONE;
         public blurScale = 2;
         private _blurBoxOffset = 0;
         private _bias = 0.00005;
@@ -39,7 +39,7 @@
             return this._blurBoxOffset;
         }
 
-        public set blurBoxOffset(value:number) {
+        public set blurBoxOffset(value: number) {
             if (this._blurBoxOffset === value) {
                 return;
             }
@@ -56,6 +56,26 @@
             };
         }
 
+        public get filter(): number {
+            return this._filter;
+        }
+
+        public set filter(value: number) {
+            if (this._filter === value) {
+                return;
+            }
+
+            this._filter = value;
+
+            if (this.useVarianceShadowMap || this.useBlurVarianceShadowMap) {
+                this._shadowMap.anisotropicFilteringLevel = 16;
+                this._shadowMap.updateSamplingMode(Texture.TRILINEAR_SAMPLINGMODE);
+            } else {
+                this._shadowMap.anisotropicFilteringLevel = 1;
+                this._shadowMap.updateSamplingMode(Texture.NEAREST_SAMPLINGMODE);
+            }
+        }
+
         public get useVarianceShadowMap(): boolean {
             return this.filter === ShadowGenerator.FILTER_VARIANCESHADOWMAP && this._light.supportsVSM();
         }
@@ -68,7 +88,7 @@
                 (!this._light.supportsVSM() && (
                     this.filter === ShadowGenerator.FILTER_VARIANCESHADOWMAP ||
                     this.filter === ShadowGenerator.FILTER_BLURVARIANCESHADOWMAP
-                ));
+                    ));
         }
         public set usePoissonSampling(value: boolean) {
             this.filter = (value ? ShadowGenerator.FILTER_POISSONSAMPLING : ShadowGenerator.FILTER_NONE);
@@ -112,6 +132,7 @@
             this._shadowMap = new RenderTargetTexture(light.name + "_shadowMap", mapSize, this._scene, false);
             this._shadowMap.wrapU = Texture.CLAMP_ADDRESSMODE;
             this._shadowMap.wrapV = Texture.CLAMP_ADDRESSMODE;
+            this._shadowMap.updateSamplingMode(Texture.NEAREST_SAMPLINGMODE);
             this._shadowMap.renderParticles = false;
 
             this._shadowMap.onAfterUnbind = () => {
@@ -123,7 +144,9 @@
                     this._shadowMap2 = new RenderTargetTexture(light.name + "_shadowMap", mapSize, this._scene, false);
                     this._shadowMap2.wrapU = Texture.CLAMP_ADDRESSMODE;
                     this._shadowMap2.wrapV = Texture.CLAMP_ADDRESSMODE;
-                    
+                    this._shadowMap2.anisotropicFilteringLevel = 16;
+                    this._shadowMap2.updateSamplingMode(Texture.TRILINEAR_SAMPLINGMODE);
+
                     this._downSamplePostprocess = new PassPostProcess("downScale", 1.0 / this.blurScale, null, Texture.NEAREST_SAMPLINGMODE, this._scene.getEngine());
                     this._downSamplePostprocess.onApply = effect => {
                         effect.setTexture("textureSampler", this._shadowMap);
@@ -327,7 +350,7 @@
             this._transparencyShadow = hasShadow;
         }
 
-        private _packHalf(depth: number): Vector2 { 
+        private _packHalf(depth: number): Vector2 {
             var scale = depth * 255.0;
             var fract = scale - Math.floor(scale);
 

+ 0 - 1
Babylon/Loading/Plugins/babylon.babylonFileLoader.js

@@ -794,7 +794,6 @@ var BABYLON;
                 rolloffFactor: parsedSound.rolloffFactor,
                 refDistance: parsedSound.refDistance,
                 distanceModel: parsedSound.distanceModel,
-                panningModel: parsedSound.panningModel,
                 playbackRate: parsedSound.playbackRate
             };
             var newSound = new BABYLON.Sound(soundName, soundUrl, scene, function () {

+ 0 - 1
Babylon/Loading/Plugins/babylon.babylonFileLoader.ts

@@ -984,7 +984,6 @@
             rolloffFactor: parsedSound.rolloffFactor,
             refDistance: parsedSound.refDistance,
             distanceModel: parsedSound.distanceModel,
-            panningModel: parsedSound.panningModel,
             playbackRate: parsedSound.playbackRate
         };
 

+ 11 - 5
Babylon/Materials/Textures/babylon.texture.js

@@ -46,7 +46,7 @@ var BABYLON;
             }
         }
         Texture.prototype.delayLoad = function () {
-            if (this.delayLoadState != BABYLON.Engine.DELAYLOADSTATE_NOTLOADED) {
+            if (this.delayLoadState !== BABYLON.Engine.DELAYLOADSTATE_NOTLOADED) {
                 return;
             }
             this.delayLoadState = BABYLON.Engine.DELAYLOADSTATE_LOADED;
@@ -58,6 +58,12 @@ var BABYLON;
                 }
             }
         };
+        Texture.prototype.updateSamplingMode = function (samplingMode) {
+            if (!this._texture) {
+                return;
+            }
+            this.getScene().getEngine().updateTextureSamplingMode(samplingMode, this._texture);
+        };
         Texture.prototype._prepareRowForTextureGeneration = function (x, y, z, t) {
             x -= this.uOffset + 0.5;
             y -= this.vOffset + 0.5;
@@ -115,21 +121,21 @@ var BABYLON;
             }
             this._cachedCoordinatesMode = this.coordinatesMode;
             switch (this.coordinatesMode) {
-                case BABYLON.Texture.SPHERICAL_MODE:
+                case Texture.SPHERICAL_MODE:
                     BABYLON.Matrix.IdentityToRef(this._cachedTextureMatrix);
                     this._cachedTextureMatrix[0] = -0.5 * this.uScale;
                     this._cachedTextureMatrix[5] = -0.5 * this.vScale;
                     this._cachedTextureMatrix[12] = 0.5 + this.uOffset;
                     this._cachedTextureMatrix[13] = 0.5 + this.vOffset;
                     break;
-                case BABYLON.Texture.PLANAR_MODE:
+                case Texture.PLANAR_MODE:
                     BABYLON.Matrix.IdentityToRef(this._cachedTextureMatrix);
                     this._cachedTextureMatrix[0] = this.uScale;
                     this._cachedTextureMatrix[5] = this.vScale;
                     this._cachedTextureMatrix[12] = this.uOffset;
                     this._cachedTextureMatrix[13] = this.vOffset;
                     break;
-                case BABYLON.Texture.PROJECTION_MODE:
+                case Texture.PROJECTION_MODE:
                     BABYLON.Matrix.IdentityToRef(this._projectionModeMatrix);
                     this._projectionModeMatrix.m[0] = 0.5;
                     this._projectionModeMatrix.m[5] = -0.5;
@@ -147,7 +153,7 @@ var BABYLON;
             return this._cachedTextureMatrix;
         };
         Texture.prototype.clone = function () {
-            var newTexture = new BABYLON.Texture(this._texture.url, this.getScene(), this._noMipmap, this._invertY, this._samplingMode);
+            var newTexture = new Texture(this._texture.url, this.getScene(), this._noMipmap, this._invertY, this._samplingMode);
             // Base texture
             newTexture.hasAlpha = this.hasAlpha;
             newTexture.level = this.level;

+ 28 - 20
Babylon/Materials/Textures/babylon.texture.ts

@@ -71,17 +71,17 @@
                         delete this._buffer;
                     }
                 } else {
-                    this.delayLoadState = BABYLON.Engine.DELAYLOADSTATE_NOTLOADED;
+                    this.delayLoadState = Engine.DELAYLOADSTATE_NOTLOADED;
                 }
             }
         }
 
         public delayLoad(): void {
-            if (this.delayLoadState != BABYLON.Engine.DELAYLOADSTATE_NOTLOADED) {
+            if (this.delayLoadState !== Engine.DELAYLOADSTATE_NOTLOADED) {
                 return;
             }
 
-            this.delayLoadState = BABYLON.Engine.DELAYLOADSTATE_LOADED;
+            this.delayLoadState = Engine.DELAYLOADSTATE_LOADED;
             this._texture = this._getFromCache(this.url, this._noMipmap, this._samplingMode);
 
             if (!this._texture) {
@@ -92,6 +92,14 @@
             }
         }
 
+        public updateSamplingMode(samplingMode: number): void {
+            if (!this._texture) {
+                return;
+            }
+
+            this.getScene().getEngine().updateTextureSamplingMode(samplingMode, this._texture);
+        }
+
         private _prepareRowForTextureGeneration(x: number, y: number, z: number, t: Vector3): void {
             x -= this.uOffset + 0.5;
             y -= this.vOffset + 0.5;
@@ -128,14 +136,14 @@
             this._cachedWAng = this.wAng;
 
             if (!this._cachedTextureMatrix) {
-                this._cachedTextureMatrix = BABYLON.Matrix.Zero();
-                this._rowGenerationMatrix = new BABYLON.Matrix();
-                this._t0 = BABYLON.Vector3.Zero();
-                this._t1 = BABYLON.Vector3.Zero();
-                this._t2 = BABYLON.Vector3.Zero();
+                this._cachedTextureMatrix = Matrix.Zero();
+                this._rowGenerationMatrix = new Matrix();
+                this._t0 = Vector3.Zero();
+                this._t1 = Vector3.Zero();
+                this._t2 = Vector3.Zero();
             }
 
-            BABYLON.Matrix.RotationYawPitchRollToRef(this.vAng, this.uAng, this.wAng, this._rowGenerationMatrix);
+            Matrix.RotationYawPitchRollToRef(this.vAng, this.uAng, this.wAng, this._rowGenerationMatrix);
 
             this._prepareRowForTextureGeneration(0, 0, 0, this._t0);
             this._prepareRowForTextureGeneration(1.0, 0, 0, this._t1);
@@ -144,7 +152,7 @@
             this._t1.subtractInPlace(this._t0);
             this._t2.subtractInPlace(this._t0);
 
-            BABYLON.Matrix.IdentityToRef(this._cachedTextureMatrix);
+            Matrix.IdentityToRef(this._cachedTextureMatrix);
             this._cachedTextureMatrix.m[0] = this._t1.x; this._cachedTextureMatrix.m[1] = this._t1.y; this._cachedTextureMatrix.m[2] = this._t1.z;
             this._cachedTextureMatrix.m[4] = this._t2.x; this._cachedTextureMatrix.m[5] = this._t2.y; this._cachedTextureMatrix.m[6] = this._t2.z;
             this._cachedTextureMatrix.m[8] = this._t0.x; this._cachedTextureMatrix.m[9] = this._t0.y; this._cachedTextureMatrix.m[10] = this._t0.z;
@@ -163,29 +171,29 @@
             }
 
             if (!this._cachedTextureMatrix) {
-                this._cachedTextureMatrix = BABYLON.Matrix.Zero();
-                this._projectionModeMatrix = BABYLON.Matrix.Zero();
+                this._cachedTextureMatrix = Matrix.Zero();
+                this._projectionModeMatrix = Matrix.Zero();
             }
 
             this._cachedCoordinatesMode = this.coordinatesMode;
 
             switch (this.coordinatesMode) {
-                case BABYLON.Texture.SPHERICAL_MODE:
-                    BABYLON.Matrix.IdentityToRef(this._cachedTextureMatrix);
+                case Texture.SPHERICAL_MODE:
+                    Matrix.IdentityToRef(this._cachedTextureMatrix);
                     this._cachedTextureMatrix[0] = -0.5 * this.uScale;
                     this._cachedTextureMatrix[5] = -0.5 * this.vScale;
                     this._cachedTextureMatrix[12] = 0.5 + this.uOffset;
                     this._cachedTextureMatrix[13] = 0.5 + this.vOffset;
                     break;
-                case BABYLON.Texture.PLANAR_MODE:
-                    BABYLON.Matrix.IdentityToRef(this._cachedTextureMatrix);
+                case Texture.PLANAR_MODE:
+                    Matrix.IdentityToRef(this._cachedTextureMatrix);
                     this._cachedTextureMatrix[0] = this.uScale;
                     this._cachedTextureMatrix[5] = this.vScale;
                     this._cachedTextureMatrix[12] = this.uOffset;
                     this._cachedTextureMatrix[13] = this.vOffset;
                     break;
-                case BABYLON.Texture.PROJECTION_MODE:
-                    BABYLON.Matrix.IdentityToRef(this._projectionModeMatrix);
+                case Texture.PROJECTION_MODE:
+                    Matrix.IdentityToRef(this._projectionModeMatrix);
 
                     this._projectionModeMatrix.m[0] = 0.5;
                     this._projectionModeMatrix.m[5] = -0.5;
@@ -198,14 +206,14 @@
                     this.getScene().getProjectionMatrix().multiplyToRef(this._projectionModeMatrix, this._cachedTextureMatrix);
                     break;
                 default:
-                    BABYLON.Matrix.IdentityToRef(this._cachedTextureMatrix);
+                    Matrix.IdentityToRef(this._cachedTextureMatrix);
                     break;
             }
             return this._cachedTextureMatrix;
         }
 
         public clone(): Texture {
-            var newTexture = new BABYLON.Texture(this._texture.url, this.getScene(), this._noMipmap, this._invertY, this._samplingMode);
+            var newTexture = new Texture(this._texture.url, this.getScene(), this._noMipmap, this._invertY, this._samplingMode);
 
             // Base texture
             newTexture.hasAlpha = this.hasAlpha;

+ 24 - 0
Babylon/Math/babylon.math.js

@@ -630,6 +630,28 @@ var BABYLON;
             result.y = ry / rw;
             result.z = rz / rw;
         };
+        Vector3.TransformCoordinatesToRefSIMD = function (vector, transformation, result) {
+            var v = SIMD.float32x4.loadXYZ(vector, 0);
+            var m0 = SIMD.float32x4.load(transformation.m, 0);
+            var m1 = SIMD.float32x4.load(transformation.m, 4);
+            var m2 = SIMD.float32x4.load(transformation.m, 8);
+            var m3 = SIMD.float32x4.load(transformation.m, 12);
+            var r = SIMD.float32x4.add(SIMD.float32x4.add(SIMD.float32x4.mul(SIMD.float32x4.swizzle(v, 0, 0, 0, 0), m0), SIMD.float32x4.mul(SIMD.float32x4.swizzle(v, 1, 1, 1, 1), m1)), SIMD.float32x4.add(SIMD.float32x4.mul(SIMD.float32x4.swizzle(v, 2, 2, 2, 2), m2), m3));
+            r = SIMD.float32x4.div(r, SIMD.float32x4.swizzle(r, 3, 3, 3, 3));
+            SIMD.float32x4.storeXYZ(result, 0, r);
+        };
+        Vector3.TransformCoordinatesFromFloatsToRefSIMD = function (x, y, z, transformation, result) {
+            var v0 = SIMD.float32x4.splat(x);
+            var v1 = SIMD.float32x4.splat(y);
+            var v2 = SIMD.float32x4.splat(z);
+            var m0 = SIMD.float32x4.load(transformation.m, 0);
+            var m1 = SIMD.float32x4.load(transformation.m, 4);
+            var m2 = SIMD.float32x4.load(transformation.m, 8);
+            var m3 = SIMD.float32x4.load(transformation.m, 12);
+            var r = SIMD.float32x4.add(SIMD.float32x4.add(SIMD.float32x4.mul(v0, m0), SIMD.float32x4.mul(v1, m1)), SIMD.float32x4.add(SIMD.float32x4.mul(v2, m2), m3));
+            r = SIMD.float32x4.div(r, SIMD.float32x4.swizzle(r, 3, 3, 3, 3));
+            SIMD.float32x4.storeXYZ(result, 0, r);
+        };
         Vector3.TransformNormal = function (vector, transformation) {
             var result = Vector3.Zero();
             Vector3.TransformNormalToRef(vector, transformation, result);
@@ -2549,6 +2571,8 @@ var BABYLON;
     if (window.SIMD !== undefined) {
         // Replace functions
         Matrix.prototype.multiplyToArray = Matrix.prototype.multiplyToArraySIMD;
+        Vector3.TransformCoordinatesToRef = Vector3.TransformCoordinatesToRefSIMD;
+        Vector3.TransformCoordinatesFromFloatsToRef = Vector3.TransformCoordinatesFromFloatsToRefSIMD;
     }
 })(BABYLON || (BABYLON = {}));
 //# sourceMappingURL=babylon.math.js.map

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

@@ -780,6 +780,38 @@
             result.z = rz / rw;
         }
 
+        public static TransformCoordinatesToRefSIMD(vector: Vector3, transformation: Matrix, result: Vector3): void {
+            var v = SIMD.float32x4.loadXYZ(vector, 0);
+            var m0 = SIMD.float32x4.load(transformation.m, 0);
+            var m1 = SIMD.float32x4.load(transformation.m, 4);
+            var m2 = SIMD.float32x4.load(transformation.m, 8);
+            var m3 = SIMD.float32x4.load(transformation.m, 12);
+
+            var r = SIMD.float32x4.add(
+                SIMD.float32x4.add(SIMD.float32x4.mul(SIMD.float32x4.swizzle(v, 0, 0, 0, 0), m0),
+                    SIMD.float32x4.mul(SIMD.float32x4.swizzle(v, 1, 1, 1, 1), m1)),
+                SIMD.float32x4.add(SIMD.float32x4.mul(SIMD.float32x4.swizzle(v, 2, 2, 2, 2), m2), m3));
+            r = SIMD.float32x4.div(r, SIMD.float32x4.swizzle(r, 3, 3, 3, 3));
+            SIMD.float32x4.storeXYZ(result, 0, r);
+        }
+
+        public static TransformCoordinatesFromFloatsToRefSIMD(x: number, y: number, z: number, transformation: Matrix, result: Vector3): void {
+            var v0 = SIMD.float32x4.splat(x);
+            var v1 = SIMD.float32x4.splat(y);
+            var v2 = SIMD.float32x4.splat(z);
+            var m0 = SIMD.float32x4.load(transformation.m, 0);
+            var m1 = SIMD.float32x4.load(transformation.m, 4);
+            var m2 = SIMD.float32x4.load(transformation.m, 8);
+            var m3 = SIMD.float32x4.load(transformation.m, 12);
+
+            var r = SIMD.float32x4.add(
+                SIMD.float32x4.add(SIMD.float32x4.mul(v0, m0),
+                    SIMD.float32x4.mul(v1, m1)),
+                SIMD.float32x4.add(SIMD.float32x4.mul(v2, m2), m3));
+            r = SIMD.float32x4.div(r, SIMD.float32x4.swizzle(r, 3, 3, 3, 3));
+            SIMD.float32x4.storeXYZ(result, 0, r);
+        }
+
         public static TransformNormal(vector: Vector3, transformation: Matrix): Vector3 {
             var result = Vector3.Zero();
 
@@ -1583,7 +1615,7 @@
                 num2 = flag ? ((-Math.sin(num * num5)) * num6) : ((Math.sin(num * num5)) * num6);
             }
 
-            return new Quaternion((num3 * left.x) + (num2 * right.x), (num3 * left.y) + (num2 * right.y), (num3 * left.z) + (num2 * right.z), (num3 * left.w) + (num2 * right.w));
+            return new Quaternion((num3 * left.x) + (num2 * right.x),(num3 * left.y) + (num2 * right.y),(num3 * left.z) + (num2 * right.z),(num3 * left.w) + (num2 * right.w));
         }
     }
 
@@ -1842,9 +1874,9 @@
         public equals(value: Matrix): boolean {
             return value &&
                 (this.m[0] === value.m[0] && this.m[1] === value.m[1] && this.m[2] === value.m[2] && this.m[3] === value.m[3] &&
-                this.m[4] === value.m[4] && this.m[5] === value.m[5] && this.m[6] === value.m[6] && this.m[7] === value.m[7] &&
-                this.m[8] === value.m[8] && this.m[9] === value.m[9] && this.m[10] === value.m[10] && this.m[11] === value.m[11] &&
-                this.m[12] === value.m[12] && this.m[13] === value.m[13] && this.m[14] === value.m[14] && this.m[15] === value.m[15]);
+                    this.m[4] === value.m[4] && this.m[5] === value.m[5] && this.m[6] === value.m[6] && this.m[7] === value.m[7] &&
+                    this.m[8] === value.m[8] && this.m[9] === value.m[9] && this.m[10] === value.m[10] && this.m[11] === value.m[11] &&
+                    this.m[12] === value.m[12] && this.m[13] === value.m[13] && this.m[14] === value.m[14] && this.m[15] === value.m[15]);
         }
 
         public clone(): Matrix {
@@ -3101,7 +3133,7 @@
                 if (i < l - 1) {
                     cur = this._curve[i + 1].subtract(this._curve[i]);
                     this._tangents[i] = prev.add(cur);
-                    this._tangents[i].normalize();               
+                    this._tangents[i].normalize();
                 }
                 this._distances[i] = this._distances[i - 1] + prev.length();   
                       
@@ -3140,20 +3172,20 @@
         // private function normalVector(v0, vt) :
         // returns an arbitrary point in the plane defined by the point v0 and the vector vt orthogonal to this plane
         private _normalVector(v0: Vector3, vt: Vector3): Vector3 {
-            var point: Vector3; 
+            var point: Vector3;
 
             if (vt.x !== 1) {     // search for a point in the plane
-                point = new Vector3(1, 0, 0);   
+                point = new Vector3(1, 0, 0);
             }
             else if (vt.y !== 1) {
-                point = new Vector3(0, 1, 0);  
+                point = new Vector3(0, 1, 0);
             }
             else if (vt.z !== 1) {
-                point = new Vector3(0, 0, 1);  
+                point = new Vector3(0, 0, 1);
             }
             var normal0: Vector3 = Vector3.Cross(vt, point);
             normal0.normalize();
-            return normal0;        
+            return normal0;
         }
     }
 
@@ -3203,5 +3235,7 @@
     if (window.SIMD !== undefined) {
         // Replace functions
         Matrix.prototype.multiplyToArray = <any>Matrix.prototype.multiplyToArraySIMD;
+        Vector3.TransformCoordinatesToRef = <any>Vector3.TransformCoordinatesToRefSIMD;
+        Vector3.TransformCoordinatesFromFloatsToRef = <any>Vector3.TransformCoordinatesFromFloatsToRefSIMD;
     }
 }

+ 2 - 1
Babylon/Mesh/babylon.geometry.js

@@ -306,7 +306,8 @@ var BABYLON;
             var updatable = false;
             var stopChecking = false;
             for (var kind in this._vertexBuffers) {
-                vertexData.set(this.getVerticesData(kind), kind);
+                // using slice() to make a copy of the array and not just reference it
+                vertexData.set(this.getVerticesData(kind).slice(0), kind);
                 if (!stopChecking) {
                     updatable = this.getVertexBuffer(kind).isUpdatable();
                     stopChecking = !updatable;

+ 4 - 2
Babylon/Mesh/babylon.geometry.ts

@@ -394,7 +394,8 @@
             var stopChecking = false;
 
             for (var kind in this._vertexBuffers) {
-                vertexData.set(this.getVerticesData(kind), kind);
+                // using slice() to make a copy of the array and not just reference it
+                vertexData.set(this.getVerticesData(kind).slice(0), kind);
 
                 if (!stopChecking) {
                     updatable = this.getVertexBuffer(kind).isUpdatable();
@@ -729,4 +730,5 @@
             }
         }
     }
-} 
+} 
+

+ 6 - 34
Babylon/Mesh/babylon.mesh.js

@@ -959,42 +959,14 @@ var BABYLON;
             var extruded = Mesh._ExtrudeShapeGeneric(name, shape, path, scale, rotation, null, null, false, false, false, scene, updatable, sideOrientation);
             return extruded;
         };
-        Mesh.ExtrudeShapeCustom = function (name, shape, path, scaleFunction, rotateFunction, ribbonCloseArray, ribbonClosePath, scene, updatable, sideOrientation) {
+        Mesh.ExtrudeShapeCustom = function (name, shape, path, scaleFunction, rotationFunction, ribbonCloseArray, ribbonClosePath, scene, updatable, sideOrientation) {
             if (sideOrientation === void 0) { sideOrientation = Mesh.DEFAULTSIDE; }
-            ribbonCloseArray = ribbonCloseArray || false;
-            ribbonClosePath = ribbonClosePath || false;
-            var extrudedCustom = Mesh._ExtrudeShapeGeneric(name, shape, path, null, null, scaleFunction, rotateFunction, ribbonCloseArray, ribbonClosePath, true, scene, updatable, sideOrientation);
+            var extrudedCustom = Mesh._ExtrudeShapeGeneric(name, shape, path, null, null, scaleFunction, rotationFunction, ribbonCloseArray, ribbonClosePath, true, scene, updatable, sideOrientation);
             return extrudedCustom;
         };
-        Mesh._ExtrudeShapeGeneric = function (name, shape, curve, scale, rotation, scaleFunction, rotateFunction, rbCA, rbCP, custom, scene, updtbl, side) {
+        Mesh._ExtrudeShapeGeneric = function (name, shape, curve, scale, rotation, scaleFunction, rotationFunction, rbCA, rbCP, custom, scene, updtbl, side) {
             var path3D = new BABYLON.Path3D(curve);
-            var tangents = path3D.getTangents();
-            var normals = path3D.getNormals();
-            var binormals = path3D.getBinormals();
-            var distances = path3D.getDistances();
-            var shapePaths = new Array();
-            var angle = 0;
-            var returnScale = function (i, distance) {
-                return scale;
-            };
-            var returnRotation = function (i, distance) {
-                return rotation;
-            };
-            var rotate = custom ? rotateFunction : returnRotation;
-            var scl = custom ? scaleFunction : returnScale;
-            for (var i = 0; i < curve.length; i++) {
-                var shapePath = new Array();
-                var angleStep = rotate(i, distances[i]);
-                var scaleRatio = scl(i, distances[i]);
-                var rotationMatrix = BABYLON.Matrix.RotationAxis(tangents[i], angle);
-                for (var p = 0; p < shape.length; p++) {
-                    var planed = ((tangents[i].scale(shape[p].z)).add(normals[i].scale(shape[p].x)).add(binormals[i].scale(shape[p].y)));
-                    var rotated = BABYLON.Vector3.TransformCoordinates(planed, rotationMatrix).scaleInPlace(scaleRatio).add(curve[i]);
-                    shapePath.push(rotated);
-                }
-                shapePaths.push(shapePath);
-                angle += angleStep;
-            }
+            var shapePaths = [];
             var extrudedGeneric = Mesh.CreateRibbon(name, shapePaths, rbCA, rbCP, 0, scene, updtbl, side);
             return extrudedGeneric;
         };
@@ -1059,7 +1031,7 @@ var BABYLON;
             var step = pi2 / tesselation;
             var returnRadius = function (i, distance) { return radius; };
             var radiusFunctionFinal = radiusFunction || returnRadius;
-            var circlePaths = [];
+            var circlePaths = new Array();
             var circlePath;
             var rad;
             var normal;
@@ -1067,7 +1039,7 @@ var BABYLON;
             var rotationMatrix;
             for (var i = 0; i < path.length; i++) {
                 rad = radiusFunctionFinal(i, distances[i]); // current radius
-                circlePath = []; // current circle array
+                circlePath = Array(); // current circle array
                 normal = normals[i]; // current normal  
                 for (var ang = 0; ang < pi2; ang += step) {
                     rotationMatrix = BABYLON.Matrix.RotationAxis(tangents[i], ang);

+ 17 - 41
Babylon/Mesh/babylon.mesh.ts

@@ -1175,42 +1175,18 @@
             return extruded;
         }
 
-        public static ExtrudeShapeCustom(name: string, shape: Vector3[], path: Vector3[], scaleFunction, rotateFunction, ribbonCloseArray: boolean, ribbonClosePath: boolean, scene: Scene, updatable?: boolean, sideOrientation: number = Mesh.DEFAULTSIDE): Mesh {
-            ribbonCloseArray = ribbonCloseArray || false;
-            ribbonClosePath = ribbonClosePath || false;
-            var extrudedCustom = Mesh._ExtrudeShapeGeneric(name, shape, path, null, null, scaleFunction, rotateFunction, ribbonCloseArray, ribbonClosePath, true, scene, updatable, sideOrientation);
+        public static ExtrudeShapeCustom(name: string, shape: Vector3[], path: Vector3[], scaleFunction, rotationFunction, ribbonCloseArray: boolean, ribbonClosePath: boolean, scene: Scene, updatable?: boolean, sideOrientation: number = Mesh.DEFAULTSIDE): Mesh {
+            var extrudedCustom = Mesh._ExtrudeShapeGeneric(name, shape, path, null, null, scaleFunction, rotationFunction, ribbonCloseArray, ribbonClosePath, true, scene, updatable, sideOrientation);
             return extrudedCustom;
         }
 
-        private static _ExtrudeShapeGeneric(name: string, shape: Vector3[], curve: Vector3[], scale: number, rotation: number, scaleFunction: { (i: number, distance: number): number; }, rotateFunction: { (i: number, distance: number): number; }, rbCA: boolean, rbCP: boolean, custom: boolean, scene: Scene, updtbl: boolean, side: number): Mesh {
+        private static _ExtrudeShapeGeneric(name: string, shape: Vector3[], curve: Vector3[], scale: number, rotation: number, scaleFunction, rotationFunction, rbCA: boolean, rbCP: boolean, custom: boolean, scene: Scene, updtbl: boolean, side: number): Mesh {
             var path3D = new Path3D(curve);
-            var tangents = path3D.getTangents();
-            var normals = path3D.getNormals();
-            var binormals = path3D.getBinormals();
-            var distances = path3D.getDistances();
-            var shapePaths = new Array<Array<Vector3>>();
-            var angle = 0;
-            var returnScale: { (i: number, distance: number): number; } = function (i, distance) { return scale; };
-            var returnRotation: { (i: number, distance: number): number; } = function (i, distance) { return rotation; };
-            var rotate: { (i: number, distance: number): number; } = custom ? rotateFunction : returnRotation;
-            var scl: { (i: number, distance: number): number; } = custom ? scaleFunction : returnScale;
-
-            for (var i: number = 0; i < curve.length; i++) {
-                var shapePath = new Array<Vector3>();
-                var angleStep = rotate(i, distances[i]);
-                var scaleRatio = scl(i, distances[i]);
-                var rotationMatrix = Matrix.RotationAxis(tangents[i], angle);
-                for (var p = 0; p < shape.length; p++) {
-                    var planed = ((tangents[i].scale(shape[p].z)).add(normals[i].scale(shape[p].x)).add(binormals[i].scale(shape[p].y)));
-                    var rotated = Vector3.TransformCoordinates(planed, rotationMatrix).scaleInPlace(scaleRatio).add(curve[i]);
-                    shapePath.push(rotated);
-                }
-                shapePaths.push(shapePath);
-                angle += angleStep;
-            }
 
+            var shapePaths: Vector3[][] = [];
             var extrudedGeneric = Mesh.CreateRibbon(name, shapePaths, rbCA, rbCP, 0, scene, updtbl, side);
             return extrudedGeneric;
+
         }
 
         // Plane & ground
@@ -1285,26 +1261,26 @@
         }
 
         public static CreateTube(name: string, path: Vector3[], radius: number, tesselation: number, radiusFunction: { (i: number, distance: number): number; }, scene: Scene, updatable?: boolean, sideOrientation: number = Mesh.DEFAULTSIDE): Mesh {
-            var path3D: Path3D = new Path3D(path);
-            var tangents: Vector3[] = path3D.getTangents();
-            var normals: Vector3[] = path3D.getNormals();
-            var distances: number[] = path3D.getDistances();
-            var pi2: number = Math.PI * 2;
-            var step: number = pi2 / tesselation;
+            var path3D = new Path3D(path);
+            var tangents = path3D.getTangents();
+            var normals = path3D.getNormals();
+            var distances = path3D.getDistances();
+            var pi2 = Math.PI * 2;
+            var step = pi2 / tesselation;
             var returnRadius: { (i: number, distance: number): number; } = (i, distance) => radius;
             var radiusFunctionFinal: { (i: number, distance: number): number; } = radiusFunction || returnRadius;
 
-            var circlePaths: Vector3[][] = [];
+            var circlePaths = new Array<Array<Vector3>>();
             var circlePath: Vector3[];
             var rad: number;
             var normal: Vector3;
             var rotated: Vector3;
             var rotationMatrix: Matrix;
-            for (var i: number = 0; i < path.length; i++) {
-                rad = radiusFunctionFinal(i, distances[i]);      // current radius
-                circlePath = [];                            // current circle array
+            for (var i = 0; i < path.length; i++) {
+                rad = radiusFunctionFinal(i, distances[i]); // current radius
+                circlePath = Array<Vector3>();              // current circle array
                 normal = normals[i];                        // current normal  
-                for (var ang: number = 0; ang < pi2; ang += step) {
+                for (var ang = 0; ang < pi2; ang += step) {
                     rotationMatrix = Matrix.RotationAxis(tangents[i], ang);
                     rotated = Vector3.TransformCoordinates(normal, rotationMatrix).scaleInPlace(rad).add(path[i]);
                     circlePath.push(rotated);
@@ -1390,4 +1366,4 @@
             return newMesh;
         }
     }
-} 
+} 

+ 10 - 3
Babylon/PostProcess/babylon.volumetricLightScatteringPostProcess.js

@@ -65,16 +65,22 @@ var BABYLON;
             var defines = [];
             var attribs = [BABYLON.VertexBuffer.PositionKind];
             var material = subMesh.getMaterial();
+            var needUV = false;
             // Render this.mesh as default
             if (mesh === this.mesh) {
                 defines.push("#define BASIC_RENDER");
+                defines.push("#define NEED_UV");
+                needUV = true;
             }
             // Alpha test
             if (material) {
                 if (material.needAlphaTesting() || mesh === this.mesh)
                     defines.push("#define ALPHATEST");
-                if (material.opacityTexture !== undefined)
+                if (material.opacityTexture !== undefined) {
                     defines.push("#define OPACITY");
+                    if (!needUV)
+                        defines.push("#define NEED_UV");
+                }
                 if (mesh.isVerticesDataPresent(BABYLON.VertexBuffer.UVKind)) {
                     attribs.push(BABYLON.VertexBuffer.UVKind);
                     defines.push("#define UV1");
@@ -103,7 +109,7 @@ var BABYLON;
             var join = defines.join("\n");
             if (this._cachedDefines !== join) {
                 this._cachedDefines = join;
-                this._volumetricLightScatteringPass = mesh.getScene().getEngine().createEffect({ vertexElement: "depth", fragmentElement: "volumetricLightScatteringPass" }, attribs, ["world", "mBones", "viewProjection", "diffuseMatrix", "far"], ["diffuseSampler", "opacitySampler"], join);
+                this._volumetricLightScatteringPass = mesh.getScene().getEngine().createEffect({ vertexElement: "depth", fragmentElement: "volumetricLightScatteringPass" }, attribs, ["world", "mBones", "viewProjection", "diffuseMatrix"], ["diffuseSampler", "opacitySampler"], join);
             }
             return this._volumetricLightScatteringPass.isReady();
         };
@@ -180,8 +186,9 @@ var BABYLON;
                     if (material && (mesh === _this.mesh || material.needAlphaTesting() || material.opacityTexture !== undefined)) {
                         var alphaTexture = material.getAlphaTestTexture();
                         _this._volumetricLightScatteringPass.setTexture("diffuseSampler", alphaTexture);
-                        if (_this.mesh.material && alphaTexture)
+                        if (alphaTexture) {
                             _this._volumetricLightScatteringPass.setMatrix("diffuseMatrix", alphaTexture.getTextureMatrix());
+                        }
                         if (material.opacityTexture !== undefined)
                             _this._volumetricLightScatteringPass.setTexture("opacitySampler", material.opacityTexture);
                     }

+ 11 - 3
Babylon/PostProcess/babylon.volumetricLightScatteringPostProcess.ts

@@ -76,10 +76,13 @@
             var defines = [];
             var attribs = [VertexBuffer.PositionKind];
             var material: any = subMesh.getMaterial();
+            var needUV: boolean = false;
 
             // Render this.mesh as default
             if (mesh === this.mesh) {
                 defines.push("#define BASIC_RENDER");
+                defines.push("#define NEED_UV");
+                needUV = true;
             }
 
             // Alpha test
@@ -87,8 +90,11 @@
                 if (material.needAlphaTesting() || mesh === this.mesh)
                     defines.push("#define ALPHATEST");
 
-                if (material.opacityTexture !== undefined)
+                if (material.opacityTexture !== undefined) {
                     defines.push("#define OPACITY");
+                    if (!needUV)
+                        defines.push("#define NEED_UV");
+                }
 
                 if (mesh.isVerticesDataPresent(VertexBuffer.UVKind)) {
                     attribs.push(VertexBuffer.UVKind);
@@ -124,7 +130,7 @@
                 this._volumetricLightScatteringPass = mesh.getScene().getEngine().createEffect(
                     { vertexElement: "depth", fragmentElement: "volumetricLightScatteringPass" },
                     attribs,
-                    ["world", "mBones", "viewProjection", "diffuseMatrix", "far"],
+                    ["world", "mBones", "viewProjection", "diffuseMatrix"],
                     ["diffuseSampler", "opacitySampler"], join);
             }
 
@@ -220,8 +226,10 @@
                     if (material && (mesh === this.mesh || material.needAlphaTesting() || material.opacityTexture !== undefined)) {
                         var alphaTexture = material.getAlphaTestTexture();
                         this._volumetricLightScatteringPass.setTexture("diffuseSampler", alphaTexture);
-                        if (this.mesh.material && alphaTexture)
+
+                        if (alphaTexture) {
                             this._volumetricLightScatteringPass.setMatrix("diffuseMatrix", alphaTexture.getTextureMatrix());
+                        }
 
                         if (material.opacityTexture !== undefined)
                             this._volumetricLightScatteringPass.setTexture("opacitySampler", material.opacityTexture);

+ 4 - 5
Babylon/Shaders/default.fragment.fx

@@ -262,20 +262,19 @@ float computeShadowWithPCF(vec4 vPositionFromLight, sampler2D shadowSampler, flo
 }
 
 // Thanks to http://devmaster.net/
-float ChebychevInequality(vec2 moments, float t, float bias)
+float ChebychevInequality(vec2 moments, float t)
 {
-	bias = 0.02 + bias;
 	if (t <= moments.x)
 	{
 		return 0.0;
 	}
 
 	float variance = moments.y - (moments.x * moments.x);
-	variance = max(variance, bias);
+	variance = max(variance, 0.02);
 
 	float d = t - moments.x;
 
-	return clamp(variance / (variance + d * d) - 0.05 - bias, 0.0, 1.0);
+	return clamp(variance / (variance + d * d) - 0.05, 0.0, 1.0);
 }
 
 float computeShadowWithVSM(vec4 vPositionFromLight, sampler2D shadowSampler, float bias)
@@ -292,7 +291,7 @@ float computeShadowWithVSM(vec4 vPositionFromLight, sampler2D shadowSampler, flo
 	vec4 texel = texture2D(shadowSampler, uv);
 
 	vec2 moments = vec2(unpackHalf(texel.xy), unpackHalf(texel.zw));
-	return 1.0 - ChebychevInequality(moments, depth.z, bias);
+	return 1.0 - ChebychevInequality(moments, depth.z - bias);
 }
 #endif
 

+ 2 - 2
Babylon/Shaders/depth.vertex.fx

@@ -24,7 +24,7 @@ uniform mat4 viewProjection;
 uniform mat4 mBones[BonesPerMesh];
 #endif
 
-#ifdef ALPHATEST
+#if defined(ALPHATEST) || defined(NEED_UV)
 varying vec2 vUV;
 uniform mat4 diffuseMatrix;
 #ifdef UV1
@@ -54,7 +54,7 @@ void main(void)
 	gl_Position = viewProjection * finalWorld * vec4(position, 1.0);
 #endif
 
-#ifdef ALPHATEST
+#if defined(ALPHATEST) || defined(BASIC_RENDER)
 #ifdef UV1
 	vUV = vec2(diffuseMatrix * vec4(uv, 1.0, 0.0));
 #endif

+ 15 - 6
Babylon/Shaders/volumetricLightScatteringPass.fragment.fx

@@ -16,7 +16,7 @@ uniform sampler2D opacitySampler;
 
 void main(void)
 {
-#if defined(ALPHATEST) || defined(OPACITY) || defined(BASIC_RENDER)
+#if defined(ALPHATEST) || defined(BASIC_RENDER)
 	vec4 diffuseColor = texture2D(diffuseSampler, vUV);
 #endif
 
@@ -25,14 +25,23 @@ void main(void)
 		discard;
 #endif
 
-#ifdef BASIC_RENDER
 #ifdef OPACITY
-	gl_FragColor = diffuseColor * texture2D(opacitySampler, vUV);
-#else
-	gl_FragColor = diffuseColor;
-#endif
+	vec4 opacityColor = texture2D(opacitySampler, vUV);
+
+	#if defined(BASIC_RENDER)
+	gl_FragColor = diffuseColor * opacityColor;
+	#else
+	if (opacityColor.r == 0.0)
+		discard;
+
+	gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
+	#endif
 #else
+	#ifndef BASIC_RENDER
 	gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
+	#else
+	gl_FragColor = diffuseColor;
+	#endif
 #endif
 
 }

+ 7 - 6
Babylon/Sprites/babylon.spriteManager.js

@@ -1,7 +1,8 @@
 var BABYLON;
 (function (BABYLON) {
     var SpriteManager = (function () {
-        function SpriteManager(name, imgUrl, capacity, cellSize, scene, epsilon) {
+        function SpriteManager(name, imgUrl, capacity, cellSize, scene, epsilon, samplingMode) {
+            if (samplingMode === void 0) { samplingMode = BABYLON.Texture.TRILINEAR_SAMPLINGMODE; }
             this.name = name;
             this.cellSize = cellSize;
             this.sprites = new Array();
@@ -10,7 +11,7 @@ var BABYLON;
             this._vertexDeclaration = [3, 4, 4, 4];
             this._vertexStrideSize = 15 * 4; // 15 floats per sprite (x, y, z, angle, size, offsetX, offsetY, invertU, invertV, cellIndexX, cellIndexY, color)
             this._capacity = capacity;
-            this._spriteTexture = new BABYLON.Texture(imgUrl, scene, true, false);
+            this._spriteTexture = new BABYLON.Texture(imgUrl, scene, true, false, samplingMode);
             this._spriteTexture.wrapU = BABYLON.Texture.CLAMP_ADDRESSMODE;
             this._spriteTexture.wrapV = BABYLON.Texture.CLAMP_ADDRESSMODE;
             this._epsilon = epsilon === undefined ? 0.01 : epsilon;
@@ -39,13 +40,13 @@ var BABYLON;
         }
         SpriteManager.prototype._appendSpriteVertex = function (index, sprite, offsetX, offsetY, rowSize) {
             var arrayOffset = index * 15;
-            if (offsetX == 0)
+            if (offsetX === 0)
                 offsetX = this._epsilon;
-            else if (offsetX == 1)
+            else if (offsetX === 1)
                 offsetX = 1 - this._epsilon;
-            if (offsetY == 0)
+            if (offsetY === 0)
                 offsetY = this._epsilon;
-            else if (offsetY == 1)
+            else if (offsetY === 1)
                 offsetY = 1 - this._epsilon;
             this._vertices[arrayOffset] = sprite.position.x;
             this._vertices[arrayOffset + 1] = sprite.position.y;

+ 12 - 11
Babylon/Sprites/babylon.spriteManager.ts

@@ -13,17 +13,18 @@
 
         private _vertexDeclaration = [3, 4, 4, 4];
         private _vertexStrideSize = 15 * 4; // 15 floats per sprite (x, y, z, angle, size, offsetX, offsetY, invertU, invertV, cellIndexX, cellIndexY, color)
-        private _vertexBuffer: WebGLBuffer
+        private _vertexBuffer: WebGLBuffer;
         private _indexBuffer: WebGLBuffer;
         private _vertices: Float32Array;
         private _effectBase: Effect;
         private _effectFog: Effect;
 
-        constructor(public name: string, imgUrl: string, capacity: number, public cellSize: number, scene: Scene, epsilon?: number) {
+        constructor(public name: string, imgUrl: string, capacity: number, public cellSize: number, scene: Scene, epsilon?: number, samplingMode: number = Texture.TRILINEAR_SAMPLINGMODE) {
             this._capacity = capacity;
-            this._spriteTexture = new BABYLON.Texture(imgUrl, scene, true, false);
-            this._spriteTexture.wrapU = BABYLON.Texture.CLAMP_ADDRESSMODE;
-            this._spriteTexture.wrapV = BABYLON.Texture.CLAMP_ADDRESSMODE;
+            this._spriteTexture = new Texture(imgUrl, scene, true, false, samplingMode);
+            this._spriteTexture.wrapU = Texture.CLAMP_ADDRESSMODE;
+            this._spriteTexture.wrapV = Texture.CLAMP_ADDRESSMODE;
+
             this._epsilon = epsilon === undefined ? 0.01 : epsilon;
 
             this._scene = scene;
@@ -64,14 +65,14 @@
         private _appendSpriteVertex(index: number, sprite: Sprite, offsetX: number, offsetY: number, rowSize: number): void {
             var arrayOffset = index * 15;
 
-            if (offsetX == 0)
+            if (offsetX === 0)
                 offsetX = this._epsilon;
-            else if (offsetX == 1)
+            else if (offsetX === 1)
                 offsetX = 1 - this._epsilon;
 
-            if (offsetY == 0)
+            if (offsetY === 0)
                 offsetY = this._epsilon;
-            else if (offsetY == 1)
+            else if (offsetY === 1)
                 offsetY = 1 - this._epsilon;
 
             this._vertices[arrayOffset] = sprite.position.x;
@@ -154,9 +155,9 @@
             engine.setColorWrite(true);
             effect.setBool("alphaTest", false);
 
-            engine.setAlphaMode(BABYLON.Engine.ALPHA_COMBINE);
+            engine.setAlphaMode(Engine.ALPHA_COMBINE);
             engine.draw(true, 0, max * 6);
-            engine.setAlphaMode(BABYLON.Engine.ALPHA_DISABLE);
+            engine.setAlphaMode(Engine.ALPHA_DISABLE);
         }
 
         public dispose(): void {

+ 10 - 10
Babylon/Tools/babylon.sceneSerializer.js

@@ -46,6 +46,15 @@ var BABYLON;
         serializationObject.power = fresnelParameter.power;
         return serializationObject;
     };
+    var appendAnimations = function (source, destination) {
+        if (source.animations) {
+            destination.animations = [];
+            for (var animationIndex = 0; animationIndex < source.animations.length; animationIndex++) {
+                var animation = source.animations[animationIndex];
+                destination.animations.push(serializeAnimation(animation));
+            }
+        }
+    };
     var serializeCamera = function (camera) {
         var serializationObject = {};
         serializationObject.name = camera.name;
@@ -148,15 +157,6 @@ var BABYLON;
         serializationObject.layerMask = camera.layerMask;
         return serializationObject;
     };
-    var appendAnimations = function (source, destination) {
-        if (source.animations) {
-            destination.animations = [];
-            for (var animationIndex = 0; animationIndex < source.animations.length; animationIndex++) {
-                var animation = source.animations[animationIndex];
-                destination.animations.push(serializeAnimation(animation));
-            }
-        }
-    };
     var serializeAnimation = function (animation) {
         var serializationObject = {};
         serializationObject.name = animation.name;
@@ -655,7 +655,7 @@ var BABYLON;
             serializationObject.geometries.vertexData = [];
             serializedGeometries = [];
             var geometries = scene.getGeometries();
-            for (var index = 0; index < geometries.length; index++) {
+            for (index = 0; index < geometries.length; index++) {
                 var geometry = geometries[index];
                 if (geometry.isReady()) {
                     serializeGeometry(geometry, serializationObject.geometries);

+ 12 - 12
Babylon/Tools/babylon.sceneSerializer.ts

@@ -52,6 +52,17 @@
         return serializationObject;
     }
 
+    var appendAnimations = (source: IAnimatable, destination: any): any => {
+        if (source.animations) {
+            destination.animations = [];
+            for (var animationIndex = 0; animationIndex < source.animations.length; animationIndex++) {
+                var animation = source.animations[animationIndex];
+
+                destination.animations.push(serializeAnimation(animation));
+            }
+        }
+    };
+
     var serializeCamera = (camera: Camera): any => {
         var serializationObject: any = {};
         serializationObject.name = camera.name;
@@ -155,17 +166,6 @@
         return serializationObject;
     };
 
-    var appendAnimations = (source: IAnimatable, destination: any): any => {
-        if (source.animations) {
-            destination.animations = [];
-            for (var animationIndex = 0; animationIndex < source.animations.length; animationIndex++) {
-                var animation = source.animations[animationIndex];
-
-                destination.animations.push(serializeAnimation(animation));
-            }
-        }
-    };
-
     var serializeAnimation = (animation: Animation): any => {
         var serializationObject: any = {};
 
@@ -801,7 +801,7 @@
 
             serializedGeometries = [];
             var geometries = scene.getGeometries();
-            for (var index = 0; index < geometries.length; index++) {
+            for (index = 0; index < geometries.length; index++) {
                 var geometry = geometries[index];
 
                 if (geometry.isReady()) {

+ 15 - 8
Babylon/babylon.engine.js

@@ -1337,11 +1337,6 @@ var BABYLON;
             var texture = this._gl.createTexture();
             width = BABYLON.Tools.GetExponantOfTwo(width, this._caps.maxTextureSize);
             height = BABYLON.Tools.GetExponantOfTwo(height, this._caps.maxTextureSize);
-            this._gl.bindTexture(this._gl.TEXTURE_2D, texture);
-            var filters = getSamplingParameters(samplingMode, generateMipMaps, this._gl);
-            this._gl.texParameteri(this._gl.TEXTURE_2D, this._gl.TEXTURE_MAG_FILTER, filters.mag);
-            this._gl.texParameteri(this._gl.TEXTURE_2D, this._gl.TEXTURE_MIN_FILTER, filters.min);
-            this._gl.bindTexture(this._gl.TEXTURE_2D, null);
             this._activeTexturesCache = [];
             texture._baseWidth = width;
             texture._baseHeight = height;
@@ -1351,9 +1346,17 @@ var BABYLON;
             texture.generateMipMaps = generateMipMaps;
             texture.references = 1;
             texture.samplingMode = samplingMode;
+            this.updateTextureSamplingMode(samplingMode, texture);
             this._loadedTexturesCache.push(texture);
             return texture;
         };
+        Engine.prototype.updateTextureSamplingMode = function (samplingMode, texture) {
+            var filters = getSamplingParameters(samplingMode, texture.generateMipMaps, this._gl);
+            this._gl.bindTexture(this._gl.TEXTURE_2D, texture);
+            this._gl.texParameteri(this._gl.TEXTURE_2D, this._gl.TEXTURE_MAG_FILTER, filters.mag);
+            this._gl.texParameteri(this._gl.TEXTURE_2D, this._gl.TEXTURE_MIN_FILTER, filters.min);
+            this._gl.bindTexture(this._gl.TEXTURE_2D, null);
+        };
         Engine.prototype.updateDynamicTexture = function (texture, canvas, invertY) {
             this._gl.bindTexture(this._gl.TEXTURE_2D, texture);
             this._gl.pixelStorei(this._gl.UNPACK_FLIP_Y_WEBGL, invertY ? 1 : 0);
@@ -1636,9 +1639,13 @@ var BABYLON;
         };
         Engine.prototype._setAnisotropicLevel = function (key, texture) {
             var anisotropicFilterExtension = this._caps.textureAnisotropicFilterExtension;
-            if (anisotropicFilterExtension && texture._cachedAnisotropicFilteringLevel !== texture.anisotropicFilteringLevel) {
-                this._gl.texParameterf(key, anisotropicFilterExtension.TEXTURE_MAX_ANISOTROPY_EXT, Math.min(texture.anisotropicFilteringLevel, this._caps.maxAnisotropy));
-                texture._cachedAnisotropicFilteringLevel = texture.anisotropicFilteringLevel;
+            var value = texture.anisotropicFilteringLevel;
+            if (texture.getInternalTexture().samplingMode === BABYLON.Texture.NEAREST_SAMPLINGMODE) {
+                value = 1;
+            }
+            if (anisotropicFilterExtension && texture._cachedAnisotropicFilteringLevel !== value) {
+                this._gl.texParameterf(key, anisotropicFilterExtension.TEXTURE_MAX_ANISOTROPY_EXT, Math.min(value, this._caps.maxAnisotropy));
+                texture._cachedAnisotropicFilteringLevel = value;
             }
         };
         Engine.prototype.readPixels = function (x, y, width, height) {

+ 20 - 11
Babylon/babylon.engine.ts

@@ -1617,14 +1617,6 @@
             width = Tools.GetExponantOfTwo(width, this._caps.maxTextureSize);
             height = Tools.GetExponantOfTwo(height, this._caps.maxTextureSize);
 
-            this._gl.bindTexture(this._gl.TEXTURE_2D, texture);
-
-            var filters = getSamplingParameters(samplingMode, generateMipMaps, this._gl);
-
-            this._gl.texParameteri(this._gl.TEXTURE_2D, this._gl.TEXTURE_MAG_FILTER, filters.mag);
-            this._gl.texParameteri(this._gl.TEXTURE_2D, this._gl.TEXTURE_MIN_FILTER, filters.min);
-            this._gl.bindTexture(this._gl.TEXTURE_2D, null);
-
             this._activeTexturesCache = [];
             texture._baseWidth = width;
             texture._baseHeight = height;
@@ -1635,11 +1627,23 @@
             texture.references = 1;
             texture.samplingMode = samplingMode;
 
+            this.updateTextureSamplingMode(samplingMode, texture);
+
             this._loadedTexturesCache.push(texture);
 
             return texture;
         }
 
+        public updateTextureSamplingMode(samplingMode: number, texture: WebGLTexture): void {
+            var filters = getSamplingParameters(samplingMode, texture.generateMipMaps, this._gl);
+
+            this._gl.bindTexture(this._gl.TEXTURE_2D, texture);
+
+            this._gl.texParameteri(this._gl.TEXTURE_2D, this._gl.TEXTURE_MAG_FILTER, filters.mag);
+            this._gl.texParameteri(this._gl.TEXTURE_2D, this._gl.TEXTURE_MIN_FILTER, filters.min);
+            this._gl.bindTexture(this._gl.TEXTURE_2D, null);
+        }
+
         public updateDynamicTexture(texture: WebGLTexture, canvas: HTMLCanvasElement, invertY: boolean): void {
             this._gl.bindTexture(this._gl.TEXTURE_2D, texture);
             this._gl.pixelStorei(this._gl.UNPACK_FLIP_Y_WEBGL, invertY ? 1 : 0);
@@ -1976,10 +1980,15 @@
 
         public _setAnisotropicLevel(key: number, texture: BaseTexture) {
             var anisotropicFilterExtension = this._caps.textureAnisotropicFilterExtension;
+            var value = texture.anisotropicFilteringLevel;
+
+            if (texture.getInternalTexture().samplingMode === Texture.NEAREST_SAMPLINGMODE) {
+                value = 1;
+            }
 
-            if (anisotropicFilterExtension && texture._cachedAnisotropicFilteringLevel !== texture.anisotropicFilteringLevel) {
-                this._gl.texParameterf(key, anisotropicFilterExtension.TEXTURE_MAX_ANISOTROPY_EXT, Math.min(texture.anisotropicFilteringLevel, this._caps.maxAnisotropy));
-                texture._cachedAnisotropicFilteringLevel = texture.anisotropicFilteringLevel;
+            if (anisotropicFilterExtension && texture._cachedAnisotropicFilteringLevel !== value) {
+                this._gl.texParameterf(key, anisotropicFilterExtension.TEXTURE_MAX_ANISOTROPY_EXT, Math.min(value, this._caps.maxAnisotropy));
+                texture._cachedAnisotropicFilteringLevel = value;
             }
         }
 

+ 30 - 13
Babylon/babylon.scene.js

@@ -102,6 +102,7 @@ var BABYLON;
             this._proceduralTextures = new Array();
             this.soundTracks = new Array();
             this._audioEnabled = true;
+            this._headphone = false;
             this._totalVertices = 0;
             this._activeVertices = 0;
             this._activeParticles = 0;
@@ -1195,6 +1196,7 @@ var BABYLON;
             }
         };
         Object.defineProperty(Scene.prototype, "audioEnabled", {
+            // Audio
             get: function () {
                 return this._audioEnabled;
             },
@@ -1234,6 +1236,34 @@ var BABYLON;
                 }
             }
         };
+        Object.defineProperty(Scene.prototype, "headphone", {
+            get: function () {
+                return this._headphone;
+            },
+            set: function (value) {
+                this._headphone = value;
+                if (this._headphone) {
+                    this._switchAudioModeForHeadphones();
+                }
+                else {
+                    this._switchAudioModeForNormalSpeakers();
+                }
+            },
+            enumerable: true,
+            configurable: true
+        });
+        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();
+            }
+        };
         Scene.prototype.enableDepthRenderer = function () {
             if (this._depthRenderer) {
                 return this._depthRenderer;
@@ -1565,19 +1595,6 @@ var BABYLON;
         Scene.prototype.getMaterialByTags = function (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
         Scene._FOGMODE_NONE = 0;
         Scene._FOGMODE_EXP = 1;

+ 32 - 17
Babylon/babylon.scene.ts

@@ -191,6 +191,7 @@
         public mainSoundTrack: SoundTrack;
         public soundTracks = new Array<SoundTrack>();
         private _audioEnabled = true;
+        private _headphone = false;
 
         //Simplification Queue
         public simplificationQueue: SimplificationQueue;
@@ -1528,6 +1529,7 @@
             }
         }
 
+        // Audio
         public get audioEnabled(): boolean {
             return this._audioEnabled;
         }
@@ -1568,6 +1570,36 @@
             }
         }
 
+        public get headphone(): boolean {
+            return this._headphone;
+        }
+
+        public set headphone(value: boolean) {
+            this._headphone = value;
+            if (this._headphone) {
+                this._switchAudioModeForHeadphones();
+            }
+            else {
+                this._switchAudioModeForNormalSpeakers();
+            }
+        }
+
+        private _switchAudioModeForHeadphones() {
+            this.mainSoundTrack.switchPanningModelToHRTF();
+
+            for (var i = 0; i < this.soundTracks.length; i++) {
+                this.soundTracks[i].switchPanningModelToHRTF();
+            }
+        }
+
+        private _switchAudioModeForNormalSpeakers() {
+            this.mainSoundTrack.switchPanningModelToEqualPower();
+
+            for (var i = 0; i < this.soundTracks.length; i++) {
+                this.soundTracks[i].switchPanningModelToEqualPower();
+            }
+        }
+
         public enableDepthRenderer(): DepthRenderer {
             if (this._depthRenderer) {
                 return this._depthRenderer;
@@ -1998,22 +2030,5 @@
         public getMaterialByTags(tagsQuery: string, forEach?: (material: Material) => void): Material[] {
             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();
-            }
-        }
     }
 } 

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 210 - 107
babylon.2.1-alpha.debug.js


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 20 - 19
babylon.2.1-alpha.js