Browse Source

merged with master

Benjamin Guignabert 8 years ago
parent
commit
09e3fef5b2
100 changed files with 11630 additions and 7897 deletions
  1. 1684 545
      Exporters/3ds Max/ActionsBuilder/Sources/babylon.max.js
  2. 2 2
      Exporters/3ds Max/BabylonExport.Entities/BabylonShadowGenerator.cs
  3. BIN
      Exporters/3ds Max/Max2Babylon-0.7.0.zip
  4. 1 1
      Exporters/3ds Max/Max2Babylon/2017/Max2Babylon2017.csproj
  5. 5 5
      Exporters/3ds Max/Max2Babylon/Exporter/BabylonExporter.ShadowGenerator.cs
  6. 1 2
      Exporters/3ds Max/Max2Babylon/Forms/CameraPropertiesForm.Designer.cs
  7. 3 4
      Exporters/3ds Max/Max2Babylon/Forms/LightPropertiesForm.Designer.cs
  8. 1 1
      Exporters/3ds Max/Max2Babylon/Forms/LightPropertiesForm.cs
  9. 1 3
      Exporters/3ds Max/Max2Babylon/Forms/ObjectPropertiesForm.Designer.cs
  10. 13 13
      Exporters/Blender/io_export_babylon.py
  11. 1 1
      Playground/scripts/shadows.js
  12. BIN
      Playground/textures/babylonjs.mp4
  13. BIN
      Playground/textures/babylonjs.webm
  14. 11 2
      Tools/Gulp/config.json
  15. BIN
      assets/sounds/explosion.wav
  16. BIN
      assets/sounds/jump.wav
  17. BIN
      assets/textures/Ground.jpg
  18. BIN
      assets/textures/babylonjs.mp4
  19. BIN
      assets/textures/babylonjs.webm
  20. 44 33
      canvas2D/src/Engine/babylon.canvas2d.ts
  21. 4 4
      canvas2D/src/Engine/babylon.ellipse2d.ts
  22. 5 3
      canvas2D/src/Engine/babylon.fontTexture.ts
  23. 28 10
      canvas2D/src/Engine/babylon.group2d.ts
  24. 17 0
      canvas2D/src/Engine/babylon.modelRenderCache.ts
  25. 28 22
      canvas2D/src/Engine/babylon.prim2dBase.ts
  26. 4 4
      canvas2D/src/Engine/babylon.rectangle2d.ts
  27. 12 13
      canvas2D/src/Engine/babylon.renderablePrim2d.ts
  28. 3 3
      canvas2D/src/Engine/babylon.shape2d.ts
  29. 9 3
      canvas2D/src/Engine/babylon.text2d.ts
  30. 10 8
      canvas2D/src/shaders/sprite2d.vertex.fx
  31. 1 1
      canvas2D/src/shaders/text2d.fragment.fx
  32. 6 5
      canvas2D/src/shaders/text2d.vertex.fx
  33. 29 30
      dist/preview release/babylon.core.js
  34. 3252 3166
      dist/preview release/babylon.d.ts
  35. 40 41
      dist/preview release/babylon.js
  36. 524 162
      dist/preview release/babylon.max.js
  37. 3252 3166
      dist/preview release/babylon.module.d.ts
  38. 39 39
      dist/preview release/babylon.noworker.js
  39. 8 3
      dist/preview release/canvas2D/babylon.canvas2d.d.ts
  40. 141 92
      dist/preview release/canvas2D/babylon.canvas2d.js
  41. 12 12
      dist/preview release/canvas2D/babylon.canvas2d.min.js
  42. 251 251
      dist/preview release/inspector/babylon.inspector.bundle.js
  43. 41 0
      dist/preview release/inspector/babylon.inspector.d.ts
  44. 153 3
      dist/preview release/inspector/babylon.inspector.js
  45. 3 3
      dist/preview release/inspector/babylon.inspector.min.js
  46. 16 0
      dist/preview release/materialsLibrary/babylon.customMaterial.d.ts
  47. 398 0
      dist/preview release/materialsLibrary/babylon.customMaterial.js
  48. 1 0
      dist/preview release/materialsLibrary/babylon.customMaterial.min.js
  49. 8 1
      dist/preview release/what's new.md
  50. 0 1
      inspector/src/Inspector.ts
  51. 59 0
      inspector/src/adapters/SoundAdapter.ts
  52. 18 0
      inspector/src/properties.ts
  53. 26 0
      inspector/src/tabs/SoundTab.ts
  54. 1 0
      inspector/src/tabs/TabBar.ts
  55. 42 0
      inspector/src/treetools/SoundInteractions.ts
  56. 12 0
      inspector/test/index.js
  57. 3 3
      loaders/src/glTF/babylon.glTFFileLoaderExtension.ts
  58. 0 34
      localDev/template/index.js
  59. 1 0
      materialsLibrary/src/custom/Babylon.CustomMaterial.js.map
  60. 398 0
      materialsLibrary/src/custom/babylon.customMaterial.js
  61. 474 0
      materialsLibrary/src/custom/babylon.customMaterial.ts
  62. 4 4
      materialsLibrary/src/gradient/babylon.gradientMaterial.ts
  63. 4 4
      materialsLibrary/src/lava/babylon.lavaMaterial.ts
  64. 4 4
      materialsLibrary/src/normal/babylon.normalMaterial.ts
  65. 33 23
      src/Bones/babylon.boneIKController.ts
  66. 1 1
      src/Cameras/Inputs/babylon.freecamera.input.gamepad.ts
  67. 94 34
      src/Cameras/VR/babylon.webVRCamera.ts
  68. 1 1
      src/Cameras/babylon.arcRotateCamera.ts
  69. 2 4
      src/Cameras/babylon.camera.ts
  70. 1 2
      src/Cameras/babylon.targetCamera.ts
  71. 11 2
      src/Culling/babylon.boundingBox.ts
  72. 1 1
      src/Culling/babylon.boundingInfo.ts
  73. 8 0
      src/Culling/babylon.rayHelper.ts
  74. 89 39
      src/Lights/Shadows/babylon.shadowGenerator.ts
  75. 14 7
      src/Lights/babylon.directionalLight.ts
  76. 3 2
      src/Lights/babylon.light.ts
  77. 14 7
      src/Lights/babylon.pointLight.ts
  78. 16 8
      src/Lights/babylon.spotLight.ts
  79. 13 2
      src/Loading/babylon.sceneLoader.ts
  80. 1 0
      src/Materials/Textures/babylon.texture.ts
  81. 10 2
      src/Materials/Textures/babylon.videoTexture.ts
  82. 10 11
      src/Materials/babylon.materialHelper.ts
  83. 28 2
      src/Materials/babylon.pbrMaterial.ts
  84. 7 0
      src/Materials/babylon.shaderMaterial.ts
  85. 26 13
      src/Materials/babylon.standardMaterial.ts
  86. 37 3
      src/Math/babylon.math.ts
  87. 3 2
      src/Mesh/babylon.abstractMesh.ts
  88. 1 1
      src/Mesh/babylon.instancedMesh.ts
  89. 1 1
      src/Mesh/babylon.mesh.ts
  90. 58 12
      src/Mesh/babylon.mesh.vertexData.ts
  91. 1 1
      src/Mesh/babylon.meshBuilder.ts
  92. 6 0
      src/Mesh/babylon.vertexBuffer.ts
  93. 3 3
      src/Physics/babylon.physicsImpostor.ts
  94. 1 1
      src/PostProcess/babylon.fxaaPostProcess.ts
  95. 2 2
      src/PostProcess/babylon.passPostProcess.ts
  96. 6 2
      src/Shaders/ShadersInclude/bumpFragment.fx
  97. 7 1
      src/Shaders/ShadersInclude/bumpFragmentFunctions.fx
  98. 8 0
      src/Shaders/ShadersInclude/bumpVertex.fx
  99. 5 0
      src/Shaders/ShadersInclude/bumpVertexDeclaration.fx
  100. 0 0
      src/Shaders/ShadersInclude/lightFragment.fx

File diff suppressed because it is too large
+ 1684 - 545
Exporters/3ds Max/ActionsBuilder/Sources/babylon.max.js


+ 2 - 2
Exporters/3ds Max/BabylonExport.Entities/BabylonShadowGenerator.cs

@@ -15,13 +15,13 @@ namespace BabylonExport.Entities
         public string lightId { get; set; }
         public string lightId { get; set; }
 
 
         [DataMember]
         [DataMember]
-        public bool useVarianceShadowMap { get; set; }
+        public bool useExponentialShadowMap { get; set; }
 
 
         [DataMember]
         [DataMember]
         public bool usePoissonSampling { get; set; }
         public bool usePoissonSampling { get; set; }
 
 
         [DataMember]
         [DataMember]
-        public bool useBlurVarianceShadowMap { get; set; }
+        public bool useBlurExponentialShadowMap { get; set; }
 
 
         [DataMember]
         [DataMember]
         public float darkness { get; set; }
         public float darkness { get; set; }

BIN
Exporters/3ds Max/Max2Babylon-0.7.0.zip


+ 1 - 1
Exporters/3ds Max/Max2Babylon/2017/Max2Babylon2017.csproj

@@ -23,7 +23,7 @@
     <DebugSymbols>true</DebugSymbols>
     <DebugSymbols>true</DebugSymbols>
     <DebugType>full</DebugType>
     <DebugType>full</DebugType>
     <Optimize>false</Optimize>
     <Optimize>false</Optimize>
-    <OutputPath>C:\Program Files\Autodesk\3ds Max 2017\bin\assemblies\</OutputPath>
+    <OutputPath>c:\Program Files\Autodesk\3ds Max 2017\bin\assemblies\</OutputPath>
     <DefineConstants>TRACE;DEBUG;MAX2017</DefineConstants>
     <DefineConstants>TRACE;DEBUG;MAX2017</DefineConstants>
     <ErrorReport>prompt</ErrorReport>
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
     <WarningLevel>4</WarningLevel>

+ 5 - 5
Exporters/3ds Max/Max2Babylon/Exporter/BabylonExporter.ShadowGenerator.cs

@@ -20,7 +20,7 @@ namespace Max2Babylon
             babylonShadowGenerator.bias = lightNode.GetFloatProperty("babylonjs_shadows_bias", 0.00005f);
             babylonShadowGenerator.bias = lightNode.GetFloatProperty("babylonjs_shadows_bias", 0.00005f);
             babylonShadowGenerator.forceBackFacesOnly = lightNode.GetBoolProperty("babylonjs_forcebackfaces");
             babylonShadowGenerator.forceBackFacesOnly = lightNode.GetBoolProperty("babylonjs_forcebackfaces");
 
 
-            var shadowsType = lightNode.GetStringProperty("babylonjs_shadows_type", "Blurred Variance");
+            var shadowsType = lightNode.GetStringProperty("babylonjs_shadows_type", "Blurred ESM");
 
 
             switch (shadowsType)
             switch (shadowsType)
             {
             {
@@ -29,11 +29,11 @@ namespace Max2Babylon
                 case "Poisson Sampling":
                 case "Poisson Sampling":
                     babylonShadowGenerator.usePoissonSampling = true;
                     babylonShadowGenerator.usePoissonSampling = true;
                     break;
                     break;
-                case "Variance":
-                    babylonShadowGenerator.useVarianceShadowMap = true;
+                case "ESM":
+                    babylonShadowGenerator.useExponentialShadowMap = true;
                     break;
                     break;
-                case"Blurred Variance":
-                    babylonShadowGenerator.useBlurVarianceShadowMap = true;
+                case"Blurred ESM":
+                    babylonShadowGenerator.useBlurExponentialShadowMap = true;
                     babylonShadowGenerator.blurScale = lightNode.GetFloatProperty("babylonjs_shadows_blurScale", 2);
                     babylonShadowGenerator.blurScale = lightNode.GetFloatProperty("babylonjs_shadows_blurScale", 2);
                     babylonShadowGenerator.blurBoxOffset = lightNode.GetFloatProperty("babylonjs_shadows_blurBoxOffset", 1);
                     babylonShadowGenerator.blurBoxOffset = lightNode.GetFloatProperty("babylonjs_shadows_blurBoxOffset", 1);
                     break;
                     break;

+ 1 - 2
Exporters/3ds Max/Max2Babylon/Forms/CameraPropertiesForm.Designer.cs

@@ -310,7 +310,7 @@
             // label6
             // label6
             // 
             // 
             this.label6.AutoSize = true;
             this.label6.AutoSize = true;
-            this.label6.Location = new System.Drawing.Point(16, 58);
+            this.label6.Location = new System.Drawing.Point(16, 57);
             this.label6.Name = "label6";
             this.label6.Name = "label6";
             this.label6.Size = new System.Drawing.Size(34, 13);
             this.label6.Size = new System.Drawing.Size(34, 13);
             this.label6.TabIndex = 6;
             this.label6.TabIndex = 6;
@@ -319,7 +319,6 @@
             // cbCameraType
             // cbCameraType
             // 
             // 
             this.cbCameraType.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
             this.cbCameraType.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
-            this.cbCameraType.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
             this.cbCameraType.FormattingEnabled = true;
             this.cbCameraType.FormattingEnabled = true;
             this.cbCameraType.Items.AddRange(new object[] {
             this.cbCameraType.Items.AddRange(new object[] {
             "AnaglyphArcRotateCamera",
             "AnaglyphArcRotateCamera",

+ 3 - 4
Exporters/3ds Max/Max2Babylon/Forms/LightPropertiesForm.Designer.cs

@@ -324,7 +324,7 @@
             // label6
             // label6
             // 
             // 
             this.label6.AutoSize = true;
             this.label6.AutoSize = true;
-            this.label6.Location = new System.Drawing.Point(18, 92);
+            this.label6.Location = new System.Drawing.Point(18, 91);
             this.label6.Name = "label6";
             this.label6.Name = "label6";
             this.label6.Size = new System.Drawing.Size(34, 13);
             this.label6.Size = new System.Drawing.Size(34, 13);
             this.label6.TabIndex = 8;
             this.label6.TabIndex = 8;
@@ -342,13 +342,12 @@
             // cbCameraType
             // cbCameraType
             // 
             // 
             this.cbCameraType.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
             this.cbCameraType.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
-            this.cbCameraType.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
             this.cbCameraType.FormattingEnabled = true;
             this.cbCameraType.FormattingEnabled = true;
             this.cbCameraType.Items.AddRange(new object[] {
             this.cbCameraType.Items.AddRange(new object[] {
             "Hard shadows",
             "Hard shadows",
             "Poisson Sampling",
             "Poisson Sampling",
-            "Variance",
-            "Blurred Variance"});
+            "ESM",
+            "Blurred ESM"});
             this.cbCameraType.Location = new System.Drawing.Point(21, 108);
             this.cbCameraType.Location = new System.Drawing.Point(21, 108);
             this.cbCameraType.Name = "cbCameraType";
             this.cbCameraType.Name = "cbCameraType";
             this.cbCameraType.Size = new System.Drawing.Size(289, 21);
             this.cbCameraType.Size = new System.Drawing.Size(289, 21);

+ 1 - 1
Exporters/3ds Max/Max2Babylon/Forms/LightPropertiesForm.cs

@@ -36,7 +36,7 @@ namespace Max2Babylon
             Tools.PrepareNumericUpDown(nupBias, lights, "babylonjs_shadows_bias", 0.00005f);
             Tools.PrepareNumericUpDown(nupBias, lights, "babylonjs_shadows_bias", 0.00005f);
             Tools.PrepareNumericUpDown(nupBlurScale, lights, "babylonjs_shadows_blurScale", 2);
             Tools.PrepareNumericUpDown(nupBlurScale, lights, "babylonjs_shadows_blurScale", 2);
             Tools.PrepareNumericUpDown(nupBlurBoxOffset, lights, "babylonjs_shadows_blurBoxOffset", 1);
             Tools.PrepareNumericUpDown(nupBlurBoxOffset, lights, "babylonjs_shadows_blurBoxOffset", 1);
-            Tools.PrepareComboBox(cbCameraType, lights[0], "babylonjs_shadows_type", "Blurred Variance");
+            Tools.PrepareComboBox(cbCameraType, lights[0], "babylonjs_shadows_type", "Blurred ESM");
         }
         }
 
 
         private void butOK_Click(object sender, EventArgs e)
         private void butOK_Click(object sender, EventArgs e)

+ 1 - 3
Exporters/3ds Max/Max2Babylon/Forms/ObjectPropertiesForm.Designer.cs

@@ -412,7 +412,7 @@
             // label6
             // label6
             // 
             // 
             this.label6.AutoSize = true;
             this.label6.AutoSize = true;
-            this.label6.Location = new System.Drawing.Point(18, 27);
+            this.label6.Location = new System.Drawing.Point(18, 26);
             this.label6.Name = "label6";
             this.label6.Name = "label6";
             this.label6.Size = new System.Drawing.Size(50, 13);
             this.label6.Size = new System.Drawing.Size(50, 13);
             this.label6.TabIndex = 8;
             this.label6.TabIndex = 8;
@@ -421,7 +421,6 @@
             // cbImpostor
             // cbImpostor
             // 
             // 
             this.cbImpostor.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
             this.cbImpostor.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
-            this.cbImpostor.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
             this.cbImpostor.FormattingEnabled = true;
             this.cbImpostor.FormattingEnabled = true;
             this.cbImpostor.Items.AddRange(new object[] {
             this.cbImpostor.Items.AddRange(new object[] {
             "None",
             "None",
@@ -681,7 +680,6 @@
             // cbDistanceModel
             // cbDistanceModel
             // 
             // 
             this.cbDistanceModel.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
             this.cbDistanceModel.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
-            this.cbDistanceModel.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
             this.cbDistanceModel.FormattingEnabled = true;
             this.cbDistanceModel.FormattingEnabled = true;
             this.cbDistanceModel.Items.AddRange(new object[] {
             this.cbDistanceModel.Items.AddRange(new object[] {
             "linear",
             "linear",

+ 13 - 13
Exporters/Blender/io_export_babylon.py

@@ -100,8 +100,8 @@ HEMI_LIGHT = 3
 NO_SHADOWS = 'NONE'
 NO_SHADOWS = 'NONE'
 STD_SHADOWS = 'STD'
 STD_SHADOWS = 'STD'
 POISSON_SHADOWS = 'POISSON'
 POISSON_SHADOWS = 'POISSON'
-VARIANCE_SHADOWS = 'VARIANCE'
-BLUR_VARIANCE_SHADOWS = 'BLUR_VARIANCE'
+ESM_SHADOWS = 'ESM'
+BLUR_ESM_SHADOWS = 'BLUR_ESM'
 
 
 # used in Texture constructor, defined in BABYLON.Texture
 # used in Texture constructor, defined in BABYLON.Texture
 CLAMP_ADDRESSMODE = 0
 CLAMP_ADDRESSMODE = 0
@@ -1656,12 +1656,12 @@ class ShadowGenerator:
         self.mapSize = lamp.data.shadowMapSize
         self.mapSize = lamp.data.shadowMapSize
         self.shadowBias = lamp.data.shadowBias
         self.shadowBias = lamp.data.shadowBias
 
 
-        if lamp.data.shadowMap == VARIANCE_SHADOWS:
-            self.useVarianceShadowMap = True
+        if lamp.data.shadowMap == ESM_SHADOWS:
+            self.useExponentialShadowMap = True
         elif lamp.data.shadowMap == POISSON_SHADOWS:
         elif lamp.data.shadowMap == POISSON_SHADOWS:
             self.usePoissonSampling = True
             self.usePoissonSampling = True
-        elif lamp.data.shadowMap == BLUR_VARIANCE_SHADOWS:
-            self.useBlurVarianceShadowMap = True
+        elif lamp.data.shadowMap == BLUR_ESM_SHADOWS:
+            self.useBlurExponentialShadowMap = True
             self.shadowBlurScale = lamp.data.shadowBlurScale
             self.shadowBlurScale = lamp.data.shadowBlurScale
             self.shadowBlurBoxOffset = lamp.data.shadowBlurBoxOffset
             self.shadowBlurBoxOffset = lamp.data.shadowBlurBoxOffset
 
 
@@ -1677,12 +1677,12 @@ class ShadowGenerator:
         write_string(file_handler, 'lightId', self.lightId)
         write_string(file_handler, 'lightId', self.lightId)
         write_float(file_handler, 'bias', self.shadowBias)
         write_float(file_handler, 'bias', self.shadowBias)
 
 
-        if hasattr(self, 'useVarianceShadowMap') :
-            write_bool(file_handler, 'useVarianceShadowMap', self.useVarianceShadowMap)
+        if hasattr(self, 'useExponentialShadowMap') :
+            write_bool(file_handler, 'useExponentialShadowMap', self.useExponentialShadowMap)
         elif hasattr(self, 'usePoissonSampling'):
         elif hasattr(self, 'usePoissonSampling'):
             write_bool(file_handler, 'usePoissonSampling', self.usePoissonSampling)
             write_bool(file_handler, 'usePoissonSampling', self.usePoissonSampling)
-        elif hasattr(self, 'useBlurVarianceShadowMap'):
-            write_bool(file_handler, 'useBlurVarianceShadowMap', self.useBlurVarianceShadowMap)
+        elif hasattr(self, 'useBlurExponentialShadowMap'):
+            write_bool(file_handler, 'useBlurExponentialShadowMap', self.useBlurExponentialShadowMap)
             write_int(file_handler, 'blurScale', self.shadowBlurScale)
             write_int(file_handler, 'blurScale', self.shadowBlurScale)
             write_int(file_handler, 'blurBoxOffset', self.shadowBlurBoxOffset)
             write_int(file_handler, 'blurBoxOffset', self.shadowBlurBoxOffset)
 
 
@@ -2713,8 +2713,8 @@ bpy.types.Lamp.shadowMap = bpy.props.EnumProperty(
     items = ((NO_SHADOWS           , 'None'         , 'No Shadow Maps'),
     items = ((NO_SHADOWS           , 'None'         , 'No Shadow Maps'),
              (STD_SHADOWS          , 'Standard'     , 'Use Standard Shadow Maps'),
              (STD_SHADOWS          , 'Standard'     , 'Use Standard Shadow Maps'),
              (POISSON_SHADOWS      , 'Poisson'      , 'Use Poisson Sampling'),
              (POISSON_SHADOWS      , 'Poisson'      , 'Use Poisson Sampling'),
-             (VARIANCE_SHADOWS     , 'Variance'     , 'Use Variance Shadow Maps'),
-             (BLUR_VARIANCE_SHADOWS, 'Blur Variance', 'Use Blur Variance Shadow Maps')
+             (ESM_SHADOWS          , 'ESM'          , 'Use Exponential Shadow Maps'),
+             (BLUR_ESM_SHADOWS     , 'Blur ESM'     , 'Use Blur Exponential Shadow Maps')
             ),
             ),
     default = NO_SHADOWS
     default = NO_SHADOWS
 )
 )
@@ -2809,7 +2809,7 @@ class ObjectPanel(bpy.types.Panel):
             layout.prop(ob.data, 'shadowBias')
             layout.prop(ob.data, 'shadowBias')
 
 
             box = layout.box()
             box = layout.box()
-            box.label(text="Blur Variance Shadows")
+            box.label(text="Blur ESM Shadows")
             box.prop(ob.data, 'shadowBlurScale')
             box.prop(ob.data, 'shadowBlurScale')
             box.prop(ob.data, 'shadowBlurBoxOffset')
             box.prop(ob.data, 'shadowBlurBoxOffset')
 
 

+ 1 - 1
Playground/scripts/shadows.js

@@ -45,7 +45,7 @@
 	// Shadows
 	// Shadows
 	var shadowGenerator = new BABYLON.ShadowGenerator(1024, light);
 	var shadowGenerator = new BABYLON.ShadowGenerator(1024, light);
 	shadowGenerator.getShadowMap().renderList.push(torus);
 	shadowGenerator.getShadowMap().renderList.push(torus);
-	shadowGenerator.useVarianceShadowMap = true;
+	shadowGenerator.useExponentialShadowMap = true;
 
 
 	var shadowGenerator2 = new BABYLON.ShadowGenerator(1024, light2);
 	var shadowGenerator2 = new BABYLON.ShadowGenerator(1024, light2);
 	shadowGenerator2.getShadowMap().renderList.push(torus);
 	shadowGenerator2.getShadowMap().renderList.push(torus);

BIN
Playground/textures/babylonjs.mp4


BIN
Playground/textures/babylonjs.webm


+ 11 - 2
Tools/Gulp/config.json

@@ -35,7 +35,7 @@
             "../../src/Culling/babylon.boundingBox.js",
             "../../src/Culling/babylon.boundingBox.js",
             "../../src/Culling/babylon.boundingInfo.js",
             "../../src/Culling/babylon.boundingInfo.js",
             "../../src/Culling/babylon.ray.js",
             "../../src/Culling/babylon.ray.js",
-            "../../src/Culling/babylon.rayHelper.js",
+            "../../src/Debug/babylon.rayHelper.js",
             "../../src/Mesh/babylon.abstractMesh.js",
             "../../src/Mesh/babylon.abstractMesh.js",
             "../../src/Lights/babylon.light.js",
             "../../src/Lights/babylon.light.js",
             "../../src/Lights/babylon.pointLight.js",
             "../../src/Lights/babylon.pointLight.js",
@@ -362,6 +362,12 @@
                     "../../materialsLibrary/src/grid/legacygrid.fragment.fx"
                     "../../materialsLibrary/src/grid/legacygrid.fragment.fx"
                 ],
                 ],
                 "output": "babylon.gridMaterial.js"
                 "output": "babylon.gridMaterial.js"
+            },
+            {
+                "files": [
+                    "../../materialsLibrary/src/custom/babylon.customMaterial.ts"
+                ], 
+                "output": "babylon.customMaterial.js"
             }
             }
         ],
         ],
         "build": {
         "build": {
@@ -588,6 +594,7 @@
                     "../../inspector/src/gui/BasicElement.ts",
                     "../../inspector/src/gui/BasicElement.ts",
                     "../../inspector/src/adapters/Adapter.ts",
                     "../../inspector/src/adapters/Adapter.ts",
                     "../../inspector/src/adapters/CameraAdapter.ts",
                     "../../inspector/src/adapters/CameraAdapter.ts",
+                    "../../inspector/src/adapters/SoundAdapter.ts",
                     "../../inspector/src/adapters/TextureAdapter.ts",
                     "../../inspector/src/adapters/TextureAdapter.ts",
                     "../../inspector/src/adapters/Canvas2DAdapter.ts",
                     "../../inspector/src/adapters/Canvas2DAdapter.ts",
                     "../../inspector/src/adapters/LightAdapter.ts",
                     "../../inspector/src/adapters/LightAdapter.ts",
@@ -607,6 +614,7 @@
                     "../../inspector/src/tabs/Tab.ts",
                     "../../inspector/src/tabs/Tab.ts",
                     "../../inspector/src/tabs/PropertyTab.ts",
                     "../../inspector/src/tabs/PropertyTab.ts",
                     "../../inspector/src/tabs/CameraTab.ts",
                     "../../inspector/src/tabs/CameraTab.ts",
+                    "../../inspector/src/tabs/SoundTab.ts",
                     "../../inspector/src/tabs/TextureTab.ts",
                     "../../inspector/src/tabs/TextureTab.ts",
                     "../../inspector/src/tabs/Canvas2DTab.ts",
                     "../../inspector/src/tabs/Canvas2DTab.ts",
                     "../../inspector/src/tabs/LightTab.ts",
                     "../../inspector/src/tabs/LightTab.ts",
@@ -629,6 +637,7 @@
                     "../../inspector/src/treetools/AbstractTreeTool.ts",
                     "../../inspector/src/treetools/AbstractTreeTool.ts",
                     "../../inspector/src/treetools/BoundingBox.ts",
                     "../../inspector/src/treetools/BoundingBox.ts",
                     "../../inspector/src/treetools/CameraPOV.ts",
                     "../../inspector/src/treetools/CameraPOV.ts",
+                    "../../inspector/src/treetools/SoundInteractions.ts",
                     "../../inspector/src/treetools/Checkbox.ts",
                     "../../inspector/src/treetools/Checkbox.ts",
                     "../../inspector/src/treetools/DebugArea.ts",
                     "../../inspector/src/treetools/DebugArea.ts",
                     "../../inspector/src/treetools/Info.ts",
                     "../../inspector/src/treetools/Info.ts",
@@ -646,4 +655,4 @@
             "distOutputDirectory": "/inspector/"
             "distOutputDirectory": "/inspector/"
         }
         }
     }
     }
-}
+}

BIN
assets/sounds/explosion.wav


BIN
assets/sounds/jump.wav


BIN
assets/textures/Ground.jpg


BIN
assets/textures/babylonjs.mp4


BIN
assets/textures/babylonjs.webm


+ 44 - 33
canvas2D/src/Engine/babylon.canvas2d.ts

@@ -156,7 +156,7 @@
             this._engine = engine;
             this._engine = engine;
             this._renderingSize = new Size(0, 0);
             this._renderingSize = new Size(0, 0);
             this._curHWScale = 0;
             this._curHWScale = 0;
-            this._canvasLevelScale = new Vector3(1, 1, 1);
+            this._canvasLevelScale = new Vector2(1, 1);
             this._designSize = settings.designSize || null;
             this._designSize = settings.designSize || null;
             this._designUseHorizAxis = settings.designUseHorizAxis === true;
             this._designUseHorizAxis = settings.designUseHorizAxis === true;
             if (!this._trackedGroups) {
             if (!this._trackedGroups) {
@@ -359,9 +359,7 @@
                     if (this.isVisible === false) {
                     if (this.isVisible === false) {
                         return;
                         return;
                     }
                     }
-                    let hs = 1 / this.engine.getHardwareScalingLevel();
-                    let localPos = e.localPosition.multiplyByFloats(hs, hs);
-                    this._handlePointerEventForInteraction(e, localPos, s);
+                    this._handlePointerEventForInteraction(e, e.localPosition, s);
                 });
                 });
             }
             }
 
 
@@ -555,7 +553,7 @@
         }
         }
 
 
         private _updatePointerInfo(eventData: PointerInfoBase, localPosition: Vector2): boolean {
         private _updatePointerInfo(eventData: PointerInfoBase, localPosition: Vector2): boolean {
-            let s = this.scale;
+            let s = this._canvasLevelScale.multiplyByFloats(this.scaleX, this.scaleY);
             let pii = this._primPointerInfo;
             let pii = this._primPointerInfo;
             pii.cancelBubble = false;
             pii.cancelBubble = false;
             if (!pii.canvasPointerPos) {
             if (!pii.canvasPointerPos) {
@@ -570,17 +568,20 @@
 
 
             if (this._isScreenSpace) {
             if (this._isScreenSpace) {
                 var cameraViewport = camera.viewport;
                 var cameraViewport = camera.viewport;
-                var viewport = cameraViewport.toGlobal(engine.getRenderWidth(), engine.getRenderHeight());
+                let renderWidth = engine.getRenderWidth();
+                let renderHeight = engine.getRenderHeight();
+//                console.log(`Render Width: ${renderWidth} Height: ${renderHeight}, localX: ${localPosition.x}, localY: ${localPosition.y}`);
+                var viewport = cameraViewport.toGlobal(renderWidth, renderHeight);
 
 
                 // Moving coordinates to local viewport world
                 // Moving coordinates to local viewport world
                 var x = localPosition.x - viewport.x;
                 var x = localPosition.x - viewport.x;
                 var y = localPosition.y - viewport.y;
                 var y = localPosition.y - viewport.y;
 
 
-                pii.canvasPointerPos.x = (x - this.actualPosition.x) / s;
-                pii.canvasPointerPos.y = (engine.getRenderHeight() - y - this.actualPosition.y) / s;
+                pii.canvasPointerPos.x = (x - this.actualPosition.x) / s.x;
+                pii.canvasPointerPos.y = (renderHeight - y - this.actualPosition.y) / s.y;
             } else {
             } else {
-                pii.canvasPointerPos.x = localPosition.x / s;
-                pii.canvasPointerPos.y = localPosition.y / s;
+                pii.canvasPointerPos.x = localPosition.x / s.x;
+                pii.canvasPointerPos.y = localPosition.y / s.x;
             }
             }
             //console.log(`UpdatePointerInfo for ${this.id}, X:${pii.canvasPointerPos.x}, Y:${pii.canvasPointerPos.y}`);
             //console.log(`UpdatePointerInfo for ${this.id}, X:${pii.canvasPointerPos.x}, Y:${pii.canvasPointerPos.y}`);
             pii.mouseWheelDelta = 0;
             pii.mouseWheelDelta = 0;
@@ -830,13 +831,13 @@
 
 
                             if (ii.isPrimIntersected(prim) !== null) {
                             if (ii.isPrimIntersected(prim) !== null) {
                                 if (prim.actionManager) {
                                 if (prim.actionManager) {
-                                    if (this._pickStartingTime !== 0 && ((new Date().getTime() - this._pickStartingTime) > ActionManager.LongPressDelay) && (Math.abs(this._pickStartingPosition.x - ii.pickPosition.x) < ActionManager.DragMovementThreshold && Math.abs(this._pickStartingPosition.y - ii.pickPosition.y) < ActionManager.DragMovementThreshold)) {
+                                    if (this._pickStartingTime !== 0 && ((new Date().getTime() - this._pickStartingTime) > Scene.LongPressDelay) && (Math.abs(this._pickStartingPosition.x - ii.pickPosition.x) < Scene.DragMovementThreshold && Math.abs(this._pickStartingPosition.y - ii.pickPosition.y) < Scene.DragMovementThreshold)) {
                                         this._pickStartingTime = 0;
                                         this._pickStartingTime = 0;
                                         prim.actionManager.processTrigger(ActionManager.OnLongPressTrigger, ActionEvent.CreateNewFromPrimitive(prim, ppi.primitivePointerPos, eventData));
                                         prim.actionManager.processTrigger(ActionManager.OnLongPressTrigger, ActionEvent.CreateNewFromPrimitive(prim, ppi.primitivePointerPos, eventData));
                                     }
                                     }
                                 }
                                 }
                             }
                             }
-                        }, ActionManager.LongPressDelay);
+                        }, Scene.LongPressDelay);
                     }
                     }
                 }
                 }
             }
             }
@@ -851,7 +852,7 @@
                     prim.actionManager.processTrigger(ActionManager.OnPickUpTrigger, actionEvent);
                     prim.actionManager.processTrigger(ActionManager.OnPickUpTrigger, actionEvent);
 
 
                     // OnPickTrigger
                     // OnPickTrigger
-                    if (Math.abs(this._pickStartingPosition.x - ppi.canvasPointerPos.x) < ActionManager.DragMovementThreshold && Math.abs(this._pickStartingPosition.y - ppi.canvasPointerPos.y) < ActionManager.DragMovementThreshold) {
+                    if (Math.abs(this._pickStartingPosition.x - ppi.canvasPointerPos.x) < Scene.DragMovementThreshold && Math.abs(this._pickStartingPosition.y - ppi.canvasPointerPos.y) < Scene.DragMovementThreshold) {
                         prim.actionManager.processTrigger(ActionManager.OnPickTrigger, actionEvent);
                         prim.actionManager.processTrigger(ActionManager.OnPickTrigger, actionEvent);
                     }
                     }
                 }
                 }
@@ -1320,7 +1321,7 @@
         private _designUseHorizAxis: boolean;
         private _designUseHorizAxis: boolean;
         public  _primitiveCollisionManager: PrimitiveCollisionManagerBase;
         public  _primitiveCollisionManager: PrimitiveCollisionManagerBase;
 
 
-        public _canvasLevelScale: Vector3;
+        public _canvasLevelScale: Vector2;
         public  _renderingSize: Size;
         public  _renderingSize: Size;
         private _curHWScale;
         private _curHWScale;
 
 
@@ -1342,6 +1343,7 @@
         private _profileInfoText: Text2D;
         private _profileInfoText: Text2D;
 
 
         private static _v = Vector3.Zero(); // Must stay zero
         private static _v = Vector3.Zero(); // Must stay zero
+        private static _cv1 = Vector2.Zero(); // Must stay zero
         private static _m = Matrix.Identity();
         private static _m = Matrix.Identity();
         private static _mI = Matrix.Identity(); // Must stay identity
         private static _mI = Matrix.Identity(); // Must stay identity
         private static tS = Vector3.Zero();
         private static tS = Vector3.Zero();
@@ -1383,8 +1385,8 @@
                 group.levelVisible = proj.z >= 0 && proj.z < 1.0;
                 group.levelVisible = proj.z >= 0 && proj.z < 1.0;
 
 
                 let s = this.scale;
                 let s = this.scale;
-                group.x = Math.round(proj.x/s);
-                group.y = Math.round((rh - proj.y)/s);
+                group.x = Math.round(proj.x / s);
+                group.y = Math.round((rh - proj.y) / s);
             }
             }
 
 
             // If it's a WorldSpaceCanvas and it's tracking a node, let's update the WSC transformation data
             // If it's a WorldSpaceCanvas and it's tracking a node, let's update the WSC transformation data
@@ -1481,7 +1483,7 @@
                 this._setRenderingScale(scale);
                 this._setRenderingScale(scale);
             }
             }
         }
         }
-        private static _pCLS = Vector3.Zero();
+        private static _pCLS = Vector2.Zero();
 
 
         private _updateCanvasState(forceRecompute: boolean) {
         private _updateCanvasState(forceRecompute: boolean) {
             // Check if the update has already been made for this render Frame
             // Check if the update has already been made for this render Frame
@@ -1519,10 +1521,10 @@
                     scale = this._renderingSize.height / (this._designSize.height * hwsl);
                     scale = this._renderingSize.height / (this._designSize.height * hwsl);
                 }
                 }
                 this.size = this._designSize.clone();
                 this.size = this._designSize.clone();
-                this._canvasLevelScale.copyFromFloats(scale, scale, 1);
+                this._canvasLevelScale.copyFromFloats(scale, scale);
             } else {
             } else {
                 let ratio = 1 / this._curHWScale;
                 let ratio = 1 / this._curHWScale;
-                this._canvasLevelScale.copyFromFloats(ratio, ratio, 1);
+                this._canvasLevelScale.copyFromFloats(ratio, ratio);
             }
             }
 
 
             if (!prevCLS.equals(this._canvasLevelScale)) {
             if (!prevCLS.equals(this._canvasLevelScale)) {
@@ -1627,18 +1629,19 @@
             let isCanvas = parent == null;
             let isCanvas = parent == null;
             let scale: Vector2;
             let scale: Vector2;
             if (noResizeScale) {
             if (noResizeScale) {
-                scale = isCanvas ? Canvas2D._unS : group.parent.actualScale;
+                scale = isCanvas ? Canvas2D._unS : group.parent.actualScale.multiply(this._canvasLevelScale);
             } else {
             } else {
-                scale = group.actualScale;
+                scale = group.actualScale.multiply(this._canvasLevelScale);
             }
             }
 
 
             // Determine size
             // Determine size
             let size = group.actualSize;
             let size = group.actualSize;
-            size = new Size(Math.ceil(size.width * scale.x), Math.ceil(size.height * scale.y));
-            let originalSize = size.clone();
+            let scaledSize = new Size(size.width * scale.x, size.height * scale.y);
+            let roundedScaledSize = new Size(Math.ceil(scaledSize.width), Math.ceil(scaledSize.height));
+            let originalSize = scaledSize.clone();
             if (minSize) {
             if (minSize) {
-                size.width = Math.max(minSize.width, size.width);
-                size.height = Math.max(minSize.height, size.height);
+                roundedScaledSize.width = Math.max(minSize.width, roundedScaledSize.width);
+                roundedScaledSize.height = Math.max(minSize.height, roundedScaledSize.height);
             }
             }
 
 
             let mapArray = this._groupCacheMaps.getOrAddWithFactory(key, () => new Array<MapTexture>());
             let mapArray = this._groupCacheMaps.getOrAddWithFactory(key, () => new Array<MapTexture>());
@@ -1648,7 +1651,7 @@
             var map: MapTexture;
             var map: MapTexture;
             for (var _map of mapArray) {
             for (var _map of mapArray) {
                 map = _map;
                 map = _map;
-                let node = map.allocateRect(size);
+                let node = map.allocateRect(roundedScaledSize);
                 if (node) {
                 if (node) {
                     res = { node: node, texture: map }
                     res = { node: node, texture: map }
                     break;
                     break;
@@ -1660,18 +1663,24 @@
                 let mapSize = new Size(Canvas2D._groupTextureCacheSize, Canvas2D._groupTextureCacheSize);
                 let mapSize = new Size(Canvas2D._groupTextureCacheSize, Canvas2D._groupTextureCacheSize);
 
 
                 // Check if the predefined size would fit, other create a custom size using the nearest bigger power of 2
                 // Check if the predefined size would fit, other create a custom size using the nearest bigger power of 2
-                if (size.width > mapSize.width || size.height > mapSize.height) {
-                    mapSize.width = Math.pow(2, Math.ceil(Math.log(size.width) / Math.log(2)));
-                    mapSize.height = Math.pow(2, Math.ceil(Math.log(size.height) / Math.log(2)));
+                if (roundedScaledSize.width > mapSize.width || roundedScaledSize.height > mapSize.height) {
+                    mapSize.width = Math.pow(2, Math.ceil(Math.log(roundedScaledSize.width) / Math.log(2)));
+                    mapSize.height = Math.pow(2, Math.ceil(Math.log(roundedScaledSize.height) / Math.log(2)));
                 }
                 }
 
 
                 let id = `groupsMapChache${this._mapCounter++}forCanvas${this.id}`;
                 let id = `groupsMapChache${this._mapCounter++}forCanvas${this.id}`;
-                map = new MapTexture(id, this._scene, mapSize, useMipMap ? Texture.TRILINEAR_SAMPLINGMODE : Texture.BILINEAR_SAMPLINGMODE, useMipMap);
+                map = new MapTexture(id, this._scene, mapSize, useMipMap ? Texture.TRILINEAR_SAMPLINGMODE : Texture.BILINEAR_SAMPLINGMODE, useMipMap, 2);
                 map.hasAlpha = true;
                 map.hasAlpha = true;
                 map.anisotropicFilteringLevel = 4;
                 map.anisotropicFilteringLevel = 4;
                 mapArray.splice(0, 0, map);
                 mapArray.splice(0, 0, map);
 
 
-                let node = map.allocateRect(size);
+                //let debug = false;
+
+                //if (debug) {
+                //    let sprite = new Sprite2D(map, { parent: this, x: 10, y: 10, id: "__cachedSpriteOfGroup__Debug", alignToPixel: true });
+                //}
+
+                let node = map.allocateRect(roundedScaledSize);
                 res = { node: node, texture: map }
                 res = { node: node, texture: map }
             }
             }
 
 
@@ -1679,6 +1688,8 @@
             // Don't do it in case of the group being a worldspace canvas (because its texture is bound to a WorldSpaceCanvas node)
             // Don't do it in case of the group being a worldspace canvas (because its texture is bound to a WorldSpaceCanvas node)
             if (group !== <any>this || this._isScreenSpace) {
             if (group !== <any>this || this._isScreenSpace) {
                 let node: PackedRect = res.node;
                 let node: PackedRect = res.node;
+                let pos = Canvas2D._cv1;
+                node.getInnerPosToRef(pos);
 
 
                 // Special case if the canvas is entirely cached: create a group that will have a single sprite it will be rendered specifically at the very end of the rendering process
                 // Special case if the canvas is entirely cached: create a group that will have a single sprite it will be rendered specifically at the very end of the rendering process
 
 
@@ -1688,14 +1699,14 @@
                         this._cachedCanvasGroup.dispose();
                         this._cachedCanvasGroup.dispose();
                     }
                     }
                     this._cachedCanvasGroup = Group2D._createCachedCanvasGroup(this);
                     this._cachedCanvasGroup = Group2D._createCachedCanvasGroup(this);
-                    sprite = new Sprite2D(map, { parent: this._cachedCanvasGroup, id: "__cachedCanvasSprite__", spriteSize: originalSize, spriteLocation: node.pos });
+                    sprite = new Sprite2D(map, { parent: this._cachedCanvasGroup, id: "__cachedCanvasSprite__", spriteSize: originalSize, size: size, alignToPixel: true, spriteLocation: pos });
                     sprite.zOrder = 1;
                     sprite.zOrder = 1;
                     sprite.origin = Vector2.Zero();
                     sprite.origin = Vector2.Zero();
                 }
                 }
 
 
                 // Create a Sprite that will be used to render this cache, the "__cachedSpriteOfGroup__" starting id is a hack to bypass exception throwing in case of the Canvas doesn't normally allows direct primitives
                 // Create a Sprite that will be used to render this cache, the "__cachedSpriteOfGroup__" starting id is a hack to bypass exception throwing in case of the Canvas doesn't normally allows direct primitives
                 else {
                 else {
-                    sprite = new Sprite2D(map, { parent: parent, id: `__cachedSpriteOfGroup__${group.id}`, x: group.actualPosition.x, y: group.actualPosition.y, spriteSize: originalSize, spriteLocation: node.pos, dontInheritParentScale: true });
+                    sprite = new Sprite2D(map, { parent: parent, id: `__cachedSpriteOfGroup__${group.id}`, x: group.x, y: group.y, spriteSize: originalSize, size: size, spriteLocation: pos, alignToPixel: true, dontInheritParentScale: true });
                     sprite.origin = group.origin.clone();
                     sprite.origin = group.origin.clone();
                     sprite.addExternalData("__cachedGroup__", group);
                     sprite.addExternalData("__cachedGroup__", group);
                     sprite.pointerEventObservable.add((e, s) => {
                     sprite.pointerEventObservable.add((e, s) => {

+ 4 - 4
canvas2D/src/Engine/babylon.ellipse2d.ts

@@ -427,18 +427,18 @@
                 return false;
                 return false;
             }
             }
 
 
-            let s = Ellipse2D._riv0;
-            this.getActualGlobalScaleToRef(s);
+            //let s = Ellipse2D._riv0;
+            //this.getActualGlobalScaleToRef(s);
 
 
             if (part.id === Shape2D.SHAPE2D_BORDERPARTID) {
             if (part.id === Shape2D.SHAPE2D_BORDERPARTID) {
                 let d = <Ellipse2DInstanceData>part;
                 let d = <Ellipse2DInstanceData>part;
                 let size = this.actualSize;
                 let size = this.actualSize;
-                d.properties = new Vector3(size.width * s.x, size.height * s.y, this.subdivisions);
+                d.properties = new Vector3(size.width/* * s.x*/, size.height/* * s.y*/, this.subdivisions);
             }
             }
             else if (part.id === Shape2D.SHAPE2D_FILLPARTID) {
             else if (part.id === Shape2D.SHAPE2D_FILLPARTID) {
                 let d = <Ellipse2DInstanceData>part;
                 let d = <Ellipse2DInstanceData>part;
                 let size = this.actualSize;
                 let size = this.actualSize;
-                d.properties = new Vector3(size.width * s.x, size.height * s.y, this.subdivisions);
+                d.properties = new Vector3(size.width/* * s.x*/, size.height/* * s.y*/, this.subdivisions);
             }
             }
             return true;
             return true;
         }
         }

+ 5 - 3
canvas2D/src/Engine/babylon.fontTexture.ts

@@ -415,6 +415,7 @@
             this._signedDistanceField = signedDistanceField;
             this._signedDistanceField = signedDistanceField;
             this._superSample = false;
             this._superSample = false;
             this._isPremultipliedAlpha = !signedDistanceField;
             this._isPremultipliedAlpha = !signedDistanceField;
+            this.name = `FontTexture ${font}`;
 
 
             // SDF will use super sample no matter what, the resolution is otherwise too poor to produce correct result
             // SDF will use super sample no matter what, the resolution is otherwise too poor to produce correct result
             if (superSample || signedDistanceField) {
             if (superSample || signedDistanceField) {
@@ -556,7 +557,7 @@
             var textureSize = this.getSize();
             var textureSize = this.getSize();
 
 
             // we reached the end of the current line?
             // we reached the end of the current line?
-            let width = Math.ceil(measure.width);
+            let width = Math.ceil(measure.width + 0.5);
             if (this._currentFreePosition.x + width + this._xMargin > textureSize.width) {
             if (this._currentFreePosition.x + width + this._xMargin > textureSize.width) {
                 this._currentFreePosition.x = 0;
                 this._currentFreePosition.x = 0;
                 this._currentFreePosition.y += Math.ceil(this._lineHeightSuper + this._yMargin*2);
                 this._currentFreePosition.y += Math.ceil(this._lineHeightSuper + this._yMargin*2);
@@ -626,9 +627,10 @@
             }
             }
 
 
             // Fill the CharInfo object
             // Fill the CharInfo object
-            info.topLeftUV = new Vector2((curPosXMargin) / textureSize.width, (this._currentFreePosition.y + this._yMargin) / textureSize.height);
-            info.bottomRightUV = new Vector2((curPosXMargin + width) / textureSize.width, info.topLeftUV.y + ((this._lineHeightSuper + this._yMargin) / textureSize.height));
+            info.topLeftUV = new Vector2((curPosXMargin-0.5) / textureSize.width, (this._currentFreePosition.y-0.5 + this._yMargin) / textureSize.height);
+            info.bottomRightUV = new Vector2((curPosXMargin-0.5 + width) / textureSize.width, info.topLeftUV.y + (this._lineHeightSuper / textureSize.height));
             info.yOffset = info.xOffset = 0;
             info.yOffset = info.xOffset = 0;
+            //console.log(`Char: ${char}, Offset: ${curPosX}, ${this._currentFreePosition.y + this._yMargin}, Size: ${width}, ${this._lineHeightSuper}, UV: ${info.topLeftUV}, ${info.bottomRightUV}`);
 
 
             if (this._signedDistanceField) {
             if (this._signedDistanceField) {
                 let off = 1/textureSize.width;
                 let off = 1/textureSize.width;

+ 28 - 10
canvas2D/src/Engine/babylon.group2d.ts

@@ -357,9 +357,12 @@
 
 
             let s = this.actualSize;
             let s = this.actualSize;
             let a = this.actualScale;
             let a = this.actualScale;
+            let ss = this.owner._canvasLevelScale;
             let hwsl = 1/this.owner.engine.getHardwareScalingLevel();
             let hwsl = 1/this.owner.engine.getHardwareScalingLevel();
-            let sw = Math.ceil(s.width * a.x * hwsl);
-            let sh = Math.ceil(s.height * a.y * hwsl);
+            //let sw = Math.ceil(s.width * a.x * ss.x/* * hwsl*/);
+            //let sh = Math.ceil(s.height * a.y *ss.y/* *  hwsl*/);
+            let sw = s.width * a.x * ss.x;
+            let sh = s.height * a.y *ss.y;
 
 
             // The dimension must be overridden when using the designSize feature, the ratio is maintain to compute a uniform scale, which is mandatory but if the designSize's ratio is different from the rendering surface's ratio, content will be clipped in some cases.
             // The dimension must be overridden when using the designSize feature, the ratio is maintain to compute a uniform scale, which is mandatory but if the designSize's ratio is different from the rendering surface's ratio, content will be clipped in some cases.
             // So we set the width/height to the rendering's one because that's what we want for the viewport!
             // So we set the width/height to the rendering's one because that's what we want for the viewport!
@@ -803,6 +806,8 @@
 
 
         private static _uV = new Vector2(1, 1);
         private static _uV = new Vector2(1, 1);
         private static _s = Size.Zero();
         private static _s = Size.Zero();
+        private static _v1 = Vector2.Zero();
+        private static _s2 = Size.Zero();
         private _bindCacheTarget() {
         private _bindCacheTarget() {
             let curWidth: number;
             let curWidth: number;
             let curHeight: number;
             let curHeight: number;
@@ -813,11 +818,11 @@
             let isCanvas = this.parent == null;
             let isCanvas = this.parent == null;
             let scale: Vector2;
             let scale: Vector2;
             if (noResizeScale) {
             if (noResizeScale) {
-                scale = isCanvas ? Group2D._uV: this.parent.actualScale;
+                scale = isCanvas ? Group2D._uV: this.parent.actualScale.multiply(this.owner._canvasLevelScale);
             } else {
             } else {
-                scale = this.actualScale;
+                scale = this.actualScale.multiply(this.owner._canvasLevelScale);
             }
             }
-
+            let actualSize = this.actualSize;
             if (isCanvas && this.owner.cachingStrategy===Canvas2D.CACHESTRATEGY_CANVAS && this.owner.isScreenSpace) {
             if (isCanvas && this.owner.cachingStrategy===Canvas2D.CACHESTRATEGY_CANVAS && this.owner.isScreenSpace) {
                 if(this.owner.designSize || this.owner.fitRenderingDevice){
                 if(this.owner.designSize || this.owner.fitRenderingDevice){
                     Group2D._s.width = this.owner.engine.getRenderWidth();
                     Group2D._s.width = this.owner.engine.getRenderWidth();
@@ -827,14 +832,15 @@
                     Group2D._s.copyFrom(this.owner.size);
                     Group2D._s.copyFrom(this.owner.size);
                 }
                 }
             } else {
             } else {
-                Group2D._s.width = Math.ceil(this.actualSize.width * scale.x * rs);
-                Group2D._s.height = Math.ceil(this.actualSize.height * scale.y * rs);
+                Group2D._s.width  = Math.ceil(actualSize.width  * scale.x * rs);
+                Group2D._s.height = Math.ceil(actualSize.height * scale.y * rs);
             }
             }
 
 
             let sizeChanged = !Group2D._s.equals(rd._cacheSize);
             let sizeChanged = !Group2D._s.equals(rd._cacheSize);
 
 
             if (rd._cacheNode) {
             if (rd._cacheNode) {
-                let size = rd._cacheNode.contentSize;
+                let size = Group2D._s;
+                rd._cacheNode.getInnerSizeToRef(size);
 
 
                 // Check if we have to deallocate because the size is too small
                 // Check if we have to deallocate because the size is too small
                 if ((size.width < Group2D._s.width) || (size.height < Group2D._s.height)) {
                 if ((size.width < Group2D._s.width) || (size.height < Group2D._s.height)) {
@@ -859,6 +865,12 @@
                 }
                 }
                 rd._cacheRenderSprite = res.sprite;
                 rd._cacheRenderSprite = res.sprite;
                 sizeChanged = true;
                 sizeChanged = true;
+            } else if (sizeChanged) {
+                let sprite = rd._cacheRenderSprite;
+                if (sprite) {
+                    sprite.size = actualSize;
+                    sprite.spriteSize = new Size(actualSize.width * scale.x * rs, actualSize.height * scale.y * rs);
+                }
             }
             }
 
 
             if (sizeChanged) {
             if (sizeChanged) {
@@ -871,8 +883,9 @@
                 this._setFlags(SmartPropertyPrim.flagWorldCacheChanged);
                 this._setFlags(SmartPropertyPrim.flagWorldCacheChanged);
             }
             }
 
 
-            let n = rd._cacheNode;
-            rd._cacheTexture.bindTextureForPosSize(n.pos, Group2D._s, true);
+            let pos = Group2D._v1;
+            rd._cacheNode.getInnerPosToRef(pos);
+            rd._cacheTexture.bindTextureForPosSize(pos, Group2D._s, true);
         }
         }
 
 
         private _unbindCacheTarget() {
         private _unbindCacheTarget() {
@@ -924,6 +937,11 @@
                 case Group2D.actualSizeProperty.id:
                 case Group2D.actualSizeProperty.id:
                     cachedSprite.size = this.actualSize.clone();
                     cachedSprite.size = this.actualSize.clone();
                     break;
                     break;
+                case Group2D.xProperty.id:
+                    cachedSprite.x = this.x;
+                    break;
+                case Group2D.yProperty.id:
+                    cachedSprite.y = this.y;
             }
             }
         }
         }
 
 

+ 17 - 0
canvas2D/src/Engine/babylon.modelRenderCache.ts

@@ -6,6 +6,7 @@
     export class GroupInstanceInfo {
     export class GroupInstanceInfo {
         constructor(owner: Group2D, mrc: ModelRenderCache, partCount: number) {
         constructor(owner: Group2D, mrc: ModelRenderCache, partCount: number) {
             this._partCount = partCount;
             this._partCount = partCount;
+            this._primCount = 0;
             this.owner = owner;
             this.owner = owner;
             this.modelRenderCache = mrc;
             this.modelRenderCache = mrc;
             this.modelRenderCache.addRef();
             this.modelRenderCache.addRef();
@@ -18,11 +19,26 @@
             this.opaqueDirty = this.alphaTestDirty = this.transparentDirty = this.transparentOrderDirty = false;
             this.opaqueDirty = this.alphaTestDirty = this.transparentDirty = this.transparentOrderDirty = false;
         }
         }
 
 
+        public incPrimCount() {
+            ++this._primCount;
+        }
+
         public dispose(): boolean {
         public dispose(): boolean {
             if (this._isDisposed) {
             if (this._isDisposed) {
                 return false;
                 return false;
             }
             }
 
 
+            // Disposed is called when a primitive instance is disposed, so we decrement the counter
+            --this._primCount;
+
+            // If the counter is still greater than 0 there's still other primitives using this GII
+            if (this._primCount > 0) {
+                return false;
+            }
+
+            // We're going to dispose this GII, first remove it from the dictionary
+            this.owner._renderableData._renderGroupInstancesInfo.remove(this.modelRenderCache.modelKey);
+
             if (this.modelRenderCache) {
             if (this.modelRenderCache) {
                 this.modelRenderCache.dispose();
                 this.modelRenderCache.dispose();
                 this.modelRenderCache = null;
                 this.modelRenderCache = null;
@@ -130,6 +146,7 @@
         }
         }
 
 
         private _partCount: number;
         private _partCount: number;
+        private _primCount: number;
         private _strides: number[];
         private _strides: number[];
         private _usedShaderCategories: string[];
         private _usedShaderCategories: string[];
         private _opaqueData: GroupInfoPartData[];
         private _opaqueData: GroupInfoPartData[];

+ 28 - 22
canvas2D/src/Engine/babylon.prim2dBase.ts

@@ -1195,8 +1195,8 @@
                             rightPixels = this.rightPixels;
                             rightPixels = this.rightPixels;
                         }
                         }
 
 
-                        let center = ((sourceArea.width - (leftPixels+rightPixels)) - (width * sx)) / 2;
-                        dstOffset.x = leftPixels + center;
+                        let center = ((sourceArea.width - (width * sx)) / 2);
+                        dstOffset.x = center + (leftPixels - rightPixels);
 
 
                         if (computeLayoutArea) {
                         if (computeLayoutArea) {
                             dstArea.width = (width * isx) + (this.leftPixels + this.rightPixels) * isx;
                             dstArea.width = (width * isx) + (this.leftPixels + this.rightPixels) * isx;
@@ -1295,8 +1295,8 @@
                             topPixels = this.topPixels;
                             topPixels = this.topPixels;
                         }
                         }
 
 
-                        let center = ((sourceArea.height - (bottomPixels+topPixels)) - (height * sy)) / 2;
-                        dstOffset.y = bottomPixels + center;
+                        let center = ((sourceArea.height - (height * sy)) / 2);
+                        dstOffset.y = center + (bottomPixels - topPixels);
 
 
                         if (computeLayoutArea) {
                         if (computeLayoutArea) {
                             dstArea.height = (height * isy) + (bottomPixels + topPixels) * isy;
                             dstArea.height = (height * isy) + (bottomPixels + topPixels) * isy;
@@ -2037,7 +2037,7 @@
             //    return;
             //    return;
             //}
             //}
             if (this._checkUseMargin()) {
             if (this._checkUseMargin()) {
-                switch (this._marginAlignment.horizontal) {
+                switch (this.marginAlignment.horizontal) {
                     case PrimitiveAlignment.AlignLeft:
                     case PrimitiveAlignment.AlignLeft:
                     case PrimitiveAlignment.AlignStretch:
                     case PrimitiveAlignment.AlignStretch:
                     case PrimitiveAlignment.AlignCenter:
                     case PrimitiveAlignment.AlignCenter:
@@ -2047,7 +2047,7 @@
                         this.margin.rightPixels = value.x;
                         this.margin.rightPixels = value.x;
                         break;
                         break;
                     }
                     }
-                switch (this._marginAlignment.vertical) {
+                switch (this.marginAlignment.vertical) {
                     case PrimitiveAlignment.AlignBottom:
                     case PrimitiveAlignment.AlignBottom:
                     case PrimitiveAlignment.AlignStretch:
                     case PrimitiveAlignment.AlignStretch:
                     case PrimitiveAlignment.AlignCenter:
                     case PrimitiveAlignment.AlignCenter:
@@ -2093,7 +2093,7 @@
                 throw new Error(`Can't set a null x in primitive ${this.id}, only the position can be turned to null`);
                 throw new Error(`Can't set a null x in primitive ${this.id}, only the position can be turned to null`);
             }
             }
             if (this._checkUseMargin()) {
             if (this._checkUseMargin()) {
-                switch (this._marginAlignment.horizontal) {
+                switch (this.marginAlignment.horizontal) {
                     case PrimitiveAlignment.AlignLeft:
                     case PrimitiveAlignment.AlignLeft:
                     case PrimitiveAlignment.AlignStretch:
                     case PrimitiveAlignment.AlignStretch:
                     case PrimitiveAlignment.AlignCenter:
                     case PrimitiveAlignment.AlignCenter:
@@ -2140,7 +2140,7 @@
                 throw new Error(`Can't set a null y in primitive ${this.id}, only the position can be turned to null`);
                 throw new Error(`Can't set a null y in primitive ${this.id}, only the position can be turned to null`);
             }
             }
             if (this._checkUseMargin()) {
             if (this._checkUseMargin()) {
-                switch (this._marginAlignment.vertical) {
+                switch (this.marginAlignment.vertical) {
                     case PrimitiveAlignment.AlignBottom:
                     case PrimitiveAlignment.AlignBottom:
                     case PrimitiveAlignment.AlignStretch:
                     case PrimitiveAlignment.AlignStretch:
                     case PrimitiveAlignment.AlignCenter:
                     case PrimitiveAlignment.AlignCenter:
@@ -2746,7 +2746,7 @@
          */
          */
         public getActualGlobalScaleToRef(res: Vector2) {
         public getActualGlobalScaleToRef(res: Vector2) {
             let as = this.actualScale;
             let as = this.actualScale;
-            let cls = this.owner._canvasLevelScale || Canvas2D._iv3;
+            let cls = this.owner._canvasLevelScale || Prim2DBase._iv2;
             res.x = as.x * cls.x;
             res.x = as.x * cls.x;
             res.y = as.y * cls.y;
             res.y = as.y * cls.y;
         }
         }
@@ -3027,7 +3027,9 @@
                 }
                 }
 
 
                 if (this._isFlagSet(SmartPropertyPrim.flagLayoutDirty)) {
                 if (this._isFlagSet(SmartPropertyPrim.flagLayoutDirty)) {
-                    this.owner.addUpdateLayoutCounter(1);
+                    if (this._owner) {
+                        this._owner.addUpdateLayoutCounter(1);
+                    }
                     this._layoutEngine.updateLayout(this);
                     this._layoutEngine.updateLayout(this);
 
 
                     this._clearFlags(SmartPropertyPrim.flagLayoutDirty);
                     this._clearFlags(SmartPropertyPrim.flagLayoutDirty);
@@ -3459,6 +3461,9 @@
                 try {
                 try {
                     Prim2DBase._bypassGroup2DExclusion = true;
                     Prim2DBase._bypassGroup2DExclusion = true;
                     let ownerGroup = this.getExternalData<Group2D>("__cachedGroup__");
                     let ownerGroup = this.getExternalData<Group2D>("__cachedGroup__");
+                    if (!ownerGroup) {
+                        return false;
+                    }
                     return ownerGroup.intersect(intersectInfo);
                     return ownerGroup.intersect(intersectInfo);
                 } finally  {
                 } finally  {
                     Prim2DBase._bypassGroup2DExclusion = false;
                     Prim2DBase._bypassGroup2DExclusion = false;
@@ -3633,6 +3638,7 @@
             }
             }
             let length = this._children.push(child);
             let length = this._children.push(child);
             this._firstZDirtyIndex = Math.min(this._firstZDirtyIndex, length - 1);
             this._firstZDirtyIndex = Math.min(this._firstZDirtyIndex, length - 1);
+            child._setFlags(SmartPropertyPrim.flagActualOpacityDirty);
         }
         }
 
 
         /**
         /**
@@ -3824,9 +3830,9 @@
         private static _t0: Matrix2D = new Matrix2D();
         private static _t0: Matrix2D = new Matrix2D();
         private static _t1: Matrix2D = new Matrix2D();
         private static _t1: Matrix2D = new Matrix2D();
         private static _t2: Matrix2D = new Matrix2D();
         private static _t2: Matrix2D = new Matrix2D();
-        private static _v0: Vector2 = Vector2.Zero();   // Must stay with the value 0,0
+        private static _v0: Vector2 = Vector2.Zero();    // Must stay with the value 0,0
         private static _v30: Vector3 = Vector3.Zero();   // Must stay with the value 0,0,0
         private static _v30: Vector3 = Vector3.Zero();   // Must stay with the value 0,0,0
-        private static _iv3: Vector3 = new Vector3(1,1,1); // Must stay identity vector
+        private static _iv2: Vector2 = new Vector2(1,1); // Must stay identity vector
         private static _ts0 = Size.Zero();
         private static _ts0 = Size.Zero();
 
 
         private _updateLocalTransform(): boolean {
         private _updateLocalTransform(): boolean {
@@ -3846,12 +3852,12 @@
                 var local: Matrix2D;
                 var local: Matrix2D;
                 let pos = this._position ? this.position : (this.layoutAreaPos || Prim2DBase._v0);
                 let pos = this._position ? this.position : (this.layoutAreaPos || Prim2DBase._v0);
                 let postScale = this._postScale;
                 let postScale = this._postScale;
-                let canvasScale = Prim2DBase._iv3;
-                let hasCanvasScale = false;
-                if (this._parent instanceof Canvas2D) {
-                    hasCanvasScale = true;
-                    canvasScale = (this._parent as Canvas2D)._canvasLevelScale || Prim2DBase._iv3;
-                }
+                let canvasScale = Prim2DBase._iv2;
+                //let hasCanvasScale = false;
+                //if (this._parent instanceof Canvas2D) {
+                //    hasCanvasScale = true;
+                //    canvasScale = (this._parent as Canvas2D)._canvasLevelScale || Prim2DBase._iv2;
+                //}
                 let globalScale = this._scale.multiplyByFloats(/*postScale.x**/canvasScale.x, /*postScale.y**/canvasScale.y);
                 let globalScale = this._scale.multiplyByFloats(/*postScale.x**/canvasScale.x, /*postScale.y**/canvasScale.y);
 
 
                 if ((this._origin.x === 0 && this._origin.y === 0) || this._hasMargin) {
                 if ((this._origin.x === 0 && this._origin.y === 0) || this._hasMargin) {
@@ -3885,10 +3891,10 @@
                     Matrix2D.TranslationToRef(pos.x + this._marginOffset.x, pos.y + this._marginOffset.y, t0);
                     Matrix2D.TranslationToRef(pos.x + this._marginOffset.x, pos.y + this._marginOffset.y, t0);
                     t2.multiplyToRef(t0, this._localTransform);
                     t2.multiplyToRef(t0, this._localTransform);
 
 
-                    if (hasCanvasScale) {
-                        Matrix2D.ScalingToRef(canvasScale.x, canvasScale.y, Prim2DBase._t1);
-                        this._localTransform.multiplyToRef(Prim2DBase._t1, this._localTransform);
-                    }
+                    //if (hasCanvasScale) {
+                    //    Matrix2D.ScalingToRef(canvasScale.x, canvasScale.y, Prim2DBase._t1);
+                    //    this._localTransform.multiplyToRef(Prim2DBase._t1, this._localTransform);
+                    //}
 
 
                     this._localLayoutTransform = Matrix2D.Compose(globalScale, rot, pos);
                     this._localLayoutTransform = Matrix2D.Compose(globalScale, rot, pos);
                 }
                 }

+ 4 - 4
canvas2D/src/Engine/babylon.rectangle2d.ts

@@ -593,18 +593,18 @@
                 return false;
                 return false;
             }
             }
 
 
-            let s = Rectangle2D._riv0;
-            this.getActualGlobalScaleToRef(s);
+            //let s = Rectangle2D._riv0;
+            //this.getActualGlobalScaleToRef(s);
 
 
             if (part.id === Shape2D.SHAPE2D_BORDERPARTID) {
             if (part.id === Shape2D.SHAPE2D_BORDERPARTID) {
                 let d = <Rectangle2DInstanceData>part;
                 let d = <Rectangle2DInstanceData>part;
                 let size = this.actualSize;
                 let size = this.actualSize;
-                d.properties = new Vector3(size.width * s.x, size.height * s.y, this.roundRadius || 0);
+                d.properties = new Vector3(size.width/* * s.x*/, size.height/* * s.y*/, this.roundRadius || 0);
             }
             }
             else if (part.id === Shape2D.SHAPE2D_FILLPARTID) {
             else if (part.id === Shape2D.SHAPE2D_FILLPARTID) {
                 let d = <Rectangle2DInstanceData>part;
                 let d = <Rectangle2DInstanceData>part;
                 let size = this.actualSize;
                 let size = this.actualSize;
-                d.properties = new Vector3(size.width * s.x, size.height * s.y, this.roundRadius || 0);
+                d.properties = new Vector3(size.width/* * s.x*/, size.height/* * s.y*/, this.roundRadius || 0);
             }
             }
             return true;
             return true;
         }
         }

+ 12 - 13
canvas2D/src/Engine/babylon.renderablePrim2d.ts

@@ -451,28 +451,19 @@
                 gii = part.groupInstanceInfo;
                 gii = part.groupInstanceInfo;
                 part.groupInstanceInfo = null;
                 part.groupInstanceInfo = null;
             }
             }
-            if (gii && !gii.isDisposed) {
-                let usedCount = 0;
+
+            if (gii) {
                 if (gii.hasOpaqueData) {
                 if (gii.hasOpaqueData) {
-                    let od = gii.opaqueData[0];
-                    usedCount += od._partData.usedElementCount;
                     gii.opaqueDirty = true;
                     gii.opaqueDirty = true;
                 }
                 }
                 if (gii.hasAlphaTestData) {
                 if (gii.hasAlphaTestData) {
-                    let atd = gii.alphaTestData[0];
-                    usedCount += atd._partData.usedElementCount;
                     gii.alphaTestDirty = true;
                     gii.alphaTestDirty = true;
                 }
                 }
                 if (gii.hasTransparentData) {
                 if (gii.hasTransparentData) {
-                    let td = gii.transparentData[0];
-                    usedCount += td._partData.usedElementCount;
                     gii.transparentDirty = true;
                     gii.transparentDirty = true;
                 }
                 }
 
 
-                if (usedCount === 0 && gii.modelRenderCache!=null) {
-                    this.renderGroup._renderableData._renderGroupInstancesInfo.remove(gii.modelRenderCache.modelKey);
-                    gii.dispose();
-                }
+                gii.dispose();
 
 
                 if (this._modelRenderCache) {
                 if (this._modelRenderCache) {
                     this._modelRenderCache.dispose();
                     this._modelRenderCache.dispose();
@@ -480,6 +471,7 @@
                 }
                 }
 
 
             }
             }
+
             this._instanceDataParts = null;
             this._instanceDataParts = null;
         }
         }
 
 
@@ -597,6 +589,9 @@
                 part.groupInstanceInfo = gii;
                 part.groupInstanceInfo = gii;
             }
             }
 
 
+            // Increment the primitive count as one more primitive is using this GroupInstanceInfo
+            gii.incPrimCount();
+
             return gii;
             return gii;
         }
         }
 
 
@@ -951,11 +946,15 @@
             let trn = RenderablePrim2D._t;
             let trn = RenderablePrim2D._t;
             let rot = t.decompose(scl, trn);
             let rot = t.decompose(scl, trn);
             let pas = this.actualScale;
             let pas = this.actualScale;
-            let canvasScale = this.owner._canvasLevelScale;
+            //let cachedGroup = (this.getExternalData<Group2D>("__cachedGroup__") !== null);
+            let canvasScale = /*cachedGroup ? RenderablePrim2D._iV2 :  */this.owner._canvasLevelScale;
             scl.x = pas.x * canvasScale.x * this._postScale.x;
             scl.x = pas.x * canvasScale.x * this._postScale.x;
             scl.y = pas.y * canvasScale.y * this._postScale.y;
             scl.y = pas.y * canvasScale.y * this._postScale.y;
+            trn.multiplyInPlace(canvasScale);
             t = Matrix2D.Compose(this.applyActualScaleOnTransform() ? scl : RenderablePrim2D._iV2, rot, trn);
             t = Matrix2D.Compose(this.applyActualScaleOnTransform() ? scl : RenderablePrim2D._iV2, rot, trn);
 
 
+            //console.log(`Update Instance Data Part: ${this.id}`);
+
             let size = (<Size>this.renderGroup.viewportSize);
             let size = (<Size>this.renderGroup.viewportSize);
             let zBias = this.actualZOffset;
             let zBias = this.actualZOffset;
 
 

+ 3 - 3
canvas2D/src/Engine/babylon.shape2d.ts

@@ -126,9 +126,9 @@
             return cat;
             return cat;
         }
         }
 
 
-        protected applyActualScaleOnTransform(): boolean {
-            return false;
-        }
+        //protected applyActualScaleOnTransform(): boolean {
+        //    return false;
+        //}
 
 
         protected refreshInstanceDataPart(part: InstanceDataBase): boolean {
         protected refreshInstanceDataPart(part: InstanceDataBase): boolean {
             if (!super.refreshInstanceDataPart(part)) {
             if (!super.refreshInstanceDataPart(part)) {

+ 9 - 3
canvas2D/src/Engine/babylon.text2d.ts

@@ -150,6 +150,7 @@
         public static fontSuperSampleProperty: Prim2DPropInfo;
         public static fontSuperSampleProperty: Prim2DPropInfo;
         public static fontSignedDistanceFieldProperty: Prim2DPropInfo;
         public static fontSignedDistanceFieldProperty: Prim2DPropInfo;
         public static textureIsPremulAlphaProperty: Prim2DPropInfo;
         public static textureIsPremulAlphaProperty: Prim2DPropInfo;
+        public static fontTextureProperty: Prim2DPropInfo;
 
 
         /**
         /**
          * Alignment is made relative to the left edge of the Content Area. Valid for horizontal alignment only.
          * Alignment is made relative to the left edge of the Content Area. Valid for horizontal alignment only.
@@ -333,6 +334,7 @@
             }
             }
         }
         }
 
 
+        @modelLevelProperty(RenderablePrim2D.RENDERABLEPRIM2D_PROPCOUNT + 8, pi => Text2D.fontTextureProperty = pi)
         public get fontTexture(): BaseFontTexture {
         public get fontTexture(): BaseFontTexture {
             if (this._fontTexture) {
             if (this._fontTexture) {
                 return this._fontTexture;
                 return this._fontTexture;
@@ -769,7 +771,7 @@
                     offsetX += (contentAreaWidth - maxLineLen) * .5;
                     offsetX += (contentAreaWidth - maxLineLen) * .5;
                 }
                 }
 
 
-                offset.x += offsetX;
+                offset.x += Math.floor(offsetX);
 
 
                 offset.y += contentAreaHeight + textHeight - lh;
                 offset.y += contentAreaHeight + textHeight - lh;
                 offset.y += this.padding.bottomPixels;
                 offset.y += this.padding.bottomPixels;
@@ -800,17 +802,21 @@
                         if(char !== "\t" && !this._isWhiteSpaceCharVert(char)){ 
                         if(char !== "\t" && !this._isWhiteSpaceCharVert(char)){ 
                             //make sure space char gets processed here or overlapping can occur when text is set
                             //make sure space char gets processed here or overlapping can occur when text is set
                             let ci = texture.getChar(char);
                             let ci = texture.getChar(char);
-                            this.updateInstanceDataPart(d, new Vector2(offset.x + ci.xOffset, offset.y +ci.yOffset));
+                            let partOffset = new Vector2(Math.floor(offset.x + ci.xOffset), Math.floor(offset.y + ci.yOffset));
+                            this.updateInstanceDataPart(d, partOffset);
                             d.topLeftUV = ci.topLeftUV;
                             d.topLeftUV = ci.topLeftUV;
                             let suv = ci.bottomRightUV.subtract(ci.topLeftUV);
                             let suv = ci.bottomRightUV.subtract(ci.topLeftUV);
                             d.sizeUV = suv;
                             d.sizeUV = suv;
                             d.textureSize = new BABYLON.Vector2(ts.width, ts.height);
                             d.textureSize = new BABYLON.Vector2(ts.width, ts.height);
                             d.color = this.defaultFontColor;
                             d.color = this.defaultFontColor;
                             d.superSampleFactor = superSampleFactor;
                             d.superSampleFactor = superSampleFactor;
+
+                            //console.log(`Char: ${char}, Offset: ${partOffset}`);
+
                             ++d.curElement;
                             ++d.curElement;
                         }
                         }
 
 
-                        offset.x += charWidth;
+                        offset.x += Math.floor(charWidth);
                         charNum++;
                         charNum++;
                     }
                     }
 
 

+ 10 - 8
canvas2D/src/shaders/sprite2d.vertex.fx

@@ -77,13 +77,15 @@ void main(void) {
 		vUV.y = 1.0 - vUV.y;
 		vUV.y = 1.0 - vUV.y;
 	}
 	}
 
 
+	//vUV.x += 0.5 / textureSize.x;
+
 	vec4 pos;
 	vec4 pos;
-	if (alignToPixel == 1.0)
-	{
-		pos.xy = floor(pos2.xy * sizeUV * textureSize);
-	} else {
+	//if (alignToPixel == 1.0)
+	//{
+	//	pos.xy = floor(pos2.xy * sizeUV * textureSize);
+	//} else {
 		pos.xy = pos2.xy * sizeUV * textureSize;
 		pos.xy = pos2.xy * sizeUV * textureSize;
-	}
+	//}
 
 
 #ifdef Scale9
 #ifdef Scale9
 	if (invertY == 1.0) {
 	if (invertY == 1.0) {
@@ -111,9 +113,9 @@ void main(void) {
 		float irw = 2.0 / rw;
 		float irw = 2.0 / rw;
 		float irh = 2.0 / rh;
 		float irh = 2.0 / rh;
 
 
-		x = floor((x / irw) + 0.5) * irw;
-		y = floor((y / irh) + 0.5) * irh;
+		x = (floor((x / irw)) * irw) + irw / 2.0;
+		y = (floor((y / irh)) * irh) + irh / 2.0;
 	}
 	}
 
 
-	gl_Position = vec4(x, y, zBias.x, 1);
+	gl_Position = vec4(x, y, zBias.x, 1.0);
 }	
 }	

+ 1 - 1
canvas2D/src/shaders/text2d.fragment.fx

@@ -26,7 +26,7 @@ void main(void) {
 		discard;
 		discard;
 	}
 	}
 #ifdef FontTexture
 #ifdef FontTexture
-	gl_FragColor = vec4(color.xxxx)*vColor;
+	gl_FragColor = vec4(color.xxx*vColor.xyz*vColor.a, vColor.a);
 #else
 #else
 	gl_FragColor = color*vColor;
 	gl_FragColor = color*vColor;
 #endif
 #endif

+ 6 - 5
canvas2D/src/shaders/text2d.vertex.fx

@@ -53,12 +53,13 @@ void main(void) {
 	}
 	}
 
 
 	// Align texture coordinate to texel to enhance rendering quality
 	// Align texture coordinate to texel to enhance rendering quality
-	vUV = (floor(vUV*textureSize) + vec2(0.0, 0.0)) / textureSize;
+//	vUV = (floor(vUV*textureSize) + vec2(0.5, 0.5)) / textureSize;
+	//vUV.x += 0.5 / textureSize.x;
 
 
 	vColor = color;
 	vColor = color;
 	vColor.a *= opacity;
 	vColor.a *= opacity;
 	vec4 pos;
 	vec4 pos;
-	pos.xy = floor(pos2.xy * superSampleFactor * sizeUV * textureSize);	// Align on target pixel to avoid bad interpolation
+	pos.xy = pos2.xy * superSampleFactor * sizeUV * textureSize;
 	pos.z = 1.0;
 	pos.z = 1.0;
 	pos.w = 1.0;
 	pos.w = 1.0;
 
 
@@ -70,9 +71,9 @@ void main(void) {
 		float irw = 2.0 / rw;
 		float irw = 2.0 / rw;
 		float irh = 2.0 / rh;
 		float irh = 2.0 / rh;
 
 
-		x = floor((x / irw) + 0.5) * irw;
-		y = floor((y / irh) + 0.5) * irh;
+		x = ((floor((x / irw) + 0.5) * irw) + irw / 2.0) + 0.5*irw;
+		y = ((floor((y / irh) + 0.5) * irh) + irh / 2.0) + 0.5*irh;
 	}
 	}
 
 
-	gl_Position = vec4(x, y, zBias.x, 1);
+	gl_Position = vec4(x, y, zBias.x, 1.0);
 }
 }

File diff suppressed because it is too large
+ 29 - 30
dist/preview release/babylon.core.js


File diff suppressed because it is too large
+ 3252 - 3166
dist/preview release/babylon.d.ts


File diff suppressed because it is too large
+ 40 - 41
dist/preview release/babylon.js


File diff suppressed because it is too large
+ 524 - 162
dist/preview release/babylon.max.js


File diff suppressed because it is too large
+ 3252 - 3166
dist/preview release/babylon.module.d.ts


File diff suppressed because it is too large
+ 39 - 39
dist/preview release/babylon.noworker.js


+ 8 - 3
dist/preview release/canvas2D/babylon.canvas2d.d.ts

@@ -2496,7 +2496,7 @@ declare module BABYLON {
         private static _t2;
         private static _t2;
         private static _v0;
         private static _v0;
         private static _v30;
         private static _v30;
-        private static _iv3;
+        private static _iv2;
         private static _ts0;
         private static _ts0;
         private _updateLocalTransform();
         private _updateLocalTransform();
         private static _transMtx;
         private static _transMtx;
@@ -2621,6 +2621,7 @@ declare module BABYLON {
     }
     }
     class GroupInstanceInfo {
     class GroupInstanceInfo {
         constructor(owner: Group2D, mrc: ModelRenderCache, partCount: number);
         constructor(owner: Group2D, mrc: ModelRenderCache, partCount: number);
+        incPrimCount(): void;
         dispose(): boolean;
         dispose(): boolean;
         readonly isDisposed: boolean;
         readonly isDisposed: boolean;
         private _isDisposed;
         private _isDisposed;
@@ -2641,6 +2642,7 @@ declare module BABYLON {
         readonly usedShaderCategories: string[];
         readonly usedShaderCategories: string[];
         readonly strides: number[];
         readonly strides: number[];
         private _partCount;
         private _partCount;
+        private _primCount;
         private _strides;
         private _strides;
         private _usedShaderCategories;
         private _usedShaderCategories;
         private _opaqueData;
         private _opaqueData;
@@ -2850,7 +2852,6 @@ declare module BABYLON {
             borderThickness?: number;
             borderThickness?: number;
         });
         });
         protected getUsedShaderCategories(dataPart: InstanceDataBase): string[];
         protected getUsedShaderCategories(dataPart: InstanceDataBase): string[];
-        protected applyActualScaleOnTransform(): boolean;
         protected refreshInstanceDataPart(part: InstanceDataBase): boolean;
         protected refreshInstanceDataPart(part: InstanceDataBase): boolean;
         private _updateTransparencyStatus();
         private _updateTransparencyStatus();
         protected _mustUpdateInstance(): boolean;
         protected _mustUpdateInstance(): boolean;
@@ -3040,6 +3041,8 @@ declare module BABYLON {
         protected _setRenderingScale(scale: number): void;
         protected _setRenderingScale(scale: number): void;
         private static _uV;
         private static _uV;
         private static _s;
         private static _s;
+        private static _v1;
+        private static _s2;
         private _bindCacheTarget();
         private _bindCacheTarget();
         private _unbindCacheTarget();
         private _unbindCacheTarget();
         protected _spreadActualScaleDirty(): void;
         protected _spreadActualScaleDirty(): void;
@@ -3861,6 +3864,7 @@ declare module BABYLON {
         static fontSuperSampleProperty: Prim2DPropInfo;
         static fontSuperSampleProperty: Prim2DPropInfo;
         static fontSignedDistanceFieldProperty: Prim2DPropInfo;
         static fontSignedDistanceFieldProperty: Prim2DPropInfo;
         static textureIsPremulAlphaProperty: Prim2DPropInfo;
         static textureIsPremulAlphaProperty: Prim2DPropInfo;
+        static fontTextureProperty: Prim2DPropInfo;
         /**
         /**
          * Alignment is made relative to the left edge of the Content Area. Valid for horizontal alignment only.
          * Alignment is made relative to the left edge of the Content Area. Valid for horizontal alignment only.
          */
          */
@@ -4502,7 +4506,7 @@ declare module BABYLON {
         private _designSize;
         private _designSize;
         private _designUseHorizAxis;
         private _designUseHorizAxis;
         _primitiveCollisionManager: PrimitiveCollisionManagerBase;
         _primitiveCollisionManager: PrimitiveCollisionManagerBase;
-        _canvasLevelScale: Vector3;
+        _canvasLevelScale: Vector2;
         _renderingSize: Size;
         _renderingSize: Size;
         private _curHWScale;
         private _curHWScale;
         private _drawCallsOpaqueCounter;
         private _drawCallsOpaqueCounter;
@@ -4521,6 +4525,7 @@ declare module BABYLON {
         private _profilingCanvas;
         private _profilingCanvas;
         private _profileInfoText;
         private _profileInfoText;
         private static _v;
         private static _v;
+        private static _cv1;
         private static _m;
         private static _m;
         private static _mI;
         private static _mI;
         private static tS;
         private static tS;

File diff suppressed because it is too large
+ 141 - 92
dist/preview release/canvas2D/babylon.canvas2d.js


File diff suppressed because it is too large
+ 12 - 12
dist/preview release/canvas2D/babylon.canvas2d.min.js


File diff suppressed because it is too large
+ 251 - 251
dist/preview release/inspector/babylon.inspector.bundle.js


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

@@ -107,6 +107,10 @@ declare module INSPECTOR {
         'FontTexture': {
         'FontTexture': {
             type: typeof BABYLON.FontTexture;
             type: typeof BABYLON.FontTexture;
         };
         };
+        'Sound': {
+            type: typeof BABYLON.Sound;
+            properties: string[];
+        };
         'ArcRotateCamera': {
         'ArcRotateCamera': {
             type: typeof BABYLON.ArcRotateCamera;
             type: typeof BABYLON.ArcRotateCamera;
             properties: string[];
             properties: string[];
@@ -224,6 +228,20 @@ declare module INSPECTOR {
 }
 }
 
 
 declare module INSPECTOR {
 declare module INSPECTOR {
+    class SoundAdapter extends Adapter implements ISoundInteractions {
+        constructor(obj: BABYLON.Sound);
+        /** Returns the name displayed in the tree */
+        id(): string;
+        /** Returns the type of this object - displayed in the tree */
+        type(): string;
+        /** Returns the list of properties to be displayed for this adapter */
+        getProperties(): Array<PropertyLine>;
+        getTools(): Array<AbstractTreeTool>;
+        setPlaying(callback: Function): void;
+    }
+}
+
+declare module INSPECTOR {
     class TextureAdapter extends Adapter {
     class TextureAdapter extends Adapter {
         constructor(obj: BABYLON.BaseTexture);
         constructor(obj: BABYLON.BaseTexture);
         /** Returns the name displayed in the tree */
         /** Returns the name displayed in the tree */
@@ -702,6 +720,13 @@ declare module INSPECTOR {
 }
 }
 
 
 declare module INSPECTOR {
 declare module INSPECTOR {
+    class SoundTab extends PropertyTab {
+        constructor(tabbar: TabBar, inspector: Inspector);
+        protected _getTree(): Array<TreeItem>;
+    }
+}
+
+declare module INSPECTOR {
     class TextureTab extends Tab {
     class TextureTab extends Tab {
         private _inspector;
         private _inspector;
         /** The panel containing a list of items */
         /** The panel containing a list of items */
@@ -1087,6 +1112,22 @@ declare module INSPECTOR {
 }
 }
 
 
 declare module INSPECTOR {
 declare module INSPECTOR {
+    interface ISoundInteractions {
+        setPlaying: (callback: Function) => void;
+    }
+    /**
+     *
+     */
+    class SoundInteractions extends AbstractTreeTool {
+        private playSound;
+        private b;
+        constructor(playSound: ISoundInteractions);
+        protected action(): void;
+        private _playSound();
+    }
+}
+
+declare module INSPECTOR {
     /** Any object implementing this interface should
     /** Any object implementing this interface should
      * provide methods to toggle its visibility
      * provide methods to toggle its visibility
      */
      */

+ 153 - 3
dist/preview release/inspector/babylon.inspector.js

@@ -112,7 +112,6 @@ var INSPECTOR;
                 else {
                 else {
                     inspector = INSPECTOR.Helpers.CreateDiv('insp-right-panel', this._c2diwrapper);
                     inspector = INSPECTOR.Helpers.CreateDiv('insp-right-panel', this._c2diwrapper);
                 }
                 }
-                console.log(inspector);
                 // Add split bar
                 // Add split bar
                 if (!this._parentElement) {
                 if (!this._parentElement) {
                     Split([canvas, inspector], {
                     Split([canvas, inspector], {
@@ -370,6 +369,23 @@ var INSPECTOR;
         'FontTexture': {
         'FontTexture': {
             type: BABYLON.FontTexture
             type: BABYLON.FontTexture
         },
         },
+        'Sound': {
+            type: BABYLON.Sound,
+            properties: [
+                'name',
+                'autoplay',
+                'loop',
+                'useCustomAttenuation',
+                'soundTrackId',
+                'spatialSound',
+                'refDistance',
+                'rolloffFactor',
+                'maxDistance',
+                'distanceModel',
+                'isPlaying',
+                'isPaused'
+            ]
+        },
         'ArcRotateCamera': {
         'ArcRotateCamera': {
             type: BABYLON.ArcRotateCamera,
             type: BABYLON.ArcRotateCamera,
             properties: [
             properties: [
@@ -725,6 +741,66 @@ var __extends = (this && this.__extends) || function (d, b) {
 };
 };
 var INSPECTOR;
 var INSPECTOR;
 (function (INSPECTOR) {
 (function (INSPECTOR) {
+    var SoundAdapter = (function (_super) {
+        __extends(SoundAdapter, _super);
+        function SoundAdapter(obj) {
+            return _super.call(this, obj) || this;
+        }
+        /** Returns the name displayed in the tree */
+        SoundAdapter.prototype.id = function () {
+            var str = '';
+            if (this._obj.name) {
+                str = this._obj.name;
+            } // otherwise nothing displayed        
+            return str;
+        };
+        /** Returns the type of this object - displayed in the tree */
+        SoundAdapter.prototype.type = function () {
+            return INSPECTOR.Helpers.GET_TYPE(this._obj);
+        };
+        /** Returns the list of properties to be displayed for this adapter */
+        SoundAdapter.prototype.getProperties = function () {
+            var propertiesLines = [];
+            var camToDisplay = [];
+            // The if is there to work with the min version of babylon
+            var soundProperties = INSPECTOR.PROPERTIES['Sound'].properties;
+            for (var _i = 0, soundProperties_1 = soundProperties; _i < soundProperties_1.length; _i++) {
+                var dirty = soundProperties_1[_i];
+                var infos = new INSPECTOR.Property(dirty, this._obj);
+                propertiesLines.push(new INSPECTOR.PropertyLine(infos));
+            }
+            return propertiesLines;
+        };
+        SoundAdapter.prototype.getTools = function () {
+            var tools = [];
+            tools.push(new INSPECTOR.SoundInteractions(this));
+            return tools;
+        };
+        SoundAdapter.prototype.setPlaying = function (callback) {
+            if (this._obj.isPlaying) {
+                this._obj.pause();
+            }
+            else {
+                this._obj.play();
+            }
+            this._obj.onended = function () {
+                callback();
+            };
+        };
+        return SoundAdapter;
+    }(INSPECTOR.Adapter));
+    INSPECTOR.SoundAdapter = SoundAdapter;
+})(INSPECTOR || (INSPECTOR = {}));
+
+//# sourceMappingURL=SoundAdapter.js.map
+
+var __extends = (this && this.__extends) || function (d, b) {
+    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
+    function __() { this.constructor = d; }
+    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
+};
+var INSPECTOR;
+(function (INSPECTOR) {
     var TextureAdapter = (function (_super) {
     var TextureAdapter = (function (_super) {
         __extends(TextureAdapter, _super);
         __extends(TextureAdapter, _super);
         function TextureAdapter(obj) {
         function TextureAdapter(obj) {
@@ -1827,8 +1903,6 @@ var INSPECTOR;
     INSPECTOR.HDRCubeTextureElement = HDRCubeTextureElement;
     INSPECTOR.HDRCubeTextureElement = HDRCubeTextureElement;
 })(INSPECTOR || (INSPECTOR = {}));
 })(INSPECTOR || (INSPECTOR = {}));
 
 
-//# sourceMappingURL=HDRCubeTextureElement.js.map
-
 var __extends = (this && this.__extends) || function (d, b) {
 var __extends = (this && this.__extends) || function (d, b) {
     for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
     for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
     function __() { this.constructor = d; }
     function __() { this.constructor = d; }
@@ -2380,6 +2454,38 @@ var __extends = (this && this.__extends) || function (d, b) {
 };
 };
 var INSPECTOR;
 var INSPECTOR;
 (function (INSPECTOR) {
 (function (INSPECTOR) {
+    var SoundTab = (function (_super) {
+        __extends(SoundTab, _super);
+        function SoundTab(tabbar, inspector) {
+            return _super.call(this, tabbar, 'Audio', inspector) || this;
+        }
+        /* Overrides super */
+        SoundTab.prototype._getTree = function () {
+            var _this = this;
+            var arr = [];
+            // get all cameras from the first scene
+            var instances = this._inspector.scene;
+            for (var _i = 0, _a = instances.soundTracks; _i < _a.length; _i++) {
+                var sounds = _a[_i];
+                var sound = sounds.soundCollection;
+                sound.forEach(function (element) {
+                    arr.push(new INSPECTOR.TreeItem(_this, new INSPECTOR.SoundAdapter(element)));
+                });
+            }
+            return arr;
+        };
+        return SoundTab;
+    }(INSPECTOR.PropertyTab));
+    INSPECTOR.SoundTab = SoundTab;
+})(INSPECTOR || (INSPECTOR = {}));
+
+var __extends = (this && this.__extends) || function (d, b) {
+    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
+    function __() { this.constructor = d; }
+    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
+};
+var INSPECTOR;
+(function (INSPECTOR) {
     var TextureTab = (function (_super) {
     var TextureTab = (function (_super) {
         __extends(TextureTab, _super);
         __extends(TextureTab, _super);
         function TextureTab(tabbar, inspector) {
         function TextureTab(tabbar, inspector) {
@@ -3415,6 +3521,7 @@ var INSPECTOR;
             }
             }
             _this._tabs.push(new INSPECTOR.MaterialTab(_this, _this._inspector));
             _this._tabs.push(new INSPECTOR.MaterialTab(_this, _this._inspector));
             _this._tabs.push(new INSPECTOR.CameraTab(_this, _this._inspector));
             _this._tabs.push(new INSPECTOR.CameraTab(_this, _this._inspector));
+            _this._tabs.push(new INSPECTOR.SoundTab(_this, _this._inspector));
             _this._toolBar = new INSPECTOR.Toolbar(_this._inspector);
             _this._toolBar = new INSPECTOR.Toolbar(_this._inspector);
             _this._build();
             _this._build();
             //Check initialTab is defined and between tabs bounds
             //Check initialTab is defined and between tabs bounds
@@ -4273,6 +4380,49 @@ var __extends = (this && this.__extends) || function (d, b) {
 var INSPECTOR;
 var INSPECTOR;
 (function (INSPECTOR) {
 (function (INSPECTOR) {
     /**
     /**
+     *
+     */
+    var SoundInteractions = (function (_super) {
+        __extends(SoundInteractions, _super);
+        function SoundInteractions(playSound) {
+            var _this = _super.call(this) || this;
+            _this.playSound = playSound;
+            _this.b = false;
+            _this._elem.classList.add('fa-play');
+            return _this;
+        }
+        SoundInteractions.prototype.action = function () {
+            _super.prototype.action.call(this);
+            this._playSound();
+        };
+        SoundInteractions.prototype._playSound = function () {
+            var _this = this;
+            if (this._elem.classList.contains('fa-play')) {
+                this._elem.classList.remove('fa-play');
+                this._elem.classList.add('fa-pause');
+            }
+            else {
+                this._elem.classList.remove('fa-pause');
+                this._elem.classList.add('fa-play');
+            }
+            this.playSound.setPlaying(function () {
+                _this._elem.classList.remove('fa-pause');
+                _this._elem.classList.add('fa-play');
+            });
+        };
+        return SoundInteractions;
+    }(INSPECTOR.AbstractTreeTool));
+    INSPECTOR.SoundInteractions = SoundInteractions;
+})(INSPECTOR || (INSPECTOR = {}));
+
+var __extends = (this && this.__extends) || function (d, b) {
+    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
+    function __() { this.constructor = d; }
+    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
+};
+var INSPECTOR;
+(function (INSPECTOR) {
+    /**
      * Checkbox to display/hide the primitive
      * Checkbox to display/hide the primitive
      */
      */
     var Checkbox = (function (_super) {
     var Checkbox = (function (_super) {

File diff suppressed because it is too large
+ 3 - 3
dist/preview release/inspector/babylon.inspector.min.js


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

@@ -0,0 +1,16 @@
+/// <reference path="../../../dist/preview release/babylon.d.ts" />
+declare module BABYLON {
+    class CustomShaderHelper {
+    }
+    interface ICustomMaterialBuilder {
+        (builder: CustomShaderHelper, name: string, mainPart: string, diffusePart: string, vertexPositionPart: string): string;
+    }
+    class CustomMaterial extends StandardMaterial {
+        builder: ICustomMaterialBuilder;
+        private _mainPart;
+        private _diffusePart;
+        private _vertexPositionPart;
+        constructor(name: string, builder: ICustomMaterialBuilder, scene: Scene);
+        isReady(mesh?: AbstractMesh, useInstances?: boolean): boolean;
+    }
+}

+ 398 - 0
dist/preview release/materialsLibrary/babylon.customMaterial.js

@@ -0,0 +1,398 @@
+/// <reference path="../../../dist/preview release/babylon.d.ts"/>
+var __extends = (this && this.__extends) || function (d, b) {
+    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
+    function __() { this.constructor = d; }
+    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
+};
+var BABYLON;
+(function (BABYLON) {
+    var CustomShaderHelper = (function () {
+        function CustomShaderHelper() {
+        }
+        return CustomShaderHelper;
+    }());
+    BABYLON.CustomShaderHelper = CustomShaderHelper;
+    var CustomMaterial = (function (_super) {
+        __extends(CustomMaterial, _super);
+        function CustomMaterial(name, builder, scene) {
+            var _this = _super.call(this, name, scene) || this;
+            _this._mainPart = 'void main(void) {';
+            _this._diffusePart = 'vec3 diffuseColor=vDiffuseColor.rgb;';
+            _this._vertexPositionPart = 'gl_Position=viewProjection*finalWorld*vec4(position,1.0);';
+            _this.builder = builder;
+            return _this;
+        }
+        CustomMaterial.prototype.isReady = function (mesh, useInstances) {
+            if (this.isFrozen) {
+                if (this._wasPreviouslyReady) {
+                    return true;
+                }
+            }
+            var scene = this.getScene();
+            var engine = scene.getEngine();
+            var needUVs = false;
+            var needNormals = false;
+            this._defines.reset();
+            // Lights
+            if (scene.lightsEnabled && !this.disableLighting) {
+                needNormals = BABYLON.MaterialHelper.PrepareDefinesForLights(scene, mesh, this._defines, this.maxSimultaneousLights);
+            }
+            if (!this.checkReadyOnEveryCall) {
+                if (this._renderId === scene.getRenderId()) {
+                    if (this._checkCache(scene, mesh, useInstances)) {
+                        return true;
+                    }
+                }
+            }
+            // Textures
+            if (scene.texturesEnabled) {
+                if (this.diffuseTexture && BABYLON.StandardMaterial.DiffuseTextureEnabled) {
+                    if (!this.diffuseTexture.isReady()) {
+                        return false;
+                    }
+                    else {
+                        needUVs = true;
+                        this._defines.DIFFUSE = true;
+                    }
+                }
+                if (this.ambientTexture && BABYLON.StandardMaterial.AmbientTextureEnabled) {
+                    if (!this.ambientTexture.isReady()) {
+                        return false;
+                    }
+                    else {
+                        needUVs = true;
+                        this._defines.AMBIENT = true;
+                    }
+                }
+                if (this.opacityTexture && BABYLON.StandardMaterial.OpacityTextureEnabled) {
+                    if (!this.opacityTexture.isReady()) {
+                        return false;
+                    }
+                    else {
+                        needUVs = true;
+                        this._defines.OPACITY = true;
+                        if (this.opacityTexture.getAlphaFromRGB) {
+                            this._defines.OPACITYRGB = true;
+                        }
+                    }
+                }
+                if (this.reflectionTexture && BABYLON.StandardMaterial.ReflectionTextureEnabled) {
+                    if (!this.reflectionTexture.isReady()) {
+                        return false;
+                    }
+                    else {
+                        needNormals = true;
+                        this._defines.REFLECTION = true;
+                        if (this.roughness > 0) {
+                            this._defines.ROUGHNESS = true;
+                        }
+                        if (this.useReflectionOverAlpha) {
+                            this._defines.REFLECTIONOVERALPHA = true;
+                        }
+                        if (this.reflectionTexture.coordinatesMode === BABYLON.Texture.INVCUBIC_MODE) {
+                            this._defines.INVERTCUBICMAP = true;
+                        }
+                        this._defines.REFLECTIONMAP_3D = this.reflectionTexture.isCube;
+                        switch (this.reflectionTexture.coordinatesMode) {
+                            case BABYLON.Texture.CUBIC_MODE:
+                            case BABYLON.Texture.INVCUBIC_MODE:
+                                this._defines.REFLECTIONMAP_CUBIC = true;
+                                break;
+                            case BABYLON.Texture.EXPLICIT_MODE:
+                                this._defines.REFLECTIONMAP_EXPLICIT = true;
+                                break;
+                            case BABYLON.Texture.PLANAR_MODE:
+                                this._defines.REFLECTIONMAP_PLANAR = true;
+                                break;
+                            case BABYLON.Texture.PROJECTION_MODE:
+                                this._defines.REFLECTIONMAP_PROJECTION = true;
+                                break;
+                            case BABYLON.Texture.SKYBOX_MODE:
+                                this._defines.REFLECTIONMAP_SKYBOX = true;
+                                break;
+                            case BABYLON.Texture.SPHERICAL_MODE:
+                                this._defines.REFLECTIONMAP_SPHERICAL = true;
+                                break;
+                            case BABYLON.Texture.EQUIRECTANGULAR_MODE:
+                                this._defines.REFLECTIONMAP_EQUIRECTANGULAR = true;
+                                break;
+                            case BABYLON.Texture.FIXED_EQUIRECTANGULAR_MODE:
+                                this._defines.REFLECTIONMAP_EQUIRECTANGULAR_FIXED = true;
+                                break;
+                        }
+                    }
+                }
+                if (this.emissiveTexture && BABYLON.StandardMaterial.EmissiveTextureEnabled) {
+                    if (!this.emissiveTexture.isReady()) {
+                        return false;
+                    }
+                    else {
+                        needUVs = true;
+                        this._defines.EMISSIVE = true;
+                    }
+                }
+                if (this.lightmapTexture && BABYLON.StandardMaterial.LightmapTextureEnabled) {
+                    if (!this.lightmapTexture.isReady()) {
+                        return false;
+                    }
+                    else {
+                        needUVs = true;
+                        this._defines.LIGHTMAP = true;
+                        this._defines.USELIGHTMAPASSHADOWMAP = this.useLightmapAsShadowmap;
+                    }
+                }
+                if (this.specularTexture && BABYLON.StandardMaterial.SpecularTextureEnabled) {
+                    if (!this.specularTexture.isReady()) {
+                        return false;
+                    }
+                    else {
+                        needUVs = true;
+                        this._defines.SPECULAR = true;
+                        this._defines.GLOSSINESS = this.useGlossinessFromSpecularMapAlpha;
+                    }
+                }
+                if (scene.getEngine().getCaps().standardDerivatives && this.bumpTexture && BABYLON.StandardMaterial.BumpTextureEnabled) {
+                    if (!this.bumpTexture.isReady()) {
+                        return false;
+                    }
+                    else {
+                        needUVs = true;
+                        this._defines.BUMP = true;
+                        if (this.useParallax) {
+                            this._defines.PARALLAX = true;
+                            if (this.useParallaxOcclusion) {
+                                this._defines.PARALLAXOCCLUSION = true;
+                            }
+                        }
+                        if (this.invertNormalMapX) {
+                            this._defines.INVERTNORMALMAPX = true;
+                        }
+                        if (this.invertNormalMapY) {
+                            this._defines.INVERTNORMALMAPY = true;
+                        }
+                        if (scene._mirroredCameraPosition) {
+                            this._defines.INVERTNORMALMAPX = !this._defines.INVERTNORMALMAPX;
+                            this._defines.INVERTNORMALMAPY = !this._defines.INVERTNORMALMAPY;
+                        }
+                    }
+                }
+                if (this.refractionTexture && BABYLON.StandardMaterial.RefractionTextureEnabled) {
+                    if (!this.refractionTexture.isReady()) {
+                        return false;
+                    }
+                    else {
+                        needUVs = true;
+                        this._defines.REFRACTION = true;
+                        this._defines.REFRACTIONMAP_3D = this.refractionTexture.isCube;
+                    }
+                }
+                if (this.cameraColorGradingTexture && BABYLON.StandardMaterial.ColorGradingTextureEnabled) {
+                    if (!this.cameraColorGradingTexture.isReady()) {
+                        return false;
+                    }
+                    else {
+                        this._defines.CAMERACOLORGRADING = true;
+                    }
+                }
+            }
+            // Effect
+            if (scene.clipPlane) {
+                this._defines.CLIPPLANE = true;
+            }
+            if (engine.getAlphaTesting()) {
+                this._defines.ALPHATEST = true;
+            }
+            if (this._shouldUseAlphaFromDiffuseTexture()) {
+                this._defines.ALPHAFROMDIFFUSE = true;
+            }
+            if (this.useEmissiveAsIllumination) {
+                this._defines.EMISSIVEASILLUMINATION = true;
+            }
+            if (this.linkEmissiveWithDiffuse) {
+                this._defines.LINKEMISSIVEWITHDIFFUSE = true;
+            }
+            if (this.useLogarithmicDepth) {
+                this._defines.LOGARITHMICDEPTH = true;
+            }
+            if (this.cameraColorCurves) {
+                this._defines.CAMERACOLORCURVES = true;
+            }
+            // Point size
+            if (this.pointsCloud || scene.forcePointsCloud) {
+                this._defines.POINTSIZE = true;
+            }
+            // Fog
+            if (scene.fogEnabled && mesh && mesh.applyFog && scene.fogMode !== BABYLON.Scene.FOGMODE_NONE && this.fogEnabled) {
+                this._defines.FOG = true;
+            }
+            if (BABYLON.StandardMaterial.FresnelEnabled) {
+                // Fresnel
+                if (this.diffuseFresnelParameters && this.diffuseFresnelParameters.isEnabled ||
+                    this.opacityFresnelParameters && this.opacityFresnelParameters.isEnabled ||
+                    this.emissiveFresnelParameters && this.emissiveFresnelParameters.isEnabled ||
+                    this.refractionFresnelParameters && this.refractionFresnelParameters.isEnabled ||
+                    this.reflectionFresnelParameters && this.reflectionFresnelParameters.isEnabled) {
+                    if (this.diffuseFresnelParameters && this.diffuseFresnelParameters.isEnabled) {
+                        this._defines.DIFFUSEFRESNEL = true;
+                    }
+                    if (this.opacityFresnelParameters && this.opacityFresnelParameters.isEnabled) {
+                        this._defines.OPACITYFRESNEL = true;
+                    }
+                    if (this.reflectionFresnelParameters && this.reflectionFresnelParameters.isEnabled) {
+                        this._defines.REFLECTIONFRESNEL = true;
+                        if (this.useReflectionFresnelFromSpecular) {
+                            this._defines.REFLECTIONFRESNELFROMSPECULAR = true;
+                        }
+                    }
+                    if (this.refractionFresnelParameters && this.refractionFresnelParameters.isEnabled) {
+                        this._defines.REFRACTIONFRESNEL = true;
+                    }
+                    if (this.emissiveFresnelParameters && this.emissiveFresnelParameters.isEnabled) {
+                        this._defines.EMISSIVEFRESNEL = true;
+                    }
+                    needNormals = true;
+                    this._defines.FRESNEL = true;
+                }
+            }
+            if (this._defines.SPECULARTERM && this.useSpecularOverAlpha) {
+                this._defines.SPECULAROVERALPHA = true;
+            }
+            // Attribs
+            if (mesh) {
+                if (needNormals && mesh.isVerticesDataPresent(BABYLON.VertexBuffer.NormalKind)) {
+                    this._defines.NORMAL = true;
+                }
+                if (needUVs) {
+                    if (mesh.isVerticesDataPresent(BABYLON.VertexBuffer.UVKind)) {
+                        this._defines.UV1 = true;
+                    }
+                    if (mesh.isVerticesDataPresent(BABYLON.VertexBuffer.UV2Kind)) {
+                        this._defines.UV2 = true;
+                    }
+                }
+                if (mesh.useVertexColors && mesh.isVerticesDataPresent(BABYLON.VertexBuffer.ColorKind)) {
+                    this._defines.VERTEXCOLOR = true;
+                    if (mesh.hasVertexAlpha) {
+                        this._defines.VERTEXALPHA = true;
+                    }
+                }
+                if (mesh.useBones && mesh.computeBonesUsingShaders) {
+                    this._defines.NUM_BONE_INFLUENCERS = mesh.numBoneInfluencers;
+                    this._defines.BonesPerMesh = (mesh.skeleton.bones.length + 1);
+                }
+                // Instances
+                if (useInstances) {
+                    this._defines.INSTANCES = true;
+                }
+            }
+            // Get correct effect      
+            if (!this._defines.isEqual(this._cachedDefines)) {
+                this._defines.cloneTo(this._cachedDefines);
+                scene.resetCachedMaterial();
+                // Fallbacks
+                var fallbacks = new BABYLON.EffectFallbacks();
+                if (this._defines.REFLECTION) {
+                    fallbacks.addFallback(0, "REFLECTION");
+                }
+                if (this._defines.SPECULAR) {
+                    fallbacks.addFallback(0, "SPECULAR");
+                }
+                if (this._defines.BUMP) {
+                    fallbacks.addFallback(0, "BUMP");
+                }
+                if (this._defines.PARALLAX) {
+                    fallbacks.addFallback(1, "PARALLAX");
+                }
+                if (this._defines.PARALLAXOCCLUSION) {
+                    fallbacks.addFallback(0, "PARALLAXOCCLUSION");
+                }
+                if (this._defines.SPECULAROVERALPHA) {
+                    fallbacks.addFallback(0, "SPECULAROVERALPHA");
+                }
+                if (this._defines.FOG) {
+                    fallbacks.addFallback(1, "FOG");
+                }
+                if (this._defines.POINTSIZE) {
+                    fallbacks.addFallback(0, "POINTSIZE");
+                }
+                if (this._defines.LOGARITHMICDEPTH) {
+                    fallbacks.addFallback(0, "LOGARITHMICDEPTH");
+                }
+                BABYLON.MaterialHelper.HandleFallbacksForShadows(this._defines, fallbacks, this.maxSimultaneousLights);
+                if (this._defines.SPECULARTERM) {
+                    fallbacks.addFallback(0, "SPECULARTERM");
+                }
+                if (this._defines.DIFFUSEFRESNEL) {
+                    fallbacks.addFallback(1, "DIFFUSEFRESNEL");
+                }
+                if (this._defines.OPACITYFRESNEL) {
+                    fallbacks.addFallback(2, "OPACITYFRESNEL");
+                }
+                if (this._defines.REFLECTIONFRESNEL) {
+                    fallbacks.addFallback(3, "REFLECTIONFRESNEL");
+                }
+                if (this._defines.EMISSIVEFRESNEL) {
+                    fallbacks.addFallback(4, "EMISSIVEFRESNEL");
+                }
+                if (this._defines.FRESNEL) {
+                    fallbacks.addFallback(4, "FRESNEL");
+                }
+                //Attributes
+                var attribs = [BABYLON.VertexBuffer.PositionKind];
+                if (this._defines.NORMAL) {
+                    attribs.push(BABYLON.VertexBuffer.NormalKind);
+                }
+                if (this._defines.UV1) {
+                    attribs.push(BABYLON.VertexBuffer.UVKind);
+                }
+                if (this._defines.UV2) {
+                    attribs.push(BABYLON.VertexBuffer.UV2Kind);
+                }
+                if (this._defines.VERTEXCOLOR) {
+                    attribs.push(BABYLON.VertexBuffer.ColorKind);
+                }
+                BABYLON.MaterialHelper.PrepareAttributesForBones(attribs, mesh, this._defines, fallbacks);
+                BABYLON.MaterialHelper.PrepareAttributesForInstances(attribs, this._defines);
+                var shaderName = "default";
+                if (this.builder) {
+                    shaderName = this.builder(new CustomShaderHelper(), shaderName, this._mainPart, this._diffusePart, this._vertexPositionPart);
+                }
+                var join = this._defines.toString();
+                var uniforms = ["world", "view", "viewProjection", "vEyePosition", "vLightsType", "vAmbientColor", "vDiffuseColor", "vSpecularColor", "vEmissiveColor",
+                    "vFogInfos", "vFogColor", "pointSize",
+                    "vDiffuseInfos", "vAmbientInfos", "vOpacityInfos", "vReflectionInfos", "vEmissiveInfos", "vSpecularInfos", "vBumpInfos", "vLightmapInfos", "vRefractionInfos",
+                    "mBones",
+                    "vClipPlane", "diffuseMatrix", "ambientMatrix", "opacityMatrix", "reflectionMatrix", "emissiveMatrix", "specularMatrix", "bumpMatrix", "lightmapMatrix", "refractionMatrix",
+                    "depthValues",
+                    "diffuseLeftColor", "diffuseRightColor", "opacityParts", "reflectionLeftColor", "reflectionRightColor", "emissiveLeftColor", "emissiveRightColor", "refractionLeftColor", "refractionRightColor",
+                    "logarithmicDepthConstant"
+                ];
+                var samplers = ["diffuseSampler", "ambientSampler", "opacitySampler", "reflectionCubeSampler", "reflection2DSampler", "emissiveSampler", "specularSampler", "bumpSampler", "lightmapSampler", "refractionCubeSampler", "refraction2DSampler"];
+                if (this._defines.CAMERACOLORCURVES) {
+                    BABYLON.ColorCurves.PrepareUniforms(uniforms);
+                }
+                if (this._defines.CAMERACOLORGRADING) {
+                    BABYLON.ColorGradingTexture.PrepareUniformsAndSamplers(uniforms, samplers);
+                }
+                BABYLON.MaterialHelper.PrepareUniformsAndSamplersList(uniforms, samplers, this._defines, this.maxSimultaneousLights);
+                this._effect = scene.getEngine().createEffect(shaderName, attribs, uniforms, samplers, join, fallbacks, this.onCompiled, this.onError, { maxSimultaneousLights: this.maxSimultaneousLights - 1 });
+            }
+            if (!this._effect.isReady()) {
+                return false;
+            }
+            this._renderId = scene.getRenderId();
+            this._wasPreviouslyReady = true;
+            if (mesh) {
+                if (!mesh._materialDefines) {
+                    mesh._materialDefines = new BABYLON.StandardMaterialDefines();
+                }
+                this._defines.cloneTo(mesh._materialDefines);
+            }
+            return true;
+        };
+        return CustomMaterial;
+    }(BABYLON.StandardMaterial));
+    BABYLON.CustomMaterial = CustomMaterial;
+})(BABYLON || (BABYLON = {}));
+
+//# sourceMappingURL=babylon.customMaterial.js.map

File diff suppressed because it is too large
+ 1 - 0
dist/preview release/materialsLibrary/babylon.customMaterial.min.js


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

@@ -5,6 +5,7 @@
 ### Major updates
 ### Major updates
  - WebGL2 context support. WebGL2 is now used instead of WebGL 1 when available. [More info here](http://doc.babylonjs.com/overviews/webgl2) ([deltakosh](https://github.com/deltakosh))
  - WebGL2 context support. WebGL2 is now used instead of WebGL 1 when available. [More info here](http://doc.babylonjs.com/overviews/webgl2) ([deltakosh](https://github.com/deltakosh))
  - Complete WebVR 1.1 support including controllers for HTC Vive and Occulus. [More info here](http://doc.babylonjs.com/overviews/webvr_camera) ([raanan](https://github.com/raananw))
  - Complete WebVR 1.1 support including controllers for HTC Vive and Occulus. [More info here](http://doc.babylonjs.com/overviews/webvr_camera) ([raanan](https://github.com/raananw))
+ - Added support for Exponential Shadow maps to replace Variance Shadow maps. [more info here](http://www.babylonjs-playground.com/debug.html#1CXNXC#3) - [Demo](http://www.babylonjs.com/Demos/AdvancedShadows/) ([deltakosh](https://github.com/deltakosh))
  - Support for [Vertex Array Objects](https://www.opengl.org/registry/specs/ARB/vertex_array_object.txt) ([deltakosh](https://github.com/deltakosh))
  - Support for [Vertex Array Objects](https://www.opengl.org/registry/specs/ARB/vertex_array_object.txt) ([deltakosh](https://github.com/deltakosh))
  - Support for multisample render targets. [Demo](http://www.babylonjs-playground.com/#12MKMN) ([deltakosh](https://github.com/deltakosh))
  - Support for multisample render targets. [Demo](http://www.babylonjs-playground.com/#12MKMN) ([deltakosh](https://github.com/deltakosh))
  - New Unity 5 Editor Toolkit. Complete pipeline integration [Doc](TODO) - ([MackeyK24](https://github.com/MackeyK24))
  - New Unity 5 Editor Toolkit. Complete pipeline integration [Doc](TODO) - ([MackeyK24](https://github.com/MackeyK24))
@@ -16,6 +17,9 @@
  - All deprecated functions and properties were removed ([deltakosh](https://github.com/deltakosh))
  - All deprecated functions and properties were removed ([deltakosh](https://github.com/deltakosh))
 
 
 ### Updates
 ### Updates
+- Added `FIXED_EQUIRECTANGULAR_MIRRORED_MODE` mode for reflection texture. [Demo here](http://www.babylonjs-playground.com/#11GAIH#22) ([deltakosh](https://github.com/deltakosh))
+- Introduced `boundingBox.centerWorld` and `boundingBox.extendSizeWorld` ([deltakosh](https://github.com/deltakosh))
+- Improved FXAA post-process ([deltakosh](https://github.com/deltakosh))
 - Added `Light.customProjectionMatrixBuilder` to allow developers to define their own projection matrix for shadows ([deltakosh](https://github.com/deltakosh))
 - Added `Light.customProjectionMatrixBuilder` to allow developers to define their own projection matrix for shadows ([deltakosh](https://github.com/deltakosh))
 - Added `set()` function to all basic types ([deltakosh](https://github.com/deltakosh))
 - Added `set()` function to all basic types ([deltakosh](https://github.com/deltakosh))
 - Added `HDRCubeTextureAssetTask` to AssetManager ([deltakosh](https://github.com/deltakosh))
 - Added `HDRCubeTextureAssetTask` to AssetManager ([deltakosh](https://github.com/deltakosh))
@@ -30,6 +34,7 @@
 - `GroundMesh`, `facetData` and `SolidParticleSystem` improvement in normal computations ([jerome](https://github.com/jbousquie))   
 - `GroundMesh`, `facetData` and `SolidParticleSystem` improvement in normal computations ([jerome](https://github.com/jbousquie))   
 - Added `AbstractMesh.addRotation()` ([jerome](https://github.com/jbousquie))  
 - Added `AbstractMesh.addRotation()` ([jerome](https://github.com/jbousquie))  
 - Added `Quaternion.RotationQuaternionFromAxis()` and `Quaternion.RotationQuaternionFromAxisToRef()` ([jerome](https://github.com/jbousquie), thanks to [abow](https://github.com/abow))   
 - Added `Quaternion.RotationQuaternionFromAxis()` and `Quaternion.RotationQuaternionFromAxisToRef()` ([jerome](https://github.com/jbousquie), thanks to [abow](https://github.com/abow))   
+- Added parameters `uvs` and `colors` to `MeshBuilder.CreateRibbon()` ([jerome](https://github.com/jbousquie))  
 - Added `Curve3.CreateCatmullRomSpline()` ([jerome](https://github.com/jbousquie) and [BitOfGold](https://github.com/BitOfGold))  
 - Added `Curve3.CreateCatmullRomSpline()` ([jerome](https://github.com/jbousquie) and [BitOfGold](https://github.com/BitOfGold))  
 - Added the optional parameter`colorFilter` to `CreateGroundFromHeightMap()` ([jerome](https://github.com/jbousquie))  
 - Added the optional parameter`colorFilter` to `CreateGroundFromHeightMap()` ([jerome](https://github.com/jbousquie))  
 - Improved the internal code of `Vector3.RotationFromAxisToRef()` ([jerome](https://github.com/jbousquie), thanks to [abow](https://github.com/abow))  
 - Improved the internal code of `Vector3.RotationFromAxisToRef()` ([jerome](https://github.com/jbousquie), thanks to [abow](https://github.com/abow))  
@@ -38,7 +43,9 @@
 - Added `POINTERTAP` and `POINTERDOUBLETAP` PointerEventTypes to register new Observer mask. (Demo here)[http://www.babylonjs-playground.com/?30] ([yuccai](https://github.com/yuccai))
 - Added `POINTERTAP` and `POINTERDOUBLETAP` PointerEventTypes to register new Observer mask. (Demo here)[http://www.babylonjs-playground.com/?30] ([yuccai](https://github.com/yuccai))
 - Added OnDoublePickTrigger for ActionManager ([yuccai](https://github.com/yuccai))
 - Added OnDoublePickTrigger for ActionManager ([yuccai](https://github.com/yuccai))
 - Added Scene.DoubleClickDelay to set the timing within a double click event like PointerEventTypes.POINTERDOUBLETAP or ActionManager.OnDoublePickTrigger has to be processed ([yuccai](https://github.com/yuccai))
 - Added Scene.DoubleClickDelay to set the timing within a double click event like PointerEventTypes.POINTERDOUBLETAP or ActionManager.OnDoublePickTrigger has to be processed ([yuccai](https://github.com/yuccai))
-- New material: ShadowOnlyMaterial to display shadows on transparent surfaces ([deltakosh](https://github.com/deltakosh)) 
+- New material: `ShadowOnlyMaterial` to display shadows on transparent surfaces ([deltakosh](https://github.com/deltakosh)) 
+- Added `VertexBuffer.TangentKind` to specify tangents in place of shader-calculated tangents ([dewadswo](https://github.com/dewadswo), [bghgary](https://github.com/bghgary))
+- Added `material.twoSidedLighting` to PBRMaterial and StandardMaterial to enable flipping normals when backfaceCulling is false ([BeardedGnome](https://github.com/BeardedGnome), [bghgary](https://github.com/bghgary))
  
  
 ### Bug fixes
 ### Bug fixes
 - Fixed a bug with spotlight direction ([deltakosh](https://github.com/deltakosh)) 
 - Fixed a bug with spotlight direction ([deltakosh](https://github.com/deltakosh)) 

+ 0 - 1
inspector/src/Inspector.ts

@@ -160,7 +160,6 @@ module INSPECTOR {
                 else {
                 else {
                     inspector = Helpers.CreateDiv('insp-right-panel', this._c2diwrapper);
                     inspector = Helpers.CreateDiv('insp-right-panel', this._c2diwrapper);
                 }
                 }
-                console.log(inspector);
 
 
                 // Add split bar
                 // Add split bar
                 if (!this._parentElement) {
                 if (!this._parentElement) {

+ 59 - 0
inspector/src/adapters/SoundAdapter.ts

@@ -0,0 +1,59 @@
+module INSPECTOR {
+
+    export class SoundAdapter
+        extends Adapter
+        implements ISoundInteractions {
+
+        constructor(obj: BABYLON.Sound) {
+            super(obj);
+        }
+
+        /** Returns the name displayed in the tree */
+        public id(): string {
+            let str = '';
+            if (this._obj.name) {
+                str = this._obj.name;
+            } // otherwise nothing displayed        
+            return str;
+        }
+
+        /** Returns the type of this object - displayed in the tree */
+        public type(): string {
+            return Helpers.GET_TYPE(this._obj);
+        }
+
+        /** Returns the list of properties to be displayed for this adapter */
+        public getProperties(): Array<PropertyLine> {
+            let propertiesLines: Array<PropertyLine> = [];
+            let camToDisplay = [];
+            // The if is there to work with the min version of babylon
+
+            let soundProperties = PROPERTIES['Sound'].properties;
+
+
+            for (let dirty of soundProperties) {
+                let infos = new Property(dirty, this._obj);
+                propertiesLines.push(new PropertyLine(infos));
+            }
+            return propertiesLines;
+        }
+
+        public getTools(): Array<AbstractTreeTool> {
+            let tools = [];
+            tools.push(new SoundInteractions(this));
+            return tools;
+        }
+
+        public setPlaying(callback: Function) {
+            if ((this._obj as BABYLON.Sound).isPlaying) {
+                (this._obj as BABYLON.Sound).pause();
+            }
+            else {
+                (this._obj as BABYLON.Sound).play();
+            }
+            (this._obj as BABYLON.Sound).onended = () => {
+                callback();
+            }
+        }
+    }
+}

+ 18 - 0
inspector/src/properties.ts

@@ -75,6 +75,24 @@ module INSPECTOR {
             type: BABYLON.FontTexture
             type: BABYLON.FontTexture
         },
         },
 
 
+        'Sound': {
+            type: BABYLON.Sound,
+            properties: [
+                'name',
+                'autoplay',
+                'loop',
+                'useCustomAttenuation',
+                'soundTrackId',
+                'spatialSound',
+                'refDistance',
+                'rolloffFactor',
+                'maxDistance',
+                'distanceModel',
+                'isPlaying',
+                'isPaused'
+            ]
+        },
+
         'ArcRotateCamera': {
         'ArcRotateCamera': {
             type: BABYLON.ArcRotateCamera,
             type: BABYLON.ArcRotateCamera,
             properties: [
             properties: [

+ 26 - 0
inspector/src/tabs/SoundTab.ts

@@ -0,0 +1,26 @@
+module INSPECTOR {
+
+    export class SoundTab extends PropertyTab {
+
+        constructor(tabbar: TabBar, inspector: Inspector) {
+            super(tabbar, 'Audio', inspector);
+        }
+        /* Overrides super */
+        protected _getTree(): Array<TreeItem> {
+            let arr = [];
+
+            // get all cameras from the first scene
+            let instances = this._inspector.scene;
+            for (let sounds of instances.soundTracks) {
+                let sound = sounds.soundCollection;
+                sound.forEach(element => {
+                    arr.push(new TreeItem(this, new SoundAdapter(element)));
+                });
+
+            }
+            return arr;
+        }
+
+    }
+
+}

+ 1 - 0
inspector/src/tabs/TabBar.ts

@@ -39,6 +39,7 @@ module INSPECTOR {
             this._tabs.push(new MaterialTab(this, this._inspector));
             this._tabs.push(new MaterialTab(this, this._inspector));
 
 
             this._tabs.push(new CameraTab(this, this._inspector));
             this._tabs.push(new CameraTab(this, this._inspector));
+            this._tabs.push(new SoundTab(this, this._inspector));
 
 
             this._toolBar = new Toolbar(this._inspector);
             this._toolBar = new Toolbar(this._inspector);
 
 

+ 42 - 0
inspector/src/treetools/SoundInteractions.ts

@@ -0,0 +1,42 @@
+module INSPECTOR {
+
+    export interface ISoundInteractions {
+        setPlaying: (callback: Function) => void;
+    }
+
+    /**
+     * 
+     */
+    export class SoundInteractions extends AbstractTreeTool {
+        private playSound: ISoundInteractions;
+        private b: boolean;
+
+        constructor(playSound: ISoundInteractions) {
+            super();
+            this.playSound = playSound;
+            this.b = false;
+            this._elem.classList.add('fa-play');
+        }
+
+        protected action() {
+            super.action();
+            this._playSound();
+        }
+
+        private _playSound() {
+
+            if (this._elem.classList.contains('fa-play')) {
+                this._elem.classList.remove('fa-play');
+                this._elem.classList.add('fa-pause');
+            }
+            else {
+                this._elem.classList.remove('fa-pause');
+                this._elem.classList.add('fa-play');
+            }
+            this.playSound.setPlaying(() => {
+                this._elem.classList.remove('fa-pause');
+                this._elem.classList.add('fa-play');
+            });
+        }
+    }
+}

+ 12 - 0
inspector/test/index.js

@@ -48,6 +48,16 @@ var Test = (function () {
             camera4.parent = camera;
             camera4.parent = camera;
         */
         */
 
 
+        //Sounds
+        var jump = new BABYLON.Sound("Jump", "/assets/sounds/jump.wav", scene);
+        var explosion = new BABYLON.Sound("Explosion", "/assets/sounds/explosion.wav", scene);
+        jump.setVolume(0.1);
+        window.addEventListener("keydown", function (evt) {
+            if (evt.keyCode === 32) {
+                jump.play();
+            }
+        });
+
         var sphere1 = BABYLON.Mesh.CreateSphere("Sphere1", 10.0, 9.0, scene);
         var sphere1 = BABYLON.Mesh.CreateSphere("Sphere1", 10.0, 9.0, scene);
         var sphere2 = BABYLON.Mesh.CreateSphere("Sphere2", 2.0, 9.0, scene);//Only two segments
         var sphere2 = BABYLON.Mesh.CreateSphere("Sphere2", 2.0, 9.0, scene);//Only two segments
         var sphere3 = BABYLON.Mesh.CreateSphere("Sphere3", 10.0, 9.0, scene);
         var sphere3 = BABYLON.Mesh.CreateSphere("Sphere3", 10.0, 9.0, scene);
@@ -181,6 +191,8 @@ var Test = (function () {
 
 
         plane.material = materialPlane;
         plane.material = materialPlane;
 
 
+
+
         var d = 50;
         var d = 50;
         var cubes = new Array();
         var cubes = new Array();
         for (var i = 0; i < 360; i += 20) {
         for (var i = 0; i < 360; i += 20) {

+ 3 - 3
loaders/src/glTF/babylon.glTFFileLoaderExtension.ts

@@ -16,7 +16,7 @@ module BABYLON {
         * Defines an override for loading the runtime
         * Defines an override for loading the runtime
         * Return true to stop further extensions from loading the runtime
         * Return true to stop further extensions from loading the runtime
         */
         */
-        public loadRuntimeAsync(scene: Scene, data: string | ArrayBuffer, rootUrl: string, onSuccess: (gltfRuntime: IGLTFRuntime) => void, onError: () => void): boolean {
+        public loadRuntimeAsync(scene: Scene, data: string, rootUrl: string, onSuccess: (gltfRuntime: IGLTFRuntime) => void, onError: () => void): boolean {
             return false;
             return false;
         }
         }
 
 
@@ -72,12 +72,12 @@ module BABYLON {
         // Utilities
         // Utilities
         // ---------
         // ---------
 
 
-        public static LoadRuntimeAsync(scene: Scene, data: string | ArrayBuffer, rootUrl: string, onSuccess: (gltfRuntime: IGLTFRuntime) => void, onError: () => void): void {
+        public static LoadRuntimeAsync(scene: Scene, data: string, rootUrl: string, onSuccess: (gltfRuntime: IGLTFRuntime) => void, onError: () => void): void {
             GLTFFileLoaderExtension.ApplyExtensions(loaderExtension => {
             GLTFFileLoaderExtension.ApplyExtensions(loaderExtension => {
                 return loaderExtension.loadRuntimeAsync(scene, data, rootUrl, onSuccess, onError);
                 return loaderExtension.loadRuntimeAsync(scene, data, rootUrl, onSuccess, onError);
             }, () => {
             }, () => {
                 setTimeout(() => {
                 setTimeout(() => {
-                    onSuccess(GLTFFileLoaderBase.CreateRuntime(JSON.parse(<string>data), scene, rootUrl));
+                    onSuccess(GLTFFileLoaderBase.CreateRuntime(JSON.parse(data), scene, rootUrl));
                 });
                 });
             });
             });
         }
         }

+ 0 - 34
localDev/template/index.js

@@ -1,34 +0,0 @@
-/// <reference path="../../dist/preview release/babylon.d.ts"/>
-
-// Playground like creation of the scene
-var createScene = function () {
-
-    // This creates a basic Babylon Scene object (non-mesh)
-    var scene = new BABYLON.Scene(engine);
-
-    // This creates and positions a free camera (non-mesh)
-    var camera = new BABYLON.FreeCamera("camera1", new BABYLON.Vector3(0, 5, -10), scene);
-
-    // This targets the camera to scene origin
-    camera.setTarget(BABYLON.Vector3.Zero());
-
-    // This attaches the camera to the canvas
-    camera.attachControl(canvas, true);
-
-    // This creates a light, aiming 0,1,0 - to the sky (non-mesh)
-    var light = new BABYLON.HemisphericLight("light1", new BABYLON.Vector3(0, 1, 0), scene);
-
-    // Default intensity is 1. Let's dim the light a small amount
-    light.intensity = 0.7;
-
-    // Our built-in 'sphere' shape. Params: name, subdivs, size, scene
-    var sphere = BABYLON.Mesh.CreateSphere("sphere1", 16, 2, scene);
-
-    // Move the sphere upward 1/2 its height
-    sphere.position.y = 1;
-
-    // Our built-in 'ground' shape. Params: name, width, depth, subdivs, scene
-    var ground = BABYLON.Mesh.CreateGround("ground1", 6, 6, 2, scene);
-
-    return scene;
-};

File diff suppressed because it is too large
+ 1 - 0
materialsLibrary/src/custom/Babylon.CustomMaterial.js.map


+ 398 - 0
materialsLibrary/src/custom/babylon.customMaterial.js

@@ -0,0 +1,398 @@
+/// <reference path="../../../dist/preview release/babylon.d.ts"/>
+var __extends = (this && this.__extends) || function (d, b) {
+    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
+    function __() { this.constructor = d; }
+    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
+};
+var BABYLON;
+(function (BABYLON) {
+    var CustomShaderHelper = (function () {
+        function CustomShaderHelper() {
+        }
+        return CustomShaderHelper;
+    }());
+    BABYLON.CustomShaderHelper = CustomShaderHelper;
+    var CustomMaterial = (function (_super) {
+        __extends(CustomMaterial, _super);
+        function CustomMaterial(name, builder, scene) {
+            var _this = _super.call(this, name, scene) || this;
+            _this._mainPart = 'void main(void) {';
+            _this._diffusePart = 'vec3 diffuseColor=vDiffuseColor.rgb;';
+            _this._vertexPositionPart = 'gl_Position=viewProjection*finalWorld*vec4(position,1.0);';
+            _this.builder = builder;
+            return _this;
+        }
+        CustomMaterial.prototype.isReady = function (mesh, useInstances) {
+            if (this.isFrozen) {
+                if (this._wasPreviouslyReady) {
+                    return true;
+                }
+            }
+            var scene = this.getScene();
+            var engine = scene.getEngine();
+            var needUVs = false;
+            var needNormals = false;
+            this._defines.reset();
+            // Lights
+            if (scene.lightsEnabled && !this.disableLighting) {
+                needNormals = BABYLON.MaterialHelper.PrepareDefinesForLights(scene, mesh, this._defines, this.maxSimultaneousLights);
+            }
+            if (!this.checkReadyOnEveryCall) {
+                if (this._renderId === scene.getRenderId()) {
+                    if (this._checkCache(scene, mesh, useInstances)) {
+                        return true;
+                    }
+                }
+            }
+            // Textures
+            if (scene.texturesEnabled) {
+                if (this.diffuseTexture && BABYLON.StandardMaterial.DiffuseTextureEnabled) {
+                    if (!this.diffuseTexture.isReady()) {
+                        return false;
+                    }
+                    else {
+                        needUVs = true;
+                        this._defines.DIFFUSE = true;
+                    }
+                }
+                if (this.ambientTexture && BABYLON.StandardMaterial.AmbientTextureEnabled) {
+                    if (!this.ambientTexture.isReady()) {
+                        return false;
+                    }
+                    else {
+                        needUVs = true;
+                        this._defines.AMBIENT = true;
+                    }
+                }
+                if (this.opacityTexture && BABYLON.StandardMaterial.OpacityTextureEnabled) {
+                    if (!this.opacityTexture.isReady()) {
+                        return false;
+                    }
+                    else {
+                        needUVs = true;
+                        this._defines.OPACITY = true;
+                        if (this.opacityTexture.getAlphaFromRGB) {
+                            this._defines.OPACITYRGB = true;
+                        }
+                    }
+                }
+                if (this.reflectionTexture && BABYLON.StandardMaterial.ReflectionTextureEnabled) {
+                    if (!this.reflectionTexture.isReady()) {
+                        return false;
+                    }
+                    else {
+                        needNormals = true;
+                        this._defines.REFLECTION = true;
+                        if (this.roughness > 0) {
+                            this._defines.ROUGHNESS = true;
+                        }
+                        if (this.useReflectionOverAlpha) {
+                            this._defines.REFLECTIONOVERALPHA = true;
+                        }
+                        if (this.reflectionTexture.coordinatesMode === BABYLON.Texture.INVCUBIC_MODE) {
+                            this._defines.INVERTCUBICMAP = true;
+                        }
+                        this._defines.REFLECTIONMAP_3D = this.reflectionTexture.isCube;
+                        switch (this.reflectionTexture.coordinatesMode) {
+                            case BABYLON.Texture.CUBIC_MODE:
+                            case BABYLON.Texture.INVCUBIC_MODE:
+                                this._defines.REFLECTIONMAP_CUBIC = true;
+                                break;
+                            case BABYLON.Texture.EXPLICIT_MODE:
+                                this._defines.REFLECTIONMAP_EXPLICIT = true;
+                                break;
+                            case BABYLON.Texture.PLANAR_MODE:
+                                this._defines.REFLECTIONMAP_PLANAR = true;
+                                break;
+                            case BABYLON.Texture.PROJECTION_MODE:
+                                this._defines.REFLECTIONMAP_PROJECTION = true;
+                                break;
+                            case BABYLON.Texture.SKYBOX_MODE:
+                                this._defines.REFLECTIONMAP_SKYBOX = true;
+                                break;
+                            case BABYLON.Texture.SPHERICAL_MODE:
+                                this._defines.REFLECTIONMAP_SPHERICAL = true;
+                                break;
+                            case BABYLON.Texture.EQUIRECTANGULAR_MODE:
+                                this._defines.REFLECTIONMAP_EQUIRECTANGULAR = true;
+                                break;
+                            case BABYLON.Texture.FIXED_EQUIRECTANGULAR_MODE:
+                                this._defines.REFLECTIONMAP_EQUIRECTANGULAR_FIXED = true;
+                                break;
+                        }
+                    }
+                }
+                if (this.emissiveTexture && BABYLON.StandardMaterial.EmissiveTextureEnabled) {
+                    if (!this.emissiveTexture.isReady()) {
+                        return false;
+                    }
+                    else {
+                        needUVs = true;
+                        this._defines.EMISSIVE = true;
+                    }
+                }
+                if (this.lightmapTexture && BABYLON.StandardMaterial.LightmapTextureEnabled) {
+                    if (!this.lightmapTexture.isReady()) {
+                        return false;
+                    }
+                    else {
+                        needUVs = true;
+                        this._defines.LIGHTMAP = true;
+                        this._defines.USELIGHTMAPASSHADOWMAP = this.useLightmapAsShadowmap;
+                    }
+                }
+                if (this.specularTexture && BABYLON.StandardMaterial.SpecularTextureEnabled) {
+                    if (!this.specularTexture.isReady()) {
+                        return false;
+                    }
+                    else {
+                        needUVs = true;
+                        this._defines.SPECULAR = true;
+                        this._defines.GLOSSINESS = this.useGlossinessFromSpecularMapAlpha;
+                    }
+                }
+                if (scene.getEngine().getCaps().standardDerivatives && this.bumpTexture && BABYLON.StandardMaterial.BumpTextureEnabled) {
+                    if (!this.bumpTexture.isReady()) {
+                        return false;
+                    }
+                    else {
+                        needUVs = true;
+                        this._defines.BUMP = true;
+                        if (this.useParallax) {
+                            this._defines.PARALLAX = true;
+                            if (this.useParallaxOcclusion) {
+                                this._defines.PARALLAXOCCLUSION = true;
+                            }
+                        }
+                        if (this.invertNormalMapX) {
+                            this._defines.INVERTNORMALMAPX = true;
+                        }
+                        if (this.invertNormalMapY) {
+                            this._defines.INVERTNORMALMAPY = true;
+                        }
+                        if (scene._mirroredCameraPosition) {
+                            this._defines.INVERTNORMALMAPX = !this._defines.INVERTNORMALMAPX;
+                            this._defines.INVERTNORMALMAPY = !this._defines.INVERTNORMALMAPY;
+                        }
+                    }
+                }
+                if (this.refractionTexture && BABYLON.StandardMaterial.RefractionTextureEnabled) {
+                    if (!this.refractionTexture.isReady()) {
+                        return false;
+                    }
+                    else {
+                        needUVs = true;
+                        this._defines.REFRACTION = true;
+                        this._defines.REFRACTIONMAP_3D = this.refractionTexture.isCube;
+                    }
+                }
+                if (this.cameraColorGradingTexture && BABYLON.StandardMaterial.ColorGradingTextureEnabled) {
+                    if (!this.cameraColorGradingTexture.isReady()) {
+                        return false;
+                    }
+                    else {
+                        this._defines.CAMERACOLORGRADING = true;
+                    }
+                }
+            }
+            // Effect
+            if (scene.clipPlane) {
+                this._defines.CLIPPLANE = true;
+            }
+            if (engine.getAlphaTesting()) {
+                this._defines.ALPHATEST = true;
+            }
+            if (this._shouldUseAlphaFromDiffuseTexture()) {
+                this._defines.ALPHAFROMDIFFUSE = true;
+            }
+            if (this.useEmissiveAsIllumination) {
+                this._defines.EMISSIVEASILLUMINATION = true;
+            }
+            if (this.linkEmissiveWithDiffuse) {
+                this._defines.LINKEMISSIVEWITHDIFFUSE = true;
+            }
+            if (this.useLogarithmicDepth) {
+                this._defines.LOGARITHMICDEPTH = true;
+            }
+            if (this.cameraColorCurves) {
+                this._defines.CAMERACOLORCURVES = true;
+            }
+            // Point size
+            if (this.pointsCloud || scene.forcePointsCloud) {
+                this._defines.POINTSIZE = true;
+            }
+            // Fog
+            if (scene.fogEnabled && mesh && mesh.applyFog && scene.fogMode !== BABYLON.Scene.FOGMODE_NONE && this.fogEnabled) {
+                this._defines.FOG = true;
+            }
+            if (BABYLON.StandardMaterial.FresnelEnabled) {
+                // Fresnel
+                if (this.diffuseFresnelParameters && this.diffuseFresnelParameters.isEnabled ||
+                    this.opacityFresnelParameters && this.opacityFresnelParameters.isEnabled ||
+                    this.emissiveFresnelParameters && this.emissiveFresnelParameters.isEnabled ||
+                    this.refractionFresnelParameters && this.refractionFresnelParameters.isEnabled ||
+                    this.reflectionFresnelParameters && this.reflectionFresnelParameters.isEnabled) {
+                    if (this.diffuseFresnelParameters && this.diffuseFresnelParameters.isEnabled) {
+                        this._defines.DIFFUSEFRESNEL = true;
+                    }
+                    if (this.opacityFresnelParameters && this.opacityFresnelParameters.isEnabled) {
+                        this._defines.OPACITYFRESNEL = true;
+                    }
+                    if (this.reflectionFresnelParameters && this.reflectionFresnelParameters.isEnabled) {
+                        this._defines.REFLECTIONFRESNEL = true;
+                        if (this.useReflectionFresnelFromSpecular) {
+                            this._defines.REFLECTIONFRESNELFROMSPECULAR = true;
+                        }
+                    }
+                    if (this.refractionFresnelParameters && this.refractionFresnelParameters.isEnabled) {
+                        this._defines.REFRACTIONFRESNEL = true;
+                    }
+                    if (this.emissiveFresnelParameters && this.emissiveFresnelParameters.isEnabled) {
+                        this._defines.EMISSIVEFRESNEL = true;
+                    }
+                    needNormals = true;
+                    this._defines.FRESNEL = true;
+                }
+            }
+            if (this._defines.SPECULARTERM && this.useSpecularOverAlpha) {
+                this._defines.SPECULAROVERALPHA = true;
+            }
+            // Attribs
+            if (mesh) {
+                if (needNormals && mesh.isVerticesDataPresent(BABYLON.VertexBuffer.NormalKind)) {
+                    this._defines.NORMAL = true;
+                }
+                if (needUVs) {
+                    if (mesh.isVerticesDataPresent(BABYLON.VertexBuffer.UVKind)) {
+                        this._defines.UV1 = true;
+                    }
+                    if (mesh.isVerticesDataPresent(BABYLON.VertexBuffer.UV2Kind)) {
+                        this._defines.UV2 = true;
+                    }
+                }
+                if (mesh.useVertexColors && mesh.isVerticesDataPresent(BABYLON.VertexBuffer.ColorKind)) {
+                    this._defines.VERTEXCOLOR = true;
+                    if (mesh.hasVertexAlpha) {
+                        this._defines.VERTEXALPHA = true;
+                    }
+                }
+                if (mesh.useBones && mesh.computeBonesUsingShaders) {
+                    this._defines.NUM_BONE_INFLUENCERS = mesh.numBoneInfluencers;
+                    this._defines.BonesPerMesh = (mesh.skeleton.bones.length + 1);
+                }
+                // Instances
+                if (useInstances) {
+                    this._defines.INSTANCES = true;
+                }
+            }
+            // Get correct effect      
+            if (!this._defines.isEqual(this._cachedDefines)) {
+                this._defines.cloneTo(this._cachedDefines);
+                scene.resetCachedMaterial();
+                // Fallbacks
+                var fallbacks = new BABYLON.EffectFallbacks();
+                if (this._defines.REFLECTION) {
+                    fallbacks.addFallback(0, "REFLECTION");
+                }
+                if (this._defines.SPECULAR) {
+                    fallbacks.addFallback(0, "SPECULAR");
+                }
+                if (this._defines.BUMP) {
+                    fallbacks.addFallback(0, "BUMP");
+                }
+                if (this._defines.PARALLAX) {
+                    fallbacks.addFallback(1, "PARALLAX");
+                }
+                if (this._defines.PARALLAXOCCLUSION) {
+                    fallbacks.addFallback(0, "PARALLAXOCCLUSION");
+                }
+                if (this._defines.SPECULAROVERALPHA) {
+                    fallbacks.addFallback(0, "SPECULAROVERALPHA");
+                }
+                if (this._defines.FOG) {
+                    fallbacks.addFallback(1, "FOG");
+                }
+                if (this._defines.POINTSIZE) {
+                    fallbacks.addFallback(0, "POINTSIZE");
+                }
+                if (this._defines.LOGARITHMICDEPTH) {
+                    fallbacks.addFallback(0, "LOGARITHMICDEPTH");
+                }
+                BABYLON.MaterialHelper.HandleFallbacksForShadows(this._defines, fallbacks, this.maxSimultaneousLights);
+                if (this._defines.SPECULARTERM) {
+                    fallbacks.addFallback(0, "SPECULARTERM");
+                }
+                if (this._defines.DIFFUSEFRESNEL) {
+                    fallbacks.addFallback(1, "DIFFUSEFRESNEL");
+                }
+                if (this._defines.OPACITYFRESNEL) {
+                    fallbacks.addFallback(2, "OPACITYFRESNEL");
+                }
+                if (this._defines.REFLECTIONFRESNEL) {
+                    fallbacks.addFallback(3, "REFLECTIONFRESNEL");
+                }
+                if (this._defines.EMISSIVEFRESNEL) {
+                    fallbacks.addFallback(4, "EMISSIVEFRESNEL");
+                }
+                if (this._defines.FRESNEL) {
+                    fallbacks.addFallback(4, "FRESNEL");
+                }
+                //Attributes
+                var attribs = [BABYLON.VertexBuffer.PositionKind];
+                if (this._defines.NORMAL) {
+                    attribs.push(BABYLON.VertexBuffer.NormalKind);
+                }
+                if (this._defines.UV1) {
+                    attribs.push(BABYLON.VertexBuffer.UVKind);
+                }
+                if (this._defines.UV2) {
+                    attribs.push(BABYLON.VertexBuffer.UV2Kind);
+                }
+                if (this._defines.VERTEXCOLOR) {
+                    attribs.push(BABYLON.VertexBuffer.ColorKind);
+                }
+                BABYLON.MaterialHelper.PrepareAttributesForBones(attribs, mesh, this._defines, fallbacks);
+                BABYLON.MaterialHelper.PrepareAttributesForInstances(attribs, this._defines);
+                var shaderName = "default";
+                if (this.builder) {
+                    shaderName = this.builder(new CustomShaderHelper(), shaderName, this._mainPart, this._diffusePart, this._vertexPositionPart);
+                }
+                var join = this._defines.toString();
+                var uniforms = ["world", "view", "viewProjection", "vEyePosition", "vLightsType", "vAmbientColor", "vDiffuseColor", "vSpecularColor", "vEmissiveColor",
+                    "vFogInfos", "vFogColor", "pointSize",
+                    "vDiffuseInfos", "vAmbientInfos", "vOpacityInfos", "vReflectionInfos", "vEmissiveInfos", "vSpecularInfos", "vBumpInfos", "vLightmapInfos", "vRefractionInfos",
+                    "mBones",
+                    "vClipPlane", "diffuseMatrix", "ambientMatrix", "opacityMatrix", "reflectionMatrix", "emissiveMatrix", "specularMatrix", "bumpMatrix", "lightmapMatrix", "refractionMatrix",
+                    "depthValues",
+                    "diffuseLeftColor", "diffuseRightColor", "opacityParts", "reflectionLeftColor", "reflectionRightColor", "emissiveLeftColor", "emissiveRightColor", "refractionLeftColor", "refractionRightColor",
+                    "logarithmicDepthConstant"
+                ];
+                var samplers = ["diffuseSampler", "ambientSampler", "opacitySampler", "reflectionCubeSampler", "reflection2DSampler", "emissiveSampler", "specularSampler", "bumpSampler", "lightmapSampler", "refractionCubeSampler", "refraction2DSampler"];
+                if (this._defines.CAMERACOLORCURVES) {
+                    BABYLON.ColorCurves.PrepareUniforms(uniforms);
+                }
+                if (this._defines.CAMERACOLORGRADING) {
+                    BABYLON.ColorGradingTexture.PrepareUniformsAndSamplers(uniforms, samplers);
+                }
+                BABYLON.MaterialHelper.PrepareUniformsAndSamplersList(uniforms, samplers, this._defines, this.maxSimultaneousLights);
+                this._effect = scene.getEngine().createEffect(shaderName, attribs, uniforms, samplers, join, fallbacks, this.onCompiled, this.onError, { maxSimultaneousLights: this.maxSimultaneousLights - 1 });
+            }
+            if (!this._effect.isReady()) {
+                return false;
+            }
+            this._renderId = scene.getRenderId();
+            this._wasPreviouslyReady = true;
+            if (mesh) {
+                if (!mesh._materialDefines) {
+                    mesh._materialDefines = new BABYLON.StandardMaterialDefines();
+                }
+                this._defines.cloneTo(mesh._materialDefines);
+            }
+            return true;
+        };
+        return CustomMaterial;
+    }(BABYLON.StandardMaterial));
+    BABYLON.CustomMaterial = CustomMaterial;
+})(BABYLON || (BABYLON = {}));
+
+//# sourceMappingURL=babylon.customMaterial.js.map

+ 474 - 0
materialsLibrary/src/custom/babylon.customMaterial.ts

@@ -0,0 +1,474 @@
+/// <reference path="../../../dist/preview release/babylon.d.ts"/>
+
+module BABYLON { 
+
+  export class CustomShaderHelper{
+ 
+  }
+
+   export interface ICustomMaterialBuilder {
+         (builder:CustomShaderHelper , name: string ,mainPart: string , diffusePart:string ,vertexPositionPart:string ): string;
+   } 
+ 
+   export class CustomMaterial extends StandardMaterial  {
+        
+        public builder: ICustomMaterialBuilder;
+        private _mainPart = 'void main(void) {';
+        private _diffusePart = 'vec3 diffuseColor=vDiffuseColor.rgb;';
+        private _vertexPositionPart = 'gl_Position=viewProjection*finalWorld*vec4(position,1.0);';
+        
+        constructor (name: string, builder:ICustomMaterialBuilder, scene: Scene) {
+            super(name, scene);  
+            this.builder = builder;             
+        }   
+ 
+        public isReady(mesh?: AbstractMesh, useInstances?: boolean): boolean {
+            if (this.isFrozen) {
+                if (this._wasPreviouslyReady) {
+                    return true;
+                }
+            }
+
+            var scene = this.getScene();
+            var engine = scene.getEngine();
+            var needUVs = false;
+            var needNormals = false;
+
+            this._defines.reset();
+
+            // Lights
+            if (scene.lightsEnabled && !this.disableLighting) {
+                needNormals = MaterialHelper.PrepareDefinesForLights(scene, mesh, this._defines, this.maxSimultaneousLights);
+            }
+
+            if (!this.checkReadyOnEveryCall) {
+                if (this._renderId === scene.getRenderId()) {
+                    if (this._checkCache(scene, mesh, useInstances)) {
+                        return true;
+                    }
+                }
+            }
+
+            // Textures
+            if (scene.texturesEnabled) {
+                if (this.diffuseTexture && StandardMaterial.DiffuseTextureEnabled) {
+                    if (!this.diffuseTexture.isReady()) {
+                        return false;
+                    } else {
+                        needUVs = true;
+                        this._defines.DIFFUSE = true;
+                    }
+                }
+
+                if (this.ambientTexture && StandardMaterial.AmbientTextureEnabled) {
+                    if (!this.ambientTexture.isReady()) {
+                        return false;
+                    } else {
+                        needUVs = true;
+                        this._defines.AMBIENT = true;
+                    }
+                }
+
+                if (this.opacityTexture && StandardMaterial.OpacityTextureEnabled) {
+                    if (!this.opacityTexture.isReady()) {
+                        return false;
+                    } else {
+                        needUVs = true;
+                        this._defines.OPACITY = true;
+
+                        if (this.opacityTexture.getAlphaFromRGB) {
+                            this._defines.OPACITYRGB = true;
+                        }
+                    }
+                }
+
+                if (this.reflectionTexture && StandardMaterial.ReflectionTextureEnabled) {
+                    if (!this.reflectionTexture.isReady()) {
+                        return false;
+                    } else {
+                        needNormals = true;
+                        this._defines.REFLECTION = true;
+
+                        if (this.roughness > 0) {
+                            this._defines.ROUGHNESS = true;
+                        }
+
+                        if (this.useReflectionOverAlpha) {
+                            this._defines.REFLECTIONOVERALPHA = true;
+                        }
+
+                        if (this.reflectionTexture.coordinatesMode === Texture.INVCUBIC_MODE) {
+                            this._defines.INVERTCUBICMAP = true;
+                        }
+
+                        this._defines.REFLECTIONMAP_3D = this.reflectionTexture.isCube;
+
+                        switch (this.reflectionTexture.coordinatesMode) {
+                            case Texture.CUBIC_MODE:
+                            case Texture.INVCUBIC_MODE:
+                                this._defines.REFLECTIONMAP_CUBIC = true;
+                                break;
+                            case Texture.EXPLICIT_MODE:
+                                this._defines.REFLECTIONMAP_EXPLICIT = true;
+                                break;
+                            case Texture.PLANAR_MODE:
+                                this._defines.REFLECTIONMAP_PLANAR = true;
+                                break;
+                            case Texture.PROJECTION_MODE:
+                                this._defines.REFLECTIONMAP_PROJECTION = true;
+                                break;
+                            case Texture.SKYBOX_MODE:
+                                this._defines.REFLECTIONMAP_SKYBOX = true;
+                                break;
+                            case Texture.SPHERICAL_MODE:
+                                this._defines.REFLECTIONMAP_SPHERICAL = true;
+                                break;
+                            case Texture.EQUIRECTANGULAR_MODE:
+                                this._defines.REFLECTIONMAP_EQUIRECTANGULAR = true;
+                                break;
+                            case Texture.FIXED_EQUIRECTANGULAR_MODE:
+                                this._defines.REFLECTIONMAP_EQUIRECTANGULAR_FIXED = true;
+                                break;
+                        }
+                    }
+                }
+
+                if (this.emissiveTexture && StandardMaterial.EmissiveTextureEnabled) {
+                    if (!this.emissiveTexture.isReady()) {
+                        return false;
+                    } else {
+                        needUVs = true;
+                        this._defines.EMISSIVE = true;
+                    }
+                }
+
+                if (this.lightmapTexture && StandardMaterial.LightmapTextureEnabled) {
+                    if (!this.lightmapTexture.isReady()) {
+                        return false;
+                    } else {
+                        needUVs = true;
+                        this._defines.LIGHTMAP = true;
+                        this._defines.USELIGHTMAPASSHADOWMAP = this.useLightmapAsShadowmap;
+                    }
+                }
+
+                if (this.specularTexture && StandardMaterial.SpecularTextureEnabled) {
+                    if (!this.specularTexture.isReady()) {
+                        return false;
+                    } else {
+                        needUVs = true;
+                        this._defines.SPECULAR = true;
+                        this._defines.GLOSSINESS = this.useGlossinessFromSpecularMapAlpha;
+                    }
+                }
+
+                if (scene.getEngine().getCaps().standardDerivatives && this.bumpTexture && StandardMaterial.BumpTextureEnabled) {
+                    if (!this.bumpTexture.isReady()) {
+                        return false;
+                    } else {
+                        needUVs = true;
+                        this._defines.BUMP = true;
+
+                        if (this.useParallax) {
+                            this._defines.PARALLAX = true;
+                            if (this.useParallaxOcclusion) {
+                                this._defines.PARALLAXOCCLUSION = true;
+                            }
+                        }
+
+                        if (this.invertNormalMapX) {
+                            this._defines.INVERTNORMALMAPX = true;
+                        }
+
+                        if (this.invertNormalMapY) {
+                            this._defines.INVERTNORMALMAPY = true;
+                        }
+
+                        if (scene._mirroredCameraPosition) {
+                            this._defines.INVERTNORMALMAPX = !this._defines.INVERTNORMALMAPX;
+                            this._defines.INVERTNORMALMAPY = !this._defines.INVERTNORMALMAPY;
+                        }
+                    }
+                }
+
+                if (this.refractionTexture && StandardMaterial.RefractionTextureEnabled) {
+                    if (!this.refractionTexture.isReady()) {
+                        return false;
+                    } else {
+                        needUVs = true;
+                        this._defines.REFRACTION = true;
+
+                        this._defines.REFRACTIONMAP_3D = this.refractionTexture.isCube;
+                    }
+                }
+
+                if (this.cameraColorGradingTexture && StandardMaterial.ColorGradingTextureEnabled) {
+                    if (!this.cameraColorGradingTexture.isReady()) {
+                        return false;
+                    } else {
+                        this._defines.CAMERACOLORGRADING = true;
+                    }
+                }
+            }
+
+            // Effect
+            if (scene.clipPlane) {
+                this._defines.CLIPPLANE = true;
+            }
+
+            if (engine.getAlphaTesting()) {
+                this._defines.ALPHATEST = true;
+            }
+
+            if (this._shouldUseAlphaFromDiffuseTexture()) {
+                this._defines.ALPHAFROMDIFFUSE = true;
+            }
+
+            if (this.useEmissiveAsIllumination) {
+                this._defines.EMISSIVEASILLUMINATION = true;
+            }
+
+            if (this.linkEmissiveWithDiffuse) {
+                this._defines.LINKEMISSIVEWITHDIFFUSE = true;
+            }
+
+            if (this.useLogarithmicDepth) {
+                this._defines.LOGARITHMICDEPTH = true;
+            }
+            
+            if (this.cameraColorCurves) {
+                this._defines.CAMERACOLORCURVES = true;
+            }
+
+            // Point size
+            if (this.pointsCloud || scene.forcePointsCloud) {
+                this._defines.POINTSIZE = true;
+            }
+
+            // Fog
+            if (scene.fogEnabled && mesh && mesh.applyFog && scene.fogMode !== Scene.FOGMODE_NONE && this.fogEnabled) {
+                this._defines.FOG = true;
+            }
+
+            if (StandardMaterial.FresnelEnabled) {
+                // Fresnel
+                if (this.diffuseFresnelParameters && this.diffuseFresnelParameters.isEnabled ||
+                    this.opacityFresnelParameters && this.opacityFresnelParameters.isEnabled ||
+                    this.emissiveFresnelParameters && this.emissiveFresnelParameters.isEnabled ||
+                    this.refractionFresnelParameters && this.refractionFresnelParameters.isEnabled ||
+                    this.reflectionFresnelParameters && this.reflectionFresnelParameters.isEnabled) {
+
+                    if (this.diffuseFresnelParameters && this.diffuseFresnelParameters.isEnabled) {
+                        this._defines.DIFFUSEFRESNEL = true;
+                    }
+
+                    if (this.opacityFresnelParameters && this.opacityFresnelParameters.isEnabled) {
+                        this._defines.OPACITYFRESNEL = true;
+                    }
+
+                    if (this.reflectionFresnelParameters && this.reflectionFresnelParameters.isEnabled) {
+                        this._defines.REFLECTIONFRESNEL = true;
+
+                        if (this.useReflectionFresnelFromSpecular) {
+                            this._defines.REFLECTIONFRESNELFROMSPECULAR = true;
+                        }
+                    }
+
+                    if (this.refractionFresnelParameters && this.refractionFresnelParameters.isEnabled) {
+                        this._defines.REFRACTIONFRESNEL = true;
+                    }
+
+                    if (this.emissiveFresnelParameters && this.emissiveFresnelParameters.isEnabled) {
+                        this._defines.EMISSIVEFRESNEL = true;
+                    }
+
+                    needNormals = true;
+                    this._defines.FRESNEL = true;
+                }
+            }
+
+            if (this._defines.SPECULARTERM && this.useSpecularOverAlpha) {
+                this._defines.SPECULAROVERALPHA = true;
+            }
+
+            // Attribs
+            if (mesh) {
+                if (needNormals && mesh.isVerticesDataPresent(VertexBuffer.NormalKind)) {
+                    this._defines.NORMAL = true;
+                }
+                if (needUVs) {
+                    if (mesh.isVerticesDataPresent(VertexBuffer.UVKind)) {
+                        this._defines.UV1 = true;
+                    }
+                    if (mesh.isVerticesDataPresent(VertexBuffer.UV2Kind)) {
+                        this._defines.UV2 = true;
+                    }
+                }
+                if (mesh.useVertexColors && mesh.isVerticesDataPresent(VertexBuffer.ColorKind)) {
+                    this._defines.VERTEXCOLOR = true;
+
+                    if (mesh.hasVertexAlpha) {
+                        this._defines.VERTEXALPHA = true;
+                    }
+                }
+                if (mesh.useBones && mesh.computeBonesUsingShaders) {
+                    this._defines.NUM_BONE_INFLUENCERS = mesh.numBoneInfluencers;
+                    this._defines.BonesPerMesh = (mesh.skeleton.bones.length + 1);
+                }
+
+                // Instances
+                if (useInstances) {
+                    this._defines.INSTANCES = true;
+                }
+            }
+
+            // Get correct effect      
+            if (!this._defines.isEqual(this._cachedDefines)) {
+                this._defines.cloneTo(this._cachedDefines);
+
+                scene.resetCachedMaterial();
+
+                // Fallbacks
+                var fallbacks = new EffectFallbacks();
+                if (this._defines.REFLECTION) {
+                    fallbacks.addFallback(0, "REFLECTION");
+                }
+
+                if (this._defines.SPECULAR) {
+                    fallbacks.addFallback(0, "SPECULAR");
+                }
+
+                if (this._defines.BUMP) {
+                    fallbacks.addFallback(0, "BUMP");
+                }
+
+                if (this._defines.PARALLAX) {
+                    fallbacks.addFallback(1, "PARALLAX");
+                }
+
+                if (this._defines.PARALLAXOCCLUSION) {
+                    fallbacks.addFallback(0, "PARALLAXOCCLUSION");
+                }
+
+                if (this._defines.SPECULAROVERALPHA) {
+                    fallbacks.addFallback(0, "SPECULAROVERALPHA");
+                }
+
+                if (this._defines.FOG) {
+                    fallbacks.addFallback(1, "FOG");
+                }
+
+                if (this._defines.POINTSIZE) {
+                    fallbacks.addFallback(0, "POINTSIZE");
+                }
+
+                if (this._defines.LOGARITHMICDEPTH) {
+                    fallbacks.addFallback(0, "LOGARITHMICDEPTH");
+                }
+
+                MaterialHelper.HandleFallbacksForShadows(this._defines, fallbacks, this.maxSimultaneousLights);
+
+                if (this._defines.SPECULARTERM) {
+                    fallbacks.addFallback(0, "SPECULARTERM");
+                }
+
+                if (this._defines.DIFFUSEFRESNEL) {
+                    fallbacks.addFallback(1, "DIFFUSEFRESNEL");
+                }
+
+                if (this._defines.OPACITYFRESNEL) {
+                    fallbacks.addFallback(2, "OPACITYFRESNEL");
+                }
+
+                if (this._defines.REFLECTIONFRESNEL) {
+                    fallbacks.addFallback(3, "REFLECTIONFRESNEL");
+                }
+
+                if (this._defines.EMISSIVEFRESNEL) {
+                    fallbacks.addFallback(4, "EMISSIVEFRESNEL");
+                }
+
+                if (this._defines.FRESNEL) {
+                    fallbacks.addFallback(4, "FRESNEL");
+                }
+
+                //Attributes
+                var attribs = [VertexBuffer.PositionKind];
+
+                if (this._defines.NORMAL) {
+                    attribs.push(VertexBuffer.NormalKind);
+                }
+
+                if (this._defines.UV1) {
+                    attribs.push(VertexBuffer.UVKind);
+                }
+
+                if (this._defines.UV2) {
+                    attribs.push(VertexBuffer.UV2Kind);
+                }
+
+                if (this._defines.VERTEXCOLOR) {
+                    attribs.push(VertexBuffer.ColorKind);
+                }
+
+                MaterialHelper.PrepareAttributesForBones(attribs, mesh, this._defines, fallbacks);
+                MaterialHelper.PrepareAttributesForInstances(attribs, this._defines);
+                
+                var shaderName = "default";
+               
+                if (this.builder) {
+ 
+                     shaderName = this.builder(
+                         new CustomShaderHelper(),
+                         shaderName, 
+                         this._mainPart,
+                         this._diffusePart, 
+                         this._vertexPositionPart ); 
+               }
+
+                var join = this._defines.toString();
+                var uniforms = ["world", "view", "viewProjection", "vEyePosition", "vLightsType", "vAmbientColor", "vDiffuseColor", "vSpecularColor", "vEmissiveColor",
+                    "vFogInfos", "vFogColor", "pointSize",
+                    "vDiffuseInfos", "vAmbientInfos", "vOpacityInfos", "vReflectionInfos", "vEmissiveInfos", "vSpecularInfos", "vBumpInfos", "vLightmapInfos", "vRefractionInfos",
+                    "mBones",
+                    "vClipPlane", "diffuseMatrix", "ambientMatrix", "opacityMatrix", "reflectionMatrix", "emissiveMatrix", "specularMatrix", "bumpMatrix", "lightmapMatrix", "refractionMatrix",
+                    "depthValues",
+                    "diffuseLeftColor", "diffuseRightColor", "opacityParts", "reflectionLeftColor", "reflectionRightColor", "emissiveLeftColor", "emissiveRightColor", "refractionLeftColor", "refractionRightColor",
+                    "logarithmicDepthConstant"
+                ];
+
+                var samplers = ["diffuseSampler", "ambientSampler", "opacitySampler", "reflectionCubeSampler", "reflection2DSampler", "emissiveSampler", "specularSampler", "bumpSampler", "lightmapSampler", "refractionCubeSampler", "refraction2DSampler"]
+
+                if (this._defines.CAMERACOLORCURVES) {
+                    ColorCurves.PrepareUniforms(uniforms);
+                }
+                if (this._defines.CAMERACOLORGRADING) {
+                    ColorGradingTexture.PrepareUniformsAndSamplers(uniforms, samplers);
+                }
+                MaterialHelper.PrepareUniformsAndSamplersList(uniforms, samplers, this._defines, this.maxSimultaneousLights);
+
+                this._effect = scene.getEngine().createEffect(shaderName,
+                    attribs, uniforms, samplers,
+                    join, fallbacks, this.onCompiled, this.onError, { maxSimultaneousLights: this.maxSimultaneousLights - 1 });
+            }
+            if (!this._effect.isReady()) {
+                return false;
+            }
+
+            this._renderId = scene.getRenderId();
+            this._wasPreviouslyReady = true;
+
+            if (mesh) {
+                if (!mesh._materialDefines) {
+                    mesh._materialDefines = new StandardMaterialDefines();
+                }
+
+                this._defines.cloneTo(mesh._materialDefines);
+            }
+
+            return true;
+        }
+    
+    }
+}
+     

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

@@ -34,10 +34,10 @@ module BABYLON {
         public SHADOW2 = false;
         public SHADOW2 = false;
         public SHADOW3 = false;
         public SHADOW3 = false;
         public SHADOWS = false;
         public SHADOWS = false;
-        public SHADOWVSM0 = false;
-        public SHADOWVSM1 = false;
-        public SHADOWVSM2 = false;
-        public SHADOWVSM3 = false;
+        public SHADOWESM0 = false;
+        public SHADOWESM1 = false;
+        public SHADOWESM2 = false;
+        public SHADOWESM3 = false;
         public SHADOWPCF0 = false;
         public SHADOWPCF0 = false;
         public SHADOWPCF1 = false;
         public SHADOWPCF1 = false;
         public SHADOWPCF2 = false;
         public SHADOWPCF2 = false;

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

@@ -32,10 +32,10 @@ module BABYLON {
         public SHADOW2 = false;
         public SHADOW2 = false;
         public SHADOW3 = false;
         public SHADOW3 = false;
         public SHADOWS = false;
         public SHADOWS = false;
-        public SHADOWVSM0 = false;
-        public SHADOWVSM1 = false;
-        public SHADOWVSM2 = false;
-        public SHADOWVSM3 = false;
+        public SHADOWESM0 = false;
+        public SHADOWESM1 = false;
+        public SHADOWESM2 = false;
+        public SHADOWESM3 = false;
         public SHADOWPCF0 = false;
         public SHADOWPCF0 = false;
         public SHADOWPCF1 = false;
         public SHADOWPCF1 = false;
         public SHADOWPCF2 = false;
         public SHADOWPCF2 = false;

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

@@ -32,10 +32,10 @@ module BABYLON {
         public SHADOW2 = false;
         public SHADOW2 = false;
         public SHADOW3 = false;
         public SHADOW3 = false;
         public SHADOWS = false;
         public SHADOWS = false;
-        public SHADOWVSM0 = false;
-        public SHADOWVSM1 = false;
-        public SHADOWVSM2 = false;
-        public SHADOWVSM3 = false;
+        public SHADOWESM0 = false;
+        public SHADOWESM1 = false;
+        public SHADOWESM2 = false;
+        public SHADOWESM3 = false;
         public SHADOWPCF0 = false;
         public SHADOWPCF0 = false;
         public SHADOWPCF1 = false;
         public SHADOWPCF1 = false;
         public SHADOWPCF2 = false;
         public SHADOWPCF2 = false;

+ 33 - 23
src/Bones/babylon.boneIKController.ts

@@ -1,6 +1,10 @@
 module BABYLON {
 module BABYLON {
     export class BoneIKController {
     export class BoneIKController {
 
 
+        private static _tmpVecs: Vector3[] = [Vector3.Zero(), Vector3.Zero(), Vector3.Zero(), Vector3.Zero(), Vector3.Zero(), Vector3.Zero()];
+        private static _tmpQuat = Quaternion.Identity();
+        private static _tmpMats: Matrix[] = [Matrix.Identity(), Matrix.Identity()];
+        
         public targetMesh: AbstractMesh;
         public targetMesh: AbstractMesh;
         public poleTargetMesh: AbstractMesh;
         public poleTargetMesh: AbstractMesh;
         public poleTargetBone: Bone;
         public poleTargetBone: Bone;
@@ -22,15 +26,6 @@ module BABYLON {
         private _maxAngle = Math.PI;
         private _maxAngle = Math.PI;
         private _maxReach: number;
         private _maxReach: number;
 
 
-        private _tmpVec1 = Vector3.Zero();
-        private _tmpVec2 = Vector3.Zero();
-        private _tmpVec3 = Vector3.Zero();
-        private _tmpVec4 = Vector3.Zero();
-        private _tmpVec5 = Vector3.Zero();
-        private _tmpMat1 = Matrix.Identity();
-        private _tmpMat2 = Matrix.Identity();
-        private _tmpQuat1 = Quaternion.Identity();
-
         private _rightHandedSystem = false;
         private _rightHandedSystem = false;
 
 
         private _bendAxis = Vector3.Right();
         private _bendAxis = Vector3.Right();
@@ -50,7 +45,18 @@ module BABYLON {
 
 
         }
         }
 
 
-        constructor(mesh: AbstractMesh, bone: Bone, options?: { targetMesh?: AbstractMesh, poleTargetMesh?: AbstractMesh, poleTargetBone?: Bone, poleTargetLocalOffset?:Vector3, poleAngle?: number, bendAxis?: Vector3, maxAngle?:number, slerpAmount?:number }){
+        constructor(mesh: AbstractMesh, 
+                    bone: Bone, 
+                    options?: { 
+                        targetMesh?: AbstractMesh, 
+                        poleTargetMesh?: AbstractMesh, 
+                        poleTargetBone?: Bone, 
+                        poleTargetLocalOffset?:Vector3, 
+                        poleAngle?: number, 
+                        bendAxis?: Vector3, 
+                        maxAngle?:number, 
+                        slerpAmount?:number 
+                    }){
 
 
             this._bone2 = bone;
             this._bone2 = bone;
             this._bone1 = bone.getParent();
             this._bone1 = bone.getParent();
@@ -160,14 +166,14 @@ module BABYLON {
 
 
         }
         }
 
 
-        public update (): void {
+        public update(): void {
 	
 	
             var bone1 = this._bone1;
             var bone1 = this._bone1;
             var target = this.targetPosition;
             var target = this.targetPosition;
             var poleTarget = this.poleTargetPosition;
             var poleTarget = this.poleTargetPosition;
 
 
-            var mat1 = this._tmpMat1;
-            var mat2 = this._tmpMat2;
+            var mat1 = BoneIKController._tmpMats[0];
+            var mat2 = BoneIKController._tmpMats[1];
 
 
             if(this.targetMesh){
             if(this.targetMesh){
                 target.copyFrom(this.targetMesh.getAbsolutePosition());
                 target.copyFrom(this.targetMesh.getAbsolutePosition());
@@ -179,11 +185,13 @@ module BABYLON {
                 Vector3.TransformCoordinatesToRef(this.poleTargetLocalOffset, this.poleTargetMesh.getWorldMatrix(), poleTarget);
                 Vector3.TransformCoordinatesToRef(this.poleTargetLocalOffset, this.poleTargetMesh.getWorldMatrix(), poleTarget);
             }
             }
 
 
-            var bonePos = this._tmpVec1;
-            var zaxis = this._tmpVec2;
-            var xaxis = this._tmpVec3;
-            var yaxis = this._tmpVec4;
-            var upAxis = this._tmpVec5;
+            var bonePos = BoneIKController._tmpVecs[0];
+            var zaxis = BoneIKController._tmpVecs[1];
+            var xaxis = BoneIKController._tmpVecs[2];
+            var yaxis = BoneIKController._tmpVecs[3];
+            var upAxis = BoneIKController._tmpVecs[4];
+
+            var _tmpQuat = BoneIKController._tmpQuat;
             
             
             bone1.getAbsolutePositionToRef(this.mesh, bonePos);
             bone1.getAbsolutePositionToRef(this.mesh, bonePos);
 
 
@@ -249,10 +257,12 @@ module BABYLON {
 
 
             } else {
             } else {
 
 
-                this._tmpVec1.copyFrom(this._bendAxis);
-                this._tmpVec1.x *= -1;
+                var _tmpVec = BoneIKController._tmpVecs[5];
+
+                _tmpVec.copyFrom(this._bendAxis);
+                _tmpVec.x *= -1;
 
 
-                Matrix.RotationAxisToRef(this._tmpVec1, -angB, mat2);
+                Matrix.RotationAxisToRef(_tmpVec, -angB, mat2);
                 mat2.multiplyToRef(mat1, mat1);
                 mat2.multiplyToRef(mat1, mat1);
                 
                 
             }
             }
@@ -266,8 +276,8 @@ module BABYLON {
                 if(!this._slerping){
                 if(!this._slerping){
                     Quaternion.FromRotationMatrixToRef(this._bone1Mat, this._bone1Quat);
                     Quaternion.FromRotationMatrixToRef(this._bone1Mat, this._bone1Quat);
                 }
                 }
-                Quaternion.FromRotationMatrixToRef(mat1, this._tmpQuat1);
-                Quaternion.SlerpToRef(this._bone1Quat, this._tmpQuat1, this.slerpAmount, this._bone1Quat);
+                Quaternion.FromRotationMatrixToRef(mat1, _tmpQuat);
+                Quaternion.SlerpToRef(this._bone1Quat, _tmpQuat, this.slerpAmount, this._bone1Quat);
                 angC = this._bone2Ang * (1.0 - this.slerpAmount) + angC * this.slerpAmount;
                 angC = this._bone2Ang * (1.0 - this.slerpAmount) + angC * this.slerpAmount;
                 this._bone1.setRotationQuaternion(this._bone1Quat, Space.WORLD, this.mesh);
                 this._bone1.setRotationQuaternion(this._bone1Quat, Space.WORLD, this.mesh);
                 this._slerping = true;
                 this._slerping = true;

+ 1 - 1
src/Cameras/Inputs/babylon.freecamera.input.gamepad.ts

@@ -29,7 +29,7 @@ module BABYLON {
         }
         }
 
 
         checkInputs() {
         checkInputs() {
-            if (this.gamepad) {
+            if (this.gamepad && this.gamepad.leftStick) {
                 var camera = this.camera;
                 var camera = this.camera;
                 var LSValues = this.gamepad.leftStick;
                 var LSValues = this.gamepad.leftStick;
                 var normalizedLX = LSValues.x / this.gamepadMoveSensibility;
                 var normalizedLX = LSValues.x / this.gamepadMoveSensibility;

+ 94 - 34
src/Cameras/VR/babylon.webVRCamera.ts

@@ -31,9 +31,11 @@ module BABYLON {
     }
     }
 
 
     export interface WebVROptions {
     export interface WebVROptions {
-        trackPosition?: boolean; //update the camera's position
+        trackPosition?: boolean; //for the sake of your users - set it to true.
         positionScale?: number;
         positionScale?: number;
         displayName?: string; //if there are more than one VRDisplays.
         displayName?: string; //if there are more than one VRDisplays.
+        controllerMeshes?: boolean; // should the native controller meshes be initialized
+        defaultLightningOnControllers?: boolean; // creating a default HemiLight only on controllers
     }
     }
 
 
     export class WebVRFreeCamera extends FreeCamera implements PoseControlled {
     export class WebVRFreeCamera extends FreeCamera implements PoseControlled {
@@ -51,6 +53,8 @@ module BABYLON {
 
 
         private _positionOffset: Vector3 = Vector3.Zero();
         private _positionOffset: Vector3 = Vector3.Zero();
 
 
+        protected _descendants: Array<Node> = [];
+
         public devicePosition = Vector3.Zero();
         public devicePosition = Vector3.Zero();
         public deviceRotationQuaternion;
         public deviceRotationQuaternion;
         public deviceScaleFactor: number = 1;
         public deviceScaleFactor: number = 1;
@@ -58,9 +62,29 @@ module BABYLON {
         public controllers: Array<WebVRController> = [];
         public controllers: Array<WebVRController> = [];
         public onControllersAttached: (controllers: Array<WebVRController>) => void;
         public onControllersAttached: (controllers: Array<WebVRController>) => void;
 
 
-        constructor(name: string, position: Vector3, scene: Scene, compensateDistortion = false, private webVROptions: WebVROptions = {}) {
+        public rigParenting: boolean = true; // should the rig cameras be used as parent instead of this camera.
+
+        private _lightOnControllers: BABYLON.HemisphericLight;
+
+        constructor(name: string, position: Vector3, scene: Scene, private webVROptions: WebVROptions = {}) {
             super(name, position, scene);
             super(name, position, scene);
 
 
+            //legacy support - the compensation boolean was removed.
+            if (arguments.length === 5) {
+                this.webVROptions = arguments[4];
+            }
+
+            // default webVR options
+            if (this.webVROptions.trackPosition == undefined) {
+                this.webVROptions.trackPosition = true;
+            }
+            if (this.webVROptions.controllerMeshes == undefined) {
+                this.webVROptions.controllerMeshes = true;
+            }
+            if (this.webVROptions.defaultLightningOnControllers == undefined) {
+                this.webVROptions.defaultLightningOnControllers = true;
+            }
+
             this.rotationQuaternion = new Quaternion();
             this.rotationQuaternion = new Quaternion();
             this.deviceRotationQuaternion = new Quaternion();
             this.deviceRotationQuaternion = new Quaternion();
 
 
@@ -110,6 +134,39 @@ module BABYLON {
 
 
             // try to attach the controllers, if found.
             // try to attach the controllers, if found.
             this.initControllers();
             this.initControllers();
+
+            /**
+             * The idea behind the following lines:
+             * objects that have the camera as parent should actually have the rig cameras as a parent.
+             * BUT, each of those cameras has a different view matrix, which means that if we set the parent to the first rig camera,
+             * the second will not show it correctly.
+             * 
+             * To solve this - each object that has the camera as parent will be added to a protected array.
+             * When the rig camera renders, it will take this array and set all of those to be its children.
+             * This way, the right camera will be used as a parent, and the mesh will be rendered correctly.
+             * Amazing!
+             */
+            scene.onBeforeCameraRenderObservable.add((camera) => {
+                if (camera.parent === this && this.rigParenting) {
+                    this._descendants = this.getDescendants(true, (n) => {
+                        // don't take the cameras or the controllers!
+                        let isController = this.controllers.some(controller => { return controller._mesh === n });
+                        let isRigCamera = this._rigCameras.indexOf(<Camera>n) !== -1
+                        return !isController && !isRigCamera;
+                    });
+                    this._descendants.forEach(node => {
+                        node.parent = camera;
+                    });
+                }
+            });
+
+            scene.onAfterCameraRenderObservable.add((camera) => {
+                if (camera.parent === this && this.rigParenting) {
+                    this._descendants.forEach(node => {
+                        node.parent = this;
+                    });
+                }
+            });
         }
         }
 
 
         public _checkInputs(): void {
         public _checkInputs(): void {
@@ -179,6 +236,16 @@ module BABYLON {
             this._vrDevice.resetPose();
             this._vrDevice.resetPose();
         }
         }
 
 
+        public _updateRigCameras() {
+            var camLeft = <TargetCamera>this._rigCameras[0];
+            var camRight = <TargetCamera>this._rigCameras[1];
+            camLeft.rotationQuaternion.copyFrom(this.deviceRotationQuaternion);
+            camRight.rotationQuaternion.copyFrom(this.deviceRotationQuaternion);
+
+            camLeft.position.copyFrom(this.devicePosition);
+            camRight.position.copyFrom(this.devicePosition);
+        }
+
         /**
         /**
          * This function is called by the two RIG cameras.
          * This function is called by the two RIG cameras.
          * 'this' is the left or right camera (and NOT (!!!) the WebVRFreeCamera instance)
          * 'this' is the left or right camera (and NOT (!!!) the WebVRFreeCamera instance)
@@ -186,17 +253,18 @@ module BABYLON {
         protected _getWebVRViewMatrix(): Matrix {
         protected _getWebVRViewMatrix(): Matrix {
             var viewArray = this._cameraRigParams["left"] ? this._cameraRigParams["frameData"].leftViewMatrix : this._cameraRigParams["frameData"].rightViewMatrix;
             var viewArray = this._cameraRigParams["left"] ? this._cameraRigParams["frameData"].leftViewMatrix : this._cameraRigParams["frameData"].rightViewMatrix;
 
 
+            Matrix.FromArrayToRef(viewArray, 0, this._webvrViewMatrix);
+
             if (!this.getScene().useRightHandedSystem) {
             if (!this.getScene().useRightHandedSystem) {
-                [2, 6, 8, 9, 14].forEach(function (num) {
-                    viewArray[num] *= -1;
+                [2, 6, 8, 9, 14].forEach((num) => {
+                    this._webvrViewMatrix.m[num] *= -1;
                 });
                 });
             }
             }
-            Matrix.FromArrayToRef(viewArray, 0, this._webvrViewMatrix);
 
 
             let parentCamera: WebVRFreeCamera = this._cameraRigParams["parentCamera"];
             let parentCamera: WebVRFreeCamera = this._cameraRigParams["parentCamera"];
 
 
             // should the view matrix be updated with scale and position offset?
             // should the view matrix be updated with scale and position offset?
-            if (parentCamera.position.lengthSquared() || parentCamera.deviceScaleFactor !== 1) {
+            if (parentCamera.deviceScaleFactor !== 1) {
                 this._webvrViewMatrix.invert();
                 this._webvrViewMatrix.invert();
                 // scale the position, if set
                 // scale the position, if set
                 if (parentCamera.deviceScaleFactor) {
                 if (parentCamera.deviceScaleFactor) {
@@ -204,49 +272,29 @@ module BABYLON {
                     this._webvrViewMatrix.m[13] *= parentCamera.deviceScaleFactor;
                     this._webvrViewMatrix.m[13] *= parentCamera.deviceScaleFactor;
                     this._webvrViewMatrix.m[14] *= parentCamera.deviceScaleFactor;
                     this._webvrViewMatrix.m[14] *= parentCamera.deviceScaleFactor;
                 }
                 }
-                // change the position (for "teleporting");
-                this._webvrViewMatrix.m[12] += parentCamera.position.x;
-                this._webvrViewMatrix.m[13] += parentCamera.position.y;
-                this._webvrViewMatrix.m[14] += parentCamera.position.z;
-
-                // is rotation offset set? 
-                if (!Quaternion.IsIdentity(this.rotationQuaternion)) {
-                    this._webvrViewMatrix.decompose(Tmp.Vector3[0], Tmp.Quaternion[0], Tmp.Vector3[1]);
-                    this.rotationQuaternion.multiplyToRef(Tmp.Quaternion[0], Tmp.Quaternion[0]);
-                    Matrix.ComposeToRef(Tmp.Vector3[0], Tmp.Quaternion[0], Tmp.Vector3[1], this._webvrViewMatrix);
-                }
 
 
                 this._webvrViewMatrix.invert();
                 this._webvrViewMatrix.invert();
             }
             }
 
 
-            this._updateCameraRotationMatrix();
+            // update the camera rotation matrix
+            this._webvrViewMatrix.getRotationMatrixToRef(this._cameraRotationMatrix);
             Vector3.TransformCoordinatesToRef(this._referencePoint, this._cameraRotationMatrix, this._transformedReferencePoint);
             Vector3.TransformCoordinatesToRef(this._referencePoint, this._cameraRotationMatrix, this._transformedReferencePoint);
 
 
-            // Computing target for getTarget()
-            this._positionOffset = this._positionOffset || Vector3.Zero();
-            this._webvrViewMatrix.getTranslationToRef(this._positionOffset);
-            this._positionOffset.addToRef(this._transformedReferencePoint, this._currentTarget);
-
+            // Computing target and final matrix
+            this.position.addToRef(this._transformedReferencePoint, this._currentTarget);
             return this._webvrViewMatrix;
             return this._webvrViewMatrix;
         }
         }
 
 
-        public _updateWebVRCameraRotationMatrix() {
-            this._webvrViewMatrix.getRotationMatrixToRef(this._cameraRotationMatrix);
-        }
-
-        public _isSynchronizedViewMatrix() {
-            return false;
-        }
-
         protected _getWebVRProjectionMatrix(): Matrix {
         protected _getWebVRProjectionMatrix(): Matrix {
             var projectionArray = this._cameraRigParams["left"] ? this._cameraRigParams["frameData"].leftProjectionMatrix : this._cameraRigParams["frameData"].rightProjectionMatrix;
             var projectionArray = this._cameraRigParams["left"] ? this._cameraRigParams["frameData"].leftProjectionMatrix : this._cameraRigParams["frameData"].rightProjectionMatrix;
+            Matrix.FromArrayToRef(projectionArray, 0, this._projectionMatrix);
+
             //babylon compatible matrix
             //babylon compatible matrix
             if (!this.getScene().useRightHandedSystem) {
             if (!this.getScene().useRightHandedSystem) {
-                [8, 9, 10, 11].forEach(function (num) {
-                    projectionArray[num] *= -1;
+                [8, 9, 10, 11].forEach((num) => {
+                    this._projectionMatrix.m[num] *= -1;
                 });
                 });
             }
             }
-            Matrix.FromArrayToRef(projectionArray, 0, this._projectionMatrix);
             return this._projectionMatrix;
             return this._projectionMatrix;
         }
         }
 
 
@@ -255,6 +303,18 @@ module BABYLON {
             new BABYLON.Gamepads((gp) => {
             new BABYLON.Gamepads((gp) => {
                 if (gp.type === BABYLON.Gamepad.POSE_ENABLED) {
                 if (gp.type === BABYLON.Gamepad.POSE_ENABLED) {
                     let webVrController: WebVRController = <WebVRController>gp;
                     let webVrController: WebVRController = <WebVRController>gp;
+                    if (this.webVROptions.controllerMeshes) {
+                        webVrController.initControllerMesh(this.getScene(), (loadedMesh) => {
+                            if (this.webVROptions.defaultLightningOnControllers) {
+                                if (!this._lightOnControllers) {
+                                    this._lightOnControllers = new BABYLON.HemisphericLight("vrControllersLight", new BABYLON.Vector3(0, 1, 0), this.getScene());
+                                }
+                                loadedMesh.getChildren().forEach((mesh) => {
+                                    this._lightOnControllers.includedOnlyMeshes.push(<AbstractMesh>mesh);
+                                });
+                            }
+                        });
+                    }
                     webVrController.attachToPoseControlledCamera(this);
                     webVrController.attachToPoseControlledCamera(this);
 
 
                     // since this is async - sanity check. Is the controller already stored?
                     // since this is async - sanity check. Is the controller already stored?

+ 1 - 1
src/Cameras/babylon.arcRotateCamera.ts

@@ -415,7 +415,7 @@ module BABYLON {
             }
             }
             
             
             if (toBoundingCenter && (<any>target).getBoundingInfo){
             if (toBoundingCenter && (<any>target).getBoundingInfo){
-                this._targetBoundingCenter = (<any>target).getBoundingInfo().boundingBox.center.clone();
+                this._targetBoundingCenter = (<any>target).getBoundingInfo().boundingBox.centerWorld.clone();
             }else{
             }else{
                 this._targetBoundingCenter = null;
                 this._targetBoundingCenter = null;
             }
             }

+ 2 - 4
src/Cameras/babylon.camera.ts

@@ -618,9 +618,8 @@
                         this._rigCameras[0].setCameraRigParameter("parentCamera", rigParams.parentCamera);
                         this._rigCameras[0].setCameraRigParameter("parentCamera", rigParams.parentCamera);
                         this._rigCameras[0]._cameraRigParams.vrWorkMatrix = new Matrix();
                         this._rigCameras[0]._cameraRigParams.vrWorkMatrix = new Matrix();
                         this._rigCameras[0].getProjectionMatrix = this._getWebVRProjectionMatrix;
                         this._rigCameras[0].getProjectionMatrix = this._getWebVRProjectionMatrix;
+                        this._rigCameras[0].parent = this;
                         this._rigCameras[0]._getViewMatrix = this._getWebVRViewMatrix;
                         this._rigCameras[0]._getViewMatrix = this._getWebVRViewMatrix;
-                        this._rigCameras[0]._isSynchronizedViewMatrix = this._isSynchronizedViewMatrix;
-                        this._rigCameras[0]._updateCameraRotationMatrix = this._updateWebVRCameraRotationMatrix;
 
 
                         //Right eye
                         //Right eye
                         this._rigCameras[1].viewport = new Viewport(0.5, 0, 0.5, 1.0);
                         this._rigCameras[1].viewport = new Viewport(0.5, 0, 0.5, 1.0);
@@ -629,9 +628,8 @@
                         this._rigCameras[1].setCameraRigParameter("parentCamera", rigParams.parentCamera);
                         this._rigCameras[1].setCameraRigParameter("parentCamera", rigParams.parentCamera);
                         this._rigCameras[1]._cameraRigParams.vrWorkMatrix = new Matrix();
                         this._rigCameras[1]._cameraRigParams.vrWorkMatrix = new Matrix();
                         this._rigCameras[1].getProjectionMatrix = this._getWebVRProjectionMatrix;
                         this._rigCameras[1].getProjectionMatrix = this._getWebVRProjectionMatrix;
+                        this._rigCameras[1].parent = this;
                         this._rigCameras[1]._getViewMatrix = this._getWebVRViewMatrix;
                         this._rigCameras[1]._getViewMatrix = this._getWebVRViewMatrix;
-                        this._rigCameras[1]._isSynchronizedViewMatrix = this._isSynchronizedViewMatrix;
-                        this._rigCameras[1]._updateCameraRotationMatrix = this._updateWebVRCameraRotationMatrix;
                     }
                     }
                     break;
                     break;
 
 

+ 1 - 2
src/Cameras/babylon.targetCamera.ts

@@ -179,7 +179,7 @@ module BABYLON {
 
 
                 //rotate, if quaternion is set and rotation was used
                 //rotate, if quaternion is set and rotation was used
                 if (this.rotationQuaternion) {
                 if (this.rotationQuaternion) {
-                    var len = this.rotation.length();
+                    var len = this.rotation.lengthSquared();
                     if (len) {
                     if (len) {
                         Quaternion.RotationYawPitchRollToRef(this.rotation.y, this.rotation.x, this.rotation.z, this.rotationQuaternion);
                         Quaternion.RotationYawPitchRollToRef(this.rotation.y, this.rotation.x, this.rotation.z, this.rotationQuaternion);
                     }
                     }
@@ -302,7 +302,6 @@ module BABYLON {
                     break;
                     break;
 
 
                 case Camera.RIG_MODE_VR:
                 case Camera.RIG_MODE_VR:
-                case Camera.RIG_MODE_WEBVR:
                     if (camLeft.rotationQuaternion) {
                     if (camLeft.rotationQuaternion) {
                         camLeft.rotationQuaternion.copyFrom(this.rotationQuaternion);
                         camLeft.rotationQuaternion.copyFrom(this.rotationQuaternion);
                         camRight.rotationQuaternion.copyFrom(this.rotationQuaternion);
                         camRight.rotationQuaternion.copyFrom(this.rotationQuaternion);

+ 11 - 2
src/Culling/babylon.boundingBox.ts

@@ -2,12 +2,15 @@
     export class BoundingBox implements ICullable {
     export class BoundingBox implements ICullable {
         public vectors: Vector3[] = new Array<Vector3>();
         public vectors: Vector3[] = new Array<Vector3>();
         public center: Vector3;
         public center: Vector3;
+        public centerWorld: Vector3;
         public extendSize: Vector3;
         public extendSize: Vector3;
+        public extendSizeWorld: Vector3;
         public directions: Vector3[];
         public directions: Vector3[];
         public vectorsWorld: Vector3[] = new Array<Vector3>();
         public vectorsWorld: Vector3[] = new Array<Vector3>();
         public minimumWorld: Vector3;
         public minimumWorld: Vector3;
         public maximumWorld: Vector3;
         public maximumWorld: Vector3;
 
 
+
         private _worldMatrix: Matrix;
         private _worldMatrix: Matrix;
 
 
         constructor(public minimum: Vector3, public maximum: Vector3) {
         constructor(public minimum: Vector3, public maximum: Vector3) {
@@ -44,6 +47,8 @@
             }
             }
             this.minimumWorld = Vector3.Zero();
             this.minimumWorld = Vector3.Zero();
             this.maximumWorld = Vector3.Zero();
             this.maximumWorld = Vector3.Zero();
+            this.centerWorld = Vector3.Zero();
+            this.extendSizeWorld = Vector3.Zero();
 
 
             this._update(Matrix.Identity());
             this._update(Matrix.Identity());
         }
         }
@@ -81,9 +86,13 @@
                     this.maximumWorld.z = v.z;
                     this.maximumWorld.z = v.z;
             }
             }
 
 
+            // Extend
+            this.maximumWorld.subtractToRef(this.minimumWorld, this.extendSizeWorld);
+            this.extendSizeWorld.scaleInPlace(0.5);
+
             // OBB
             // OBB
-            this.maximumWorld.addToRef(this.minimumWorld, this.center);
-            this.center.scaleInPlace(0.5);
+            this.maximumWorld.addToRef(this.minimumWorld, this.centerWorld);
+            this.centerWorld.scaleInPlace(0.5);
 
 
             Vector3.FromFloatArrayToRef(world.m, 0, this.directions[0]);
             Vector3.FromFloatArrayToRef(world.m, 0, this.directions[0]);
             Vector3.FromFloatArrayToRef(world.m, 4, this.directions[1]);
             Vector3.FromFloatArrayToRef(world.m, 4, this.directions[1]);

+ 1 - 1
src/Culling/babylon.boundingInfo.ts

@@ -1,6 +1,6 @@
 module BABYLON {
 module BABYLON {
     var computeBoxExtents = (axis: Vector3, box: BoundingBox) => {
     var computeBoxExtents = (axis: Vector3, box: BoundingBox) => {
-        var p = Vector3.Dot(box.center, axis);
+        var p = Vector3.Dot(box.centerWorld, axis);
 
 
         var r0 = Math.abs(Vector3.Dot(box.directions[0], axis)) * box.extendSize.x;
         var r0 = Math.abs(Vector3.Dot(box.directions[0], axis)) * box.extendSize.x;
         var r1 = Math.abs(Vector3.Dot(box.directions[1], axis)) * box.extendSize.y;
         var r1 = Math.abs(Vector3.Dot(box.directions[1], axis)) * box.extendSize.y;

+ 8 - 0
src/Culling/babylon.rayHelper.ts

@@ -13,6 +13,14 @@ module BABYLON {
         private _meshSpaceDirection: Vector3;
         private _meshSpaceDirection: Vector3;
         private _meshSpaceOrigin: Vector3;
         private _meshSpaceOrigin: Vector3;
 
 
+        public static CreateAndShow(ray: Ray, scene: Scene, color:Color3): RayHelper {
+            var helper = new RayHelper(ray);
+
+            helper.show(scene, color);
+
+            return helper;
+        }
+
         constructor(ray:Ray) {
         constructor(ray:Ray) {
             this.ray = ray;
             this.ray = ray;
         }
         }

+ 89 - 39
src/Lights/Shadows/babylon.shadowGenerator.ts

@@ -7,25 +7,25 @@
  
  
     export class ShadowGenerator implements IShadowGenerator {
     export class ShadowGenerator implements IShadowGenerator {
         private static _FILTER_NONE = 0;
         private static _FILTER_NONE = 0;
-        private static _FILTER_VARIANCESHADOWMAP = 1;
+        private static _FILTER_EXPONENTIALSHADOWMAP = 1;
         private static _FILTER_POISSONSAMPLING = 2;
         private static _FILTER_POISSONSAMPLING = 2;
-        private static _FILTER_BLURVARIANCESHADOWMAP = 3;
+        private static _FILTER_BLUREXPONENTIALSHADOWMAP = 3;
 
 
         // Static
         // Static
         public static get FILTER_NONE(): number {
         public static get FILTER_NONE(): number {
             return ShadowGenerator._FILTER_NONE;
             return ShadowGenerator._FILTER_NONE;
         }
         }
 
 
-        public static get FILTER_VARIANCESHADOWMAP(): number {
-            return ShadowGenerator._FILTER_VARIANCESHADOWMAP;
-        }
-
         public static get FILTER_POISSONSAMPLING(): number {
         public static get FILTER_POISSONSAMPLING(): number {
             return ShadowGenerator._FILTER_POISSONSAMPLING;
             return ShadowGenerator._FILTER_POISSONSAMPLING;
         }
         }
 
 
-        public static get FILTER_BLURVARIANCESHADOWMAP(): number {
-            return ShadowGenerator._FILTER_BLURVARIANCESHADOWMAP;
+        public static get FILTER_EXPONENTIALSHADOWMAP(): number {
+            return ShadowGenerator._FILTER_EXPONENTIALSHADOWMAP;
+        }
+
+        public static get FILTER_BLUREXPONENTIALSHADOWMAP(): number {
+            return ShadowGenerator._FILTER_BLUREXPONENTIALSHADOWMAP;
         }
         }
 
 
         // Members
         // Members
@@ -34,6 +34,7 @@
         private _blurBoxOffset = 0;
         private _blurBoxOffset = 0;
         private _bias = 0.00005;
         private _bias = 0.00005;
         private _lightDirection = Vector3.Zero();
         private _lightDirection = Vector3.Zero();
+        private _depthScale: number;
 
 
         public forceBackFacesOnly = false;
         public forceBackFacesOnly = false;
 
 
@@ -44,6 +45,7 @@
         public set bias(bias: number) {
         public set bias(bias: number) {
             this._bias = bias;
             this._bias = bias;
         }
         }
+
         public get blurBoxOffset(): number {
         public get blurBoxOffset(): number {
             return this._blurBoxOffset;
             return this._blurBoxOffset;
         }
         }
@@ -59,12 +61,29 @@
                 this._boxBlurPostprocess.dispose();
                 this._boxBlurPostprocess.dispose();
             }
             }
 
 
-            this._boxBlurPostprocess = new PostProcess("DepthBoxBlur", "depthBoxBlur", ["screenSize", "boxOffset"], [], 1.0 / this.blurScale, null, Texture.BILINEAR_SAMPLINGMODE, this._scene.getEngine(), false, "#define OFFSET " + value);
+            var textureType: number;
+            var caps = this._scene.getEngine().getCaps();
+            if (this._useFullFloat) {
+                textureType = Engine.TEXTURETYPE_FLOAT;
+            }
+            else {
+                textureType = Engine.TEXTURETYPE_UNSIGNED_INT;
+            }
+
+            this._boxBlurPostprocess = new PostProcess("DepthBoxBlur", "depthBoxBlur", ["screenSize", "boxOffset"], [], 1.0 / this.blurScale, null, Texture.BILINEAR_SAMPLINGMODE, this._scene.getEngine(), false, "#define OFFSET " + value, textureType);
             this._boxBlurPostprocess.onApplyObservable.add(effect => {
             this._boxBlurPostprocess.onApplyObservable.add(effect => {
                 effect.setFloat2("screenSize", this._mapSize / this.blurScale, this._mapSize / this.blurScale);
                 effect.setFloat2("screenSize", this._mapSize / this.blurScale, this._mapSize / this.blurScale);
             });
             });
         }
         }
 
 
+        public get depthScale(): number {
+            return this._depthScale !== undefined ? this._depthScale : this._light.getDepthScale();
+        }
+
+        public set depthScale(value: number) {
+            this._depthScale = value;
+        }
+
         public get filter(): number {
         public get filter(): number {
             return this._filter;
             return this._filter;
         }
         }
@@ -76,7 +95,7 @@
 
 
             this._filter = value;
             this._filter = value;
 
 
-            if (this.useVarianceShadowMap || this.useBlurVarianceShadowMap || this.usePoissonSampling) {
+            if (this.usePoissonSampling || this.useExponentialShadowMap || this.useBlurExponentialShadowMap) {
                 this._shadowMap.anisotropicFilteringLevel = 16;
                 this._shadowMap.anisotropicFilteringLevel = 16;
                 this._shadowMap.updateSamplingMode(Texture.BILINEAR_SAMPLINGMODE);
                 this._shadowMap.updateSamplingMode(Texture.BILINEAR_SAMPLINGMODE);
             } else {
             } else {
@@ -86,28 +105,47 @@
         }
         }
 
 
         public get useVarianceShadowMap(): boolean {
         public get useVarianceShadowMap(): boolean {
-            return this.filter === ShadowGenerator.FILTER_VARIANCESHADOWMAP && this._light.supportsVSM();
+            Tools.Warn("VSM are now replaced by ESM. Please use useExponentialShadowMap instead.");
+            return this.useExponentialShadowMap;
         }
         }
         public set useVarianceShadowMap(value: boolean) {
         public set useVarianceShadowMap(value: boolean) {
-            this.filter = (value ? ShadowGenerator.FILTER_VARIANCESHADOWMAP : ShadowGenerator.FILTER_NONE);
+            Tools.Warn("VSM are now replaced by ESM. Please use useExponentialShadowMap instead.");
+            this.useExponentialShadowMap = value;
+        }
+
+        public get useExponentialShadowMap(): boolean {
+            return this.filter === ShadowGenerator.FILTER_EXPONENTIALSHADOWMAP;
+        }
+        public set useExponentialShadowMap(value: boolean) {
+            this.filter = (value ? ShadowGenerator.FILTER_EXPONENTIALSHADOWMAP : ShadowGenerator.FILTER_NONE);
         }
         }
 
 
         public get usePoissonSampling(): boolean {
         public get usePoissonSampling(): boolean {
-            return this.filter === ShadowGenerator.FILTER_POISSONSAMPLING ||
-                (!this._light.supportsVSM() && (
-                    this.filter === ShadowGenerator.FILTER_VARIANCESHADOWMAP ||
-                    this.filter === ShadowGenerator.FILTER_BLURVARIANCESHADOWMAP
-                ));
+            return this.filter === ShadowGenerator.FILTER_POISSONSAMPLING;
         }
         }
+
         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);
         }
         }
 
 
         public get useBlurVarianceShadowMap(): boolean {
         public get useBlurVarianceShadowMap(): boolean {
-            return this.filter === ShadowGenerator.FILTER_BLURVARIANCESHADOWMAP && this._light.supportsVSM();
+            Tools.Warn("VSM are now replaced by ESM. Please use useBlurExponentialShadowMap instead.");
+            return this.useBlurExponentialShadowMap;
         }
         }
         public set useBlurVarianceShadowMap(value: boolean) {
         public set useBlurVarianceShadowMap(value: boolean) {
-            this.filter = (value ? ShadowGenerator.FILTER_BLURVARIANCESHADOWMAP : ShadowGenerator.FILTER_NONE);
+            Tools.Warn("VSM are now replaced by ESM. Please use useBlurExponentialShadowMap instead.");
+            this.useBlurExponentialShadowMap = value;
+        }
+
+        public get useBlurExponentialShadowMap(): boolean {
+            return this.filter === ShadowGenerator.FILTER_BLUREXPONENTIALSHADOWMAP;
+        }
+        public set useBlurExponentialShadowMap(value: boolean) {            
+            if (this._light.needCube() && value) {
+                this.useExponentialShadowMap = true; // Blurring the cubemap is going to be too expensive. Reverting to unblurred version
+            } else {
+                this.filter = (value ? ShadowGenerator.FILTER_BLUREXPONENTIALSHADOWMAP : ShadowGenerator.FILTER_NONE);
+            }
         }
         }
 
 
         private _light: IShadowLight;
         private _light: IShadowLight;
@@ -167,7 +205,7 @@
             this._shadowMap.wrapU = Texture.CLAMP_ADDRESSMODE;
             this._shadowMap.wrapU = Texture.CLAMP_ADDRESSMODE;
             this._shadowMap.wrapV = Texture.CLAMP_ADDRESSMODE;
             this._shadowMap.wrapV = Texture.CLAMP_ADDRESSMODE;
             this._shadowMap.anisotropicFilteringLevel = 1;
             this._shadowMap.anisotropicFilteringLevel = 1;
-            this._shadowMap.updateSamplingMode(Texture.NEAREST_SAMPLINGMODE);
+            this._shadowMap.updateSamplingMode(Texture.BILINEAR_SAMPLINGMODE);
             this._shadowMap.renderParticles = false;
             this._shadowMap.renderParticles = false;
 
 
             this._shadowMap.onBeforeRenderObservable.add((faceIndex: number) => {
             this._shadowMap.onBeforeRenderObservable.add((faceIndex: number) => {
@@ -175,7 +213,7 @@
             });
             });
 
 
             this._shadowMap.onAfterUnbindObservable.add(() => {
             this._shadowMap.onAfterUnbindObservable.add(() => {
-                if (!this.useBlurVarianceShadowMap) {
+                if (!this.useBlurExponentialShadowMap) {
                     return;
                     return;
                 }
                 }
 
 
@@ -183,9 +221,9 @@
                     this._shadowMap2 = new RenderTargetTexture(light.name + "_shadowMap", mapSize, this._scene, false, true, textureType);
                     this._shadowMap2 = new RenderTargetTexture(light.name + "_shadowMap", mapSize, this._scene, false, true, textureType);
                     this._shadowMap2.wrapU = Texture.CLAMP_ADDRESSMODE;
                     this._shadowMap2.wrapU = Texture.CLAMP_ADDRESSMODE;
                     this._shadowMap2.wrapV = Texture.CLAMP_ADDRESSMODE;
                     this._shadowMap2.wrapV = Texture.CLAMP_ADDRESSMODE;
-                    this._shadowMap2.updateSamplingMode(Texture.TRILINEAR_SAMPLINGMODE);
+                    this._shadowMap2.updateSamplingMode(Texture.BILINEAR_SAMPLINGMODE);
 
 
-                    this._downSamplePostprocess = new PassPostProcess("downScale", 1.0 / this.blurScale, null, Texture.BILINEAR_SAMPLINGMODE, this._scene.getEngine());
+                    this._downSamplePostprocess = new PassPostProcess("downScale", 1.0 / this.blurScale, null, Texture.BILINEAR_SAMPLINGMODE, this._scene.getEngine(), false, textureType);
                     this._downSamplePostprocess.onApplyObservable.add(effect => {
                     this._downSamplePostprocess.onApplyObservable.add(effect => {
                         effect.setTexture("textureSampler", this._shadowMap);
                         effect.setTexture("textureSampler", this._shadowMap);
                     });
                     });
@@ -219,6 +257,8 @@
                     mesh._bind(subMesh, this._effect, Material.TriangleFillMode);
                     mesh._bind(subMesh, this._effect, Material.TriangleFillMode);
                     var material = subMesh.getMaterial();
                     var material = subMesh.getMaterial();
 
 
+                    this._effect.setFloat2("biasAndScale", this.bias, this.depthScale);
+
                     this._effect.setMatrix("viewProjection", this.getTransformMatrix());
                     this._effect.setMatrix("viewProjection", this.getTransformMatrix());
                     this._effect.setVector3("lightPosition", this.getLight().position);
                     this._effect.setVector3("lightPosition", this.getLight().position);
 
 
@@ -274,7 +314,7 @@
             };
             };
 
 
             this._shadowMap.onClearObservable.add((engine: Engine) => {
             this._shadowMap.onClearObservable.add((engine: Engine) => {
-                if (this.useBlurVarianceShadowMap || this.useVarianceShadowMap) {
+                if (this.useExponentialShadowMap || this.useBlurExponentialShadowMap) {
                     engine.clear(new Color4(0, 0, 0, 0), true, true, true);
                     engine.clear(new Color4(0, 0, 0, 0), true, true, true);
                 } else {
                 } else {
                     engine.clear(new Color4(1.0, 1.0, 1.0, 1.0), true, true, true);
                     engine.clear(new Color4(1.0, 1.0, 1.0, 1.0), true, true, true);
@@ -291,8 +331,8 @@
                 defines.push("#define FULLFLOAT");
                 defines.push("#define FULLFLOAT");
             }
             }
 
 
-            if (this.useVarianceShadowMap || this.useBlurVarianceShadowMap) {
-                defines.push("#define VSM");
+            if (this.useExponentialShadowMap || this.useBlurExponentialShadowMap) {
+                defines.push("#define ESM");
             }
             }
 
 
             if (this.getLight().needCube()) {
             if (this.getLight().needCube()) {
@@ -350,7 +390,7 @@
                 this._cachedDefines = join;
                 this._cachedDefines = join;
                 this._effect = this._scene.getEngine().createEffect("shadowMap",
                 this._effect = this._scene.getEngine().createEffect("shadowMap",
                     attribs,
                     attribs,
-                    ["world", "mBones", "viewProjection", "diffuseMatrix", "lightPosition", "depthValues"],
+                    ["world", "mBones", "viewProjection", "diffuseMatrix", "lightPosition", "depthValues", "biasAndScale"],
                     ["diffuseSampler"], join);
                     ["diffuseSampler"], join);
             }
             }
 
 
@@ -481,7 +521,8 @@
 
 
             serializationObject.lightId = this._light.id;
             serializationObject.lightId = this._light.id;
             serializationObject.mapSize = this.getShadowMap().getRenderSize();
             serializationObject.mapSize = this.getShadowMap().getRenderSize();
-            serializationObject.useVarianceShadowMap = this.useVarianceShadowMap;
+            serializationObject.useExponentialShadowMap = this.useExponentialShadowMap;
+            serializationObject.useBlurExponentialShadowMap = this.useBlurExponentialShadowMap;
             serializationObject.usePoissonSampling = this.usePoissonSampling;
             serializationObject.usePoissonSampling = this.usePoissonSampling;
             serializationObject.forceBackFacesOnly = this.forceBackFacesOnly;
             serializationObject.forceBackFacesOnly = this.forceBackFacesOnly;
             serializationObject.darkness = this.getDarkness();
             serializationObject.darkness = this.getDarkness();
@@ -512,20 +553,29 @@
 
 
             if (parsedShadowGenerator.usePoissonSampling) {
             if (parsedShadowGenerator.usePoissonSampling) {
                 shadowGenerator.usePoissonSampling = true;
                 shadowGenerator.usePoissonSampling = true;
-            } else if (parsedShadowGenerator.useVarianceShadowMap) {
-                shadowGenerator.useVarianceShadowMap = true;
-            } else if (parsedShadowGenerator.useBlurVarianceShadowMap) {
-                shadowGenerator.useBlurVarianceShadowMap = true;
-
-                if (parsedShadowGenerator.blurScale) {
-                    shadowGenerator.blurScale = parsedShadowGenerator.blurScale;
-                }
+            }
+            else if (parsedShadowGenerator.useExponentialShadowMap) {
+                shadowGenerator.useExponentialShadowMap = true;
+            }
+            else if (parsedShadowGenerator.useBlurExponentialShadowMap) {
+                shadowGenerator.useBlurExponentialShadowMap = true;
+            }            
+            // Backward compat
+            else if (parsedShadowGenerator.useVarianceShadowMap) {
+                shadowGenerator.useExponentialShadowMap = true;
+            }
+            else if (parsedShadowGenerator.useBlurVarianceShadowMap) {
+                shadowGenerator.useBlurExponentialShadowMap = true;
+            }
 
 
-                if (parsedShadowGenerator.blurBoxOffset) {
-                    shadowGenerator.blurBoxOffset = parsedShadowGenerator.blurBoxOffset;
-                }
+            if (parsedShadowGenerator.blurScale) {
+                shadowGenerator.blurScale = parsedShadowGenerator.blurScale;
             }
             }
 
 
+            if (parsedShadowGenerator.blurBoxOffset) {
+                shadowGenerator.blurBoxOffset = parsedShadowGenerator.blurBoxOffset;
+            }
+                
             if (parsedShadowGenerator.bias !== undefined) {
             if (parsedShadowGenerator.bias !== undefined) {
                 shadowGenerator.bias = parsedShadowGenerator.bias;
                 shadowGenerator.bias = parsedShadowGenerator.bias;
             }
             }

+ 14 - 7
src/Lights/babylon.directionalLight.ts

@@ -17,6 +17,11 @@ module BABYLON {
 
 
         @serialize()
         @serialize()
         public autoUpdateExtends = true;
         public autoUpdateExtends = true;
+
+        @serialize()
+        public shadowMinZ: number;
+        @serialize()
+        public shadowMaxZ: number;
         
         
         public customProjectionMatrixBuilder: (viewMatrix: Matrix, renderList: Array<AbstractMesh>, result: Matrix) => void;
         public customProjectionMatrixBuilder: (viewMatrix: Matrix, renderList: Array<AbstractMesh>, result: Matrix) => void;
 
 
@@ -57,6 +62,14 @@ module BABYLON {
             this.direction = Vector3.Normalize(target.subtract(this.position));
             this.direction = Vector3.Normalize(target.subtract(this.position));
             return this.direction;
             return this.direction;
         }
         }
+
+        /**
+         * Return the depth scale used for the shadow map.
+         */
+        public getDepthScale(): number {
+            return 30.0;
+        }
+
         /**
         /**
          * Sets the passed matrix "matrix" as projection matrix for the shadows cast by the light according to the passed view matrix.  
          * Sets the passed matrix "matrix" as projection matrix for the shadows cast by the light according to the passed view matrix.  
          * Returns the DirectionalLight.  
          * Returns the DirectionalLight.  
@@ -112,7 +125,7 @@ module BABYLON {
 
 
                 Matrix.OrthoOffCenterLHToRef(this._orthoLeft - xOffset * this.shadowOrthoScale, this._orthoRight + xOffset * this.shadowOrthoScale,
                 Matrix.OrthoOffCenterLHToRef(this._orthoLeft - xOffset * this.shadowOrthoScale, this._orthoRight + xOffset * this.shadowOrthoScale,
                     this._orthoBottom - yOffset * this.shadowOrthoScale, this._orthoTop + yOffset * this.shadowOrthoScale,
                     this._orthoBottom - yOffset * this.shadowOrthoScale, this._orthoTop + yOffset * this.shadowOrthoScale,
-                    -activeCamera.maxZ, activeCamera.maxZ, matrix);
+                    this.shadowMinZ !== undefined ? this.shadowMinZ : activeCamera.minZ, this.shadowMaxZ !== undefined ? this.shadowMaxZ : activeCamera.maxZ, matrix);
             }
             }
             return this;
             return this;
         }
         }
@@ -120,12 +133,6 @@ module BABYLON {
         /**
         /**
          * Boolean : true by default.  
          * Boolean : true by default.  
          */
          */
-        public supportsVSM(): boolean {
-            return true;
-        }
-        /**
-         * Boolean : true by default.  
-         */
         public needRefreshPerFrame(): boolean {
         public needRefreshPerFrame(): boolean {
             return true;
             return true;
         }
         }

+ 3 - 2
src/Lights/babylon.light.ts

@@ -5,15 +5,16 @@
         position: Vector3;
         position: Vector3;
         transformedPosition: Vector3;
         transformedPosition: Vector3;
         name: string;
         name: string;
+        shadowMinZ: number;
+        shadowMaxZ: number;
 
 
         computeTransformedPosition(): boolean;
         computeTransformedPosition(): boolean;
         getScene(): Scene;
         getScene(): Scene;
 
 
-
         customProjectionMatrixBuilder: (viewMatrix: Matrix, renderList: Array<AbstractMesh>, result: Matrix) => void;
         customProjectionMatrixBuilder: (viewMatrix: Matrix, renderList: Array<AbstractMesh>, result: Matrix) => void;
         setShadowProjectionMatrix(matrix: Matrix, viewMatrix: Matrix, renderList: Array<AbstractMesh>): void;
         setShadowProjectionMatrix(matrix: Matrix, viewMatrix: Matrix, renderList: Array<AbstractMesh>): void;
+        getDepthScale(): number;
 
 
-        supportsVSM(): boolean;
         needRefreshPerFrame(): boolean;
         needRefreshPerFrame(): boolean;
         needCube(): boolean;
         needCube(): boolean;
 
 

+ 14 - 7
src/Lights/babylon.pointLight.ts

@@ -5,6 +5,11 @@
 
 
         @serializeAsVector3()
         @serializeAsVector3()
         public position: Vector3;
         public position: Vector3;
+
+        @serialize()
+        public shadowMinZ: number;
+        @serialize()
+        public shadowMaxZ: number;
         
         
         public customProjectionMatrixBuilder: (viewMatrix: Matrix, renderList: Array<AbstractMesh>, result: Matrix) => void;
         public customProjectionMatrixBuilder: (viewMatrix: Matrix, renderList: Array<AbstractMesh>, result: Matrix) => void;
 
 
@@ -79,12 +84,6 @@
         /**
         /**
          * Boolean : returns false by default.  
          * Boolean : returns false by default.  
          */
          */
-        public supportsVSM(): boolean {
-            return false;
-        }
-        /**
-         * Boolean : returns false by default.  
-         */
         public needRefreshPerFrame(): boolean {
         public needRefreshPerFrame(): boolean {
             return false;
             return false;
         }
         }
@@ -110,6 +109,13 @@
 
 
             return Vector3.Zero();
             return Vector3.Zero();
         }
         }
+        
+        /**
+         * Return the depth scale used for the shadow map.
+         */
+        public getDepthScale(): number {
+            return 30.0;
+        }
 
 
         /**
         /**
          * Sets the passed matrix "matrix" as a left-handed perspective projection matrix with the following settings : 
          * Sets the passed matrix "matrix" as a left-handed perspective projection matrix with the following settings : 
@@ -123,7 +129,8 @@
                 this.customProjectionMatrixBuilder(viewMatrix, renderList, matrix);
                 this.customProjectionMatrixBuilder(viewMatrix, renderList, matrix);
             } else {
             } else {
                 var activeCamera = this.getScene().activeCamera;
                 var activeCamera = this.getScene().activeCamera;
-                Matrix.PerspectiveFovLHToRef(Math.PI / 2, 1.0, activeCamera.minZ, activeCamera.maxZ, matrix);
+                Matrix.PerspectiveFovLHToRef(Math.PI / 2, 1.0, 
+                this.shadowMinZ !== undefined ? this.shadowMinZ : activeCamera.minZ, this.shadowMaxZ !== undefined ? this.shadowMaxZ : activeCamera.maxZ, matrix);
             }
             }
             return this;
             return this;
         }
         }

+ 16 - 8
src/Lights/babylon.spotLight.ts

@@ -10,7 +10,12 @@
         public angle: number;
         public angle: number;
 
 
         @serialize()
         @serialize()
-        public exponent: number
+        public exponent: number;
+        
+        @serialize()
+        public shadowMinZ: number;
+        @serialize()
+        public shadowMaxZ: number;
 
 
         public transformedPosition: Vector3;
         public transformedPosition: Vector3;
 
 
@@ -49,6 +54,14 @@
         public getAbsolutePosition(): Vector3 {
         public getAbsolutePosition(): Vector3 {
             return this.transformedPosition ? this.transformedPosition : this.position;
             return this.transformedPosition ? this.transformedPosition : this.position;
         }
         }
+
+        /**
+         * Return the depth scale used for the shadow map.
+         */
+        public getDepthScale(): number {
+            return 30.0;
+        }
+        
         /**
         /**
          * Sets the passed matrix "matrix" as perspective projection matrix for the shadows and the passed view matrix with the fov equal to the SpotLight angle and and aspect ratio of 1.0.  
          * Sets the passed matrix "matrix" as perspective projection matrix for the shadows and the passed view matrix with the fov equal to the SpotLight angle and and aspect ratio of 1.0.  
          * Returns the SpotLight.  
          * Returns the SpotLight.  
@@ -58,7 +71,8 @@
                 this.customProjectionMatrixBuilder(viewMatrix, renderList, matrix);
                 this.customProjectionMatrixBuilder(viewMatrix, renderList, matrix);
             } else {
             } else {
                 var activeCamera = this.getScene().activeCamera;
                 var activeCamera = this.getScene().activeCamera;
-                Matrix.PerspectiveFovLHToRef(this.angle, 1.0, activeCamera.minZ, activeCamera.maxZ, matrix);
+                Matrix.PerspectiveFovLHToRef(this.angle, 1.0, 
+                this.shadowMinZ !== undefined ? this.shadowMinZ : activeCamera.minZ, this.shadowMaxZ !== undefined ? this.shadowMaxZ : activeCamera.maxZ, matrix);
             }
             }
             return this;
             return this;
         }
         }
@@ -69,12 +83,6 @@
             return false;
             return false;
         }
         }
         /**
         /**
-         * Boolean : true by default.  
-         */
-        public supportsVSM(): boolean {
-            return true;
-        }
-        /**
          * Boolean : false by default.  
          * Boolean : false by default.  
          */
          */
         public needRefreshPerFrame(): boolean {
         public needRefreshPerFrame(): boolean {

+ 13 - 2
src/Loading/babylon.sceneLoader.ts

@@ -135,7 +135,7 @@
             }
             }
         }
         }
 
 
-        public static ImportMesh(meshesNames: any, rootUrl: string, sceneFilename: string, scene: Scene, onsuccess?: (meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]) => void, progressCallBack?: () => void, onerror?: (scene: Scene, message: string, exception?: any) => void): void {
+        public static ImportMesh(meshesNames: any, rootUrl: string, sceneFilename: string, scene: Scene, onsuccess?: (meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]) => void, progressCallBack?: () => void, onerror?: (scene: Scene, message: string, exception?: any) => void): void {            
             if (sceneFilename.substr && sceneFilename.substr(0, 1) === "/") {
             if (sceneFilename.substr && sceneFilename.substr(0, 1) === "/") {
                 Tools.Error("Wrong sceneFilename parameter");
                 Tools.Error("Wrong sceneFilename parameter");
                 return;
                 return;
@@ -163,6 +163,13 @@
                     var particleSystems = [];
                     var particleSystems = [];
                     var skeletons = [];
                     var skeletons = [];
 
 
+                    if (scene.isDisposed) {
+                        if (onerror) {
+                            onerror(scene, 'Scene was disposed before being able to load ' + rootUrl + sceneFilename);
+                        }
+                        return;
+                    }
+
                     try {
                     try {
                         if ((<any>plugin).importMesh) {
                         if ((<any>plugin).importMesh) {
                             var syncedPlugin = <ISceneLoaderPlugin>plugin;
                             var syncedPlugin = <ISceneLoaderPlugin>plugin;
@@ -209,7 +216,11 @@
 
 
                 Tools.LoadFile(rootUrl + sceneFilename, data => {
                 Tools.LoadFile(rootUrl + sceneFilename, data => {
                     importMeshFromData(data);
                     importMeshFromData(data);
-                }, progressCallBack, database, useArrayBuffer);
+                }, progressCallBack, database, useArrayBuffer, () => {
+                    if (onerror) {
+                        onerror(scene, 'Unable to load file ' + rootUrl + sceneFilename)
+                    }
+                });
             };
             };
 
 
             if (scene.getEngine().enableOfflineSupport && !directLoad) {
             if (scene.getEngine().enableOfflineSupport && !directLoad) {

+ 1 - 0
src/Materials/Textures/babylon.texture.ts

@@ -14,6 +14,7 @@
         public static INVCUBIC_MODE = 6;
         public static INVCUBIC_MODE = 6;
         public static EQUIRECTANGULAR_MODE = 7;
         public static EQUIRECTANGULAR_MODE = 7;
         public static FIXED_EQUIRECTANGULAR_MODE = 8;
         public static FIXED_EQUIRECTANGULAR_MODE = 8;
+        public static FIXED_EQUIRECTANGULAR_MIRRORED_MODE = 9;
 
 
         public static CLAMP_ADDRESSMODE = 0;
         public static CLAMP_ADDRESSMODE = 0;
         public static WRAP_ADDRESSMODE = 1;
         public static WRAP_ADDRESSMODE = 1;

+ 10 - 2
src/Materials/Textures/babylon.videoTexture.ts

@@ -85,17 +85,25 @@
                 minWidth: number, 
                 minWidth: number, 
                 maxWidth: number, 
                 maxWidth: number, 
                 minHeight: number, 
                 minHeight: number, 
-                maxHeight: number
+                maxHeight: number,
+                deviceId: string
             }): void {
             }): void {
             var video = document.createElement("video");
             var video = document.createElement("video");
+            var constraintsDeviceId;
+            if (constraints && constraints.deviceId){
+                constraintsDeviceId = { 
+                    exact: constraints.deviceId                     
+                }
+            }
 
 
 		    navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
 		    navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
 		    window.URL = window.URL || window.webkitURL || window.mozURL || window.msURL;
 		    window.URL = window.URL || window.webkitURL || window.mozURL || window.msURL;
 
 
 
 
 		    if (navigator.getUserMedia) {
 		    if (navigator.getUserMedia) {
-			    navigator.getUserMedia({ 
+			    navigator.getUserMedia({                     
                     video: {
                     video: {
+                        deviceId: constraintsDeviceId,
                         width: {
                         width: {
                             min: (constraints && constraints.minWidth) || 256,
                             min: (constraints && constraints.minWidth) || 256,
                             max: (constraints && constraints.maxWidth) || 640
                             max: (constraints && constraints.maxWidth) || 640

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

@@ -84,20 +84,19 @@
 
 
                         defines["SHADOWS"] = true;
                         defines["SHADOWS"] = true;
 
 
-                        if (shadowGenerator.useVarianceShadowMap || shadowGenerator.useBlurVarianceShadowMap) {
-                            if (defines["SHADOWVSM" + lightIndex] === undefined) {
-                                needRebuild = true;
-                            }
-
-                            defines["SHADOWVSM" + lightIndex] = true;
-                        }
-
                         if (shadowGenerator.usePoissonSampling) {
                         if (shadowGenerator.usePoissonSampling) {
                             if (defines["SHADOWPCF" + lightIndex] === undefined) {
                             if (defines["SHADOWPCF" + lightIndex] === undefined) {
                                 needRebuild = true;
                                 needRebuild = true;
                             }
                             }
 
 
                             defines["SHADOWPCF" + lightIndex] = true;
                             defines["SHADOWPCF" + lightIndex] = true;
+                        } 
+                        else if (shadowGenerator.useExponentialShadowMap || shadowGenerator.useBlurExponentialShadowMap) {
+                            if (defines["SHADOWESM" + lightIndex] === undefined) {
+                                needRebuild = true;
+                            }
+
+                            defines["SHADOWESM" + lightIndex] = true;
                         }
                         }
 
 
                         needShadows = true;
                         needShadows = true;
@@ -184,8 +183,8 @@
                     fallbacks.addFallback(0, "SHADOWPCF" + lightIndex);
                     fallbacks.addFallback(0, "SHADOWPCF" + lightIndex);
                 }
                 }
 
 
-                if (defines["SHADOWVSM" + lightIndex]) {
-                    fallbacks.addFallback(0, "SHADOWVSM" + lightIndex);
+                if (defines["SHADOWESM" + lightIndex]) {
+                    fallbacks.addFallback(0, "SHADOWESM" + lightIndex);
                 }
                 }
             }
             }
         }
         }
@@ -225,7 +224,7 @@
                     }
                     }
                 }
                 }
                 effect.setTexture("shadowSampler" + lightIndex, shadowGenerator.getShadowMapForRendering());
                 effect.setTexture("shadowSampler" + lightIndex, shadowGenerator.getShadowMapForRendering());
-                effect.setFloat3("shadowsInfo" + lightIndex, shadowGenerator.getDarkness(), shadowGenerator.blurScale / shadowGenerator.getShadowMap().getSize().width, shadowGenerator.bias);
+                effect.setFloat3("shadowsInfo" + lightIndex, shadowGenerator.getDarkness(), shadowGenerator.blurScale / shadowGenerator.getShadowMap().getSize().width, shadowGenerator.depthScale);
             }
             }
 
 
             return depthValuesAlreadySet;
             return depthValuesAlreadySet;

+ 28 - 2
src/Materials/babylon.pbrMaterial.ts

@@ -21,6 +21,7 @@
         public EMISSIVEFRESNEL = false;
         public EMISSIVEFRESNEL = false;
         public FRESNEL = false;
         public FRESNEL = false;
         public NORMAL = false;
         public NORMAL = false;
+        public TANGENT = false;
         public UV1 = false;
         public UV1 = false;
         public UV2 = false;
         public UV2 = false;
         public VERTEXCOLOR = false;
         public VERTEXCOLOR = false;
@@ -41,7 +42,9 @@
         public REFLECTIONMAP_PROJECTION = false;
         public REFLECTIONMAP_PROJECTION = false;
         public REFLECTIONMAP_SKYBOX = false;
         public REFLECTIONMAP_SKYBOX = false;
         public REFLECTIONMAP_EXPLICIT = false;
         public REFLECTIONMAP_EXPLICIT = false;
-        public REFLECTIONMAP_EQUIRECTANGULAR = false;
+        public REFLECTIONMAP_EQUIRECTANGULAR = false;        
+        public REFLECTIONMAP_EQUIRECTANGULAR_FIXED = false;
+        public REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED = false;
         public INVERTCUBICMAP = false;
         public INVERTCUBICMAP = false;
         public LOGARITHMICDEPTH = false;
         public LOGARITHMICDEPTH = false;
         public CAMERATONEMAP = false;
         public CAMERATONEMAP = false;
@@ -60,9 +63,9 @@
         public RADIANCEOVERALPHA = false;
         public RADIANCEOVERALPHA = false;
         public USEPMREMREFLECTION = false;
         public USEPMREMREFLECTION = false;
         public USEPMREMREFRACTION = false;
         public USEPMREMREFRACTION = false;
-        public OPENGLNORMALMAP = false;
         public INVERTNORMALMAPX = false;
         public INVERTNORMALMAPX = false;
         public INVERTNORMALMAPY = false;
         public INVERTNORMALMAPY = false;
+        public TWOSIDEDLIGHTING = false;
         public SHADOWFULLFLOAT = false;
         public SHADOWFULLFLOAT = false;
 
 
         public METALLICWORKFLOW = false;
         public METALLICWORKFLOW = false;
@@ -486,6 +489,12 @@
         @serialize()
         @serialize()
         public invertNormalMapY = false;
         public invertNormalMapY = false;
 
 
+        /**
+         * If sets to true and backfaceCulling is false, normals will be flipped on the backside.
+         */
+        @serialize()
+        public twoSidedLighting = false;
+
         private _renderTargets = new SmartArray<RenderTargetTexture>(16);
         private _renderTargets = new SmartArray<RenderTargetTexture>(16);
         private _worldViewProjectionMatrix = Matrix.Zero();
         private _worldViewProjectionMatrix = Matrix.Zero();
         private _globalAmbientColor = new Color3(0, 0, 0);
         private _globalAmbientColor = new Color3(0, 0, 0);
@@ -732,6 +741,12 @@
                             case Texture.EQUIRECTANGULAR_MODE:
                             case Texture.EQUIRECTANGULAR_MODE:
                                 this._defines.REFLECTIONMAP_EQUIRECTANGULAR = true;
                                 this._defines.REFLECTIONMAP_EQUIRECTANGULAR = true;
                                 break;
                                 break;
+                            case Texture.FIXED_EQUIRECTANGULAR_MODE:
+                                this._defines.REFLECTIONMAP_EQUIRECTANGULAR_FIXED = true;
+                                break;
+                            case Texture.FIXED_EQUIRECTANGULAR_MIRRORED_MODE:
+                                this._defines.REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED = true;
+                                break;                                
                         }
                         }
 
 
                         if (this.reflectionTexture instanceof HDRCubeTexture && (<HDRCubeTexture>this.reflectionTexture)) {
                         if (this.reflectionTexture instanceof HDRCubeTexture && (<HDRCubeTexture>this.reflectionTexture)) {
@@ -845,6 +860,10 @@
                         this._defines.CAMERACOLORGRADING = true;
                         this._defines.CAMERACOLORGRADING = true;
                     }
                     }
                 }
                 }
+
+                if (!this.backFaceCulling && this.twoSidedLighting) {
+                    this._defines.TWOSIDEDLIGHTING = true;
+                }
             }
             }
 
 
             // Effect
             // Effect
@@ -946,6 +965,9 @@
             if (mesh) {
             if (mesh) {
                 if (needNormals && mesh.isVerticesDataPresent(VertexBuffer.NormalKind)) {
                 if (needNormals && mesh.isVerticesDataPresent(VertexBuffer.NormalKind)) {
                     this._defines.NORMAL = true;
                     this._defines.NORMAL = true;
+                    if (mesh.isVerticesDataPresent(VertexBuffer.TangentKind)) {
+                        this._defines.TANGENT = true;
+                    }
                 }
                 }
                 if (needUVs) {
                 if (needUVs) {
                     if (mesh.isVerticesDataPresent(VertexBuffer.UVKind)) {
                     if (mesh.isVerticesDataPresent(VertexBuffer.UVKind)) {
@@ -1050,6 +1072,10 @@
                     attribs.push(VertexBuffer.NormalKind);
                     attribs.push(VertexBuffer.NormalKind);
                 }
                 }
 
 
+                if (this._defines.TANGENT) {
+                    attribs.push(VertexBuffer.TangentKind);
+                }
+
                 if (this._defines.UV1) {
                 if (this._defines.UV1) {
                     attribs.push(VertexBuffer.UVKind);
                     attribs.push(VertexBuffer.UVKind);
                 }
                 }

+ 7 - 0
src/Materials/babylon.shaderMaterial.ts

@@ -190,6 +190,13 @@
                 fallbacks.addCPUSkinningFallback(0, mesh);
                 fallbacks.addCPUSkinningFallback(0, mesh);
             }
             }
 
 
+            // Textures
+            for (var name in this._textures) {
+                if (!this._textures[name].isReady()) {
+                    return false;
+                }
+            }
+
             // Alpha test
             // Alpha test
             if (engine.getAlphaTesting()) {
             if (engine.getAlphaTesting()) {
                 defines.push("#define ALPHATEST");
                 defines.push("#define ALPHATEST");

+ 26 - 13
src/Materials/babylon.standardMaterial.ts

@@ -1,5 +1,5 @@
-module BABYLON {
-    class StandardMaterialDefines extends MaterialDefines {
+module BABYLON {
+   export class StandardMaterialDefines extends MaterialDefines {
         public DIFFUSE = false;
         public DIFFUSE = false;
         public AMBIENT = false;
         public AMBIENT = false;
         public OPACITY = false;
         public OPACITY = false;
@@ -47,6 +47,7 @@
         public REFLECTIONMAP_EXPLICIT = false;
         public REFLECTIONMAP_EXPLICIT = false;
         public REFLECTIONMAP_EQUIRECTANGULAR = false;
         public REFLECTIONMAP_EQUIRECTANGULAR = false;
         public REFLECTIONMAP_EQUIRECTANGULAR_FIXED = false;
         public REFLECTIONMAP_EQUIRECTANGULAR_FIXED = false;
+        public REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED = false;
         public INVERTCUBICMAP = false;
         public INVERTCUBICMAP = false;
         public LOGARITHMICDEPTH = false;
         public LOGARITHMICDEPTH = false;
         public REFRACTION = false;
         public REFRACTION = false;
@@ -54,6 +55,7 @@
         public REFLECTIONOVERALPHA = false;
         public REFLECTIONOVERALPHA = false;
         public INVERTNORMALMAPX = false;
         public INVERTNORMALMAPX = false;
         public INVERTNORMALMAPY = false;
         public INVERTNORMALMAPY = false;
+        public TWOSIDEDLIGHTING = false;
         public SHADOWFULLFLOAT = false;
         public SHADOWFULLFLOAT = false;
         public CAMERACOLORGRADING = false;
         public CAMERACOLORGRADING = false;
         public CAMERACOLORCURVES = false;
         public CAMERACOLORCURVES = false;
@@ -183,6 +185,12 @@
         public invertNormalMapY = false;
         public invertNormalMapY = false;
 
 
         /**
         /**
+         * If sets to true and backfaceCulling is false, normals will be flipped on the backside.
+         */
+        @serialize()
+        public twoSidedLighting = false;
+
+        /**
          * Color Grading 2D Lookup Texture.
          * Color Grading 2D Lookup Texture.
          * This allows special effects like sepia, black and white to sixties rendering style. 
          * This allows special effects like sepia, black and white to sixties rendering style. 
          */
          */
@@ -198,15 +206,15 @@
         @serializeAsColorCurves()
         @serializeAsColorCurves()
         public cameraColorCurves: ColorCurves = null;
         public cameraColorCurves: ColorCurves = null;
 
 
-        private _renderTargets = new SmartArray<RenderTargetTexture>(16);
-        private _worldViewProjectionMatrix = Matrix.Zero();
-        private _globalAmbientColor = new Color3(0, 0, 0);
-        private _renderId: number;
+        protected _renderTargets = new SmartArray<RenderTargetTexture>(16);
+        protected _worldViewProjectionMatrix = Matrix.Zero();
+        protected _globalAmbientColor = new Color3(0, 0, 0);
+        protected _renderId: number;
 
 
-        private _defines = new StandardMaterialDefines();
-        private _cachedDefines = new StandardMaterialDefines();
+        protected _defines = new StandardMaterialDefines();
+        protected _cachedDefines = new StandardMaterialDefines();
 
 
-        private _useLogarithmicDepth: boolean;
+        protected _useLogarithmicDepth: boolean;
 
 
         constructor(name: string, scene: Scene) {
         constructor(name: string, scene: Scene) {
             super(name, scene);
             super(name, scene);
@@ -249,7 +257,7 @@
             return this.diffuseTexture != null && this.diffuseTexture.hasAlpha;
             return this.diffuseTexture != null && this.diffuseTexture.hasAlpha;
         }
         }
 
 
-        private _shouldUseAlphaFromDiffuseTexture(): boolean {
+        protected _shouldUseAlphaFromDiffuseTexture(): boolean {
             return this.diffuseTexture != null && this.diffuseTexture.hasAlpha && this.useAlphaFromDiffuseTexture;
             return this.diffuseTexture != null && this.diffuseTexture.hasAlpha && this.useAlphaFromDiffuseTexture;
         }
         }
 
 
@@ -258,7 +266,7 @@
         }
         }
 
 
         // Methods   
         // Methods   
-        private _checkCache(scene: Scene, mesh?: AbstractMesh, useInstances?: boolean): boolean {
+        protected _checkCache(scene: Scene, mesh?: AbstractMesh, useInstances?: boolean): boolean {
             if (!mesh) {
             if (!mesh) {
                 return true;
                 return true;
             }
             }
@@ -381,6 +389,9 @@
                             case Texture.FIXED_EQUIRECTANGULAR_MODE:
                             case Texture.FIXED_EQUIRECTANGULAR_MODE:
                                 this._defines.REFLECTIONMAP_EQUIRECTANGULAR_FIXED = true;
                                 this._defines.REFLECTIONMAP_EQUIRECTANGULAR_FIXED = true;
                                 break;
                                 break;
+                            case Texture.FIXED_EQUIRECTANGULAR_MIRRORED_MODE:
+                                this._defines.REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED = true;
+                                break;
                         }
                         }
                     }
                     }
                 }
                 }
@@ -461,6 +472,10 @@
                         this._defines.CAMERACOLORGRADING = true;
                         this._defines.CAMERACOLORGRADING = true;
                     }
                     }
                 }
                 }
+
+                if (!this.backFaceCulling && this.twoSidedLighting) {
+                    this._defines.TWOSIDEDLIGHTING = true;
+                }
             }
             }
 
 
             // Effect
             // Effect
@@ -1010,8 +1025,6 @@
                 }
                 }
             }
             }
 
 
-            this._renderTargets.dispose();
-
             super.dispose(forceDisposeEffect, forceDisposeTextures);
             super.dispose(forceDisposeEffect, forceDisposeTextures);
         }
         }
 
 

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

@@ -2144,7 +2144,7 @@
         /**
         /**
          * Returns a new Vector4 set from the starting index of the passed array.  
          * Returns a new Vector4 set from the starting index of the passed array.  
          */
          */
-        public static FromArray(array: number[], offset?: number): Vector4 {
+        public static FromArray(array: number[]  | Float32Array, offset?: number): Vector4 {
             if (!offset) {
             if (!offset) {
                 offset = 0;
                 offset = 0;
             }
             }
@@ -2153,7 +2153,7 @@
         /**
         /**
          * Updates the passed vector "result" from the starting index of the passed array.  
          * Updates the passed vector "result" from the starting index of the passed array.  
          */
          */
-        public static FromArrayToRef(array: number[], offset: number, result: Vector4): void {
+        public static FromArrayToRef(array: number[] | Float32Array, offset: number, result: Vector4): void {
             result.x = array[offset];
             result.x = array[offset];
             result.y = array[offset + 1];
             result.y = array[offset + 1];
             result.z = array[offset + 2];
             result.z = array[offset + 2];
@@ -2219,7 +2219,6 @@
         /**
         /**
          * Returns the squared distance (float) between the vectors "value1" and "value2".  
          * Returns the squared distance (float) between the vectors "value1" and "value2".  
          */
          */
-        publi
         public static DistanceSquared(value1: Vector4, value2: Vector4): number {
         public static DistanceSquared(value1: Vector4, value2: Vector4): number {
             var x = value1.x - value2.x;
             var x = value1.x - value2.x;
             var y = value1.y - value2.y;
             var y = value1.y - value2.y;
@@ -2236,6 +2235,41 @@
             center.scaleInPlace(0.5);
             center.scaleInPlace(0.5);
             return center;
             return center;
         }
         }
+
+        /**
+         * Returns a new Vector4 set with the result of the normal transformation by the passed matrix of the passed vector.  
+         * This methods computes transformed normalized direction vectors only.  
+         */
+        public static TransformNormal(vector: Vector4, transformation: Matrix): Vector4 {
+            var result = Vector4.Zero();
+            Vector4.TransformNormalToRef(vector, transformation, result);
+            return result;
+        }
+
+        /**
+         * Sets the passed vector "result" with the result of the normal transformation by the passed matrix of the passed vector.  
+         * This methods computes transformed normalized direction vectors only. 
+         */
+        public static TransformNormalToRef(vector: Vector4, transformation: Matrix, result: Vector4): void {
+            var x = (vector.x * transformation.m[0]) + (vector.y * transformation.m[4]) + (vector.z * transformation.m[8]);
+            var y = (vector.x * transformation.m[1]) + (vector.y * transformation.m[5]) + (vector.z * transformation.m[9]);
+            var z = (vector.x * transformation.m[2]) + (vector.y * transformation.m[6]) + (vector.z * transformation.m[10]);
+            result.x = x;
+            result.y = y;
+            result.z = z;
+            result.w = vector.w;
+        }
+
+        /**
+         * Sets the passed vector "result" with the result of the normal transformation by the passed matrix of the passed floats (x, y, z, w).  
+         * This methods computes transformed normalized direction vectors only. 
+         */
+        public static TransformNormalFromFloatsToRef(x: number, y: number, z: number, w: number, transformation: Matrix, result: Vector4): void {
+            result.x = (x * transformation.m[0]) + (y * transformation.m[4]) + (z * transformation.m[8]);
+            result.y = (x * transformation.m[1]) + (y * transformation.m[5]) + (z * transformation.m[9]);
+            result.z = (x * transformation.m[2]) + (y * transformation.m[6]) + (z * transformation.m[10]);
+            result.w = w;
+        }
     }
     }
 
 
     export interface ISize {
     export interface ISize {

+ 3 - 2
src/Mesh/babylon.abstractMesh.ts

@@ -460,7 +460,8 @@
             if (this._masterMesh) {
             if (this._masterMesh) {
                 return this._masterMesh.getWorldMatrix();
                 return this._masterMesh.getWorldMatrix();
             }
             }
-            if (this._currentRenderId !== this.getScene().getRenderId()) {
+            
+            if (this._currentRenderId !== this.getScene().getRenderId() || !this.isSynchronized()) {
                 this.computeWorldMatrix();
                 this.computeWorldMatrix();
             }
             }
             return this._worldMatrix;
             return this._worldMatrix;
@@ -813,7 +814,7 @@
                 return this._worldMatrix;
                 return this._worldMatrix;
             }
             }
 
 
-            if (!force && (this._currentRenderId === this.getScene().getRenderId() || this.isSynchronized(true))) {
+            if (!force && ((this._currentRenderId === this.getScene().getRenderId() && this.isSynchronized(true)))) {
                 this._currentRenderId = this.getScene().getRenderId();
                 this._currentRenderId = this.getScene().getRenderId();
                 return this._worldMatrix;
                 return this._worldMatrix;
             }
             }

+ 1 - 1
src/Mesh/babylon.instancedMesh.ts

@@ -160,7 +160,7 @@
             var result = this._sourceMesh.createInstance(name);
             var result = this._sourceMesh.createInstance(name);
 
 
             // Deep copy
             // Deep copy
-            Tools.DeepCopy(this, result, ["name", "subMeshes"], []);
+            Tools.DeepCopy(this, result, ["name", "subMeshes", "uniqueId"], []);
 
 
             // Bounding info
             // Bounding info
             this.refreshBoundingInfo();
             this.refreshBoundingInfo();

+ 1 - 1
src/Mesh/babylon.mesh.ts

@@ -151,7 +151,7 @@
                 }
                 }
 
 
                 // Deep copy
                 // Deep copy
-                Tools.DeepCopy(source, this, ["name", "material", "skeleton", "instances", "parent"], ["_poseMatrix"]);
+                Tools.DeepCopy(source, this, ["name", "material", "skeleton", "instances", "parent", "uniqueId"], ["_poseMatrix"]);
 
 
                 // Parent
                 // Parent
                 this.parent = source.parent;
                 this.parent = source.parent;

+ 58 - 12
src/Mesh/babylon.mesh.vertexData.ts

@@ -14,6 +14,7 @@
     export class VertexData {
     export class VertexData {
         public positions: number[] | Float32Array;
         public positions: number[] | Float32Array;
         public normals: number[] | Float32Array;
         public normals: number[] | Float32Array;
+        public tangents: number[] | Float32Array;
         public uvs: number[] | Float32Array;
         public uvs: number[] | Float32Array;
         public uvs2: number[] | Float32Array;
         public uvs2: number[] | Float32Array;
         public uvs3: number[] | Float32Array;
         public uvs3: number[] | Float32Array;
@@ -35,6 +36,9 @@
                 case VertexBuffer.NormalKind:
                 case VertexBuffer.NormalKind:
                     this.normals = data;
                     this.normals = data;
                     break;
                     break;
+                case VertexBuffer.TangentKind:
+                    this.tangents = data;
+                    break;
                 case VertexBuffer.UVKind:
                 case VertexBuffer.UVKind:
                     this.uvs = data;
                     this.uvs = data;
                     break;
                     break;
@@ -118,6 +122,10 @@
                 meshOrGeometry.setVerticesData(VertexBuffer.NormalKind, this.normals, updatable);
                 meshOrGeometry.setVerticesData(VertexBuffer.NormalKind, this.normals, updatable);
             }
             }
 
 
+            if (this.tangents) {
+                meshOrGeometry.setVerticesData(VertexBuffer.TangentKind, this.tangents, updatable);
+            }
+
             if (this.uvs) {
             if (this.uvs) {
                 meshOrGeometry.setVerticesData(VertexBuffer.UVKind, this.uvs, updatable);
                 meshOrGeometry.setVerticesData(VertexBuffer.UVKind, this.uvs, updatable);
             }
             }
@@ -177,6 +185,10 @@
                 meshOrGeometry.updateVerticesData(VertexBuffer.NormalKind, this.normals, updateExtends, makeItUnique);
                 meshOrGeometry.updateVerticesData(VertexBuffer.NormalKind, this.normals, updateExtends, makeItUnique);
             }
             }
 
 
+            if (this.tangents) {
+                meshOrGeometry.updateVerticesData(VertexBuffer.TangentKind, this.tangents, updateExtends, makeItUnique);
+            }
+
             if (this.uvs) {
             if (this.uvs) {
                 meshOrGeometry.updateVerticesData(VertexBuffer.UVKind, this.uvs, updateExtends, makeItUnique);
                 meshOrGeometry.updateVerticesData(VertexBuffer.UVKind, this.uvs, updateExtends, makeItUnique);
             }
             }
@@ -259,6 +271,22 @@
                     this.normals[index + 2] = transformed.z;
                     this.normals[index + 2] = transformed.z;
                 }
                 }
             }
             }
+
+            if (this.tangents) {
+                var tangent = Vector4.Zero();
+                var tangentTransformed = Vector4.Zero();
+
+                for (index = 0; index < this.tangents.length; index += 4) {
+                    Vector4.FromArrayToRef(this.tangents, index, tangent);
+
+                    Vector4.TransformNormalToRef(tangent, matrix, tangentTransformed);
+                    this.tangents[index] = tangentTransformed.x;
+                    this.tangents[index + 1] = tangentTransformed.y;
+                    this.tangents[index + 2] = tangentTransformed.z;
+                    this.tangents[index + 3] = tangentTransformed.w;
+                }
+            }
+
             return this;
             return this;
         }
         }
 
 
@@ -281,6 +309,7 @@
 
 
             this.positions = this._mergeElement(this.positions, other.positions);
             this.positions = this._mergeElement(this.positions, other.positions);
             this.normals = this._mergeElement(this.normals, other.normals);
             this.normals = this._mergeElement(this.normals, other.normals);
+            this.tangents = this._mergeElement(this.tangents, other.tangents);
             this.uvs = this._mergeElement(this.uvs, other.uvs);
             this.uvs = this._mergeElement(this.uvs, other.uvs);
             this.uvs2 = this._mergeElement(this.uvs2, other.uvs2);
             this.uvs2 = this._mergeElement(this.uvs2, other.uvs2);
             this.uvs3 = this._mergeElement(this.uvs3, other.uvs3);
             this.uvs3 = this._mergeElement(this.uvs3, other.uvs3);
@@ -339,6 +368,10 @@
                 serializationObject.normals = this.normals;
                 serializationObject.normals = this.normals;
             }
             }
 
 
+            if (this.tangents) {
+                serializationObject.tangents = this.tangents;
+            }
+
             if (this.uvs) {
             if (this.uvs) {
                 serializationObject.uvs = this.uvs;
                 serializationObject.uvs = this.uvs;
             }
             }
@@ -416,6 +449,10 @@
                 result.normals = meshOrGeometry.getVerticesData(VertexBuffer.NormalKind, copyWhenShared);
                 result.normals = meshOrGeometry.getVerticesData(VertexBuffer.NormalKind, copyWhenShared);
             }
             }
 
 
+            if (meshOrGeometry.isVerticesDataPresent(VertexBuffer.TangentKind)) {
+                result.tangents = meshOrGeometry.getVerticesData(VertexBuffer.TangentKind, copyWhenShared);
+            }
+
             if (meshOrGeometry.isVerticesDataPresent(VertexBuffer.UVKind)) {
             if (meshOrGeometry.isVerticesDataPresent(VertexBuffer.UVKind)) {
                 result.uvs = meshOrGeometry.getVerticesData(VertexBuffer.UVKind, copyWhenShared);
                 result.uvs = meshOrGeometry.getVerticesData(VertexBuffer.UVKind, copyWhenShared);
             }
             }
@@ -678,11 +715,14 @@
 
 
             // Result
             // Result
             var vertexData = new VertexData();
             var vertexData = new VertexData();
-
+            var positions32 = new Float32Array(positions);
+            var normals32 = new Float32Array(normals);
+            var uvs32 = new Float32Array(uvs);
+            
             vertexData.indices = indices;
             vertexData.indices = indices;
-            vertexData.positions = positions;
-            vertexData.normals = normals;
-            vertexData.uvs = uvs;
+            vertexData.positions = positions32;
+            vertexData.normals = normals32;
+            vertexData.uvs = uvs32;
             if (customColors) {
             if (customColors) {
                 vertexData.set(colors, VertexBuffer.ColorKind);
                 vertexData.set(colors, VertexBuffer.ColorKind);
             }
             }
@@ -2085,7 +2125,7 @@
          * bbSize : optional bounding box size data, required for facetPartitioning computation
          * bbSize : optional bounding box size data, required for facetPartitioning computation
          * bInfo : optional bounding info, required for facetPartitioning computation
          * bInfo : optional bounding info, required for facetPartitioning computation
          */
          */
-        public static ComputeNormals(positions: any, indices: any, normals: any, 
+        public static ComputeNormals(positions: any, indices: any, normals: any,
             options?: { facetNormals?: any, facetPositions?: any, facetPartitioning?: any, ratio?: number, bInfo?: any, bbSize?: Vector3, subDiv?: any}): void {
             options?: { facetNormals?: any, facetPositions?: any, facetPartitioning?: any, ratio?: number, bInfo?: any, bbSize?: Vector3, subDiv?: any}): void {
 
 
             // temporary scalar variables
             // temporary scalar variables
@@ -2119,7 +2159,7 @@
             }
             }
 
 
             // facetPartitioning reinit if needed
             // facetPartitioning reinit if needed
-            if (computeFacetPartitioning) {  
+            if (computeFacetPartitioning) {
                 var ox = 0;                 // X partitioning index for facet position
                 var ox = 0;                 // X partitioning index for facet position
                 var oy = 0;                 // Y partinioning index for facet position
                 var oy = 0;                 // Y partinioning index for facet position
                 var oz = 0;                 // Z partinioning index for facet position
                 var oz = 0;                 // Z partinioning index for facet position
@@ -2145,7 +2185,7 @@
                 var subSq = options.subDiv.max * options.subDiv.max;
                 var subSq = options.subDiv.max * options.subDiv.max;
                 options.facetPartitioning.length = 0;
                 options.facetPartitioning.length = 0;
             }
             }
-        
+
             // reset the normals
             // reset the normals
             for (index = 0; index < positions.length; index++) {
             for (index = 0; index < positions.length; index++) {
                 normals[index] = 0.0;
                 normals[index] = 0.0;
@@ -2164,7 +2204,7 @@
                 v2z = v2x + 2;
                 v2z = v2x + 2;
                 v3x = indices[index * 3 + 2] * 3;
                 v3x = indices[index * 3 + 2] * 3;
                 v3y = v3x + 1;
                 v3y = v3x + 1;
-                v3z = v3x + 2;        
+                v3z = v3x + 2;
 
 
                 p1p2x = positions[v1x] - positions[v2x];          // compute two vectors per facet : p1p2 and p3p2
                 p1p2x = positions[v1x] - positions[v2x];          // compute two vectors per facet : p1p2 and p3p2
                 p1p2y = positions[v1y] - positions[v2y];
                 p1p2y = positions[v1y] - positions[v2y];
@@ -2175,7 +2215,7 @@
                 p3p2z = positions[v3z] - positions[v2z];
                 p3p2z = positions[v3z] - positions[v2z];
 
 
                 // compute the face normal with the cross product
                 // compute the face normal with the cross product
-                faceNormalx = p1p2y * p3p2z - p1p2z * p3p2y;            
+                faceNormalx = p1p2y * p3p2z - p1p2z * p3p2y;
                 faceNormaly = p1p2z * p3p2x - p1p2x * p3p2z;
                 faceNormaly = p1p2z * p3p2x - p1p2x * p3p2z;
                 faceNormalz = p1p2x * p3p2y - p1p2y * p3p2x;
                 faceNormalz = p1p2x * p3p2y - p1p2y * p3p2x;
                 // normalize this normal and store it in the array facetData
                 // normalize this normal and store it in the array facetData
@@ -2186,7 +2226,7 @@
                 faceNormalz /= length;
                 faceNormalz /= length;
 
 
                 if (computeFacetNormals) {
                 if (computeFacetNormals) {
-                    options.facetNormals[index].x = faceNormalx;                                  
+                    options.facetNormals[index].x = faceNormalx;
                     options.facetNormals[index].y = faceNormaly;
                     options.facetNormals[index].y = faceNormaly;
                     options.facetNormals[index].z = faceNormalz;
                     options.facetNormals[index].z = faceNormalz;
                 }
                 }
@@ -2213,7 +2253,7 @@
                     b3x = Math.floor((positions[v3x] - options.bInfo.minimum.x * options.ratio) * xSubRatio);
                     b3x = Math.floor((positions[v3x] - options.bInfo.minimum.x * options.ratio) * xSubRatio);
                     b3y = Math.floor((positions[v3y] - options.bInfo.minimum.y * options.ratio) * ySubRatio);
                     b3y = Math.floor((positions[v3y] - options.bInfo.minimum.y * options.ratio) * ySubRatio);
                     b3z = Math.floor((positions[v3z] - options.bInfo.minimum.z * options.ratio) * zSubRatio);
                     b3z = Math.floor((positions[v3z] - options.bInfo.minimum.z * options.ratio) * zSubRatio);
-                    
+
                     block_idx_v1 = b1x + options.subDiv.max * b1y + subSq * b1z;
                     block_idx_v1 = b1x + options.subDiv.max * b1y + subSq * b1z;
                     block_idx_v2 = b2x + options.subDiv.max * b2y + subSq * b2z;
                     block_idx_v2 = b2x + options.subDiv.max * b2y + subSq * b2z;
                     block_idx_v3 = b3x + options.subDiv.max * b3y + subSq * b3z;
                     block_idx_v3 = b3x + options.subDiv.max * b3y + subSq * b3z;
@@ -2233,7 +2273,7 @@
                         options.facetPartitioning[block_idx_v3].push(index);
                         options.facetPartitioning[block_idx_v3].push(index);
                     }
                     }
                     if (!(block_idx_o == block_idx_v1 || block_idx_o == block_idx_v2 || block_idx_o == block_idx_v3)) {
                     if (!(block_idx_o == block_idx_v1 || block_idx_o == block_idx_v2 || block_idx_o == block_idx_v3)) {
-                        options.facetPartitioning[block_idx_o].push(index); 
+                        options.facetPartitioning[block_idx_o].push(index);
                     }
                     }
                 }
                 }
 
 
@@ -2338,6 +2378,12 @@
                 vertexData.set(normals, VertexBuffer.NormalKind);
                 vertexData.set(normals, VertexBuffer.NormalKind);
             }
             }
 
 
+            // tangents
+            var tangents = parsedVertexData.tangents;
+            if (tangents) {
+                vertexData.set(tangents, VertexBuffer.TangentKind);
+            }
+
             // uvs
             // uvs
             var uvs = parsedVertexData.uvs;
             var uvs = parsedVertexData.uvs;
             if (uvs) {
             if (uvs) {

+ 1 - 1
src/Mesh/babylon.meshBuilder.ts

@@ -122,7 +122,7 @@
          * You can also set the mesh side orientation with the values : BABYLON.Mesh.FRONTSIDE (default), BABYLON.Mesh.BACKSIDE or BABYLON.Mesh.DOUBLESIDE  
          * You can also set the mesh side orientation with the values : BABYLON.Mesh.FRONTSIDE (default), BABYLON.Mesh.BACKSIDE or BABYLON.Mesh.DOUBLESIDE  
          * Detail here : http://doc.babylonjs.com/tutorials/02._Discover_Basic_Elements#side-orientation    
          * Detail here : http://doc.babylonjs.com/tutorials/02._Discover_Basic_Elements#side-orientation    
          * The optional parameter `invertUV` (boolean, default false) swaps in the geometry the U and V coordinates to apply a texture.  
          * The optional parameter `invertUV` (boolean, default false) swaps in the geometry the U and V coordinates to apply a texture.  
-         * The parameter `uvs` is an optional flat array of `Vector4` to update/set each ribbon vertex with its own custom UV values instead of the computed ones.  
+         * The parameter `uvs` is an optional flat array of `Vector2` to update/set each ribbon vertex with its own custom UV values instead of the computed ones.  
          * The parameters `colors` is an optional flat array of `Color4` to set/update each ribbon vertex with its own custom color values.  
          * The parameters `colors` is an optional flat array of `Color4` to set/update each ribbon vertex with its own custom color values.  
          * Note that if you use the parameters `uvs` or `colors`, the passed arrays must be populated with the right number of elements, it is to say the number of ribbon vertices. Remember that 
          * Note that if you use the parameters `uvs` or `colors`, the passed arrays must be populated with the right number of elements, it is to say the number of ribbon vertices. Remember that 
          * if you set `closePath` to `true`, there's one extra vertex per path in the geometry.  
          * if you set `closePath` to `true`, there's one extra vertex per path in the geometry.  

+ 6 - 0
src/Mesh/babylon.vertexBuffer.ts

@@ -25,6 +25,7 @@
                     case VertexBuffer.UV6Kind:
                     case VertexBuffer.UV6Kind:
                         stride = 2;
                         stride = 2;
                         break;
                         break;
+                    case VertexBuffer.TangentKind:
                     case VertexBuffer.ColorKind:
                     case VertexBuffer.ColorKind:
                         stride = 4;
                         stride = 4;
                         break;
                         break;
@@ -154,6 +155,7 @@
         // Enums
         // Enums
         private static _PositionKind = "position";
         private static _PositionKind = "position";
         private static _NormalKind = "normal";
         private static _NormalKind = "normal";
+        private static _TangentKind = "tangent";
         private static _UVKind = "uv";
         private static _UVKind = "uv";
         private static _UV2Kind = "uv2";
         private static _UV2Kind = "uv2";
         private static _UV3Kind = "uv3";
         private static _UV3Kind = "uv3";
@@ -174,6 +176,10 @@
             return VertexBuffer._NormalKind;
             return VertexBuffer._NormalKind;
         }
         }
 
 
+        public static get TangentKind(): string {
+            return VertexBuffer._TangentKind;
+        }
+
         public static get UVKind(): string {
         public static get UVKind(): string {
             return VertexBuffer._UVKind;
             return VertexBuffer._UVKind;
         }
         }

+ 3 - 3
src/Physics/babylon.physicsImpostor.ts

@@ -169,7 +169,7 @@ module BABYLON {
         public getObjectExtendSize(): Vector3 {
         public getObjectExtendSize(): Vector3 {
             if (this.object.getBoundingInfo) {
             if (this.object.getBoundingInfo) {
                 this.object.computeWorldMatrix && this.object.computeWorldMatrix(true);
                 this.object.computeWorldMatrix && this.object.computeWorldMatrix(true);
-                return this.object.getBoundingInfo().boundingBox.extendSize.scale(2).multiply(this.object.scaling)
+                return this.object.getBoundingInfo().boundingBox.extendSizeWorld.scale(2).multiply(this.object.scaling)
             } else {
             } else {
                 return PhysicsImpostor.DEFAULT_OBJECT_SIZE;
                 return PhysicsImpostor.DEFAULT_OBJECT_SIZE;
             }
             }
@@ -177,7 +177,7 @@ module BABYLON {
 
 
         public getObjectCenter(): Vector3 {
         public getObjectCenter(): Vector3 {
             if (this.object.getBoundingInfo) {
             if (this.object.getBoundingInfo) {
-                return this.object.getBoundingInfo().boundingBox.center;
+                return this.object.getBoundingInfo().boundingBox.centerWorld;
             } else {
             } else {
                 return this.object.position;
                 return this.object.position;
             }
             }
@@ -327,7 +327,7 @@ module BABYLON {
         /**
         /**
          * Legacy collision detection event support
          * Legacy collision detection event support
          */
          */
-        public onCollideEvent: (collider:BABYLON.PhysicsImpostor, collidedWith:BABYLON.PhysicsImpostor) => void = null;
+        public onCollideEvent: (collider: BABYLON.PhysicsImpostor, collidedWith: BABYLON.PhysicsImpostor) => void = null;
 
 
         //event and body object due to cannon's event-based architecture.
         //event and body object due to cannon's event-based architecture.
         public onCollide = (e: { body: any }) => {
         public onCollide = (e: { body: any }) => {

+ 1 - 1
src/PostProcess/babylon.fxaaPostProcess.ts

@@ -4,7 +4,7 @@
         public texelHeight: number;
         public texelHeight: number;
 
 
         constructor(name: string, options: number | PostProcessOptions, camera: Camera, samplingMode?: number, engine?: Engine, reusable?: boolean) {
         constructor(name: string, options: number | PostProcessOptions, camera: Camera, samplingMode?: number, engine?: Engine, reusable?: boolean) {
-            super(name, "fxaa", ["texelSize"], null, options, camera, samplingMode, engine, reusable);
+            super(name, "fxaa", ["texelSize"], null, options, camera, samplingMode || BABYLON.Texture.BILINEAR_SAMPLINGMODE, engine, reusable);
 
 
             this.onSizeChangedObservable.add(() => {
             this.onSizeChangedObservable.add(() => {
                 this.texelWidth = 1.0 / this.width;
                 this.texelWidth = 1.0 / this.width;

+ 2 - 2
src/PostProcess/babylon.passPostProcess.ts

@@ -1,7 +1,7 @@
 module BABYLON {
 module BABYLON {
     export class PassPostProcess extends PostProcess {
     export class PassPostProcess extends PostProcess {
-        constructor(name: string, options: number | PostProcessOptions, camera: Camera, samplingMode?: number, engine?: Engine, reusable?: boolean) {
-            super(name, "pass", null, null, options, camera, samplingMode, engine, reusable);
+        constructor(name: string, options: number | PostProcessOptions, camera: Camera, samplingMode?: number, engine?: Engine, reusable?: boolean, textureType: number = Engine.TEXTURETYPE_UNSIGNED_INT) {
+            super(name, "pass", null, null, options, camera, samplingMode, engine, reusable, null, textureType);
         }
         }
     }
     }
 } 
 } 

+ 6 - 2
src/Shaders/ShadersInclude/bumpFragment.fx

@@ -1,7 +1,11 @@
 vec2 uvOffset = vec2(0.0, 0.0);
 vec2 uvOffset = vec2(0.0, 0.0);
 
 
 #if defined(BUMP) || defined(PARALLAX)
 #if defined(BUMP) || defined(PARALLAX)
-	mat3 TBN = cotangent_frame(normalW * vBumpInfos.y, -viewDirectionW, vBumpUV);
+	#if defined(TANGENT) && defined(NORMAL)
+		mat3 TBN = vTBN;
+	#else
+		mat3 TBN = cotangent_frame(normalW * vBumpInfos.y, vPositionW, vBumpUV);
+	#endif
 #endif
 #endif
 
 
 #ifdef PARALLAX
 #ifdef PARALLAX
@@ -15,5 +19,5 @@
 #endif
 #endif
 
 
 #ifdef BUMP
 #ifdef BUMP
-	normalW = perturbNormal(viewDirectionW, TBN, vBumpUV + uvOffset);
+	normalW = perturbNormal(TBN, vBumpUV + uvOffset);
 #endif
 #endif

+ 7 - 1
src/Shaders/ShadersInclude/bumpFragmentFunctions.fx

@@ -2,10 +2,16 @@
 	varying vec2 vBumpUV;
 	varying vec2 vBumpUV;
 	uniform vec3 vBumpInfos;
 	uniform vec3 vBumpInfos;
 	uniform sampler2D bumpSampler;
 	uniform sampler2D bumpSampler;
+#if defined(TANGENT) && defined(NORMAL) 
+	varying mat3 vTBN;
+#endif
 
 
 	// Thanks to http://www.thetenthplanet.de/archives/1180
 	// Thanks to http://www.thetenthplanet.de/archives/1180
 	mat3 cotangent_frame(vec3 normal, vec3 p, vec2 uv)
 	mat3 cotangent_frame(vec3 normal, vec3 p, vec2 uv)
 	{
 	{
+		// flip the uv for the backface
+		uv = gl_FrontFacing ? uv : -uv;
+
 		// get edge vectors of the pixel triangle
 		// get edge vectors of the pixel triangle
 		vec3 dp1 = dFdx(p);
 		vec3 dp1 = dFdx(p);
 		vec3 dp2 = dFdy(p);
 		vec3 dp2 = dFdy(p);
@@ -23,7 +29,7 @@
 		return mat3(tangent * invmax, binormal * invmax, normal);
 		return mat3(tangent * invmax, binormal * invmax, normal);
 	}
 	}
 
 
-	vec3 perturbNormal(vec3 viewDir, mat3 cotangentFrame, vec2 uv)
+	vec3 perturbNormal(mat3 cotangentFrame, vec2 uv)
 	{
 	{
 		vec3 map = texture2D(bumpSampler, uv).xyz;
 		vec3 map = texture2D(bumpSampler, uv).xyz;
 
 

+ 8 - 0
src/Shaders/ShadersInclude/bumpVertex.fx

@@ -0,0 +1,8 @@
+#if defined(BUMP) || defined(PARALLAX)
+	#if defined(TANGENT) && defined(NORMAL)
+		vec3 normalW = normalize(vec3(finalWorld * vec4(normal, 0.0)));
+		vec3 tangentW = normalize(vec3(finalWorld * vec4(tangent.xyz, 0.0)));
+		vec3 bitangentW = cross(normalW, tangentW) * tangent.w;
+		vTBN = mat3(tangentW, bitangentW, normalW);
+	#endif
+#endif

+ 5 - 0
src/Shaders/ShadersInclude/bumpVertexDeclaration.fx

@@ -0,0 +1,5 @@
+#if defined(BUMP) || defined(PARALLAX)
+	#if defined(TANGENT) && defined(NORMAL) 
+		varying mat3 vTBN;
+	#endif
+#endif

+ 0 - 0
src/Shaders/ShadersInclude/lightFragment.fx


Some files were not shown because too many files changed in this diff