Bladeren bron

merged with upstream

Benjamin Guignabert 8 jaren geleden
bovenliggende
commit
e63abf4409
100 gewijzigde bestanden met toevoegingen van 100733 en 6348 verwijderingen
  1. 12 0
      .vscode/launch.json
  2. 1 0
      .vscode/settings.json
  3. 4 0
      Exporters/3ds Max/BabylonExport.Entities/BabylonPBRMaterial.cs
  4. 17 0
      Exporters/Maya/Tools/babylonReskinTool.mel
  5. 23 0
      Playground/debug.html
  6. 23 0
      Playground/index-local.html
  7. 64 0
      Playground/index.css
  8. 23 1
      Playground/index.html
  9. 116 10
      Playground/index.js
  10. 23 0
      Playground/index2_5.html
  11. 1 1
      Playground/package.json
  12. 21 21
      Tools/Gulp/config.json
  13. 187 184
      Tools/Gulp/custom.config.json
  14. 240 0
      Tools/Gulp/profiling.html
  15. 12512 0
      Tools/Npm/Oimo.js
  16. 20676 0
      Tools/Npm/babylon.canvas2d.js
  17. 31 0
      Tools/Npm/babylon.core.js
  18. 43 0
      Tools/Npm/babylon.js
  19. 61376 0
      Tools/Npm/babylon.max.js
  20. 41 0
      Tools/Npm/babylon.noworker.js
  21. 1 0
      Tools/Npm/getfiles.bat
  22. 2 1
      Tools/Npm/package.json
  23. 0 2
      dist/poly2tri.js
  24. 25 25
      dist/preview release/babylon.core.js
  25. 1346 1398
      dist/preview release/babylon.d.ts
  26. 35 35
      dist/preview release/babylon.js
  27. 562 534
      dist/preview release/babylon.max.js
  28. 1346 1398
      dist/preview release/babylon.module.d.ts
  29. 35 35
      dist/preview release/babylon.noworker.js
  30. 4 4
      dist/preview release/inspector/babylon.inspector.bundle.js
  31. 2 2
      dist/preview release/inspector/babylon.inspector.css
  32. 1 1
      dist/preview release/inspector/babylon.inspector.js
  33. 3 3
      dist/preview release/inspector/babylon.inspector.min.js
  34. 6 7
      dist/preview release/materialsLibrary/babylon.fireMaterial.d.ts
  35. 97 124
      dist/preview release/materialsLibrary/babylon.fireMaterial.js
  36. 1 1
      dist/preview release/materialsLibrary/babylon.fireMaterial.min.js
  37. 8 8
      dist/preview release/materialsLibrary/babylon.furMaterial.d.ts
  38. 105 140
      dist/preview release/materialsLibrary/babylon.furMaterial.js
  39. 1 1
      dist/preview release/materialsLibrary/babylon.furMaterial.min.js
  40. 5 7
      dist/preview release/materialsLibrary/babylon.gradientMaterial.d.ts
  41. 60 107
      dist/preview release/materialsLibrary/babylon.gradientMaterial.js
  42. 1 1
      dist/preview release/materialsLibrary/babylon.gradientMaterial.min.js
  43. 3 7
      dist/preview release/materialsLibrary/babylon.gridMaterial.d.ts
  44. 38 50
      dist/preview release/materialsLibrary/babylon.gridMaterial.js
  45. 1 1
      dist/preview release/materialsLibrary/babylon.gridMaterial.min.js
  46. 6 7
      dist/preview release/materialsLibrary/babylon.lavaMaterial.d.ts
  47. 88 123
      dist/preview release/materialsLibrary/babylon.lavaMaterial.js
  48. 1 1
      dist/preview release/materialsLibrary/babylon.lavaMaterial.min.js
  49. 7 7
      dist/preview release/materialsLibrary/babylon.normalMaterial.d.ts
  50. 84 117
      dist/preview release/materialsLibrary/babylon.normalMaterial.js
  51. 1 1
      dist/preview release/materialsLibrary/babylon.normalMaterial.min.js
  52. 3 7
      dist/preview release/materialsLibrary/babylon.shadowOnlyMaterial.d.ts
  53. 42 75
      dist/preview release/materialsLibrary/babylon.shadowOnlyMaterial.js
  54. 1 1
      dist/preview release/materialsLibrary/babylon.shadowOnlyMaterial.min.js
  55. 6 7
      dist/preview release/materialsLibrary/babylon.simpleMaterial.d.ts
  56. 83 119
      dist/preview release/materialsLibrary/babylon.simpleMaterial.js
  57. 1 1
      dist/preview release/materialsLibrary/babylon.simpleMaterial.min.js
  58. 3 7
      dist/preview release/materialsLibrary/babylon.skyMaterial.d.ts
  59. 41 64
      dist/preview release/materialsLibrary/babylon.skyMaterial.js
  60. 1 1
      dist/preview release/materialsLibrary/babylon.skyMaterial.min.js
  61. 12 7
      dist/preview release/materialsLibrary/babylon.terrainMaterial.d.ts
  62. 112 135
      dist/preview release/materialsLibrary/babylon.terrainMaterial.js
  63. 1 1
      dist/preview release/materialsLibrary/babylon.terrainMaterial.min.js
  64. 17 13
      dist/preview release/materialsLibrary/babylon.triPlanarMaterial.d.ts
  65. 112 127
      dist/preview release/materialsLibrary/babylon.triPlanarMaterial.js
  66. 1 1
      dist/preview release/materialsLibrary/babylon.triPlanarMaterial.min.js
  67. 9 7
      dist/preview release/materialsLibrary/babylon.waterMaterial.d.ts
  68. 119 148
      dist/preview release/materialsLibrary/babylon.waterMaterial.js
  69. 1 1
      dist/preview release/materialsLibrary/babylon.waterMaterial.min.js
  70. 1 1
      index.html
  71. 1 1
      inspector/sass/defines.scss
  72. 1 1
      inspector/src/Inspector.ts
  73. 5 0
      localDev/src/index.js
  74. 2 0
      materialsLibrary/index.html
  75. 5 11
      materialsLibrary/src/fire/babylon.fireMaterial.ts
  76. 108 156
      materialsLibrary/src/fur/babylon.furMaterial.ts
  77. 5 0
      materialsLibrary/src/fur/fur.fragment.fx
  78. 6 2
      materialsLibrary/src/fur/fur.vertex.fx
  79. 61 122
      materialsLibrary/src/gradient/babylon.gradientMaterial.ts
  80. 37 53
      materialsLibrary/src/grid/babylon.gridmaterial.ts
  81. 89 137
      materialsLibrary/src/lava/babylon.lavaMaterial.ts
  82. 86 131
      materialsLibrary/src/normal/babylon.normalMaterial.ts
  83. 46 85
      materialsLibrary/src/shadowOnly/babylon.shadowOnlyMaterial.ts
  84. 6 16
      materialsLibrary/src/simple/babylon.simpleMaterial.ts
  85. 45 72
      materialsLibrary/src/sky/babylon.skyMaterial.ts
  86. 115 156
      materialsLibrary/src/terrain/babylon.terrainMaterial.ts
  87. 116 150
      materialsLibrary/src/triPlanar/babylon.triPlanarMaterial.ts
  88. 124 167
      materialsLibrary/src/water/babylon.waterMaterial.ts
  89. BIN
      sandbox/Assets/BtnDragdrop.png
  90. BIN
      sandbox/Assets/BtnFullscreen.png
  91. BIN
      sandbox/Assets/BtnPerf.png
  92. BIN
      sandbox/Assets/FlecheDown.png
  93. BIN
      sandbox/Assets/FlecheTuto.png
  94. BIN
      sandbox/Assets/Interface-Sandbox.jpg
  95. BIN
      sandbox/Assets/LogoSandbox.png
  96. BIN
      sandbox/Assets/WideLogo.png
  97. BIN
      sandbox/Assets/arrow.png
  98. BIN
      sandbox/Assets/down.png
  99. BIN
      sandbox/Assets/sep.png
  100. 0 0
      sandbox/Assets/up.png

+ 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,

+ 4 - 0
Exporters/3ds Max/BabylonExport.Entities/BabylonPBRMaterial.cs

@@ -169,6 +169,9 @@ namespace BabylonExport.Entities
         [DataMember]
         public bool disableLighting { get; set; }
 
+        [DataMember]
+        public bool twoSidedLighting { get; set; }
+
         public BabylonPBRMaterial() : base()
         {
             customType = "BABYLON.PBRMaterial";
@@ -180,6 +183,7 @@ namespace BabylonExport.Entities
             cameraExposure = 1.0f;
             cameraContrast = 1.0f;
             indexOfRefraction = 0.66f;
+            twoSidedLighting = false;
             useRadianceOverAlpha = true;
             useSpecularOverAlpha = true;
             usePhysicalLightFalloff = true;

+ 17 - 0
Exporters/Maya/Tools/babylonReskinTool.mel

@@ -3,9 +3,25 @@ global proc reskinSelectedMeshes() {
     $selected = size($selection);
     if ($selected > 0) {
         $skinName = `textFieldGrp -q -text myReskinName`;
+        $copyName = `textFieldGrp -q -text myUvsetName`;
         $regenerate = `radioButtonGrp -q -select myReskinGenerate`;
         $influencers = `intSliderGrp -q -value myReskinInfluencers`;
         if ($skinName != "") {
+            if ($copyName != "") {
+                for ($i = 0; $i < $selected; $i++) {
+                    string $selectedObject = $selection[$i];
+                    select $selectedObject;
+                    string $uvSets[] = `polyUVSet -q -allUVSets`;
+                    int $uvSize = `size($uvSets)`;
+                    if ($uvSize > 0) {
+                        string $defaultSet = $uvSets[0];
+                        if ($defaultSet != $copyName) {
+                            polyUVSet -copy -uvSet $defaultSet -nuv $copyName;
+                        }
+                    }
+                }
+                select $selection;
+            }
             $textField_exists = `objExists $skinName`;
             if ($textField_exists == 0) {
                 waitCursor -state 1;
@@ -46,6 +62,7 @@ global proc babylonReskinTool() {
     columnLayout -adjustableColumn true;
     textFieldGrp -label "Skin Name" -text "" myReskinName;
     intSliderGrp -label "Max Influencers" -field true -minValue 1 -maxValue 4 -fieldMinValue 1 -fieldMaxValue 4 -value 4 myReskinInfluencers;
+    textFieldGrp -label "Copy Set Name" -text "" myUvsetName;
     radioButtonGrp -label "UV Map Generation" -numberOfRadioButtons 3 -labelArray3 "No Merge" "Same Name" "Set Links" -select 2 myReskinGenerate;
     button -label "Reskin Selected Meshes" -command "reskinSelectedMeshes()" myReskinButton; 
     showWindow $window;

+ 23 - 0
Playground/debug.html

@@ -82,6 +82,7 @@
                 <label class="btn btn-sm active">
                     <input type="checkbox" autocomplete="off" id='safemodeToggle' style="margin-top:-0.1em;margin-right:4px">Safe Mode
                 </label>
+                <button class="btn btn-sm" id="metadataButton">+Meta data</button>
                 <button class="btn btn-sm" id="editorButton">-Editor</button>
                 <button class="btn btn-sm" id="debugButton">+Debug layer</button>
             </div>
@@ -95,6 +96,9 @@
                 </a>
                 <ul class="dropdown-menu" id="scriptsList"></ul>
             </div>
+            <div class="save-message" id="saveMessage">
+                This PG has no metadata. Click save to add them.
+            </div>
         </div>
     </div>
 
@@ -121,10 +125,29 @@
                 <li><a href="https://babylonjs.azurewebsites.net/sandbox">Sandbox</a></li>
                 <li><a href="https://github.com/BabylonJS/Babylon.js/wiki">Wiki</a></li>
                 <li><a href="https://doc.babylonjs.com">Documentation</a></li>
+                <li><a href="https://doc.babylonjs.com/playground">Playground Search</a></li>
             </ul>
         </div>
     </div>
 
+    <div id="saveLayer" class="save-layer">
+        <div class="save-form">
+            <label for="saveFormTitle">TITLE</label>
+            <div class="separator"></div>
+            <input type="text" maxlength="120" id="saveFormTitle" class="save-form-title">
+            <label for="saveFormDescription">DESCRIPTION</label>
+            <div class="separator"></div>
+            <textarea id="saveFormDescription" rows="4" cols="10"></textarea>
+            <label for="saveFormTags">TAGS (separated by comma)</label>
+            <div class="separator"></div>
+            <textarea id="saveFormTags" rows="4" cols="10"></textarea>
+            <div class="save-form-buttons" id="saveFormButtons">
+                <button class="btn save-form-button" id="saveFormButtonOk">OK</button>
+                <button class="btn save-form-button" id="saveFormButtonCancel">Cancel</button>
+            </div>
+        </div>
+    </div>
+
     <script src="https://code.jquery.com/jquery.js"></script>
     <script src="bootstrap/js/bootstrap.js"></script>
     <script src="index.js"></script>

+ 23 - 0
Playground/index-local.html

@@ -51,6 +51,7 @@
                 <label class="btn btn-sm active">
                     <input type="checkbox" autocomplete="off" id='safemodeToggle' style="margin-top:-0.1em;margin-right:4px">Safe Mode
                 </label>
+                <button class="btn btn-sm" id="metadataButton">+Meta data</button>
                 <button class="btn btn-sm" id="editorButton">-Editor</button>
                 <button class="btn btn-sm" id="debugButton">+Debug layer</button>
             </div>
@@ -65,6 +66,9 @@
                 <ul class="dropdown-menu" id="scriptsList"></ul>
             </div>
         </div>
+        <div class="save-message" id="saveMessage">
+            This PG has no metadata. Click save to add them.
+        </div>
     </div>
 
     <x-splitbox>
@@ -90,10 +94,29 @@
                 <li><a href="http://www.babylonjs.com/sandbox">Sandbox</a></li>
                 <li><a href="https://github.com/BabylonJS/Babylon.js/wiki">Wiki</a></li>
                 <li><a href="https://doc.babylonjs.com">Documentation</a></li>
+                <li><a href="https://doc.babylonjs.com/playground">Playground Search</a></li>
             </ul>
         </div>
     </div>
 
+    <div id="saveLayer" class="save-layer">
+        <div class="save-form">
+            <label for="saveFormTitle">TITLE</label>
+            <div class="separator"></div>
+            <input type="text" maxlength="120" id="saveFormTitle" class="save-form-title">
+            <label for="saveFormDescription">DESCRIPTION</label>
+            <div class="separator"></div>
+            <textarea id="saveFormDescription" rows="4" cols="10"></textarea>
+            <label for="saveFormTags">TAGS (separated by comma)</label>
+            <div class="separator"></div>
+            <textarea id="saveFormTags" rows="4" cols="10"></textarea>
+            <div class="save-form-buttons" id="saveFormButtons">
+                <button class="btn save-form-button" id="saveFormButtonOk">OK</button>
+                <button class="btn save-form-button" id="saveFormButtonCancel">Cancel</button>
+            </div>
+        </div>
+    </div>
+
     <script src="http://code.jquery.com/jquery.js"></script>
     <script src="bootstrap/js/bootstrap.min.js"></script>
     <script>

+ 64 - 0
Playground/index.css

@@ -122,3 +122,67 @@ ul#scriptsList {
 .monaco-editor .invisible {
     visibility: visible;
 }
+
+
+/* Save form & co */
+
+.save-message {
+    display: none;
+    float: left;
+    width: 100%;
+    background-color: rgba(0,0,0,.5);
+    text-align: center;
+    color: white;
+    font-size: 1.1em;
+    line-height: 2em;
+}
+
+.save-layer {
+    display: none;
+    position: absolute;
+    top: 0;
+    left: 0;
+
+    width: 100%;
+    height: 100%;
+
+    background-color: rgba(120,120,120,.5);
+    text-align: center;
+}
+.save-layer .save-form {
+    position: absolute;
+    top: 150px;
+    left: calc(50% - 205px);
+
+    width: 410px;
+    height: 390px;
+    padding-top: 15px;
+    -webkit-border-radius: 6px;
+    -moz-border-radius: 6px;
+    border-radius: 6px;
+
+    background-color: rgba(27,27,27,0.75);/*#1b1b1b;*/
+    background-image: -moz-linear-gradient(top,rgba(34,34,34,.75),rgba(17,17,17,.75));
+    background-image: -webkit-gradient(linear,0 0,0 100%,from(rgba(34,34,34,.75)),to(rgba(17,17,17,.75)));
+    background-image: -webkit-linear-gradient(top,rgba(34,34,34,.75),rgba(17,17,17,.75));
+    background-image: -o-linear-gradient(top,rgba(34,34,34,.75),rgba(17,17,17,.75));
+    background-image: linear-gradient(to bottom,rgba(34,34,34,.75),rgba(17,17,17,.75));
+    background-repeat: repeat-x;
+    border-color: #252525;
+    color: white;
+    font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
+    font-size: 14px;
+}
+.save-layer .save-form .separator {
+    width: 350px;
+    border-bottom: 1px solid #999;
+    margin: auto;
+    margin-top: -6px;
+    margin-bottom: 10px;
+}
+.save-layer .save-form .save-form-buttons {
+    margin-top: 10px;
+}
+.save-layer .save-form input, .save-layer .save-form textarea {
+    width: 350px;
+}

+ 23 - 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>
@@ -93,6 +92,7 @@
                 <label class="btn btn-sm active">
                     <input type="checkbox" autocomplete="off" id='safemodeToggle' style="margin-top:-0.1em;margin-right:4px">Safe Mode
                 </label>
+                <button class="btn btn-sm" id="metadataButton">+Meta data</button>
                 <button class="btn btn-sm" id="editorButton">-Editor</button>
                 <button class="btn btn-sm" id="debugButton">+Debug layer</button>
             </div>
@@ -107,6 +107,9 @@
                 <ul class="dropdown-menu" id="scriptsList"></ul>
             </div>
         </div>
+        <div class="save-message" id="saveMessage">
+            This PG has no metadata. Click save to add them.
+        </div>
     </div>
 
     <x-splitbox>
@@ -132,10 +135,29 @@
                 <li><a href="https://babylonjs.azurewebsites.net/sandbox">Sandbox</a></li>
                 <li><a href="https://github.com/BabylonJS/Babylon.js/wiki">Wiki</a></li>
                 <li><a href="https://doc.babylonjs.com">Documentation</a></li>
+                <li><a href="https://doc.babylonjs.com/playground">Playground Search</a></li>
             </ul>
         </div>
     </div>
 
+    <div id="saveLayer" class="save-layer">
+        <div class="save-form">
+            <label for="saveFormTitle">TITLE</label>
+            <div class="separator"></div>
+            <input type="text" maxlength="120" id="saveFormTitle" class="save-form-title">
+            <label for="saveFormDescription">DESCRIPTION</label>
+            <div class="separator"></div>
+            <textarea id="saveFormDescription" rows="4" cols="10"></textarea>
+            <label for="saveFormTags">TAGS (separated by comma)</label>
+            <div class="separator"></div>
+            <textarea id="saveFormTags" rows="4" cols="10"></textarea>
+            <div class="save-form-buttons" id="saveFormButtons">
+                <button class="btn save-form-button" id="saveFormButtonOk">OK</button>
+                <button class="btn save-form-button" id="saveFormButtonCancel">Cancel</button>
+            </div>
+        </div>
+    </div>
+
     <script src="https://code.jquery.com/jquery.js"></script>
     <script src="bootstrap/js/bootstrap.min.js"></script>
     <script src="index.js"></script>

File diff suppressed because it is too large
+ 116 - 10
Playground/index.js


+ 23 - 0
Playground/index2_5.html

@@ -90,6 +90,7 @@
                 <label class="btn btn-sm active">
                     <input type="checkbox" autocomplete="off" id='safemodeToggle' style="margin-top:-0.1em;margin-right:4px">Safe Mode
                 </label>
+                <button class="btn btn-sm" id="metadataButton">+Meta data</button>
                 <button class="btn btn-sm" id="editorButton">-Editor</button>
                 <button class="btn btn-sm" id="debugButton">+Debug layer</button>
             </div>
@@ -103,6 +104,9 @@
                 </a>
                 <ul class="dropdown-menu" id="scriptsList"></ul>
             </div>
+            <div class="save-message" id="saveMessage">
+                Be the first to fill this playground metadata!
+            </div>
         </div>
     </div>
 
@@ -129,10 +133,29 @@
                 <li><a href="https://babylonjs.azurewebsites.net/sandbox">Sandbox</a></li>
                 <li><a href="https://github.com/BabylonJS/Babylon.js/wiki">Wiki</a></li>
                 <li><a href="https://doc.babylonjs.com">Documentation</a></li>
+                <li><a href="https://doc.babylonjs.com/playground">Playground Search</a></li>
             </ul>
         </div>
     </div>
 
+    <div id="saveLayer" class="save-layer">
+        <div class="save-form">
+            <label for="saveFormTitle">TITLE</label>
+            <div class="separator"></div>
+            <input type="text" maxlength="120" id="saveFormTitle" class="save-form-title">
+            <label for="saveFormDescription">DESCRIPTION</label>
+            <div class="separator"></div>
+            <textarea id="saveFormDescription" rows="4" cols="10"></textarea>
+            <label for="saveFormTags">TAGS (separated by comma)</label>
+            <div class="separator"></div>
+            <textarea id="saveFormTags" rows="4" cols="10"></textarea>
+            <div class="save-form-buttons" id="saveFormButtons">
+                <button class="btn save-form-button" id="saveFormButtonOk">OK</button>
+                <button class="btn save-form-button" id="saveFormButtonCancel">Cancel</button>
+            </div>
+        </div>
+    </div>
+
     <script src="https://code.jquery.com/jquery.js"></script>
     <script src="bootstrap/js/bootstrap.min.js"></script>
     <script src="index.js"></script>

+ 1 - 1
Playground/package.json

@@ -4,7 +4,7 @@
   "description": "Babylon.js is a 3D engine based on webgl and javascript",
   "main": "",
   "repository": { "url": "https://github.com/BabylonJS/Babylon.js/" },
-  "readme": "https://github.com/BabylonJS/Babylon.js/edit/master/readme.md",
+  "readme": "https://github.com/BabylonJS/Babylon.js/blob/master/readme.md",
   "license": "(Apache-2.0)",
   "devDependencies": {
     "monaco-editor": "^0.7.0"

+ 21 - 21
Tools/Gulp/config.json

@@ -20,13 +20,14 @@
             "../../src/Tools/babylon.decorators.js",
             "../../src/Tools/babylon.observable.js",
             "../../src/Tools/babylon.database.js",
-            "../../src/Tools/babylon.tools.tga.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",
@@ -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",
@@ -106,7 +110,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",
@@ -117,8 +120,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",
@@ -128,7 +129,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",
@@ -165,7 +165,7 @@
             "../../src/Tools/babylon.dynamicFloatArray.js",
             "../../src/Materials/Textures/babylon.mapTexture.js",
             "../../src/Materials/babylon.shaderMaterial.js",
-            "../../src/Tools/babylon.tools.dds.js",
+            "../../src/Tools/babylon.dds.js",
             "../../src/Tools/babylon.khronosTextureContainer.js",
             "../../src/Physics/Plugins/babylon.cannonJSPlugin.js",
             "../../src/Physics/Plugins/babylon.oimoJSPlugin.js",
@@ -177,7 +177,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",
@@ -217,10 +217,10 @@
             "../../src/Probes/babylon.reflectionProbe.js",
             "../../src/Particles/babylon.solidParticle.js",
             "../../src/Particles/babylon.solidParticleSystem.js",
-            "../../src/Tools/HDR/babylon.tools.cubemapToSphericalPolynomial.js",
-            "../../src/Tools/HDR/babylon.tools.panoramaToCubemap.js",
-            "../../src/Tools/HDR/babylon.tools.hdr.js",
-            "../../src/Tools/HDR/babylon.tools.pmremgenerator.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",

+ 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.tools.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.tools.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.tools.cubemapToSphericalPolynomial.js",
-      "../../src/Tools/HDR/babylon.tools.panoramaToCubemap.js",
-      "../../src/Tools/HDR/babylon.tools.hdr.js",
-      "../../src/Tools/HDR/babylon.tools.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
+ 12512 - 0
Tools/Npm/Oimo.js


File diff suppressed because it is too large
+ 20676 - 0
Tools/Npm/babylon.canvas2d.js


File diff suppressed because it is too large
+ 31 - 0
Tools/Npm/babylon.core.js


File diff suppressed because it is too large
+ 43 - 0
Tools/Npm/babylon.js


File diff suppressed because it is too large
+ 61376 - 0
Tools/Npm/babylon.max.js


File diff suppressed because it is too large
+ 41 - 0
Tools/Npm/babylon.noworker.js


+ 1 - 0
Tools/Npm/getfiles.bat

@@ -5,5 +5,6 @@ xcopy /Y /F "../../dist/preview release/babylon.max.js"  .
 xcopy /Y /F "../../dist/preview release/babylon.noworker.js" . 
 xcopy /Y /F "../../dist/preview release/babylon.core.js" . 
 xcopy /Y /F "../../dist/preview release/canvas2D/babylon.canvas2d.js" . 
+xcopy /Y /F "../../dist/preview release/canvas2D/babylon.canvas2d.d.ts" . 
 xcopy /Y /F "../../dist/preview release/oimo.js" . 
 pause

+ 2 - 1
Tools/Npm/package.json

@@ -7,7 +7,7 @@
   ],
   "name": "babylonjs",
   "description": "Babylon.js is a JavaScript 3D engine based on webgl.",
-  "version": "2.5.0",
+  "version": "3.0.0-alpha",
   "repository": {
     "type": "git",
     "url": "https://github.com/BabylonJS/Babylon.js.git"
@@ -21,6 +21,7 @@
     "babylon.noworker.js",
     "babylon.core.js",
     "babylon.canvas2d.js",
+    "babylon.canvas2d.d.ts",
     "Oimo.js",
     "package.json"
   ],

File diff suppressed because it is too large
+ 0 - 2
dist/poly2tri.js


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


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


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


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


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


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


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


+ 2 - 2
dist/preview release/inspector/babylon.inspector.css

@@ -1,8 +1,8 @@
 @import url(https://maxcdn.bootstrapcdn.com/font-awesome/4.6.3/css/font-awesome.min.css);
-@import url(http://fonts.googleapis.com/css?family=Inconsolata);
+@import url(https://fonts.googleapis.com/css?family=Inconsolata);
 
 @import url(https://maxcdn.bootstrapcdn.com/font-awesome/4.6.3/css/font-awesome.min.css);
-@import url(http://fonts.googleapis.com/css?family=Inconsolata);
+@import url(https://fonts.googleapis.com/css?family=Inconsolata);
 .insp-wrapper {
   user-select: none;
   display: flex;

+ 1 - 1
dist/preview release/inspector/babylon.inspector.js

@@ -20,7 +20,7 @@ var INSPECTOR;
             Inspector.WINDOW = window;
             // Load the Canvas2D library if it's not already done
             if (!BABYLON.Canvas2D) {
-                BABYLON.Tools.LoadScript("http://www.babylonjs.com/babylon.canvas2d.js", function () { });
+                BABYLON.Tools.LoadScript("https://www.babylonjs.com/babylon.canvas2d.js", function () { });
             }
             // POPUP MODE
             if (popup) {

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


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

@@ -1,24 +1,23 @@
 /// <reference path="../../../dist/preview release/babylon.d.ts" />
 declare module BABYLON {
-    class FireMaterial extends Material {
+    class FireMaterial extends PushMaterial {
+        private _diffuseTexture;
         diffuseTexture: BaseTexture;
+        private _distortionTexture;
         distortionTexture: BaseTexture;
+        private _opacityTexture;
         opacityTexture: BaseTexture;
         diffuseColor: Color3;
         speed: number;
         private _scaledDiffuse;
         private _renderId;
-        private _defines;
-        private _cachedDefines;
         private _lastTime;
         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): FireMaterial;

+ 97 - 124
dist/preview release/materialsLibrary/babylon.fireMaterial.js

@@ -17,7 +17,6 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
 };
 var BABYLON;
 (function (BABYLON) {
-    var maxSimultaneousLights = 4;
     var FireMaterialDefines = (function (_super) {
         __extends(FireMaterialDefines, _super);
         function FireMaterialDefines() {
@@ -33,7 +32,7 @@ var BABYLON;
             _this.BonesPerMesh = 0;
             _this.NUM_BONE_INFLUENCERS = 0;
             _this.INSTANCES = false;
-            _this._keys = Object.keys(_this);
+            _this.rebuild();
             return _this;
         }
         return FireMaterialDefines;
@@ -45,122 +44,84 @@ var BABYLON;
             _this.diffuseColor = new BABYLON.Color3(1, 1, 1);
             _this.speed = 1.0;
             _this._scaledDiffuse = new BABYLON.Color3();
-            _this._defines = new FireMaterialDefines();
-            _this._cachedDefines = new FireMaterialDefines();
             _this._lastTime = 0;
-            _this._cachedDefines.BonesPerMesh = -1;
             return _this;
         }
         FireMaterial.prototype.needAlphaBlending = function () {
-            return (this.alpha < 1.0);
+            return false;
         };
         FireMaterial.prototype.needAlphaTesting = function () {
-            return false;
+            return true;
         };
         FireMaterial.prototype.getAlphaTestTexture = function () {
             return null;
         };
         // Methods   
-        FireMaterial.prototype._checkCache = function (scene, mesh, useInstances) {
-            if (!mesh) {
-                return true;
-            }
-            if (this._defines.INSTANCES !== useInstances) {
-                return false;
-            }
-            return false;
-        };
-        FireMaterial.prototype.isReady = function (mesh, useInstances) {
-            if (this.checkReadyOnlyOnce) {
-                if (this._wasPreviouslyReady) {
+        FireMaterial.prototype.isReadyForSubMesh = function (mesh, subMesh, useInstances) {
+            if (this.isFrozen) {
+                if (this._wasPreviouslyReady && subMesh.effect) {
                     return true;
                 }
             }
+            if (!subMesh._materialDefines) {
+                subMesh._materialDefines = new FireMaterialDefines();
+            }
+            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()) {
+            if (defines._areTexturesDirty) {
+                defines._needUVs = false;
+                if (this._diffuseTexture && BABYLON.StandardMaterial.DiffuseTextureEnabled) {
+                    if (!this._diffuseTexture.isReady()) {
                         return false;
                     }
                     else {
-                        needUVs = true;
-                        this._defines.DIFFUSE = true;
+                        defines._needUVs = true;
+                        defines.DIFFUSE = true;
                     }
                 }
             }
-            // Effect
-            if (scene.clipPlane) {
-                this._defines.CLIPPLANE = true;
-            }
-            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.
+            if (defines._areMiscDirty) {
+                defines.POINTSIZE = (this.pointsCloud || scene.forcePointsCloud);
+                defines.FOG = (scene.fogEnabled && mesh.applyFog && scene.fogMode !== BABYLON.Scene.FOGMODE_NONE && this.fogEnabled);
             }
+            // Values that need to be evaluated on every frame
+            BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances);
             // Attribs
-            if (mesh) {
-                if (needUVs) {
-                    if (mesh.isVerticesDataPresent(BABYLON.VertexBuffer.UVKind)) {
-                        this._defines.UV1 = 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");
                 }
-                if (this._defines.NUM_BONE_INFLUENCERS > 0) {
+                if (defines.NUM_BONE_INFLUENCERS > 0) {
                     fallbacks.addCPUSkinningFallback(0, mesh);
                 }
                 //Attributes
                 var attribs = [BABYLON.VertexBuffer.PositionKind];
-                if (this._defines.UV1) {
+                if (defines.UV1) {
                     attribs.push(BABYLON.VertexBuffer.UVKind);
                 }
-                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 = "fire";
-                var join = this._defines.toString();
-                this._effect = scene.getEngine().createEffect(shaderName, attribs, ["world", "view", "viewProjection", "vEyePosition",
+                var join = defines.toString();
+                subMesh.setEffect(scene.getEngine().createEffect(shaderName, attribs, ["world", "view", "viewProjection", "vEyePosition",
                     "vFogInfos", "vFogColor", "pointSize",
                     "vDiffuseInfos",
                     "mBones",
@@ -170,78 +131,81 @@ var BABYLON;
                 ], ["diffuseSampler",
                     // Fire
                     "distortionSampler", "opacitySampler"
-                ], 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;
         };
-        FireMaterial.prototype.bindOnlyWorldMatrix = function (world) {
-            this._effect.setMatrix("world", world);
-        };
-        FireMaterial.prototype.bind = function (world, mesh) {
+        FireMaterial.prototype.bindForSubMesh = function (world, mesh, subMesh) {
             var scene = this.getScene();
-            // Matrices        
+            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._effect.setTexture("distortionSampler", this.distortionTexture);
-                    this._effect.setTexture("opacitySampler", this.opacityTexture);
+                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());
+                    this._activeEffect.setTexture("distortionSampler", this._distortionTexture);
+                    this._activeEffect.setTexture("opacitySampler", this._opacityTexture);
                 }
                 // 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);
                 }
-                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);
             // 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);
             // Time
             this._lastTime += scene.getEngine().getDeltaTime();
-            this._effect.setFloat("time", this._lastTime);
+            this._activeEffect.setFloat("time", this._lastTime);
             // Speed
-            this._effect.setFloat("speed", this.speed);
-            _super.prototype.bind.call(this, world, mesh);
+            this._activeEffect.setFloat("speed", this.speed);
+            this._afterBind(mesh, this._activeEffect);
         };
         FireMaterial.prototype.getAnimatables = function () {
             var results = [];
-            if (this.diffuseTexture && this.diffuseTexture.animations && this.diffuseTexture.animations.length > 0) {
-                results.push(this.diffuseTexture);
+            if (this._diffuseTexture && this._diffuseTexture.animations && this._diffuseTexture.animations.length > 0) {
+                results.push(this._diffuseTexture);
             }
-            if (this.distortionTexture && this.distortionTexture.animations && this.distortionTexture.animations.length > 0) {
-                results.push(this.distortionTexture);
+            if (this._distortionTexture && this._distortionTexture.animations && this._distortionTexture.animations.length > 0) {
+                results.push(this._distortionTexture);
             }
-            if (this.opacityTexture && this.opacityTexture.animations && this.opacityTexture.animations.length > 0) {
-                results.push(this.opacityTexture);
+            if (this._opacityTexture && this._opacityTexture.animations && this._opacityTexture.animations.length > 0) {
+                results.push(this._opacityTexture);
             }
             return results;
         };
         FireMaterial.prototype.dispose = function (forceDisposeEffect) {
-            if (this.diffuseTexture) {
-                this.diffuseTexture.dispose();
+            if (this._diffuseTexture) {
+                this._diffuseTexture.dispose();
             }
-            if (this.distortionTexture) {
-                this.distortionTexture.dispose();
+            if (this._distortionTexture) {
+                this._distortionTexture.dispose();
             }
             _super.prototype.dispose.call(this, forceDisposeEffect);
         };
@@ -254,14 +218,14 @@ var BABYLON;
             serializationObject.customType = "BABYLON.FireMaterial";
             serializationObject.diffuseColor = this.diffuseColor.asArray();
             serializationObject.speed = this.speed;
-            if (this.diffuseTexture) {
-                serializationObject.diffuseTexture = this.diffuseTexture.serialize();
+            if (this._diffuseTexture) {
+                serializationObject._diffuseTexture = this._diffuseTexture.serialize();
             }
-            if (this.distortionTexture) {
-                serializationObject.distortionTexture = this.distortionTexture.serialize();
+            if (this._distortionTexture) {
+                serializationObject._distortionTexture = this._distortionTexture.serialize();
             }
-            if (this.opacityTexture) {
-                serializationObject.opacityTexture = this.opacityTexture.serialize();
+            if (this._opacityTexture) {
+                serializationObject._opacityTexture = this._opacityTexture.serialize();
             }
             return serializationObject;
         };
@@ -274,14 +238,14 @@ var BABYLON;
             BABYLON.Tags.AddTagsTo(material, source.tags);
             material.backFaceCulling = source.backFaceCulling;
             material.wireframe = source.wireframe;
-            if (source.diffuseTexture) {
-                material.diffuseTexture = BABYLON.Texture.Parse(source.diffuseTexture, scene, rootUrl);
+            if (source._diffuseTexture) {
+                material._diffuseTexture = BABYLON.Texture.Parse(source._diffuseTexture, scene, rootUrl);
             }
-            if (source.distortionTexture) {
-                material.distortionTexture = BABYLON.Texture.Parse(source.distortionTexture, scene, rootUrl);
+            if (source._distortionTexture) {
+                material._distortionTexture = BABYLON.Texture.Parse(source._distortionTexture, scene, rootUrl);
             }
-            if (source.opacityTexture) {
-                material.opacityTexture = BABYLON.Texture.Parse(source.opacityTexture, scene, rootUrl);
+            if (source._opacityTexture) {
+                material._opacityTexture = BABYLON.Texture.Parse(source._opacityTexture, scene, rootUrl);
             }
             if (source.checkReadyOnlyOnce) {
                 material.checkReadyOnlyOnce = source.checkReadyOnlyOnce;
@@ -289,15 +253,24 @@ var BABYLON;
             return material;
         };
         return FireMaterial;
-    }(BABYLON.Material));
+    }(BABYLON.PushMaterial));
     __decorate([
-        BABYLON.serializeAsTexture()
+        BABYLON.serializeAsTexture("diffuseTexture")
+    ], FireMaterial.prototype, "_diffuseTexture", void 0);
+    __decorate([
+        BABYLON.expandToProperty("_markAllSubMeshesAsTexturesDirty")
     ], FireMaterial.prototype, "diffuseTexture", void 0);
     __decorate([
-        BABYLON.serializeAsTexture()
+        BABYLON.serializeAsTexture("distortionTexture")
+    ], FireMaterial.prototype, "_distortionTexture", void 0);
+    __decorate([
+        BABYLON.expandToProperty("_markAllSubMeshesAsTexturesDirty")
     ], FireMaterial.prototype, "distortionTexture", void 0);
     __decorate([
-        BABYLON.serializeAsTexture()
+        BABYLON.serializeAsTexture("opacityTexture")
+    ], FireMaterial.prototype, "_opacityTexture", void 0);
+    __decorate([
+        BABYLON.expandToProperty("_markAllSubMeshesAsTexturesDirty")
     ], FireMaterial.prototype, "opacityTexture", void 0);
     __decorate([
         BABYLON.serialize("diffuseColor")

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;

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


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;

+ 60 - 107
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() {
@@ -68,7 +67,7 @@ var BABYLON;
             _this.NUM_BONE_INFLUENCERS = 0;
             _this.BonesPerMesh = 0;
             _this.INSTANCES = false;
-            _this._keys = Object.keys(_this);
+            _this.rebuild();
             return _this;
         }
         return 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,118 +101,65 @@ 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);
-            }
+            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",
-                    "vLightData0", "vLightDiffuse0", "vLightSpecular0", "vLightDirection0", "vLightGround0", "lightMatrix0",
-                    "vLightData1", "vLightDiffuse1", "vLightSpecular1", "vLightDirection1", "vLightGround1", "lightMatrix1",
-                    "vLightData2", "vLightDiffuse2", "vLightSpecular2", "vLightDirection2", "vLightGround2", "lightMatrix2",
-                    "vLightData3", "vLightDiffuse3", "vLightSpecular3", "vLightDirection3", "vLightGround3", "lightMatrix3",
+                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",
+                    "vLightData3", "vLightDiffuse3", "vLightDirection3", "vLightGround3", "lightMatrix3",
                     "vFogInfos", "vFogColor", "pointSize",
                     "vDiffuseInfos",
                     "mBones",
@@ -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);
-            _super.prototype.bind.call(this, world, 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;

+ 38 - 50
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._keys = Object.keys(_this);
+            _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);
-            _super.prototype.bind.call(this, world, 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;

+ 88 - 123
dist/preview release/materialsLibrary/babylon.lavaMaterial.js

@@ -67,7 +67,7 @@ var BABYLON;
             _this.NUM_BONE_INFLUENCERS = 0;
             _this.BonesPerMesh = 0;
             _this.INSTANCES = false;
-            _this._keys = Object.keys(_this);
+            _this.rebuild();
             return _this;
         }
         return LavaMaterialDefines;
@@ -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,127 +98,83 @@ 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, 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",
-                    "vLightData0", "vLightDiffuse0", "vLightSpecular0", "vLightDirection0", "vLightGround0", "lightMatrix0",
-                    "vLightData1", "vLightDiffuse1", "vLightSpecular1", "vLightDirection1", "vLightGround1", "lightMatrix1",
-                    "vLightData2", "vLightDiffuse2", "vLightSpecular2", "vLightDirection2", "vLightGround2", "lightMatrix2",
-                    "vLightData3", "vLightDiffuse3", "vLightSpecular3", "vLightDirection3", "vLightGround3", "lightMatrix3",
+                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",
+                    "vLightData3", "vLightDiffuse3", "vLightDirection3", "vLightGround3", "lightMatrix3",
                     "vFogInfos", "vFogColor", "pointSize",
                     "vDiffuseInfos",
                     "mBones",
@@ -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);
-            _super.prototype.bind.call(this, world, 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;

+ 84 - 117
dist/preview release/materialsLibrary/babylon.normalMaterial.js

@@ -67,7 +67,7 @@ var BABYLON;
             _this.NUM_BONE_INFLUENCERS = 0;
             _this.BonesPerMesh = 0;
             _this.INSTANCES = false;
-            _this._keys = Object.keys(_this);
+            _this.rebuild();
             return _this;
         }
         return NormalMaterialDefines;
@@ -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,128 +93,82 @@ 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);
-            }
+            // 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",
-                    "vLightData0", "vLightDiffuse0", "vLightSpecular0", "vLightDirection0", "vLightGround0", "lightMatrix0",
-                    "vLightData1", "vLightDiffuse1", "vLightSpecular1", "vLightDirection1", "vLightGround1", "lightMatrix1",
-                    "vLightData2", "vLightDiffuse2", "vLightSpecular2", "vLightDirection2", "vLightGround2", "lightMatrix2",
-                    "vLightData3", "vLightDiffuse3", "vLightSpecular3", "vLightDirection3", "vLightGround3", "lightMatrix3",
+                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",
+                    "vLightData3", "vLightDiffuse3", "vLightDirection3", "vLightGround3", "lightMatrix3",
                     "vFogInfos", "vFogColor", "pointSize",
                     "vDiffuseInfos",
                     "mBones",
@@ -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);
-            _super.prototype.bind.call(this, world, 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, 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);
-            _super.prototype.bind.call(this, world, 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


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

@@ -1,23 +1,22 @@
 /// <reference path="../../../dist/preview release/babylon.d.ts" />
 declare module BABYLON {
-    class SimpleMaterial extends Material {
+    class SimpleMaterial 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): SimpleMaterial;

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


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;

+ 41 - 64
dist/preview release/materialsLibrary/babylon.skyMaterial.js

@@ -26,7 +26,7 @@ var BABYLON;
             _this.FOG = false;
             _this.VERTEXCOLOR = false;
             _this.VERTEXALPHA = false;
-            _this._keys = Object.keys(_this);
+            _this.rebuild();
             return _this;
         }
         return SkyMaterialDefines;
@@ -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);
-            _super.prototype.bind.call(this, world, 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, 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);
-            _super.prototype.bind.call(this, world, 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, 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);
-            _super.prototype.bind.call(this, world, 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, 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);
-            _super.prototype.bind.call(this, world, 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


+ 1 - 1
index.html

@@ -69,7 +69,7 @@
 								sphere.material.diffuseColor = new BABYLON.Color3(Math.random(), Math.random(), Math.random());
 								sphere.material.specularColor = new BABYLON.Color3(Math.random() < 0.8 ? 0 : 1, Math.random() < 0.8 ? 0 : 1, Math.random() < 0.8 ? 0 : 1);
 								sphere.material.emissiveColor = new BABYLON.Color3(0, 0, 0);
-								// sphere.material.freeze();
+								sphere.material.freeze();
 								sphere.freezeWorldMatrix();
 								spheres.push(sphere);
 							}

+ 1 - 1
inspector/sass/defines.scss

@@ -1,5 +1,5 @@
 @import url(https://maxcdn.bootstrapcdn.com/font-awesome/4.6.3/css/font-awesome.min.css);
-@import url(http://fonts.googleapis.com/css?family=Inconsolata);
+@import url(https://fonts.googleapis.com/css?family=Inconsolata);
 
 $font               : 'Inconsolata', sans-serif;
 

+ 1 - 1
inspector/src/Inspector.ts

@@ -55,7 +55,7 @@ module INSPECTOR {
 
             // Load the Canvas2D library if it's not already done
             if (!BABYLON.Canvas2D) {
-                BABYLON.Tools.LoadScript("http://www.babylonjs.com/babylon.canvas2d.js", () => { });
+                BABYLON.Tools.LoadScript("https://www.babylonjs.com/babylon.canvas2d.js", () => { });
             }
 
             // POPUP MODE

+ 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 () {
+}

+ 2 - 0
materialsLibrary/index.html

@@ -71,6 +71,7 @@
 			pointLight.setEnabled(false);
 			var directionalLight = new BABYLON.DirectionalLight("directional", new BABYLON.Vector3(0,-1, 0), scene);
 			directionalLight.setEnabled(false);
+			directionalLight.position = new BABYLON.Vector3(0, 50, 0);
 			var spotLight = new BABYLON.SpotLight("spot", new BABYLON.Vector3(0, -30, 0), new BABYLON.Vector3(0, 1, 0), 1.1, 1, scene);
 			spotLight.setEnabled(false);
 
@@ -128,6 +129,7 @@
 				var shadowGenerator = new BABYLON.ShadowGenerator(1024, directionalLight);
 				shadowGenerator.getShadowMap().renderList.push(shadowCaster);
 				shadowGenerator.usePoissonSampling = true;
+				shadowGenerator.bias = 0;
 				
 				var shadowGenerator2 = new BABYLON.ShadowGenerator(1024, spotLight);
 				shadowGenerator2.getShadowMap().renderList.push(shadowCaster2);

+ 5 - 11
materialsLibrary/src/fire/babylon.fireMaterial.ts

@@ -96,30 +96,24 @@ module BABYLON {
                         defines._needUVs = true;
                         defines.DIFFUSE = true;
                     }
-                }  
-                defines._areTexturesDirty = false;              
+                }              
             }
 
             // Misc.
             if (defines._areMiscDirty) {
                 defines.POINTSIZE = (this.pointsCloud || scene.forcePointsCloud);
                 defines.FOG = (scene.fogEnabled && mesh.applyFog && scene.fogMode !== Scene.FOGMODE_NONE && this.fogEnabled);
-
-                defines._areMiscDirty = false;
             }
             
             // Values that need to be evaluated on every frame
-            defines.CLIPPLANE = (scene.clipPlane !== undefined && scene.clipPlane !== null);
-            defines.ALPHATEST = engine.getAlphaTesting();
-            defines.INSTANCES = useInstances;
+            MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances);
             
             // Attribs
-            MaterialHelper.PrepareDefinesForAttributes(mesh, defines, useInstances);
-            defines._areAttributesDirty = false;
+            MaterialHelper.PrepareDefinesForAttributes(mesh, defines, false, true);
 
             // Get correct effect      
-            if (defines._isDirty) {
-                defines._isDirty = false;
+            if (defines.isDirty) {
+                defines.markAsProcessed();
 
                 scene.resetCachedMaterial();
 

+ 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) {
-                    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, 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[] {

+ 5 - 0
materialsLibrary/src/fur/fur.fragment.fx

@@ -97,9 +97,14 @@ void main(void) {
 	// Lighting
 	vec3 diffuseBase = vec3(0., 0., 0.);
     lightingInfo info;
+
 	float shadow = 1.;
 	float glossiness = 0.;
 
+#ifdef SPECULARTERM
+	vec3 specularBase = vec3(0., 0., 0.);
+#endif
+
 	#include<lightFragment>[0..maxSimultaneousLights]
 
 #ifdef VERTEXALPHA

+ 6 - 2
materialsLibrary/src/fur/fur.vertex.fx

@@ -76,8 +76,12 @@ void main(void) {
 
 //FUR
 float r = Rand(position);
-#ifdef HEIGHTMAP	
-	vfur_length = furLength * texture2D(heightTexture, uv).rgb.x;
+#ifdef HEIGHTMAP
+	#if __VERSION__ > 100
+	vfur_length = furLength * texture(heightTexture, uv).x;
+	#else
+	vfur_length = furLength * texture2D(heightTexture, uv).r;
+	#endif
 #else	
 	vfur_length = (furLength * r);
 #endif

+ 61 - 122
materialsLibrary/src/gradient/babylon.gradientMaterial.ts

@@ -1,8 +1,6 @@
 /// <reference path="../../../dist/preview release/babylon.d.ts"/>
 
 module BABYLON {
-    var maxSimultaneousLights = 4;
-
     class GradientMaterialDefines extends MaterialDefines {
         public DIFFUSE = false;
         public CLIPPLANE = false;
@@ -53,11 +51,16 @@ module BABYLON {
 
         constructor() {
             super();
-            this._keys = Object.keys(this);
+            this.rebuild();
         }
     }
 
-    export class GradientMaterial extends Material {
+    export class GradientMaterial extends PushMaterial {
+          
+        @serialize("maxSimultaneousLights")
+        private _maxSimultaneousLights = 4;
+        @expandToProperty("_markAllSubMeshesAsLightsDirty")
+        public maxSimultaneousLights: number;       
 
         // The gradient top color, red by default
         @serializeAsColor3()
@@ -87,13 +90,8 @@ module BABYLON {
         private _scaledDiffuse = new Color3();
         private _renderId: number;
 
-        private _defines = new GradientMaterialDefines();
-        private _cachedDefines = new GradientMaterialDefines();
-
         constructor(name: string, scene: Scene) {
             super(name, scene);
-
-            this._cachedDefines.BonesPerMesh = -1;
         }
 
         public needAlphaBlending(): boolean {
@@ -109,149 +107,88 @@ 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 GradientMaterialDefines();
+            }
+
+            var defines = <GradientMaterialDefines>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;
-            }
+            MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances);
 
-            // 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);
 
-            var lightIndex = 0;
-            if (scene.lightsEnabled && !this.disableLighting) {
-                needNormals = MaterialHelper.PrepareDefinesForLights(scene, mesh, this._defines);
-            }
+            defines._needNormals = MaterialHelper.PrepareDefinesForLights(scene, mesh, defines, false, this._maxSimultaneousLights);
 
             // 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, 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 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 = "gradient";
-                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", "vLightSpecular0", "vLightDirection0", "vLightGround0", "lightMatrix0",
-                        "vLightData1", "vLightDiffuse1", "vLightSpecular1", "vLightDirection1", "vLightGround1", "lightMatrix1",
-                        "vLightData2", "vLightDiffuse2", "vLightSpecular2", "vLightDirection2", "vLightGround2", "lightMatrix2",
-                        "vLightData3", "vLightDiffuse3", "vLightSpecular3", "vLightDirection3", "vLightGround3", "lightMatrix3",
+                        "vLightData0", "vLightDiffuse0","vLightDirection0", "vLightGround0", "lightMatrix0",
+                        "vLightData1", "vLightDiffuse1", "vLightDirection1", "vLightGround1", "lightMatrix1",
+                        "vLightData2", "vLightDiffuse2", "vLightDirection2", "vLightGround2", "lightMatrix2",
+                        "vLightData3", "vLightDiffuse3", "vLightDirection3", "vLightGround3", "lightMatrix3",
                         "vFogInfos", "vFogColor", "pointSize",
                         "vDiffuseInfos", 
                         "mBones",
@@ -261,9 +198,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;
             }
 
@@ -273,54 +210,56 @@ 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 = <GradientMaterialDefines>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);
 
-
-            if (scene.getCachedMaterial() !== this) {
+            if (this._mustRebind(scene, effect)) {
                 // Clip plane
                 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) {
-                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._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._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._afterBind(mesh, this._activeEffect);
         }
 
         public getAnimatables(): IAnimatable[] {

+ 37 - 53
materialsLibrary/src/grid/babylon.gridmaterial.ts

@@ -1,14 +1,14 @@
 /// <reference path="../../../dist/preview release/babylon.d.ts"/>
 
 module BABYLON {
-    class GRIDMaterialDefines extends MaterialDefines {
+    class GridMaterialDefines extends MaterialDefines {
         public TRANSPARENT = false;
 
         public FOG = false;
 
         constructor() {
             super();
-            this._keys = Object.keys(this);
+            this.rebuild();
         }
     }
 
@@ -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 {

+ 89 - 137
materialsLibrary/src/lava/babylon.lavaMaterial.ts

@@ -51,12 +51,14 @@ module BABYLON {
 
         constructor() {
             super();
-            this._keys = Object.keys(this);
+            this.rebuild();
         }
     }
 
-    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,156 +115,104 @@ 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, 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", "vLightSpecular0", "vLightDirection0", "vLightGround0", "lightMatrix0",
-                        "vLightData1", "vLightDiffuse1", "vLightSpecular1", "vLightDirection1", "vLightGround1", "lightMatrix1",
-                        "vLightData2", "vLightDiffuse2", "vLightSpecular2", "vLightDirection2", "vLightGround2", "lightMatrix2",
-                        "vLightData3", "vLightDiffuse3", "vLightSpecular3", "vLightDirection3", "vLightGround3", "lightMatrix3",
+                        "vLightData0", "vLightDiffuse0", "vLightDirection0", "vLightGround0", "lightMatrix0",
+                        "vLightData1", "vLightDiffuse1", "vLightDirection1", "vLightGround1", "lightMatrix1",
+                        "vLightData2", "vLightDiffuse2", "vLightDirection2", "vLightGround2", "lightMatrix2",
+                        "vLightData3", "vLightDiffuse3", "vLightDirection3", "vLightGround3", "lightMatrix3",
                         "vFogInfos", "vFogColor", "pointSize",
                         "vDiffuseInfos",
                         "mBones",
@@ -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[] {

+ 86 - 131
materialsLibrary/src/normal/babylon.normalMaterial.ts

@@ -51,31 +51,35 @@ module BABYLON {
 
         constructor() {
             super();
-            this._keys = Object.keys(this);
+            this.rebuild();
         }
     }
 
-    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,157 +95,104 @@ 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);
-            }
+            // 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", "vLightSpecular0", "vLightDirection0", "vLightGround0", "lightMatrix0",
-                        "vLightData1", "vLightDiffuse1", "vLightSpecular1", "vLightDirection1", "vLightGround1", "lightMatrix1",
-                        "vLightData2", "vLightDiffuse2", "vLightSpecular2", "vLightDirection2", "vLightGround2", "lightMatrix2",
-                        "vLightData3", "vLightDiffuse3", "vLightSpecular3", "vLightDirection3", "vLightGround3", "lightMatrix3",
+                        "vLightData0", "vLightDiffuse0", "vLightDirection0", "vLightGround0", "lightMatrix0",
+                        "vLightData1", "vLightDiffuse1", "vLightDirection1", "vLightGround1", "lightMatrix1",
+                        "vLightData2", "vLightDiffuse2", "vLightDirection2", "vLightGround2", "lightMatrix2",
+                        "vLightData3", "vLightDiffuse3", "vLightDirection3", "vLightGround3", "lightMatrix3",
                         "vFogInfos", "vFogColor", "pointSize",
                         "vDiffuseInfos", 
                         "mBones",
@@ -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[] {

+ 46 - 85
materialsLibrary/src/shadowOnly/babylon.shadowOnlyMaterial.ts

@@ -16,20 +16,15 @@ module BABYLON {
         }
     }
 
-    export class ShadowOnlyMaterial extends Material {
+    export class ShadowOnlyMaterial extends PushMaterial {
         @serialize()
 
         private _worldViewProjectionMatrix = Matrix.Zero();
         private _scaledDiffuse = new Color3();
         private _renderId: number;
 
-        private _defines = new ShadowOnlyMaterialDefines();
-        private _cachedDefines = new ShadowOnlyMaterialDefines();
-
         constructor(name: string, scene: Scene) {
             super(name, scene);
-
-            this._cachedDefines.BonesPerMesh = -1;
         }
 
         public needAlphaBlending(): boolean {
@@ -45,105 +40,67 @@ 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 ShadowOnlyMaterialDefines();
+            }
+
+            var defines = <ShadowOnlyMaterialDefines>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();
+            MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances);
 
-            // Effect
-            if (scene.clipPlane) {
-                this._defines.CLIPPLANE = true;
-            }
+            MaterialHelper.PrepareDefinesForMisc(mesh, scene, false, this.pointsCloud, this.fogEnabled, defines);
 
-            // Point size
-            if (this.pointsCloud || scene.forcePointsCloud) {
-                this._defines.POINTSIZE = true;
-            }
-
-            // Fog
-            if (scene.fogEnabled && mesh && mesh.applyFog && scene.fogMode !== Scene.FOGMODE_NONE && this.fogEnabled) {
-                this._defines.FOG = true;
-            }
-
-            if (scene.lightsEnabled) {
-                needNormals = MaterialHelper.PrepareDefinesForLights(scene, mesh, this._defines, 1);
-            }
+            defines._needNormals = MaterialHelper.PrepareDefinesForLights(scene, mesh, defines, false, 1);
 
             // Attribs
-            if (mesh) {
-                if (needNormals && mesh.isVerticesDataPresent(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;
-                }
-            }
+            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 EffectFallbacks();             
-                if (this._defines.FOG) {
+                if (defines.FOG) {
                     fallbacks.addFallback(1, "FOG");
                 }
 
-                MaterialHelper.HandleFallbacksForShadows(this._defines, fallbacks, 1);
+                MaterialHelper.HandleFallbacksForShadows(defines, fallbacks, 1);
                 
-                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);
                 }
 
-                MaterialHelper.PrepareAttributesForBones(attribs, mesh, this._defines, fallbacks);
-                MaterialHelper.PrepareAttributesForInstances(attribs, this._defines);
+                MaterialHelper.PrepareAttributesForBones(attribs, mesh, defines, fallbacks);
+                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",
@@ -151,13 +108,13 @@ module BABYLON {
                 ];
                 var samplers = [];
                     
-                MaterialHelper.PrepareUniformsAndSamplersList(uniforms, samplers, this._defines, 1);
+                MaterialHelper.PrepareUniformsAndSamplersList(uniforms, samplers, defines, 1);
                 
-                this._effect = scene.getEngine().createEffect(shaderName,
+                subMesh.setEffect(scene.getEngine().createEffect(shaderName,
                     attribs, uniforms, samplers,
-                    join, fallbacks, this.onCompiled, this.onError, {maxSimultaneousLights: 1});
+                    join, fallbacks, this.onCompiled, this.onError, {maxSimultaneousLights: 1}), defines);
             }
-            if (!this._effect.isReady()) {
+            if (!subMesh.effect.isReady()) {
                 return false;
             }
 
@@ -167,46 +124,50 @@ 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 = <ShadowOnlyMaterialDefines>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)) {
                 // 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);                
             }
 
             // Lights
             if (scene.lightsEnabled) {
-                MaterialHelper.BindLights(scene, mesh, this._effect, this._defines, 1);          
+                MaterialHelper.BindLights(scene, mesh, this._activeEffect, defines, 1);          
             }
 
             // 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 clone(name: string): ShadowOnlyMaterial {

+ 6 - 16
materialsLibrary/src/simple/babylon.simpleMaterial.ts

@@ -97,33 +97,23 @@ module BABYLON {
                         }
                     }                
                 }
-                defines._areTexturesDirty = false;
             }
 
             // Misc.
-            if (defines._areMiscDirty) {
-                defines.POINTSIZE = (this.pointsCloud || scene.forcePointsCloud);
-                defines.FOG = (scene.fogEnabled && mesh.applyFog && scene.fogMode !== Scene.FOGMODE_NONE && this.fogEnabled);
-
-                defines._areMiscDirty = false;
-            }
+            MaterialHelper.PrepareDefinesForMisc(mesh, scene, false, this.pointsCloud, this.fogEnabled, defines);
 
             // Lights
-            defines._needNormals = MaterialHelper.PrepareDefinesForLights(scene, mesh, defines, this._maxSimultaneousLights, this._disableLighting);
-            defines._areLightsDirty = false;
+            defines._needNormals = MaterialHelper.PrepareDefinesForLights(scene, mesh, defines, false, this._maxSimultaneousLights, this._disableLighting);
 
             // Values that need to be evaluated on every frame
-            defines.CLIPPLANE = (scene.clipPlane !== undefined && scene.clipPlane !== null);
-            defines.ALPHATEST = true;
-            defines.INSTANCES = useInstances;
+            MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances);
             
             // Attribs
-            MaterialHelper.PrepareDefinesForAttributes(mesh, defines, useInstances);
-            defines._areAttributesDirty = false;
+            MaterialHelper.PrepareDefinesForAttributes(mesh, defines, true, true);
 
             // Get correct effect      
-            if (defines._isDirty) {
-                defines._isDirty = false;
+            if (defines.isDirty) {
+                defines.markAsProcessed();
                 scene.resetCachedMaterial();
 
                 // Fallbacks

+ 45 - 72
materialsLibrary/src/sky/babylon.skyMaterial.ts

@@ -10,11 +10,11 @@ module BABYLON {
 
         constructor() {
             super();
-            this._keys = Object.keys(this);
+            this.rebuild();
         }
     }
     
-    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, 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, 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[] {

+ 124 - 167
materialsLibrary/src/water/babylon.waterMaterial.ts

@@ -29,12 +29,14 @@ module BABYLON {
         }
     }
 	
-	export class WaterMaterial extends Material {
+	export class WaterMaterial extends PushMaterial {
 		/*
 		* Public members
 		*/
-        @serializeAsTexture()
-        public bumpTexture: BaseTexture;
+        @serializeAsTexture("bumpTexture")
+        private _bumpTexture: BaseTexture;
+        @expandToProperty("_markAllSubMeshesAsTexturesDirty")
+        public bumpTexture: BaseTexture;        
         
         @serializeAsColor3()
         public diffuseColor = new Color3(1, 1, 1);
@@ -45,11 +47,15 @@ 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;                   
         
         /**
         * @param {number}: Represents the wind force
@@ -74,18 +80,26 @@ module BABYLON {
         /**
          * @param {boolean}: Add a smaller moving bump to less steady waves.
          */
-        @serialize()
-        public bumpSuperimpose = false;
+        @serialize("bumpSuperimpose")
+        private _bumpSuperimpose = false;
+        @expandToProperty("_markAllSubMeshesAsMiscDirty")
+        public bumpSuperimpose: boolean;
+
         /**
          * @param {boolean}: Color refraction and reflection differently with .waterColor2 and .colorBlendFactor2. Non-linear (physically correct) fresnel.
          */
-        @serialize()
-        public fresnelSeparate = false;
+        @serialize("fresnelSeparate")
+        private _fresnelSeparate = false;
+        @expandToProperty("_markAllSubMeshesAsMiscDirty")
+        public fresnelSeparate: boolean;
+
         /**
          * @param {boolean}: bump Waves modify the reflection.
          */
-        @serialize()
-        public bumpAffectsReflection = false;
+        @serialize("bumpAffectsReflection")
+        private _bumpAffectsReflection = false;
+        @expandToProperty("_markAllSubMeshesAsMiscDirty")
+        public bumpAffectsReflection: boolean;        
 
         /**
         * @param {number}: The water color blended with the refraction (near)
@@ -134,9 +148,6 @@ module BABYLON {
         
         private _renderId: number;
 
-        private _defines = new WaterMaterialDefines();
-        private _cachedDefines = new WaterMaterialDefines();
-
         private _useLogarithmicDepth: boolean;
 
         /**
@@ -156,6 +167,7 @@ module BABYLON {
 
         public set useLogarithmicDepth(value: boolean) {
             this._useLogarithmicDepth = value && this.getScene().getEngine().getCaps().fragmentDepthSupported;
+            this._markAllSubMeshesAsMiscDirty();
         }
 
         // Get / Set
@@ -199,179 +211,120 @@ module BABYLON {
         public getAlphaTestTexture(): BaseTexture {
             return null;
         }
-        
-        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 WaterMaterialDefines();
+            }
+
+            var defines = <WaterMaterialDefines>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 && StandardMaterial.BumpTextureEnabled) {
-                    if (!this.bumpTexture.isReady()) {
-                        return false;
-                    } else {
-                        needUVs = true;
-                        this._defines.BUMP = true;
+            if (defines._areTexturesDirty) {
+                defines._needUVs = false;
+                if (scene.texturesEnabled) {
+                    if (this.bumpTexture && StandardMaterial.BumpTextureEnabled) {
+                        if (!this.bumpTexture.isReady()) {
+                            return false;
+                        } else {
+                            defines._needUVs = true;
+                            defines.BUMP = true;
+                        }
+                    }
+                    
+                    if (StandardMaterial.ReflectionTextureEnabled) {
+                        defines.REFLECTION = true;
                     }
                 }
-                
-                if (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;
-            }
+            MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances);
 
-            if (this.bumpAffectsReflection) {
-                this._defines.BUMPAFFECTSREFLECTION = true;
-            }
+            MaterialHelper.PrepareDefinesForMisc(mesh, scene, this._useLogarithmicDepth, this.pointsCloud, this.fogEnabled, defines);
 
-            // 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, this.maxSimultaneousLights);
-            }
-
-            // Attribs
-            if (mesh) {
-                if (needNormals && mesh.isVerticesDataPresent(VertexBuffer.NormalKind)) {
-                    this._defines.NORMAL = true;
+            if (defines._areMiscDirty) {
+                if (this._fresnelSeparate) {
+                    defines.FRESNELSEPARATE = 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);
+                if (this._bumpSuperimpose) {
+                    defines.BUMPSUPERIMPOSE = true;
                 }
 
-                // Instances
-                if (useInstances) {
-                    this._defines.INSTANCES = true;
+                if (this._bumpAffectsReflection) {
+                    defines.BUMPAFFECTSREFLECTION = true;
                 }
             }
+           
+            // Lights
+            defines._needNormals = MaterialHelper.PrepareDefinesForLights(scene, mesh, defines, true, this._maxSimultaneousLights, this._disableLighting);
+
+            // Attribs
+            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 EffectFallbacks();             
-                if (this._defines.FOG) {
+                if (defines.FOG) {
                     fallbacks.addFallback(1, "FOG");
                 }
 
-                if (this._defines.LOGARITHMICDEPTH) {
+                if (defines.LOGARITHMICDEPTH) {
                     fallbacks.addFallback(0, "LOGARITHMICDEPTH");
                 }
 
-                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 = "water";
-                var join = this._defines.toString();
+                var join = defines.toString();
                 var uniforms = ["world", "view", "viewProjection", "vEyePosition", "vLightsType", "vDiffuseColor", "vSpecularColor",
                     "vFogInfos", "vFogColor", "pointSize",
                     "vNormalInfos", 
@@ -388,13 +341,13 @@ module BABYLON {
                     "refractionSampler", "reflectionSampler"
                 ];
                 
-                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;
             }
 
@@ -404,83 +357,87 @@ 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 = <WaterMaterialDefines>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.bumpTexture && StandardMaterial.BumpTextureEnabled) {
-                    this._effect.setTexture("normalSampler", this.bumpTexture);
+                    this._activeEffect.setTexture("normalSampler", this.bumpTexture);
 
-                    this._effect.setFloat2("vNormalInfos", this.bumpTexture.coordinatesIndex, this.bumpTexture.level);
-                    this._effect.setMatrix("normalMatrix", this.bumpTexture.getTextureMatrix());
+                    this._activeEffect.setFloat2("vNormalInfos", this.bumpTexture.coordinatesIndex, this.bumpTexture.level);
+                    this._activeEffect.setMatrix("normalMatrix", this.bumpTexture.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);
             
-            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);
 
             // Log. depth
-            MaterialHelper.BindLogDepth(this._defines, this._effect, scene);
+            MaterialHelper.BindLogDepth(defines, this._activeEffect, scene);
 
             // Water
             if (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);
 		}
 		
 		private _createRenderTargets(scene: Scene, renderTargetSize: Vector2): void {

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


+ 0 - 0
sandbox/Assets/up.png


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