浏览代码

merged with master

Benjamin Guignabert 8 年之前
父节点
当前提交
09e3fef5b2
共有 100 个文件被更改,包括 11630 次插入7897 次删除
  1. 1684 545
      Exporters/3ds Max/ActionsBuilder/Sources/babylon.max.js
  2. 2 2
      Exporters/3ds Max/BabylonExport.Entities/BabylonShadowGenerator.cs
  3. 二进制
      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. 二进制
      Playground/textures/babylonjs.mp4
  13. 二进制
      Playground/textures/babylonjs.webm
  14. 11 2
      Tools/Gulp/config.json
  15. 二进制
      assets/sounds/explosion.wav
  16. 二进制
      assets/sounds/jump.wav
  17. 二进制
      assets/textures/Ground.jpg
  18. 二进制
      assets/textures/babylonjs.mp4
  19. 二进制
      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

文件差异内容过多而无法显示
+ 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; }
 
         [DataMember]
-        public bool useVarianceShadowMap { get; set; }
+        public bool useExponentialShadowMap { get; set; }
 
         [DataMember]
         public bool usePoissonSampling { get; set; }
 
         [DataMember]
-        public bool useBlurVarianceShadowMap { get; set; }
+        public bool useBlurExponentialShadowMap { get; set; }
 
         [DataMember]
         public float darkness { get; set; }

二进制
Exporters/3ds Max/Max2Babylon-0.7.0.zip


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

@@ -23,7 +23,7 @@
     <DebugSymbols>true</DebugSymbols>
     <DebugType>full</DebugType>
     <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>
     <ErrorReport>prompt</ErrorReport>
     <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.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)
             {
@@ -29,11 +29,11 @@ namespace Max2Babylon
                 case "Poisson Sampling":
                     babylonShadowGenerator.usePoissonSampling = true;
                     break;
-                case "Variance":
-                    babylonShadowGenerator.useVarianceShadowMap = true;
+                case "ESM":
+                    babylonShadowGenerator.useExponentialShadowMap = true;
                     break;
-                case"Blurred Variance":
-                    babylonShadowGenerator.useBlurVarianceShadowMap = true;
+                case"Blurred ESM":
+                    babylonShadowGenerator.useBlurExponentialShadowMap = true;
                     babylonShadowGenerator.blurScale = lightNode.GetFloatProperty("babylonjs_shadows_blurScale", 2);
                     babylonShadowGenerator.blurBoxOffset = lightNode.GetFloatProperty("babylonjs_shadows_blurBoxOffset", 1);
                     break;

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

@@ -310,7 +310,7 @@
             // label6
             // 
             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.Size = new System.Drawing.Size(34, 13);
             this.label6.TabIndex = 6;
@@ -319,7 +319,6 @@
             // cbCameraType
             // 
             this.cbCameraType.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
-            this.cbCameraType.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
             this.cbCameraType.FormattingEnabled = true;
             this.cbCameraType.Items.AddRange(new object[] {
             "AnaglyphArcRotateCamera",

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

@@ -324,7 +324,7 @@
             // label6
             // 
             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.Size = new System.Drawing.Size(34, 13);
             this.label6.TabIndex = 8;
@@ -342,13 +342,12 @@
             // cbCameraType
             // 
             this.cbCameraType.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
-            this.cbCameraType.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
             this.cbCameraType.FormattingEnabled = true;
             this.cbCameraType.Items.AddRange(new object[] {
             "Hard shadows",
             "Poisson Sampling",
-            "Variance",
-            "Blurred Variance"});
+            "ESM",
+            "Blurred ESM"});
             this.cbCameraType.Location = new System.Drawing.Point(21, 108);
             this.cbCameraType.Name = "cbCameraType";
             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(nupBlurScale, lights, "babylonjs_shadows_blurScale", 2);
             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)

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

@@ -412,7 +412,7 @@
             // label6
             // 
             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.Size = new System.Drawing.Size(50, 13);
             this.label6.TabIndex = 8;
@@ -421,7 +421,6 @@
             // cbImpostor
             // 
             this.cbImpostor.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
-            this.cbImpostor.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
             this.cbImpostor.FormattingEnabled = true;
             this.cbImpostor.Items.AddRange(new object[] {
             "None",
@@ -681,7 +680,6 @@
             // cbDistanceModel
             // 
             this.cbDistanceModel.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
-            this.cbDistanceModel.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
             this.cbDistanceModel.FormattingEnabled = true;
             this.cbDistanceModel.Items.AddRange(new object[] {
             "linear",

+ 13 - 13
Exporters/Blender/io_export_babylon.py

@@ -100,8 +100,8 @@ HEMI_LIGHT = 3
 NO_SHADOWS = 'NONE'
 STD_SHADOWS = 'STD'
 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
 CLAMP_ADDRESSMODE = 0
@@ -1656,12 +1656,12 @@ class ShadowGenerator:
         self.mapSize = lamp.data.shadowMapSize
         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:
             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.shadowBlurBoxOffset = lamp.data.shadowBlurBoxOffset
 
@@ -1677,12 +1677,12 @@ class ShadowGenerator:
         write_string(file_handler, 'lightId', self.lightId)
         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'):
             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, 'blurBoxOffset', self.shadowBlurBoxOffset)
 
@@ -2713,8 +2713,8 @@ bpy.types.Lamp.shadowMap = bpy.props.EnumProperty(
     items = ((NO_SHADOWS           , 'None'         , 'No Shadow Maps'),
              (STD_SHADOWS          , 'Standard'     , 'Use Standard Shadow Maps'),
              (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
 )
@@ -2809,7 +2809,7 @@ class ObjectPanel(bpy.types.Panel):
             layout.prop(ob.data, 'shadowBias')
 
             box = layout.box()
-            box.label(text="Blur Variance Shadows")
+            box.label(text="Blur ESM Shadows")
             box.prop(ob.data, 'shadowBlurScale')
             box.prop(ob.data, 'shadowBlurBoxOffset')
 

+ 1 - 1
Playground/scripts/shadows.js

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

二进制
Playground/textures/babylonjs.mp4


二进制
Playground/textures/babylonjs.webm


+ 11 - 2
Tools/Gulp/config.json

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

二进制
assets/sounds/explosion.wav


二进制
assets/sounds/jump.wav


二进制
assets/textures/Ground.jpg


二进制
assets/textures/babylonjs.mp4


二进制
assets/textures/babylonjs.webm


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

@@ -156,7 +156,7 @@
             this._engine = engine;
             this._renderingSize = new Size(0, 0);
             this._curHWScale = 0;
-            this._canvasLevelScale = new Vector3(1, 1, 1);
+            this._canvasLevelScale = new Vector2(1, 1);
             this._designSize = settings.designSize || null;
             this._designUseHorizAxis = settings.designUseHorizAxis === true;
             if (!this._trackedGroups) {
@@ -359,9 +359,7 @@
                     if (this.isVisible === false) {
                         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 {
-            let s = this.scale;
+            let s = this._canvasLevelScale.multiplyByFloats(this.scaleX, this.scaleY);
             let pii = this._primPointerInfo;
             pii.cancelBubble = false;
             if (!pii.canvasPointerPos) {
@@ -570,17 +568,20 @@
 
             if (this._isScreenSpace) {
                 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
                 var x = localPosition.x - viewport.x;
                 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 {
-                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}`);
             pii.mouseWheelDelta = 0;
@@ -830,13 +831,13 @@
 
                             if (ii.isPrimIntersected(prim) !== null) {
                                 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;
                                         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);
 
                     // 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);
                     }
                 }
@@ -1320,7 +1321,7 @@
         private _designUseHorizAxis: boolean;
         public  _primitiveCollisionManager: PrimitiveCollisionManagerBase;
 
-        public _canvasLevelScale: Vector3;
+        public _canvasLevelScale: Vector2;
         public  _renderingSize: Size;
         private _curHWScale;
 
@@ -1342,6 +1343,7 @@
         private _profileInfoText: Text2D;
 
         private static _v = Vector3.Zero(); // Must stay zero
+        private static _cv1 = Vector2.Zero(); // Must stay zero
         private static _m = Matrix.Identity();
         private static _mI = Matrix.Identity(); // Must stay identity
         private static tS = Vector3.Zero();
@@ -1383,8 +1385,8 @@
                 group.levelVisible = proj.z >= 0 && proj.z < 1.0;
 
                 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
@@ -1481,7 +1483,7 @@
                 this._setRenderingScale(scale);
             }
         }
-        private static _pCLS = Vector3.Zero();
+        private static _pCLS = Vector2.Zero();
 
         private _updateCanvasState(forceRecompute: boolean) {
             // Check if the update has already been made for this render Frame
@@ -1519,10 +1521,10 @@
                     scale = this._renderingSize.height / (this._designSize.height * hwsl);
                 }
                 this.size = this._designSize.clone();
-                this._canvasLevelScale.copyFromFloats(scale, scale, 1);
+                this._canvasLevelScale.copyFromFloats(scale, scale);
             } else {
                 let ratio = 1 / this._curHWScale;
-                this._canvasLevelScale.copyFromFloats(ratio, ratio, 1);
+                this._canvasLevelScale.copyFromFloats(ratio, ratio);
             }
 
             if (!prevCLS.equals(this._canvasLevelScale)) {
@@ -1627,18 +1629,19 @@
             let isCanvas = parent == null;
             let scale: Vector2;
             if (noResizeScale) {
-                scale = isCanvas ? Canvas2D._unS : group.parent.actualScale;
+                scale = isCanvas ? Canvas2D._unS : group.parent.actualScale.multiply(this._canvasLevelScale);
             } else {
-                scale = group.actualScale;
+                scale = group.actualScale.multiply(this._canvasLevelScale);
             }
 
             // Determine size
             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) {
-                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>());
@@ -1648,7 +1651,7 @@
             var map: MapTexture;
             for (var _map of mapArray) {
                 map = _map;
-                let node = map.allocateRect(size);
+                let node = map.allocateRect(roundedScaledSize);
                 if (node) {
                     res = { node: node, texture: map }
                     break;
@@ -1660,18 +1663,24 @@
                 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
-                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}`;
-                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.anisotropicFilteringLevel = 4;
                 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 }
             }
 
@@ -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)
             if (group !== <any>this || this._isScreenSpace) {
                 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
 
@@ -1688,14 +1699,14 @@
                         this._cachedCanvasGroup.dispose();
                     }
                     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.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
                 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.addExternalData("__cachedGroup__", group);
                     sprite.pointerEventObservable.add((e, s) => {

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

@@ -427,18 +427,18 @@
                 return false;
             }
 
-            let s = Ellipse2D._riv0;
-            this.getActualGlobalScaleToRef(s);
+            //let s = Ellipse2D._riv0;
+            //this.getActualGlobalScaleToRef(s);
 
             if (part.id === Shape2D.SHAPE2D_BORDERPARTID) {
                 let d = <Ellipse2DInstanceData>part;
                 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) {
                 let d = <Ellipse2DInstanceData>part;
                 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;
         }

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

@@ -415,6 +415,7 @@
             this._signedDistanceField = signedDistanceField;
             this._superSample = false;
             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
             if (superSample || signedDistanceField) {
@@ -556,7 +557,7 @@
             var textureSize = this.getSize();
 
             // 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) {
                 this._currentFreePosition.x = 0;
                 this._currentFreePosition.y += Math.ceil(this._lineHeightSuper + this._yMargin*2);
@@ -626,9 +627,10 @@
             }
 
             // 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;
+            //console.log(`Char: ${char}, Offset: ${curPosX}, ${this._currentFreePosition.y + this._yMargin}, Size: ${width}, ${this._lineHeightSuper}, UV: ${info.topLeftUV}, ${info.bottomRightUV}`);
 
             if (this._signedDistanceField) {
                 let off = 1/textureSize.width;

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

@@ -357,9 +357,12 @@
 
             let s = this.actualSize;
             let a = this.actualScale;
+            let ss = this.owner._canvasLevelScale;
             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.
             // 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 _s = Size.Zero();
+        private static _v1 = Vector2.Zero();
+        private static _s2 = Size.Zero();
         private _bindCacheTarget() {
             let curWidth: number;
             let curHeight: number;
@@ -813,11 +818,11 @@
             let isCanvas = this.parent == null;
             let scale: Vector2;
             if (noResizeScale) {
-                scale = isCanvas ? Group2D._uV: this.parent.actualScale;
+                scale = isCanvas ? Group2D._uV: this.parent.actualScale.multiply(this.owner._canvasLevelScale);
             } 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(this.owner.designSize || this.owner.fitRenderingDevice){
                     Group2D._s.width = this.owner.engine.getRenderWidth();
@@ -827,14 +832,15 @@
                     Group2D._s.copyFrom(this.owner.size);
                 }
             } 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);
 
             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
                 if ((size.width < Group2D._s.width) || (size.height < Group2D._s.height)) {
@@ -859,6 +865,12 @@
                 }
                 rd._cacheRenderSprite = res.sprite;
                 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) {
@@ -871,8 +883,9 @@
                 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() {
@@ -924,6 +937,11 @@
                 case Group2D.actualSizeProperty.id:
                     cachedSprite.size = this.actualSize.clone();
                     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 {
         constructor(owner: Group2D, mrc: ModelRenderCache, partCount: number) {
             this._partCount = partCount;
+            this._primCount = 0;
             this.owner = owner;
             this.modelRenderCache = mrc;
             this.modelRenderCache.addRef();
@@ -18,11 +19,26 @@
             this.opaqueDirty = this.alphaTestDirty = this.transparentDirty = this.transparentOrderDirty = false;
         }
 
+        public incPrimCount() {
+            ++this._primCount;
+        }
+
         public dispose(): boolean {
             if (this._isDisposed) {
                 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) {
                 this.modelRenderCache.dispose();
                 this.modelRenderCache = null;
@@ -130,6 +146,7 @@
         }
 
         private _partCount: number;
+        private _primCount: number;
         private _strides: number[];
         private _usedShaderCategories: string[];
         private _opaqueData: GroupInfoPartData[];

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

@@ -1195,8 +1195,8 @@
                             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) {
                             dstArea.width = (width * isx) + (this.leftPixels + this.rightPixels) * isx;
@@ -1295,8 +1295,8 @@
                             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) {
                             dstArea.height = (height * isy) + (bottomPixels + topPixels) * isy;
@@ -2037,7 +2037,7 @@
             //    return;
             //}
             if (this._checkUseMargin()) {
-                switch (this._marginAlignment.horizontal) {
+                switch (this.marginAlignment.horizontal) {
                     case PrimitiveAlignment.AlignLeft:
                     case PrimitiveAlignment.AlignStretch:
                     case PrimitiveAlignment.AlignCenter:
@@ -2047,7 +2047,7 @@
                         this.margin.rightPixels = value.x;
                         break;
                     }
-                switch (this._marginAlignment.vertical) {
+                switch (this.marginAlignment.vertical) {
                     case PrimitiveAlignment.AlignBottom:
                     case PrimitiveAlignment.AlignStretch:
                     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`);
             }
             if (this._checkUseMargin()) {
-                switch (this._marginAlignment.horizontal) {
+                switch (this.marginAlignment.horizontal) {
                     case PrimitiveAlignment.AlignLeft:
                     case PrimitiveAlignment.AlignStretch:
                     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`);
             }
             if (this._checkUseMargin()) {
-                switch (this._marginAlignment.vertical) {
+                switch (this.marginAlignment.vertical) {
                     case PrimitiveAlignment.AlignBottom:
                     case PrimitiveAlignment.AlignStretch:
                     case PrimitiveAlignment.AlignCenter:
@@ -2746,7 +2746,7 @@
          */
         public getActualGlobalScaleToRef(res: Vector2) {
             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.y = as.y * cls.y;
         }
@@ -3027,7 +3027,9 @@
                 }
 
                 if (this._isFlagSet(SmartPropertyPrim.flagLayoutDirty)) {
-                    this.owner.addUpdateLayoutCounter(1);
+                    if (this._owner) {
+                        this._owner.addUpdateLayoutCounter(1);
+                    }
                     this._layoutEngine.updateLayout(this);
 
                     this._clearFlags(SmartPropertyPrim.flagLayoutDirty);
@@ -3459,6 +3461,9 @@
                 try {
                     Prim2DBase._bypassGroup2DExclusion = true;
                     let ownerGroup = this.getExternalData<Group2D>("__cachedGroup__");
+                    if (!ownerGroup) {
+                        return false;
+                    }
                     return ownerGroup.intersect(intersectInfo);
                 } finally  {
                     Prim2DBase._bypassGroup2DExclusion = false;
@@ -3633,6 +3638,7 @@
             }
             let length = this._children.push(child);
             this._firstZDirtyIndex = Math.min(this._firstZDirtyIndex, length - 1);
+            child._setFlags(SmartPropertyPrim.flagActualOpacityDirty);
         }
 
         /**
@@ -3824,9 +3830,9 @@
         private static _t0: Matrix2D = new Matrix2D();
         private static _t1: 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 _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 _updateLocalTransform(): boolean {
@@ -3846,12 +3852,12 @@
                 var local: Matrix2D;
                 let pos = this._position ? this.position : (this.layoutAreaPos || Prim2DBase._v0);
                 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);
 
                 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);
                     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);
                 }

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

@@ -593,18 +593,18 @@
                 return false;
             }
 
-            let s = Rectangle2D._riv0;
-            this.getActualGlobalScaleToRef(s);
+            //let s = Rectangle2D._riv0;
+            //this.getActualGlobalScaleToRef(s);
 
             if (part.id === Shape2D.SHAPE2D_BORDERPARTID) {
                 let d = <Rectangle2DInstanceData>part;
                 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) {
                 let d = <Rectangle2DInstanceData>part;
                 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;
         }

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

@@ -451,28 +451,19 @@
                 gii = part.groupInstanceInfo;
                 part.groupInstanceInfo = null;
             }
-            if (gii && !gii.isDisposed) {
-                let usedCount = 0;
+
+            if (gii) {
                 if (gii.hasOpaqueData) {
-                    let od = gii.opaqueData[0];
-                    usedCount += od._partData.usedElementCount;
                     gii.opaqueDirty = true;
                 }
                 if (gii.hasAlphaTestData) {
-                    let atd = gii.alphaTestData[0];
-                    usedCount += atd._partData.usedElementCount;
                     gii.alphaTestDirty = true;
                 }
                 if (gii.hasTransparentData) {
-                    let td = gii.transparentData[0];
-                    usedCount += td._partData.usedElementCount;
                     gii.transparentDirty = true;
                 }
 
-                if (usedCount === 0 && gii.modelRenderCache!=null) {
-                    this.renderGroup._renderableData._renderGroupInstancesInfo.remove(gii.modelRenderCache.modelKey);
-                    gii.dispose();
-                }
+                gii.dispose();
 
                 if (this._modelRenderCache) {
                     this._modelRenderCache.dispose();
@@ -480,6 +471,7 @@
                 }
 
             }
+
             this._instanceDataParts = null;
         }
 
@@ -597,6 +589,9 @@
                 part.groupInstanceInfo = gii;
             }
 
+            // Increment the primitive count as one more primitive is using this GroupInstanceInfo
+            gii.incPrimCount();
+
             return gii;
         }
 
@@ -951,11 +946,15 @@
             let trn = RenderablePrim2D._t;
             let rot = t.decompose(scl, trn);
             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.y = pas.y * canvasScale.y * this._postScale.y;
+            trn.multiplyInPlace(canvasScale);
             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 zBias = this.actualZOffset;
 

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

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

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

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

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

@@ -77,13 +77,15 @@ void main(void) {
 		vUV.y = 1.0 - vUV.y;
 	}
 
+	//vUV.x += 0.5 / textureSize.x;
+
 	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;
-	}
+	//}
 
 #ifdef Scale9
 	if (invertY == 1.0) {
@@ -111,9 +113,9 @@ void main(void) {
 		float irw = 2.0 / rw;
 		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;
 	}
 #ifdef FontTexture
-	gl_FragColor = vec4(color.xxxx)*vColor;
+	gl_FragColor = vec4(color.xxx*vColor.xyz*vColor.a, vColor.a);
 #else
 	gl_FragColor = color*vColor;
 #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
-	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.a *= opacity;
 	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.w = 1.0;
 
@@ -70,9 +71,9 @@ void main(void) {
 		float irw = 2.0 / rw;
 		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);
 }

文件差异内容过多而无法显示
+ 29 - 30
dist/preview release/babylon.core.js


文件差异内容过多而无法显示
+ 3252 - 3166
dist/preview release/babylon.d.ts


文件差异内容过多而无法显示
+ 40 - 41
dist/preview release/babylon.js


文件差异内容过多而无法显示
+ 524 - 162
dist/preview release/babylon.max.js


文件差异内容过多而无法显示
+ 3252 - 3166
dist/preview release/babylon.module.d.ts


文件差异内容过多而无法显示
+ 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 _v0;
         private static _v30;
-        private static _iv3;
+        private static _iv2;
         private static _ts0;
         private _updateLocalTransform();
         private static _transMtx;
@@ -2621,6 +2621,7 @@ declare module BABYLON {
     }
     class GroupInstanceInfo {
         constructor(owner: Group2D, mrc: ModelRenderCache, partCount: number);
+        incPrimCount(): void;
         dispose(): boolean;
         readonly isDisposed: boolean;
         private _isDisposed;
@@ -2641,6 +2642,7 @@ declare module BABYLON {
         readonly usedShaderCategories: string[];
         readonly strides: number[];
         private _partCount;
+        private _primCount;
         private _strides;
         private _usedShaderCategories;
         private _opaqueData;
@@ -2850,7 +2852,6 @@ declare module BABYLON {
             borderThickness?: number;
         });
         protected getUsedShaderCategories(dataPart: InstanceDataBase): string[];
-        protected applyActualScaleOnTransform(): boolean;
         protected refreshInstanceDataPart(part: InstanceDataBase): boolean;
         private _updateTransparencyStatus();
         protected _mustUpdateInstance(): boolean;
@@ -3040,6 +3041,8 @@ declare module BABYLON {
         protected _setRenderingScale(scale: number): void;
         private static _uV;
         private static _s;
+        private static _v1;
+        private static _s2;
         private _bindCacheTarget();
         private _unbindCacheTarget();
         protected _spreadActualScaleDirty(): void;
@@ -3861,6 +3864,7 @@ declare module BABYLON {
         static fontSuperSampleProperty: Prim2DPropInfo;
         static fontSignedDistanceFieldProperty: Prim2DPropInfo;
         static textureIsPremulAlphaProperty: Prim2DPropInfo;
+        static fontTextureProperty: Prim2DPropInfo;
         /**
          * 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 _designUseHorizAxis;
         _primitiveCollisionManager: PrimitiveCollisionManagerBase;
-        _canvasLevelScale: Vector3;
+        _canvasLevelScale: Vector2;
         _renderingSize: Size;
         private _curHWScale;
         private _drawCallsOpaqueCounter;
@@ -4521,6 +4525,7 @@ declare module BABYLON {
         private _profilingCanvas;
         private _profileInfoText;
         private static _v;
+        private static _cv1;
         private static _m;
         private static _mI;
         private static tS;

文件差异内容过多而无法显示
+ 141 - 92
dist/preview release/canvas2D/babylon.canvas2d.js


文件差异内容过多而无法显示
+ 12 - 12
dist/preview release/canvas2D/babylon.canvas2d.min.js


文件差异内容过多而无法显示
+ 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': {
             type: typeof BABYLON.FontTexture;
         };
+        'Sound': {
+            type: typeof BABYLON.Sound;
+            properties: string[];
+        };
         'ArcRotateCamera': {
             type: typeof BABYLON.ArcRotateCamera;
             properties: string[];
@@ -224,6 +228,20 @@ 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 {
         constructor(obj: BABYLON.BaseTexture);
         /** Returns the name displayed in the tree */
@@ -702,6 +720,13 @@ 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 {
         private _inspector;
         /** The panel containing a list of items */
@@ -1087,6 +1112,22 @@ 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
      * provide methods to toggle its visibility
      */

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

@@ -112,7 +112,6 @@ var INSPECTOR;
                 else {
                     inspector = INSPECTOR.Helpers.CreateDiv('insp-right-panel', this._c2diwrapper);
                 }
-                console.log(inspector);
                 // Add split bar
                 if (!this._parentElement) {
                     Split([canvas, inspector], {
@@ -370,6 +369,23 @@ var INSPECTOR;
         'FontTexture': {
             type: BABYLON.FontTexture
         },
+        'Sound': {
+            type: BABYLON.Sound,
+            properties: [
+                'name',
+                'autoplay',
+                'loop',
+                'useCustomAttenuation',
+                'soundTrackId',
+                'spatialSound',
+                'refDistance',
+                'rolloffFactor',
+                'maxDistance',
+                'distanceModel',
+                'isPlaying',
+                'isPaused'
+            ]
+        },
         'ArcRotateCamera': {
             type: BABYLON.ArcRotateCamera,
             properties: [
@@ -725,6 +741,66 @@ var __extends = (this && this.__extends) || function (d, b) {
 };
 var 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) {
         __extends(TextureAdapter, _super);
         function TextureAdapter(obj) {
@@ -1827,8 +1903,6 @@ var INSPECTOR;
     INSPECTOR.HDRCubeTextureElement = HDRCubeTextureElement;
 })(INSPECTOR || (INSPECTOR = {}));
 
-//# sourceMappingURL=HDRCubeTextureElement.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; }
@@ -2380,6 +2454,38 @@ var __extends = (this && this.__extends) || function (d, b) {
 };
 var 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) {
         __extends(TextureTab, _super);
         function TextureTab(tabbar, inspector) {
@@ -3415,6 +3521,7 @@ var INSPECTOR;
             }
             _this._tabs.push(new INSPECTOR.MaterialTab(_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._build();
             //Check initialTab is defined and between tabs bounds
@@ -4273,6 +4380,49 @@ var __extends = (this && this.__extends) || function (d, b) {
 var 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
      */
     var Checkbox = (function (_super) {

文件差异内容过多而无法显示
+ 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

文件差异内容过多而无法显示
+ 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
  - 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))
+ - 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 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))
@@ -16,6 +17,9 @@
  - All deprecated functions and properties were removed ([deltakosh](https://github.com/deltakosh))
 
 ### 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 `set()` function to all basic types ([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))   
 - 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 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 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))  
@@ -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 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))
-- 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
 - Fixed a bug with spotlight direction ([deltakosh](https://github.com/deltakosh)) 

+ 0 - 1
inspector/src/Inspector.ts

@@ -160,7 +160,6 @@ module INSPECTOR {
                 else {
                     inspector = Helpers.CreateDiv('insp-right-panel', this._c2diwrapper);
                 }
-                console.log(inspector);
 
                 // Add split bar
                 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
         },
 
+        'Sound': {
+            type: BABYLON.Sound,
+            properties: [
+                'name',
+                'autoplay',
+                'loop',
+                'useCustomAttenuation',
+                'soundTrackId',
+                'spatialSound',
+                'refDistance',
+                'rolloffFactor',
+                'maxDistance',
+                'distanceModel',
+                'isPlaying',
+                'isPaused'
+            ]
+        },
+
         'ArcRotateCamera': {
             type: BABYLON.ArcRotateCamera,
             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 CameraTab(this, this._inspector));
+            this._tabs.push(new SoundTab(this, 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;
         */
 
+        //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 sphere2 = BABYLON.Mesh.CreateSphere("Sphere2", 2.0, 9.0, scene);//Only two segments
         var sphere3 = BABYLON.Mesh.CreateSphere("Sphere3", 10.0, 9.0, scene);
@@ -181,6 +191,8 @@ var Test = (function () {
 
         plane.material = materialPlane;
 
+
+
         var d = 50;
         var cubes = new Array();
         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
         * 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;
         }
 
@@ -72,12 +72,12 @@ module BABYLON {
         // 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 => {
                 return loaderExtension.loadRuntimeAsync(scene, data, rootUrl, onSuccess, onError);
             }, () => {
                 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;
-};

文件差异内容过多而无法显示
+ 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 SHADOW3 = 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 SHADOWPCF1 = false;
         public SHADOWPCF2 = false;

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

@@ -32,10 +32,10 @@ module BABYLON {
         public SHADOW2 = false;
         public SHADOW3 = 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 SHADOWPCF1 = false;
         public SHADOWPCF2 = false;

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

@@ -32,10 +32,10 @@ module BABYLON {
         public SHADOW2 = false;
         public SHADOW3 = 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 SHADOWPCF1 = false;
         public SHADOWPCF2 = false;

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

@@ -1,6 +1,10 @@
 module BABYLON {
     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 poleTargetMesh: AbstractMesh;
         public poleTargetBone: Bone;
@@ -22,15 +26,6 @@ module BABYLON {
         private _maxAngle = Math.PI;
         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 _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._bone1 = bone.getParent();
@@ -160,14 +166,14 @@ module BABYLON {
 
         }
 
-        public update (): void {
+        public update(): void {
 	
             var bone1 = this._bone1;
             var target = this.targetPosition;
             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){
                 target.copyFrom(this.targetMesh.getAbsolutePosition());
@@ -179,11 +185,13 @@ module BABYLON {
                 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);
 
@@ -249,10 +257,12 @@ module BABYLON {
 
             } 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);
                 
             }
@@ -266,8 +276,8 @@ module BABYLON {
                 if(!this._slerping){
                     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;
                 this._bone1.setRotationQuaternion(this._bone1Quat, Space.WORLD, this.mesh);
                 this._slerping = true;

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

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

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

@@ -31,9 +31,11 @@ module BABYLON {
     }
 
     export interface WebVROptions {
-        trackPosition?: boolean; //update the camera's position
+        trackPosition?: boolean; //for the sake of your users - set it to true.
         positionScale?: number;
         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 {
@@ -51,6 +53,8 @@ module BABYLON {
 
         private _positionOffset: Vector3 = Vector3.Zero();
 
+        protected _descendants: Array<Node> = [];
+
         public devicePosition = Vector3.Zero();
         public deviceRotationQuaternion;
         public deviceScaleFactor: number = 1;
@@ -58,9 +62,29 @@ module BABYLON {
         public controllers: Array<WebVRController> = [];
         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);
 
+            //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.deviceRotationQuaternion = new Quaternion();
 
@@ -110,6 +134,39 @@ module BABYLON {
 
             // try to attach the controllers, if found.
             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 {
@@ -179,6 +236,16 @@ module BABYLON {
             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' is the left or right camera (and NOT (!!!) the WebVRFreeCamera instance)
@@ -186,17 +253,18 @@ module BABYLON {
         protected _getWebVRViewMatrix(): Matrix {
             var viewArray = this._cameraRigParams["left"] ? this._cameraRigParams["frameData"].leftViewMatrix : this._cameraRigParams["frameData"].rightViewMatrix;
 
+            Matrix.FromArrayToRef(viewArray, 0, this._webvrViewMatrix);
+
             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"];
 
             // 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();
                 // scale the position, if set
                 if (parentCamera.deviceScaleFactor) {
@@ -204,49 +272,29 @@ module BABYLON {
                     this._webvrViewMatrix.m[13] *= 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._updateCameraRotationMatrix();
+            // update the camera rotation matrix
+            this._webvrViewMatrix.getRotationMatrixToRef(this._cameraRotationMatrix);
             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;
         }
 
-        public _updateWebVRCameraRotationMatrix() {
-            this._webvrViewMatrix.getRotationMatrixToRef(this._cameraRotationMatrix);
-        }
-
-        public _isSynchronizedViewMatrix() {
-            return false;
-        }
-
         protected _getWebVRProjectionMatrix(): Matrix {
             var projectionArray = this._cameraRigParams["left"] ? this._cameraRigParams["frameData"].leftProjectionMatrix : this._cameraRigParams["frameData"].rightProjectionMatrix;
+            Matrix.FromArrayToRef(projectionArray, 0, this._projectionMatrix);
+
             //babylon compatible matrix
             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;
         }
 
@@ -255,6 +303,18 @@ module BABYLON {
             new BABYLON.Gamepads((gp) => {
                 if (gp.type === BABYLON.Gamepad.POSE_ENABLED) {
                     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);
 
                     // 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){
-                this._targetBoundingCenter = (<any>target).getBoundingInfo().boundingBox.center.clone();
+                this._targetBoundingCenter = (<any>target).getBoundingInfo().boundingBox.centerWorld.clone();
             }else{
                 this._targetBoundingCenter = null;
             }

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

@@ -618,9 +618,8 @@
                         this._rigCameras[0].setCameraRigParameter("parentCamera", rigParams.parentCamera);
                         this._rigCameras[0]._cameraRigParams.vrWorkMatrix = new Matrix();
                         this._rigCameras[0].getProjectionMatrix = this._getWebVRProjectionMatrix;
+                        this._rigCameras[0].parent = this;
                         this._rigCameras[0]._getViewMatrix = this._getWebVRViewMatrix;
-                        this._rigCameras[0]._isSynchronizedViewMatrix = this._isSynchronizedViewMatrix;
-                        this._rigCameras[0]._updateCameraRotationMatrix = this._updateWebVRCameraRotationMatrix;
 
                         //Right eye
                         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]._cameraRigParams.vrWorkMatrix = new Matrix();
                         this._rigCameras[1].getProjectionMatrix = this._getWebVRProjectionMatrix;
+                        this._rigCameras[1].parent = this;
                         this._rigCameras[1]._getViewMatrix = this._getWebVRViewMatrix;
-                        this._rigCameras[1]._isSynchronizedViewMatrix = this._isSynchronizedViewMatrix;
-                        this._rigCameras[1]._updateCameraRotationMatrix = this._updateWebVRCameraRotationMatrix;
                     }
                     break;
 

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

@@ -179,7 +179,7 @@ module BABYLON {
 
                 //rotate, if quaternion is set and rotation was used
                 if (this.rotationQuaternion) {
-                    var len = this.rotation.length();
+                    var len = this.rotation.lengthSquared();
                     if (len) {
                         Quaternion.RotationYawPitchRollToRef(this.rotation.y, this.rotation.x, this.rotation.z, this.rotationQuaternion);
                     }
@@ -302,7 +302,6 @@ module BABYLON {
                     break;
 
                 case Camera.RIG_MODE_VR:
-                case Camera.RIG_MODE_WEBVR:
                     if (camLeft.rotationQuaternion) {
                         camLeft.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 {
         public vectors: Vector3[] = new Array<Vector3>();
         public center: Vector3;
+        public centerWorld: Vector3;
         public extendSize: Vector3;
+        public extendSizeWorld: Vector3;
         public directions: Vector3[];
         public vectorsWorld: Vector3[] = new Array<Vector3>();
         public minimumWorld: Vector3;
         public maximumWorld: Vector3;
 
+
         private _worldMatrix: Matrix;
 
         constructor(public minimum: Vector3, public maximum: Vector3) {
@@ -44,6 +47,8 @@
             }
             this.minimumWorld = Vector3.Zero();
             this.maximumWorld = Vector3.Zero();
+            this.centerWorld = Vector3.Zero();
+            this.extendSizeWorld = Vector3.Zero();
 
             this._update(Matrix.Identity());
         }
@@ -81,9 +86,13 @@
                     this.maximumWorld.z = v.z;
             }
 
+            // Extend
+            this.maximumWorld.subtractToRef(this.minimumWorld, this.extendSizeWorld);
+            this.extendSizeWorld.scaleInPlace(0.5);
+
             // 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, 4, this.directions[1]);

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

@@ -1,6 +1,6 @@
 module BABYLON {
     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 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 _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) {
             this.ray = ray;
         }

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

@@ -7,25 +7,25 @@
  
     export class ShadowGenerator implements IShadowGenerator {
         private static _FILTER_NONE = 0;
-        private static _FILTER_VARIANCESHADOWMAP = 1;
+        private static _FILTER_EXPONENTIALSHADOWMAP = 1;
         private static _FILTER_POISSONSAMPLING = 2;
-        private static _FILTER_BLURVARIANCESHADOWMAP = 3;
+        private static _FILTER_BLUREXPONENTIALSHADOWMAP = 3;
 
         // Static
         public static get FILTER_NONE(): number {
             return ShadowGenerator._FILTER_NONE;
         }
 
-        public static get FILTER_VARIANCESHADOWMAP(): number {
-            return ShadowGenerator._FILTER_VARIANCESHADOWMAP;
-        }
-
         public static get FILTER_POISSONSAMPLING(): number {
             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
@@ -34,6 +34,7 @@
         private _blurBoxOffset = 0;
         private _bias = 0.00005;
         private _lightDirection = Vector3.Zero();
+        private _depthScale: number;
 
         public forceBackFacesOnly = false;
 
@@ -44,6 +45,7 @@
         public set bias(bias: number) {
             this._bias = bias;
         }
+
         public get blurBoxOffset(): number {
             return this._blurBoxOffset;
         }
@@ -59,12 +61,29 @@
                 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 => {
                 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 {
             return this._filter;
         }
@@ -76,7 +95,7 @@
 
             this._filter = value;
 
-            if (this.useVarianceShadowMap || this.useBlurVarianceShadowMap || this.usePoissonSampling) {
+            if (this.usePoissonSampling || this.useExponentialShadowMap || this.useBlurExponentialShadowMap) {
                 this._shadowMap.anisotropicFilteringLevel = 16;
                 this._shadowMap.updateSamplingMode(Texture.BILINEAR_SAMPLINGMODE);
             } else {
@@ -86,28 +105,47 @@
         }
 
         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) {
-            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 {
-            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) {
             this.filter = (value ? ShadowGenerator.FILTER_POISSONSAMPLING : ShadowGenerator.FILTER_NONE);
         }
 
         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) {
-            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;
@@ -167,7 +205,7 @@
             this._shadowMap.wrapU = Texture.CLAMP_ADDRESSMODE;
             this._shadowMap.wrapV = Texture.CLAMP_ADDRESSMODE;
             this._shadowMap.anisotropicFilteringLevel = 1;
-            this._shadowMap.updateSamplingMode(Texture.NEAREST_SAMPLINGMODE);
+            this._shadowMap.updateSamplingMode(Texture.BILINEAR_SAMPLINGMODE);
             this._shadowMap.renderParticles = false;
 
             this._shadowMap.onBeforeRenderObservable.add((faceIndex: number) => {
@@ -175,7 +213,7 @@
             });
 
             this._shadowMap.onAfterUnbindObservable.add(() => {
-                if (!this.useBlurVarianceShadowMap) {
+                if (!this.useBlurExponentialShadowMap) {
                     return;
                 }
 
@@ -183,9 +221,9 @@
                     this._shadowMap2 = new RenderTargetTexture(light.name + "_shadowMap", mapSize, this._scene, false, true, textureType);
                     this._shadowMap2.wrapU = 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 => {
                         effect.setTexture("textureSampler", this._shadowMap);
                     });
@@ -219,6 +257,8 @@
                     mesh._bind(subMesh, this._effect, Material.TriangleFillMode);
                     var material = subMesh.getMaterial();
 
+                    this._effect.setFloat2("biasAndScale", this.bias, this.depthScale);
+
                     this._effect.setMatrix("viewProjection", this.getTransformMatrix());
                     this._effect.setVector3("lightPosition", this.getLight().position);
 
@@ -274,7 +314,7 @@
             };
 
             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);
                 } else {
                     engine.clear(new Color4(1.0, 1.0, 1.0, 1.0), true, true, true);
@@ -291,8 +331,8 @@
                 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()) {
@@ -350,7 +390,7 @@
                 this._cachedDefines = join;
                 this._effect = this._scene.getEngine().createEffect("shadowMap",
                     attribs,
-                    ["world", "mBones", "viewProjection", "diffuseMatrix", "lightPosition", "depthValues"],
+                    ["world", "mBones", "viewProjection", "diffuseMatrix", "lightPosition", "depthValues", "biasAndScale"],
                     ["diffuseSampler"], join);
             }
 
@@ -481,7 +521,8 @@
 
             serializationObject.lightId = this._light.id;
             serializationObject.mapSize = this.getShadowMap().getRenderSize();
-            serializationObject.useVarianceShadowMap = this.useVarianceShadowMap;
+            serializationObject.useExponentialShadowMap = this.useExponentialShadowMap;
+            serializationObject.useBlurExponentialShadowMap = this.useBlurExponentialShadowMap;
             serializationObject.usePoissonSampling = this.usePoissonSampling;
             serializationObject.forceBackFacesOnly = this.forceBackFacesOnly;
             serializationObject.darkness = this.getDarkness();
@@ -512,20 +553,29 @@
 
             if (parsedShadowGenerator.usePoissonSampling) {
                 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) {
                 shadowGenerator.bias = parsedShadowGenerator.bias;
             }

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

@@ -17,6 +17,11 @@ module BABYLON {
 
         @serialize()
         public autoUpdateExtends = true;
+
+        @serialize()
+        public shadowMinZ: number;
+        @serialize()
+        public shadowMaxZ: number;
         
         public customProjectionMatrixBuilder: (viewMatrix: Matrix, renderList: Array<AbstractMesh>, result: Matrix) => void;
 
@@ -57,6 +62,14 @@ module BABYLON {
             this.direction = Vector3.Normalize(target.subtract(this.position));
             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.  
          * Returns the DirectionalLight.  
@@ -112,7 +125,7 @@ module BABYLON {
 
                 Matrix.OrthoOffCenterLHToRef(this._orthoLeft - xOffset * this.shadowOrthoScale, this._orthoRight + xOffset * 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;
         }
@@ -120,12 +133,6 @@ module BABYLON {
         /**
          * Boolean : true by default.  
          */
-        public supportsVSM(): boolean {
-            return true;
-        }
-        /**
-         * Boolean : true by default.  
-         */
         public needRefreshPerFrame(): boolean {
             return true;
         }

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

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

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

@@ -5,6 +5,11 @@
 
         @serializeAsVector3()
         public position: Vector3;
+
+        @serialize()
+        public shadowMinZ: number;
+        @serialize()
+        public shadowMaxZ: number;
         
         public customProjectionMatrixBuilder: (viewMatrix: Matrix, renderList: Array<AbstractMesh>, result: Matrix) => void;
 
@@ -79,12 +84,6 @@
         /**
          * Boolean : returns false by default.  
          */
-        public supportsVSM(): boolean {
-            return false;
-        }
-        /**
-         * Boolean : returns false by default.  
-         */
         public needRefreshPerFrame(): boolean {
             return false;
         }
@@ -110,6 +109,13 @@
 
             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 : 
@@ -123,7 +129,8 @@
                 this.customProjectionMatrixBuilder(viewMatrix, renderList, matrix);
             } else {
                 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;
         }

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

@@ -10,7 +10,12 @@
         public angle: number;
 
         @serialize()
-        public exponent: number
+        public exponent: number;
+        
+        @serialize()
+        public shadowMinZ: number;
+        @serialize()
+        public shadowMaxZ: number;
 
         public transformedPosition: Vector3;
 
@@ -49,6 +54,14 @@
         public getAbsolutePosition(): Vector3 {
             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.  
          * Returns the SpotLight.  
@@ -58,7 +71,8 @@
                 this.customProjectionMatrixBuilder(viewMatrix, renderList, matrix);
             } else {
                 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;
         }
@@ -69,12 +83,6 @@
             return false;
         }
         /**
-         * Boolean : true by default.  
-         */
-        public supportsVSM(): boolean {
-            return true;
-        }
-        /**
          * Boolean : false by default.  
          */
         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) === "/") {
                 Tools.Error("Wrong sceneFilename parameter");
                 return;
@@ -163,6 +163,13 @@
                     var particleSystems = [];
                     var skeletons = [];
 
+                    if (scene.isDisposed) {
+                        if (onerror) {
+                            onerror(scene, 'Scene was disposed before being able to load ' + rootUrl + sceneFilename);
+                        }
+                        return;
+                    }
+
                     try {
                         if ((<any>plugin).importMesh) {
                             var syncedPlugin = <ISceneLoaderPlugin>plugin;
@@ -209,7 +216,11 @@
 
                 Tools.LoadFile(rootUrl + sceneFilename, data => {
                     importMeshFromData(data);
-                }, progressCallBack, database, useArrayBuffer);
+                }, progressCallBack, database, useArrayBuffer, () => {
+                    if (onerror) {
+                        onerror(scene, 'Unable to load file ' + rootUrl + sceneFilename)
+                    }
+                });
             };
 
             if (scene.getEngine().enableOfflineSupport && !directLoad) {

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

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

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

@@ -85,17 +85,25 @@
                 minWidth: number, 
                 maxWidth: number, 
                 minHeight: number, 
-                maxHeight: number
+                maxHeight: number,
+                deviceId: string
             }): void {
             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;
 		    window.URL = window.URL || window.webkitURL || window.mozURL || window.msURL;
 
 
 		    if (navigator.getUserMedia) {
-			    navigator.getUserMedia({ 
+			    navigator.getUserMedia({                     
                     video: {
+                        deviceId: constraintsDeviceId,
                         width: {
                             min: (constraints && constraints.minWidth) || 256,
                             max: (constraints && constraints.maxWidth) || 640

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

@@ -84,20 +84,19 @@
 
                         defines["SHADOWS"] = true;
 
-                        if (shadowGenerator.useVarianceShadowMap || shadowGenerator.useBlurVarianceShadowMap) {
-                            if (defines["SHADOWVSM" + lightIndex] === undefined) {
-                                needRebuild = true;
-                            }
-
-                            defines["SHADOWVSM" + lightIndex] = true;
-                        }
-
                         if (shadowGenerator.usePoissonSampling) {
                             if (defines["SHADOWPCF" + lightIndex] === undefined) {
                                 needRebuild = true;
                             }
 
                             defines["SHADOWPCF" + lightIndex] = true;
+                        } 
+                        else if (shadowGenerator.useExponentialShadowMap || shadowGenerator.useBlurExponentialShadowMap) {
+                            if (defines["SHADOWESM" + lightIndex] === undefined) {
+                                needRebuild = true;
+                            }
+
+                            defines["SHADOWESM" + lightIndex] = true;
                         }
 
                         needShadows = true;
@@ -184,8 +183,8 @@
                     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.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;

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

@@ -21,6 +21,7 @@
         public EMISSIVEFRESNEL = false;
         public FRESNEL = false;
         public NORMAL = false;
+        public TANGENT = false;
         public UV1 = false;
         public UV2 = false;
         public VERTEXCOLOR = false;
@@ -41,7 +42,9 @@
         public REFLECTIONMAP_PROJECTION = false;
         public REFLECTIONMAP_SKYBOX = 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 LOGARITHMICDEPTH = false;
         public CAMERATONEMAP = false;
@@ -60,9 +63,9 @@
         public RADIANCEOVERALPHA = false;
         public USEPMREMREFLECTION = false;
         public USEPMREMREFRACTION = false;
-        public OPENGLNORMALMAP = false;
         public INVERTNORMALMAPX = false;
         public INVERTNORMALMAPY = false;
+        public TWOSIDEDLIGHTING = false;
         public SHADOWFULLFLOAT = false;
 
         public METALLICWORKFLOW = false;
@@ -486,6 +489,12 @@
         @serialize()
         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 _worldViewProjectionMatrix = Matrix.Zero();
         private _globalAmbientColor = new Color3(0, 0, 0);
@@ -732,6 +741,12 @@
                             case Texture.EQUIRECTANGULAR_MODE:
                                 this._defines.REFLECTIONMAP_EQUIRECTANGULAR = true;
                                 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)) {
@@ -845,6 +860,10 @@
                         this._defines.CAMERACOLORGRADING = true;
                     }
                 }
+
+                if (!this.backFaceCulling && this.twoSidedLighting) {
+                    this._defines.TWOSIDEDLIGHTING = true;
+                }
             }
 
             // Effect
@@ -946,6 +965,9 @@
             if (mesh) {
                 if (needNormals && mesh.isVerticesDataPresent(VertexBuffer.NormalKind)) {
                     this._defines.NORMAL = true;
+                    if (mesh.isVerticesDataPresent(VertexBuffer.TangentKind)) {
+                        this._defines.TANGENT = true;
+                    }
                 }
                 if (needUVs) {
                     if (mesh.isVerticesDataPresent(VertexBuffer.UVKind)) {
@@ -1050,6 +1072,10 @@
                     attribs.push(VertexBuffer.NormalKind);
                 }
 
+                if (this._defines.TANGENT) {
+                    attribs.push(VertexBuffer.TangentKind);
+                }
+
                 if (this._defines.UV1) {
                     attribs.push(VertexBuffer.UVKind);
                 }

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

@@ -190,6 +190,13 @@
                 fallbacks.addCPUSkinningFallback(0, mesh);
             }
 
+            // Textures
+            for (var name in this._textures) {
+                if (!this._textures[name].isReady()) {
+                    return false;
+                }
+            }
+
             // Alpha test
             if (engine.getAlphaTesting()) {
                 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 AMBIENT = false;
         public OPACITY = false;
@@ -47,6 +47,7 @@
         public REFLECTIONMAP_EXPLICIT = false;
         public REFLECTIONMAP_EQUIRECTANGULAR = false;
         public REFLECTIONMAP_EQUIRECTANGULAR_FIXED = false;
+        public REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED = false;
         public INVERTCUBICMAP = false;
         public LOGARITHMICDEPTH = false;
         public REFRACTION = false;
@@ -54,6 +55,7 @@
         public REFLECTIONOVERALPHA = false;
         public INVERTNORMALMAPX = false;
         public INVERTNORMALMAPY = false;
+        public TWOSIDEDLIGHTING = false;
         public SHADOWFULLFLOAT = false;
         public CAMERACOLORGRADING = false;
         public CAMERACOLORCURVES = false;
@@ -183,6 +185,12 @@
         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.
          * This allows special effects like sepia, black and white to sixties rendering style. 
          */
@@ -198,15 +206,15 @@
         @serializeAsColorCurves()
         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) {
             super(name, scene);
@@ -249,7 +257,7 @@
             return this.diffuseTexture != null && this.diffuseTexture.hasAlpha;
         }
 
-        private _shouldUseAlphaFromDiffuseTexture(): boolean {
+        protected _shouldUseAlphaFromDiffuseTexture(): boolean {
             return this.diffuseTexture != null && this.diffuseTexture.hasAlpha && this.useAlphaFromDiffuseTexture;
         }
 
@@ -258,7 +266,7 @@
         }
 
         // Methods   
-        private _checkCache(scene: Scene, mesh?: AbstractMesh, useInstances?: boolean): boolean {
+        protected _checkCache(scene: Scene, mesh?: AbstractMesh, useInstances?: boolean): boolean {
             if (!mesh) {
                 return true;
             }
@@ -381,6 +389,9 @@
                             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;
                         }
                     }
                 }
@@ -461,6 +472,10 @@
                         this._defines.CAMERACOLORGRADING = true;
                     }
                 }
+
+                if (!this.backFaceCulling && this.twoSidedLighting) {
+                    this._defines.TWOSIDEDLIGHTING = true;
+                }
             }
 
             // Effect
@@ -1010,8 +1025,6 @@
                 }
             }
 
-            this._renderTargets.dispose();
-
             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.  
          */
-        public static FromArray(array: number[], offset?: number): Vector4 {
+        public static FromArray(array: number[]  | Float32Array, offset?: number): Vector4 {
             if (!offset) {
                 offset = 0;
             }
@@ -2153,7 +2153,7 @@
         /**
          * 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.y = array[offset + 1];
             result.z = array[offset + 2];
@@ -2219,7 +2219,6 @@
         /**
          * Returns the squared distance (float) between the vectors "value1" and "value2".  
          */
-        publi
         public static DistanceSquared(value1: Vector4, value2: Vector4): number {
             var x = value1.x - value2.x;
             var y = value1.y - value2.y;
@@ -2236,6 +2235,41 @@
             center.scaleInPlace(0.5);
             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 {

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

@@ -460,7 +460,8 @@
             if (this._masterMesh) {
                 return this._masterMesh.getWorldMatrix();
             }
-            if (this._currentRenderId !== this.getScene().getRenderId()) {
+            
+            if (this._currentRenderId !== this.getScene().getRenderId() || !this.isSynchronized()) {
                 this.computeWorldMatrix();
             }
             return this._worldMatrix;
@@ -813,7 +814,7 @@
                 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();
                 return this._worldMatrix;
             }

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

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

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

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

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

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

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

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

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

@@ -169,7 +169,7 @@ module BABYLON {
         public getObjectExtendSize(): Vector3 {
             if (this.object.getBoundingInfo) {
                 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 {
                 return PhysicsImpostor.DEFAULT_OBJECT_SIZE;
             }
@@ -177,7 +177,7 @@ module BABYLON {
 
         public getObjectCenter(): Vector3 {
             if (this.object.getBoundingInfo) {
-                return this.object.getBoundingInfo().boundingBox.center;
+                return this.object.getBoundingInfo().boundingBox.centerWorld;
             } else {
                 return this.object.position;
             }
@@ -327,7 +327,7 @@ module BABYLON {
         /**
          * 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.
         public onCollide = (e: { body: any }) => {

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

@@ -4,7 +4,7 @@
         public texelHeight: number;
 
         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.texelWidth = 1.0 / this.width;

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

@@ -1,7 +1,7 @@
 module BABYLON {
     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);
 
 #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
 
 #ifdef PARALLAX
@@ -15,5 +19,5 @@
 #endif
 
 #ifdef BUMP
-	normalW = perturbNormal(viewDirectionW, TBN, vBumpUV + uvOffset);
+	normalW = perturbNormal(TBN, vBumpUV + uvOffset);
 #endif

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

@@ -2,10 +2,16 @@
 	varying vec2 vBumpUV;
 	uniform vec3 vBumpInfos;
 	uniform sampler2D bumpSampler;
+#if defined(TANGENT) && defined(NORMAL) 
+	varying mat3 vTBN;
+#endif
 
 	// Thanks to http://www.thetenthplanet.de/archives/1180
 	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
 		vec3 dp1 = dFdx(p);
 		vec3 dp2 = dFdy(p);
@@ -23,7 +29,7 @@
 		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;
 

+ 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


部分文件因为文件数量过多而无法显示