Browse Source

Merge branch 'master' of https://github.com/BabylonJS/Babylon.js

Jaskar 8 years ago
parent
commit
3ae0677b0e
86 changed files with 12896 additions and 12718 deletions
  1. 12 0
      .vscode/launch.json
  2. 1 0
      .vscode/settings.json
  3. 0 1
      Playground/index.html
  4. 16 12
      Playground/index.js
  5. 15 15
      Tools/Gulp/config.json
  6. 187 184
      Tools/Gulp/custom.config.json
  7. 240 0
      Tools/Gulp/profiling.html
  8. 25 25
      dist/preview release/babylon.core.js
  9. 4967 4968
      dist/preview release/babylon.d.ts
  10. 34 34
      dist/preview release/babylon.js
  11. 445 448
      dist/preview release/babylon.max.js
  12. 4967 4968
      dist/preview release/babylon.module.d.ts
  13. 34 34
      dist/preview release/babylon.noworker.js
  14. 2 2
      dist/preview release/inspector/babylon.inspector.bundle.js
  15. 1 4
      dist/preview release/materialsLibrary/babylon.fireMaterial.js
  16. 1 1
      dist/preview release/materialsLibrary/babylon.fireMaterial.min.js
  17. 8 8
      dist/preview release/materialsLibrary/babylon.furMaterial.d.ts
  18. 103 138
      dist/preview release/materialsLibrary/babylon.furMaterial.js
  19. 1 1
      dist/preview release/materialsLibrary/babylon.furMaterial.min.js
  20. 5 7
      dist/preview release/materialsLibrary/babylon.gradientMaterial.d.ts
  21. 55 102
      dist/preview release/materialsLibrary/babylon.gradientMaterial.js
  22. 1 1
      dist/preview release/materialsLibrary/babylon.gradientMaterial.min.js
  23. 3 7
      dist/preview release/materialsLibrary/babylon.gridMaterial.d.ts
  24. 37 49
      dist/preview release/materialsLibrary/babylon.gridMaterial.js
  25. 1 1
      dist/preview release/materialsLibrary/babylon.gridMaterial.min.js
  26. 6 7
      dist/preview release/materialsLibrary/babylon.lavaMaterial.d.ts
  27. 83 118
      dist/preview release/materialsLibrary/babylon.lavaMaterial.js
  28. 1 1
      dist/preview release/materialsLibrary/babylon.lavaMaterial.min.js
  29. 7 7
      dist/preview release/materialsLibrary/babylon.normalMaterial.d.ts
  30. 79 112
      dist/preview release/materialsLibrary/babylon.normalMaterial.js
  31. 1 1
      dist/preview release/materialsLibrary/babylon.normalMaterial.min.js
  32. 3 7
      dist/preview release/materialsLibrary/babylon.shadowOnlyMaterial.d.ts
  33. 42 75
      dist/preview release/materialsLibrary/babylon.shadowOnlyMaterial.js
  34. 1 1
      dist/preview release/materialsLibrary/babylon.shadowOnlyMaterial.min.js
  35. 2 9
      dist/preview release/materialsLibrary/babylon.simpleMaterial.js
  36. 1 1
      dist/preview release/materialsLibrary/babylon.simpleMaterial.min.js
  37. 3 7
      dist/preview release/materialsLibrary/babylon.skyMaterial.d.ts
  38. 40 63
      dist/preview release/materialsLibrary/babylon.skyMaterial.js
  39. 1 1
      dist/preview release/materialsLibrary/babylon.skyMaterial.min.js
  40. 12 7
      dist/preview release/materialsLibrary/babylon.terrainMaterial.d.ts
  41. 112 135
      dist/preview release/materialsLibrary/babylon.terrainMaterial.js
  42. 1 1
      dist/preview release/materialsLibrary/babylon.terrainMaterial.min.js
  43. 17 13
      dist/preview release/materialsLibrary/babylon.triPlanarMaterial.d.ts
  44. 112 127
      dist/preview release/materialsLibrary/babylon.triPlanarMaterial.js
  45. 1 1
      dist/preview release/materialsLibrary/babylon.triPlanarMaterial.min.js
  46. 9 7
      dist/preview release/materialsLibrary/babylon.waterMaterial.d.ts
  47. 119 148
      dist/preview release/materialsLibrary/babylon.waterMaterial.js
  48. 1 1
      dist/preview release/materialsLibrary/babylon.waterMaterial.min.js
  49. 5 0
      localDev/src/index.js
  50. 108 156
      materialsLibrary/src/fur/babylon.furMaterial.ts
  51. 36 52
      materialsLibrary/src/grid/babylon.gridmaterial.ts
  52. 84 132
      materialsLibrary/src/lava/babylon.lavaMaterial.ts
  53. 81 126
      materialsLibrary/src/normal/babylon.normalMaterial.ts
  54. 44 71
      materialsLibrary/src/sky/babylon.skyMaterial.ts
  55. 115 156
      materialsLibrary/src/terrain/babylon.terrainMaterial.ts
  56. 116 150
      materialsLibrary/src/triPlanar/babylon.triPlanarMaterial.ts
  57. BIN
      sandbox/Assets/BtnDragdrop.png
  58. BIN
      sandbox/Assets/BtnFullscreen.png
  59. BIN
      sandbox/Assets/BtnPerf.png
  60. BIN
      sandbox/Assets/FlecheDown.png
  61. BIN
      sandbox/Assets/FlecheTuto.png
  62. BIN
      sandbox/Assets/Interface-Sandbox.jpg
  63. BIN
      sandbox/Assets/LogoSandbox.png
  64. BIN
      sandbox/Assets/WideLogo.png
  65. BIN
      sandbox/Assets/arrow.png
  66. BIN
      sandbox/Assets/down.png
  67. BIN
      sandbox/Assets/sep.png
  68. BIN
      sandbox/Assets/up.png
  69. BIN
      sandbox/Assets/video.png
  70. 56 0
      sandbox/index-local.html
  71. 264 0
      sandbox/index.css
  72. 49 0
      sandbox/index.html
  73. 115 0
      sandbox/index.js
  74. 0 0
      src/Cameras/Inputs/babylon.arcRotateCameraGamepadInput.ts
  75. 0 0
      src/Cameras/Inputs/babylon.arcRotateCameraKeyboardMoveInput.ts
  76. 0 0
      src/Cameras/Inputs/babylon.arcRotateCameraMouseWheelInput.ts
  77. 0 0
      src/Cameras/Inputs/babylon.arcRotateCameraPointersInput.ts
  78. 0 0
      src/Cameras/Inputs/babylon.arcRotateCameraVRDeviceOrientationInput.ts
  79. 0 0
      src/Cameras/Inputs/babylon.freeCameraDeviceOrientationInput.ts
  80. 0 0
      src/Cameras/Inputs/babylon.freeCameraGamepadInput.ts
  81. 0 0
      src/Cameras/Inputs/babylon.freeCameraKeyboardMoveInput.ts
  82. 0 0
      src/Cameras/Inputs/babylon.freeCameraMouseInput.ts
  83. 0 0
      src/Cameras/Inputs/babylon.freeCameraTouchInput.ts
  84. 0 0
      src/Cameras/Inputs/babylon.freeCameraVirtualJoystickInput.ts
  85. 5 12
      src/Tools/babylon.filesInput.ts
  86. 3 3
      src/Tools/babylon.tools.ts

+ 12 - 0
.vscode/launch.json

@@ -2,6 +2,18 @@
     "version": "0.1.0",
     "configurations": [
         {
+            "name": "Launch sandbox (Chrome)",
+            "type": "chrome",
+            "request": "launch",
+            "url": "http://localhost:1338/sandbox/index-local.html",
+            "webRoot": "${workspaceRoot}/",
+            "sourceMaps": true,
+            "userDataDir": "${workspaceRoot}/.tempChromeProfileForDebug",
+            "runtimeArgs": [
+                "--enable-unsafe-es3-apis" 
+            ]
+        },         
+        {
             "name": "Launch playground (Chrome)",
             "type": "chrome",
             "request": "launch",

+ 1 - 0
.vscode/settings.json

@@ -9,6 +9,7 @@
         "**/.vs": true,        
         "**/.tempChromeProfileForDebug": true,
         "**/node_modules": true,
+        "**/dist": true,
         "**/temp": true,
         "**/.temp": true,
         "**/*.d.ts": true,

+ 0 - 1
Playground/index.html

@@ -3,7 +3,6 @@
 <head>
     <title>Babylon.js Playground</title>
     <script src="https://code.jquery.com/pep/0.4.2/pep.min.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/poly2tri.js"></script>
     <script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.6.2/dat.gui.min.js"></script>
     <!--x-tag-->
     <script src="xtag.min.js"></script>

+ 16 - 12
Playground/index.js

@@ -182,7 +182,7 @@
                 }
 
                 var canvas = document.getElementById("renderCanvas");
-                engine = new BABYLON.Engine(canvas, true, {preserveDrawingBuffer: true, stencil: true});
+                engine = new BABYLON.Engine(canvas, true, { preserveDrawingBuffer: true, stencil: true });
                 document.getElementById("errorZone").innerHTML = "";
                 document.getElementById("statusBar").innerHTML = "Loading assets...Please wait";
 
@@ -510,7 +510,7 @@
         var save = function () {
 
             // Retrieve title if necessary
-            if(document.getElementById("saveLayer")) {
+            if (document.getElementById("saveLayer")) {
                 currentSnippetTitle = document.getElementById("saveFormTitle").value;
                 currentSnippetDescription = document.getElementById("saveFormDescription").value;
                 currentSnippetTags = document.getElementById("saveFormTags").value;
@@ -552,8 +552,8 @@
             xmlHttp.send(JSON.stringify(dataToSend));
         }
 
-        document.getElementById("saveButton").addEventListener("click", function() {
-            if(currentSnippetTitle == null
+        document.getElementById("saveButton").addEventListener("click", function () {
+            if (currentSnippetTitle == null
                 && currentSnippetDescription == null
                 && currentSnippetTags == null) {
 
@@ -570,7 +570,7 @@
         document.getElementById("saveFormButtonCancel").addEventListener("click", function () {
             document.getElementById("saveLayer").style.display = "none";
         });
-        document.getElementById("saveMessage").addEventListener("click", function() {
+        document.getElementById("saveMessage").addEventListener("click", function () {
             document.getElementById("saveMessage").style.display = "none";
         });
         document.getElementById("mainTitle").innerHTML = "Babylon.js v" + BABYLON.Engine.Version + " Playground";
@@ -605,18 +605,22 @@
                                     jsEditor.setValue(JSON.parse(snippet.jsonPayload).code.toString());
 
                                     // Check if title / descr / tags are already set
-                                    if((snippet.name != null && snippet.name != "")
+                                    if ((snippet.name != null && snippet.name != "")
                                         || (snippet.description != null && snippet.description != "")
-                                        || (snippet.tags != null && snippet.tags != ""))
-                                    {
+                                        || (snippet.tags != null && snippet.tags != "")) {
                                         currentSnippetTitle = snippet.name;
                                         currentSnippetDescription = snippet.description;
                                         currentSnippetTags = snippet.tags;
 
-                                        if(document.getElementById("saveLayer")) {
+                                        if (document.getElementById("saveLayer")) {
                                             var elem = document.getElementById("saveLayer");
-                                            elem.outerHTML = "";
-                                            delete elem;
+                                            // elem.outerHTML = "";
+                                            // delete elem;
+
+                                            document.getElementById("saveFormTitle").value = '';
+                                            document.getElementById("saveFormDescription").value = '';
+                                            document.getElementById("saveFormTags").value = '';
+                                            elem.style.display = 'none';
                                         }
                                     }
                                     else {
@@ -686,7 +690,7 @@
 
                     run();
                 });
-           }
+            }
         }
     };
     xhr.send(null);

+ 15 - 15
Tools/Gulp/config.json

@@ -27,6 +27,7 @@
             "../../src/States/babylon.alphaCullingState.js",
             "../../src/States/babylon.depthCullingState.js",
             "../../src/States/babylon.stencilState.js",
+            "../../src/Tools/babylon.loadingScreen.js",
             "../../src/babylon.engine.js",
             "../../src/babylon.node.js",
             "../../src/Tools/babylon.filesInput.js",
@@ -47,16 +48,16 @@
             "../../src/Collisions/babylon.collisionCoordinator.js",
             "../../src/Cameras/babylon.camera.js",
             "../../src/Cameras/babylon.cameraInputsManager.js",
-            "../../src/Cameras/Inputs/babylon.freecamera.input.mouse.js",
-            "../../src/Cameras/Inputs/babylon.freecamera.input.keyboard.js",
-            "../../src/Cameras/Inputs/babylon.freecamera.input.touch.js",
-            "../../src/Cameras/Inputs/babylon.freecamera.input.deviceorientation.js",
-            "../../src/Cameras/Inputs/babylon.freecamera.input.gamepad.js",
-            "../../src/Cameras/Inputs/babylon.arcrotatecamera.input.keyboard.js",
-            "../../src/Cameras/Inputs/babylon.arcrotatecamera.input.mousewheel.js",
-            "../../src/Cameras/Inputs/babylon.arcrotatecamera.input.pointers.js",
-            "../../src/Cameras/Inputs/babylon.arcrotatecamera.input.gamepad.js",
-            "../../src/Cameras/Inputs/babylon.arcrotatecamera.input.vrdeviceorientation.js",
+            "../../src/Cameras/Inputs/babylon.freeCameraMouseInput.js",
+            "../../src/Cameras/Inputs/babylon.freeCameraKeyboardMoveInput.js",
+            "../../src/Cameras/Inputs/babylon.freeCameraTouchInput.js",
+            "../../src/Cameras/Inputs/babylon.freeCameraDeviceOrientationInput.js",
+            "../../src/Cameras/Inputs/babylon.freeCameraGamepadInput.js",
+            "../../src/Cameras/Inputs/babylon.arcRotateCameraKeyboardMoveInput.js",
+            "../../src/Cameras/Inputs/babylon.arcRotateCameraMouseWheelInput.js",
+            "../../src/Cameras/Inputs/babylon.arcRotateCameraPointersInput.js",
+            "../../src/Cameras/Inputs/babylon.arcRotateCameraGamepadInput.js",
+            "../../src/Cameras/Inputs/babylon.arcRotateCameraVRDeviceOrientationInput.js",
             "../../src/Cameras/babylon.targetCamera.js",
             "../../src/Cameras/babylon.freeCamera.js",
             "../../src/Cameras/babylon.freeCameraInputsManager.js",
@@ -66,6 +67,9 @@
             "../../src/Cameras/babylon.arcRotateCameraInputsManager.js",
             "../../src/Rendering/babylon.renderingManager.js",
             "../../src/Rendering/babylon.renderingGroup.js",
+            "../../src/PostProcess/babylon.postProcessManager.js",
+            "../../src/PostProcess/RenderPipeline/babylon.postProcessRenderPipelineManager.js",
+            "../../src/Rendering/babylon.boundingBoxRenderer.js",
             "../../src/babylon.scene.js",
             "../../src/Mesh/babylon.buffer.js",
             "../../src/Mesh/babylon.vertexBuffer.js",
@@ -105,7 +109,6 @@
             "../../src/Bones/babylon.boneLookController.js",
             "../../src/Bones/babylon.skeleton.js",
             "../../src/PostProcess/babylon.postProcess.js",
-            "../../src/PostProcess/babylon.postProcessManager.js",
             "../../src/PostProcess/babylon.passPostProcess.js",
             "../../src/Physics/babylon.physicsJoint.js",
             "../../src/Physics/babylon.physicsImpostor.js",
@@ -116,8 +119,6 @@
             "../../src/PostProcess/RenderPipeline/babylon.postProcessRenderPass.js",
             "../../src/PostProcess/RenderPipeline/babylon.postProcessRenderEffect.js",
             "../../src/PostProcess/RenderPipeline/babylon.postProcessRenderPipeline.js",
-            "../../src/PostProcess/RenderPipeline/babylon.postProcessRenderPipelineManager.js",
-            "../../src/Rendering/babylon.boundingBoxRenderer.js",
             "../../src/Actions/babylon.condition.js",
             "../../src/Actions/babylon.action.js",
             "../../src/Actions/babylon.actionManager.js",
@@ -127,7 +128,6 @@
             "../../src/Mesh/babylon.groundMesh.js",
             "../../src/Mesh/babylon.instancedMesh.js",
             "../../src/Mesh/babylon.linesMesh.js",
-            "../../src/Tools/babylon.loadingScreen.js",
             "../../src/Audio/babylon.audioEngine.js",
             "../../src/Audio/babylon.sound.js",
             "../../src/Audio/babylon.soundtrack.js",
@@ -176,7 +176,7 @@
             "../../src/PostProcess/babylon.vrDistortionCorrectionPostProcess.js",
             "../../src/Tools/babylon.virtualJoystick.js",
             "../../src/Cameras/babylon.virtualJoysticksCamera.js",
-            "../../src/Cameras/Inputs/babylon.freecamera.input.virtualjoystick.js",
+            "../../src/Cameras/Inputs/babylon.freeCameraVirtualJoystickInput.js",
             "../../src/PostProcess/babylon.anaglyphPostProcess.js",
             "../../src/Rendering/babylon.outlineRenderer.js",
             "../../src/Tools/babylon.assetsManager.js",

+ 187 - 184
Tools/Gulp/custom.config.json

@@ -11,190 +11,193 @@
       "!../../src/**/*.d.ts"
     ],
     "files": [
-      "../../src/Math/babylon.math.js",
-      "../../src/babylon.mixins.js",
-      "../../src/Tools/babylon.decorators.js",
-      "../../src/Tools/babylon.observable.js",
-      "../../src/Tools/babylon.database.js",
-      "../../src/Tools/babylon.tga.js",
-      "../../src/Tools/babylon.smartArray.js",
-      "../../src/Tools/babylon.stringDictionary.js",
-      "../../src/Tools/babylon.tools.js",
-      "../../src/States/babylon.alphaCullingState.js",
-      "../../src/States/babylon.depthCullingState.js",
-      "../../src/States/babylon.stencilState.js",
-      "../../src/babylon.engine.js",
-      "../../src/babylon.node.js",
-      "../../src/Tools/babylon.filesInput.js",
-      "../../src/Collisions/babylon.pickingInfo.js",
-      "../../src/Culling/babylon.boundingSphere.js",
-      "../../src/Culling/babylon.boundingBox.js",
-      "../../src/Culling/babylon.boundingInfo.js",
-      "../../src/Culling/babylon.ray.js",
-      "../../src/Mesh/babylon.abstractMesh.js",
-      "../../src/Lights/babylon.light.js",
-      "../../src/Lights/babylon.pointLight.js",
-      "../../src/Lights/babylon.spotLight.js",
-      "../../src/Lights/babylon.hemisphericLight.js",
-      "../../src/Lights/babylon.directionalLight.js",
-      "../../src/Lights/Shadows/babylon.shadowGenerator.js",
-      "../../src/Collisions/babylon.collider.js",
-      "../../src/Collisions/babylon.collisionCoordinator.js",
-      "../../src/Cameras/babylon.camera.js",
-      "../../src/Cameras/babylon.cameraInputsManager.js",
-      "../../src/Cameras/Inputs/babylon.freecamera.input.mouse.js",
-      "../../src/Cameras/Inputs/babylon.freecamera.input.keyboard.js",
-      "../../src/Cameras/Inputs/babylon.freecamera.input.touch.js",
-      "../../src/Cameras/Inputs/babylon.freecamera.input.deviceorientation.js",
-      "../../src/Cameras/Inputs/babylon.freecamera.input.gamepad.js",
-      "../../src/Cameras/Inputs/babylon.arcrotatecamera.input.keyboard.js",
-      "../../src/Cameras/Inputs/babylon.arcrotatecamera.input.mousewheel.js",
-      "../../src/Cameras/Inputs/babylon.arcrotatecamera.input.pointers.js",
-      "../../src/Cameras/Inputs/babylon.arcrotatecamera.input.gamepad.js",
-      "../../src/Cameras/Inputs/babylon.arcrotatecamera.input.vrdeviceorientation.js",
-      "../../src/Cameras/babylon.targetCamera.js",
-      "../../src/Cameras/babylon.freeCamera.js",
-      "../../src/Cameras/babylon.freeCameraInputsManager.js",
-      "../../src/Cameras/babylon.followCamera.js",
-      "../../src/Cameras/babylon.touchCamera.js",
-      "../../src/Cameras/babylon.arcRotateCamera.js",
-      "../../src/Cameras/babylon.arcRotateCameraInputsManager.js",
-      "../../src/Rendering/babylon.renderingManager.js",
-      "../../src/Rendering/babylon.renderingGroup.js",
-      "../../src/babylon.scene.js",
-      "../../src/Mesh/babylon.buffer.js",
-      "../../src/Mesh/babylon.vertexBuffer.js",
-      "../../src/Mesh/babylon.instancedMesh.js",
-      "../../src/Mesh/babylon.mesh.js",
-      "../../src/Mesh/babylon.subMesh.js",
-      "../../src/Mesh/babylon.meshBuilder.js",
-      "../../src/Materials/Textures/babylon.baseTexture.js",
-      "../../src/Materials/Textures/babylon.texture.js",
-      "../../src/Materials/Textures/babylon.cubeTexture.js",
-      "../../src/Materials/Textures/babylon.renderTargetTexture.js",
-      "../../src/Materials/Textures/Procedurals/babylon.proceduralTexture.js",
-      "../../src/Materials/Textures/babylon.mirrorTexture.js",
-      "../../src/Materials/Textures/babylon.refractionTexture.js",
-      "../../src/Materials/Textures/babylon.dynamicTexture.js",
-      "../../src/Materials/Textures/babylon.videoTexture.js",
-      "../../src/Materials/Textures/Procedurals/babylon.customProceduralTexture.js",
-      "../../src/Materials/babylon.effect.js",
-      "../../src/Materials/babylon.materialHelper.js",
-      "../../src/Materials/babylon.fresnelParameters.js",
-      "../../src/Materials/babylon.material.js",
-      "../../src/Materials/babylon.pushMaterial.js",
-      "../../src/Materials/babylon.standardMaterial.js",
-      "../../src/Materials/babylon.multiMaterial.js",
-      "../../src/Loading/babylon.sceneLoader.js",
-      "../../src/Loading/Plugins/babylon.babylonFileLoader.js",
-      "../../src/Sprites/babylon.spriteManager.js",
-      "../../src/Sprites/babylon.sprite.js",
-      "../../src/Layer/babylon.layer.js",
-      "../../src/Particles/babylon.particle.js",
-      "../../src/Particles/babylon.particleSystem.js",
-      "../../src/Animations/babylon.animation.js",
-      "../../src/Animations/babylon.animatable.js",
-      "../../src/Animations/babylon.easing.js",
-      "../../src/Bones/babylon.bone.js",
-      "../../src/Bones/babylon.boneIKController.js",
-      "../../src/Bones/babylon.boneLookController.js",
-      "../../src/Bones/babylon.skeleton.js",
-      "../../src/PostProcess/babylon.postProcess.js",
-      "../../src/PostProcess/babylon.postProcessManager.js",
-      "../../src/PostProcess/babylon.passPostProcess.js",
-      "../../src/Physics/babylon.physicsJoint.js",
-      "../../src/Physics/babylon.physicsImpostor.js",
-      "../../src/Physics/babylon.physicsEngine.js",
-      "../../src/Mesh/babylon.mesh.vertexData.js",
-      "../../src/Tools/babylon.tags.js",
-      "../../src/Tools/babylon.andOrNotEvaluator.js",
-      "../../src/PostProcess/RenderPipeline/babylon.postProcessRenderPass.js",
-      "../../src/PostProcess/RenderPipeline/babylon.postProcessRenderEffect.js",
-      "../../src/PostProcess/RenderPipeline/babylon.postProcessRenderPipeline.js",
-      "../../src/PostProcess/RenderPipeline/babylon.postProcessRenderPipelineManager.js",
-      "../../src/Rendering/babylon.boundingBoxRenderer.js",
-      "../../src/Actions/babylon.condition.js",
-      "../../src/Actions/babylon.action.js",
-      "../../src/Actions/babylon.actionManager.js",
-      "../../src/Actions/babylon.interpolateValueAction.js",
-      "../../src/Actions/babylon.directActions.js",
-      "../../src/Mesh/babylon.geometry.js",
-      "../../src/Mesh/babylon.groundMesh.js",
-      "../../src/Mesh/babylon.instancedMesh.js",
-      "../../src/Mesh/babylon.linesMesh.js",
-      "../../src/Tools/babylon.loadingScreen.js",
-      "../../src/Audio/babylon.audioEngine.js",
-      "../../src/Audio/babylon.sound.js",
-      "../../src/Audio/babylon.soundtrack.js",
-      "../../src/Layer/babylon.highlightlayer.js",
-      "../../src/Math/babylon.math.SIMD.js",
-      "../../src/Tools/babylon.rectPackingMap.js",
-      "../../src/Tools/babylon.dynamicFloatArray.js",
-      "../../src/Materials/Textures/babylon.mapTexture.js",
-      "../../src/Materials/babylon.shaderMaterial.js",
-      "../../src/Tools/babylon.dds.js",
-      "../../src/Physics/Plugins/babylon.cannonJSPlugin.js",
-      "../../src/Physics/Plugins/babylon.oimoJSPlugin.js",
-      "../../src/PostProcess/babylon.displayPassPostProcess.js",
-      "../../src/Mesh/babylon.meshSimplification.js",
-      "../../src/Tools/babylon.sceneSerializer.js",
-      "../../src/Tools/babylon.earcut.js",
-      "../../src/Mesh/babylon.csg.js",
-      "../../src/PostProcess/babylon.vrDistortionCorrectionPostProcess.js",
-      "../../src/Tools/babylon.virtualJoystick.js",
-      "../../src/Cameras/babylon.virtualJoysticksCamera.js",      
-      "../../src/Cameras/Inputs/babylon.freecamera.input.virtualjoystick.js",
-      "../../src/PostProcess/babylon.anaglyphPostProcess.js",
-      "../../src/Rendering/babylon.outlineRenderer.js",
-      "../../src/Tools/babylon.assetsManager.js",
-      "../../src/Cameras/VR/babylon.vrCameraMetrics.js",
-      "../../src/Cameras/VR/babylon.webVRCamera.js",
-      "../../src/Tools/babylon.sceneOptimizer.js",
-      "../../src/Mesh/babylon.meshLODLevel.js",
-      "../../src/Materials/Textures/babylon.rawTexture.js",
-      "../../src/Mesh/babylon.polygonMesh.js",
-      "../../src/Culling/Octrees/babylon.octree.js",
-      "../../src/Culling/Octrees/babylon.octreeBlock.js",
-      "../../src/PostProcess/babylon.blurPostProcess.js",
-      "../../src/PostProcess/babylon.refractionPostProcess.js",
-      "../../src/PostProcess/babylon.blackAndWhitePostProcess.js",
-      "../../src/PostProcess/babylon.convolutionPostProcess.js",
-      "../../src/PostProcess/babylon.filterPostProcess.js",
-      "../../src/PostProcess/babylon.fxaaPostProcess.js",
-      "../../src/PostProcess/babylon.stereoscopicInterlacePostProcess.js",
-      "../../src/LensFlare/babylon.lensFlare.js",
-      "../../src/LensFlare/babylon.lensFlareSystem.js",
-      "../../src/Cameras/babylon.deviceOrientationCamera.js",
-      "../../src/Cameras/VR/babylon.vrDeviceOrientationCamera.js",
-      "../../src/Cameras/babylon.universalCamera.js",
-      "../../src/Tools/babylon.gamepads.js",
-      "../../src/Cameras/babylon.gamepadCamera.js",
-      "../../src/Audio/babylon.analyser.js",
-      "../../src/Rendering/babylon.depthRenderer.js",
-      "../../src/PostProcess/babylon.ssaoRenderingPipeline.js",
-      "../../src/PostProcess/babylon.volumetricLightScatteringPostProcess.js",
-      "../../src/PostProcess/babylon.lensRenderingPipeline.js",
-      "../../src/PostProcess/babylon.colorCorrectionPostProcess.js",
-      "../../src/Cameras/babylon.stereoscopicCameras.js",
-      "../../src/PostProcess/babylon.hdrRenderingPipeline.js",
-      "../../src/Rendering/babylon.edgesRenderer.js",
-      "../../src/PostProcess/babylon.tonemapPostProcess.js",
-      "../../src/Probes/babylon.reflectionProbe.js",
-      "../../src/Particles/babylon.solidParticle.js",
-      "../../src/Particles/babylon.solidParticleSystem.js",
-      "../../src/Tools/HDR/babylon.cubemapToSphericalPolynomial.js",
-      "../../src/Tools/HDR/babylon.panoramaToCubemap.js",
-      "../../src/Tools/HDR/babylon.hdr.js",
-      "../../src/Tools/HDR/babylon.pmremgenerator.js",
-      "../../src/Materials/Textures/babylon.hdrCubeTexture.js",
-      "../../src/Debug/babylon.skeletonViewer.js",
-      "../../src/Debug/babylon.axesViewer.js",
-      "../../src/Debug/babylon.boneAxesViewer.js",
-      "../../src/Materials/Textures/babylon.colorGradingTexture.js",
-      "../../src/Materials/babylon.colorCurves.js",
-      "../../src/Materials/babylon.pbrMaterial.js",      
-      "../../src/Debug/babylon.debugLayer.js",
-      "../../src/PostProcess/babylon.standardRenderingPipeline.js"
+            "../../src/Math/babylon.math.js",
+            "../../src/babylon.mixins.js",
+            "../../src/Tools/babylon.decorators.js",
+            "../../src/Tools/babylon.observable.js",
+            "../../src/Tools/babylon.database.js",
+            "../../src/Tools/babylon.tga.js",
+            "../../src/Tools/babylon.smartArray.js",
+            "../../src/Tools/babylon.stringDictionary.js",
+            "../../src/Tools/babylon.tools.js",
+            "../../src/States/babylon.alphaCullingState.js",
+            "../../src/States/babylon.depthCullingState.js",
+            "../../src/States/babylon.stencilState.js",
+            "../../src/Tools/babylon.loadingScreen.js",
+            "../../src/babylon.engine.js",
+            "../../src/babylon.node.js",
+            "../../src/Tools/babylon.filesInput.js",
+            "../../src/Collisions/babylon.pickingInfo.js",
+            "../../src/Culling/babylon.boundingSphere.js",
+            "../../src/Culling/babylon.boundingBox.js",
+            "../../src/Culling/babylon.boundingInfo.js",
+            "../../src/Culling/babylon.ray.js",
+            "../../src/Debug/babylon.rayHelper.js",
+            "../../src/Mesh/babylon.abstractMesh.js",
+            "../../src/Lights/babylon.light.js",
+            "../../src/Lights/babylon.pointLight.js",
+            "../../src/Lights/babylon.spotLight.js",
+            "../../src/Lights/babylon.hemisphericLight.js",
+            "../../src/Lights/babylon.directionalLight.js",
+            "../../src/Lights/Shadows/babylon.shadowGenerator.js",
+            "../../src/Collisions/babylon.collider.js",
+            "../../src/Collisions/babylon.collisionCoordinator.js",
+            "../../src/Cameras/babylon.camera.js",
+            "../../src/Cameras/babylon.cameraInputsManager.js",
+            "../../src/Cameras/Inputs/babylon.freeCameraMouseInput.js",
+            "../../src/Cameras/Inputs/babylon.freeCameraKeyboardMoveInput.js",
+            "../../src/Cameras/Inputs/babylon.freeCameraTouchInput.js",
+            "../../src/Cameras/Inputs/babylon.freeCameraDeviceOrientationInput.js",
+            "../../src/Cameras/Inputs/babylon.freeCameraGamepadInput.js",
+            "../../src/Cameras/Inputs/babylon.arcRotateCameraKeyboardMoveInput.js",
+            "../../src/Cameras/Inputs/babylon.arcRotateCameraMouseWheelInput.js",
+            "../../src/Cameras/Inputs/babylon.arcRotateCameraPointersInput.js",
+            "../../src/Cameras/Inputs/babylon.arcRotateCameraGamepadInput.js",
+            "../../src/Cameras/Inputs/babylon.arcRotateCameraVRDeviceOrientationInput.js",
+            "../../src/Cameras/babylon.targetCamera.js",
+            "../../src/Cameras/babylon.freeCamera.js",
+            "../../src/Cameras/babylon.freeCameraInputsManager.js",
+            "../../src/Cameras/babylon.followCamera.js",
+            "../../src/Cameras/babylon.touchCamera.js",
+            "../../src/Cameras/babylon.arcRotateCamera.js",
+            "../../src/Cameras/babylon.arcRotateCameraInputsManager.js",
+            "../../src/Rendering/babylon.renderingManager.js",
+            "../../src/Rendering/babylon.renderingGroup.js",
+            "../../src/PostProcess/babylon.postProcessManager.js",
+            "../../src/PostProcess/RenderPipeline/babylon.postProcessRenderPipelineManager.js",
+            "../../src/Rendering/babylon.boundingBoxRenderer.js",
+            "../../src/babylon.scene.js",
+            "../../src/Mesh/babylon.buffer.js",
+            "../../src/Mesh/babylon.vertexBuffer.js",
+            "../../src/Mesh/babylon.instancedMesh.js",
+            "../../src/Mesh/babylon.mesh.js",
+            "../../src/Mesh/babylon.subMesh.js",
+            "../../src/Mesh/babylon.meshBuilder.js",
+            "../../src/Materials/Textures/babylon.baseTexture.js",
+            "../../src/Materials/Textures/babylon.texture.js",
+            "../../src/Materials/Textures/babylon.cubeTexture.js",
+            "../../src/Materials/Textures/babylon.renderTargetTexture.js",
+            "../../src/Materials/Textures/Procedurals/babylon.proceduralTexture.js",
+            "../../src/Materials/Textures/babylon.mirrorTexture.js",
+            "../../src/Materials/Textures/babylon.refractionTexture.js",
+            "../../src/Materials/Textures/babylon.dynamicTexture.js",
+            "../../src/Materials/Textures/babylon.videoTexture.js",
+            "../../src/Materials/Textures/Procedurals/babylon.customProceduralTexture.js",
+            "../../src/Materials/babylon.effect.js",
+            "../../src/Materials/babylon.materialHelper.js",
+            "../../src/Materials/babylon.fresnelParameters.js",
+            "../../src/Materials/babylon.material.js",
+            "../../src/Materials/babylon.pushMaterial.js",
+            "../../src/Materials/babylon.standardMaterial.js",
+            "../../src/Materials/babylon.multiMaterial.js",
+            "../../src/Loading/babylon.sceneLoader.js",
+            "../../src/Loading/Plugins/babylon.babylonFileLoader.js",
+            "../../src/Sprites/babylon.spriteManager.js",
+            "../../src/Sprites/babylon.sprite.js",
+            "../../src/Layer/babylon.layer.js",
+            "../../src/Particles/babylon.particle.js",
+            "../../src/Particles/babylon.particleSystem.js",
+            "../../src/Animations/babylon.animation.js",
+            "../../src/Animations/babylon.animatable.js",
+            "../../src/Animations/babylon.easing.js",
+            "../../src/Bones/babylon.bone.js",
+            "../../src/Bones/babylon.boneIKController.js",
+            "../../src/Bones/babylon.boneLookController.js",
+            "../../src/Bones/babylon.skeleton.js",
+            "../../src/PostProcess/babylon.postProcess.js",
+            "../../src/PostProcess/babylon.passPostProcess.js",
+            "../../src/Physics/babylon.physicsJoint.js",
+            "../../src/Physics/babylon.physicsImpostor.js",
+            "../../src/Physics/babylon.physicsEngine.js",
+            "../../src/Mesh/babylon.mesh.vertexData.js",
+            "../../src/Tools/babylon.tags.js",
+            "../../src/Tools/babylon.andOrNotEvaluator.js",
+            "../../src/PostProcess/RenderPipeline/babylon.postProcessRenderPass.js",
+            "../../src/PostProcess/RenderPipeline/babylon.postProcessRenderEffect.js",
+            "../../src/PostProcess/RenderPipeline/babylon.postProcessRenderPipeline.js",
+            "../../src/Actions/babylon.condition.js",
+            "../../src/Actions/babylon.action.js",
+            "../../src/Actions/babylon.actionManager.js",
+            "../../src/Actions/babylon.interpolateValueAction.js",
+            "../../src/Actions/babylon.directActions.js",
+            "../../src/Mesh/babylon.geometry.js",
+            "../../src/Mesh/babylon.groundMesh.js",
+            "../../src/Mesh/babylon.instancedMesh.js",
+            "../../src/Mesh/babylon.linesMesh.js",
+            "../../src/Audio/babylon.audioEngine.js",
+            "../../src/Audio/babylon.sound.js",
+            "../../src/Audio/babylon.soundtrack.js",
+            "../../src/Layer/babylon.highlightlayer.js",
+            "../../src/Math/babylon.math.SIMD.js",
+            "../../src/Tools/babylon.rectPackingMap.js",
+            "../../src/Tools/babylon.dynamicFloatArray.js",
+            "../../src/Materials/Textures/babylon.mapTexture.js",
+            "../../src/Materials/babylon.shaderMaterial.js",
+            "../../src/Tools/babylon.dds.js",
+            "../../src/Tools/babylon.khronosTextureContainer.js",
+            "../../src/Physics/Plugins/babylon.cannonJSPlugin.js",
+            "../../src/Physics/Plugins/babylon.oimoJSPlugin.js",
+            "../../src/PostProcess/babylon.displayPassPostProcess.js",
+            "../../src/Mesh/babylon.meshSimplification.js",
+            "../../src/Tools/babylon.sceneSerializer.js",
+            "../../src/Tools/babylon.earcut.js",
+            "../../src/Mesh/babylon.csg.js",
+            "../../src/PostProcess/babylon.vrDistortionCorrectionPostProcess.js",
+            "../../src/Tools/babylon.virtualJoystick.js",
+            "../../src/Cameras/babylon.virtualJoysticksCamera.js",
+            "../../src/Cameras/Inputs/babylon.freeCameraVirtualJoystickInput.js",
+            "../../src/PostProcess/babylon.anaglyphPostProcess.js",
+            "../../src/Rendering/babylon.outlineRenderer.js",
+            "../../src/Tools/babylon.assetsManager.js",
+            "../../src/Cameras/VR/babylon.vrCameraMetrics.js",
+            "../../src/Cameras/VR/babylon.webVRCamera.js",
+            "../../src/Tools/babylon.sceneOptimizer.js",
+            "../../src/Mesh/babylon.meshLODLevel.js",
+            "../../src/Materials/Textures/babylon.rawTexture.js",
+            "../../src/Mesh/babylon.polygonMesh.js",
+            "../../src/Culling/Octrees/babylon.octree.js",
+            "../../src/Culling/Octrees/babylon.octreeBlock.js",
+            "../../src/PostProcess/babylon.blurPostProcess.js",
+            "../../src/PostProcess/babylon.refractionPostProcess.js",
+            "../../src/PostProcess/babylon.blackAndWhitePostProcess.js",
+            "../../src/PostProcess/babylon.convolutionPostProcess.js",
+            "../../src/PostProcess/babylon.filterPostProcess.js",
+            "../../src/PostProcess/babylon.fxaaPostProcess.js",
+            "../../src/PostProcess/babylon.stereoscopicInterlacePostProcess.js",
+            "../../src/LensFlare/babylon.lensFlare.js",
+            "../../src/LensFlare/babylon.lensFlareSystem.js",
+            "../../src/Cameras/babylon.deviceOrientationCamera.js",
+            "../../src/Cameras/VR/babylon.vrDeviceOrientationCamera.js",
+            "../../src/Cameras/babylon.universalCamera.js",
+            "../../src/Tools/babylon.gamepads.js",
+            "../../src/Tools/babylon.extendedGamepad.js",
+            "../../src/Cameras/babylon.gamepadCamera.js",
+            "../../src/Audio/babylon.analyser.js",
+            "../../src/Rendering/babylon.depthRenderer.js",
+            "../../src/PostProcess/babylon.ssaoRenderingPipeline.js",
+            "../../src/PostProcess/babylon.volumetricLightScatteringPostProcess.js",
+            "../../src/PostProcess/babylon.lensRenderingPipeline.js",
+            "../../src/PostProcess/babylon.colorCorrectionPostProcess.js",
+            "../../src/Cameras/babylon.stereoscopicCameras.js",
+            "../../src/PostProcess/babylon.hdrRenderingPipeline.js",
+            "../../src/Rendering/babylon.edgesRenderer.js",
+            "../../src/PostProcess/babylon.tonemapPostProcess.js",
+            "../../src/Probes/babylon.reflectionProbe.js",
+            "../../src/Particles/babylon.solidParticle.js",
+            "../../src/Particles/babylon.solidParticleSystem.js",
+            "../../src/Tools/HDR/babylon.cubemapToSphericalPolynomial.js",
+            "../../src/Tools/HDR/babylon.panoramaToCubemap.js",
+            "../../src/Tools/HDR/babylon.hdr.js",
+            "../../src/Tools/HDR/babylon.pmremgenerator.js",
+            "../../src/Materials/Textures/babylon.hdrCubeTexture.js",
+            "../../src/Debug/babylon.skeletonViewer.js",
+            "../../src/Debug/babylon.axesViewer.js",
+            "../../src/Debug/babylon.boneAxesViewer.js",
+            "../../src/Materials/Textures/babylon.colorGradingTexture.js",
+            "../../src/Materials/babylon.colorCurves.js",
+            "../../src/Materials/babylon.pbrMaterial.js",
+            "../../src/Debug/babylon.debugLayer.js",
+            "../../src/PostProcess/babylon.standardRenderingPipeline.js"
     ]
   }
 }

+ 240 - 0
Tools/Gulp/profiling.html

@@ -0,0 +1,240 @@
+<html>
+<head>
+    <title>Customize BJS for a specific Scene</title>
+    <meta charset="UTF-8">
+    <script src="../../dist/preview release/babylon.js"></script>
+    
+</head>
+<body onload="readConfigFile()">
+Obtain a FireFox performance file by:
+<ol>
+	<li>Make sure scene uses Babylon MAX.</li>
+	<li>Load the scene.</li>
+	<li>Turn on performance profiling.</li>
+	<li>Reload the scene (very important if code like sceneLoader runs on page load).</li>
+	<li>Do anything that might call code in babylon.js not yet encountered.</li>
+	<li>Stop recording, and save the data as a file.</li>
+</ol>
+On this page:
+<ol>
+	<li>Select File with 'Browse' button below, and pick the file saved from above.</li>
+	<li>Make any changes of name to babylon file names.</li>
+	<li>Click Generate.</li>
+	<li>Copy the 'custom.cofig.json' file generated in Downloads directory to the Gulp directory.</li>
+	<li>run: 'Gulp build-custom'</li>
+	<li>Copy generated scripts from dist/preview lease to where needed, and test.  Tip: test with the max version</li>
+	<li>If need stuff did not get recorded in performance file, then select file(s) &amp; click Generate again.</li>
+</ol>
+	<form>
+		<input type="radio" name="browser" id="firefox" checked="checked"><label for="firefox"> Firefox</label>
+		<input type="radio" name="browser" id="chrome" disabled data-toggle="tooltip" title="Not yet implemented, Go for it!"><label for="chrome"> Chrome</label>
+		<input type="radio" name="browser" id="edge"   disabled data-toggle="tooltip" title="Not yet implemented, Go for it!"><label for="edge"> Edge</label><br>
+		
+		<label>Profiling file: <input type="file" id="upload_file" name="upload" accept="text/*" multiple="" onchange="assignProfile(this.files[0])"/></label><br><br>
+		
+		Filename: <input type="text" id="filename" maxlength="32" value="babylon.custom.max.js">         
+		minFilename: <input type="text" id="minFilename" maxlength="32" value="babylon.custom.js"><br>         
+        Files Not In Recording: (Select those to still keep)
+			<input type="button" value="Generate" onclick="generate()"><br>
+        <select id="discards" multiple size="30">
+        </select>
+
+	</form>
+	<script>
+	    //  each "File" is a: [keep: boolean, fullPath: string, search]
+	    //  search is initially the file name without the .js.  
+	    var files;
+    	var reg = new RegExp('babylon\\.\\w+');
+	
+	    var FIRE_FOX = 0;
+	    var CHROME   = 1;
+	    var EDGE     = 3;
+	    
+	    function readConfigFile() {
+	    	// read the regular config file, not custom, in-case custom has already been reduced
+	    	// the regular config file has files in 2 separate sections
+	        BABYLON.Tools.LoadFile("./config.json",
+	                function(data){
+	        	        var startInd = data.indexOf('"files": [') + 11; // 11 for "files": [
+	        	        var endInd = data.indexOf(']', startInd);
+	        	        var fileNames = data.substring(startInd, endInd);
+	        	        fileNames += ","; // for spliting once glued to part 2
+	        	        
+	        	        var extras = data.indexOf('"extras"');
+	        	        startInd = data.indexOf('"files": [', extras) + 11; // 11 for "files": [
+	        	        endInd = data.indexOf(']', startInd);
+	        	        fileNames += data.substring(startInd, endInd);
+	        	        
+	        	        fileNames = fileNames.replace(/(\r\n|\n|\r)/gm,""); // strip all line breaks
+	        	        fileNames = fileNames.replace(/\s+/g, ""); // strip all whitespace
+	        	        fileNames = fileNames.split(',');
+
+	        	        var len = fileNames.length;
+                        files = new Array(len);
+                        for (var i = 0; i < len; i++) {
+                        	var name = fileNames[i].match(reg)[0].substring(8);  // remove the babylon.
+                        	files[i] = [false, fileNames[i], name];
+                        }
+						appendSecondarySearches("math.js", "mathtools|color3|color4|vector2|vector3|vector4|size|quaternion|matrix|plane|viewport|frustum|bezierCurve"); // got tired
+
+						// force stuff to always be added
+						appendSecondarySearches("decorators.js", "engine"); //needed for Serialize
+						appendSecondarySearches("stringDictionary.js", "engine"); //needed in Engine Constructor
+						appendSecondarySearches("loadingScreen.js", "engine"); //needed in Engine Constructor		
+						appendSecondarySearches("postProcessRenderPipelineManager.js", "scene"); //needed in Scene Constructor		
+						appendSecondarySearches("boundingBoxRenderer.js", "scene"); //needed in Scene Constructor		
+						appendSecondarySearches("collisionCoordinator.js", "scene"); //needed in Scene Constructor, from a called set of this.workerCollisions = false;
+						appendSecondarySearches("collider.js", "abstractMesh"); // needed in abstractMesh constructor
+						appendSecondarySearches("linesMesh.js", "geometry"); // needed in geometry constructor
+						appendSecondarySearches("multiMaterial.js", "subMesh"); // needed in subMesh.getMaterial()
+						appendSecondarySearches("pointLight.js", "subMesh"); // needed in MaterialHelper.PrepareDefinesForLights
+						appendSecondarySearches("spotLight.js", "subMesh"); // needed in MaterialHelper.PrepareDefinesForLights
+						appendSecondarySearches("hemisphericLight.js", "subMesh"); // needed in MaterialHelper.PrepareDefinesForLights
+						appendSecondarySearches("directionalLight.js", "subMesh"); // needed in MaterialHelper.PrepareDefinesForLights
+						appendSecondarySearches("videoTexture.js", "engine"); //needed in Engine._setTexture()	
+						
+						// there should always some detection of FreeCamera or ArcRotateCamera, but maybe not all inputs got recorded
+						appendSecondarySearches("cameraInputsManager.js", "freeCamera\\w+|arcRotateCamera\\w+");
+						
+						appendSecondarySearches("freeCamera.js", "freeCamera\\w+");
+						appendSecondarySearches("freeCameraInputsManager.js", "freeCamera\\w+");
+						appendSecondarySearches("freeCameraMouseInput.js"            , "freeCamera\\w+");
+						appendSecondarySearches("freeCameraKeyboardMoveInput.js"     , "freeCamera\\w+");
+						appendSecondarySearches("freeCameraTouchInput.js"            , "freeCamera\\w+");
+						appendSecondarySearches("freeCameraDeviceOrientationInput.js", "freeCamera\\w+");
+						appendSecondarySearches("freeCameraGamepadInput.js"          , "freeCamera\\w+");
+						appendSecondarySearches("freeCameraVirtualJoystickInput.js"  , "freeCamera\\w+");
+						
+						appendSecondarySearches("arcRotateCamera.js", "arcRotateCamera\\w+");
+						appendSecondarySearches("arcRotateCameraInputsManager.js", "arcRotateCamera\\w+");
+						appendSecondarySearches("arcRotateCameraKeyboardMoveInput.js"       , "arcRotateCamera\\w+");
+						appendSecondarySearches("arcRotateCameraMouseWheelInput.js"         , "arcRotateCamera\\w+");
+						appendSecondarySearches("arcRotateCameraPointersInput.js"           , "arcRotateCamera\\w+");
+						appendSecondarySearches("arcRotateCameraGamepadInput.js"            , "arcRotateCamera\\w+");
+						appendSecondarySearches("arcRotateCameraVRDeviceOrientationInput.js", "arcRotateCamera\\w+");
+						
+						// these are internal classes where class name has a leading '_'
+						appendSecondarySearches("alphaCullingState.js"   , "engine");
+						appendSecondarySearches("depthCullingState.js"   , "_depthCullingState");
+						appendSecondarySearches("stencilState.js"        , "_stencilState");
+						
+						// dependencies with few / no methods, so no performance to record.
+						appendSecondarySearches("pushMaterial.js", "standardMaterial");
+                        
+	                }, null, true
+	        );
+	    }
+	    
+	    // add addition conditions to match a file to.
+	    // additionals is a string with all separated with a '|'
+	    function appendSecondarySearches(baseFilename, additionals) {
+	    	for (var i = 0, len = files.length; i < len; i++) {
+	    		if (files[i][1].indexOf(baseFilename) !== -1) {
+	    			files[i][2] += "|" + additionals;
+	    			return;
+	    		}
+	    	}
+	    	throw "'" + baseFilename + "' not found as a base file name";
+	    }
+	
+	    function assignProfile(file) {
+	        BABYLON.Tools.ReadFile(file, analyse, null, false);
+	    }
+	    
+	    function analyse(data){
+	    	// make sure max was used
+	    	if (!data.match('\\.max\\.js')) {
+	    		alert('babylon.max not detected. File rejected');
+	    		return;
+	    	}
+	    	var browser;
+	    	if (document.getElementById("firefox").checked) browser = FIRE_FOX;
+	    	if (document.getElementById("chrome" ).checked) browser = CHROME;
+	    	if (document.getElementById("edge"   ).checked) browser = EDGE;
+	    	
+			var discards = document.getElementById("discards");
+			discards.options.length = 0;
+	    	
+	    	for (var i = 0, len = files.length; i < len; i++) {
+	    		files[i][0] = false; // clean out boolean for additional runs
+    			switch(browser) {
+    			case FIRE_FOX:
+	     			var exp = new RegExp('"(' + files[i][2] + ')(\\.prototype|\\.\\w)', 'i');
+    				if (data.match(exp) ) {
+    					files[i][0] = true;
+    				}
+    				break;
+    			case CHROME:
+    			case EDGE:
+    				window.alert("Code from your PR goes here!");
+    				return;
+    			}
+	    		
+	    		// add onto the discard select when not found
+	    		if (!files[i][0]){
+	    			var option = document.createElement("option");
+	    			option.text = files[i][1];
+	    			discards.add(option);
+	    		}
+	    	}
+	    }
+	    
+	    function generate() {
+	    	// get all the ones from select
+			var discards = document.getElementById("discards");
+			var opt;
+			var asText = "";
+			for (var i = 0, len = discards.options.length; i < len; i++) {
+				opt = discards.options[i];
+                if (opt.selected) {	
+                	asText += opt.text;
+                }
+			}
+
+			var filename    = document.getElementById("filename"   ).value;
+			var minFilename = document.getElementById("minFilename").value;
+	    	var out = '';
+	    	out += '{\n';
+	    	out += '  "build": {\n';
+	    	out += '	    "filename": "' + filename + '",\n';
+	    	out += '	    "minFilename": "' + minFilename + '",\n';
+	    	out += '	    "outputDirectory": "../../dist/preview release",\n';
+	    	out += '	    "srcOutputDirectory": "../../src/"\n';
+	    	out += '	  },\n';
+	    	out += '	  "core": {\n';
+	    	out += '	    "typescript": [\n';
+	    	out += '	      "../../src/**/*.ts",\n';
+	    	out += '	      "!../../src/**/*.d.ts"\n';
+	    	out += '	    ],\n';
+	    	out += '	    "files": [\n';
+	    		
+	    	var isFirst = true;
+		    for (var i = 0, len = files.length; i < len; i++) {
+		    	if (files[i][0] || asText.indexOf(files[i][1]) !== -1) {
+		    		if (!isFirst) {
+		    			out += ',';
+		    		}
+	    			isFirst = false;
+		    		out += '\n      ' + files[i][1];
+		    	}
+		    }
+		    out += '\n    ]\n';
+		    out += '  }\n';
+		    out += '}\n';
+		    
+            var blob = new Blob ( [ out ], { type : 'text/plain;charset=utf-8' } );
+
+            // turn blob into an object URL;
+            var objectUrl = (window.webkitURL || window.URL).createObjectURL(blob);
+
+            var link = window.document.createElement("a");
+            link.href = objectUrl;
+            link.download = "custom.config.json";
+            var click = document.createEvent("MouseEvents");
+            click.initEvent("click", true, false);
+            link.dispatchEvent(click);	            
+	    }
+
+	</script>
+</body>
+</html>

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


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


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


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


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


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


+ 2 - 2
dist/preview release/inspector/babylon.inspector.bundle.js

@@ -65,8 +65,8 @@ var INSPECTOR =
 	if(false) {
 		// When the styles change, update the <style> tags
 		if(!content.locals) {
-			module.hot.accept("!!./../../../Tools/Gulp/node_modules/css-loader/index.js!./babylon.inspector.css", function() {
-				var newContent = require("!!./../../../Tools/Gulp/node_modules/css-loader/index.js!./babylon.inspector.css");
+			module.hot.accept("!!../../../Tools/Gulp/node_modules/css-loader/index.js!./babylon.inspector.css", function() {
+				var newContent = require("!!../../../Tools/Gulp/node_modules/css-loader/index.js!./babylon.inspector.css");
 				if(typeof newContent === 'string') newContent = [[module.id, newContent, '']];
 				update(newContent);
 			});

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

@@ -86,19 +86,16 @@ var BABYLON;
                         defines.DIFFUSE = true;
                     }
                 }
-                defines._areTexturesDirty = false;
             }
             // Misc.
             if (defines._areMiscDirty) {
                 defines.POINTSIZE = (this.pointsCloud || scene.forcePointsCloud);
                 defines.FOG = (scene.fogEnabled && mesh.applyFog && scene.fogMode !== BABYLON.Scene.FOGMODE_NONE && this.fogEnabled);
-                defines._areMiscDirty = false;
             }
             // Values that need to be evaluated on every frame
             BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances);
             // Attribs
-            BABYLON.MaterialHelper.PrepareDefinesForAttributes(mesh, defines, useInstances);
-            defines._areAttributesDirty = false;
+            BABYLON.MaterialHelper.PrepareDefinesForAttributes(mesh, defines, false, true);
             // Get correct effect      
             if (defines.isDirty) {
                 defines.markAsProcessed();

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


+ 8 - 8
dist/preview release/materialsLibrary/babylon.furMaterial.d.ts

@@ -1,7 +1,9 @@
 /// <reference path="../../../dist/preview release/babylon.d.ts" />
 declare module BABYLON {
-    class FurMaterial extends Material {
+    class FurMaterial extends PushMaterial {
+        private _diffuseTexture;
         diffuseTexture: BaseTexture;
+        private _heightTexture;
         heightTexture: BaseTexture;
         diffuseColor: Color3;
         furLength: number;
@@ -13,25 +15,23 @@ declare module BABYLON {
         furSpeed: number;
         furDensity: number;
         furTexture: DynamicTexture;
+        private _disableLighting;
         disableLighting: boolean;
-        highLevelFur: boolean;
+        private _maxSimultaneousLights;
         maxSimultaneousLights: number;
+        highLevelFur: boolean;
         _meshes: AbstractMesh[];
         private _worldViewProjectionMatrix;
         private _renderId;
         private _furTime;
-        private _defines;
-        private _cachedDefines;
         constructor(name: string, scene: Scene);
         furTime: number;
         needAlphaBlending(): boolean;
         needAlphaTesting(): boolean;
         getAlphaTestTexture(): BaseTexture;
         updateFur(): void;
-        private _checkCache(scene, mesh?, useInstances?);
-        isReady(mesh?: AbstractMesh, useInstances?: boolean): boolean;
-        bindOnlyWorldMatrix(world: Matrix): void;
-        bind(world: Matrix, mesh?: Mesh): void;
+        isReadyForSubMesh(mesh: AbstractMesh, subMesh: SubMesh, useInstances?: boolean): boolean;
+        bindForSubMesh(world: Matrix, mesh: Mesh, subMesh: SubMesh): void;
         getAnimatables(): IAnimatable[];
         dispose(forceDisposeEffect?: boolean): void;
         clone(name: string): FurMaterial;

+ 103 - 138
dist/preview release/materialsLibrary/babylon.furMaterial.js

@@ -17,7 +17,6 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
 };
 var BABYLON;
 (function (BABYLON) {
-    var maxSimultaneousLights = 4;
     var FurMaterialDefines = (function (_super) {
         __extends(FurMaterialDefines, _super);
         function FurMaterialDefines() {
@@ -55,14 +54,11 @@ var BABYLON;
             _this.furGravity = new BABYLON.Vector3(0, 0, 0);
             _this.furSpeed = 100;
             _this.furDensity = 20;
-            _this.disableLighting = false;
+            _this._disableLighting = false;
+            _this._maxSimultaneousLights = 4;
             _this.highLevelFur = true;
-            _this.maxSimultaneousLights = 4;
             _this._worldViewProjectionMatrix = BABYLON.Matrix.Zero();
             _this._furTime = 0;
-            _this._defines = new FurMaterialDefines();
-            _this._cachedDefines = new FurMaterialDefines();
-            _this._cachedDefines.BonesPerMesh = -1;
             return _this;
         }
         Object.defineProperty(FurMaterial.prototype, "furTime", {
@@ -101,137 +97,91 @@ var BABYLON;
             }
         };
         // Methods   
-        FurMaterial.prototype._checkCache = function (scene, mesh, useInstances) {
-            if (!mesh) {
-                return true;
-            }
-            if (this._defines.INSTANCES !== useInstances) {
-                return false;
-            }
-            return false;
-        };
-        FurMaterial.prototype.isReady = function (mesh, useInstances) {
-            if (this.checkReadyOnlyOnce) {
-                if (this._wasPreviouslyReady) {
+        FurMaterial.prototype.isReadyForSubMesh = function (mesh, subMesh, useInstances) {
+            if (this.isFrozen) {
+                if (this._wasPreviouslyReady && subMesh.effect) {
                     return true;
                 }
             }
+            if (!subMesh._materialDefines) {
+                subMesh._materialDefines = new FurMaterialDefines();
+            }
+            var defines = subMesh._materialDefines;
             var scene = this.getScene();
             if (!this.checkReadyOnEveryCall) {
                 if (this._renderId === scene.getRenderId()) {
-                    if (this._checkCache(scene, mesh, useInstances)) {
-                        return true;
-                    }
+                    return true;
                 }
             }
             var engine = scene.getEngine();
-            var needNormals = false;
-            var needUVs = false;
-            this._defines.reset();
             // 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.heightTexture && engine.getCaps().maxVertexTextureImageUnits) {
-                    if (!this.heightTexture.isReady()) {
-                        return false;
+            if (defines._areTexturesDirty) {
+                if (scene.texturesEnabled) {
+                    if (this.diffuseTexture && BABYLON.StandardMaterial.DiffuseTextureEnabled) {
+                        if (!this.diffuseTexture.isReady()) {
+                            return false;
+                        }
+                        else {
+                            defines._needUVs = true;
+                            defines.DIFFUSE = true;
+                        }
                     }
-                    else {
-                        needUVs = true;
-                        this._defines.HEIGHTMAP = true;
+                    if (this.heightTexture && engine.getCaps().maxVertexTextureImageUnits) {
+                        if (!this.heightTexture.isReady()) {
+                            return false;
+                        }
+                        else {
+                            defines._needUVs = true;
+                            defines.HEIGHTMAP = true;
+                        }
                     }
                 }
             }
-            // Effect
-            if (scene.clipPlane) {
-                this._defines.CLIPPLANE = true;
-            }
-            if (engine.getAlphaTesting()) {
-                this._defines.ALPHATEST = 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;
-            }
             // High level
-            if (this.highLevelFur) {
-                this._defines.HIGHLEVEL = true;
+            if (this.highLevelFur !== defines.HIGHLEVEL) {
+                defines.HIGHLEVEL = true;
+                defines.markAsUnprocessed();
             }
+            // Misc.   
+            BABYLON.MaterialHelper.PrepareDefinesForMisc(mesh, scene, false, this.pointsCloud, this.fogEnabled, defines);
             // Lights
-            if (scene.lightsEnabled && !this.disableLighting) {
-                needNormals = BABYLON.MaterialHelper.PrepareDefinesForLights(scene, mesh, this._defines, false, this.maxSimultaneousLights);
-            }
+            defines._needNormals = BABYLON.MaterialHelper.PrepareDefinesForLights(scene, mesh, defines, false, this._maxSimultaneousLights, this._disableLighting);
+            // Values that need to be evaluated on every frame
+            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances);
             // 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;
-                }
-            }
+            BABYLON.MaterialHelper.PrepareDefinesForAttributes(mesh, defines, true, true);
             // Get correct effect      
-            if (!this._defines.isEqual(this._cachedDefines)) {
-                this._defines.cloneTo(this._cachedDefines);
+            if (defines.isDirty) {
+                defines.markAsProcessed();
                 scene.resetCachedMaterial();
                 // Fallbacks
                 var fallbacks = new BABYLON.EffectFallbacks();
-                if (this._defines.FOG) {
+                if (defines.FOG) {
                     fallbacks.addFallback(1, "FOG");
                 }
-                BABYLON.MaterialHelper.HandleFallbacksForShadows(this._defines, fallbacks, this.maxSimultaneousLights);
-                if (this._defines.NUM_BONE_INFLUENCERS > 0) {
+                BABYLON.MaterialHelper.HandleFallbacksForShadows(defines, fallbacks, this.maxSimultaneousLights);
+                if (defines.NUM_BONE_INFLUENCERS > 0) {
                     fallbacks.addCPUSkinningFallback(0, mesh);
                 }
                 //Attributes
                 var attribs = [BABYLON.VertexBuffer.PositionKind];
-                if (this._defines.NORMAL) {
+                if (defines.NORMAL) {
                     attribs.push(BABYLON.VertexBuffer.NormalKind);
                 }
-                if (this._defines.UV1) {
+                if (defines.UV1) {
                     attribs.push(BABYLON.VertexBuffer.UVKind);
                 }
-                if (this._defines.UV2) {
+                if (defines.UV2) {
                     attribs.push(BABYLON.VertexBuffer.UV2Kind);
                 }
-                if (this._defines.VERTEXCOLOR) {
+                if (defines.VERTEXCOLOR) {
                     attribs.push(BABYLON.VertexBuffer.ColorKind);
                 }
-                BABYLON.MaterialHelper.PrepareAttributesForBones(attribs, mesh, this._defines, fallbacks);
-                BABYLON.MaterialHelper.PrepareAttributesForInstances(attribs, this._defines);
+                BABYLON.MaterialHelper.PrepareAttributesForBones(attribs, mesh, defines, fallbacks);
+                BABYLON.MaterialHelper.PrepareAttributesForInstances(attribs, defines);
                 // Legacy browser patch
                 var shaderName = "fur";
-                var join = this._defines.toString();
+                var join = defines.toString();
                 var uniforms = ["world", "view", "viewProjection", "vEyePosition", "vLightsType", "vDiffuseColor",
                     "vFogInfos", "vFogColor", "pointSize",
                     "vDiffuseInfos",
@@ -242,67 +192,70 @@ var BABYLON;
                 var samplers = ["diffuseSampler",
                     "heightTexture", "furTexture"
                 ];
-                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 });
+                BABYLON.MaterialHelper.PrepareUniformsAndSamplersList(uniforms, samplers, defines, this.maxSimultaneousLights);
+                subMesh.setEffect(scene.getEngine().createEffect(shaderName, attribs, uniforms, samplers, join, fallbacks, this.onCompiled, this.onError, { maxSimultaneousLights: this.maxSimultaneousLights }), defines);
             }
-            if (!this._effect.isReady()) {
+            if (!subMesh.effect.isReady()) {
                 return false;
             }
             this._renderId = scene.getRenderId();
             this._wasPreviouslyReady = true;
             return true;
         };
-        FurMaterial.prototype.bindOnlyWorldMatrix = function (world) {
-            this._effect.setMatrix("world", world);
-        };
-        FurMaterial.prototype.bind = function (world, mesh) {
+        FurMaterial.prototype.bindForSubMesh = function (world, mesh, subMesh) {
             var scene = this.getScene();
+            var defines = subMesh._materialDefines;
+            if (!defines) {
+                return;
+            }
+            var effect = subMesh.effect;
+            this._activeEffect = effect;
             // Matrices        
             this.bindOnlyWorldMatrix(world);
-            this._effect.setMatrix("viewProjection", scene.getTransformMatrix());
+            this._activeEffect.setMatrix("viewProjection", scene.getTransformMatrix());
             // Bones
-            BABYLON.MaterialHelper.BindBonesParameters(mesh, this._effect);
+            BABYLON.MaterialHelper.BindBonesParameters(mesh, this._activeEffect);
             if (scene.getCachedMaterial() !== this) {
                 // Textures        
-                if (this.diffuseTexture && BABYLON.StandardMaterial.DiffuseTextureEnabled) {
-                    this._effect.setTexture("diffuseSampler", this.diffuseTexture);
-                    this._effect.setFloat2("vDiffuseInfos", this.diffuseTexture.coordinatesIndex, this.diffuseTexture.level);
-                    this._effect.setMatrix("diffuseMatrix", this.diffuseTexture.getTextureMatrix());
+                if (this._diffuseTexture && BABYLON.StandardMaterial.DiffuseTextureEnabled) {
+                    this._activeEffect.setTexture("diffuseSampler", this._diffuseTexture);
+                    this._activeEffect.setFloat2("vDiffuseInfos", this._diffuseTexture.coordinatesIndex, this._diffuseTexture.level);
+                    this._activeEffect.setMatrix("diffuseMatrix", this._diffuseTexture.getTextureMatrix());
                 }
-                if (this.heightTexture) {
-                    this._effect.setTexture("heightTexture", this.heightTexture);
+                if (this._heightTexture) {
+                    this._activeEffect.setTexture("heightTexture", this._heightTexture);
                 }
                 // Clip plane
-                BABYLON.MaterialHelper.BindClipPlane(this._effect, scene);
+                BABYLON.MaterialHelper.BindClipPlane(this._activeEffect, scene);
                 // Point size
                 if (this.pointsCloud) {
-                    this._effect.setFloat("pointSize", this.pointSize);
+                    this._activeEffect.setFloat("pointSize", this.pointSize);
                 }
-                this._effect.setVector3("vEyePosition", scene._mirroredCameraPosition ? scene._mirroredCameraPosition : scene.activeCamera.position);
+                this._activeEffect.setVector3("vEyePosition", scene._mirroredCameraPosition ? scene._mirroredCameraPosition : scene.activeCamera.position);
             }
-            this._effect.setColor4("vDiffuseColor", this.diffuseColor, this.alpha * mesh.visibility);
+            this._activeEffect.setColor4("vDiffuseColor", this.diffuseColor, this.alpha * mesh.visibility);
             if (scene.lightsEnabled && !this.disableLighting) {
-                BABYLON.MaterialHelper.BindLights(scene, mesh, this._effect, this._defines, this.maxSimultaneousLights);
+                BABYLON.MaterialHelper.BindLights(scene, mesh, this._activeEffect, defines, this.maxSimultaneousLights);
             }
             // View
             if (scene.fogEnabled && mesh.applyFog && scene.fogMode !== BABYLON.Scene.FOGMODE_NONE) {
-                this._effect.setMatrix("view", scene.getViewMatrix());
+                this._activeEffect.setMatrix("view", scene.getViewMatrix());
             }
             // Fog
-            BABYLON.MaterialHelper.BindFogParameters(scene, mesh, this._effect);
-            this._effect.setFloat("furLength", this.furLength);
-            this._effect.setFloat("furAngle", this.furAngle);
-            this._effect.setColor4("furColor", this.furColor, 1.0);
+            BABYLON.MaterialHelper.BindFogParameters(scene, mesh, this._activeEffect);
+            this._activeEffect.setFloat("furLength", this.furLength);
+            this._activeEffect.setFloat("furAngle", this.furAngle);
+            this._activeEffect.setColor4("furColor", this.furColor, 1.0);
             if (this.highLevelFur) {
-                this._effect.setVector3("furGravity", this.furGravity);
-                this._effect.setFloat("furOffset", this.furOffset);
-                this._effect.setFloat("furSpacing", this.furSpacing);
-                this._effect.setFloat("furDensity", this.furDensity);
+                this._activeEffect.setVector3("furGravity", this.furGravity);
+                this._activeEffect.setFloat("furOffset", this.furOffset);
+                this._activeEffect.setFloat("furSpacing", this.furSpacing);
+                this._activeEffect.setFloat("furDensity", this.furDensity);
                 this._furTime += this.getScene().getEngine().getDeltaTime() / this.furSpeed;
-                this._effect.setFloat("furTime", this._furTime);
-                this._effect.setTexture("furTexture", this.furTexture);
+                this._activeEffect.setFloat("furTime", this._furTime);
+                this._activeEffect.setTexture("furTexture", this.furTexture);
             }
-            this._afterBind(mesh);
+            this._afterBind(mesh, this._activeEffect);
         };
         FurMaterial.prototype.getAnimatables = function () {
             var results = [];
@@ -407,12 +360,18 @@ var BABYLON;
             return meshes;
         };
         return FurMaterial;
-    }(BABYLON.Material));
+    }(BABYLON.PushMaterial));
     __decorate([
-        BABYLON.serializeAsTexture()
+        BABYLON.serializeAsTexture("diffuseTexture")
+    ], FurMaterial.prototype, "_diffuseTexture", void 0);
+    __decorate([
+        BABYLON.expandToProperty("_markAllSubMeshesAsTexturesDirty")
     ], FurMaterial.prototype, "diffuseTexture", void 0);
     __decorate([
-        BABYLON.serializeAsTexture()
+        BABYLON.serializeAsTexture("heightTexture")
+    ], FurMaterial.prototype, "_heightTexture", void 0);
+    __decorate([
+        BABYLON.expandToProperty("_markAllSubMeshesAsTexturesDirty")
     ], FurMaterial.prototype, "heightTexture", void 0);
     __decorate([
         BABYLON.serializeAsColor3()
@@ -442,16 +401,22 @@ var BABYLON;
         BABYLON.serialize()
     ], FurMaterial.prototype, "furDensity", void 0);
     __decorate([
-        BABYLON.serialize()
+        BABYLON.serialize("disableLighting")
+    ], FurMaterial.prototype, "_disableLighting", void 0);
+    __decorate([
+        BABYLON.expandToProperty("_markAllSubMeshesAsLightsDirty")
     ], FurMaterial.prototype, "disableLighting", void 0);
     __decorate([
-        BABYLON.serialize()
-    ], FurMaterial.prototype, "highLevelFur", void 0);
+        BABYLON.serialize("maxSimultaneousLights")
+    ], FurMaterial.prototype, "_maxSimultaneousLights", void 0);
     __decorate([
-        BABYLON.serialize()
+        BABYLON.expandToProperty("_markAllSubMeshesAsLightsDirty")
     ], FurMaterial.prototype, "maxSimultaneousLights", void 0);
     __decorate([
         BABYLON.serialize()
+    ], FurMaterial.prototype, "highLevelFur", void 0);
+    __decorate([
+        BABYLON.serialize()
     ], FurMaterial.prototype, "furTime", null);
     BABYLON.FurMaterial = FurMaterial;
 })(BABYLON || (BABYLON = {}));

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


+ 5 - 7
dist/preview release/materialsLibrary/babylon.gradientMaterial.d.ts

@@ -1,6 +1,8 @@
 /// <reference path="../../../dist/preview release/babylon.d.ts" />
 declare module BABYLON {
-    class GradientMaterial extends Material {
+    class GradientMaterial extends PushMaterial {
+        private _maxSimultaneousLights;
+        maxSimultaneousLights: number;
         topColor: Color3;
         topColorAlpha: number;
         bottomColor: Color3;
@@ -11,16 +13,12 @@ declare module BABYLON {
         private _worldViewProjectionMatrix;
         private _scaledDiffuse;
         private _renderId;
-        private _defines;
-        private _cachedDefines;
         constructor(name: string, scene: Scene);
         needAlphaBlending(): boolean;
         needAlphaTesting(): boolean;
         getAlphaTestTexture(): BaseTexture;
-        private _checkCache(scene, mesh?, useInstances?);
-        isReady(mesh?: AbstractMesh, useInstances?: boolean): boolean;
-        bindOnlyWorldMatrix(world: Matrix): void;
-        bind(world: Matrix, mesh?: Mesh): void;
+        isReadyForSubMesh(mesh: AbstractMesh, subMesh: SubMesh, useInstances?: boolean): boolean;
+        bindForSubMesh(world: Matrix, mesh: Mesh, subMesh: SubMesh): void;
         getAnimatables(): IAnimatable[];
         dispose(forceDisposeEffect?: boolean): void;
         clone(name: string): GradientMaterial;

+ 55 - 102
dist/preview release/materialsLibrary/babylon.gradientMaterial.js

@@ -17,7 +17,6 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
 };
 var BABYLON;
 (function (BABYLON) {
-    var maxSimultaneousLights = 4;
     var GradientMaterialDefines = (function (_super) {
         __extends(GradientMaterialDefines, _super);
         function GradientMaterialDefines() {
@@ -77,6 +76,7 @@ var BABYLON;
         __extends(GradientMaterial, _super);
         function GradientMaterial(name, scene) {
             var _this = _super.call(this, name, scene) || this;
+            _this._maxSimultaneousLights = 4;
             // The gradient top color, red by default
             _this.topColor = new BABYLON.Color3(1, 0, 0);
             _this.topColorAlpha = 1.0;
@@ -89,9 +89,6 @@ var BABYLON;
             _this.disableLighting = false;
             _this._worldViewProjectionMatrix = BABYLON.Matrix.Zero();
             _this._scaledDiffuse = new BABYLON.Color3();
-            _this._defines = new GradientMaterialDefines();
-            _this._cachedDefines = new GradientMaterialDefines();
-            _this._cachedDefines.BonesPerMesh = -1;
             return _this;
         }
         GradientMaterial.prototype.needAlphaBlending = function () {
@@ -104,114 +101,61 @@ var BABYLON;
             return null;
         };
         // Methods   
-        GradientMaterial.prototype._checkCache = function (scene, mesh, useInstances) {
-            if (!mesh) {
-                return true;
-            }
-            if (this._defines.INSTANCES !== useInstances) {
-                return false;
-            }
-            return false;
-        };
-        GradientMaterial.prototype.isReady = function (mesh, useInstances) {
-            if (this.checkReadyOnlyOnce) {
-                if (this._wasPreviouslyReady) {
+        GradientMaterial.prototype.isReadyForSubMesh = function (mesh, subMesh, useInstances) {
+            if (this.isFrozen) {
+                if (this._wasPreviouslyReady && subMesh.effect) {
                     return true;
                 }
             }
+            if (!subMesh._materialDefines) {
+                subMesh._materialDefines = new GradientMaterialDefines();
+            }
+            var defines = subMesh._materialDefines;
             var scene = this.getScene();
             if (!this.checkReadyOnEveryCall) {
                 if (this._renderId === scene.getRenderId()) {
-                    if (this._checkCache(scene, mesh, useInstances)) {
-                        return true;
-                    }
+                    return true;
                 }
             }
             var engine = scene.getEngine();
-            var needNormals = false;
-            var needUVs = false;
-            this._defines.reset();
-            // No textures
-            // Effect
-            if (scene.clipPlane) {
-                this._defines.CLIPPLANE = true;
-            }
-            if (engine.getAlphaTesting()) {
-                this._defines.ALPHATEST = 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;
-            }
-            var lightIndex = 0;
-            if (scene.lightsEnabled && !this.disableLighting) {
-                needNormals = BABYLON.MaterialHelper.PrepareDefinesForLights(scene, mesh, this._defines, false);
-            }
+            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances);
+            BABYLON.MaterialHelper.PrepareDefinesForMisc(mesh, scene, false, this.pointsCloud, this.fogEnabled, defines);
+            defines._needNormals = BABYLON.MaterialHelper.PrepareDefinesForLights(scene, mesh, defines, false, this._maxSimultaneousLights);
             // 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;
-                }
-            }
+            BABYLON.MaterialHelper.PrepareDefinesForAttributes(mesh, defines, false, true);
             // Get correct effect      
-            if (!this._defines.isEqual(this._cachedDefines)) {
-                this._defines.cloneTo(this._cachedDefines);
+            if (defines.isDirty) {
+                defines.markAsProcessed();
                 scene.resetCachedMaterial();
                 // Fallbacks
                 var fallbacks = new BABYLON.EffectFallbacks();
-                if (this._defines.FOG) {
+                if (defines.FOG) {
                     fallbacks.addFallback(1, "FOG");
                 }
-                BABYLON.MaterialHelper.HandleFallbacksForShadows(this._defines, fallbacks);
-                if (this._defines.NUM_BONE_INFLUENCERS > 0) {
+                BABYLON.MaterialHelper.HandleFallbacksForShadows(defines, fallbacks);
+                if (defines.NUM_BONE_INFLUENCERS > 0) {
                     fallbacks.addCPUSkinningFallback(0, mesh);
                 }
                 //Attributes
                 var attribs = [BABYLON.VertexBuffer.PositionKind];
-                if (this._defines.NORMAL) {
+                if (defines.NORMAL) {
                     attribs.push(BABYLON.VertexBuffer.NormalKind);
                 }
-                if (this._defines.UV1) {
+                if (defines.UV1) {
                     attribs.push(BABYLON.VertexBuffer.UVKind);
                 }
-                if (this._defines.UV2) {
+                if (defines.UV2) {
                     attribs.push(BABYLON.VertexBuffer.UV2Kind);
                 }
-                if (this._defines.VERTEXCOLOR) {
+                if (defines.VERTEXCOLOR) {
                     attribs.push(BABYLON.VertexBuffer.ColorKind);
                 }
-                BABYLON.MaterialHelper.PrepareAttributesForBones(attribs, mesh, this._defines, fallbacks);
-                BABYLON.MaterialHelper.PrepareAttributesForInstances(attribs, this._defines);
+                BABYLON.MaterialHelper.PrepareAttributesForBones(attribs, mesh, defines, fallbacks);
+                BABYLON.MaterialHelper.PrepareAttributesForInstances(attribs, defines);
                 // Legacy browser patch
                 var shaderName = "gradient";
-                var join = this._defines.toString();
-                this._effect = scene.getEngine().createEffect(shaderName, attribs, ["world", "view", "viewProjection", "vEyePosition", "vLightsType", "vDiffuseColor",
+                var join = defines.toString();
+                subMesh.setEffect(scene.getEngine().createEffect(shaderName, attribs, ["world", "view", "viewProjection", "vEyePosition", "vLightsType", "vDiffuseColor",
                     "vLightData0", "vLightDiffuse0", "vLightDirection0", "vLightGround0", "lightMatrix0",
                     "vLightData1", "vLightDiffuse1", "vLightDirection1", "vLightGround1", "lightMatrix1",
                     "vLightData2", "vLightDiffuse2", "vLightDirection2", "vLightGround2", "lightMatrix2",
@@ -223,49 +167,52 @@ var BABYLON;
                     "shadowsInfo0", "shadowsInfo1", "shadowsInfo2", "shadowsInfo3", "depthValues", "topColor", "bottomColor", "offset", "smoothness"
                 ], ["diffuseSampler",
                     "shadowSampler0", "shadowSampler1", "shadowSampler2", "shadowSampler3"
-                ], join, fallbacks, this.onCompiled, this.onError, { maxSimultaneousLights: 4 });
+                ], join, fallbacks, this.onCompiled, this.onError, { maxSimultaneousLights: 4 }), defines);
             }
-            if (!this._effect.isReady()) {
+            if (!subMesh.effect.isReady()) {
                 return false;
             }
             this._renderId = scene.getRenderId();
             this._wasPreviouslyReady = true;
             return true;
         };
-        GradientMaterial.prototype.bindOnlyWorldMatrix = function (world) {
-            this._effect.setMatrix("world", world);
-        };
-        GradientMaterial.prototype.bind = function (world, mesh) {
+        GradientMaterial.prototype.bindForSubMesh = function (world, mesh, subMesh) {
             var scene = this.getScene();
+            var defines = subMesh._materialDefines;
+            if (!defines) {
+                return;
+            }
+            var effect = subMesh.effect;
+            this._activeEffect = effect;
             // Matrices        
             this.bindOnlyWorldMatrix(world);
-            this._effect.setMatrix("viewProjection", scene.getTransformMatrix());
+            this._activeEffect.setMatrix("viewProjection", scene.getTransformMatrix());
             // Bones
             BABYLON.MaterialHelper.BindBonesParameters(mesh, this._effect);
-            if (scene.getCachedMaterial() !== this) {
+            if (this._mustRebind(scene, effect)) {
                 // Clip plane
                 BABYLON.MaterialHelper.BindClipPlane(this._effect, scene);
                 // Point size
                 if (this.pointsCloud) {
-                    this._effect.setFloat("pointSize", this.pointSize);
+                    this._activeEffect.setFloat("pointSize", this.pointSize);
                 }
-                this._effect.setVector3("vEyePosition", scene._mirroredCameraPosition ? scene._mirroredCameraPosition : scene.activeCamera.position);
+                this._activeEffect.setVector3("vEyePosition", scene._mirroredCameraPosition ? scene._mirroredCameraPosition : scene.activeCamera.position);
             }
-            this._effect.setColor4("vDiffuseColor", this._scaledDiffuse, this.alpha * mesh.visibility);
+            this._activeEffect.setColor4("vDiffuseColor", this._scaledDiffuse, this.alpha * mesh.visibility);
             if (scene.lightsEnabled && !this.disableLighting) {
-                BABYLON.MaterialHelper.BindLights(scene, mesh, this._effect, this._defines);
+                BABYLON.MaterialHelper.BindLights(scene, mesh, this._activeEffect, defines);
             }
             // View
             if (scene.fogEnabled && mesh.applyFog && scene.fogMode !== BABYLON.Scene.FOGMODE_NONE) {
-                this._effect.setMatrix("view", scene.getViewMatrix());
+                this._activeEffect.setMatrix("view", scene.getViewMatrix());
             }
             // Fog
-            BABYLON.MaterialHelper.BindFogParameters(scene, mesh, this._effect);
-            this._effect.setColor4("topColor", this.topColor, this.topColorAlpha);
-            this._effect.setColor4("bottomColor", this.bottomColor, this.bottomColorAlpha);
-            this._effect.setFloat("offset", this.offset);
-            this._effect.setFloat("smoothness", this.smoothness);
-            this._afterBind(mesh);
+            BABYLON.MaterialHelper.BindFogParameters(scene, mesh, this._activeEffect);
+            this._activeEffect.setColor4("topColor", this.topColor, this.topColorAlpha);
+            this._activeEffect.setColor4("bottomColor", this.bottomColor, this.bottomColorAlpha);
+            this._activeEffect.setFloat("offset", this.offset);
+            this._activeEffect.setFloat("smoothness", this.smoothness);
+            this._afterBind(mesh, this._activeEffect);
         };
         GradientMaterial.prototype.getAnimatables = function () {
             return [];
@@ -287,7 +234,13 @@ var BABYLON;
             return BABYLON.SerializationHelper.Parse(function () { return new GradientMaterial(source.name, scene); }, source, scene, rootUrl);
         };
         return GradientMaterial;
-    }(BABYLON.Material));
+    }(BABYLON.PushMaterial));
+    __decorate([
+        BABYLON.serialize("maxSimultaneousLights")
+    ], GradientMaterial.prototype, "_maxSimultaneousLights", void 0);
+    __decorate([
+        BABYLON.expandToProperty("_markAllSubMeshesAsLightsDirty")
+    ], GradientMaterial.prototype, "maxSimultaneousLights", void 0);
     __decorate([
         BABYLON.serializeAsColor3()
     ], GradientMaterial.prototype, "topColor", void 0);

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


+ 3 - 7
dist/preview release/materialsLibrary/babylon.gridMaterial.d.ts

@@ -4,7 +4,7 @@ declare module BABYLON {
      * The grid materials allows you to wrap any shape with a grid.
      * Colors are customizable.
      */
-    class GridMaterial extends BABYLON.Material {
+    class GridMaterial extends BABYLON.PushMaterial {
         /**
          * Main color of the grid (e.g. between lines)
          */
@@ -31,8 +31,6 @@ declare module BABYLON {
         opacity: number;
         private _gridControl;
         private _renderId;
-        private _defines;
-        private _cachedDefines;
         /**
          * constructor
          * @param name The name given to the material in order to identify it afterwards.
@@ -43,10 +41,8 @@ declare module BABYLON {
          * Returns wehter or not the grid requires alpha blending.
          */
         needAlphaBlending(): boolean;
-        private _checkCache(scene, mesh?, useInstances?);
-        isReady(mesh?: AbstractMesh, useInstances?: boolean): boolean;
-        bindOnlyWorldMatrix(world: Matrix): void;
-        bind(world: Matrix, mesh?: Mesh): void;
+        isReadyForSubMesh(mesh: AbstractMesh, subMesh: SubMesh, useInstances?: boolean): boolean;
+        bindForSubMesh(world: Matrix, mesh: Mesh, subMesh: SubMesh): void;
         dispose(forceDisposeEffect?: boolean): void;
         clone(name: string): GridMaterial;
         serialize(): any;

+ 37 - 49
dist/preview release/materialsLibrary/babylon.gridMaterial.js

@@ -17,16 +17,16 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
 };
 var BABYLON;
 (function (BABYLON) {
-    var GRIDMaterialDefines = (function (_super) {
-        __extends(GRIDMaterialDefines, _super);
-        function GRIDMaterialDefines() {
+    var GridMaterialDefines = (function (_super) {
+        __extends(GridMaterialDefines, _super);
+        function GridMaterialDefines() {
             var _this = _super.call(this) || this;
             _this.TRANSPARENT = false;
             _this.FOG = false;
             _this.rebuild();
             return _this;
         }
-        return GRIDMaterialDefines;
+        return GridMaterialDefines;
     }(BABYLON.MaterialDefines));
     /**
      * The grid materials allows you to wrap any shape with a grid.
@@ -66,8 +66,6 @@ var BABYLON;
              */
             _this.opacity = 1.0;
             _this._gridControl = new BABYLON.Vector4(_this.gridRatio, _this.majorUnitFrequency, _this.minorUnitVisibility, _this.opacity);
-            _this._defines = new GRIDMaterialDefines();
-            _this._cachedDefines = new GRIDMaterialDefines();
             return _this;
         }
         /**
@@ -76,82 +74,72 @@ var BABYLON;
         GridMaterial.prototype.needAlphaBlending = function () {
             return this.opacity < 1.0;
         };
-        GridMaterial.prototype._checkCache = function (scene, mesh, useInstances) {
-            if (!mesh) {
-                return true;
-            }
-            return false;
-        };
-        GridMaterial.prototype.isReady = function (mesh, useInstances) {
-            if (this.checkReadyOnlyOnce) {
-                if (this._wasPreviouslyReady) {
+        GridMaterial.prototype.isReadyForSubMesh = function (mesh, subMesh, useInstances) {
+            if (this.isFrozen) {
+                if (this._wasPreviouslyReady && subMesh.effect) {
                     return true;
                 }
             }
+            if (!subMesh._materialDefines) {
+                subMesh._materialDefines = new GridMaterialDefines();
+            }
+            var defines = subMesh._materialDefines;
             var scene = this.getScene();
             if (!this.checkReadyOnEveryCall) {
                 if (this._renderId === scene.getRenderId()) {
-                    if (this._checkCache(scene, mesh, useInstances)) {
-                        return true;
-                    }
+                    return true;
                 }
             }
             var engine = scene.getEngine();
-            var needNormals = true;
-            this._defines.reset();
-            if (this.opacity < 1.0) {
-                this._defines.TRANSPARENT = true;
-            }
-            // Fog
-            if (scene.fogEnabled && mesh && mesh.applyFog && scene.fogMode !== BABYLON.Scene.FOGMODE_NONE && this.fogEnabled) {
-                this._defines.FOG = true;
+            if (this.opacity < 1.0 && !defines.TRANSPARENT) {
+                defines.TRANSPARENT = true;
+                defines.markAsUnprocessed();
             }
+            BABYLON.MaterialHelper.PrepareDefinesForMisc(mesh, scene, false, false, this.fogEnabled, defines);
             // Get correct effect      
-            if (!this._effect || !this._defines.isEqual(this._cachedDefines)) {
-                this._defines.cloneTo(this._cachedDefines);
+            if (defines.isDirty) {
+                defines.markAsProcessed();
                 scene.resetCachedMaterial();
                 // Attributes
                 var attribs = [BABYLON.VertexBuffer.PositionKind, BABYLON.VertexBuffer.NormalKind];
                 // Effect
                 var shaderName = scene.getEngine().getCaps().standardDerivatives ? "grid" : "legacygrid";
                 // Defines
-                var join = this._defines.toString();
-                this._effect = scene.getEngine().createEffect(shaderName, attribs, ["worldViewProjection", "mainColor", "lineColor", "gridControl", "vFogInfos", "vFogColor", "world", "view"], [], join, null, this.onCompiled, this.onError);
+                var join = defines.toString();
+                subMesh.setEffect(scene.getEngine().createEffect(shaderName, attribs, ["worldViewProjection", "mainColor", "lineColor", "gridControl", "vFogInfos", "vFogColor", "world", "view"], [], join, null, this.onCompiled, this.onError), defines);
             }
-            if (!this._effect.isReady()) {
+            if (!subMesh.effect.isReady()) {
                 return false;
             }
             this._renderId = scene.getRenderId();
             this._wasPreviouslyReady = true;
             return true;
         };
-        GridMaterial.prototype.bindOnlyWorldMatrix = function (world) {
-            var scene = this.getScene();
-            this._effect.setMatrix("worldViewProjection", world.multiply(scene.getTransformMatrix()));
-            this._effect.setMatrix("world", world);
-            this._effect.setMatrix("view", scene.getViewMatrix());
-        };
-        GridMaterial.prototype.bind = function (world, mesh) {
+        GridMaterial.prototype.bindForSubMesh = function (world, mesh, subMesh) {
             var scene = this.getScene();
+            var defines = subMesh._materialDefines;
+            if (!defines) {
+                return;
+            }
+            var effect = subMesh.effect;
+            this._activeEffect = effect;
             // Matrices
             this.bindOnlyWorldMatrix(world);
+            this._activeEffect.setMatrix("worldViewProjection", world.multiply(scene.getTransformMatrix()));
+            this._activeEffect.setMatrix("view", scene.getViewMatrix());
             // Uniforms
-            if (scene.getCachedMaterial() !== this) {
-                this._effect.setColor3("mainColor", this.mainColor);
-                this._effect.setColor3("lineColor", this.lineColor);
+            if (this._mustRebind(scene, effect)) {
+                this._activeEffect.setColor3("mainColor", this.mainColor);
+                this._activeEffect.setColor3("lineColor", this.lineColor);
                 this._gridControl.x = this.gridRatio;
                 this._gridControl.y = Math.round(this.majorUnitFrequency);
                 this._gridControl.z = this.minorUnitVisibility;
                 this._gridControl.w = this.opacity;
-                this._effect.setVector4("gridControl", this._gridControl);
-            }
-            // View
-            if (scene.fogEnabled && mesh.applyFog && scene.fogMode !== BABYLON.Scene.FOGMODE_NONE) {
-                this._effect.setMatrix("view", scene.getViewMatrix());
+                this._activeEffect.setVector4("gridControl", this._gridControl);
             }
             // Fog
-            BABYLON.MaterialHelper.BindFogParameters(scene, mesh, this._effect);
-            this._afterBind(mesh);
+            BABYLON.MaterialHelper.BindFogParameters(scene, mesh, this._activeEffect);
+            this._afterBind(mesh, this._activeEffect);
         };
         GridMaterial.prototype.dispose = function (forceDisposeEffect) {
             _super.prototype.dispose.call(this, forceDisposeEffect);
@@ -169,7 +157,7 @@ var BABYLON;
             return BABYLON.SerializationHelper.Parse(function () { return new GridMaterial(source.name, scene); }, source, scene, rootUrl);
         };
         return GridMaterial;
-    }(BABYLON.Material));
+    }(BABYLON.PushMaterial));
     __decorate([
         BABYLON.serializeAsColor3()
     ], GridMaterial.prototype, "mainColor", void 0);

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


+ 6 - 7
dist/preview release/materialsLibrary/babylon.lavaMaterial.d.ts

@@ -1,6 +1,7 @@
 /// <reference path="../../../dist/preview release/babylon.d.ts" />
 declare module BABYLON {
-    class LavaMaterial extends Material {
+    class LavaMaterial extends PushMaterial {
+        private _diffuseTexture;
         diffuseTexture: BaseTexture;
         noiseTexture: BaseTexture;
         fogColor: Color3;
@@ -10,21 +11,19 @@ declare module BABYLON {
         fogDensity: number;
         private _lastTime;
         diffuseColor: Color3;
+        private _disableLighting;
         disableLighting: boolean;
+        private _maxSimultaneousLights;
         maxSimultaneousLights: number;
         private _worldViewProjectionMatrix;
         private _scaledDiffuse;
         private _renderId;
-        private _defines;
-        private _cachedDefines;
         constructor(name: string, scene: Scene);
         needAlphaBlending(): boolean;
         needAlphaTesting(): boolean;
         getAlphaTestTexture(): BaseTexture;
-        private _checkCache(scene, mesh?, useInstances?);
-        isReady(mesh?: AbstractMesh, useInstances?: boolean): boolean;
-        bindOnlyWorldMatrix(world: Matrix): void;
-        bind(world: Matrix, mesh?: Mesh): void;
+        isReadyForSubMesh(mesh: AbstractMesh, subMesh: SubMesh, useInstances?: boolean): boolean;
+        bindForSubMesh(world: Matrix, mesh: Mesh, subMesh: SubMesh): void;
         getAnimatables(): IAnimatable[];
         dispose(forceDisposeEffect?: boolean): void;
         clone(name: string): LavaMaterial;

+ 83 - 118
dist/preview release/materialsLibrary/babylon.lavaMaterial.js

@@ -82,13 +82,10 @@ var BABYLON;
             _this.fogDensity = 0.15;
             _this._lastTime = 0;
             _this.diffuseColor = new BABYLON.Color3(1, 1, 1);
-            _this.disableLighting = false;
-            _this.maxSimultaneousLights = 4;
+            _this._disableLighting = false;
+            _this._maxSimultaneousLights = 4;
             _this._worldViewProjectionMatrix = BABYLON.Matrix.Zero();
             _this._scaledDiffuse = new BABYLON.Color3();
-            _this._defines = new LavaMaterialDefines();
-            _this._cachedDefines = new LavaMaterialDefines();
-            _this._cachedDefines.BonesPerMesh = -1;
             return _this;
         }
         LavaMaterial.prototype.needAlphaBlending = function () {
@@ -101,123 +98,79 @@ var BABYLON;
             return null;
         };
         // Methods   
-        LavaMaterial.prototype._checkCache = function (scene, mesh, useInstances) {
-            if (!mesh) {
-                return true;
-            }
-            if (this._defines.INSTANCES !== useInstances) {
-                return false;
-            }
-            return false;
-        };
-        LavaMaterial.prototype.isReady = function (mesh, useInstances) {
-            if (this.checkReadyOnlyOnce) {
-                if (this._wasPreviouslyReady) {
+        LavaMaterial.prototype.isReadyForSubMesh = function (mesh, subMesh, useInstances) {
+            if (this.isFrozen) {
+                if (this._wasPreviouslyReady && subMesh.effect) {
                     return true;
                 }
             }
+            if (!subMesh._materialDefines) {
+                subMesh._materialDefines = new LavaMaterialDefines();
+            }
+            var defines = subMesh._materialDefines;
             var scene = this.getScene();
             if (!this.checkReadyOnEveryCall) {
                 if (this._renderId === scene.getRenderId()) {
-                    if (this._checkCache(scene, mesh, useInstances)) {
-                        return true;
-                    }
+                    return true;
                 }
             }
             var engine = scene.getEngine();
-            var needUVs = false;
-            this._defines.reset();
             // Textures
-            if (scene.texturesEnabled) {
-                if (this.diffuseTexture && BABYLON.StandardMaterial.DiffuseTextureEnabled) {
-                    if (!this.diffuseTexture.isReady()) {
-                        return false;
-                    }
-                    else {
-                        needUVs = true;
-                        this._defines.DIFFUSE = true;
+            if (defines._areTexturesDirty) {
+                defines._needUVs = false;
+                if (scene.texturesEnabled) {
+                    if (this._diffuseTexture && BABYLON.StandardMaterial.DiffuseTextureEnabled) {
+                        if (!this._diffuseTexture.isReady()) {
+                            return false;
+                        }
+                        else {
+                            defines._needUVs = true;
+                            defines.DIFFUSE = true;
+                        }
                     }
                 }
             }
-            // Effect
-            if (scene.clipPlane) {
-                this._defines.CLIPPLANE = true;
-            }
-            if (engine.getAlphaTesting()) {
-                this._defines.ALPHATEST = 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 (scene.lightsEnabled && !this.disableLighting) {
-                BABYLON.MaterialHelper.PrepareDefinesForLights(scene, mesh, this._defines, false, this.maxSimultaneousLights);
-            }
+            // Misc.
+            BABYLON.MaterialHelper.PrepareDefinesForMisc(mesh, scene, false, this.pointsCloud, this.fogEnabled, defines);
+            // Lights
+            defines._needNormals = BABYLON.MaterialHelper.PrepareDefinesForLights(scene, mesh, defines, false, this._maxSimultaneousLights, this._disableLighting);
+            // Values that need to be evaluated on every frame
+            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances);
             // Attribs
-            if (mesh) {
-                if (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;
-                }
-            }
+            BABYLON.MaterialHelper.PrepareDefinesForAttributes(mesh, defines, true, true);
             // Get correct effect      
-            if (!this._defines.isEqual(this._cachedDefines)) {
-                this._defines.cloneTo(this._cachedDefines);
+            if (defines.isDirty) {
+                defines.markAsProcessed();
                 scene.resetCachedMaterial();
                 // Fallbacks
                 var fallbacks = new BABYLON.EffectFallbacks();
-                if (this._defines.FOG) {
+                if (defines.FOG) {
                     fallbacks.addFallback(1, "FOG");
                 }
-                BABYLON.MaterialHelper.HandleFallbacksForShadows(this._defines, fallbacks);
-                if (this._defines.NUM_BONE_INFLUENCERS > 0) {
+                BABYLON.MaterialHelper.HandleFallbacksForShadows(defines, fallbacks);
+                if (defines.NUM_BONE_INFLUENCERS > 0) {
                     fallbacks.addCPUSkinningFallback(0, mesh);
                 }
                 //Attributes
                 var attribs = [BABYLON.VertexBuffer.PositionKind];
-                if (this._defines.NORMAL) {
+                if (defines.NORMAL) {
                     attribs.push(BABYLON.VertexBuffer.NormalKind);
                 }
-                if (this._defines.UV1) {
+                if (defines.UV1) {
                     attribs.push(BABYLON.VertexBuffer.UVKind);
                 }
-                if (this._defines.UV2) {
+                if (defines.UV2) {
                     attribs.push(BABYLON.VertexBuffer.UV2Kind);
                 }
-                if (this._defines.VERTEXCOLOR) {
+                if (defines.VERTEXCOLOR) {
                     attribs.push(BABYLON.VertexBuffer.ColorKind);
                 }
-                BABYLON.MaterialHelper.PrepareAttributesForBones(attribs, mesh, this._defines, fallbacks);
-                BABYLON.MaterialHelper.PrepareAttributesForInstances(attribs, this._defines);
+                BABYLON.MaterialHelper.PrepareAttributesForBones(attribs, mesh, defines, fallbacks);
+                BABYLON.MaterialHelper.PrepareAttributesForInstances(attribs, defines);
                 // Legacy browser patch
                 var shaderName = "lava";
-                var join = this._defines.toString();
-                this._effect = scene.getEngine().createEffect(shaderName, attribs, ["world", "view", "viewProjection", "vEyePosition", "vLightsType", "vDiffuseColor",
+                var join = defines.toString();
+                subMesh.setEffect(scene.getEngine().createEffect(shaderName, attribs, ["world", "view", "viewProjection", "vEyePosition", "vLightsType", "vDiffuseColor",
                     "vLightData0", "vLightDiffuse0", "vLightDirection0", "vLightGround0", "lightMatrix0",
                     "vLightData1", "vLightDiffuse1", "vLightDirection1", "vLightGround1", "lightMatrix1",
                     "vLightData2", "vLightDiffuse2", "vLightDirection2", "vLightGround2", "lightMatrix2",
@@ -231,63 +184,66 @@ var BABYLON;
                     "fogColor", "fogDensity", "lowFrequencySpeed"
                 ], ["diffuseSampler",
                     "shadowSampler0", "shadowSampler1", "shadowSampler2", "shadowSampler3", "noiseTexture"
-                ], join, fallbacks, this.onCompiled, this.onError, { maxSimultaneousLights: this.maxSimultaneousLights - 1 });
+                ], join, fallbacks, this.onCompiled, this.onError, { maxSimultaneousLights: this.maxSimultaneousLights - 1 }), defines);
             }
-            if (!this._effect.isReady()) {
+            if (!subMesh.effect.isReady()) {
                 return false;
             }
             this._renderId = scene.getRenderId();
             this._wasPreviouslyReady = true;
             return true;
         };
-        LavaMaterial.prototype.bindOnlyWorldMatrix = function (world) {
-            this._effect.setMatrix("world", world);
-        };
-        LavaMaterial.prototype.bind = function (world, mesh) {
+        LavaMaterial.prototype.bindForSubMesh = function (world, mesh, subMesh) {
             var scene = this.getScene();
+            var defines = subMesh._materialDefines;
+            if (!defines) {
+                return;
+            }
+            var effect = subMesh.effect;
+            this._activeEffect = effect;
             // Matrices        
             this.bindOnlyWorldMatrix(world);
-            this._effect.setMatrix("viewProjection", scene.getTransformMatrix());
+            this._activeEffect.setMatrix("viewProjection", scene.getTransformMatrix());
             // Bones
-            BABYLON.MaterialHelper.BindBonesParameters(mesh, this._effect);
-            if (scene.getCachedMaterial() !== this) {
+            BABYLON.MaterialHelper.BindBonesParameters(mesh, this._activeEffect);
+            if (this._mustRebind(scene, effect)) {
                 // Textures        
                 if (this.diffuseTexture && BABYLON.StandardMaterial.DiffuseTextureEnabled) {
-                    this._effect.setTexture("diffuseSampler", this.diffuseTexture);
-                    this._effect.setFloat2("vDiffuseInfos", this.diffuseTexture.coordinatesIndex, this.diffuseTexture.level);
-                    this._effect.setMatrix("diffuseMatrix", this.diffuseTexture.getTextureMatrix());
+                    this._activeEffect.setTexture("diffuseSampler", this.diffuseTexture);
+                    this._activeEffect.setFloat2("vDiffuseInfos", this.diffuseTexture.coordinatesIndex, this.diffuseTexture.level);
+                    this._activeEffect.setMatrix("diffuseMatrix", this.diffuseTexture.getTextureMatrix());
                 }
                 if (this.noiseTexture) {
-                    this._effect.setTexture("noiseTexture", this.noiseTexture);
+                    this._activeEffect.setTexture("noiseTexture", this.noiseTexture);
                 }
                 // Clip plane
-                BABYLON.MaterialHelper.BindClipPlane(this._effect, scene);
+                BABYLON.MaterialHelper.BindClipPlane(this._activeEffect, scene);
                 // Point size
                 if (this.pointsCloud) {
-                    this._effect.setFloat("pointSize", this.pointSize);
+                    this._activeEffect.setFloat("pointSize", this.pointSize);
                 }
-                this._effect.setVector3("vEyePosition", scene._mirroredCameraPosition ? scene._mirroredCameraPosition : scene.activeCamera.position);
+                this._activeEffect.setVector3("vEyePosition", scene._mirroredCameraPosition ? scene._mirroredCameraPosition : scene.activeCamera.position);
             }
-            this._effect.setColor4("vDiffuseColor", this._scaledDiffuse, this.alpha * mesh.visibility);
+            this._activeEffect.setColor4("vDiffuseColor", this._scaledDiffuse, this.alpha * mesh.visibility);
             if (scene.lightsEnabled && !this.disableLighting) {
-                BABYLON.MaterialHelper.BindLights(scene, mesh, this._effect, this._defines);
+                BABYLON.MaterialHelper.BindLights(scene, mesh, this._activeEffect, defines);
             }
             // View
             if (scene.fogEnabled && mesh.applyFog && scene.fogMode !== BABYLON.Scene.FOGMODE_NONE) {
-                this._effect.setMatrix("view", scene.getViewMatrix());
+                this._activeEffect.setMatrix("view", scene.getViewMatrix());
             }
             // Fog
-            BABYLON.MaterialHelper.BindFogParameters(scene, mesh, this._effect);
+            BABYLON.MaterialHelper.BindFogParameters(scene, mesh, this._activeEffect);
             this._lastTime += scene.getEngine().getDeltaTime();
-            this._effect.setFloat("time", this._lastTime * this.speed / 1000);
+            this._activeEffect.setFloat("time", this._lastTime * this.speed / 1000);
             if (!this.fogColor) {
                 this.fogColor = BABYLON.Color3.Black();
             }
-            this._effect.setColor3("fogColor", this.fogColor);
-            this._effect.setFloat("fogDensity", this.fogDensity);
-            this._effect.setFloat("lowFrequencySpeed", this.lowFrequencySpeed);
-            this._effect.setFloat("movingSpeed", this.movingSpeed);
-            this._afterBind(mesh);
+            this._activeEffect.setColor3("fogColor", this.fogColor);
+            this._activeEffect.setFloat("fogDensity", this.fogDensity);
+            this._activeEffect.setFloat("lowFrequencySpeed", this.lowFrequencySpeed);
+            this._activeEffect.setFloat("movingSpeed", this.movingSpeed);
+            this._afterBind(mesh, this._activeEffect);
         };
         LavaMaterial.prototype.getAnimatables = function () {
             var results = [];
@@ -322,9 +278,12 @@ var BABYLON;
             return BABYLON.SerializationHelper.Parse(function () { return new LavaMaterial(source.name, scene); }, source, scene, rootUrl);
         };
         return LavaMaterial;
-    }(BABYLON.Material));
+    }(BABYLON.PushMaterial));
     __decorate([
-        BABYLON.serializeAsTexture()
+        BABYLON.serializeAsTexture("diffuseTexture")
+    ], LavaMaterial.prototype, "_diffuseTexture", void 0);
+    __decorate([
+        BABYLON.expandToProperty("_markAllSubMeshesAsTexturesDirty")
     ], LavaMaterial.prototype, "diffuseTexture", void 0);
     __decorate([
         BABYLON.serializeAsTexture()
@@ -348,10 +307,16 @@ var BABYLON;
         BABYLON.serializeAsColor3()
     ], LavaMaterial.prototype, "diffuseColor", void 0);
     __decorate([
-        BABYLON.serialize()
+        BABYLON.serialize("disableLighting")
+    ], LavaMaterial.prototype, "_disableLighting", void 0);
+    __decorate([
+        BABYLON.expandToProperty("_markAllSubMeshesAsLightsDirty")
     ], LavaMaterial.prototype, "disableLighting", void 0);
     __decorate([
-        BABYLON.serialize()
+        BABYLON.serialize("maxSimultaneousLights")
+    ], LavaMaterial.prototype, "_maxSimultaneousLights", void 0);
+    __decorate([
+        BABYLON.expandToProperty("_markAllSubMeshesAsLightsDirty")
     ], LavaMaterial.prototype, "maxSimultaneousLights", void 0);
     BABYLON.LavaMaterial = LavaMaterial;
 })(BABYLON || (BABYLON = {}));

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


+ 7 - 7
dist/preview release/materialsLibrary/babylon.normalMaterial.d.ts

@@ -1,22 +1,22 @@
 /// <reference path="../../../dist/preview release/babylon.d.ts" />
 declare module BABYLON {
-    class NormalMaterial extends Material {
+    class NormalMaterial extends PushMaterial {
+        private _diffuseTexture;
         diffuseTexture: BaseTexture;
         diffuseColor: Color3;
+        private _disableLighting;
         disableLighting: boolean;
+        private _maxSimultaneousLights;
+        maxSimultaneousLights: number;
         private _worldViewProjectionMatrix;
         private _scaledDiffuse;
         private _renderId;
-        private _defines;
-        private _cachedDefines;
         constructor(name: string, scene: Scene);
         needAlphaBlending(): boolean;
         needAlphaTesting(): boolean;
         getAlphaTestTexture(): BaseTexture;
-        private _checkCache(scene, mesh?, useInstances?);
-        isReady(mesh?: AbstractMesh, useInstances?: boolean): boolean;
-        bindOnlyWorldMatrix(world: Matrix): void;
-        bind(world: Matrix, mesh?: Mesh): void;
+        isReadyForSubMesh(mesh: AbstractMesh, subMesh: SubMesh, useInstances?: boolean): boolean;
+        bindForSubMesh(world: Matrix, mesh: Mesh, subMesh: SubMesh): void;
         getAnimatables(): IAnimatable[];
         dispose(forceDisposeEffect?: boolean): void;
         clone(name: string): NormalMaterial;

+ 79 - 112
dist/preview release/materialsLibrary/babylon.normalMaterial.js

@@ -77,12 +77,10 @@ var BABYLON;
         function NormalMaterial(name, scene) {
             var _this = _super.call(this, name, scene) || this;
             _this.diffuseColor = new BABYLON.Color3(1, 1, 1);
-            _this.disableLighting = false;
+            _this._disableLighting = false;
+            _this._maxSimultaneousLights = 4;
             _this._worldViewProjectionMatrix = BABYLON.Matrix.Zero();
             _this._scaledDiffuse = new BABYLON.Color3();
-            _this._defines = new NormalMaterialDefines();
-            _this._cachedDefines = new NormalMaterialDefines();
-            _this._cachedDefines.BonesPerMesh = -1;
             return _this;
         }
         NormalMaterial.prototype.needAlphaBlending = function () {
@@ -95,124 +93,78 @@ var BABYLON;
             return null;
         };
         // Methods   
-        NormalMaterial.prototype._checkCache = function (scene, mesh, useInstances) {
-            if (!mesh) {
-                return true;
-            }
-            if (this._defines.INSTANCES !== useInstances) {
-                return false;
-            }
-            return false;
-        };
-        NormalMaterial.prototype.isReady = function (mesh, useInstances) {
-            if (this.checkReadyOnlyOnce) {
-                if (this._wasPreviouslyReady) {
+        NormalMaterial.prototype.isReadyForSubMesh = function (mesh, subMesh, useInstances) {
+            if (this.isFrozen) {
+                if (this._wasPreviouslyReady && subMesh.effect) {
                     return true;
                 }
             }
+            if (!subMesh._materialDefines) {
+                subMesh._materialDefines = new NormalMaterialDefines();
+            }
+            var defines = subMesh._materialDefines;
             var scene = this.getScene();
             if (!this.checkReadyOnEveryCall) {
                 if (this._renderId === scene.getRenderId()) {
-                    if (this._checkCache(scene, mesh, useInstances)) {
-                        return true;
-                    }
+                    return true;
                 }
             }
             var engine = scene.getEngine();
-            var needNormals = false;
-            var needUVs = false;
-            this._defines.reset();
             // Textures
-            if (scene.texturesEnabled) {
-                if (this.diffuseTexture && BABYLON.StandardMaterial.DiffuseTextureEnabled) {
-                    if (!this.diffuseTexture.isReady()) {
-                        return false;
-                    }
-                    else {
-                        needUVs = true;
-                        this._defines.DIFFUSE = true;
+            if (defines._areTexturesDirty) {
+                defines._needUVs = false;
+                if (scene.texturesEnabled) {
+                    if (this._diffuseTexture && BABYLON.StandardMaterial.DiffuseTextureEnabled) {
+                        if (!this._diffuseTexture.isReady()) {
+                            return false;
+                        }
+                        else {
+                            defines._needUVs = true;
+                            defines.DIFFUSE = true;
+                        }
                     }
                 }
             }
-            // Effect
-            if (scene.clipPlane) {
-                this._defines.CLIPPLANE = true;
-            }
-            if (engine.getAlphaTesting()) {
-                this._defines.ALPHATEST = 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;
-            }
-            var lightIndex = 0;
-            if (scene.lightsEnabled && !this.disableLighting) {
-                needNormals = BABYLON.MaterialHelper.PrepareDefinesForLights(scene, mesh, this._defines, false);
-            }
+            // Misc.
+            BABYLON.MaterialHelper.PrepareDefinesForMisc(mesh, scene, false, this.pointsCloud, this.fogEnabled, defines);
+            // Lights
+            defines._needNormals = BABYLON.MaterialHelper.PrepareDefinesForLights(scene, mesh, defines, false, this._maxSimultaneousLights, this._disableLighting);
+            // Values that need to be evaluated on every frame
+            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances);
             // 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;
-                }
-            }
+            BABYLON.MaterialHelper.PrepareDefinesForAttributes(mesh, defines, true, true);
             // Get correct effect      
-            if (!this._defines.isEqual(this._cachedDefines)) {
-                this._defines.cloneTo(this._cachedDefines);
+            if (defines.isDirty) {
+                defines.markAsProcessed();
                 scene.resetCachedMaterial();
                 // Fallbacks
                 var fallbacks = new BABYLON.EffectFallbacks();
-                if (this._defines.FOG) {
+                if (defines.FOG) {
                     fallbacks.addFallback(1, "FOG");
                 }
-                BABYLON.MaterialHelper.HandleFallbacksForShadows(this._defines, fallbacks);
-                if (this._defines.NUM_BONE_INFLUENCERS > 0) {
+                BABYLON.MaterialHelper.HandleFallbacksForShadows(defines, fallbacks);
+                if (defines.NUM_BONE_INFLUENCERS > 0) {
                     fallbacks.addCPUSkinningFallback(0, mesh);
                 }
                 //Attributes
                 var attribs = [BABYLON.VertexBuffer.PositionKind];
-                if (this._defines.NORMAL) {
+                if (defines.NORMAL) {
                     attribs.push(BABYLON.VertexBuffer.NormalKind);
                 }
-                if (this._defines.UV1) {
+                if (defines.UV1) {
                     attribs.push(BABYLON.VertexBuffer.UVKind);
                 }
-                if (this._defines.UV2) {
+                if (defines.UV2) {
                     attribs.push(BABYLON.VertexBuffer.UV2Kind);
                 }
-                if (this._defines.VERTEXCOLOR) {
+                if (defines.VERTEXCOLOR) {
                     attribs.push(BABYLON.VertexBuffer.ColorKind);
                 }
-                BABYLON.MaterialHelper.PrepareAttributesForBones(attribs, mesh, this._defines, fallbacks);
-                BABYLON.MaterialHelper.PrepareAttributesForInstances(attribs, this._defines);
+                BABYLON.MaterialHelper.PrepareAttributesForBones(attribs, mesh, defines, fallbacks);
+                BABYLON.MaterialHelper.PrepareAttributesForInstances(attribs, defines);
                 var shaderName = "normal";
-                var join = this._defines.toString();
-                this._effect = scene.getEngine().createEffect(shaderName, attribs, ["world", "view", "viewProjection", "vEyePosition", "vLightsType", "vDiffuseColor",
+                var join = defines.toString();
+                subMesh.setEffect(scene.getEngine().createEffect(shaderName, attribs, ["world", "view", "viewProjection", "vEyePosition", "vLightsType", "vDiffuseColor",
                     "vLightData0", "vLightDiffuse0", "vLightDirection0", "vLightGround0", "lightMatrix0",
                     "vLightData1", "vLightDiffuse1", "vLightDirection1", "vLightGround1", "lightMatrix1",
                     "vLightData2", "vLightDiffuse2", "vLightDirection2", "vLightGround2", "lightMatrix2",
@@ -224,52 +176,55 @@ var BABYLON;
                     "shadowsInfo0", "shadowsInfo1", "shadowsInfo2", "shadowsInfo3", "depthValues"
                 ], ["diffuseSampler",
                     "shadowSampler0", "shadowSampler1", "shadowSampler2", "shadowSampler3"
-                ], join, fallbacks, this.onCompiled, this.onError, { maxSimultaneousLights: 4 });
+                ], join, fallbacks, this.onCompiled, this.onError, { maxSimultaneousLights: 4 }), defines);
             }
-            if (!this._effect.isReady()) {
+            if (!subMesh.effect.isReady()) {
                 return false;
             }
             this._renderId = scene.getRenderId();
             this._wasPreviouslyReady = true;
             return true;
         };
-        NormalMaterial.prototype.bindOnlyWorldMatrix = function (world) {
-            this._effect.setMatrix("world", world);
-        };
-        NormalMaterial.prototype.bind = function (world, mesh) {
+        NormalMaterial.prototype.bindForSubMesh = function (world, mesh, subMesh) {
             var scene = this.getScene();
+            var defines = subMesh._materialDefines;
+            if (!defines) {
+                return;
+            }
+            var effect = subMesh.effect;
+            this._activeEffect = effect;
             // Matrices        
             this.bindOnlyWorldMatrix(world);
-            this._effect.setMatrix("viewProjection", scene.getTransformMatrix());
+            this._activeEffect.setMatrix("viewProjection", scene.getTransformMatrix());
             // Bones
-            BABYLON.MaterialHelper.BindBonesParameters(mesh, this._effect);
-            if (scene.getCachedMaterial() !== this) {
+            BABYLON.MaterialHelper.BindBonesParameters(mesh, this._activeEffect);
+            if (this._mustRebind(scene, effect)) {
                 // Textures        
                 if (this.diffuseTexture && BABYLON.StandardMaterial.DiffuseTextureEnabled) {
-                    this._effect.setTexture("diffuseSampler", this.diffuseTexture);
-                    this._effect.setFloat2("vDiffuseInfos", this.diffuseTexture.coordinatesIndex, this.diffuseTexture.level);
-                    this._effect.setMatrix("diffuseMatrix", this.diffuseTexture.getTextureMatrix());
+                    this._activeEffect.setTexture("diffuseSampler", this.diffuseTexture);
+                    this._activeEffect.setFloat2("vDiffuseInfos", this.diffuseTexture.coordinatesIndex, this.diffuseTexture.level);
+                    this._activeEffect.setMatrix("diffuseMatrix", this.diffuseTexture.getTextureMatrix());
                 }
                 // Clip plane
-                BABYLON.MaterialHelper.BindClipPlane(this._effect, scene);
+                BABYLON.MaterialHelper.BindClipPlane(this._activeEffect, scene);
                 // Point size
                 if (this.pointsCloud) {
-                    this._effect.setFloat("pointSize", this.pointSize);
+                    this._activeEffect.setFloat("pointSize", this.pointSize);
                 }
-                this._effect.setVector3("vEyePosition", scene._mirroredCameraPosition ? scene._mirroredCameraPosition : scene.activeCamera.position);
+                this._activeEffect.setVector3("vEyePosition", scene._mirroredCameraPosition ? scene._mirroredCameraPosition : scene.activeCamera.position);
             }
-            this._effect.setColor4("vDiffuseColor", this.diffuseColor, this.alpha * mesh.visibility);
+            this._activeEffect.setColor4("vDiffuseColor", this.diffuseColor, this.alpha * mesh.visibility);
             // Lights
             if (scene.lightsEnabled && !this.disableLighting) {
-                BABYLON.MaterialHelper.BindLights(scene, mesh, this._effect, this._defines);
+                BABYLON.MaterialHelper.BindLights(scene, mesh, this._activeEffect, defines);
             }
             // View
             if (scene.fogEnabled && mesh.applyFog && scene.fogMode !== BABYLON.Scene.FOGMODE_NONE) {
-                this._effect.setMatrix("view", scene.getViewMatrix());
+                this._activeEffect.setMatrix("view", scene.getViewMatrix());
             }
             // Fog
-            BABYLON.MaterialHelper.BindFogParameters(scene, mesh, this._effect);
-            this._afterBind(mesh);
+            BABYLON.MaterialHelper.BindFogParameters(scene, mesh, this._activeEffect);
+            this._afterBind(mesh, this._activeEffect);
         };
         NormalMaterial.prototype.getAnimatables = function () {
             var results = [];
@@ -298,16 +253,28 @@ var BABYLON;
             return BABYLON.SerializationHelper.Parse(function () { return new NormalMaterial(source.name, scene); }, source, scene, rootUrl);
         };
         return NormalMaterial;
-    }(BABYLON.Material));
+    }(BABYLON.PushMaterial));
     __decorate([
-        BABYLON.serializeAsTexture()
+        BABYLON.serializeAsTexture("diffuseTexture")
+    ], NormalMaterial.prototype, "_diffuseTexture", void 0);
+    __decorate([
+        BABYLON.expandToProperty("_markAllSubMeshesAsTexturesDirty")
     ], NormalMaterial.prototype, "diffuseTexture", void 0);
     __decorate([
         BABYLON.serializeAsColor3()
     ], NormalMaterial.prototype, "diffuseColor", void 0);
     __decorate([
-        BABYLON.serialize()
+        BABYLON.serialize("disableLighting")
+    ], NormalMaterial.prototype, "_disableLighting", void 0);
+    __decorate([
+        BABYLON.expandToProperty("_markAllSubMeshesAsLightsDirty")
     ], NormalMaterial.prototype, "disableLighting", void 0);
+    __decorate([
+        BABYLON.serialize("maxSimultaneousLights")
+    ], NormalMaterial.prototype, "_maxSimultaneousLights", void 0);
+    __decorate([
+        BABYLON.expandToProperty("_markAllSubMeshesAsLightsDirty")
+    ], NormalMaterial.prototype, "maxSimultaneousLights", void 0);
     BABYLON.NormalMaterial = NormalMaterial;
 })(BABYLON || (BABYLON = {}));
 

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


+ 3 - 7
dist/preview release/materialsLibrary/babylon.shadowOnlyMaterial.d.ts

@@ -1,19 +1,15 @@
 /// <reference path="../../../dist/preview release/babylon.d.ts" />
 declare module BABYLON {
-    class ShadowOnlyMaterial extends Material {
+    class ShadowOnlyMaterial extends PushMaterial {
         private _worldViewProjectionMatrix;
         private _scaledDiffuse;
         private _renderId;
-        private _defines;
-        private _cachedDefines;
         constructor(name: string, scene: Scene);
         needAlphaBlending(): boolean;
         needAlphaTesting(): boolean;
         getAlphaTestTexture(): BaseTexture;
-        private _checkCache(scene, mesh?, useInstances?);
-        isReady(mesh?: AbstractMesh, useInstances?: boolean): boolean;
-        bindOnlyWorldMatrix(world: Matrix): void;
-        bind(world: Matrix, mesh?: Mesh): void;
+        isReadyForSubMesh(mesh: AbstractMesh, subMesh: SubMesh, useInstances?: boolean): boolean;
+        bindForSubMesh(world: Matrix, mesh: Mesh, subMesh: SubMesh): void;
         clone(name: string): ShadowOnlyMaterial;
         serialize(): any;
         static Parse(source: any, scene: Scene, rootUrl: string): ShadowOnlyMaterial;

+ 42 - 75
dist/preview release/materialsLibrary/babylon.shadowOnlyMaterial.js

@@ -39,9 +39,6 @@ var BABYLON;
             var _this = _super.call(this, name, scene) || this;
             _this._worldViewProjectionMatrix = BABYLON.Matrix.Zero();
             _this._scaledDiffuse = new BABYLON.Color3();
-            _this._defines = new ShadowOnlyMaterialDefines();
-            _this._cachedDefines = new ShadowOnlyMaterialDefines();
-            _this._cachedDefines.BonesPerMesh = -1;
             return _this;
         }
         ShadowOnlyMaterial.prototype.needAlphaBlending = function () {
@@ -54,129 +51,99 @@ var BABYLON;
             return null;
         };
         // Methods   
-        ShadowOnlyMaterial.prototype._checkCache = function (scene, mesh, useInstances) {
-            if (!mesh) {
-                return true;
-            }
-            if (this._defines.INSTANCES !== useInstances) {
-                return false;
-            }
-            return false;
-        };
-        ShadowOnlyMaterial.prototype.isReady = function (mesh, useInstances) {
-            if (this.checkReadyOnlyOnce) {
-                if (this._wasPreviouslyReady) {
+        ShadowOnlyMaterial.prototype.isReadyForSubMesh = function (mesh, subMesh, useInstances) {
+            if (this.isFrozen) {
+                if (this._wasPreviouslyReady && subMesh.effect) {
                     return true;
                 }
             }
+            if (!subMesh._materialDefines) {
+                subMesh._materialDefines = new ShadowOnlyMaterialDefines();
+            }
+            var defines = subMesh._materialDefines;
             var scene = this.getScene();
             if (!this.checkReadyOnEveryCall) {
                 if (this._renderId === scene.getRenderId()) {
-                    if (this._checkCache(scene, mesh, useInstances)) {
-                        return true;
-                    }
+                    return true;
                 }
             }
             var engine = scene.getEngine();
-            var needNormals = false;
-            this._defines.reset();
-            // Effect
-            if (scene.clipPlane) {
-                this._defines.CLIPPLANE = 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 (scene.lightsEnabled) {
-                needNormals = BABYLON.MaterialHelper.PrepareDefinesForLights(scene, mesh, this._defines, false, 1);
-            }
+            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances);
+            BABYLON.MaterialHelper.PrepareDefinesForMisc(mesh, scene, false, this.pointsCloud, this.fogEnabled, defines);
+            defines._needNormals = BABYLON.MaterialHelper.PrepareDefinesForLights(scene, mesh, defines, false, 1);
             // Attribs
-            if (mesh) {
-                if (needNormals && mesh.isVerticesDataPresent(BABYLON.VertexBuffer.NormalKind)) {
-                    this._defines.NORMAL = 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;
-                }
-            }
+            BABYLON.MaterialHelper.PrepareDefinesForAttributes(mesh, defines, false, true);
             // Get correct effect      
-            if (!this._defines.isEqual(this._cachedDefines)) {
-                this._defines.cloneTo(this._cachedDefines);
+            if (defines.isDirty) {
+                defines.markAsProcessed();
                 scene.resetCachedMaterial();
                 // Fallbacks
                 var fallbacks = new BABYLON.EffectFallbacks();
-                if (this._defines.FOG) {
+                if (defines.FOG) {
                     fallbacks.addFallback(1, "FOG");
                 }
-                BABYLON.MaterialHelper.HandleFallbacksForShadows(this._defines, fallbacks, 1);
-                if (this._defines.NUM_BONE_INFLUENCERS > 0) {
+                BABYLON.MaterialHelper.HandleFallbacksForShadows(defines, fallbacks, 1);
+                if (defines.NUM_BONE_INFLUENCERS > 0) {
                     fallbacks.addCPUSkinningFallback(0, mesh);
                 }
                 //Attributes
                 var attribs = [BABYLON.VertexBuffer.PositionKind];
-                if (this._defines.NORMAL) {
+                if (defines.NORMAL) {
                     attribs.push(BABYLON.VertexBuffer.NormalKind);
                 }
-                BABYLON.MaterialHelper.PrepareAttributesForBones(attribs, mesh, this._defines, fallbacks);
-                BABYLON.MaterialHelper.PrepareAttributesForInstances(attribs, this._defines);
+                BABYLON.MaterialHelper.PrepareAttributesForBones(attribs, mesh, defines, fallbacks);
+                BABYLON.MaterialHelper.PrepareAttributesForInstances(attribs, defines);
                 var shaderName = "shadowOnly";
-                var join = this._defines.toString();
+                var join = defines.toString();
                 var uniforms = ["world", "view", "viewProjection", "vEyePosition", "vLightsType",
                     "vFogInfos", "vFogColor", "pointSize",
                     "mBones",
                     "vClipPlane", "depthValues"
                 ];
                 var samplers = [];
-                BABYLON.MaterialHelper.PrepareUniformsAndSamplersList(uniforms, samplers, this._defines, 1);
-                this._effect = scene.getEngine().createEffect(shaderName, attribs, uniforms, samplers, join, fallbacks, this.onCompiled, this.onError, { maxSimultaneousLights: 1 });
+                BABYLON.MaterialHelper.PrepareUniformsAndSamplersList(uniforms, samplers, defines, 1);
+                subMesh.setEffect(scene.getEngine().createEffect(shaderName, attribs, uniforms, samplers, join, fallbacks, this.onCompiled, this.onError, { maxSimultaneousLights: 1 }), defines);
             }
-            if (!this._effect.isReady()) {
+            if (!subMesh.effect.isReady()) {
                 return false;
             }
             this._renderId = scene.getRenderId();
             this._wasPreviouslyReady = true;
             return true;
         };
-        ShadowOnlyMaterial.prototype.bindOnlyWorldMatrix = function (world) {
-            this._effect.setMatrix("world", world);
-        };
-        ShadowOnlyMaterial.prototype.bind = function (world, mesh) {
+        ShadowOnlyMaterial.prototype.bindForSubMesh = function (world, mesh, subMesh) {
             var scene = this.getScene();
+            var defines = subMesh._materialDefines;
+            if (!defines) {
+                return;
+            }
+            var effect = subMesh.effect;
+            this._activeEffect = effect;
             // Matrices        
             this.bindOnlyWorldMatrix(world);
-            this._effect.setMatrix("viewProjection", scene.getTransformMatrix());
+            this._activeEffect.setMatrix("viewProjection", scene.getTransformMatrix());
             // Bones
-            BABYLON.MaterialHelper.BindBonesParameters(mesh, this._effect);
-            if (scene.getCachedMaterial() !== this) {
+            BABYLON.MaterialHelper.BindBonesParameters(mesh, this._activeEffect);
+            if (this._mustRebind(scene, effect)) {
                 // Clip plane
-                BABYLON.MaterialHelper.BindClipPlane(this._effect, scene);
+                BABYLON.MaterialHelper.BindClipPlane(this._activeEffect, scene);
                 // Point size
                 if (this.pointsCloud) {
-                    this._effect.setFloat("pointSize", this.pointSize);
+                    this._activeEffect.setFloat("pointSize", this.pointSize);
                 }
-                this._effect.setVector3("vEyePosition", scene._mirroredCameraPosition ? scene._mirroredCameraPosition : scene.activeCamera.position);
+                this._activeEffect.setVector3("vEyePosition", scene._mirroredCameraPosition ? scene._mirroredCameraPosition : scene.activeCamera.position);
             }
             // Lights
             if (scene.lightsEnabled) {
-                BABYLON.MaterialHelper.BindLights(scene, mesh, this._effect, this._defines, 1);
+                BABYLON.MaterialHelper.BindLights(scene, mesh, this._activeEffect, defines, 1);
             }
             // View
             if (scene.fogEnabled && mesh.applyFog && scene.fogMode !== BABYLON.Scene.FOGMODE_NONE) {
-                this._effect.setMatrix("view", scene.getViewMatrix());
+                this._activeEffect.setMatrix("view", scene.getViewMatrix());
             }
             // Fog
-            BABYLON.MaterialHelper.BindFogParameters(scene, mesh, this._effect);
-            this._afterBind(mesh);
+            BABYLON.MaterialHelper.BindFogParameters(scene, mesh, this._activeEffect);
+            this._afterBind(mesh, this._activeEffect);
         };
         ShadowOnlyMaterial.prototype.clone = function (name) {
             var _this = this;
@@ -192,7 +159,7 @@ var BABYLON;
             return BABYLON.SerializationHelper.Parse(function () { return new ShadowOnlyMaterial(source.name, scene); }, source, scene, rootUrl);
         };
         return ShadowOnlyMaterial;
-    }(BABYLON.Material));
+    }(BABYLON.PushMaterial));
     __decorate([
         BABYLON.serialize()
     ], ShadowOnlyMaterial.prototype, "_worldViewProjectionMatrix", void 0);

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


+ 2 - 9
dist/preview release/materialsLibrary/babylon.simpleMaterial.js

@@ -91,22 +91,15 @@ var BABYLON;
                         }
                     }
                 }
-                defines._areTexturesDirty = false;
             }
             // Misc.
-            if (defines._areMiscDirty) {
-                defines.POINTSIZE = (this.pointsCloud || scene.forcePointsCloud);
-                defines.FOG = (scene.fogEnabled && mesh.applyFog && scene.fogMode !== BABYLON.Scene.FOGMODE_NONE && this.fogEnabled);
-                defines._areMiscDirty = false;
-            }
+            BABYLON.MaterialHelper.PrepareDefinesForMisc(mesh, scene, false, this.pointsCloud, this.fogEnabled, defines);
             // Lights
             defines._needNormals = BABYLON.MaterialHelper.PrepareDefinesForLights(scene, mesh, defines, false, this._maxSimultaneousLights, this._disableLighting);
-            defines._areLightsDirty = false;
             // Values that need to be evaluated on every frame
             BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances);
             // Attribs
-            BABYLON.MaterialHelper.PrepareDefinesForAttributes(mesh, defines, useInstances);
-            defines._areAttributesDirty = false;
+            BABYLON.MaterialHelper.PrepareDefinesForAttributes(mesh, defines, true, true);
             // Get correct effect      
             if (defines.isDirty) {
                 defines.markAsProcessed();

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


+ 3 - 7
dist/preview release/materialsLibrary/babylon.skyMaterial.d.ts

@@ -1,6 +1,6 @@
 /// <reference path="../../../dist/preview release/babylon.d.ts" />
 declare module BABYLON {
-    class SkyMaterial extends Material {
+    class SkyMaterial extends PushMaterial {
         luminance: number;
         turbidity: number;
         rayleigh: number;
@@ -13,16 +13,12 @@ declare module BABYLON {
         useSunPosition: boolean;
         private _cameraPosition;
         private _renderId;
-        private _defines;
-        private _cachedDefines;
         constructor(name: string, scene: Scene);
         needAlphaBlending(): boolean;
         needAlphaTesting(): boolean;
         getAlphaTestTexture(): BaseTexture;
-        private _checkCache(scene, mesh?, useInstances?);
-        isReady(mesh?: AbstractMesh, useInstances?: boolean): boolean;
-        bindOnlyWorldMatrix(world: Matrix): void;
-        bind(world: Matrix, mesh?: Mesh): void;
+        isReadyForSubMesh(mesh: AbstractMesh, subMesh: SubMesh, useInstances?: boolean): boolean;
+        bindForSubMesh(world: Matrix, mesh: Mesh, subMesh: SubMesh): void;
         getAnimatables(): IAnimatable[];
         dispose(forceDisposeEffect?: boolean): void;
         clone(name: string): SkyMaterial;

+ 40 - 63
dist/preview release/materialsLibrary/babylon.skyMaterial.js

@@ -48,8 +48,6 @@ var BABYLON;
             _this.useSunPosition = false;
             // Private members
             _this._cameraPosition = BABYLON.Vector3.Zero();
-            _this._defines = new SkyMaterialDefines();
-            _this._cachedDefines = new SkyMaterialDefines();
             return _this;
         }
         SkyMaterial.prototype.needAlphaBlending = function () {
@@ -62,104 +60,83 @@ var BABYLON;
             return null;
         };
         // Methods   
-        SkyMaterial.prototype._checkCache = function (scene, mesh, useInstances) {
-            if (!mesh) {
-                return true;
-            }
-            return false;
-        };
-        SkyMaterial.prototype.isReady = function (mesh, useInstances) {
-            if (this.checkReadyOnlyOnce) {
-                if (this._wasPreviouslyReady) {
+        SkyMaterial.prototype.isReadyForSubMesh = function (mesh, subMesh, useInstances) {
+            if (this.isFrozen) {
+                if (this._wasPreviouslyReady && subMesh.effect) {
                     return true;
                 }
             }
+            if (!subMesh._materialDefines) {
+                subMesh._materialDefines = new SkyMaterialDefines();
+            }
+            var defines = subMesh._materialDefines;
             var scene = this.getScene();
             if (!this.checkReadyOnEveryCall) {
                 if (this._renderId === scene.getRenderId()) {
-                    if (this._checkCache(scene, mesh, useInstances)) {
-                        return true;
-                    }
+                    return true;
                 }
             }
             var engine = scene.getEngine();
-            this._defines.reset();
-            // Effect
-            if (scene.clipPlane) {
-                this._defines.CLIPPLANE = 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;
-            }
+            BABYLON.MaterialHelper.PrepareDefinesForMisc(mesh, scene, false, this.pointsCloud, this.fogEnabled, defines);
             // Attribs
-            if (mesh) {
-                if (mesh.useVertexColors && mesh.isVerticesDataPresent(BABYLON.VertexBuffer.ColorKind)) {
-                    this._defines.VERTEXCOLOR = true;
-                    if (mesh.hasVertexAlpha) {
-                        this._defines.VERTEXALPHA = true;
-                    }
-                }
-            }
+            BABYLON.MaterialHelper.PrepareDefinesForAttributes(mesh, defines, true, false);
             // Get correct effect      
-            if (!this._defines.isEqual(this._cachedDefines) || !this._effect) {
-                this._defines.cloneTo(this._cachedDefines);
+            if (defines.isDirty) {
+                defines.markAsProcessed();
                 scene.resetCachedMaterial();
                 // Fallbacks
                 var fallbacks = new BABYLON.EffectFallbacks();
-                if (this._defines.FOG) {
+                if (defines.FOG) {
                     fallbacks.addFallback(1, "FOG");
                 }
                 //Attributes
                 var attribs = [BABYLON.VertexBuffer.PositionKind];
-                if (this._defines.VERTEXCOLOR) {
+                if (defines.VERTEXCOLOR) {
                     attribs.push(BABYLON.VertexBuffer.ColorKind);
                 }
-                // Legacy browser patch
                 var shaderName = "sky";
-                var join = this._defines.toString();
-                this._effect = scene.getEngine().createEffect(shaderName, attribs, ["world", "viewProjection", "view",
+                var join = defines.toString();
+                subMesh.setEffect(scene.getEngine().createEffect(shaderName, attribs, ["world", "viewProjection", "view",
                     "vFogInfos", "vFogColor", "pointSize", "vClipPlane",
                     "luminance", "turbidity", "rayleigh", "mieCoefficient", "mieDirectionalG", "sunPosition",
                     "cameraPosition"
-                ], [], join, fallbacks, this.onCompiled, this.onError);
+                ], [], join, fallbacks, this.onCompiled, this.onError), defines);
             }
-            if (!this._effect.isReady()) {
+            if (!subMesh.effect.isReady()) {
                 return false;
             }
             this._renderId = scene.getRenderId();
             this._wasPreviouslyReady = true;
             return true;
         };
-        SkyMaterial.prototype.bindOnlyWorldMatrix = function (world) {
-            this._effect.setMatrix("world", world);
-        };
-        SkyMaterial.prototype.bind = function (world, mesh) {
+        SkyMaterial.prototype.bindForSubMesh = function (world, mesh, subMesh) {
             var scene = this.getScene();
+            var defines = subMesh._materialDefines;
+            if (!defines) {
+                return;
+            }
+            var effect = subMesh.effect;
+            this._activeEffect = effect;
             // Matrices        
             this.bindOnlyWorldMatrix(world);
-            this._effect.setMatrix("viewProjection", scene.getTransformMatrix());
-            if (scene.getCachedMaterial() !== this) {
+            this._activeEffect.setMatrix("viewProjection", scene.getTransformMatrix());
+            if (this._mustRebind(scene, effect)) {
                 // Clip plane
                 if (scene.clipPlane) {
                     var clipPlane = scene.clipPlane;
-                    this._effect.setFloat4("vClipPlane", clipPlane.normal.x, clipPlane.normal.y, clipPlane.normal.z, clipPlane.d);
+                    this._activeEffect.setFloat4("vClipPlane", clipPlane.normal.x, clipPlane.normal.y, clipPlane.normal.z, clipPlane.d);
                 }
                 // Point size
                 if (this.pointsCloud) {
-                    this._effect.setFloat("pointSize", this.pointSize);
+                    this._activeEffect.setFloat("pointSize", this.pointSize);
                 }
             }
             // View
             if (scene.fogEnabled && mesh.applyFog && scene.fogMode !== BABYLON.Scene.FOGMODE_NONE) {
-                this._effect.setMatrix("view", scene.getViewMatrix());
+                this._activeEffect.setMatrix("view", scene.getViewMatrix());
             }
             // Fog
-            BABYLON.MaterialHelper.BindFogParameters(scene, mesh, this._effect);
+            BABYLON.MaterialHelper.BindFogParameters(scene, mesh, this._activeEffect);
             // Sky
             var camera = scene.activeCamera;
             if (camera) {
@@ -167,15 +144,15 @@ var BABYLON;
                 this._cameraPosition.x = cameraWorldMatrix.m[12];
                 this._cameraPosition.y = cameraWorldMatrix.m[13];
                 this._cameraPosition.z = cameraWorldMatrix.m[14];
-                this._effect.setVector3("cameraPosition", this._cameraPosition);
+                this._activeEffect.setVector3("cameraPosition", this._cameraPosition);
             }
             if (this.luminance > 0) {
-                this._effect.setFloat("luminance", this.luminance);
+                this._activeEffect.setFloat("luminance", this.luminance);
             }
-            this._effect.setFloat("turbidity", this.turbidity);
-            this._effect.setFloat("rayleigh", this.rayleigh);
-            this._effect.setFloat("mieCoefficient", this.mieCoefficient);
-            this._effect.setFloat("mieDirectionalG", this.mieDirectionalG);
+            this._activeEffect.setFloat("turbidity", this.turbidity);
+            this._activeEffect.setFloat("rayleigh", this.rayleigh);
+            this._activeEffect.setFloat("mieCoefficient", this.mieCoefficient);
+            this._activeEffect.setFloat("mieDirectionalG", this.mieDirectionalG);
             if (!this.useSunPosition) {
                 var theta = Math.PI * (this.inclination - 0.5);
                 var phi = 2 * Math.PI * (this.azimuth - 0.5);
@@ -183,8 +160,8 @@ var BABYLON;
                 this.sunPosition.y = this.distance * Math.sin(phi) * Math.sin(theta);
                 this.sunPosition.z = this.distance * Math.sin(phi) * Math.cos(theta);
             }
-            this._effect.setVector3("sunPosition", this.sunPosition);
-            this._afterBind(mesh);
+            this._activeEffect.setVector3("sunPosition", this.sunPosition);
+            this._afterBind(mesh, this._activeEffect);
         };
         SkyMaterial.prototype.getAnimatables = function () {
             return [];
@@ -206,7 +183,7 @@ var BABYLON;
             return BABYLON.SerializationHelper.Parse(function () { return new SkyMaterial(source.name, scene); }, source, scene, rootUrl);
         };
         return SkyMaterial;
-    }(BABYLON.Material));
+    }(BABYLON.PushMaterial));
     __decorate([
         BABYLON.serialize()
     ], SkyMaterial.prototype, "luminance", void 0);

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


+ 12 - 7
dist/preview release/materialsLibrary/babylon.terrainMaterial.d.ts

@@ -1,30 +1,35 @@
 /// <reference path="../../../dist/preview release/babylon.d.ts" />
 declare module BABYLON {
-    class TerrainMaterial extends Material {
+    class TerrainMaterial extends PushMaterial {
+        private _mixTexture;
         mixTexture: BaseTexture;
+        private _diffuseTexture1;
         diffuseTexture1: Texture;
+        private _diffuseTexture2;
         diffuseTexture2: Texture;
+        private _diffuseTexture3;
         diffuseTexture3: Texture;
+        private _bumpTexture1;
         bumpTexture1: Texture;
+        private _bumpTexture2;
         bumpTexture2: Texture;
+        private _bumpTexture3;
         bumpTexture3: Texture;
         diffuseColor: Color3;
         specularColor: Color3;
         specularPower: number;
+        private _disableLighting;
         disableLighting: boolean;
+        private _maxSimultaneousLights;
         maxSimultaneousLights: number;
         private _worldViewProjectionMatrix;
         private _renderId;
-        private _defines;
-        private _cachedDefines;
         constructor(name: string, scene: Scene);
         needAlphaBlending(): boolean;
         needAlphaTesting(): boolean;
         getAlphaTestTexture(): BaseTexture;
-        private _checkCache(scene, mesh?, useInstances?);
-        isReady(mesh?: AbstractMesh, useInstances?: boolean): boolean;
-        bindOnlyWorldMatrix(world: Matrix): void;
-        bind(world: Matrix, mesh?: Mesh): void;
+        isReadyForSubMesh(mesh: AbstractMesh, subMesh: SubMesh, useInstances?: boolean): boolean;
+        bindForSubMesh(world: Matrix, mesh: Mesh, subMesh: SubMesh): void;
         getAnimatables(): IAnimatable[];
         dispose(forceDisposeEffect?: boolean): void;
         clone(name: string): TerrainMaterial;

+ 112 - 135
dist/preview release/materialsLibrary/babylon.terrainMaterial.js

@@ -17,7 +17,6 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
 };
 var BABYLON;
 (function (BABYLON) {
-    var maxSimultaneousLights = 4;
     var TerrainMaterialDefines = (function (_super) {
         __extends(TerrainMaterialDefines, _super);
         function TerrainMaterialDefines() {
@@ -49,12 +48,9 @@ var BABYLON;
             _this.diffuseColor = new BABYLON.Color3(1, 1, 1);
             _this.specularColor = new BABYLON.Color3(0, 0, 0);
             _this.specularPower = 64;
-            _this.disableLighting = false;
-            _this.maxSimultaneousLights = 4;
+            _this._disableLighting = false;
+            _this._maxSimultaneousLights = 4;
             _this._worldViewProjectionMatrix = BABYLON.Matrix.Zero();
-            _this._defines = new TerrainMaterialDefines();
-            _this._cachedDefines = new TerrainMaterialDefines();
-            _this._cachedDefines.BonesPerMesh = -1;
             return _this;
         }
         TerrainMaterial.prototype.needAlphaBlending = function () {
@@ -67,52 +63,23 @@ var BABYLON;
             return null;
         };
         // Methods   
-        TerrainMaterial.prototype._checkCache = function (scene, mesh, useInstances) {
-            if (!mesh) {
-                return true;
-            }
-            if (this._defines.INSTANCES !== useInstances) {
-                return false;
-            }
-            return false;
-        };
-        TerrainMaterial.prototype.isReady = function (mesh, useInstances) {
-            if (this.checkReadyOnlyOnce) {
-                if (this._wasPreviouslyReady) {
+        TerrainMaterial.prototype.isReadyForSubMesh = function (mesh, subMesh, useInstances) {
+            if (this.isFrozen) {
+                if (this._wasPreviouslyReady && subMesh.effect) {
                     return true;
                 }
             }
+            if (!subMesh._materialDefines) {
+                subMesh._materialDefines = new TerrainMaterialDefines();
+            }
+            var defines = subMesh._materialDefines;
             var scene = this.getScene();
             if (!this.checkReadyOnEveryCall) {
                 if (this._renderId === scene.getRenderId()) {
-                    if (this._checkCache(scene, mesh, useInstances)) {
-                        return true;
-                    }
+                    return true;
                 }
             }
             var engine = scene.getEngine();
-            var needNormals = false;
-            var needUVs = false;
-            this._defines.reset();
-            // Effect
-            if (scene.clipPlane) {
-                this._defines.CLIPPLANE = true;
-            }
-            if (engine.getAlphaTesting()) {
-                this._defines.ALPHATEST = 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;
-            }
-            // Lights
-            if (scene.lightsEnabled && !this.disableLighting) {
-                needNormals = BABYLON.MaterialHelper.PrepareDefinesForLights(scene, mesh, this._defines, true, this.maxSimultaneousLights);
-            }
             // Textures
             if (scene.texturesEnabled) {
                 if (this.mixTexture && BABYLON.StandardMaterial.DiffuseTextureEnabled) {
@@ -120,76 +87,56 @@ var BABYLON;
                         return false;
                     }
                     else {
-                        needUVs = true;
-                        this._defines.DIFFUSE = true;
+                        defines._needUVs = true;
+                        defines.DIFFUSE = true;
                     }
                 }
                 if ((this.bumpTexture1 || this.bumpTexture2 || this.bumpTexture3) && BABYLON.StandardMaterial.BumpTextureEnabled) {
-                    needUVs = true;
-                    needNormals = true;
-                    this._defines.BUMP = true;
+                    defines._needUVs = true;
+                    defines._needNormals = true;
+                    defines.BUMP = true;
                 }
             }
+            // Misc.
+            BABYLON.MaterialHelper.PrepareDefinesForMisc(mesh, scene, false, this.pointsCloud, this.fogEnabled, defines);
+            // Lights
+            defines._needNormals = BABYLON.MaterialHelper.PrepareDefinesForLights(scene, mesh, defines, false, this._maxSimultaneousLights, this._disableLighting);
+            // Values that need to be evaluated on every frame
+            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances);
             // 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;
-                }
-            }
+            BABYLON.MaterialHelper.PrepareDefinesForAttributes(mesh, defines, true, true);
             // Get correct effect      
-            if (!this._defines.isEqual(this._cachedDefines)) {
-                this._defines.cloneTo(this._cachedDefines);
+            if (defines.isDirty) {
+                defines.markAsProcessed();
                 scene.resetCachedMaterial();
                 // Fallbacks
                 var fallbacks = new BABYLON.EffectFallbacks();
-                if (this._defines.FOG) {
+                if (defines.FOG) {
                     fallbacks.addFallback(1, "FOG");
                 }
-                BABYLON.MaterialHelper.HandleFallbacksForShadows(this._defines, fallbacks, this.maxSimultaneousLights);
-                if (this._defines.NUM_BONE_INFLUENCERS > 0) {
+                BABYLON.MaterialHelper.HandleFallbacksForShadows(defines, fallbacks, this.maxSimultaneousLights);
+                if (defines.NUM_BONE_INFLUENCERS > 0) {
                     fallbacks.addCPUSkinningFallback(0, mesh);
                 }
                 //Attributes
                 var attribs = [BABYLON.VertexBuffer.PositionKind];
-                if (this._defines.NORMAL) {
+                if (defines.NORMAL) {
                     attribs.push(BABYLON.VertexBuffer.NormalKind);
                 }
-                if (this._defines.UV1) {
+                if (defines.UV1) {
                     attribs.push(BABYLON.VertexBuffer.UVKind);
                 }
-                if (this._defines.UV2) {
+                if (defines.UV2) {
                     attribs.push(BABYLON.VertexBuffer.UV2Kind);
                 }
-                if (this._defines.VERTEXCOLOR) {
+                if (defines.VERTEXCOLOR) {
                     attribs.push(BABYLON.VertexBuffer.ColorKind);
                 }
-                BABYLON.MaterialHelper.PrepareAttributesForBones(attribs, mesh, this._defines, fallbacks);
-                BABYLON.MaterialHelper.PrepareAttributesForInstances(attribs, this._defines);
+                BABYLON.MaterialHelper.PrepareAttributesForBones(attribs, mesh, defines, fallbacks);
+                BABYLON.MaterialHelper.PrepareAttributesForInstances(attribs, defines);
                 // Legacy browser patch
                 var shaderName = "terrain";
-                var join = this._defines.toString();
+                var join = defines.toString();
                 var uniforms = ["world", "view", "viewProjection", "vEyePosition", "vLightsType", "vDiffuseColor", "vSpecularColor",
                     "vFogInfos", "vFogColor", "pointSize",
                     "vTextureInfos",
@@ -200,80 +147,83 @@ var BABYLON;
                 var samplers = ["textureSampler", "diffuse1Sampler", "diffuse2Sampler", "diffuse3Sampler",
                     "bump1Sampler", "bump2Sampler", "bump3Sampler"
                 ];
-                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 });
+                BABYLON.MaterialHelper.PrepareUniformsAndSamplersList(uniforms, samplers, defines, this.maxSimultaneousLights);
+                subMesh.setEffect(scene.getEngine().createEffect(shaderName, attribs, uniforms, samplers, join, fallbacks, this.onCompiled, this.onError, { maxSimultaneousLights: this.maxSimultaneousLights }), defines);
             }
-            if (!this._effect.isReady()) {
+            if (!subMesh.effect.isReady()) {
                 return false;
             }
             this._renderId = scene.getRenderId();
             this._wasPreviouslyReady = true;
             return true;
         };
-        TerrainMaterial.prototype.bindOnlyWorldMatrix = function (world) {
-            this._effect.setMatrix("world", world);
-        };
-        TerrainMaterial.prototype.bind = function (world, mesh) {
+        TerrainMaterial.prototype.bindForSubMesh = function (world, mesh, subMesh) {
             var scene = this.getScene();
+            var defines = subMesh._materialDefines;
+            if (!defines) {
+                return;
+            }
+            var effect = subMesh.effect;
+            this._activeEffect = effect;
             // Matrices        
             this.bindOnlyWorldMatrix(world);
-            this._effect.setMatrix("viewProjection", scene.getTransformMatrix());
+            this._activeEffect.setMatrix("viewProjection", scene.getTransformMatrix());
             // Bones
-            BABYLON.MaterialHelper.BindBonesParameters(mesh, this._effect);
-            if (scene.getCachedMaterial() !== this) {
+            BABYLON.MaterialHelper.BindBonesParameters(mesh, this._activeEffect);
+            if (this._mustRebind(scene, effect)) {
                 // Textures        
                 if (this.mixTexture) {
-                    this._effect.setTexture("textureSampler", this.mixTexture);
-                    this._effect.setFloat2("vTextureInfos", this.mixTexture.coordinatesIndex, this.mixTexture.level);
-                    this._effect.setMatrix("textureMatrix", this.mixTexture.getTextureMatrix());
+                    this._activeEffect.setTexture("textureSampler", this._mixTexture);
+                    this._activeEffect.setFloat2("vTextureInfos", this._mixTexture.coordinatesIndex, this._mixTexture.level);
+                    this._activeEffect.setMatrix("textureMatrix", this._mixTexture.getTextureMatrix());
                     if (BABYLON.StandardMaterial.DiffuseTextureEnabled) {
-                        if (this.diffuseTexture1) {
-                            this._effect.setTexture("diffuse1Sampler", this.diffuseTexture1);
-                            this._effect.setFloat2("diffuse1Infos", this.diffuseTexture1.uScale, this.diffuseTexture1.vScale);
+                        if (this._diffuseTexture1) {
+                            this._activeEffect.setTexture("diffuse1Sampler", this._diffuseTexture1);
+                            this._activeEffect.setFloat2("diffuse1Infos", this._diffuseTexture1.uScale, this._diffuseTexture1.vScale);
                         }
-                        if (this.diffuseTexture2) {
-                            this._effect.setTexture("diffuse2Sampler", this.diffuseTexture2);
-                            this._effect.setFloat2("diffuse2Infos", this.diffuseTexture2.uScale, this.diffuseTexture2.vScale);
+                        if (this._diffuseTexture2) {
+                            this._activeEffect.setTexture("diffuse2Sampler", this._diffuseTexture2);
+                            this._activeEffect.setFloat2("diffuse2Infos", this._diffuseTexture2.uScale, this._diffuseTexture2.vScale);
                         }
-                        if (this.diffuseTexture3) {
-                            this._effect.setTexture("diffuse3Sampler", this.diffuseTexture3);
-                            this._effect.setFloat2("diffuse3Infos", this.diffuseTexture3.uScale, this.diffuseTexture3.vScale);
+                        if (this._diffuseTexture3) {
+                            this._activeEffect.setTexture("diffuse3Sampler", this._diffuseTexture3);
+                            this._activeEffect.setFloat2("diffuse3Infos", this._diffuseTexture3.uScale, this._diffuseTexture3.vScale);
                         }
                     }
                     if (BABYLON.StandardMaterial.BumpTextureEnabled && scene.getEngine().getCaps().standardDerivatives) {
-                        if (this.bumpTexture1) {
-                            this._effect.setTexture("bump1Sampler", this.bumpTexture1);
+                        if (this._bumpTexture1) {
+                            this._activeEffect.setTexture("bump1Sampler", this._bumpTexture1);
                         }
-                        if (this.bumpTexture2) {
-                            this._effect.setTexture("bump2Sampler", this.bumpTexture2);
+                        if (this._bumpTexture2) {
+                            this._activeEffect.setTexture("bump2Sampler", this._bumpTexture2);
                         }
-                        if (this.bumpTexture3) {
-                            this._effect.setTexture("bump3Sampler", this.bumpTexture3);
+                        if (this._bumpTexture3) {
+                            this._activeEffect.setTexture("bump3Sampler", this._bumpTexture3);
                         }
                     }
                 }
                 // Clip plane
-                BABYLON.MaterialHelper.BindClipPlane(this._effect, scene);
+                BABYLON.MaterialHelper.BindClipPlane(this._activeEffect, scene);
                 // Point size
                 if (this.pointsCloud) {
-                    this._effect.setFloat("pointSize", this.pointSize);
+                    this._activeEffect.setFloat("pointSize", this.pointSize);
                 }
-                this._effect.setVector3("vEyePosition", scene._mirroredCameraPosition ? scene._mirroredCameraPosition : scene.activeCamera.position);
+                this._activeEffect.setVector3("vEyePosition", scene._mirroredCameraPosition ? scene._mirroredCameraPosition : scene.activeCamera.position);
             }
-            this._effect.setColor4("vDiffuseColor", this.diffuseColor, this.alpha * mesh.visibility);
-            if (this._defines.SPECULARTERM) {
-                this._effect.setColor4("vSpecularColor", this.specularColor, this.specularPower);
+            this._activeEffect.setColor4("vDiffuseColor", this.diffuseColor, this.alpha * mesh.visibility);
+            if (defines.SPECULARTERM) {
+                this._activeEffect.setColor4("vSpecularColor", this.specularColor, this.specularPower);
             }
             if (scene.lightsEnabled && !this.disableLighting) {
-                BABYLON.MaterialHelper.BindLights(scene, mesh, this._effect, this._defines, this.maxSimultaneousLights);
+                BABYLON.MaterialHelper.BindLights(scene, mesh, this._activeEffect, defines, this.maxSimultaneousLights);
             }
             // View
             if (scene.fogEnabled && mesh.applyFog && scene.fogMode !== BABYLON.Scene.FOGMODE_NONE) {
-                this._effect.setMatrix("view", scene.getViewMatrix());
+                this._activeEffect.setMatrix("view", scene.getViewMatrix());
             }
             // Fog
-            BABYLON.MaterialHelper.BindFogParameters(scene, mesh, this._effect);
-            this._afterBind(mesh);
+            BABYLON.MaterialHelper.BindFogParameters(scene, mesh, this._activeEffect);
+            this._afterBind(mesh, this._activeEffect);
         };
         TerrainMaterial.prototype.getAnimatables = function () {
             var results = [];
@@ -302,27 +252,48 @@ var BABYLON;
             return BABYLON.SerializationHelper.Parse(function () { return new TerrainMaterial(source.name, scene); }, source, scene, rootUrl);
         };
         return TerrainMaterial;
-    }(BABYLON.Material));
+    }(BABYLON.PushMaterial));
     __decorate([
-        BABYLON.serializeAsTexture()
+        BABYLON.serializeAsTexture("mixTexture")
+    ], TerrainMaterial.prototype, "_mixTexture", void 0);
+    __decorate([
+        BABYLON.expandToProperty("_markAllSubMeshesAsTexturesDirty")
     ], TerrainMaterial.prototype, "mixTexture", void 0);
     __decorate([
-        BABYLON.serializeAsTexture()
+        BABYLON.serializeAsTexture("diffuseTexture1")
+    ], TerrainMaterial.prototype, "_diffuseTexture1", void 0);
+    __decorate([
+        BABYLON.expandToProperty("_markAllSubMeshesAsTexturesDirty")
     ], TerrainMaterial.prototype, "diffuseTexture1", void 0);
     __decorate([
-        BABYLON.serializeAsTexture()
+        BABYLON.serializeAsTexture("diffuseTexture2")
+    ], TerrainMaterial.prototype, "_diffuseTexture2", void 0);
+    __decorate([
+        BABYLON.expandToProperty("_markAllSubMeshesAsTexturesDirty")
     ], TerrainMaterial.prototype, "diffuseTexture2", void 0);
     __decorate([
-        BABYLON.serializeAsTexture()
+        BABYLON.serializeAsTexture("diffuseTexture3")
+    ], TerrainMaterial.prototype, "_diffuseTexture3", void 0);
+    __decorate([
+        BABYLON.expandToProperty("_markAllSubMeshesAsTexturesDirty")
     ], TerrainMaterial.prototype, "diffuseTexture3", void 0);
     __decorate([
-        BABYLON.serializeAsTexture()
+        BABYLON.serializeAsTexture("bumpTexture1")
+    ], TerrainMaterial.prototype, "_bumpTexture1", void 0);
+    __decorate([
+        BABYLON.expandToProperty("_markAllSubMeshesAsTexturesDirty")
     ], TerrainMaterial.prototype, "bumpTexture1", void 0);
     __decorate([
-        BABYLON.serializeAsTexture()
+        BABYLON.serializeAsTexture("bumpTexture2")
+    ], TerrainMaterial.prototype, "_bumpTexture2", void 0);
+    __decorate([
+        BABYLON.expandToProperty("_markAllSubMeshesAsTexturesDirty")
     ], TerrainMaterial.prototype, "bumpTexture2", void 0);
     __decorate([
-        BABYLON.serializeAsTexture()
+        BABYLON.serializeAsTexture("bumpTexture3")
+    ], TerrainMaterial.prototype, "_bumpTexture3", void 0);
+    __decorate([
+        BABYLON.expandToProperty("_markAllSubMeshesAsTexturesDirty")
     ], TerrainMaterial.prototype, "bumpTexture3", void 0);
     __decorate([
         BABYLON.serializeAsColor3()
@@ -334,10 +305,16 @@ var BABYLON;
         BABYLON.serialize()
     ], TerrainMaterial.prototype, "specularPower", void 0);
     __decorate([
-        BABYLON.serialize()
+        BABYLON.serialize("disableLighting")
+    ], TerrainMaterial.prototype, "_disableLighting", void 0);
+    __decorate([
+        BABYLON.expandToProperty("_markAllSubMeshesAsLightsDirty")
     ], TerrainMaterial.prototype, "disableLighting", void 0);
     __decorate([
-        BABYLON.serialize()
+        BABYLON.serialize("maxSimultaneousLights")
+    ], TerrainMaterial.prototype, "_maxSimultaneousLights", void 0);
+    __decorate([
+        BABYLON.expandToProperty("_markAllSubMeshesAsLightsDirty")
     ], TerrainMaterial.prototype, "maxSimultaneousLights", void 0);
     BABYLON.TerrainMaterial = TerrainMaterial;
 })(BABYLON || (BABYLON = {}));

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


+ 17 - 13
dist/preview release/materialsLibrary/babylon.triPlanarMaterial.d.ts

@@ -1,31 +1,35 @@
 /// <reference path="../../../dist/preview release/babylon.d.ts" />
 declare module BABYLON {
-    class TriPlanarMaterial extends Material {
+    class TriPlanarMaterial extends PushMaterial {
         mixTexture: BaseTexture;
-        diffuseTextureX: Texture;
-        diffuseTextureY: Texture;
-        diffuseTextureZ: Texture;
-        normalTextureX: Texture;
-        normalTextureY: Texture;
-        normalTextureZ: Texture;
+        private _diffuseTextureX;
+        diffuseTextureX: BaseTexture;
+        private _diffuseTextureY;
+        diffuseTextureY: BaseTexture;
+        private _diffuseTextureZ;
+        diffuseTextureZ: BaseTexture;
+        private _normalTextureX;
+        normalTextureX: BaseTexture;
+        private _normalTextureY;
+        normalTextureY: BaseTexture;
+        private _normalTextureZ;
+        normalTextureZ: BaseTexture;
         tileSize: number;
         diffuseColor: Color3;
         specularColor: Color3;
         specularPower: number;
+        private _disableLighting;
         disableLighting: boolean;
+        private _maxSimultaneousLights;
         maxSimultaneousLights: number;
         private _worldViewProjectionMatrix;
         private _renderId;
-        private _defines;
-        private _cachedDefines;
         constructor(name: string, scene: Scene);
         needAlphaBlending(): boolean;
         needAlphaTesting(): boolean;
         getAlphaTestTexture(): BaseTexture;
-        private _checkCache(scene, mesh?, useInstances?);
-        isReady(mesh?: AbstractMesh, useInstances?: boolean): boolean;
-        bindOnlyWorldMatrix(world: Matrix): void;
-        bind(world: Matrix, mesh?: Mesh): void;
+        isReadyForSubMesh(mesh: AbstractMesh, subMesh: SubMesh, useInstances?: boolean): boolean;
+        bindForSubMesh(world: Matrix, mesh: Mesh, subMesh: SubMesh): void;
         getAnimatables(): IAnimatable[];
         dispose(forceDisposeEffect?: boolean): void;
         clone(name: string): TriPlanarMaterial;

+ 112 - 127
dist/preview release/materialsLibrary/babylon.triPlanarMaterial.js

@@ -17,7 +17,6 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
 };
 var BABYLON;
 (function (BABYLON) {
-    var maxSimultaneousLights = 4;
     var TriPlanarMaterialDefines = (function (_super) {
         __extends(TriPlanarMaterialDefines, _super);
         function TriPlanarMaterialDefines() {
@@ -52,12 +51,9 @@ var BABYLON;
             _this.diffuseColor = new BABYLON.Color3(1, 1, 1);
             _this.specularColor = new BABYLON.Color3(0.2, 0.2, 0.2);
             _this.specularPower = 64;
-            _this.disableLighting = false;
-            _this.maxSimultaneousLights = 4;
+            _this._disableLighting = false;
+            _this._maxSimultaneousLights = 4;
             _this._worldViewProjectionMatrix = BABYLON.Matrix.Zero();
-            _this._defines = new TriPlanarMaterialDefines();
-            _this._cachedDefines = new TriPlanarMaterialDefines();
-            _this._cachedDefines.BonesPerMesh = -1;
             return _this;
         }
         TriPlanarMaterial.prototype.needAlphaBlending = function () {
@@ -70,128 +66,90 @@ var BABYLON;
             return null;
         };
         // Methods   
-        TriPlanarMaterial.prototype._checkCache = function (scene, mesh, useInstances) {
-            if (!mesh) {
-                return true;
-            }
-            if (this._defines.INSTANCES !== useInstances) {
-                return false;
-            }
-            return false;
-        };
-        TriPlanarMaterial.prototype.isReady = function (mesh, useInstances) {
-            if (this.checkReadyOnlyOnce) {
-                if (this._wasPreviouslyReady) {
+        TriPlanarMaterial.prototype.isReadyForSubMesh = function (mesh, subMesh, useInstances) {
+            if (this.isFrozen) {
+                if (this._wasPreviouslyReady && subMesh.effect) {
                     return true;
                 }
             }
+            if (!subMesh._materialDefines) {
+                subMesh._materialDefines = new TriPlanarMaterialDefines();
+            }
+            var defines = subMesh._materialDefines;
             var scene = this.getScene();
             if (!this.checkReadyOnEveryCall) {
                 if (this._renderId === scene.getRenderId()) {
-                    if (this._checkCache(scene, mesh, useInstances)) {
-                        return true;
-                    }
+                    return true;
                 }
             }
             var engine = scene.getEngine();
-            var needNormals = false;
-            this._defines.reset();
             // Textures
-            if (scene.texturesEnabled) {
-                if (BABYLON.StandardMaterial.DiffuseTextureEnabled) {
-                    var textures = [this.diffuseTextureX, this.diffuseTextureY, this.diffuseTextureZ];
-                    var textureDefines = ["DIFFUSEX", "DIFFUSEY", "DIFFUSEZ"];
-                    for (var i = 0; i < textures.length; i++) {
-                        if (textures[i]) {
-                            if (!textures[i].isReady()) {
-                                return false;
-                            }
-                            else {
-                                this._defines[textureDefines[i]] = true;
+            if (defines._areTexturesDirty) {
+                if (scene.texturesEnabled) {
+                    if (BABYLON.StandardMaterial.DiffuseTextureEnabled) {
+                        var textures = [this.diffuseTextureX, this.diffuseTextureY, this.diffuseTextureZ];
+                        var textureDefines = ["DIFFUSEX", "DIFFUSEY", "DIFFUSEZ"];
+                        for (var i = 0; i < textures.length; i++) {
+                            if (textures[i]) {
+                                if (!textures[i].isReady()) {
+                                    return false;
+                                }
+                                else {
+                                    defines[textureDefines[i]] = true;
+                                }
                             }
                         }
                     }
-                }
-                if (BABYLON.StandardMaterial.BumpTextureEnabled) {
-                    var textures = [this.normalTextureX, this.normalTextureY, this.normalTextureZ];
-                    var textureDefines = ["BUMPX", "BUMPY", "BUMPZ"];
-                    for (var i = 0; i < textures.length; i++) {
-                        if (textures[i]) {
-                            if (!textures[i].isReady()) {
-                                return false;
-                            }
-                            else {
-                                this._defines[textureDefines[i]] = true;
+                    if (BABYLON.StandardMaterial.BumpTextureEnabled) {
+                        var textures = [this.normalTextureX, this.normalTextureY, this.normalTextureZ];
+                        var textureDefines = ["BUMPX", "BUMPY", "BUMPZ"];
+                        for (var i = 0; i < textures.length; i++) {
+                            if (textures[i]) {
+                                if (!textures[i].isReady()) {
+                                    return false;
+                                }
+                                else {
+                                    defines[textureDefines[i]] = true;
+                                }
                             }
                         }
                     }
                 }
             }
-            // Effect
-            if (scene.clipPlane) {
-                this._defines.CLIPPLANE = true;
-            }
-            if (engine.getAlphaTesting()) {
-                this._defines.ALPHATEST = 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;
-            }
+            // Misc.
+            BABYLON.MaterialHelper.PrepareDefinesForMisc(mesh, scene, false, this.pointsCloud, this.fogEnabled, defines);
             // Lights
-            if (scene.lightsEnabled && !this.disableLighting) {
-                needNormals = BABYLON.MaterialHelper.PrepareDefinesForLights(scene, mesh, this._defines, true, this.maxSimultaneousLights);
-            }
+            defines._needNormals = BABYLON.MaterialHelper.PrepareDefinesForLights(scene, mesh, defines, false, this._maxSimultaneousLights, this._disableLighting);
+            // Values that need to be evaluated on every frame
+            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances);
             // Attribs
-            if (mesh) {
-                if (needNormals && mesh.isVerticesDataPresent(BABYLON.VertexBuffer.NormalKind)) {
-                    this._defines.NORMAL = 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;
-                }
-            }
+            BABYLON.MaterialHelper.PrepareDefinesForAttributes(mesh, defines, true, true);
             // Get correct effect      
-            if (!this._defines.isEqual(this._cachedDefines)) {
-                this._defines.cloneTo(this._cachedDefines);
+            if (defines.isDirty) {
+                defines.markAsProcessed();
                 scene.resetCachedMaterial();
                 // Fallbacks
                 var fallbacks = new BABYLON.EffectFallbacks();
-                if (this._defines.FOG) {
+                if (defines.FOG) {
                     fallbacks.addFallback(1, "FOG");
                 }
-                BABYLON.MaterialHelper.HandleFallbacksForShadows(this._defines, fallbacks, this.maxSimultaneousLights);
-                if (this._defines.NUM_BONE_INFLUENCERS > 0) {
+                BABYLON.MaterialHelper.HandleFallbacksForShadows(defines, fallbacks, this.maxSimultaneousLights);
+                if (defines.NUM_BONE_INFLUENCERS > 0) {
                     fallbacks.addCPUSkinningFallback(0, mesh);
                 }
                 //Attributes
                 var attribs = [BABYLON.VertexBuffer.PositionKind];
-                if (this._defines.NORMAL) {
+                if (defines.NORMAL) {
                     attribs.push(BABYLON.VertexBuffer.NormalKind);
                 }
-                if (this._defines.VERTEXCOLOR) {
+                if (defines.VERTEXCOLOR) {
                     attribs.push(BABYLON.VertexBuffer.ColorKind);
                 }
-                BABYLON.MaterialHelper.PrepareAttributesForBones(attribs, mesh, this._defines, fallbacks);
-                BABYLON.MaterialHelper.PrepareAttributesForInstances(attribs, this._defines);
+                BABYLON.MaterialHelper.PrepareAttributesForBones(attribs, mesh, defines, fallbacks);
+                BABYLON.MaterialHelper.PrepareAttributesForInstances(attribs, defines);
                 // Legacy browser patch
                 var shaderName = "triplanar";
-                var join = this._defines.toString();
+                var join = defines.toString();
                 var uniforms = ["world", "view", "viewProjection", "vEyePosition", "vLightsType", "vDiffuseColor", "vSpecularColor",
                     "vFogInfos", "vFogColor", "pointSize",
                     "mBones",
@@ -201,69 +159,72 @@ var BABYLON;
                 var samplers = ["diffuseSamplerX", "diffuseSamplerY", "diffuseSamplerZ",
                     "normalSamplerX", "normalSamplerY", "normalSamplerZ"
                 ];
-                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 });
+                BABYLON.MaterialHelper.PrepareUniformsAndSamplersList(uniforms, samplers, defines, this.maxSimultaneousLights);
+                subMesh.setEffect(scene.getEngine().createEffect(shaderName, attribs, uniforms, samplers, join, fallbacks, this.onCompiled, this.onError, { maxSimultaneousLights: this.maxSimultaneousLights }), defines);
             }
-            if (!this._effect.isReady()) {
+            if (!subMesh.effect.isReady()) {
                 return false;
             }
             this._renderId = scene.getRenderId();
             this._wasPreviouslyReady = true;
             return true;
         };
-        TriPlanarMaterial.prototype.bindOnlyWorldMatrix = function (world) {
-            this._effect.setMatrix("world", world);
-        };
-        TriPlanarMaterial.prototype.bind = function (world, mesh) {
+        TriPlanarMaterial.prototype.bindForSubMesh = function (world, mesh, subMesh) {
             var scene = this.getScene();
+            var defines = subMesh._materialDefines;
+            if (!defines) {
+                return;
+            }
+            var effect = subMesh.effect;
+            this._activeEffect = effect;
             // Matrices        
             this.bindOnlyWorldMatrix(world);
-            this._effect.setMatrix("viewProjection", scene.getTransformMatrix());
+            this._activeEffect.setMatrix("viewProjection", scene.getTransformMatrix());
             // Bones
-            BABYLON.MaterialHelper.BindBonesParameters(mesh, this._effect);
-            this._effect.setFloat("tileSize", this.tileSize);
+            BABYLON.MaterialHelper.BindBonesParameters(mesh, this._activeEffect);
+            this._activeEffect.setFloat("tileSize", this.tileSize);
             if (scene.getCachedMaterial() !== this) {
                 // Textures        
                 if (this.diffuseTextureX) {
-                    this._effect.setTexture("diffuseSamplerX", this.diffuseTextureX);
+                    this._activeEffect.setTexture("diffuseSamplerX", this.diffuseTextureX);
                 }
                 if (this.diffuseTextureY) {
-                    this._effect.setTexture("diffuseSamplerY", this.diffuseTextureY);
+                    this._activeEffect.setTexture("diffuseSamplerY", this.diffuseTextureY);
                 }
                 if (this.diffuseTextureZ) {
-                    this._effect.setTexture("diffuseSamplerZ", this.diffuseTextureZ);
+                    this._activeEffect.setTexture("diffuseSamplerZ", this.diffuseTextureZ);
                 }
                 if (this.normalTextureX) {
-                    this._effect.setTexture("normalSamplerX", this.normalTextureX);
+                    this._activeEffect.setTexture("normalSamplerX", this.normalTextureX);
                 }
                 if (this.normalTextureY) {
-                    this._effect.setTexture("normalSamplerY", this.normalTextureY);
+                    this._activeEffect.setTexture("normalSamplerY", this.normalTextureY);
                 }
                 if (this.normalTextureZ) {
-                    this._effect.setTexture("normalSamplerZ", this.normalTextureZ);
+                    this._activeEffect.setTexture("normalSamplerZ", this.normalTextureZ);
                 }
                 // Clip plane
-                BABYLON.MaterialHelper.BindClipPlane(this._effect, scene);
+                BABYLON.MaterialHelper.BindClipPlane(this._activeEffect, scene);
                 // Point size
                 if (this.pointsCloud) {
-                    this._effect.setFloat("pointSize", this.pointSize);
+                    this._activeEffect.setFloat("pointSize", this.pointSize);
                 }
-                this._effect.setVector3("vEyePosition", scene._mirroredCameraPosition ? scene._mirroredCameraPosition : scene.activeCamera.position);
+                this._activeEffect.setVector3("vEyePosition", scene._mirroredCameraPosition ? scene._mirroredCameraPosition : scene.activeCamera.position);
             }
-            this._effect.setColor4("vDiffuseColor", this.diffuseColor, this.alpha * mesh.visibility);
-            if (this._defines.SPECULARTERM) {
-                this._effect.setColor4("vSpecularColor", this.specularColor, this.specularPower);
+            this._activeEffect.setColor4("vDiffuseColor", this.diffuseColor, this.alpha * mesh.visibility);
+            if (defines.SPECULARTERM) {
+                this._activeEffect.setColor4("vSpecularColor", this.specularColor, this.specularPower);
             }
             if (scene.lightsEnabled && !this.disableLighting) {
-                BABYLON.MaterialHelper.BindLights(scene, mesh, this._effect, this._defines, this.maxSimultaneousLights);
+                BABYLON.MaterialHelper.BindLights(scene, mesh, this._activeEffect, defines, this.maxSimultaneousLights);
             }
             // View
             if (scene.fogEnabled && mesh.applyFog && scene.fogMode !== BABYLON.Scene.FOGMODE_NONE) {
-                this._effect.setMatrix("view", scene.getViewMatrix());
+                this._activeEffect.setMatrix("view", scene.getViewMatrix());
             }
             // Fog
-            BABYLON.MaterialHelper.BindFogParameters(scene, mesh, this._effect);
-            this._afterBind(mesh);
+            BABYLON.MaterialHelper.BindFogParameters(scene, mesh, this._activeEffect);
+            this._afterBind(mesh, this._activeEffect);
         };
         TriPlanarMaterial.prototype.getAnimatables = function () {
             var results = [];
@@ -292,27 +253,45 @@ var BABYLON;
             return BABYLON.SerializationHelper.Parse(function () { return new TriPlanarMaterial(source.name, scene); }, source, scene, rootUrl);
         };
         return TriPlanarMaterial;
-    }(BABYLON.Material));
+    }(BABYLON.PushMaterial));
     __decorate([
         BABYLON.serializeAsTexture()
     ], TriPlanarMaterial.prototype, "mixTexture", void 0);
     __decorate([
-        BABYLON.serializeAsTexture()
+        BABYLON.serializeAsTexture("diffuseTextureX")
+    ], TriPlanarMaterial.prototype, "_diffuseTextureX", void 0);
+    __decorate([
+        BABYLON.expandToProperty("_markAllSubMeshesAsTexturesDirty")
     ], TriPlanarMaterial.prototype, "diffuseTextureX", void 0);
     __decorate([
-        BABYLON.serializeAsTexture()
+        BABYLON.serializeAsTexture("diffuseTexturY")
+    ], TriPlanarMaterial.prototype, "_diffuseTextureY", void 0);
+    __decorate([
+        BABYLON.expandToProperty("_markAllSubMeshesAsTexturesDirty")
     ], TriPlanarMaterial.prototype, "diffuseTextureY", void 0);
     __decorate([
-        BABYLON.serializeAsTexture()
+        BABYLON.serializeAsTexture("diffuseTextureZ")
+    ], TriPlanarMaterial.prototype, "_diffuseTextureZ", void 0);
+    __decorate([
+        BABYLON.expandToProperty("_markAllSubMeshesAsTexturesDirty")
     ], TriPlanarMaterial.prototype, "diffuseTextureZ", void 0);
     __decorate([
-        BABYLON.serializeAsTexture()
+        BABYLON.serializeAsTexture("normalTextureX")
+    ], TriPlanarMaterial.prototype, "_normalTextureX", void 0);
+    __decorate([
+        BABYLON.expandToProperty("_markAllSubMeshesAsTexturesDirty")
     ], TriPlanarMaterial.prototype, "normalTextureX", void 0);
     __decorate([
-        BABYLON.serializeAsTexture()
+        BABYLON.serializeAsTexture("normalTextureY")
+    ], TriPlanarMaterial.prototype, "_normalTextureY", void 0);
+    __decorate([
+        BABYLON.expandToProperty("_markAllSubMeshesAsTexturesDirty")
     ], TriPlanarMaterial.prototype, "normalTextureY", void 0);
     __decorate([
-        BABYLON.serializeAsTexture()
+        BABYLON.serializeAsTexture("normalTextureZ")
+    ], TriPlanarMaterial.prototype, "_normalTextureZ", void 0);
+    __decorate([
+        BABYLON.expandToProperty("_markAllSubMeshesAsTexturesDirty")
     ], TriPlanarMaterial.prototype, "normalTextureZ", void 0);
     __decorate([
         BABYLON.serialize()
@@ -327,10 +306,16 @@ var BABYLON;
         BABYLON.serialize()
     ], TriPlanarMaterial.prototype, "specularPower", void 0);
     __decorate([
-        BABYLON.serialize()
+        BABYLON.serialize("disableLighting")
+    ], TriPlanarMaterial.prototype, "_disableLighting", void 0);
+    __decorate([
+        BABYLON.expandToProperty("_markAllSubMeshesAsLightsDirty")
     ], TriPlanarMaterial.prototype, "disableLighting", void 0);
     __decorate([
-        BABYLON.serialize()
+        BABYLON.serialize("maxSimultaneousLights")
+    ], TriPlanarMaterial.prototype, "_maxSimultaneousLights", void 0);
+    __decorate([
+        BABYLON.expandToProperty("_markAllSubMeshesAsLightsDirty")
     ], TriPlanarMaterial.prototype, "maxSimultaneousLights", void 0);
     BABYLON.TriPlanarMaterial = TriPlanarMaterial;
 })(BABYLON || (BABYLON = {}));

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


+ 9 - 7
dist/preview release/materialsLibrary/babylon.waterMaterial.d.ts

@@ -1,12 +1,15 @@
 /// <reference path="../../../dist/preview release/babylon.d.ts" />
 declare module BABYLON {
-    class WaterMaterial extends Material {
+    class WaterMaterial extends PushMaterial {
         renderTargetSize: Vector2;
+        private _bumpTexture;
         bumpTexture: BaseTexture;
         diffuseColor: Color3;
         specularColor: Color3;
         specularPower: number;
+        private _disableLighting;
         disableLighting: boolean;
+        private _maxSimultaneousLights;
         maxSimultaneousLights: number;
         /**
         * @param {number}: Represents the wind force
@@ -27,14 +30,17 @@ declare module BABYLON {
         /**
          * @param {boolean}: Add a smaller moving bump to less steady waves.
          */
+        private _bumpSuperimpose;
         bumpSuperimpose: boolean;
         /**
          * @param {boolean}: Color refraction and reflection differently with .waterColor2 and .colorBlendFactor2. Non-linear (physically correct) fresnel.
          */
+        private _fresnelSeparate;
         fresnelSeparate: boolean;
         /**
          * @param {boolean}: bump Waves modify the reflection.
          */
+        private _bumpAffectsReflection;
         bumpAffectsReflection: boolean;
         /**
         * @param {number}: The water color blended with the refraction (near)
@@ -67,8 +73,6 @@ declare module BABYLON {
         private _reflectionTransform;
         private _lastTime;
         private _renderId;
-        private _defines;
-        private _cachedDefines;
         private _useLogarithmicDepth;
         /**
         * Constructor
@@ -84,10 +88,8 @@ declare module BABYLON {
         needAlphaBlending(): boolean;
         needAlphaTesting(): boolean;
         getAlphaTestTexture(): BaseTexture;
-        private _checkCache(scene, mesh?, useInstances?);
-        isReady(mesh?: AbstractMesh, useInstances?: boolean): boolean;
-        bindOnlyWorldMatrix(world: Matrix): void;
-        bind(world: Matrix, mesh?: Mesh): void;
+        isReadyForSubMesh(mesh: AbstractMesh, subMesh: SubMesh, useInstances?: boolean): boolean;
+        bindForSubMesh(world: Matrix, mesh: Mesh, subMesh: SubMesh): void;
         private _createRenderTargets(scene, renderTargetSize);
         getAnimatables(): IAnimatable[];
         dispose(forceDisposeEffect?: boolean): void;

+ 119 - 148
dist/preview release/materialsLibrary/babylon.waterMaterial.js

@@ -57,8 +57,8 @@ var BABYLON;
             _this.diffuseColor = new BABYLON.Color3(1, 1, 1);
             _this.specularColor = new BABYLON.Color3(0, 0, 0);
             _this.specularPower = 64;
-            _this.disableLighting = false;
-            _this.maxSimultaneousLights = 4;
+            _this._disableLighting = false;
+            _this._maxSimultaneousLights = 4;
             /**
             * @param {number}: Represents the wind force
             */
@@ -78,15 +78,15 @@ var BABYLON;
             /**
              * @param {boolean}: Add a smaller moving bump to less steady waves.
              */
-            _this.bumpSuperimpose = false;
+            _this._bumpSuperimpose = false;
             /**
              * @param {boolean}: Color refraction and reflection differently with .waterColor2 and .colorBlendFactor2. Non-linear (physically correct) fresnel.
              */
-            _this.fresnelSeparate = false;
+            _this._fresnelSeparate = false;
             /**
              * @param {boolean}: bump Waves modify the reflection.
              */
-            _this.bumpAffectsReflection = false;
+            _this._bumpAffectsReflection = false;
             /**
             * @param {number}: The water color blended with the refraction (near)
             */
@@ -117,8 +117,6 @@ var BABYLON;
             _this._mesh = null;
             _this._reflectionTransform = BABYLON.Matrix.Zero();
             _this._lastTime = 0;
-            _this._defines = new WaterMaterialDefines();
-            _this._cachedDefines = new WaterMaterialDefines();
             // Create render targets
             _this._createRenderTargets(scene, renderTargetSize);
             return _this;
@@ -129,6 +127,7 @@ var BABYLON;
             },
             set: function (value) {
                 this._useLogarithmicDepth = value && this.getScene().getEngine().getCaps().fragmentDepthSupported;
+                this._markAllSubMeshesAsMiscDirty();
             },
             enumerable: true,
             configurable: true
@@ -177,143 +176,94 @@ var BABYLON;
         WaterMaterial.prototype.getAlphaTestTexture = function () {
             return null;
         };
-        WaterMaterial.prototype._checkCache = function (scene, mesh, useInstances) {
-            if (!mesh) {
-                return true;
-            }
-            if (this._defines.INSTANCES !== useInstances) {
-                return false;
-            }
-            return false;
-        };
-        WaterMaterial.prototype.isReady = function (mesh, useInstances) {
-            if (this.checkReadyOnlyOnce) {
-                if (this._wasPreviouslyReady) {
+        WaterMaterial.prototype.isReadyForSubMesh = function (mesh, subMesh, useInstances) {
+            if (this.isFrozen) {
+                if (this._wasPreviouslyReady && subMesh.effect) {
                     return true;
                 }
             }
+            if (!subMesh._materialDefines) {
+                subMesh._materialDefines = new WaterMaterialDefines();
+            }
+            var defines = subMesh._materialDefines;
             var scene = this.getScene();
             if (!this.checkReadyOnEveryCall) {
                 if (this._renderId === scene.getRenderId()) {
-                    if (this._checkCache(scene, mesh, useInstances)) {
-                        return true;
-                    }
+                    return true;
                 }
             }
             var engine = scene.getEngine();
-            var needNormals = false;
-            var needUVs = false;
-            this._defines.reset();
             // Textures
-            if (scene.texturesEnabled) {
-                if (this.bumpTexture && BABYLON.StandardMaterial.BumpTextureEnabled) {
-                    if (!this.bumpTexture.isReady()) {
-                        return false;
+            if (defines._areTexturesDirty) {
+                defines._needUVs = false;
+                if (scene.texturesEnabled) {
+                    if (this.bumpTexture && BABYLON.StandardMaterial.BumpTextureEnabled) {
+                        if (!this.bumpTexture.isReady()) {
+                            return false;
+                        }
+                        else {
+                            defines._needUVs = true;
+                            defines.BUMP = true;
+                        }
                     }
-                    else {
-                        needUVs = true;
-                        this._defines.BUMP = true;
+                    if (BABYLON.StandardMaterial.ReflectionTextureEnabled) {
+                        defines.REFLECTION = true;
                     }
                 }
-                if (BABYLON.StandardMaterial.ReflectionTextureEnabled) {
-                    this._defines.REFLECTION = true;
-                }
-            }
-            // Effect
-            if (scene.clipPlane) {
-                this._defines.CLIPPLANE = true;
-            }
-            if (engine.getAlphaTesting()) {
-                this._defines.ALPHATEST = true;
-            }
-            // Point size
-            if (this.pointsCloud || scene.forcePointsCloud) {
-                this._defines.POINTSIZE = true;
-            }
-            if (this.useLogarithmicDepth) {
-                this._defines.LOGARITHMICDEPTH = true;
-            }
-            if (this.fresnelSeparate) {
-                this._defines.FRESNELSEPARATE = true;
-            }
-            if (this.bumpSuperimpose) {
-                this._defines.BUMPSUPERIMPOSE = true;
-            }
-            if (this.bumpAffectsReflection) {
-                this._defines.BUMPAFFECTSREFLECTION = true;
-            }
-            // Fog
-            if (scene.fogEnabled && mesh && mesh.applyFog && scene.fogMode !== BABYLON.Scene.FOGMODE_NONE && this.fogEnabled) {
-                this._defines.FOG = true;
-            }
-            // Lights
-            if (scene.lightsEnabled && !this.disableLighting) {
-                needNormals = BABYLON.MaterialHelper.PrepareDefinesForLights(scene, mesh, this._defines, true, this.maxSimultaneousLights);
             }
-            // 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;
-                    }
+            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances);
+            BABYLON.MaterialHelper.PrepareDefinesForMisc(mesh, scene, this._useLogarithmicDepth, this.pointsCloud, this.fogEnabled, defines);
+            if (defines._areMiscDirty) {
+                if (this._fresnelSeparate) {
+                    defines.FRESNELSEPARATE = true;
                 }
-                if (mesh.useBones && mesh.computeBonesUsingShaders) {
-                    this._defines.NUM_BONE_INFLUENCERS = mesh.numBoneInfluencers;
-                    this._defines.BonesPerMesh = (mesh.skeleton.bones.length + 1);
+                if (this._bumpSuperimpose) {
+                    defines.BUMPSUPERIMPOSE = true;
                 }
-                // Instances
-                if (useInstances) {
-                    this._defines.INSTANCES = true;
+                if (this._bumpAffectsReflection) {
+                    defines.BUMPAFFECTSREFLECTION = true;
                 }
             }
+            // Lights
+            defines._needNormals = BABYLON.MaterialHelper.PrepareDefinesForLights(scene, mesh, defines, true, this._maxSimultaneousLights, this._disableLighting);
+            // Attribs
+            BABYLON.MaterialHelper.PrepareDefinesForAttributes(mesh, defines, true, true);
             this._mesh = mesh;
             // Get correct effect      
-            if (!this._defines.isEqual(this._cachedDefines)) {
-                this._defines.cloneTo(this._cachedDefines);
+            if (defines.isDirty) {
+                defines.markAsProcessed();
                 scene.resetCachedMaterial();
                 // Fallbacks
                 var fallbacks = new BABYLON.EffectFallbacks();
-                if (this._defines.FOG) {
+                if (defines.FOG) {
                     fallbacks.addFallback(1, "FOG");
                 }
-                if (this._defines.LOGARITHMICDEPTH) {
+                if (defines.LOGARITHMICDEPTH) {
                     fallbacks.addFallback(0, "LOGARITHMICDEPTH");
                 }
-                BABYLON.MaterialHelper.HandleFallbacksForShadows(this._defines, fallbacks, this.maxSimultaneousLights);
-                if (this._defines.NUM_BONE_INFLUENCERS > 0) {
+                BABYLON.MaterialHelper.HandleFallbacksForShadows(defines, fallbacks, this.maxSimultaneousLights);
+                if (defines.NUM_BONE_INFLUENCERS > 0) {
                     fallbacks.addCPUSkinningFallback(0, mesh);
                 }
                 //Attributes
                 var attribs = [BABYLON.VertexBuffer.PositionKind];
-                if (this._defines.NORMAL) {
+                if (defines.NORMAL) {
                     attribs.push(BABYLON.VertexBuffer.NormalKind);
                 }
-                if (this._defines.UV1) {
+                if (defines.UV1) {
                     attribs.push(BABYLON.VertexBuffer.UVKind);
                 }
-                if (this._defines.UV2) {
+                if (defines.UV2) {
                     attribs.push(BABYLON.VertexBuffer.UV2Kind);
                 }
-                if (this._defines.VERTEXCOLOR) {
+                if (defines.VERTEXCOLOR) {
                     attribs.push(BABYLON.VertexBuffer.ColorKind);
                 }
-                BABYLON.MaterialHelper.PrepareAttributesForBones(attribs, mesh, this._defines, fallbacks);
-                BABYLON.MaterialHelper.PrepareAttributesForInstances(attribs, this._defines);
+                BABYLON.MaterialHelper.PrepareAttributesForBones(attribs, mesh, defines, fallbacks);
+                BABYLON.MaterialHelper.PrepareAttributesForInstances(attribs, defines);
                 // Legacy browser patch
                 var shaderName = "water";
-                var join = this._defines.toString();
+                var join = defines.toString();
                 var uniforms = ["world", "view", "viewProjection", "vEyePosition", "vLightsType", "vDiffuseColor", "vSpecularColor",
                     "vFogInfos", "vFogColor", "pointSize",
                     "vNormalInfos",
@@ -328,76 +278,79 @@ var BABYLON;
                     // Water
                     "refractionSampler", "reflectionSampler"
                 ];
-                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 });
+                BABYLON.MaterialHelper.PrepareUniformsAndSamplersList(uniforms, samplers, defines, this.maxSimultaneousLights);
+                subMesh.setEffect(scene.getEngine().createEffect(shaderName, attribs, uniforms, samplers, join, fallbacks, this.onCompiled, this.onError, { maxSimultaneousLights: this.maxSimultaneousLights }), defines);
             }
-            if (!this._effect.isReady()) {
+            if (!subMesh.effect.isReady()) {
                 return false;
             }
             this._renderId = scene.getRenderId();
             this._wasPreviouslyReady = true;
             return true;
         };
-        WaterMaterial.prototype.bindOnlyWorldMatrix = function (world) {
-            this._effect.setMatrix("world", world);
-        };
-        WaterMaterial.prototype.bind = function (world, mesh) {
+        WaterMaterial.prototype.bindForSubMesh = function (world, mesh, subMesh) {
             var scene = this.getScene();
+            var defines = subMesh._materialDefines;
+            if (!defines) {
+                return;
+            }
+            var effect = subMesh.effect;
+            this._activeEffect = effect;
             // Matrices        
             this.bindOnlyWorldMatrix(world);
-            this._effect.setMatrix("viewProjection", scene.getTransformMatrix());
+            this._activeEffect.setMatrix("viewProjection", scene.getTransformMatrix());
             // Bones
-            BABYLON.MaterialHelper.BindBonesParameters(mesh, this._effect);
-            if (scene.getCachedMaterial() !== this) {
+            BABYLON.MaterialHelper.BindBonesParameters(mesh, this._activeEffect);
+            if (this._mustRebind(scene, effect)) {
                 // Textures        
                 if (this.bumpTexture && BABYLON.StandardMaterial.BumpTextureEnabled) {
-                    this._effect.setTexture("normalSampler", this.bumpTexture);
-                    this._effect.setFloat2("vNormalInfos", this.bumpTexture.coordinatesIndex, this.bumpTexture.level);
-                    this._effect.setMatrix("normalMatrix", this.bumpTexture.getTextureMatrix());
+                    this._activeEffect.setTexture("normalSampler", this.bumpTexture);
+                    this._activeEffect.setFloat2("vNormalInfos", this.bumpTexture.coordinatesIndex, this.bumpTexture.level);
+                    this._activeEffect.setMatrix("normalMatrix", this.bumpTexture.getTextureMatrix());
                 }
                 // Clip plane
-                BABYLON.MaterialHelper.BindClipPlane(this._effect, scene);
+                BABYLON.MaterialHelper.BindClipPlane(this._activeEffect, scene);
                 // Point size
                 if (this.pointsCloud) {
-                    this._effect.setFloat("pointSize", this.pointSize);
+                    this._activeEffect.setFloat("pointSize", this.pointSize);
                 }
-                this._effect.setVector3("vEyePosition", scene._mirroredCameraPosition ? scene._mirroredCameraPosition : scene.activeCamera.position);
+                this._activeEffect.setVector3("vEyePosition", scene._mirroredCameraPosition ? scene._mirroredCameraPosition : scene.activeCamera.position);
             }
-            this._effect.setColor4("vDiffuseColor", this.diffuseColor, this.alpha * mesh.visibility);
-            if (this._defines.SPECULARTERM) {
-                this._effect.setColor4("vSpecularColor", this.specularColor, this.specularPower);
+            this._activeEffect.setColor4("vDiffuseColor", this.diffuseColor, this.alpha * mesh.visibility);
+            if (defines.SPECULARTERM) {
+                this._activeEffect.setColor4("vSpecularColor", this.specularColor, this.specularPower);
             }
             if (scene.lightsEnabled && !this.disableLighting) {
-                BABYLON.MaterialHelper.BindLights(scene, mesh, this._effect, this._defines, this.maxSimultaneousLights);
+                BABYLON.MaterialHelper.BindLights(scene, mesh, this._activeEffect, defines, this.maxSimultaneousLights);
             }
             // View
             if (scene.fogEnabled && mesh.applyFog && scene.fogMode !== BABYLON.Scene.FOGMODE_NONE) {
-                this._effect.setMatrix("view", scene.getViewMatrix());
+                this._activeEffect.setMatrix("view", scene.getViewMatrix());
             }
             // Fog
-            BABYLON.MaterialHelper.BindFogParameters(scene, mesh, this._effect);
+            BABYLON.MaterialHelper.BindFogParameters(scene, mesh, this._activeEffect);
             // Log. depth
-            BABYLON.MaterialHelper.BindLogDepth(this._defines, this._effect, scene);
+            BABYLON.MaterialHelper.BindLogDepth(defines, this._activeEffect, scene);
             // Water
             if (BABYLON.StandardMaterial.ReflectionTextureEnabled) {
-                this._effect.setTexture("refractionSampler", this._refractionRTT);
-                this._effect.setTexture("reflectionSampler", this._reflectionRTT);
+                this._activeEffect.setTexture("refractionSampler", this._refractionRTT);
+                this._activeEffect.setTexture("reflectionSampler", this._reflectionRTT);
             }
             var wrvp = this._mesh.getWorldMatrix().multiply(this._reflectionTransform).multiply(scene.getProjectionMatrix());
             this._lastTime += scene.getEngine().getDeltaTime();
-            this._effect.setMatrix("worldReflectionViewProjection", wrvp);
-            this._effect.setVector2("windDirection", this.windDirection);
-            this._effect.setFloat("waveLength", this.waveLength);
-            this._effect.setFloat("time", this._lastTime / 100000);
-            this._effect.setFloat("windForce", this.windForce);
-            this._effect.setFloat("waveHeight", this.waveHeight);
-            this._effect.setFloat("bumpHeight", this.bumpHeight);
-            this._effect.setColor4("waterColor", this.waterColor, 1.0);
-            this._effect.setFloat("colorBlendFactor", this.colorBlendFactor);
-            this._effect.setColor4("waterColor2", this.waterColor2, 1.0);
-            this._effect.setFloat("colorBlendFactor2", this.colorBlendFactor2);
-            this._effect.setFloat("waveSpeed", this.waveSpeed);
-            this._afterBind(mesh);
+            this._activeEffect.setMatrix("worldReflectionViewProjection", wrvp);
+            this._activeEffect.setVector2("windDirection", this.windDirection);
+            this._activeEffect.setFloat("waveLength", this.waveLength);
+            this._activeEffect.setFloat("time", this._lastTime / 100000);
+            this._activeEffect.setFloat("windForce", this.windForce);
+            this._activeEffect.setFloat("waveHeight", this.waveHeight);
+            this._activeEffect.setFloat("bumpHeight", this.bumpHeight);
+            this._activeEffect.setColor4("waterColor", this.waterColor, 1.0);
+            this._activeEffect.setFloat("colorBlendFactor", this.colorBlendFactor);
+            this._activeEffect.setColor4("waterColor2", this.waterColor2, 1.0);
+            this._activeEffect.setFloat("colorBlendFactor2", this.colorBlendFactor2);
+            this._activeEffect.setFloat("waveSpeed", this.waveSpeed);
+            this._afterBind(mesh, this._activeEffect);
         };
         WaterMaterial.prototype._createRenderTargets = function (scene, renderTargetSize) {
             var _this = this;
@@ -514,9 +467,12 @@ var BABYLON;
             return mesh;
         };
         return WaterMaterial;
-    }(BABYLON.Material));
+    }(BABYLON.PushMaterial));
+    __decorate([
+        BABYLON.serializeAsTexture("bumpTexture")
+    ], WaterMaterial.prototype, "_bumpTexture", void 0);
     __decorate([
-        BABYLON.serializeAsTexture()
+        BABYLON.expandToProperty("_markAllSubMeshesAsTexturesDirty")
     ], WaterMaterial.prototype, "bumpTexture", void 0);
     __decorate([
         BABYLON.serializeAsColor3()
@@ -528,10 +484,16 @@ var BABYLON;
         BABYLON.serialize()
     ], WaterMaterial.prototype, "specularPower", void 0);
     __decorate([
-        BABYLON.serialize()
+        BABYLON.serialize("disableLighting")
+    ], WaterMaterial.prototype, "_disableLighting", void 0);
+    __decorate([
+        BABYLON.expandToProperty("_markAllSubMeshesAsLightsDirty")
     ], WaterMaterial.prototype, "disableLighting", void 0);
     __decorate([
-        BABYLON.serialize()
+        BABYLON.serialize("maxSimultaneousLights")
+    ], WaterMaterial.prototype, "_maxSimultaneousLights", void 0);
+    __decorate([
+        BABYLON.expandToProperty("_markAllSubMeshesAsLightsDirty")
     ], WaterMaterial.prototype, "maxSimultaneousLights", void 0);
     __decorate([
         BABYLON.serialize()
@@ -546,13 +508,22 @@ var BABYLON;
         BABYLON.serialize()
     ], WaterMaterial.prototype, "bumpHeight", void 0);
     __decorate([
-        BABYLON.serialize()
+        BABYLON.serialize("bumpSuperimpose")
+    ], WaterMaterial.prototype, "_bumpSuperimpose", void 0);
+    __decorate([
+        BABYLON.expandToProperty("_markAllSubMeshesAsMiscDirty")
     ], WaterMaterial.prototype, "bumpSuperimpose", void 0);
     __decorate([
-        BABYLON.serialize()
+        BABYLON.serialize("fresnelSeparate")
+    ], WaterMaterial.prototype, "_fresnelSeparate", void 0);
+    __decorate([
+        BABYLON.expandToProperty("_markAllSubMeshesAsMiscDirty")
     ], WaterMaterial.prototype, "fresnelSeparate", void 0);
     __decorate([
-        BABYLON.serialize()
+        BABYLON.serialize("bumpAffectsReflection")
+    ], WaterMaterial.prototype, "_bumpAffectsReflection", void 0);
+    __decorate([
+        BABYLON.expandToProperty("_markAllSubMeshesAsMiscDirty")
     ], WaterMaterial.prototype, "bumpAffectsReflection", void 0);
     __decorate([
         BABYLON.serializeAsColor3()

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


+ 5 - 0
localDev/src/index.js

@@ -0,0 +1,5 @@
+/// <reference path="../../dist/preview release/babylon.d.ts"/>
+
+// Playground like creation of the scene
+var createScene = function () {
+}

+ 108 - 156
materialsLibrary/src/fur/babylon.furMaterial.ts

@@ -1,8 +1,6 @@
 /// <reference path="../../../dist/preview release/babylon.d.ts"/>
 
 module BABYLON {
-    var maxSimultaneousLights = 4;
-
     class FurMaterialDefines extends MaterialDefines {
         public DIFFUSE = false;
         public HEIGHTMAP = false;
@@ -26,13 +24,17 @@ module BABYLON {
         }
     }
 
-    export class FurMaterial extends Material {
+    export class FurMaterial extends PushMaterial {
         
-        @serializeAsTexture()
+        @serializeAsTexture("diffuseTexture")
+        private _diffuseTexture: BaseTexture;
+        @expandToProperty("_markAllSubMeshesAsTexturesDirty")
         public diffuseTexture: BaseTexture;
         
-        @serializeAsTexture()
-        public heightTexture: BaseTexture;
+        @serializeAsTexture("heightTexture")
+        private _heightTexture: BaseTexture;
+        @expandToProperty("_markAllSubMeshesAsTexturesDirty")
+        public heightTexture: BaseTexture;        
         
         @serializeAsColor3()
         public diffuseColor = new Color3(1, 1, 1);
@@ -63,15 +65,20 @@ module BABYLON {
         
         public furTexture: DynamicTexture;
         
-        @serialize()
-        public disableLighting = false;
         
-        @serialize()
-        public highLevelFur: boolean = true;
+        @serialize("disableLighting")
+        private _disableLighting = false;
+        @expandToProperty("_markAllSubMeshesAsLightsDirty")
+        public disableLighting: boolean;   
         
-        @serialize()
-        public maxSimultaneousLights = 4;
+        @serialize("maxSimultaneousLights")
+        private _maxSimultaneousLights = 4;
+        @expandToProperty("_markAllSubMeshesAsLightsDirty")
+        public maxSimultaneousLights: number; 
         
+        @serialize()
+        public highLevelFur: boolean = true;
+               
         public _meshes: AbstractMesh[];
 
         private _worldViewProjectionMatrix = Matrix.Zero();
@@ -79,13 +86,8 @@ module BABYLON {
         
         private _furTime: number = 0;
 
-        private _defines = new FurMaterialDefines();
-        private _cachedDefines = new FurMaterialDefines();
-
         constructor(name: string, scene: Scene) {
             super(name, scene);
-
-            this._cachedDefines.BonesPerMesh = -1;
         }
         
         @serialize()
@@ -128,165 +130,111 @@ module BABYLON {
         }
 
         // Methods   
-        private _checkCache(scene: Scene, mesh?: AbstractMesh, useInstances?: boolean): boolean {
-            if (!mesh) {
-                return true;
-            }
-
-            if (this._defines.INSTANCES !== useInstances) {
-                return false;
-            }
-
-            return false;
-        }
-
-        public isReady(mesh?: AbstractMesh, useInstances?: boolean): boolean {
-            if (this.checkReadyOnlyOnce) {
-                if (this._wasPreviouslyReady) {
+        public isReadyForSubMesh(mesh: AbstractMesh, subMesh: SubMesh, useInstances?: boolean): boolean {   
+            if (this.isFrozen) {
+                if (this._wasPreviouslyReady && subMesh.effect) {
                     return true;
                 }
             }
 
+            if (!subMesh._materialDefines) {
+                subMesh._materialDefines = new FurMaterialDefines();
+            }
+
+            var defines = <FurMaterialDefines>subMesh._materialDefines;
             var scene = this.getScene();
 
             if (!this.checkReadyOnEveryCall) {
                 if (this._renderId === scene.getRenderId()) {
-                    if (this._checkCache(scene, mesh, useInstances)) {
-                        return true;
-                    }
+                    return true;
                 }
             }
 
             var engine = scene.getEngine();
-            var needNormals = false;
-            var needUVs = false;
-
-            this._defines.reset();
 
             // Textures
-            if (scene.texturesEnabled) {
-                if (this.diffuseTexture && StandardMaterial.DiffuseTextureEnabled) {
-                    if (!this.diffuseTexture.isReady()) {
-                        return false;
-                    } else {
-                        needUVs = true;
-                        this._defines.DIFFUSE = true;
-                    }
-                } 
-                if (this.heightTexture && engine.getCaps().maxVertexTextureImageUnits) {
-                    if (!this.heightTexture.isReady()) {
-                        return false;
-                    } else {
-                        needUVs = true;
-                        this._defines.HEIGHTMAP = true;
-                    }
-                }               
-            }
-
-            // Effect
-            if (scene.clipPlane) {
-                this._defines.CLIPPLANE = true;
-            }
-
-            if (engine.getAlphaTesting()) {
-                this._defines.ALPHATEST = true;
-            }
-
-            // Point size
-            if (this.pointsCloud || scene.forcePointsCloud) {
-                this._defines.POINTSIZE = true;
+            if (defines._areTexturesDirty) {
+                if (scene.texturesEnabled) {
+                    if (this.diffuseTexture && StandardMaterial.DiffuseTextureEnabled) {
+                        if (!this.diffuseTexture.isReady()) {
+                            return false;
+                        } else {
+                            defines._needUVs = true;
+                            defines.DIFFUSE = true;
+                        }
+                    } 
+                    if (this.heightTexture && engine.getCaps().maxVertexTextureImageUnits) {
+                        if (!this.heightTexture.isReady()) {
+                            return false;
+                        } else {
+                            defines._needUVs = true;
+                            defines.HEIGHTMAP = true;
+                        }
+                    }               
+                }
             }
 
-            // Fog
-            if (scene.fogEnabled && mesh && mesh.applyFog && scene.fogMode !== Scene.FOGMODE_NONE && this.fogEnabled) {
-                this._defines.FOG = true;
-            }
-            
             // High level
-            if (this.highLevelFur) {
-                this._defines.HIGHLEVEL = true;
+            if (this.highLevelFur !== defines.HIGHLEVEL) {
+                defines.HIGHLEVEL = true;
+                defines.markAsUnprocessed();
             }
 
+            // Misc.   
+            MaterialHelper.PrepareDefinesForMisc(mesh, scene, false, this.pointsCloud, this.fogEnabled, defines);
+
             // Lights
-            if (scene.lightsEnabled && !this.disableLighting) {
-                needNormals = MaterialHelper.PrepareDefinesForLights(scene, mesh, this._defines, false, this.maxSimultaneousLights);
-            }
+            defines._needNormals = MaterialHelper.PrepareDefinesForLights(scene, mesh, defines, false, this._maxSimultaneousLights, this._disableLighting);
 
+            // Values that need to be evaluated on every frame
+            MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances);
+            
             // 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;
-                }
-            }
+            MaterialHelper.PrepareDefinesForAttributes(mesh, defines, true, true);
 
             // Get correct effect      
-            if (!this._defines.isEqual(this._cachedDefines)) {
-                this._defines.cloneTo(this._cachedDefines);
+            if (defines.isDirty) {
+                defines.markAsProcessed();
 
                 scene.resetCachedMaterial();
 
                 // Fallbacks
                 var fallbacks = new EffectFallbacks();             
-                if (this._defines.FOG) {
+                if (defines.FOG) {
                     fallbacks.addFallback(1, "FOG");
                 }
 
-                MaterialHelper.HandleFallbacksForShadows(this._defines, fallbacks, this.maxSimultaneousLights);
+                MaterialHelper.HandleFallbacksForShadows(defines, fallbacks, this.maxSimultaneousLights);
              
-                if (this._defines.NUM_BONE_INFLUENCERS > 0) {
+                if (defines.NUM_BONE_INFLUENCERS > 0) {
                     fallbacks.addCPUSkinningFallback(0, mesh);
                 }
 
                 //Attributes
                 var attribs = [VertexBuffer.PositionKind];
 
-                if (this._defines.NORMAL) {
+                if (defines.NORMAL) {
                     attribs.push(VertexBuffer.NormalKind);
                 }
 
-                if (this._defines.UV1) {
+                if (defines.UV1) {
                     attribs.push(VertexBuffer.UVKind);
                 }
 
-                if (this._defines.UV2) {
+                if (defines.UV2) {
                     attribs.push(VertexBuffer.UV2Kind);
                 }
 
-                if (this._defines.VERTEXCOLOR) {
+                if (defines.VERTEXCOLOR) {
                     attribs.push(VertexBuffer.ColorKind);
                 }
 
-                MaterialHelper.PrepareAttributesForBones(attribs, mesh, this._defines, fallbacks);
-                MaterialHelper.PrepareAttributesForInstances(attribs, this._defines);
+                MaterialHelper.PrepareAttributesForBones(attribs, mesh, defines, fallbacks);
+                MaterialHelper.PrepareAttributesForInstances(attribs, defines);
 
                 // Legacy browser patch
                 var shaderName = "fur";
-                var join = this._defines.toString();
+                var join = defines.toString();
                 var uniforms = ["world", "view", "viewProjection", "vEyePosition", "vLightsType", "vDiffuseColor",
                     "vFogInfos", "vFogColor", "pointSize",
                     "vDiffuseInfos", 
@@ -298,13 +246,13 @@ module BABYLON {
                     "heightTexture", "furTexture"
                 ];
                 
-                MaterialHelper.PrepareUniformsAndSamplersList(uniforms, samplers, this._defines, this.maxSimultaneousLights);
+                MaterialHelper.PrepareUniformsAndSamplersList(uniforms, samplers, defines, this.maxSimultaneousLights);
                 
-                this._effect = scene.getEngine().createEffect(shaderName,
+                subMesh.setEffect(scene.getEngine().createEffect(shaderName,
                     attribs, uniforms, samplers,
-                    join, fallbacks, this.onCompiled, this.onError, { maxSimultaneousLights: this.maxSimultaneousLights });
+                    join, fallbacks, this.onCompiled, this.onError, { maxSimultaneousLights: this.maxSimultaneousLights }), defines);
             }
-            if (!this._effect.isReady()) {
+            if (!subMesh.effect.isReady()) {
                 return false;
             }
 
@@ -314,75 +262,79 @@ module BABYLON {
             return true;
         }
 
-        public bindOnlyWorldMatrix(world: Matrix): void {
-            this._effect.setMatrix("world", world);
-        }
-
-        public bind(world: Matrix, mesh?: Mesh): void {
+        public bindForSubMesh(world: Matrix, mesh: Mesh, subMesh: SubMesh): void {
             var scene = this.getScene();
 
+            var defines = <FurMaterialDefines>subMesh._materialDefines;
+            if (!defines) {
+                return;
+            }
+
+            var effect = subMesh.effect;
+            this._activeEffect = effect;
+
             // Matrices        
             this.bindOnlyWorldMatrix(world);
-            this._effect.setMatrix("viewProjection", scene.getTransformMatrix());
+            this._activeEffect.setMatrix("viewProjection", scene.getTransformMatrix());
 
             // Bones
-            MaterialHelper.BindBonesParameters(mesh, this._effect);
+            MaterialHelper.BindBonesParameters(mesh, this._activeEffect);
 
             if (scene.getCachedMaterial() !== this) {
                 // Textures        
-                if (this.diffuseTexture && StandardMaterial.DiffuseTextureEnabled) {
-                    this._effect.setTexture("diffuseSampler", this.diffuseTexture);
+                if (this._diffuseTexture && StandardMaterial.DiffuseTextureEnabled) {
+                    this._activeEffect.setTexture("diffuseSampler", this._diffuseTexture);
 
-                    this._effect.setFloat2("vDiffuseInfos", this.diffuseTexture.coordinatesIndex, this.diffuseTexture.level);
-                    this._effect.setMatrix("diffuseMatrix", this.diffuseTexture.getTextureMatrix());
+                    this._activeEffect.setFloat2("vDiffuseInfos", this._diffuseTexture.coordinatesIndex, this._diffuseTexture.level);
+                    this._activeEffect.setMatrix("diffuseMatrix", this._diffuseTexture.getTextureMatrix());
                 }
                 
-                if (this.heightTexture) {
-                    this._effect.setTexture("heightTexture", this.heightTexture);
+                if (this._heightTexture) {
+                    this._activeEffect.setTexture("heightTexture", this._heightTexture);
                 }
                 
                 // Clip plane
-                MaterialHelper.BindClipPlane(this._effect, scene);
+                MaterialHelper.BindClipPlane(this._activeEffect, scene);
 
                 // Point size
                 if (this.pointsCloud) {
-                    this._effect.setFloat("pointSize", this.pointSize);
+                    this._activeEffect.setFloat("pointSize", this.pointSize);
                 }
 
-                this._effect.setVector3("vEyePosition", scene._mirroredCameraPosition ? scene._mirroredCameraPosition : scene.activeCamera.position);                
+                this._activeEffect.setVector3("vEyePosition", scene._mirroredCameraPosition ? scene._mirroredCameraPosition : scene.activeCamera.position);                
             }
 
-            this._effect.setColor4("vDiffuseColor", this.diffuseColor, this.alpha * mesh.visibility);
+            this._activeEffect.setColor4("vDiffuseColor", this.diffuseColor, this.alpha * mesh.visibility);
 
             if (scene.lightsEnabled && !this.disableLighting) {
-                MaterialHelper.BindLights(scene, mesh, this._effect, this._defines, this.maxSimultaneousLights);
+                MaterialHelper.BindLights(scene, mesh, this._activeEffect, defines, this.maxSimultaneousLights);
             }
 
             // View
             if (scene.fogEnabled && mesh.applyFog && scene.fogMode !== Scene.FOGMODE_NONE) {
-                this._effect.setMatrix("view", scene.getViewMatrix());
+                this._activeEffect.setMatrix("view", scene.getViewMatrix());
             }
 
             // Fog
-            MaterialHelper.BindFogParameters(scene, mesh, this._effect);
+            MaterialHelper.BindFogParameters(scene, mesh, this._activeEffect);
             
-            this._effect.setFloat("furLength", this.furLength);
-            this._effect.setFloat("furAngle", this.furAngle);
-            this._effect.setColor4("furColor", this.furColor, 1.0);
+            this._activeEffect.setFloat("furLength", this.furLength);
+            this._activeEffect.setFloat("furAngle", this.furAngle);
+            this._activeEffect.setColor4("furColor", this.furColor, 1.0);
             
             if (this.highLevelFur) {
-                this._effect.setVector3("furGravity", this.furGravity);
-                this._effect.setFloat("furOffset", this.furOffset);
-                this._effect.setFloat("furSpacing", this.furSpacing);
-                this._effect.setFloat("furDensity", this.furDensity);
+                this._activeEffect.setVector3("furGravity", this.furGravity);
+                this._activeEffect.setFloat("furOffset", this.furOffset);
+                this._activeEffect.setFloat("furSpacing", this.furSpacing);
+                this._activeEffect.setFloat("furDensity", this.furDensity);
                 
                 this._furTime += this.getScene().getEngine().getDeltaTime() / this.furSpeed;
-                this._effect.setFloat("furTime", this._furTime);
+                this._activeEffect.setFloat("furTime", this._furTime);
                 
-                this._effect.setTexture("furTexture", this.furTexture);
+                this._activeEffect.setTexture("furTexture", this.furTexture);
             }
  
-            this._afterBind(mesh);
+            this._afterBind(mesh, this._activeEffect);
         }
 
         public getAnimatables(): IAnimatable[] {

+ 36 - 52
materialsLibrary/src/grid/babylon.gridmaterial.ts

@@ -1,7 +1,7 @@
 /// <reference path="../../../dist/preview release/babylon.d.ts"/>
 
 module BABYLON {
-    class GRIDMaterialDefines extends MaterialDefines {
+    class GridMaterialDefines extends MaterialDefines {
         public TRANSPARENT = false;
 
         public FOG = false;
@@ -16,7 +16,7 @@ module BABYLON {
      * The grid materials allows you to wrap any shape with a grid.
      * Colors are customizable.
      */
-    export class GridMaterial extends BABYLON.Material {
+    export class GridMaterial extends BABYLON.PushMaterial {
 
         /**
          * Main color of the grid (e.g. between lines)
@@ -57,8 +57,6 @@ module BABYLON {
         private _gridControl: Vector4 = new Vector4(this.gridRatio, this.majorUnitFrequency, this.minorUnitVisibility, this.opacity);
 
         private _renderId: number;
-        private _defines = new GRIDMaterialDefines();
-        private _cachedDefines = new GRIDMaterialDefines();
 
         /**
          * constructor
@@ -76,48 +74,38 @@ module BABYLON {
             return this.opacity < 1.0;
         }
 
-        private _checkCache(scene: Scene, mesh?: AbstractMesh, useInstances?: boolean): boolean {
-            if (!mesh) {
-                return true;
-            }
-            
-            return false;
-        }
-
-        public isReady(mesh?: AbstractMesh, useInstances?: boolean): boolean {
-            if (this.checkReadyOnlyOnce) {
-                if (this._wasPreviouslyReady) {
+        public isReadyForSubMesh(mesh: AbstractMesh, subMesh: SubMesh, useInstances?: boolean): boolean {   
+            if (this.isFrozen) {
+                if (this._wasPreviouslyReady && subMesh.effect) {
                     return true;
                 }
             }
 
+            if (!subMesh._materialDefines) {
+                subMesh._materialDefines = new GridMaterialDefines();
+            }
+
+            var defines = <GridMaterialDefines>subMesh._materialDefines;
             var scene = this.getScene();
 
             if (!this.checkReadyOnEveryCall) {
                 if (this._renderId === scene.getRenderId()) {
-                    if (this._checkCache(scene, mesh, useInstances)) {
-                        return true;
-                    }
+                    return true;
                 }
             }
 
             var engine = scene.getEngine();
-            var needNormals = true;
 
-            this._defines.reset();
-
-            if (this.opacity < 1.0) {
-                this._defines.TRANSPARENT = true;
+            if (this.opacity < 1.0 && !defines.TRANSPARENT) {
+                defines.TRANSPARENT = true;
+                defines.markAsUnprocessed();
             }
 
-            // Fog
-            if (scene.fogEnabled && mesh && mesh.applyFog && scene.fogMode !== Scene.FOGMODE_NONE && this.fogEnabled) {
-                this._defines.FOG = true;
-            }
+            MaterialHelper.PrepareDefinesForMisc(mesh, scene, false, false, this.fogEnabled, defines);
 
             // Get correct effect      
-            if (!this._effect || !this._defines.isEqual(this._cachedDefines)) {
-                this._defines.cloneTo(this._cachedDefines);
+            if (defines.isDirty) {
+                defines.markAsProcessed();
                 scene.resetCachedMaterial();
 
                 // Attributes
@@ -127,18 +115,18 @@ module BABYLON {
                 var shaderName = scene.getEngine().getCaps().standardDerivatives ? "grid" : "legacygrid";
 
                 // Defines
-                var join = this._defines.toString();
-                this._effect = scene.getEngine().createEffect(shaderName,
+                var join = defines.toString();
+                subMesh.setEffect(scene.getEngine().createEffect(shaderName,
                     attribs,
                     ["worldViewProjection", "mainColor", "lineColor", "gridControl", "vFogInfos", "vFogColor", "world", "view"],
                     [],
                     join,
                     null,
                     this.onCompiled,
-                    this.onError);
+                    this.onError), defines);
             }
 
-            if (!this._effect.isReady()) {
+            if (!subMesh.effect.isReady()) {
                 return false;
             }
 
@@ -148,41 +136,37 @@ module BABYLON {
             return true;
         }
 
-        public bindOnlyWorldMatrix(world: Matrix): void {
+        public bindForSubMesh(world: Matrix, mesh: Mesh, subMesh: SubMesh): void {
             var scene = this.getScene();
 
-            this._effect.setMatrix("worldViewProjection", world.multiply(scene.getTransformMatrix()));
-            this._effect.setMatrix("world", world);
-            this._effect.setMatrix("view", scene.getViewMatrix());
-        }
+            var defines = <GridMaterialDefines>subMesh._materialDefines;
+            if (!defines) {
+                return;
+            }
 
-        public bind(world: Matrix, mesh?: Mesh): void {
-            var scene = this.getScene();
+            var effect = subMesh.effect;
+            this._activeEffect = effect;
 
             // Matrices
             this.bindOnlyWorldMatrix(world);
+            this._activeEffect.setMatrix("worldViewProjection", world.multiply(scene.getTransformMatrix()));
+            this._activeEffect.setMatrix("view", scene.getViewMatrix());
 
             // Uniforms
-            if (scene.getCachedMaterial() !== (<BABYLON.Material>this)) {
-                this._effect.setColor3("mainColor", this.mainColor);
-                this._effect.setColor3("lineColor", this.lineColor);
+            if (this._mustRebind(scene, effect)) {
+                this._activeEffect.setColor3("mainColor", this.mainColor);
+                this._activeEffect.setColor3("lineColor", this.lineColor);
 
                 this._gridControl.x = this.gridRatio;
                 this._gridControl.y = Math.round(this.majorUnitFrequency);
                 this._gridControl.z = this.minorUnitVisibility;
                 this._gridControl.w = this.opacity;
-                this._effect.setVector4("gridControl", this._gridControl);
+                this._activeEffect.setVector4("gridControl", this._gridControl);
             }
-
-            // View
-            if (scene.fogEnabled && mesh.applyFog && scene.fogMode !== Scene.FOGMODE_NONE) {
-                this._effect.setMatrix("view", scene.getViewMatrix());
-            }
-
             // Fog
-            MaterialHelper.BindFogParameters(scene, mesh, this._effect);
+            MaterialHelper.BindFogParameters(scene, mesh, this._activeEffect);
 
-            this._afterBind(mesh);
+            this._afterBind(mesh, this._activeEffect);
         }
 
         public dispose(forceDisposeEffect?: boolean): void {

+ 84 - 132
materialsLibrary/src/lava/babylon.lavaMaterial.ts

@@ -55,8 +55,10 @@ module BABYLON {
         }
     }
 
-    export class LavaMaterial extends Material {
-        @serializeAsTexture()
+    export class LavaMaterial extends PushMaterial {
+        @serializeAsTexture("diffuseTexture")
+        private _diffuseTexture: BaseTexture;
+        @expandToProperty("_markAllSubMeshesAsTexturesDirty")
         public diffuseTexture: BaseTexture;
         
         @serializeAsTexture()
@@ -82,23 +84,22 @@ module BABYLON {
         @serializeAsColor3()
         public diffuseColor = new Color3(1, 1, 1);
         
-        @serialize()
-        public disableLighting = false;
+        @serialize("disableLighting")
+        private _disableLighting = false;
+        @expandToProperty("_markAllSubMeshesAsLightsDirty")
+        public disableLighting: boolean;   
 
-        @serialize()
-        public maxSimultaneousLights = 4;
+        @serialize("maxSimultaneousLights")
+        private _maxSimultaneousLights = 4;
+        @expandToProperty("_markAllSubMeshesAsLightsDirty")
+        public maxSimultaneousLights: number; 
 
         private _worldViewProjectionMatrix = Matrix.Zero();
         private _scaledDiffuse = new Color3();
         private _renderId: number;
 
-        private _defines = new LavaMaterialDefines();
-        private _cachedDefines = new LavaMaterialDefines();
-
         constructor(name: string, scene: Scene) {
             super(name, scene);
-
-            this._cachedDefines.BonesPerMesh = -1;
         }
 
         public needAlphaBlending(): boolean {
@@ -114,150 +115,98 @@ module BABYLON {
         }
 
         // Methods   
-        private _checkCache(scene: Scene, mesh?: AbstractMesh, useInstances?: boolean): boolean {
-            if (!mesh) {
-                return true;
-            }
-
-            if (this._defines.INSTANCES !== useInstances) {
-                return false;
-            }
-
-            return false;
-        }
-
-        public isReady(mesh?: AbstractMesh, useInstances?: boolean): boolean {
-            if (this.checkReadyOnlyOnce) {
-                if (this._wasPreviouslyReady) {
+        public isReadyForSubMesh(mesh: AbstractMesh, subMesh: SubMesh, useInstances?: boolean): boolean {   
+            if (this.isFrozen) {
+                if (this._wasPreviouslyReady && subMesh.effect) {
                     return true;
                 }
             }
 
+            if (!subMesh._materialDefines) {
+                subMesh._materialDefines = new LavaMaterialDefines();
+            }
+
+            var defines = <LavaMaterialDefines>subMesh._materialDefines;
             var scene = this.getScene();
 
             if (!this.checkReadyOnEveryCall) {
                 if (this._renderId === scene.getRenderId()) {
-                    if (this._checkCache(scene, mesh, useInstances)) {
-                        return true;
-                    }
+                    return true;
                 }
             }
 
             var engine = scene.getEngine();
-            var needUVs = false;
-
-            this._defines.reset();
 
             // Textures
-            if (scene.texturesEnabled) {
-                if (this.diffuseTexture && StandardMaterial.DiffuseTextureEnabled) {
-                    if (!this.diffuseTexture.isReady()) {
-                        return false;
-                    } else {
-                        needUVs = true;
-                        this._defines.DIFFUSE = true;
-                    }
+            if (defines._areTexturesDirty) {
+                defines._needUVs = false;
+                if (scene.texturesEnabled) {
+                    if (this._diffuseTexture && StandardMaterial.DiffuseTextureEnabled) {
+                        if (!this._diffuseTexture.isReady()) {
+                            return false;
+                        } else {
+                            defines._needUVs = true;
+                            defines.DIFFUSE = true;
+                        }
+                    }                
                 }
             }
 
-            // Effect
-            if (scene.clipPlane) {
-                this._defines.CLIPPLANE = true;
-            }
-
-            if (engine.getAlphaTesting()) {
-                this._defines.ALPHATEST = 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;
-            }
+               // Misc.
+            MaterialHelper.PrepareDefinesForMisc(mesh, scene, false, this.pointsCloud, this.fogEnabled, defines);
 
-            if (scene.lightsEnabled && !this.disableLighting) {
-                MaterialHelper.PrepareDefinesForLights(scene, mesh, this._defines, false, this.maxSimultaneousLights);
-            }
+            // Lights
+            defines._needNormals = MaterialHelper.PrepareDefinesForLights(scene, mesh, defines, false, this._maxSimultaneousLights, this._disableLighting);
 
+            // Values that need to be evaluated on every frame
+            MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances);
+            
             // Attribs
-            if (mesh) {
-                if (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;
-                }
-            }
+            MaterialHelper.PrepareDefinesForAttributes(mesh, defines, true, true);
 
             // Get correct effect      
-            if (!this._defines.isEqual(this._cachedDefines)) {
-                this._defines.cloneTo(this._cachedDefines);
-
+            if (defines.isDirty) {
+                defines.markAsProcessed();
                 scene.resetCachedMaterial();
 
                 // Fallbacks
                 var fallbacks = new EffectFallbacks();
-                if (this._defines.FOG) {
+                if (defines.FOG) {
                     fallbacks.addFallback(1, "FOG");
                 }
 
-                MaterialHelper.HandleFallbacksForShadows(this._defines, fallbacks);
+                MaterialHelper.HandleFallbacksForShadows(defines, fallbacks);
 
-                if (this._defines.NUM_BONE_INFLUENCERS > 0) {
+                if (defines.NUM_BONE_INFLUENCERS > 0) {
                     fallbacks.addCPUSkinningFallback(0, mesh);
                 }
 
                 //Attributes
                 var attribs = [VertexBuffer.PositionKind];
 
-                if (this._defines.NORMAL) {
+                if (defines.NORMAL) {
                     attribs.push(VertexBuffer.NormalKind);
                 }
 
-                if (this._defines.UV1) {
+                if (defines.UV1) {
                     attribs.push(VertexBuffer.UVKind);
                 }
 
-                if (this._defines.UV2) {
+                if (defines.UV2) {
                     attribs.push(VertexBuffer.UV2Kind);
                 }
 
-                if (this._defines.VERTEXCOLOR) {
+                if (defines.VERTEXCOLOR) {
                     attribs.push(VertexBuffer.ColorKind);
                 }
 
-                MaterialHelper.PrepareAttributesForBones(attribs, mesh, this._defines, fallbacks);
-                MaterialHelper.PrepareAttributesForInstances(attribs, this._defines);
+                MaterialHelper.PrepareAttributesForBones(attribs, mesh, defines, fallbacks);
+                MaterialHelper.PrepareAttributesForInstances(attribs, defines);
 
                 // Legacy browser patch
                 var shaderName = "lava";
-                var join = this._defines.toString();
-                this._effect = scene.getEngine().createEffect(shaderName,
+                var join = defines.toString();
+                subMesh.setEffect(scene.getEngine().createEffect(shaderName,
                     attribs,
                     ["world", "view", "viewProjection", "vEyePosition", "vLightsType", "vDiffuseColor",
                         "vLightData0", "vLightDiffuse0", "vLightDirection0", "vLightGround0", "lightMatrix0",
@@ -275,9 +224,9 @@ module BABYLON {
                     ["diffuseSampler",
                         "shadowSampler0", "shadowSampler1", "shadowSampler2", "shadowSampler3", "noiseTexture"
                     ],
-                    join, fallbacks, this.onCompiled, this.onError, { maxSimultaneousLights: this.maxSimultaneousLights - 1 });
+                    join, fallbacks, this.onCompiled, this.onError, { maxSimultaneousLights: this.maxSimultaneousLights - 1 }), defines);
             }
-            if (!this._effect.isReady()) {
+            if (!subMesh.effect.isReady()) {
                 return false;
             }
 
@@ -287,73 +236,76 @@ module BABYLON {
             return true;
         }
 
-        public bindOnlyWorldMatrix(world: Matrix): void {
-            this._effect.setMatrix("world", world);
-        }
-
-        public bind(world: Matrix, mesh?: Mesh): void {
+        public bindForSubMesh(world: Matrix, mesh: Mesh, subMesh: SubMesh): void {
             var scene = this.getScene();
 
+            var defines = <LavaMaterialDefines>subMesh._materialDefines;
+            if (!defines) {
+                return;
+            }
+
+            var effect = subMesh.effect;
+            this._activeEffect = effect;
+
             // Matrices        
             this.bindOnlyWorldMatrix(world);
-            this._effect.setMatrix("viewProjection", scene.getTransformMatrix());
+            this._activeEffect.setMatrix("viewProjection", scene.getTransformMatrix());
 
             // Bones
-            MaterialHelper.BindBonesParameters(mesh, this._effect);
+            MaterialHelper.BindBonesParameters(mesh, this._activeEffect);
 
-            if (scene.getCachedMaterial() !== this) {
+            if (this._mustRebind(scene, effect)) {
                 // Textures        
                 if (this.diffuseTexture && StandardMaterial.DiffuseTextureEnabled) {
-                    this._effect.setTexture("diffuseSampler", this.diffuseTexture);
+                    this._activeEffect.setTexture("diffuseSampler", this.diffuseTexture);
 
-                    this._effect.setFloat2("vDiffuseInfos", this.diffuseTexture.coordinatesIndex, this.diffuseTexture.level);
-                    this._effect.setMatrix("diffuseMatrix", this.diffuseTexture.getTextureMatrix());
+                    this._activeEffect.setFloat2("vDiffuseInfos", this.diffuseTexture.coordinatesIndex, this.diffuseTexture.level);
+                    this._activeEffect.setMatrix("diffuseMatrix", this.diffuseTexture.getTextureMatrix());
                 }
 
                 if (this.noiseTexture) {
-                    this._effect.setTexture("noiseTexture", this.noiseTexture);
+                    this._activeEffect.setTexture("noiseTexture", this.noiseTexture);
                 }
 
                 // Clip plane
-                MaterialHelper.BindClipPlane(this._effect, scene);
+                MaterialHelper.BindClipPlane(this._activeEffect, scene);
 
                 // Point size
                 if (this.pointsCloud) {
-                    this._effect.setFloat("pointSize", this.pointSize);
+                    this._activeEffect.setFloat("pointSize", this.pointSize);
                 }
 
-                this._effect.setVector3("vEyePosition", scene._mirroredCameraPosition ? scene._mirroredCameraPosition : scene.activeCamera.position);
+                this._activeEffect.setVector3("vEyePosition", scene._mirroredCameraPosition ? scene._mirroredCameraPosition : scene.activeCamera.position);
             }
 
-            this._effect.setColor4("vDiffuseColor", this._scaledDiffuse, this.alpha * mesh.visibility);
+            this._activeEffect.setColor4("vDiffuseColor", this._scaledDiffuse, this.alpha * mesh.visibility);
 
             if (scene.lightsEnabled && !this.disableLighting) {
-                MaterialHelper.BindLights(scene, mesh, this._effect, this._defines);
+                MaterialHelper.BindLights(scene, mesh, this._activeEffect, defines);
             }
 
             // View
             if (scene.fogEnabled && mesh.applyFog && scene.fogMode !== Scene.FOGMODE_NONE) {
-                this._effect.setMatrix("view", scene.getViewMatrix());
+                this._activeEffect.setMatrix("view", scene.getViewMatrix());
             }
 
             // Fog
-            MaterialHelper.BindFogParameters(scene, mesh, this._effect);
+            MaterialHelper.BindFogParameters(scene, mesh, this._activeEffect);
 
 
             this._lastTime += scene.getEngine().getDeltaTime();
-            this._effect.setFloat("time", this._lastTime * this.speed / 1000);
+            this._activeEffect.setFloat("time", this._lastTime * this.speed / 1000);
 
             if (! this.fogColor) {
                 this.fogColor = Color3.Black();
             }
-            this._effect.setColor3("fogColor", this.fogColor);
-            this._effect.setFloat("fogDensity", this.fogDensity);
-
-            this._effect.setFloat("lowFrequencySpeed", this.lowFrequencySpeed);
-            this._effect.setFloat("movingSpeed", this.movingSpeed);
+            this._activeEffect.setColor3("fogColor", this.fogColor);
+            this._activeEffect.setFloat("fogDensity", this.fogDensity);
 
+            this._activeEffect.setFloat("lowFrequencySpeed", this.lowFrequencySpeed);
+            this._activeEffect.setFloat("movingSpeed", this.movingSpeed);
 
-            this._afterBind(mesh);
+            this._afterBind(mesh, this._activeEffect);
         }
 
         public getAnimatables(): IAnimatable[] {

+ 81 - 126
materialsLibrary/src/normal/babylon.normalMaterial.ts

@@ -55,27 +55,31 @@ module BABYLON {
         }
     }
 
-    export class NormalMaterial extends Material {
-        @serializeAsTexture()
+    export class NormalMaterial extends PushMaterial {
+        @serializeAsTexture("diffuseTexture")
+        private _diffuseTexture: BaseTexture;
+        @expandToProperty("_markAllSubMeshesAsTexturesDirty")
         public diffuseTexture: BaseTexture;
 
         @serializeAsColor3()
         public diffuseColor = new Color3(1, 1, 1);
         
-        @serialize()
-        public disableLighting = false;
+        @serialize("disableLighting")
+        private _disableLighting = false;
+        @expandToProperty("_markAllSubMeshesAsLightsDirty")
+        public disableLighting: boolean;   
+        
+        @serialize("maxSimultaneousLights")
+        private _maxSimultaneousLights = 4;
+        @expandToProperty("_markAllSubMeshesAsLightsDirty")
+        public maxSimultaneousLights: number; 
 
         private _worldViewProjectionMatrix = Matrix.Zero();
         private _scaledDiffuse = new Color3();
         private _renderId: number;
 
-        private _defines = new NormalMaterialDefines();
-        private _cachedDefines = new NormalMaterialDefines();
-
         constructor(name: string, scene: Scene) {
             super(name, scene);
-
-            this._cachedDefines.BonesPerMesh = -1;
         }
 
         public needAlphaBlending(): boolean {
@@ -91,151 +95,98 @@ module BABYLON {
         }
 
         // Methods   
-        private _checkCache(scene: Scene, mesh?: AbstractMesh, useInstances?: boolean): boolean {
-            if (!mesh) {
-                return true;
-            }
-
-            if (this._defines.INSTANCES !== useInstances) {
-                return false;
-            }
-
-            return false;
-        }
-
-        public isReady(mesh?: AbstractMesh, useInstances?: boolean): boolean {
-            if (this.checkReadyOnlyOnce) {
-                if (this._wasPreviouslyReady) {
+        public isReadyForSubMesh(mesh: AbstractMesh, subMesh: SubMesh, useInstances?: boolean): boolean {   
+            if (this.isFrozen) {
+                if (this._wasPreviouslyReady && subMesh.effect) {
                     return true;
                 }
             }
 
+            if (!subMesh._materialDefines) {
+                subMesh._materialDefines = new NormalMaterialDefines();
+            }
+
+            var defines = <NormalMaterialDefines>subMesh._materialDefines;
             var scene = this.getScene();
 
             if (!this.checkReadyOnEveryCall) {
                 if (this._renderId === scene.getRenderId()) {
-                    if (this._checkCache(scene, mesh, useInstances)) {
-                        return true;
-                    }
+                    return true;
                 }
             }
 
             var engine = scene.getEngine();
-            var needNormals = false;
-            var needUVs = false;
-
-            this._defines.reset();
-
-            // Textures
-            if (scene.texturesEnabled) {
-                if (this.diffuseTexture && StandardMaterial.DiffuseTextureEnabled) {
-                    if (!this.diffuseTexture.isReady()) {
-                        return false;
-                    } else {
-                        needUVs = true;
-                        this._defines.DIFFUSE = true;
-                    }
-                }                
-            }
 
-            // Effect
-            if (scene.clipPlane) {
-                this._defines.CLIPPLANE = true;
-            }
-
-            if (engine.getAlphaTesting()) {
-                this._defines.ALPHATEST = true;
-            }
-
-            // Point size
-            if (this.pointsCloud || scene.forcePointsCloud) {
-                this._defines.POINTSIZE = true;
+             // Textures
+            if (defines._areTexturesDirty) {
+                defines._needUVs = false;
+                if (scene.texturesEnabled) {
+                    if (this._diffuseTexture && StandardMaterial.DiffuseTextureEnabled) {
+                        if (!this._diffuseTexture.isReady()) {
+                            return false;
+                        } else {
+                            defines._needUVs = true;
+                            defines.DIFFUSE = true;
+                        }
+                    }                
+                }
             }
 
-            // Fog
-            if (scene.fogEnabled && mesh && mesh.applyFog && scene.fogMode !== Scene.FOGMODE_NONE && this.fogEnabled) {
-                this._defines.FOG = true;
-            }
+            // Misc.
+            MaterialHelper.PrepareDefinesForMisc(mesh, scene, false, this.pointsCloud, this.fogEnabled, defines);
 
-            var lightIndex = 0;
-            if (scene.lightsEnabled && !this.disableLighting) {
-                needNormals = MaterialHelper.PrepareDefinesForLights(scene, mesh, this._defines, false);
-            }
+            // Lights
+            defines._needNormals = MaterialHelper.PrepareDefinesForLights(scene, mesh, defines, false, this._maxSimultaneousLights, this._disableLighting);
 
+            // Values that need to be evaluated on every frame
+            MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances);
+            
             // 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;
-                }
-            }
+            MaterialHelper.PrepareDefinesForAttributes(mesh, defines, true, true);
 
             // Get correct effect      
-            if (!this._defines.isEqual(this._cachedDefines)) {
-                this._defines.cloneTo(this._cachedDefines);
+            if (defines.isDirty) {
+                defines.markAsProcessed();
 
                 scene.resetCachedMaterial();
 
                 // Fallbacks
                 var fallbacks = new EffectFallbacks();             
-                if (this._defines.FOG) {
+                if (defines.FOG) {
                     fallbacks.addFallback(1, "FOG");
                 }
 
-                MaterialHelper.HandleFallbacksForShadows(this._defines, fallbacks);
+                MaterialHelper.HandleFallbacksForShadows(defines, fallbacks);
                 
-                if (this._defines.NUM_BONE_INFLUENCERS > 0) {
+                if (defines.NUM_BONE_INFLUENCERS > 0) {
                     fallbacks.addCPUSkinningFallback(0, mesh);
                 }
 
                 //Attributes
                 var attribs = [VertexBuffer.PositionKind];
 
-                if (this._defines.NORMAL) {
+                if (defines.NORMAL) {
                     attribs.push(VertexBuffer.NormalKind);
                 }
 
-                if (this._defines.UV1) {
+                if (defines.UV1) {
                     attribs.push(VertexBuffer.UVKind);
                 }
 
-                if (this._defines.UV2) {
+                if (defines.UV2) {
                     attribs.push(VertexBuffer.UV2Kind);
                 }
 
-                if (this._defines.VERTEXCOLOR) {
+                if (defines.VERTEXCOLOR) {
                     attribs.push(VertexBuffer.ColorKind);
                 }
 
-                MaterialHelper.PrepareAttributesForBones(attribs, mesh, this._defines, fallbacks);
-                MaterialHelper.PrepareAttributesForInstances(attribs, this._defines);
+                MaterialHelper.PrepareAttributesForBones(attribs, mesh, defines, fallbacks);
+                MaterialHelper.PrepareAttributesForInstances(attribs, defines);
 
                 var shaderName = "normal";
-                var join = this._defines.toString();
-                this._effect = scene.getEngine().createEffect(shaderName,
+                var join = defines.toString();
+                subMesh.setEffect(scene.getEngine().createEffect(shaderName,
                     attribs,
                     ["world", "view", "viewProjection", "vEyePosition", "vLightsType", "vDiffuseColor",
                         "vLightData0", "vLightDiffuse0", "vLightDirection0", "vLightGround0", "lightMatrix0",
@@ -251,9 +202,9 @@ module BABYLON {
                     ["diffuseSampler",
                         "shadowSampler0", "shadowSampler1", "shadowSampler2", "shadowSampler3"
                     ],
-                    join, fallbacks, this.onCompiled, this.onError, { maxSimultaneousLights: 4 });
+                    join, fallbacks, this.onCompiled, this.onError, { maxSimultaneousLights: 4 }), defines);
             }
-            if (!this._effect.isReady()) {
+            if (!subMesh.effect.isReady()) {
                 return false;
             }
 
@@ -263,55 +214,59 @@ module BABYLON {
             return true;
         }
 
-        public bindOnlyWorldMatrix(world: Matrix): void {
-            this._effect.setMatrix("world", world);
-        }
-
-        public bind(world: Matrix, mesh?: Mesh): void {
+        public bindForSubMesh(world: Matrix, mesh: Mesh, subMesh: SubMesh): void {
             var scene = this.getScene();
 
+            var defines = <NormalMaterialDefines>subMesh._materialDefines;
+            if (!defines) {
+                return;
+            }
+
+            var effect = subMesh.effect;
+            this._activeEffect = effect;
+
             // Matrices        
             this.bindOnlyWorldMatrix(world);
-            this._effect.setMatrix("viewProjection", scene.getTransformMatrix());
+            this._activeEffect.setMatrix("viewProjection", scene.getTransformMatrix());
 
             // Bones
-            MaterialHelper.BindBonesParameters(mesh, this._effect);
+            MaterialHelper.BindBonesParameters(mesh, this._activeEffect);
 
-            if (scene.getCachedMaterial() !== this) {
+            if (this._mustRebind(scene, effect)) {
                 // Textures        
                 if (this.diffuseTexture && StandardMaterial.DiffuseTextureEnabled) {
-                    this._effect.setTexture("diffuseSampler", this.diffuseTexture);
+                    this._activeEffect.setTexture("diffuseSampler", this.diffuseTexture);
 
-                    this._effect.setFloat2("vDiffuseInfos", this.diffuseTexture.coordinatesIndex, this.diffuseTexture.level);
-                    this._effect.setMatrix("diffuseMatrix", this.diffuseTexture.getTextureMatrix());
+                    this._activeEffect.setFloat2("vDiffuseInfos", this.diffuseTexture.coordinatesIndex, this.diffuseTexture.level);
+                    this._activeEffect.setMatrix("diffuseMatrix", this.diffuseTexture.getTextureMatrix());
                 }
                 // Clip plane
-                MaterialHelper.BindClipPlane(this._effect, scene);
+                MaterialHelper.BindClipPlane(this._activeEffect, scene);
 
                 // Point size
                 if (this.pointsCloud) {
-                    this._effect.setFloat("pointSize", this.pointSize);
+                    this._activeEffect.setFloat("pointSize", this.pointSize);
                 }
 
-                this._effect.setVector3("vEyePosition", scene._mirroredCameraPosition ? scene._mirroredCameraPosition : scene.activeCamera.position);                
+                this._activeEffect.setVector3("vEyePosition", scene._mirroredCameraPosition ? scene._mirroredCameraPosition : scene.activeCamera.position);                
             }
 
-            this._effect.setColor4("vDiffuseColor", this.diffuseColor, this.alpha * mesh.visibility);
+            this._activeEffect.setColor4("vDiffuseColor", this.diffuseColor, this.alpha * mesh.visibility);
 
             // Lights
             if (scene.lightsEnabled && !this.disableLighting) {
-                MaterialHelper.BindLights(scene, mesh, this._effect, this._defines);          
+                MaterialHelper.BindLights(scene, mesh, this._activeEffect, defines);          
             }
 
             // View
             if (scene.fogEnabled && mesh.applyFog && scene.fogMode !== Scene.FOGMODE_NONE) {
-                this._effect.setMatrix("view", scene.getViewMatrix());
+                this._activeEffect.setMatrix("view", scene.getViewMatrix());
             }
 
             // Fog
-            MaterialHelper.BindFogParameters(scene, mesh, this._effect);
+            MaterialHelper.BindFogParameters(scene, mesh, this._activeEffect);
 
-            this._afterBind(mesh);
+            this._afterBind(mesh, this._activeEffect);
         }
 
         public getAnimatables(): IAnimatable[] {

+ 44 - 71
materialsLibrary/src/sky/babylon.skyMaterial.ts

@@ -14,7 +14,7 @@ module BABYLON {
         }
     }
     
-    export class SkyMaterial extends Material {
+    export class SkyMaterial extends PushMaterial {
         // Public members
         @serialize()
         public luminance: number = 1.0;
@@ -49,10 +49,7 @@ module BABYLON {
         // Private members
         private _cameraPosition: Vector3 = Vector3.Zero();
         
-        private _renderId: number;
-        
-        private _defines = new SkyMaterialDefines();
-        private _cachedDefines = new SkyMaterialDefines();
+        private _renderId: number;        
 
         constructor(name: string, scene: Scene) {
             super(name, scene);
@@ -71,84 +68,56 @@ module BABYLON {
         }
 
         // Methods   
-        private _checkCache(scene: Scene, mesh?: AbstractMesh, useInstances?: boolean): boolean {
-            if (!mesh) {
-                return true;
-            }
-
-            return false;
-        }
-
-        public isReady(mesh?: AbstractMesh, useInstances?: boolean): boolean {
-            if (this.checkReadyOnlyOnce) {
-                if (this._wasPreviouslyReady) {
+        public isReadyForSubMesh(mesh: AbstractMesh, subMesh: SubMesh, useInstances?: boolean): boolean {   
+            if (this.isFrozen) {
+                if (this._wasPreviouslyReady && subMesh.effect) {
                     return true;
                 }
             }
 
+            if (!subMesh._materialDefines) {
+                subMesh._materialDefines = new SkyMaterialDefines();
+            }
+
+            var defines = <SkyMaterialDefines>subMesh._materialDefines;
             var scene = this.getScene();
 
             if (!this.checkReadyOnEveryCall) {
                 if (this._renderId === scene.getRenderId()) {
-                    if (this._checkCache(scene, mesh, useInstances)) {
-                        return true;
-                    }
+                    return true;
                 }
             }
 
             var engine = scene.getEngine();
-            this._defines.reset();
 
-            // Effect
-            if (scene.clipPlane) {
-                this._defines.CLIPPLANE = 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;
-            }
+            MaterialHelper.PrepareDefinesForMisc(mesh, scene, false, this.pointsCloud, this.fogEnabled, defines);
             
             // Attribs
-            if (mesh) {
-                if (mesh.useVertexColors && mesh.isVerticesDataPresent(VertexBuffer.ColorKind)) {
-                    this._defines.VERTEXCOLOR = true;
-
-                    if (mesh.hasVertexAlpha) {
-                        this._defines.VERTEXALPHA = true;
-                    }
-                }
-            }
+            MaterialHelper.PrepareDefinesForAttributes(mesh, defines, true, false);
 
             // Get correct effect      
-            if (!this._defines.isEqual(this._cachedDefines) || !this._effect) {
-                this._defines.cloneTo(this._cachedDefines);
+            if (defines.isDirty) {
+                defines.markAsProcessed();
                 
                 scene.resetCachedMaterial();
                 
                 // Fallbacks
                 var fallbacks = new EffectFallbacks();             
-                if (this._defines.FOG) {
+                if (defines.FOG) {
                     fallbacks.addFallback(1, "FOG");
                 }
                 
                 //Attributes
                 var attribs = [VertexBuffer.PositionKind];
 
-                if (this._defines.VERTEXCOLOR) {
+                if (defines.VERTEXCOLOR) {
                     attribs.push(VertexBuffer.ColorKind);
                 }
 
-                // Legacy browser patch
                 var shaderName = "sky";
                 
-                var join = this._defines.toString();
-                this._effect = scene.getEngine().createEffect(shaderName,
+                var join = defines.toString();
+                subMesh.setEffect(scene.getEngine().createEffect(shaderName,
                     attribs,
                     ["world", "viewProjection", "view",
                         "vFogInfos", "vFogColor", "pointSize", "vClipPlane",
@@ -156,10 +125,10 @@ module BABYLON {
                         "cameraPosition"
                     ],
                     [],
-                    join, fallbacks, this.onCompiled, this.onError);
+                    join, fallbacks, this.onCompiled, this.onError), defines);
             }
             
-            if (!this._effect.isReady()) {
+            if (!subMesh.effect.isReady()) {
                 return false;
             }
 
@@ -169,37 +138,41 @@ module BABYLON {
             return true;
         }
 
-        public bindOnlyWorldMatrix(world: Matrix): void {
-            this._effect.setMatrix("world", world);
-        }
-
-        public bind(world: Matrix, mesh?: Mesh): void {
+        public bindForSubMesh(world: Matrix, mesh: Mesh, subMesh: SubMesh): void {
             var scene = this.getScene();
 
+            var defines = <SkyMaterialDefines>subMesh._materialDefines;
+            if (!defines) {
+                return;
+            }
+
+            var effect = subMesh.effect;
+            this._activeEffect = effect;
+
             // Matrices        
             this.bindOnlyWorldMatrix(world);
-            this._effect.setMatrix("viewProjection", scene.getTransformMatrix());
+            this._activeEffect.setMatrix("viewProjection", scene.getTransformMatrix());
 
-            if (scene.getCachedMaterial() !== this) {
+            if (this._mustRebind(scene, effect)) {
                 // Clip plane
                 if (scene.clipPlane) {
                     var clipPlane = scene.clipPlane;
-                    this._effect.setFloat4("vClipPlane", clipPlane.normal.x, clipPlane.normal.y, clipPlane.normal.z, clipPlane.d);
+                    this._activeEffect.setFloat4("vClipPlane", clipPlane.normal.x, clipPlane.normal.y, clipPlane.normal.z, clipPlane.d);
                 }
 
                 // Point size
                 if (this.pointsCloud) {
-                    this._effect.setFloat("pointSize", this.pointSize);
+                    this._activeEffect.setFloat("pointSize", this.pointSize);
                 }               
             }
 
             // View
             if (scene.fogEnabled && mesh.applyFog && scene.fogMode !== Scene.FOGMODE_NONE) {
-                this._effect.setMatrix("view", scene.getViewMatrix());
+                this._activeEffect.setMatrix("view", scene.getViewMatrix());
             }
             
             // Fog
-            MaterialHelper.BindFogParameters(scene, mesh, this._effect);
+            MaterialHelper.BindFogParameters(scene, mesh, this._activeEffect);
             
             // Sky
             var camera = scene.activeCamera;
@@ -208,17 +181,17 @@ module BABYLON {
                 this._cameraPosition.x = cameraWorldMatrix.m[12];
                 this._cameraPosition.y = cameraWorldMatrix.m[13];
                 this._cameraPosition.z = cameraWorldMatrix.m[14];
-                this._effect.setVector3("cameraPosition", this._cameraPosition);
+                this._activeEffect.setVector3("cameraPosition", this._cameraPosition);
             }
             
             if (this.luminance > 0) {
-                this._effect.setFloat("luminance", this.luminance);
+                this._activeEffect.setFloat("luminance", this.luminance);
             }
             
-			this._effect.setFloat("turbidity", this.turbidity);
-			this._effect.setFloat("rayleigh", this.rayleigh);
-			this._effect.setFloat("mieCoefficient", this.mieCoefficient);
-			this._effect.setFloat("mieDirectionalG", this.mieDirectionalG);
+			this._activeEffect.setFloat("turbidity", this.turbidity);
+			this._activeEffect.setFloat("rayleigh", this.rayleigh);
+			this._activeEffect.setFloat("mieCoefficient", this.mieCoefficient);
+			this._activeEffect.setFloat("mieDirectionalG", this.mieDirectionalG);
             
             if (!this.useSunPosition) {
                 var theta = Math.PI * (this.inclination - 0.5);
@@ -229,9 +202,9 @@ module BABYLON {
                 this.sunPosition.z = this.distance * Math.sin(phi) * Math.cos(theta);
             }
             
-			this._effect.setVector3("sunPosition", this.sunPosition);
+			this._activeEffect.setVector3("sunPosition", this.sunPosition);
 
-            this._afterBind(mesh);
+            this._afterBind(mesh, this._activeEffect);
         }
 
         public getAnimatables(): IAnimatable[] {

+ 115 - 156
materialsLibrary/src/terrain/babylon.terrainMaterial.ts

@@ -1,7 +1,6 @@
 /// <reference path="../../../dist/preview release/babylon.d.ts"/>
 
 module BABYLON {
-    var maxSimultaneousLights = 4;
 
     class TerrainMaterialDefines extends MaterialDefines {
         public DIFFUSE = false;
@@ -26,27 +25,41 @@ module BABYLON {
         }
     }
 
-    export class TerrainMaterial extends Material {
-        @serializeAsTexture()
-        public mixTexture: BaseTexture;
+    export class TerrainMaterial extends PushMaterial {
+        @serializeAsTexture("mixTexture")
+        private _mixTexture: BaseTexture;
+        @expandToProperty("_markAllSubMeshesAsTexturesDirty")
+        public mixTexture: BaseTexture;        
         
-        @serializeAsTexture()
+        @serializeAsTexture("diffuseTexture1")
+        private _diffuseTexture1: Texture;
+        @expandToProperty("_markAllSubMeshesAsTexturesDirty")
         public diffuseTexture1: Texture;
-        
-        @serializeAsTexture()
+
+        @serializeAsTexture("diffuseTexture2")
+        private _diffuseTexture2: Texture;
+        @expandToProperty("_markAllSubMeshesAsTexturesDirty")
         public diffuseTexture2: Texture;
         
-        @serializeAsTexture()
+        @serializeAsTexture("diffuseTexture3")
+        private _diffuseTexture3: Texture;
+        @expandToProperty("_markAllSubMeshesAsTexturesDirty")
         public diffuseTexture3: Texture;
         
-        @serializeAsTexture()
-        public bumpTexture1: Texture;
+        @serializeAsTexture("bumpTexture1")
+        private _bumpTexture1: Texture;
+        @expandToProperty("_markAllSubMeshesAsTexturesDirty")
+        public bumpTexture1: Texture;        
         
-        @serializeAsTexture()
-        public bumpTexture2: Texture;
+        @serializeAsTexture("bumpTexture2")
+        private _bumpTexture2: Texture;
+        @expandToProperty("_markAllSubMeshesAsTexturesDirty")
+        public bumpTexture2: Texture;        
         
-        @serializeAsTexture()
-        public bumpTexture3: Texture;
+        @serializeAsTexture("bumpTexture3")
+        private _bumpTexture3: Texture;
+        @expandToProperty("_markAllSubMeshesAsTexturesDirty")
+        public bumpTexture3: Texture;   
         
         @serializeAsColor3()
         public diffuseColor = new Color3(1, 1, 1);
@@ -57,22 +70,21 @@ module BABYLON {
         @serialize()
         public specularPower = 64;
         
-        @serialize()
-        public disableLighting = false;
+        @serialize("disableLighting")
+        private _disableLighting = false;
+        @expandToProperty("_markAllSubMeshesAsLightsDirty")
+        public disableLighting: boolean;   
         
-        @serialize()
-        public maxSimultaneousLights = 4;
+        @serialize("maxSimultaneousLights")
+        private _maxSimultaneousLights = 4;
+        @expandToProperty("_markAllSubMeshesAsLightsDirty")
+        public maxSimultaneousLights: number; 
 
         private _worldViewProjectionMatrix = Matrix.Zero();
         private _renderId: number;
 
-        private _defines = new TerrainMaterialDefines();
-        private _cachedDefines = new TerrainMaterialDefines();
-
         constructor(name: string, scene: Scene) {
             super(name, scene);
-
-            this._cachedDefines.BonesPerMesh = -1;
         }
 
         public needAlphaBlending(): boolean {
@@ -88,156 +100,99 @@ module BABYLON {
         }
 
         // Methods   
-        private _checkCache(scene: Scene, mesh?: AbstractMesh, useInstances?: boolean): boolean {
-            if (!mesh) {
-                return true;
-            }
-
-            if (this._defines.INSTANCES !== useInstances) {
-                return false;
-            }
-
-            return false;
-        }
-
-        public isReady(mesh?: AbstractMesh, useInstances?: boolean): boolean {
-            if (this.checkReadyOnlyOnce) {
-                if (this._wasPreviouslyReady) {
+        public isReadyForSubMesh(mesh: AbstractMesh, subMesh: SubMesh, useInstances?: boolean): boolean {   
+            if (this.isFrozen) {
+                if (this._wasPreviouslyReady && subMesh.effect) {
                     return true;
                 }
             }
 
+            if (!subMesh._materialDefines) {
+                subMesh._materialDefines = new TerrainMaterialDefines();
+            }
+
+            var defines = <TerrainMaterialDefines>subMesh._materialDefines;
             var scene = this.getScene();
 
             if (!this.checkReadyOnEveryCall) {
                 if (this._renderId === scene.getRenderId()) {
-                    if (this._checkCache(scene, mesh, useInstances)) {
-                        return true;
-                    }
+                    return true;
                 }
             }
 
             var engine = scene.getEngine();
-            var needNormals = false;
-            var needUVs = false;
-
-            this._defines.reset();
-
-            // Effect
-            if (scene.clipPlane) {
-                this._defines.CLIPPLANE = true;
-            }
 
-            if (engine.getAlphaTesting()) {
-                this._defines.ALPHATEST = 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;
-            }
-
-            // Lights
-            if (scene.lightsEnabled && !this.disableLighting) {
-                needNormals = MaterialHelper.PrepareDefinesForLights(scene, mesh, this._defines, true, this.maxSimultaneousLights);
-            }
-            
             // Textures
             if (scene.texturesEnabled) {
                 if (this.mixTexture && StandardMaterial.DiffuseTextureEnabled) {
                     if (!this.mixTexture.isReady()) {
                         return false;
                     } else {
-                        needUVs = true;
-                        this._defines.DIFFUSE = true;
+                        defines._needUVs = true;
+                        defines.DIFFUSE = true;
                     }
                 }
                 if ((this.bumpTexture1 || this.bumpTexture2 || this.bumpTexture3) && StandardMaterial.BumpTextureEnabled) {
-                    needUVs = true;
-                    needNormals = true;
-                    this._defines.BUMP = true;
+                    defines._needUVs = true;
+                    defines._needNormals = true;
+                    defines.BUMP = true;
                 }
             }
+            
+            // Misc.
+            MaterialHelper.PrepareDefinesForMisc(mesh, scene, false, this.pointsCloud, this.fogEnabled, defines);
 
-            // 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);
-                }
+            // Lights
+            defines._needNormals = MaterialHelper.PrepareDefinesForLights(scene, mesh, defines, false, this._maxSimultaneousLights, this._disableLighting);
 
-                // Instances
-                if (useInstances) {
-                    this._defines.INSTANCES = true;
-                }
-            }
+            // Values that need to be evaluated on every frame
+            MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances);
+            
+            // Attribs
+            MaterialHelper.PrepareDefinesForAttributes(mesh, defines, true, true);
 
             // Get correct effect      
-            if (!this._defines.isEqual(this._cachedDefines)) {
-                this._defines.cloneTo(this._cachedDefines);
-
+            if (defines.isDirty) {
+                defines.markAsProcessed();
                 scene.resetCachedMaterial();
 
                 // Fallbacks
                 var fallbacks = new EffectFallbacks();             
-                if (this._defines.FOG) {
+                if (defines.FOG) {
                     fallbacks.addFallback(1, "FOG");
                 }
 
-                MaterialHelper.HandleFallbacksForShadows(this._defines, fallbacks, this.maxSimultaneousLights);
+                MaterialHelper.HandleFallbacksForShadows(defines, fallbacks, this.maxSimultaneousLights);
              
-                if (this._defines.NUM_BONE_INFLUENCERS > 0) {
+                if (defines.NUM_BONE_INFLUENCERS > 0) {
                     fallbacks.addCPUSkinningFallback(0, mesh);
                 }
 
                 //Attributes
                 var attribs = [VertexBuffer.PositionKind];
 
-                if (this._defines.NORMAL) {
+                if (defines.NORMAL) {
                     attribs.push(VertexBuffer.NormalKind);
                 }
 
-                if (this._defines.UV1) {
+                if (defines.UV1) {
                     attribs.push(VertexBuffer.UVKind);
                 }
 
-                if (this._defines.UV2) {
+                if (defines.UV2) {
                     attribs.push(VertexBuffer.UV2Kind);
                 }
 
-                if (this._defines.VERTEXCOLOR) {
+                if (defines.VERTEXCOLOR) {
                     attribs.push(VertexBuffer.ColorKind);
                 }
 
-                MaterialHelper.PrepareAttributesForBones(attribs, mesh, this._defines, fallbacks);
-                MaterialHelper.PrepareAttributesForInstances(attribs, this._defines);
+                MaterialHelper.PrepareAttributesForBones(attribs, mesh, defines, fallbacks);
+                MaterialHelper.PrepareAttributesForInstances(attribs, defines);
 
                 // Legacy browser patch
                 var shaderName = "terrain";
-                var join = this._defines.toString();
+                var join = defines.toString();
                 var uniforms = ["world", "view", "viewProjection", "vEyePosition", "vLightsType", "vDiffuseColor", "vSpecularColor",
                     "vFogInfos", "vFogColor", "pointSize",
                     "vTextureInfos", 
@@ -250,13 +205,13 @@ module BABYLON {
                     "bump1Sampler", "bump2Sampler", "bump3Sampler"
                 ];
                 
-                MaterialHelper.PrepareUniformsAndSamplersList(uniforms, samplers, this._defines, this.maxSimultaneousLights);
+                MaterialHelper.PrepareUniformsAndSamplersList(uniforms, samplers, defines, this.maxSimultaneousLights);
                 
-                this._effect = scene.getEngine().createEffect(shaderName,
+                subMesh.setEffect(scene.getEngine().createEffect(shaderName,
                     attribs, uniforms, samplers,
-                    join, fallbacks, this.onCompiled, this.onError, { maxSimultaneousLights: this.maxSimultaneousLights });
+                    join, fallbacks, this.onCompiled, this.onError, { maxSimultaneousLights: this.maxSimultaneousLights }), defines);
             }
-            if (!this._effect.isReady()) {
+            if (!subMesh.effect.isReady()) {
                 return false;
             }
 
@@ -266,84 +221,88 @@ module BABYLON {
             return true;
         }
 
-        public bindOnlyWorldMatrix(world: Matrix): void {
-            this._effect.setMatrix("world", world);
-        }
-
-        public bind(world: Matrix, mesh?: Mesh): void {
+        public bindForSubMesh(world: Matrix, mesh: Mesh, subMesh: SubMesh): void {
             var scene = this.getScene();
 
+            var defines = <TerrainMaterialDefines>subMesh._materialDefines;
+            if (!defines) {
+                return;
+            }
+
+            var effect = subMesh.effect;
+            this._activeEffect = effect;
+
             // Matrices        
             this.bindOnlyWorldMatrix(world);
-            this._effect.setMatrix("viewProjection", scene.getTransformMatrix());
+            this._activeEffect.setMatrix("viewProjection", scene.getTransformMatrix());
 
             // Bones
-            MaterialHelper.BindBonesParameters(mesh, this._effect);
+            MaterialHelper.BindBonesParameters(mesh, this._activeEffect);
 
-            if (scene.getCachedMaterial() !== this) {
+            if (this._mustRebind(scene, effect)) {
                 // Textures        
                 if (this.mixTexture) {
-                    this._effect.setTexture("textureSampler", this.mixTexture);
-                    this._effect.setFloat2("vTextureInfos", this.mixTexture.coordinatesIndex, this.mixTexture.level);
-                    this._effect.setMatrix("textureMatrix", this.mixTexture.getTextureMatrix());
+                    this._activeEffect.setTexture("textureSampler", this._mixTexture);
+                    this._activeEffect.setFloat2("vTextureInfos", this._mixTexture.coordinatesIndex, this._mixTexture.level);
+                    this._activeEffect.setMatrix("textureMatrix", this._mixTexture.getTextureMatrix());
                     
                     if (StandardMaterial.DiffuseTextureEnabled) {
-                        if (this.diffuseTexture1) {
-                            this._effect.setTexture("diffuse1Sampler", this.diffuseTexture1);
-                            this._effect.setFloat2("diffuse1Infos", this.diffuseTexture1.uScale, this.diffuseTexture1.vScale);
+                        if (this._diffuseTexture1) {
+                            this._activeEffect.setTexture("diffuse1Sampler", this._diffuseTexture1);
+                            this._activeEffect.setFloat2("diffuse1Infos", this._diffuseTexture1.uScale, this._diffuseTexture1.vScale);
                         }
-                        if (this.diffuseTexture2) {
-                            this._effect.setTexture("diffuse2Sampler", this.diffuseTexture2);
-                            this._effect.setFloat2("diffuse2Infos", this.diffuseTexture2.uScale, this.diffuseTexture2.vScale);
+                        if (this._diffuseTexture2) {
+                            this._activeEffect.setTexture("diffuse2Sampler", this._diffuseTexture2);
+                            this._activeEffect.setFloat2("diffuse2Infos", this._diffuseTexture2.uScale, this._diffuseTexture2.vScale);
                         }
-                        if (this.diffuseTexture3) {
-                            this._effect.setTexture("diffuse3Sampler", this.diffuseTexture3);
-                            this._effect.setFloat2("diffuse3Infos", this.diffuseTexture3.uScale, this.diffuseTexture3.vScale);
+                        if (this._diffuseTexture3) {
+                            this._activeEffect.setTexture("diffuse3Sampler", this._diffuseTexture3);
+                            this._activeEffect.setFloat2("diffuse3Infos", this._diffuseTexture3.uScale, this._diffuseTexture3.vScale);
                         }
                     }
                     
                     if (StandardMaterial.BumpTextureEnabled && scene.getEngine().getCaps().standardDerivatives) {
-                        if (this.bumpTexture1) {
-                            this._effect.setTexture("bump1Sampler", this.bumpTexture1);
+                        if (this._bumpTexture1) {
+                            this._activeEffect.setTexture("bump1Sampler", this._bumpTexture1);
                         }
-                        if (this.bumpTexture2) {
-                            this._effect.setTexture("bump2Sampler", this.bumpTexture2);
+                        if (this._bumpTexture2) {
+                            this._activeEffect.setTexture("bump2Sampler", this._bumpTexture2);
                         }
-                        if (this.bumpTexture3) {
-                            this._effect.setTexture("bump3Sampler", this.bumpTexture3);
+                        if (this._bumpTexture3) {
+                            this._activeEffect.setTexture("bump3Sampler", this._bumpTexture3);
                         }
                     }
                 }
                 // Clip plane
-                MaterialHelper.BindClipPlane(this._effect, scene);
+                MaterialHelper.BindClipPlane(this._activeEffect, scene);
 
                 // Point size
                 if (this.pointsCloud) {
-                    this._effect.setFloat("pointSize", this.pointSize);
+                    this._activeEffect.setFloat("pointSize", this.pointSize);
                 }
 
-                this._effect.setVector3("vEyePosition", scene._mirroredCameraPosition ? scene._mirroredCameraPosition : scene.activeCamera.position);                
+                this._activeEffect.setVector3("vEyePosition", scene._mirroredCameraPosition ? scene._mirroredCameraPosition : scene.activeCamera.position);                
             }
 
-            this._effect.setColor4("vDiffuseColor", this.diffuseColor, this.alpha * mesh.visibility);
+            this._activeEffect.setColor4("vDiffuseColor", this.diffuseColor, this.alpha * mesh.visibility);
             
-            if (this._defines.SPECULARTERM) {
-                this._effect.setColor4("vSpecularColor", this.specularColor, this.specularPower);
+            if (defines.SPECULARTERM) {
+                this._activeEffect.setColor4("vSpecularColor", this.specularColor, this.specularPower);
             }
 
             if (scene.lightsEnabled && !this.disableLighting) {
-                MaterialHelper.BindLights(scene, mesh, this._effect, this._defines, this.maxSimultaneousLights);
+                MaterialHelper.BindLights(scene, mesh, this._activeEffect, defines, this.maxSimultaneousLights);
             }
 
             // View
             if (scene.fogEnabled && mesh.applyFog && scene.fogMode !== Scene.FOGMODE_NONE) {
-                this._effect.setMatrix("view", scene.getViewMatrix());
+                this._activeEffect.setMatrix("view", scene.getViewMatrix());
             }
 
             // Fog
-            MaterialHelper.BindFogParameters(scene, mesh, this._effect);
+            MaterialHelper.BindFogParameters(scene, mesh, this._activeEffect);
 
-            this._afterBind(mesh);
+            this._afterBind(mesh, this._activeEffect);
         }
 
         public getAnimatables(): IAnimatable[] {

+ 116 - 150
materialsLibrary/src/triPlanar/babylon.triPlanarMaterial.ts

@@ -1,8 +1,6 @@
 /// <reference path="../../../dist/preview release/babylon.d.ts"/>
 
 module BABYLON {
-    var maxSimultaneousLights = 4;
-
     class TriPlanarMaterialDefines extends MaterialDefines {
         public DIFFUSEX = false;
         public DIFFUSEY = false;
@@ -30,28 +28,40 @@ module BABYLON {
         }
     }
 
-    export class TriPlanarMaterial extends Material {
+    export class TriPlanarMaterial extends PushMaterial {
         @serializeAsTexture()
         public mixTexture: BaseTexture;
         
-        @serializeAsTexture()
-        public diffuseTextureX: Texture;
+        @serializeAsTexture("diffuseTextureX")
+        private _diffuseTextureX: BaseTexture;
+        @expandToProperty("_markAllSubMeshesAsTexturesDirty")
+        public diffuseTextureX: BaseTexture;
         
-        @serializeAsTexture()
-        public diffuseTextureY: Texture;
+        @serializeAsTexture("diffuseTexturY")
+        private _diffuseTextureY: BaseTexture;
+        @expandToProperty("_markAllSubMeshesAsTexturesDirty")
+        public diffuseTextureY: BaseTexture;        
         
-        @serializeAsTexture()
-        public diffuseTextureZ: Texture;
+        @serializeAsTexture("diffuseTextureZ")
+        private _diffuseTextureZ: BaseTexture;
+        @expandToProperty("_markAllSubMeshesAsTexturesDirty")
+        public diffuseTextureZ: BaseTexture;        
         
-        @serializeAsTexture()
-        public normalTextureX: Texture;
+        @serializeAsTexture("normalTextureX")
+        private _normalTextureX: BaseTexture;
+        @expandToProperty("_markAllSubMeshesAsTexturesDirty")
+        public normalTextureX: BaseTexture;        
         
-        @serializeAsTexture()
-        public normalTextureY: Texture;
-        
-        @serializeAsTexture()
-        public normalTextureZ: Texture;
+        @serializeAsTexture("normalTextureY")
+        private _normalTextureY: BaseTexture;
+        @expandToProperty("_markAllSubMeshesAsTexturesDirty")
+        public normalTextureY: BaseTexture;        
         
+        @serializeAsTexture("normalTextureZ")
+        private _normalTextureZ: BaseTexture;
+        @expandToProperty("_markAllSubMeshesAsTexturesDirty")
+        public normalTextureZ: BaseTexture;        
+               
         @serialize()
         public tileSize: number = 1;
         
@@ -64,22 +74,21 @@ module BABYLON {
         @serialize()
         public specularPower = 64;
         
-        @serialize()
-        public disableLighting = false;
+        @serialize("disableLighting")
+        private _disableLighting = false;
+        @expandToProperty("_markAllSubMeshesAsLightsDirty")
+        public disableLighting: boolean;   
         
-        @serialize()
-        public maxSimultaneousLights = 4;
+        @serialize("maxSimultaneousLights")
+        private _maxSimultaneousLights = 4;
+        @expandToProperty("_markAllSubMeshesAsLightsDirty")
+        public maxSimultaneousLights: number; 
 
         private _worldViewProjectionMatrix = Matrix.Zero();
         private _renderId: number;
 
-        private _defines = new TriPlanarMaterialDefines();
-        private _cachedDefines = new TriPlanarMaterialDefines();
-
         constructor(name: string, scene: Scene) {
             super(name, scene);
-
-            this._cachedDefines.BonesPerMesh = -1;
         }
 
         public needAlphaBlending(): boolean {
@@ -95,155 +104,108 @@ module BABYLON {
         }
 
         // Methods   
-        private _checkCache(scene: Scene, mesh?: AbstractMesh, useInstances?: boolean): boolean {
-            if (!mesh) {
-                return true;
-            }
-
-            if (this._defines.INSTANCES !== useInstances) {
-                return false;
-            }
-
-            return false;
-        }
-
-        public isReady(mesh?: AbstractMesh, useInstances?: boolean): boolean {
-            if (this.checkReadyOnlyOnce) {
-                if (this._wasPreviouslyReady) {
+        public isReadyForSubMesh(mesh: AbstractMesh, subMesh: SubMesh, useInstances?: boolean): boolean {   
+            if (this.isFrozen) {
+                if (this._wasPreviouslyReady && subMesh.effect) {
                     return true;
                 }
             }
 
+            if (!subMesh._materialDefines) {
+                subMesh._materialDefines = new TriPlanarMaterialDefines();
+            }
+
+            var defines = <TriPlanarMaterialDefines>subMesh._materialDefines;
             var scene = this.getScene();
 
             if (!this.checkReadyOnEveryCall) {
                 if (this._renderId === scene.getRenderId()) {
-                    if (this._checkCache(scene, mesh, useInstances)) {
-                        return true;
-                    }
+                    return true;
                 }
             }
 
             var engine = scene.getEngine();
-            var needNormals = false;
-
-            this._defines.reset();
 
             // Textures
-            if (scene.texturesEnabled) {
-                if (StandardMaterial.DiffuseTextureEnabled) {
-                    var textures = [this.diffuseTextureX, this.diffuseTextureY, this.diffuseTextureZ];
-                    var textureDefines = ["DIFFUSEX", "DIFFUSEY", "DIFFUSEZ"];
-                    
-                    for (var i=0; i < textures.length; i++) {
-                        if (textures[i]) {
-                            if (!textures[i].isReady()) {
-                                return false;
-                            } else {
-                                this._defines[textureDefines[i]] = true;
+            if (defines._areTexturesDirty) {                
+                if (scene.texturesEnabled) {
+                    if (StandardMaterial.DiffuseTextureEnabled) {
+                        var textures = [this.diffuseTextureX, this.diffuseTextureY, this.diffuseTextureZ];
+                        var textureDefines = ["DIFFUSEX", "DIFFUSEY", "DIFFUSEZ"];
+                        
+                        for (var i=0; i < textures.length; i++) {
+                            if (textures[i]) {
+                                if (!textures[i].isReady()) {
+                                    return false;
+                                } else {
+                                    defines[textureDefines[i]] = true;
+                                }
                             }
                         }
                     }
-                }
-                if (StandardMaterial.BumpTextureEnabled) {
-                    var textures = [this.normalTextureX, this.normalTextureY, this.normalTextureZ];
-                    var textureDefines = ["BUMPX", "BUMPY", "BUMPZ"];
-                    
-                    for (var i=0; i < textures.length; i++) {
-                        if (textures[i]) {
-                            if (!textures[i].isReady()) {
-                                return false;
-                            } else {
-                                this._defines[textureDefines[i]] = true;
+                    if (StandardMaterial.BumpTextureEnabled) {
+                        var textures = [this.normalTextureX, this.normalTextureY, this.normalTextureZ];
+                        var textureDefines = ["BUMPX", "BUMPY", "BUMPZ"];
+                        
+                        for (var i=0; i < textures.length; i++) {
+                            if (textures[i]) {
+                                if (!textures[i].isReady()) {
+                                    return false;
+                                } else {
+                                    defines[textureDefines[i]] = true;
+                                }
                             }
                         }
                     }
                 }
             }
 
-            // Effect
-            if (scene.clipPlane) {
-                this._defines.CLIPPLANE = true;
-            }
-
-            if (engine.getAlphaTesting()) {
-                this._defines.ALPHATEST = 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;
-            }
+            // Misc.
+            MaterialHelper.PrepareDefinesForMisc(mesh, scene, false, this.pointsCloud, this.fogEnabled, defines);
 
             // Lights
-            if (scene.lightsEnabled && !this.disableLighting) {
-                needNormals = MaterialHelper.PrepareDefinesForLights(scene, mesh, this._defines, true, this.maxSimultaneousLights);
-            }
+            defines._needNormals = MaterialHelper.PrepareDefinesForLights(scene, mesh, defines, false, this._maxSimultaneousLights, this._disableLighting);
 
+            // Values that need to be evaluated on every frame
+            MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances);
+            
             // Attribs
-            if (mesh) {
-                if (needNormals && mesh.isVerticesDataPresent(VertexBuffer.NormalKind)) {
-                    this._defines.NORMAL = 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;
-                }
-            }
+            MaterialHelper.PrepareDefinesForAttributes(mesh, defines, true, true);
 
             // Get correct effect      
-            if (!this._defines.isEqual(this._cachedDefines)) {
-                this._defines.cloneTo(this._cachedDefines);
-
+            if (defines.isDirty) {
+                defines.markAsProcessed();
                 scene.resetCachedMaterial();
 
                 // Fallbacks
                 var fallbacks = new EffectFallbacks();             
-                if (this._defines.FOG) {
+                if (defines.FOG) {
                     fallbacks.addFallback(1, "FOG");
                 }
 
-                MaterialHelper.HandleFallbacksForShadows(this._defines, fallbacks, this.maxSimultaneousLights);
+                MaterialHelper.HandleFallbacksForShadows(defines, fallbacks, this.maxSimultaneousLights);
              
-                if (this._defines.NUM_BONE_INFLUENCERS > 0) {
+                if (defines.NUM_BONE_INFLUENCERS > 0) {
                     fallbacks.addCPUSkinningFallback(0, mesh);
                 }
 
                 //Attributes
                 var attribs = [VertexBuffer.PositionKind];
 
-                if (this._defines.NORMAL) {
+                if (defines.NORMAL) {
                     attribs.push(VertexBuffer.NormalKind);
                 }
 
-                if (this._defines.VERTEXCOLOR) {
+                if (defines.VERTEXCOLOR) {
                     attribs.push(VertexBuffer.ColorKind);
                 }
 
-                MaterialHelper.PrepareAttributesForBones(attribs, mesh, this._defines, fallbacks);
-                MaterialHelper.PrepareAttributesForInstances(attribs, this._defines);
+                MaterialHelper.PrepareAttributesForBones(attribs, mesh, defines, fallbacks);
+                MaterialHelper.PrepareAttributesForInstances(attribs, defines);
 
                 // Legacy browser patch
                 var shaderName = "triplanar";
-                var join = this._defines.toString();
+                var join = defines.toString();
                 var uniforms = ["world", "view", "viewProjection", "vEyePosition", "vLightsType", "vDiffuseColor", "vSpecularColor",
                     "vFogInfos", "vFogColor", "pointSize",
                     "mBones",
@@ -254,13 +216,13 @@ module BABYLON {
                     "normalSamplerX", "normalSamplerY", "normalSamplerZ"
                 ];
                 
-                MaterialHelper.PrepareUniformsAndSamplersList(uniforms, samplers, this._defines, this.maxSimultaneousLights);
+                MaterialHelper.PrepareUniformsAndSamplersList(uniforms, samplers, defines, this.maxSimultaneousLights);
                 
-                this._effect = scene.getEngine().createEffect(shaderName,
+                subMesh.setEffect(scene.getEngine().createEffect(shaderName,
                     attribs, uniforms, samplers,
-                    join, fallbacks, this.onCompiled, this.onError, { maxSimultaneousLights: this.maxSimultaneousLights });
+                    join, fallbacks, this.onCompiled, this.onError, { maxSimultaneousLights: this.maxSimultaneousLights }), defines);
             }
-            if (!this._effect.isReady()) {
+            if (!subMesh.effect.isReady()) {
                 return false;
             }
 
@@ -270,72 +232,76 @@ module BABYLON {
             return true;
         }
 
-        public bindOnlyWorldMatrix(world: Matrix): void {
-            this._effect.setMatrix("world", world);
-        }
-
-        public bind(world: Matrix, mesh?: Mesh): void {
+        public bindForSubMesh(world: Matrix, mesh: Mesh, subMesh: SubMesh): void {
             var scene = this.getScene();
 
+            var defines = <TriPlanarMaterialDefines>subMesh._materialDefines;
+            if (!defines) {
+                return;
+            }
+
+            var effect = subMesh.effect;
+            this._activeEffect = effect;
+
             // Matrices        
             this.bindOnlyWorldMatrix(world);
-            this._effect.setMatrix("viewProjection", scene.getTransformMatrix());
+            this._activeEffect.setMatrix("viewProjection", scene.getTransformMatrix());
 
             // Bones
-            MaterialHelper.BindBonesParameters(mesh, this._effect);
+            MaterialHelper.BindBonesParameters(mesh, this._activeEffect);
             
-            this._effect.setFloat("tileSize", this.tileSize);
+            this._activeEffect.setFloat("tileSize", this.tileSize);
 
             if (scene.getCachedMaterial() !== this) {
                 // Textures        
                 if (this.diffuseTextureX) {
-                    this._effect.setTexture("diffuseSamplerX", this.diffuseTextureX);
+                    this._activeEffect.setTexture("diffuseSamplerX", this.diffuseTextureX);
                 }
                 if (this.diffuseTextureY) {
-                    this._effect.setTexture("diffuseSamplerY", this.diffuseTextureY);
+                    this._activeEffect.setTexture("diffuseSamplerY", this.diffuseTextureY);
                 }
                 if (this.diffuseTextureZ) {
-                    this._effect.setTexture("diffuseSamplerZ", this.diffuseTextureZ);
+                    this._activeEffect.setTexture("diffuseSamplerZ", this.diffuseTextureZ);
                 }
                 if (this.normalTextureX) {
-                    this._effect.setTexture("normalSamplerX", this.normalTextureX);
+                    this._activeEffect.setTexture("normalSamplerX", this.normalTextureX);
                 }
                 if (this.normalTextureY) {
-                    this._effect.setTexture("normalSamplerY", this.normalTextureY);
+                    this._activeEffect.setTexture("normalSamplerY", this.normalTextureY);
                 }
                 if (this.normalTextureZ) {
-                    this._effect.setTexture("normalSamplerZ", this.normalTextureZ);
+                    this._activeEffect.setTexture("normalSamplerZ", this.normalTextureZ);
                 }
                 // Clip plane
-                MaterialHelper.BindClipPlane(this._effect, scene);
+                MaterialHelper.BindClipPlane(this._activeEffect, scene);
 
                 // Point size
                 if (this.pointsCloud) {
-                    this._effect.setFloat("pointSize", this.pointSize);
+                    this._activeEffect.setFloat("pointSize", this.pointSize);
                 }
 
-                this._effect.setVector3("vEyePosition", scene._mirroredCameraPosition ? scene._mirroredCameraPosition : scene.activeCamera.position);                
+                this._activeEffect.setVector3("vEyePosition", scene._mirroredCameraPosition ? scene._mirroredCameraPosition : scene.activeCamera.position);                
             }
 
-            this._effect.setColor4("vDiffuseColor", this.diffuseColor, this.alpha * mesh.visibility);
+            this._activeEffect.setColor4("vDiffuseColor", this.diffuseColor, this.alpha * mesh.visibility);
             
-            if (this._defines.SPECULARTERM) {
-                this._effect.setColor4("vSpecularColor", this.specularColor, this.specularPower);
+            if (defines.SPECULARTERM) {
+                this._activeEffect.setColor4("vSpecularColor", this.specularColor, this.specularPower);
             }
 
             if (scene.lightsEnabled && !this.disableLighting) {
-                MaterialHelper.BindLights(scene, mesh, this._effect, this._defines, this.maxSimultaneousLights);
+                MaterialHelper.BindLights(scene, mesh, this._activeEffect, defines, this.maxSimultaneousLights);
             }
 
             // View
             if (scene.fogEnabled && mesh.applyFog && scene.fogMode !== Scene.FOGMODE_NONE) {
-                this._effect.setMatrix("view", scene.getViewMatrix());
+                this._activeEffect.setMatrix("view", scene.getViewMatrix());
             }
 
             // Fog
-            MaterialHelper.BindFogParameters(scene, mesh, this._effect);
+            MaterialHelper.BindFogParameters(scene, mesh, this._activeEffect);
 
-            this._afterBind(mesh);
+            this._afterBind(mesh, this._activeEffect);
         }
 
         public getAnimatables(): IAnimatable[] {

BIN
sandbox/Assets/BtnDragdrop.png


BIN
sandbox/Assets/BtnFullscreen.png


BIN
sandbox/Assets/BtnPerf.png


BIN
sandbox/Assets/FlecheDown.png


BIN
sandbox/Assets/FlecheTuto.png


BIN
sandbox/Assets/Interface-Sandbox.jpg


BIN
sandbox/Assets/LogoSandbox.png


BIN
sandbox/Assets/WideLogo.png


BIN
sandbox/Assets/arrow.png


BIN
sandbox/Assets/down.png


BIN
sandbox/Assets/sep.png


BIN
sandbox/Assets/up.png


BIN
sandbox/Assets/video.png


+ 56 - 0
sandbox/index-local.html

@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>BabylonJS - Sandbox</title>
+    <link href="index.css" rel="stylesheet" />
+    <script src="https://babylonjs.azurewebsites.net/cannon.js"></script>
+    <script src="https://babylonjs.azurewebsites.net/Oimo.js"></script>
+	<script src="../Tools/DevLoader/BabylonLoader.js"></script>
+</head>
+<body>
+    <canvas id="renderCanvas"></canvas>
+    <div id="logo">
+    </div>
+    <div id="help01" class="help">
+        <span class="helpText">Press this button to open your assets' files</span>
+        <img id="helpArrow" src="./Assets/FlecheTuto.png" />
+    </div>
+    <div id="help02" class="help2">
+        <span class="helpText">Or directly drag'n'drop your files in the browser</span>
+    </div>
+    <div id="perf" class="perffooter">
+        <div class="footerLeft">
+            <div id="miscCounters"></div>
+        </div>
+        <div class="footerRight">
+            <div id="fps"></div>
+            <img id="btnDownArrow" src="./Assets/FlecheDown.png" />
+        </div>
+    </div>
+    <div class="footer">
+        <div class="footerLeft">
+            Powered by <a href="http://www.babylonjs.com/" target="_blank">Babylon.js</a><br />
+        </div>
+        <div class="footerRight">
+            <ul>
+                <li id="btnFullscreen">
+                    <img src="./Assets/BtnFullscreen.png" alt="Switch the scene to full screen" title="Switch the scene to full screen" />
+                </li>
+                <li id="btnPerf">
+                    <img src="./Assets/BtnPerf.png" alt="Display inspector" title="Display inspector" />
+                </li>
+                <li id="btnFiles">
+                    <div class="custom-upload" title="Open your .babylon scene from your hard drive">
+                        <input type="file" id="files" multiple />
+                    </div>
+                </li>
+            </ul>
+        </div>
+    </div>
+    <div id="loadingText" class="loadingText"></div>
+    <script>
+        BABYLONDEVTOOLS.Loader.require('index.js')
+            .load();
+    </script>	
+</body>
+</html>

+ 264 - 0
sandbox/index.css

@@ -0,0 +1,264 @@
+html, body {
+    width: 100%;
+    height: 100%;
+    padding: 0;
+    margin: 0;
+    overflow: hidden;
+    font-family: "Segoe WP", "Segoe UI", "Verdana", "Arial";
+}
+
+#DebugLayerLogs {
+    height: 100px !important;   
+}
+
+    #DebugLayerLogs > div:first-child {
+        background-color: #988DB5 !important;
+    }
+
+#DebugLayerStats {
+    margin-top: 2px !important;
+}
+
+#DebugLayerStats div:nth-child(2) {
+    max-height: 180px !important;
+}
+
+    #DebugLayerStats > div:first-child {
+        background-color: #988DB5 !important;
+    }
+
+#DebugLayerOptions {
+    overflow-y: hidden !important;
+}
+
+#DebugLayerOptions > div:first-child {
+    background-color: #988DB5 !important;
+}
+
+#DebugLayerTree > div:first-child {
+    background-color: #988DB5 !important;
+}
+
+a {
+    color: white;
+}
+
+    a:visited {
+        color: white;
+    }
+
+.hidden {
+    display: none;
+}
+
+#renderCanvas {
+    position: absolute;
+    width: 100%;
+    height: 100%;
+    top: 0;
+    margin-bottom: 70px;
+    touch-action: none;
+    -ms-touch-action: none;
+}
+
+.help {
+    position: absolute;
+    background-color: #988DB5;
+    right: 0;
+    bottom: 70px;
+    color: white;
+    padding-right: 10px;
+    width: 360px;
+    height: 30px;
+    transition: all 0.5s ease;
+    -webkit-transition: all 0.5s ease;
+    transform: translateX(400px);
+    -webkit-transform: translateX(400px);
+        text-align: center;
+}
+
+    .help.shown {
+        transform: translateX(-100px);
+        -webkit-transform: translateX(-100px);
+    }
+
+ .help2 {
+    position: absolute;
+    background-color: #988DB5;
+    right: 0;
+    bottom: 70px;
+    color: white;
+    padding-right: 10px;
+    width: 360px;
+    height: 30px;
+    transition: all 0.5s ease;
+    -webkit-transition: all 0.5s ease;
+    transform: translateX(400px);
+    -webkit-transform: translateX(400px);
+        text-align: center;
+}
+
+    .help2.shown {
+        transform: translateX(0px);
+        -webkit-transform: translateX(0px);
+    }
+
+#helpArrow {
+    position: absolute;
+    right: -65px;
+    bottom: 10px;
+}
+
+#fps {
+    position: absolute;
+    font-size: 30px;
+    color: white;
+    bottom: 15px;
+    right: 85px;
+    width: 85px;
+}
+
+.footer {
+    position: absolute;
+    width: 100%;
+    height: 60px;
+    bottom: 0;
+    background-color: #59448F;
+    padding-top: 5px;
+    padding-left: 15px;
+}
+
+.perffooter {
+    position: absolute;
+    width: 100%;
+    height: 60px;
+    bottom: 0px;
+    background-color: #988DB5;
+    padding-top: 5px;
+    padding-left: 15px;
+        transition: all 0.5s ease;
+    -webkit-transition: all 0.5s ease;
+}
+
+    .perffooter.shown {
+        transform: translateY(-65px);
+        -webkit-transform: translateY(-65px);
+    }
+
+.footerRight {
+    display: inline;
+    position: absolute;
+    bottom: 0;
+    right: 10px;
+}
+
+.footerLeft {
+    position: absolute;
+    bottom: 20px;
+    left: 15px;
+    color: white;
+}
+
+.custom-upload {
+    position: relative;
+    background:url(./Assets/BtnDragdrop.png) center right no-repeat;
+    height: 56px;
+    width: 56px;
+    margin: 10px 20px 5px 5px;
+}
+
+.custom-upload input[type=file]
+{
+    outline:none;
+    position: relative;
+    text-align: right;    
+    -moz-opacity:0 ;
+    filter:alpha(opacity: 0);
+    opacity: 0;
+    z-index: 2;
+    width:100%;
+    height:100%;
+    
+}
+
+#logo {
+    width: 100%;
+    height: 100%;
+    background: url('./Assets/LogoSandbox.png') no-repeat 0 0;
+    background-position: center;
+}
+
+#btnFullscreen {
+}
+
+#btnFullscreen {
+    margin-top: 10px;
+    margin-right: 25px;
+}
+
+#btnPerf {
+    margin-top: 10px;
+    margin-right: 15px;
+}
+
+ul {
+ padding:0;
+ margin:0;
+ list-style-type:none;
+ }
+
+li {
+ float:left;
+ }
+
+#btnDownArrow {
+    position: absolute;
+    bottom: 35px;
+    right: 30px;
+}
+
+#miscCounters {
+    position: relative;
+    top: 18px;
+    height: 60px;
+    -webkit-column-width: 150px;
+    -moz-column-width: 150px;
+    -ms-column-width: 150px;
+    -o-column-width: 150px;
+    column-width: 150px;
+
+    font-size: 14px;
+}
+
+#loadingText {
+    width: 100%;
+    height: 60px;
+    position: absolute;
+    top: 50%;
+    left: 0;
+    margin-top: -30px;
+    color: white;
+    text-align: center;
+    padding-top: 10px;
+    font-size: 30px;
+    transition: transform 0.25s ease-in-out;
+    -webkit-transition: -webkit-transform 0.25s ease-in-out;
+    z-index: 3;
+    cursor: default;
+    background-color: #988DB5;
+}
+
+.loadingText {
+    transform: translateX(120%);
+    -webkit-transform: translateX(120%);
+}
+
+#btnFullscreen, #btnPerf, #btnFiles {
+     -webkit-transition: -webkit-transform 0.15s ease-in-out;
+     transition: transform 0.15s ease-in-out;
+}
+
+#btnFullscreen:hover, #btnPerf:hover, #btnFiles:hover {
+    -webkit-transform: scale(0.9);
+    transform: scale(0.9);
+}

+ 49 - 0
sandbox/index.html

@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>BabylonJS - Sandbox</title>
+    <link href="index.css" rel="stylesheet" />
+    <script src="https://code.jquery.com/pep/0.4.2/pep.min.js"></script>
+
+    <script src="https://babylonjs.azurewebsites.net/cannon.js"></script>
+    <script src="https://babylonjs.azurewebsites.net/Oimo.js"></script>
+    <script src="https://babylonjs.azurewebsites.net/babylon.js"></script>
+    <script src="https://babylonjs.azurewebsites.net/lib/babylon.glTFFileLoader.js"></script>
+    <script src="https://babylonjs.azurewebsites.net/lib/babylon.objFileLoader.js"></script>
+    <script src="https://babylonjs.azurewebsites.net/lib/babylon.stlFileLoader.js"></script>    
+</head>
+<body>
+    <canvas id="renderCanvas"></canvas>
+    <div id="logo">
+    </div>
+    <div id="help01" class="help">
+        <span class="helpText">Press this button to open your assets' files</span>
+        <img id="helpArrow" src="./Assets/FlecheTuto.png" />
+    </div>
+    <div id="help02" class="help2">
+        <span class="helpText">Or directly drag'n'drop your files in the browser</span>
+    </div>
+    <div class="footer">
+        <div class="footerLeft">
+            Powered by <a href="http://www.babylonjs.com/" target="_blank">Babylon.js</a><br />
+        </div>
+        <div class="footerRight">
+            <ul>
+                <li id="btnFullscreen">
+                    <img src="./Assets/BtnFullscreen.png" alt="Switch the scene to full screen" title="Switch the scene to full screen" />
+                </li>
+                <li id="btnPerf">
+                    <img src="./Assets/BtnPerf.png" alt="Display debug & performance layer" title="Display debug & performance layer" />
+                </li>
+                <li id="btnFiles">
+                    <div class="custom-upload" title="Open your .babylon scene from your hard drive">
+                        <input type="file" id="files" multiple />
+                    </div>
+                </li>
+            </ul>
+        </div>
+    </div>
+    <div id="loadingText" class="loadingText"></div>
+    <script src="index.js"></script>
+</body>
+</html>

+ 115 - 0
sandbox/index.js

@@ -0,0 +1,115 @@
+/// <reference path="../../babylon.js" />
+
+if (BABYLON.Engine.isSupported()) {
+    var canvas = document.getElementById("renderCanvas");
+    var engine = new BABYLON.Engine(canvas, true);
+    var divFps = document.getElementById("fps");
+    var htmlInput = document.getElementById("files");
+    var btnFullScreen = document.getElementById("btnFullscreen");
+    var btnDownArrow = document.getElementById("btnDownArrow");
+    var perffooter = document.getElementById("perf");
+    var btnPerf = document.getElementById("btnPerf");
+    var miscCounters = document.getElementById("miscCounters");
+    var help01 = document.getElementById("help01");
+    var help02 = document.getElementById("help02");
+    var loadingText = document.getElementById("loadingText");
+    var filesInput;
+    var currentHelpCounter;
+    var currentScene;
+    var enableDebugLayer = false;
+
+    currentHelpCounter = localStorage.getItem("helpcounter");
+
+    BABYLON.Engine.ShadersRepository = "/src/Shaders/";
+
+    if (!currentHelpCounter) currentHelpCounter = 0;
+
+    // Resize
+    window.addEventListener("resize", function () {
+        engine.resize();
+    });
+
+    var sceneLoaded = function (sceneFile, babylonScene) {
+        function displayDebugLayerAndLogs() {
+            currentScene.debugLayer._displayLogs = true;
+            enableDebugLayer = true;
+            currentScene.debugLayer.show();
+        };
+        function hideDebugLayerAndLogs() {
+            currentScene.debugLayer._displayLogs = false;
+            enableDebugLayer = false;
+            currentScene.debugLayer.hide();
+        };
+        if (enableDebugLayer) {
+            hideDebugLayerAndLogs();
+        }
+        currentScene = babylonScene;
+        document.title = "BabylonJS - " + sceneFile.name;
+        // Fix for IE, otherwise it will change the default filter for files selection after first use
+        htmlInput.value = "";
+        // In case of error during loading, meshes will be empty and clearColor is set to red
+        if (currentScene.meshes.length === 0 && currentScene.clearColor.r === 1 && currentScene.clearColor.g === 0 && currentScene.clearColor.b === 0) {
+            document.getElementById("logo").className = "";
+            canvas.style.opacity = 0;
+            displayDebugLayerAndLogs();
+        }
+        else {
+            if (BABYLON.Tools.errorsCount > 0) {
+                displayDebugLayerAndLogs();
+            }
+            document.getElementById("logo").className = "hidden";
+            canvas.style.opacity = 1;
+            if (currentScene.activeCamera.keysUp) {
+                currentScene.activeCamera.keysUp.push(90); // Z
+                currentScene.activeCamera.keysUp.push(87); // W
+                currentScene.activeCamera.keysDown.push(83); // S
+                currentScene.activeCamera.keysLeft.push(65); // A
+                currentScene.activeCamera.keysLeft.push(81); // Q
+                currentScene.activeCamera.keysRight.push(69); // E
+                currentScene.activeCamera.keysRight.push(68); // D
+            }
+        }
+    };
+
+    filesInput = new BABYLON.FilesInput(engine, null, canvas, sceneLoaded);
+    filesInput.monitorElementForDragNDrop(canvas);
+
+    window.addEventListener("keydown", function (evt) {
+        // Press R to reload
+        if (evt.keyCode === 82) {
+            filesInput.reload();
+        }
+    });
+    htmlInput.addEventListener('change', function (event) {
+        filesInput.loadFiles(event);
+    }, false);
+    btnFullScreen.addEventListener('click', function () {
+        engine.switchFullscreen(true);
+    }, false);
+    btnPerf.addEventListener('click', function () {
+        if (currentScene) {
+            if (!enableDebugLayer) {
+                currentScene.debugLayer.show();
+                enableDebugLayer = true;
+
+            } else {
+                currentScene.debugLayer.hide();
+                enableDebugLayer = false;
+            }
+        }
+    }, false);
+
+    // The help tips will be displayed only 5 times
+    if (currentHelpCounter < 5) {
+        help01.className = "help shown";
+
+        setTimeout(function () {
+            help01.className = "help";
+            help02.className = "help2 shown";
+            setTimeout(function () {
+                help02.className = "help2";
+                localStorage.setItem("helpcounter", currentHelpCounter + 1);
+            }, 5000);
+        }, 5000);
+    }
+}

src/Cameras/Inputs/babylon.arcrotatecamera.input.gamepad.ts → src/Cameras/Inputs/babylon.arcRotateCameraGamepadInput.ts


src/Cameras/Inputs/babylon.arcrotatecamera.input.keyboard.ts → src/Cameras/Inputs/babylon.arcRotateCameraKeyboardMoveInput.ts


src/Cameras/Inputs/babylon.arcrotatecamera.input.mousewheel.ts → src/Cameras/Inputs/babylon.arcRotateCameraMouseWheelInput.ts


src/Cameras/Inputs/babylon.arcrotatecamera.input.pointers.ts → src/Cameras/Inputs/babylon.arcRotateCameraPointersInput.ts


src/Cameras/Inputs/babylon.arcrotatecamera.input.vrdeviceorientation.ts → src/Cameras/Inputs/babylon.arcRotateCameraVRDeviceOrientationInput.ts


src/Cameras/Inputs/babylon.freecamera.input.deviceorientation.ts → src/Cameras/Inputs/babylon.freeCameraDeviceOrientationInput.ts


src/Cameras/Inputs/babylon.freecamera.input.gamepad.ts → src/Cameras/Inputs/babylon.freeCameraGamepadInput.ts


src/Cameras/Inputs/babylon.freecamera.input.keyboard.ts → src/Cameras/Inputs/babylon.freeCameraKeyboardMoveInput.ts


src/Cameras/Inputs/babylon.freecamera.input.mouse.ts → src/Cameras/Inputs/babylon.freeCameraMouseInput.ts


src/Cameras/Inputs/babylon.freecamera.input.touch.ts → src/Cameras/Inputs/babylon.freeCameraTouchInput.ts


src/Cameras/Inputs/babylon.freecamera.input.virtualjoystick.ts → src/Cameras/Inputs/babylon.freeCameraVirtualJoystickInput.ts


+ 5 - 12
src/Tools/babylon.filesInput.ts

@@ -9,7 +9,6 @@
         private _textureLoadingCallback;
         private _startingProcessingFilesCallback;
         private _elementToMonitor: HTMLElement;
-        public static FilesTextures: File[] = new Array();
         public static FilesToLoad: File[] = new Array();
 
         private _sceneFileToLoad: File;
@@ -86,18 +85,12 @@
                     let extension = name.split('.').pop();
                     let type = this._filesToLoad[i].type;
                     
-                    if (extension === "jpg" || extension === "png" || extension === "bmp" || extension === "jpeg" || 
-                        type === "image/jpeg" || type === "image/png" || type === "image/bmp") {
-                           FilesInput.FilesTextures[name] = this._filesToLoad[i]; 
-                        }
+                    if ((extension === "babylon" || extension === "stl" || extension === "obj" || extension === "gltf" || extension === "glb") 
+                        && name.indexOf(".binary.babylon") === -1 && name.indexOf(".incremental.babylon") === -1) {
+                        this._sceneFileToLoad = this._filesToLoad[i];
+                    }
                     else {
-                        if ((extension === "babylon" || extension === "stl" || extension === "obj") 
-                            && name.indexOf(".binary.babylon") === -1 && name.indexOf(".incremental.babylon") === -1) {
-                            this._sceneFileToLoad = this._filesToLoad[i];
-                        }
-                        else {
-                            FilesInput.FilesToLoad[name] = this._filesToLoad[i];
-                        }
+                        FilesInput.FilesToLoad[name] = this._filesToLoad[i];
                     }
                 }
 

+ 3 - 3
src/Tools/babylon.tools.ts

@@ -368,15 +368,15 @@
                 }
                 else {
                     var textureName = url.substring(5).toLowerCase();
-                    if (FilesInput.FilesTextures[textureName]) {
+                    if (FilesInput.FilesToLoad[textureName]) {
                         try {
                             var blobURL;
                             try {
-                                blobURL = URL.createObjectURL(FilesInput.FilesTextures[textureName], { oneTimeOnly: true });
+                                blobURL = URL.createObjectURL(FilesInput.FilesToLoad[textureName], { oneTimeOnly: true });
                             }
                             catch (ex) {
                                 // Chrome doesn't support oneTimeOnly parameter
-                                blobURL = URL.createObjectURL(FilesInput.FilesTextures[textureName]);
+                                blobURL = URL.createObjectURL(FilesInput.FilesToLoad[textureName]);
                             }
                             img.src = blobURL;
                         }